| | |
| | | import java.util.Set; |
| | | import java.util.SortedSet; |
| | | import java.util.concurrent.ExecutionException; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | |
| | | import org.forgerock.i18n.LocalizableException; |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | |
| | | /** The root container to use for this backend. */ |
| | | private RootContainer rootContainer; |
| | | |
| | | // FIXME: this is broken. Replace with read-write lock. |
| | | /** A count of the total operation threads currently in the backend. */ |
| | | private final AtomicInteger threadTotalCount = new AtomicInteger(0); |
| | | /** |
| | | * A count of the total operation threads currently in the backend. Bumped |
| | | * twice per operation by all worker threads, so it uses a striped counter |
| | | * to avoid contending on a single cache line; it is only read when waiting |
| | | * for the backend to become quiescent, which is why it is not a LongAdder — |
| | | * see {@link StripedCounter}. |
| | | */ |
| | | private final StripedCounter threadTotalCount = new StripedCounter(); |
| | | /** The base DNs defined for this backend instance. */ |
| | | private Set<DN> baseDNs; |
| | | |
| | |
| | | throw new DirectoryException( |
| | | noEntryContainerResultCode, ERR_BACKEND_ENTRY_DOESNT_EXIST.get(entryDN, getBackendID())); |
| | | } |
| | | threadTotalCount.getAndIncrement(); |
| | | threadTotalCount.increment(); |
| | | return ec; |
| | | } |
| | | |
| | | /** End a Backend API method that accesses the EntryContainer. */ |
| | | private void accessEnd() |
| | | { |
| | | threadTotalCount.getAndDecrement(); |
| | | threadTotalCount.decrement(); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | private void waitUntilQuiescent() |
| | | { |
| | | while (threadTotalCount.get() > 0) |
| | | while (threadTotalCount.sum() > 0) |
| | | { |
| | | // Still have threads accessing the storage so sleep a little |
| | | try |
| | |
| | | } |
| | | |
| | | // Make sure the thread counts are zero for next initialization. |
| | | threadTotalCount.set(0); |
| | | threadTotalCount.reset(); |
| | | |
| | | // Log an informational message. |
| | | logger.info(NOTE_BACKEND_OFFLINE, cfg.getBackendId()); |
| | |
| | | throw de; |
| | | } |
| | | |
| | | container.sharedLock.lock(); |
| | | container.beginSharedAccess(); |
| | | try |
| | | { |
| | | return ConditionResult.valueOf(container.hasSubordinates(entryDN)); |
| | |
| | | } |
| | | finally |
| | | { |
| | | container.sharedLock.unlock(); |
| | | container.endSharedAccess(); |
| | | accessEnd(); |
| | | } |
| | | } |
| | |
| | | checkNotNull(baseDN, "baseDN must not be null"); |
| | | |
| | | final EntryContainer ec = accessBegin(null, baseDN); |
| | | ec.sharedLock.lock(); |
| | | ec.beginSharedAccess(); |
| | | try |
| | | { |
| | | return ec.getNumberOfEntriesInBaseDN(); |
| | |
| | | } |
| | | finally |
| | | { |
| | | ec.sharedLock.unlock(); |
| | | ec.endSharedAccess(); |
| | | accessEnd(); |
| | | } |
| | | } |
| | |
| | | throw de; |
| | | } |
| | | |
| | | ec.sharedLock.lock(); |
| | | ec.beginSharedAccess(); |
| | | try |
| | | { |
| | | return ec.getNumberOfChildren(parentDN); |
| | |
| | | } |
| | | finally |
| | | { |
| | | ec.sharedLock.unlock(); |
| | | ec.endSharedAccess(); |
| | | accessEnd(); |
| | | } |
| | | } |
| | |
| | | public boolean entryExists(final DN entryDN) throws DirectoryException |
| | | { |
| | | EntryContainer ec = accessBegin(null, entryDN); |
| | | ec.sharedLock.lock(); |
| | | ec.beginSharedAccess(); |
| | | try |
| | | { |
| | | return ec.entryExists(entryDN); |
| | |
| | | } |
| | | finally |
| | | { |
| | | ec.sharedLock.unlock(); |
| | | ec.endSharedAccess(); |
| | | accessEnd(); |
| | | } |
| | | } |
| | |
| | | public Entry getEntry(DN entryDN) throws DirectoryException |
| | | { |
| | | EntryContainer ec = accessBegin(null, entryDN); |
| | | ec.sharedLock.lock(); |
| | | ec.beginSharedAccess(); |
| | | try |
| | | { |
| | | return ec.getEntry(entryDN); |
| | |
| | | } |
| | | finally |
| | | { |
| | | ec.sharedLock.unlock(); |
| | | ec.endSharedAccess(); |
| | | accessEnd(); |
| | | } |
| | | } |
| | |
| | | { |
| | | EntryContainer ec = accessBegin(addOperation, entry.getName()); |
| | | |
| | | ec.sharedLock.lock(); |
| | | ec.beginSharedAccess(); |
| | | try |
| | | { |
| | | ec.addEntry(entry, addOperation); |
| | |
| | | } |
| | | finally |
| | | { |
| | | ec.sharedLock.unlock(); |
| | | ec.endSharedAccess(); |
| | | accessEnd(); |
| | | } |
| | | } |
| | |
| | | { |
| | | EntryContainer ec = accessBegin(deleteOperation, entryDN); |
| | | |
| | | ec.sharedLock.lock(); |
| | | ec.beginSharedAccess(); |
| | | try |
| | | { |
| | | ec.deleteEntry(entryDN, deleteOperation); |
| | |
| | | } |
| | | finally |
| | | { |
| | | ec.sharedLock.unlock(); |
| | | ec.endSharedAccess(); |
| | | accessEnd(); |
| | | } |
| | | } |
| | |
| | | { |
| | | EntryContainer ec = accessBegin(modifyOperation, newEntry.getName()); |
| | | |
| | | ec.sharedLock.lock(); |
| | | ec.beginSharedAccess(); |
| | | |
| | | try |
| | | { |
| | |
| | | } |
| | | finally |
| | | { |
| | | ec.sharedLock.unlock(); |
| | | ec.endSharedAccess(); |
| | | accessEnd(); |
| | | } |
| | | } |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, WARN_FUNCTION_NOT_SUPPORTED.get()); |
| | | } |
| | | |
| | | currentContainer.sharedLock.lock(); |
| | | currentContainer.beginSharedAccess(); |
| | | try |
| | | { |
| | | currentContainer.renameEntry(currentDN, entry, modifyDNOperation); |
| | |
| | | } |
| | | finally |
| | | { |
| | | currentContainer.sharedLock.unlock(); |
| | | currentContainer.endSharedAccess(); |
| | | accessEnd(); |
| | | } |
| | | } |
| | |
| | | // is concerned: report it as such instead of the UNDEFINED result code used internally. |
| | | EntryContainer ec = accessBegin(searchOperation, searchOperation.getBaseDN(), ResultCode.NO_SUCH_OBJECT); |
| | | |
| | | ec.sharedLock.lock(); |
| | | ec.beginSharedAccess(); |
| | | |
| | | try |
| | | { |
| | |
| | | } |
| | | finally |
| | | { |
| | | ec.sharedLock.unlock(); |
| | | ec.endSharedAccess(); |
| | | accessEnd(); |
| | | } |
| | | } |