4f197e2d3a7c677375cd4fd899e3a5b89a78f758
[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.locking;
22
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Map;
26 import java.util.concurrent.locks.ReadWriteLock;
27
28 import org.onap.policy.apex.context.ContextException;
29 import org.onap.policy.apex.context.LockManager;
30 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
31 import org.slf4j.ext.XLogger;
32 import org.slf4j.ext.XLoggerFactory;
33
34 /**
35  * This class implements the {@link LockManager} functionality that is common across all implementations. Lock managers
36  * for specific lock mechanisms specialize this class.
37  *
38  * @author Liam Fallon (liam.fallon@ericsson.com)
39  */
40 public abstract class AbstractLockManager implements LockManager {
41     // Logger for this class
42     private static final XLogger LOGGER = XLoggerFactory.getXLogger(AbstractLockManager.class);
43
44     // The key of this lock manager
45     private AxArtifactKey key = null;
46
47     // Map of locks in use on this distributor for each context map
48     private final Map<String, Map<String, ReadWriteLock>> lockMaps =
49             Collections.synchronizedMap(new HashMap<String, Map<String, ReadWriteLock>>());
50
51     /*
52      * (non-Javadoc)
53      *
54      * @see org.onap.policy.apex.context.LockManager#init(org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey)
55      */
56     @Override
57     public void init(final AxArtifactKey lockManagerKey) throws ContextException {
58         this.key = lockManagerKey;
59     }
60
61     /*
62      * (non-Javadoc)
63      *
64      * @see org.onap.policy.apex.context.LockManager#getKey()
65      */
66     @Override
67     public AxArtifactKey getKey() {
68         return key;
69     }
70
71     /*
72      * (non-Javadoc)
73      *
74      * @see org.onap.policy.apex.core.context.LockManager#lockForReading(org.onap.policy.apex.core.model.concepts.
75      * AxArtifactKey, java.lang.String)
76      */
77     @Override
78     public synchronized void lockForReading(final String lockTypeKey, final String lockKey) throws ContextException {
79         LOGGER.entry("lockForReading(" + lockTypeKey + "_" + lockKey + ")");
80
81         // Find the lock or create a new one
82         final ReadWriteLock lock = getLock(lockTypeKey, lockKey, true);
83
84         try {
85             lock.readLock().lock();
86             LOGGER.exit("lockForReading(" + lockTypeKey + "_" + lockKey + ")");
87         } catch (final Exception e) {
88             LOGGER.warn("error acquiring read lock on context map " + lockTypeKey + " context item " + lockKey, e);
89             throw new ContextException(
90                     "error acquiring read lock on context map " + lockTypeKey + " context item " + lockKey, e);
91         }
92     }
93
94     /*
95      * (non-Javadoc)
96      *
97      * @see org.onap.policy.apex.core.context.LockManager#lockForWriting(java.lang.String, java.lang.String)
98      */
99     @Override
100     public synchronized void lockForWriting(final String lockTypeKey, final String lockKey) throws ContextException {
101         LOGGER.entry("lockForWriting(" + lockTypeKey + "_" + lockKey + ")");
102
103         // Find the lock or create a new one
104         final ReadWriteLock lock = getLock(lockTypeKey, lockKey, true);
105
106         try {
107             lock.writeLock().lock();
108             LOGGER.exit("lockForWriting(" + lockTypeKey + "_" + lockKey + ")");
109         } catch (final Exception e) {
110             LOGGER.warn("error acquiring write lock on context map " + lockTypeKey + " context item " + lockKey, e);
111             throw new ContextException(
112                     "error acquiring write lock on context map " + lockTypeKey + " context item " + lockKey, e);
113         }
114     }
115
116     /*
117      * (non-Javadoc)
118      *
119      * @see org.onap.policy.apex.core.context.LockManager#unlockForReading(java.lang.String, java.lang.String)
120      */
121     @Override
122     public void unlockForReading(final String lockTypeKey, final String lockKey) throws ContextException {
123         LOGGER.entry("unlockForReading(" + lockTypeKey + "_" + lockKey + ")");
124
125         // Find the lock
126         final ReadWriteLock lock = getLock(lockTypeKey, lockKey, false);
127
128         try {
129             lock.readLock().unlock();
130             LOGGER.exit("unlockForReading(" + lockTypeKey + "_" + lockKey + ")");
131         } catch (final Exception e) {
132             LOGGER.warn("error releasing read lock on context map " + lockTypeKey + " context item " + lockKey, e);
133             throw new ContextException(
134                     "error releasing read lock on context map " + lockTypeKey + " context item " + lockKey, e);
135         }
136     }
137
138     /*
139      * (non-Javadoc)
140      *
141      * @see org.onap.policy.apex.core.context.LockManager#unlockForWriting(java.lang.String, java.lang.String)
142      */
143     @Override
144     public void unlockForWriting(final String lockTypeKey, final String lockKey) throws ContextException {
145         LOGGER.entry("unlockForWriting(" + lockTypeKey + "_" + lockKey + ")");
146
147         // Find the lock
148         final ReadWriteLock lock = getLock(lockTypeKey, lockKey, false);
149
150         try {
151             lock.writeLock().unlock();
152             LOGGER.exit("unlockForWriting(" + lockTypeKey + "_" + lockKey + ")");
153         } catch (final Exception e) {
154             LOGGER.warn("error releasing write lock on context map " + lockTypeKey + " context item " + lockKey, e);
155             throw new ContextException(
156                     "error releasing write lock on context map " + lockTypeKey + " context item " + lockKey, e);
157         }
158     }
159
160     /*
161      * (non-Javadoc)
162      *
163      * @see org.onap.policy.apex.core.context.LockManager#shutdown()
164      */
165     @Override
166     public abstract void shutdown();
167
168     /**
169      * Get a reentrant read write lock from whatever locking mechanism is in use.
170      *
171      * @param lockId The unique ID of the lock.
172      * @return The lock
173      * @throws ContextException On errors getting a lock
174      */
175     protected abstract ReadWriteLock getReentrantReadWriteLock(String lockId) throws ContextException;
176
177     /**
178      * Get a lock for a context item in a context map.
179      *
180      * @param lockTypeKey The key of the map where the context item to lock is
181      * @param lockKey The key on the map to lock
182      * @param createMode if true, create a lock if it does not exist
183      * @return The lock
184      * @throws ContextException On errors getting the lock
185      */
186     private ReadWriteLock getLock(final String lockTypeKey, final String lockKey, final boolean createMode)
187             throws ContextException {
188         // Check if we have a lock type map for this lock type yet
189         if (!lockMaps.containsKey(lockTypeKey)) {
190             // Create a lock type map for the lock type
191             lockMaps.put(lockTypeKey, Collections.synchronizedMap(new HashMap<String, ReadWriteLock>()));
192         }
193
194         // Find or create a lock in the lock map
195         ReadWriteLock lock = lockMaps.get(lockTypeKey).get(lockKey);
196         if (lock != null) {
197             return lock;
198         }
199
200         // Should we create a lock?
201         if (!createMode) {
202             LOGGER.warn("error getting lock on context map " + lockTypeKey + " context item " + lockKey
203                     + ", lock does not exist");
204             throw new ContextException("error getting lock on context map " + lockTypeKey + " context item " + lockKey
205                     + ", lock does not exist");
206         }
207
208         try {
209             // Create the lock using the specialization of this abstract class
210             lock = getReentrantReadWriteLock(lockTypeKey + "_" + lockKey);
211
212             // Add the lock to the lock map
213             lockMaps.get(lockTypeKey).put(lockKey, lock);
214
215             if (LOGGER.isTraceEnabled()) {
216                 LOGGER.trace("created lock " + lockTypeKey + "_" + lockKey);
217             }
218             return lock;
219         } catch (final Exception e) {
220             LOGGER.warn("error getting lock on context map " + lockTypeKey + " context item " + lockKey, e);
221             throw new ContextException("error getting lock on context map " + lockTypeKey + " context item " + lockKey,
222                     e);
223         }
224     }
225 }