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