49b0a669a087231fb85217ebc1a09a6b9f8e4b52
[policy/apex-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.apex.context.impl.distribution;
22
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Map;
26 import java.util.Map.Entry;
27
28 import org.onap.policy.apex.context.ContextAlbum;
29 import org.onap.policy.apex.context.ContextException;
30 import org.onap.policy.apex.context.Distributor;
31 import org.onap.policy.apex.context.LockManager;
32 import org.onap.policy.apex.context.Persistor;
33 import org.onap.policy.apex.context.impl.ContextAlbumImpl;
34 import org.onap.policy.apex.context.impl.locking.LockManagerFactory;
35 import org.onap.policy.apex.context.impl.persistence.PersistorFactory;
36 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
37 import org.onap.policy.apex.model.basicmodel.concepts.AxKeyInformation;
38 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult;
39 import org.onap.policy.apex.model.basicmodel.service.ModelService;
40 import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum;
41 import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbums;
42 import org.onap.policy.apex.model.contextmodel.concepts.AxContextModel;
43 import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
44 import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
45 import org.slf4j.ext.XLogger;
46 import org.slf4j.ext.XLoggerFactory;
47
48 /**
49  * This context distributor implements the mechanism-neutral parts of a context distributor.
50  *
51  * @author Liam Fallon (liam.fallon@ericsson.com)
52  */
53 public abstract class AbstractDistributor implements Distributor {
54
55     // Logger for this class
56     private static final XLogger LOGGER = XLoggerFactory.getXLogger(AbstractDistributor.class);
57
58     // The key of this distributor
59     private AxArtifactKey key = null;
60
61     // The context albums for this context set indexed by their keys
62     private static Map<AxArtifactKey, ContextAlbum> albumMaps = Collections
63                     .synchronizedMap(new HashMap<AxArtifactKey, ContextAlbum>());
64
65     // Lock manager for this distributor
66     private static LockManager lockManager = null;
67
68     // Hold a persistor for this distributor
69     private Persistor persistor = null;
70
71     // Hold a flush timer for this context distributor
72     private static DistributorFlushTimerTask flushTimer = null;
73
74     /**
75      * Create an instance of an abstract Context Distributor.
76      */
77     public AbstractDistributor() {
78         LOGGER.entry("AbstractContextDistributor()");
79         LOGGER.exit("AbstractContextDistributor()");
80     }
81
82     /**
83      * {@inheritDoc}.
84      */
85     @Override
86     public void init(final AxArtifactKey distributorKey) throws ContextException {
87         LOGGER.entry("init(" + distributorKey + ")");
88
89         // Record parameters and key
90         this.key = distributorKey;
91
92         // Create the lock manager if it doesn't already exist
93         if (lockManager == null) {
94             setLockManager(new LockManagerFactory().createLockManager(key));
95         }
96
97         // Set up flushing on the context distributor if its not set up already
98         if (flushTimer == null) {
99             setFlushTimer(new DistributorFlushTimerTask(this));
100         }
101
102         // Create a new persistor for this key
103         persistor = new PersistorFactory().createPersistor(key);
104         LOGGER.exit("init(" + key + ")");
105     }
106
107     /**
108      * Set the static lock manager.
109      *
110      * @param incomingLockManager the lock manager value
111      */
112     private static void setLockManager(final LockManager incomingLockManager) {
113         lockManager = incomingLockManager;
114     }
115
116     /**
117      * Set the static flush timer.
118      *
119      * @param incomingFlushTimer the flush timer value
120      */
121     private static void setFlushTimer(final DistributorFlushTimerTask incomingFlushTimer) {
122         flushTimer = incomingFlushTimer;
123     }
124
125     /**
126      * {@inheritDoc}.
127      */
128     @Override
129     public abstract void shutdown();
130
131     /**
132      * {@inheritDoc}.
133      */
134     @Override
135     public AxArtifactKey getKey() {
136         return key;
137     }
138
139     /**
140      * Create a context album using whatever underlying mechanism we are using for albums.
141      *
142      * @param contextAlbumKey The key of the album
143      * @return The album as a string-object map
144      */
145     public abstract Map<String, Object> getContextAlbumMap(AxArtifactKey contextAlbumKey);
146
147     /**
148      * {@inheritDoc}.
149      */
150     @Override
151     public void registerModel(final AxContextModel contextModel) throws ContextException {
152         ModelService.registerModel(AxKeyInformation.class, contextModel.getKeyInformation());
153         ModelService.registerModel(AxContextSchemas.class, contextModel.getSchemas());
154         ModelService.registerModel(AxContextAlbums.class, contextModel.getAlbums());
155     }
156
157     /**
158      * {@inheritDoc}.
159      */
160     @Override
161     public synchronized ContextAlbum createContextAlbum(final AxArtifactKey axContextAlbumKey) throws ContextException {
162         // Get the context album definition
163         final AxContextAlbum album = ModelService.getModel(AxContextAlbums.class).get(axContextAlbumKey);
164         if (album == null) {
165             final String resultString = "context album " + axContextAlbumKey.getId() + " does not exist";
166             LOGGER.warn(resultString);
167             throw new ContextException(resultString);
168         }
169
170         // Check if the context album is valid
171         final AxValidationResult result = album.validate(new AxValidationResult());
172         if (!result.isValid()) {
173             final String resultString = "context album definition for " + album.getKey().getId() + " is invalid"
174                             + result;
175             LOGGER.warn(resultString);
176             throw new ContextException(resultString);
177         }
178
179         // Get the schema of the context album
180         final AxContextSchema schema = ModelService.getModel(AxContextSchemas.class).get(album.getItemSchema());
181         if (schema == null) {
182             final String resultString = "schema \"" + album.getItemSchema().getId() + "\" for context album "
183                             + album.getKey().getId() + " does not exist";
184             LOGGER.warn(resultString);
185             throw new ContextException(resultString);
186         }
187
188         synchronized (albumMaps) {
189             // Check if the map has already been instantiated
190             if (!albumMaps.containsKey(album.getKey())) {
191                 // Instantiate the album map for this context album that we'll distribute using the distribution
192                 // mechanism
193                 final Map<String, Object> newContextAlbumMap = getContextAlbumMap(album.getKey());
194
195                 // The distributed context album will have content from another process instance if the album exists in
196                 // another process, if not, we have to try to read the content from persistence
197                 if (newContextAlbumMap.isEmpty()) {
198                     // Read entries from persistence, (Not implemented yet)
199                 }
200
201                 // Create the context album and put the context album object onto the distributor
202                 albumMaps.put(album.getKey(), new ContextAlbumImpl(album, this, newContextAlbumMap));
203             }
204
205             return albumMaps.get(album.getKey());
206         }
207     }
208
209     /**
210      * {@inheritDoc}.
211      */
212     @Override
213     public void removeContextAlbum(final AxContextAlbum contextAlbum) throws ContextException {
214         synchronized (albumMaps) {
215             // Check if the map already exists, if not return
216             if (!albumMaps.containsKey(contextAlbum.getKey())) {
217                 LOGGER.warn("map remove failed, supplied map is null");
218                 throw new ContextException("map update failed, supplied map is null");
219             }
220
221             // Remove the map from the distributor
222             albumMaps.remove(contextAlbum.getKey());
223         }
224     }
225
226     /**
227      * {@inheritDoc}.
228      */
229     @Override
230     public void flush() throws ContextException {
231         synchronized (albumMaps) {
232             // Flush all the maps
233             for (final Entry<AxArtifactKey, ContextAlbum> distributorMapEntry : albumMaps.entrySet()) {
234                 // Let the persistor write each of the entries
235                 for (final Object contextItem : distributorMapEntry.getValue().values()) {
236                     persistor.writeContextItem(contextItem);
237                 }
238             }
239         }
240     }
241
242     /**
243      * {@inheritDoc}.
244      */
245     @Override
246     public void flushContextAlbum(final ContextAlbum contextAlbum) throws ContextException {
247         synchronized (albumMaps) {
248             // Check if the map already exists, if not return
249             if (!albumMaps.containsKey(contextAlbum.getKey())) {
250                 LOGGER.warn("map flush failed, supplied map is null");
251                 throw new ContextException("map flush failed, supplied map is null");
252             }
253
254             // Let the persistor flush the items on the map
255             for (final Object contextItem : albumMaps.get(contextAlbum.getKey()).values()) {
256                 persistor.writeContextItem(contextItem);
257             }
258         }
259     }
260
261     /**
262      * {@inheritDoc}.
263      */
264     @Override
265     public synchronized void lockForReading(final AxArtifactKey mapKey, final String itemKey) throws ContextException {
266         // Lock using the lock manager
267         lockManager.lockForReading(mapKey.getId(), itemKey);
268     }
269
270     /**
271      * {@inheritDoc}.
272      */
273     @Override
274     public synchronized void lockForWriting(final AxArtifactKey mapKey, final String itemKey) throws ContextException {
275         // Lock using the lock manager
276         lockManager.lockForWriting(mapKey.getId(), itemKey);
277     }
278
279     /**
280      * {@inheritDoc}.
281      */
282     @Override
283     public void unlockForReading(final AxArtifactKey mapKey, final String itemKey) throws ContextException {
284         // Unlock using the lock manager
285         lockManager.unlockForReading(mapKey.getId(), itemKey);
286     }
287
288     /**
289      * {@inheritDoc}.
290      */
291     @Override
292     public void unlockForWriting(final AxArtifactKey mapKey, final String itemKey) throws ContextException {
293         // Unlock using the lock manager
294         lockManager.unlockForWriting(mapKey.getId(), itemKey);
295     }
296
297     /**
298      * {@inheritDoc}.
299      */
300     @Override
301     public void clear() {
302         // Shut down the lock manager
303         if (lockManager != null) {
304             lockManager.shutdown();
305             setLockManager(null);
306         }
307
308         synchronized (albumMaps) {
309             albumMaps.clear();
310         }
311
312         // Turn off the flush timer
313         flushTimer.cancel();
314
315         // Shut down the specialization of the context distributor
316         shutdown();
317     }
318 }