| 91 | private SessionNode root = new SessionNode(LockLevel.CLUSTER); |
| 92 | |
| 93 | public Lock lock( |
| 94 | CollectionParams.CollectionAction action, List<String> path, String callingLockId) { |
| 95 | if (action.lockLevel == LockLevel.NONE) return FREELOCK; |
| 96 | Node startingNode = LockTree.this.root; |
| 97 | SessionNode startingSession = root; |
| 98 | |
| 99 | // If a callingLockId was passed in, validate it with the current lock path, and only start |
| 100 | // locking below the calling lock |
| 101 | Lock callingLock = StrUtils.isBlank(callingLockId) ? null : allLocks.get(callingLockId); |
| 102 | log.debug("Calling lock id: {}, level: {}", callingLockId, callingLock); |
| 103 | boolean reuseCurrentLock = false; |
| 104 | if (callingLock != null) { |
| 105 | if (callingLock.validateSubpath(action.lockLevel.getHeight(), path)) { |
| 106 | startingNode = ((LockImpl) callingLock).node; |
| 107 | startingSession = startingSession.find(startingNode.level.getHeight(), path); |
| 108 | if (startingSession == null) { |
| 109 | startingSession = root; |
| 110 | } |
| 111 | reuseCurrentLock = true; |
| 112 | } else { |
| 113 | throw new SolrException( |
| 114 | SolrException.ErrorCode.SERVER_ERROR, |
| 115 | String.format( |
| 116 | Locale.ROOT, |
| 117 | "Cannot lock an action under a different path than the calling action. Calling action lock path: %s, Requested action lock path: %s", |
| 118 | callingLock, |
| 119 | String.join("/", path))); |
| 120 | } |
| 121 | } |
| 122 | synchronized (LockTree.this) { |
| 123 | if (startingSession.isBusy(action.lockLevel, path)) return null; |
| 124 | Lock lockObject = startingNode.lock(action.lockLevel, path, reuseCurrentLock); |
| 125 | if (lockObject == null) { |
| 126 | startingSession.markBusy(action.lockLevel, path); |
| 127 | } else { |
| 128 | allLocks.put(lockObject.id(), lockObject); |
| 129 | } |
| 130 | return lockObject; |
| 131 | } |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | private static class SessionNode { |