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