From ffb9044301d1c169f934e0adf4f473e99da39a47 Mon Sep 17 00:00:00 2001
From: boli <boli@localhost>
Date: Mon, 27 Aug 2007 18:58:10 +0000
Subject: [PATCH] This adds the numSubordinates and hasSubordinates operational attribute support in OpenDS. - Implemented as virtual attributes - They are enabled by default - numSubordinates and hasSubordinates methods added to the backend API and implemented for all existing backends - JE implementation uses the id2children index to keep count of the number of subordinates for each entry. - The behavior of exceeding the index-entry-limit (ALL-IDs) has changed to store a 8 byte entry ID set count with the most significant bit set to 1 instead of a 0 byte array to signify the index-entry-limit has been exceeded. The previous format is still compatible but all requests for numSubordinates will return undefined (-1). - The DBTest tool is also included in this fix. This can be used to list root containers, entry containers, database containers, index status, as well as dumping a database with or without decoding the data.
---
opends/src/server/org/opends/server/backends/jeb/BackendImpl.java | 101 ++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 93 insertions(+), 8 deletions(-)
diff --git a/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java b/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
index cc8b802..b9a7956 100644
--- a/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
+++ b/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
@@ -311,7 +311,7 @@
EnvironmentConfig envConfig =
ConfigurableEnvironment.parseConfigEntry(cfg);
- initializeRootContainer(envConfig);
+ rootContainer = initializeRootContainer(envConfig);
}
// Preload the database cache.
@@ -598,7 +598,63 @@
return -1;
}
+ /**
+ * {@inheritDoc}
+ */
+ public ConditionResult hasSubordinates(DN entryDN) throws DirectoryException
+ {
+ long ret = numSubordinates(entryDN);
+ if(ret < 0)
+ {
+ return ConditionResult.UNDEFINED;
+ }
+ else if(ret == 0)
+ {
+ return ConditionResult.FALSE;
+ }
+ else
+ {
+ return ConditionResult.TRUE;
+ }
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public long numSubordinates(DN entryDN) throws DirectoryException
+ {
+ EntryContainer ec = rootContainer.getEntryContainer(entryDN);
+ if(ec == null)
+ {
+ return -1;
+ }
+
+ readerBegin();
+ ec.sharedLock.lock();
+ try
+ {
+ long count = ec.getNumSubordinates(entryDN);
+ if(count == Long.MAX_VALUE)
+ {
+ // The index entry limit has exceeded and there is no count maintained.
+ return -1;
+ }
+ return count;
+ }
+ catch (DatabaseException e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ throw createDirectoryException(e);
+ }
+ finally
+ {
+ ec.sharedLock.unlock();
+ readerEnd();
+ }
+ }
/**
* Retrieves the requested entry from this backend. Note that the caller must
@@ -938,7 +994,7 @@
envConfig.setConfigParam("je.env.isLocking", "true");
envConfig.setConfigParam("je.env.runCheckpointer", "true");
- initializeRootContainer(envConfig);
+ rootContainer = initializeRootContainer(envConfig);
}
@@ -1081,7 +1137,7 @@
envConfig.setConfigParam("je.env.runCheckpointer", "false");
}
- initializeRootContainer(envConfig);
+ rootContainer = initializeRootContainer(envConfig);
ImportJob importJob = new ImportJob(importConfig);
return importJob.importLDIF(rootContainer);
@@ -1192,7 +1248,7 @@
envConfig.setConfigParam("je.env.isLocking", "true");
envConfig.setConfigParam("je.env.runCheckpointer", "true");
- initializeRootContainer(envConfig);
+ rootContainer = initializeRootContainer(envConfig);
}
VerifyJob verifyJob = new VerifyJob(verifyConfig);
@@ -1275,7 +1331,7 @@
EnvironmentConfig envConfig =
ConfigurableEnvironment.parseConfigEntry(cfg);
- initializeRootContainer(envConfig);
+ rootContainer = initializeRootContainer(envConfig);
}
RebuildJob rebuildJob = new RebuildJob(rebuildConfig);
@@ -1502,6 +1558,34 @@
}
/**
+ * Returns a new read-only handle to the JE root container for this backend.
+ * The caller is responsible for closing the root container after use.
+ *
+ * @return The read-only RootContainer object for this backend.
+ *
+ * @throws ConfigException If an unrecoverable problem arises during
+ * initialization.
+ * @throws InitializationException If a problem occurs during initialization
+ * that is not related to the server
+ * configuration.
+ */
+ public RootContainer getReadOnlyRootContainer()
+ throws ConfigException, InitializationException
+ {
+ EnvironmentConfig envConfig =
+ ConfigurableEnvironment.parseConfigEntry(cfg);
+
+ envConfig.setReadOnly(true);
+ envConfig.setAllowCreate(false);
+ envConfig.setTransactional(false);
+ envConfig.setTxnNoSync(false);
+ envConfig.setConfigParam("je.env.isLocking", "true");
+ envConfig.setConfigParam("je.env.runCheckpointer", "true");
+
+ return initializeRootContainer(envConfig);
+ }
+
+ /**
* Clears all the entries from the backend. This method is for test cases
* that use the JE backend.
*
@@ -1589,14 +1673,15 @@
return cfg.dn();
}
- private void initializeRootContainer(EnvironmentConfig envConfig)
+ private RootContainer initializeRootContainer(EnvironmentConfig envConfig)
throws ConfigException, InitializationException
{
// Open the database environment
try
{
- rootContainer = new RootContainer(this, cfg);
- rootContainer.open(envConfig);
+ RootContainer rc = new RootContainer(this, cfg);
+ rc.open(envConfig);
+ return rc;
}
catch (DatabaseException e)
{
--
Gitblit v1.10.0