|
21 | 21 |
|
22 | 22 | import java.util.ArrayList; |
23 | 23 | import java.util.List; |
| 24 | +import java.util.function.Consumer; |
24 | 25 |
|
25 | 26 | import org.slf4j.Logger; |
26 | 27 | import org.slf4j.LoggerFactory; |
@@ -75,6 +76,9 @@ public class OzoneManagerLock { |
75 | 76 | private static final Logger LOG = |
76 | 77 | LoggerFactory.getLogger(OzoneManagerLock.class); |
77 | 78 |
|
| 79 | + private static final String READ_LOCK = "read"; |
| 80 | + private static final String WRITE_LOCK = "write"; |
| 81 | + |
78 | 82 | private final LockManager<String> manager; |
79 | 83 | private final ThreadLocal<Short> lockSet = ThreadLocal.withInitial( |
80 | 84 | () -> Short.valueOf((short)0)); |
@@ -105,15 +109,66 @@ public OzoneManagerLock(Configuration conf) { |
105 | 109 | * should be bucket name. For remaining all resource only one param should |
106 | 110 | * be passed. |
107 | 111 | */ |
| 112 | + @Deprecated |
108 | 113 | public boolean acquireLock(Resource resource, String... resources) { |
109 | 114 | String resourceName = generateResourceName(resource, resources); |
| 115 | + return lock(resource, resourceName, manager::writeLock, WRITE_LOCK); |
| 116 | + } |
| 117 | + |
| 118 | + /** |
| 119 | + * Acquire read lock on resource. |
| 120 | + * |
| 121 | + * For S3_BUCKET_LOCK, VOLUME_LOCK, BUCKET_LOCK type resource, same |
| 122 | + * thread acquiring lock again is allowed. |
| 123 | + * |
| 124 | + * For USER_LOCK, PREFIX_LOCK, S3_SECRET_LOCK type resource, same thread |
| 125 | + * acquiring lock again is not allowed. |
| 126 | + * |
| 127 | + * Special Note for USER_LOCK: Single thread can acquire single user lock/ |
| 128 | + * multi user lock. But not both at the same time. |
| 129 | + * @param resource - Type of the resource. |
| 130 | + * @param resources - Resource names on which user want to acquire lock. |
| 131 | + * For Resource type BUCKET_LOCK, first param should be volume, second param |
| 132 | + * should be bucket name. For remaining all resource only one param should |
| 133 | + * be passed. |
| 134 | + */ |
| 135 | + public boolean acquireReadLock(Resource resource, String... resources) { |
| 136 | + String resourceName = generateResourceName(resource, resources); |
| 137 | + return lock(resource, resourceName, manager::readLock, READ_LOCK); |
| 138 | + } |
| 139 | + |
| 140 | + |
| 141 | + /** |
| 142 | + * Acquire write lock on resource. |
| 143 | + * |
| 144 | + * For S3_BUCKET_LOCK, VOLUME_LOCK, BUCKET_LOCK type resource, same |
| 145 | + * thread acquiring lock again is allowed. |
| 146 | + * |
| 147 | + * For USER_LOCK, PREFIX_LOCK, S3_SECRET_LOCK type resource, same thread |
| 148 | + * acquiring lock again is not allowed. |
| 149 | + * |
| 150 | + * Special Note for USER_LOCK: Single thread can acquire single user lock/ |
| 151 | + * multi user lock. But not both at the same time. |
| 152 | + * @param resource - Type of the resource. |
| 153 | + * @param resources - Resource names on which user want to acquire lock. |
| 154 | + * For Resource type BUCKET_LOCK, first param should be volume, second param |
| 155 | + * should be bucket name. For remaining all resource only one param should |
| 156 | + * be passed. |
| 157 | + */ |
| 158 | + public boolean acquireWriteLock(Resource resource, String... resources) { |
| 159 | + String resourceName = generateResourceName(resource, resources); |
| 160 | + return lock(resource, resourceName, manager::writeLock, WRITE_LOCK); |
| 161 | + } |
| 162 | + |
| 163 | + private boolean lock(Resource resource, String resourceName, |
| 164 | + Consumer<String> lockFn, String lockType) { |
110 | 165 | if (!resource.canLock(lockSet.get())) { |
111 | 166 | String errorMessage = getErrorMessage(resource); |
112 | 167 | LOG.error(errorMessage); |
113 | 168 | throw new RuntimeException(errorMessage); |
114 | 169 | } else { |
115 | | - manager.lock(resourceName); |
116 | | - LOG.debug("Acquired {} lock on resource {}", resource.name, |
| 170 | + lockFn.accept(resourceName); |
| 171 | + LOG.debug("Acquired {} {} lock on resource {}", lockType, resource.name, |
117 | 172 | resourceName); |
118 | 173 | lockSet.set(resource.setLock(lockSet.get())); |
119 | 174 | return true; |
@@ -197,19 +252,19 @@ public boolean acquireMultiUserLock(String firstUser, String secondUser) { |
197 | 252 |
|
198 | 253 | if (compare == 0) { |
199 | 254 | // both users are equal. |
200 | | - manager.lock(firstUser); |
| 255 | + manager.writeLock(firstUser); |
201 | 256 | } else { |
202 | | - manager.lock(firstUser); |
| 257 | + manager.writeLock(firstUser); |
203 | 258 | try { |
204 | | - manager.lock(secondUser); |
| 259 | + manager.writeLock(secondUser); |
205 | 260 | } catch (Exception ex) { |
206 | 261 | // We got an exception acquiring 2nd user lock. Release already |
207 | 262 | // acquired user lock, and throw exception to the user. |
208 | | - manager.unlock(firstUser); |
| 263 | + manager.writeUnlock(firstUser); |
209 | 264 | throw ex; |
210 | 265 | } |
211 | 266 | } |
212 | | - LOG.debug("Acquired {} lock on resource {} and {}", resource.name, |
| 267 | + LOG.debug("Acquired Write {} lock on resource {} and {}", resource.name, |
213 | 268 | firstUser, secondUser); |
214 | 269 | lockSet.set(resource.setLock(lockSet.get())); |
215 | 270 | return true; |
@@ -240,35 +295,66 @@ public void releaseMultiUserLock(String firstUser, String secondUser) { |
240 | 295 |
|
241 | 296 | if (compare == 0) { |
242 | 297 | // both users are equal. |
243 | | - manager.unlock(firstUser); |
| 298 | + manager.writeUnlock(firstUser); |
244 | 299 | } else { |
245 | | - manager.unlock(firstUser); |
246 | | - manager.unlock(secondUser); |
| 300 | + manager.writeUnlock(firstUser); |
| 301 | + manager.writeUnlock(secondUser); |
247 | 302 | } |
248 | | - LOG.debug("Release {} lock on resource {} and {}", resource.name, |
| 303 | + LOG.debug("Release Write {} lock on resource {} and {}", resource.name, |
249 | 304 | firstUser, secondUser); |
250 | 305 | lockSet.set(resource.clearLock(lockSet.get())); |
251 | 306 | } |
252 | 307 |
|
253 | 308 | /** |
254 | | - * Release lock on resource. |
| 309 | + * Release write lock on resource. |
| 310 | + * @param resource - Type of the resource. |
| 311 | + * @param resources - Resource names on which user want to acquire lock. |
| 312 | + * For Resource type BUCKET_LOCK, first param should be volume, second param |
| 313 | + * should be bucket name. For remaining all resource only one param should |
| 314 | + * be passed. |
| 315 | + */ |
| 316 | + public void releaseWriteLock(Resource resource, String... resources) { |
| 317 | + String resourceName = generateResourceName(resource, resources); |
| 318 | + unlock(resource, resourceName, manager::writeUnlock, WRITE_LOCK); |
| 319 | + } |
| 320 | + |
| 321 | + /** |
| 322 | + * Release read lock on resource. |
| 323 | + * @param resource - Type of the resource. |
| 324 | + * @param resources - Resource names on which user want to acquire lock. |
| 325 | + * For Resource type BUCKET_LOCK, first param should be volume, second param |
| 326 | + * should be bucket name. For remaining all resource only one param should |
| 327 | + * be passed. |
| 328 | + */ |
| 329 | + public void releaseReadLock(Resource resource, String... resources) { |
| 330 | + String resourceName = generateResourceName(resource, resources); |
| 331 | + unlock(resource, resourceName, manager::readUnlock, READ_LOCK); |
| 332 | + } |
| 333 | + |
| 334 | + /** |
| 335 | + * Release write lock on resource. |
255 | 336 | * @param resource - Type of the resource. |
256 | 337 | * @param resources - Resource names on which user want to acquire lock. |
257 | 338 | * For Resource type BUCKET_LOCK, first param should be volume, second param |
258 | 339 | * should be bucket name. For remaining all resource only one param should |
259 | 340 | * be passed. |
260 | 341 | */ |
| 342 | + @Deprecated |
261 | 343 | public void releaseLock(Resource resource, String... resources) { |
262 | 344 | String resourceName = generateResourceName(resource, resources); |
| 345 | + unlock(resource, resourceName, manager::writeUnlock, WRITE_LOCK); |
| 346 | + } |
| 347 | + |
| 348 | + private void unlock(Resource resource, String resourceName, |
| 349 | + Consumer<String> lockFn, String lockType) { |
263 | 350 | // TODO: Not checking release of higher order level lock happened while |
264 | 351 | // releasing lower order level lock, as for that we need counter for |
265 | 352 | // locks, as some locks support acquiring lock again. |
266 | | - manager.unlock(resourceName); |
| 353 | + lockFn.accept(resourceName); |
267 | 354 | // clear lock |
268 | | - LOG.debug("Release {}, lock on resource {}", resource.name, |
269 | | - resource.name, resourceName); |
| 355 | + LOG.debug("Release {} {}, lock on resource {}", lockType, resource.name, |
| 356 | + resourceName); |
270 | 357 | lockSet.set(resource.clearLock(lockSet.get())); |
271 | | - |
272 | 358 | } |
273 | 359 |
|
274 | 360 | /** |
|
0 commit comments