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