From 5031429bf032af5e3d8797210cc47b402ef831d6 Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Tue, 16 Dec 2014 23:48:24 +0000
Subject: [PATCH] OPENDJ-1602 (CR-5566) New pluggable storage based backend
---
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DN2URI.java | 3
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/IndexFilter.java | 1
opendj3-server-dev/src/server/org/opends/server/backends/persistit/PersistItStorage.java | 431 ++++++++++++
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/NullIndex.java | 2
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/SuffixContainer.java | 8
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VLVIndex.java | 122 +--
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DatabaseEnvironmentMonitor.java | 394 +++++++++++
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/Index.java | 2
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VerifyJob.java | 59 -
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/SortValuesSet.java | 10
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DatabaseContainer.java | 2
/dev/null | 90 --
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/AttributeIndex.java | 16
opendj3-server-dev/src/server/org/opends/server/backends/jeb/EntryContainer.java | 1
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/RootContainer.java | 291 ++-----
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EnvManager.java | 39
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/ExportJob.java | 3
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EntryContainer.java | 457 +++++-------
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/BackendImpl.java | 129 +--
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EntryIDSetSorter.java | 3
20 files changed, 1,263 insertions(+), 800 deletions(-)
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/EntryContainer.java b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/EntryContainer.java
index 1e1c2d5..a667fa4 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/EntryContainer.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/EntryContainer.java
@@ -2687,7 +2687,6 @@
* @return The number of entries stored in this entry container.
* @throws DatabaseException If an error occurs in the JE database.
*/
- @Override
public long getEntryCount() throws DatabaseException
{
EntryID entryID = dn2id.get(null, baseDN, LockMode.DEFAULT);
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/persistit/PersistItStorage.java b/opendj3-server-dev/src/server/org/opends/server/backends/persistit/PersistItStorage.java
new file mode 100644
index 0000000..1abbddc
--- /dev/null
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/persistit/PersistItStorage.java
@@ -0,0 +1,431 @@
+package org.opends.server.backends.persistit;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.forgerock.opendj.ldap.ByteSequence;
+import org.forgerock.opendj.ldap.ByteString;
+import org.opends.server.admin.std.server.LocalDBBackendCfg;
+import org.opends.server.backends.pluggable.BackendImpl.Cursor;
+import org.opends.server.backends.pluggable.BackendImpl.Importer;
+import org.opends.server.backends.pluggable.BackendImpl.ReadOperation;
+import org.opends.server.backends.pluggable.BackendImpl.Storage;
+import org.opends.server.backends.pluggable.BackendImpl.StorageRuntimeException;
+import org.opends.server.backends.pluggable.BackendImpl.TreeName;
+import org.opends.server.backends.pluggable.BackendImpl.WriteOperation;
+import org.opends.server.backends.pluggable.BackendImpl.WriteableStorage;
+import org.opends.server.types.DN;
+
+import com.persistit.Exchange;
+import com.persistit.Key;
+import com.persistit.Persistit;
+import com.persistit.Transaction;
+import com.persistit.Tree;
+import com.persistit.TreeBuilder;
+import com.persistit.Value;
+import com.persistit.Volume;
+import com.persistit.exception.PersistitException;
+import com.persistit.exception.RollbackException;
+
+@SuppressWarnings("javadoc")
+public final class PersistItStorage implements Storage {
+ private final class ImporterImpl implements Importer {
+ private final Map<TreeName, Tree> trees = new HashMap<TreeName, Tree>();
+ private final TreeBuilder importer = new TreeBuilder(db);
+ private final Key importKey = new Key(db);
+ private final Value importValue = new Value(db);
+
+ @Override
+ public void createTree(TreeName treeName) {
+ try {
+ // FIXME: how do we set the comparator?
+ final Tree tree = getVolume(treeName).getTree(treeName.toString(), true);
+ trees.put(treeName, tree);
+ } catch (PersistitException e) {
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ @Override
+ public void put(TreeName treeName, ByteSequence key, ByteSequence value) {
+ try {
+ final Tree tree = trees.get(treeName);
+ byte[] keyBytes = key.toByteArray();
+ importKey.clear().appendByteArray(keyBytes, 0, keyBytes.length);
+ importValue.clear().putByteArray(value.toByteArray());
+ importer.store(tree, importKey, importValue);
+ } catch (Exception e) {
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ @Override
+ public void close() {
+ try {
+ importer.merge();
+ } catch (Exception e) {
+ throw new StorageRuntimeException(e);
+ } finally {
+ PersistItStorage.this.close();
+ }
+ }
+ }
+
+ private final class StorageImpl implements WriteableStorage {
+ private final Map<TreeName, Exchange> exchanges = new HashMap<TreeName, Exchange>();
+
+ private void release() {
+ for (Exchange ex : exchanges.values()) {
+ db.releaseExchange(ex);
+ }
+ }
+
+ private Exchange getExchange(TreeName treeName) throws PersistitException {
+ Exchange exchange = exchanges.get(treeName);
+ if (exchange == null) {
+ exchange = getExchange0(treeName, false);
+ exchanges.put(treeName, exchange);
+ }
+ return exchange;
+ }
+
+ @Override
+ public ByteString get(TreeName treeName, ByteSequence key) {
+ try {
+ final Exchange ex = getExchange(treeName);
+ ex.getKey().clear().append(key.toByteArray());
+ ex.fetch();
+ final Value value = ex.getValue();
+ if (value.isDefined()) {
+ return ByteString.wrap(value.getByteArray());
+ }
+ return null;
+ } catch (PersistitException e) {
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ @Override
+ public ByteString getRMW(TreeName treeName, ByteSequence key) {
+ return get(treeName, key);
+ }
+
+ @Override
+ public void put(TreeName treeName, ByteSequence key, ByteSequence value) {
+ try {
+ final Exchange ex = getExchange(treeName);
+ ex.getKey().clear().append(key.toByteArray());
+ ex.getValue().clear().putByteArray(value.toByteArray());
+ ex.store();
+ } catch (Exception e) {
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean putIfAbsent(TreeName treeName, ByteSequence key, ByteSequence value) {
+ try {
+ final Exchange ex = getExchange(treeName);
+ ex.getKey().clear().append(key.toByteArray());
+ ex.fetch();
+ // FIXME poor man's CAS: this will not work under high volume,
+ // but PersistIt does not provide APIs for this use case.
+ if (ex.isValueDefined()) {
+ return false;
+ }
+ ex.getValue().clear().putByteArray(value.toByteArray());
+ ex.store();
+ return true;
+ } catch (Exception e) {
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean remove(TreeName treeName, ByteSequence key) {
+ try {
+ final Exchange ex = getExchange(treeName);
+ ex.getKey().clear().append(key.toByteArray());
+ return ex.remove();
+ } catch (PersistitException e) {
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ @Override
+ public Cursor openCursor(TreeName treeName) {
+ try {
+ return new CursorImpl(getExchange(treeName));
+ } catch (PersistitException e) {
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ @Override
+ public void openTree(TreeName treeName) {
+ Exchange ex = null;
+ try {
+ ex = getExchange0(treeName, true);
+ } catch (PersistitException e) {
+ throw new StorageRuntimeException(e);
+ } finally {
+ db.releaseExchange(ex);
+ }
+ }
+ }
+
+ private final class CursorImpl implements Cursor {
+
+ private final Exchange ex;
+ private boolean useCurrentKeyForNext = false;
+
+ public CursorImpl(Exchange exchange) {
+ this.ex = exchange;
+ }
+
+ @Override
+ public boolean positionToKey(ByteSequence key) {
+ ex.getKey().clear().append(key.toByteArray());
+ try {
+ ex.fetch();
+ useCurrentKeyForNext = ex.getValue().isDefined();
+ return useCurrentKeyForNext;
+ } catch (PersistitException e) {
+ useCurrentKeyForNext = false;
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean positionToKeyOrNext(ByteSequence key) {
+ ex.getKey().clear().append(key.toByteArray());
+ try {
+ ex.fetch();
+ if (ex.getValue().isDefined()) {
+ useCurrentKeyForNext = true;
+ } else {
+ // provided key does not exist, look for next key
+ useCurrentKeyForNext = ex.next();
+ }
+ return useCurrentKeyForNext;
+ } catch (PersistitException e) {
+ useCurrentKeyForNext = false;
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean positionToLastKey() {
+ try {
+ ex.getKey().to(Key.AFTER);
+ useCurrentKeyForNext = ex.previous() && ex.getValue().isDefined();
+ return useCurrentKeyForNext;
+ } catch (PersistitException e) {
+ useCurrentKeyForNext = false;
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean next() {
+ if (useCurrentKeyForNext) {
+ useCurrentKeyForNext = false;
+ return true;
+ }
+ try {
+ return ex.next();
+ } catch (PersistitException e) {
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean previous() {
+ try {
+ return ex.previous();
+ } catch (PersistitException e) {
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ @Override
+ public ByteString getKey() {
+ return ByteString.wrap(ex.getKey().decodeByteArray());
+ }
+
+ @Override
+ public ByteString getValue() {
+ return ByteString.wrap(ex.getValue().getByteArray());
+ }
+
+ @Override
+ public void close() {
+ // Exchange is released by StorageImpl.release()
+ // once the Read/Write Operation is closed
+ }
+ }
+
+ private final File backendDirectory;
+ private final LocalDBBackendCfg config;
+ private Persistit db;
+ private final ConcurrentMap<TreeName, Volume> volumes = new ConcurrentHashMap<TreeName, Volume>();
+ private Properties properties;
+
+ public PersistItStorage(File backendDirectory, LocalDBBackendCfg config) {
+ this.backendDirectory = backendDirectory;
+ this.config = config;
+ }
+
+ private Volume getVolume(TreeName treeName) {
+ return volumes.get(treeName.getSuffix());
+ }
+
+ @Override
+ public void initialize(Map<String, String> options) {
+ properties = new Properties();
+ properties.setProperty("datapath", backendDirectory.toString());
+ properties.setProperty("logpath", backendDirectory.toString());
+ properties.setProperty("logfile", "${logpath}/dj_${timestamp}.log");
+ properties.setProperty("buffer.count.16384", "64K");
+ properties.setProperty("journalpath", "${datapath}/dj_journal");
+ int i = 1;
+ for (DN baseDN : config.getBaseDN()) {
+ // TODO use VolumeSpecification Configuration.setVolumeList()?
+ properties.setProperty("volume." + i++,
+ "${datapath}/" + toSuffixName(baseDN.toString())
+ + ",create,pageSize:16K"
+ + ",initialSize:50M"
+ + ",extensionSize:1M"
+ + ",maximumSize:10G");
+ }
+
+ if (options != null) {
+ for (Entry<String, String> entry : options.entrySet()) {
+ properties.setProperty(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ /**
+ * Replace persistit reserved comma character with an underscore character.
+ */
+ public String toSuffixName(String prefix) {
+ return prefix.replaceAll("[,=]", "_");
+ }
+
+ @Override
+ public void open() {
+ try {
+ db = new Persistit(properties);
+ db.initialize();
+ for (DN baseDN : config.getBaseDN()) {
+ final String volumeName = toSuffixName(baseDN.toString());
+ final TreeName suffixName = TreeName.of(volumeName);
+ volumes.put(suffixName, db.loadVolume(volumeName));
+ }
+ } catch (PersistitException e) {
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ @Override
+ public void close() {
+ if (db != null) {
+ try {
+ db.close();
+ db = null;
+ } catch (PersistitException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ static void clearAndCreateDbDir(final File dbDir) {
+ if (dbDir.exists()) {
+ for (final File child : dbDir.listFiles()) {
+ child.delete();
+ }
+ } else {
+ dbDir.mkdirs();
+ }
+ }
+
+ @Override
+ public Importer startImport() {
+ clearAndCreateDbDir(backendDirectory);
+ open();
+ return new ImporterImpl();
+ }
+
+ @Override
+ public <T> T read(ReadOperation<T> operation) throws Exception {
+ final Transaction txn = db.getTransaction();
+ for (;;) {
+ txn.begin();
+ try {
+ final StorageImpl storageImpl = new StorageImpl();
+ try {
+ final T result = operation.run(storageImpl);
+ txn.commit();
+ return result;
+ } catch (StorageRuntimeException e) {
+ throw (Exception) e.getCause();
+ } finally {
+ storageImpl.release();
+ }
+ } catch (RollbackException e) {
+ // retry
+ } catch (Exception e) {
+ txn.rollback();
+ throw e;
+ } finally {
+ txn.end();
+ }
+ }
+ }
+
+ @Override
+ public void write(WriteOperation operation) throws Exception {
+ final Transaction txn = db.getTransaction();
+ for (;;) {
+ txn.begin();
+ try {
+ final StorageImpl storageImpl = new StorageImpl();
+ try {
+ operation.run(storageImpl);
+ txn.commit();
+ return;
+ } catch (StorageRuntimeException e) {
+ throw (Exception) e.getCause();
+ } finally {
+ storageImpl.release();
+ }
+ } catch (RollbackException e) {
+ // retry
+ } catch (Exception e) {
+ txn.rollback();
+ throw e;
+ } finally {
+ txn.end();
+ }
+ }
+ }
+
+ @Override
+ public Cursor openCursor(TreeName treeName) {
+ try {
+ return new CursorImpl(getExchange0(treeName, false));//FIXME JNR we must release the exchange
+ } catch (PersistitException e) {
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ private Exchange getExchange0(TreeName treeName, boolean create) throws PersistitException {
+ return db.getExchange(getVolume(treeName), treeName.toString(), create);
+ }
+}
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/AttributeIndex.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/AttributeIndex.java
index 2183b19..014d9f7 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/AttributeIndex.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/AttributeIndex.java
@@ -49,7 +49,6 @@
import org.opends.server.backends.pluggable.BackendImpl.WriteOperation;
import org.opends.server.backends.pluggable.BackendImpl.WriteableStorage;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.monitors.DatabaseEnvironmentMonitor;
import org.opends.server.types.*;
import org.opends.server.util.StaticUtils;
@@ -716,11 +715,12 @@
}
}
}
- removeIndexesForExtensibleMatchingRules(validRules, validIndexIds);
+ removeIndexesForExtensibleMatchingRules(txn, validRules, validIndexIds);
}
/** Remove indexes which do not correspond to valid rules. */
- private void removeIndexesForExtensibleMatchingRules(Set<MatchingRule> validRules, Set<String> validIndexIds)
+ private void removeIndexesForExtensibleMatchingRules(WriteableStorage txn, Set<MatchingRule> validRules,
+ Set<String> validIndexIds)
{
final Set<MatchingRule> rulesToDelete = getCurrentExtensibleMatchingRules();
rulesToDelete.removeAll(validRules);
@@ -746,7 +746,7 @@
Index index = nameToIndexes.get(indexId);
if (index != null)
{
- entryContainer.deleteDatabase(index);
+ entryContainer.deleteDatabase(txn, index);
nameToIndexes.remove(index);
}
}
@@ -779,7 +779,7 @@
Index index = nameToIndexes.get(indexId);
if (!cfg.getIndexType().contains(indexType))
{
- removeIndex(index, indexType);
+ removeIndex(txn, index, indexType);
return;
}
@@ -811,7 +811,7 @@
Index index = nameToIndexes.get(indexID);
if (!cfg.getIndexType().contains(indexType))
{
- removeIndex(index, indexType);
+ removeIndex(txn, index, indexType);
return;
}
@@ -832,7 +832,7 @@
}
}
- private void removeIndex(Index index, IndexType indexType)
+ private void removeIndex(WriteableStorage txn, Index index, IndexType indexType)
{
if (index != null)
{
@@ -840,7 +840,7 @@
try
{
nameToIndexes.remove(indexType.toString());
- entryContainer.deleteDatabase(index);
+ entryContainer.deleteDatabase(txn, index);
}
finally
{
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/BackendImpl.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/BackendImpl.java
index 8411478..2334b57 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/BackendImpl.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/BackendImpl.java
@@ -54,16 +54,12 @@
import org.opends.server.api.Backend;
import org.opends.server.api.DiskSpaceMonitorHandler;
import org.opends.server.api.MonitorProvider;
+import org.opends.server.backends.pluggable.BackendImpl.WriteableStorage;
import org.opends.server.core.*;
import org.opends.server.extensions.DiskSpaceMonitor;
import org.opends.server.types.*;
import org.opends.server.util.RuntimeInformation;
-import com.sleepycat.je.Durability;
-import com.sleepycat.je.EnvironmentConfig;
-
-import static com.sleepycat.je.EnvironmentConfig.*;
-
import static org.opends.messages.BackendMessages.*;
import static org.opends.messages.JebMessages.*;
import static org.opends.server.backends.jeb.ConfigurableEnvironment.*;
@@ -408,7 +404,7 @@
if (mustOpenRootContainer())
{
- rootContainer = initializeRootContainer(parseConfigEntry(cfg));
+ rootContainer = initializeRootContainer();
}
// Preload the database cache.
@@ -417,7 +413,7 @@
try
{
// Log an informational message about the number of entries.
- logger.info(NOTE_JEB_BACKEND_STARTED, cfg.getBackendId(), rootContainer.getEntryCount());
+ logger.info(NOTE_JEB_BACKEND_STARTED, cfg.getBackendId(), getEntryCount());
}
catch (StorageRuntimeException e)
{
@@ -640,7 +636,6 @@
logger.traceException(e);
}
}
-
return -1;
}
@@ -988,7 +983,7 @@
throw new NotImplementedException();
// Importer importer = new Importer(importConfig, cfg, envConfig);
-// rootContainer = initializeRootContainer(envConfig);
+// rootContainer = initializeRootContainer();
// return importer.processImport(rootContainer);
}
catch (ExecutionException execEx)
@@ -1005,10 +1000,10 @@
logger.traceException(intEx);
throw new DirectoryException(errorRC, ERR_INTERRUPTED_ERROR.get(intEx.getMessage()));
}
- catch (JebException je)
+ catch (StorageRuntimeException e)
{
- logger.traceException(je);
- throw new DirectoryException(errorRC, je.getMessageObject());
+ logger.traceException(e);
+ throw new DirectoryException(errorRC, LocalizableMessage.raw(e.getMessage()));
}
catch (InitializationException ie)
{
@@ -1093,12 +1088,6 @@
logger.traceException(e);
throw createDirectoryException(e);
}
- catch (JebException e)
- {
- logger.traceException(e);
- throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
- e.getMessageObject());
- }
finally
{
closeTemporaryRootContainer(openRootContainer);
@@ -1141,7 +1130,7 @@
if (openRootContainer)
{
envConfig = getEnvConfigForImport();
- rootContainer = initializeRootContainer(envConfig);
+ rootContainer = initializeRootContainer();
}
else
{
@@ -1167,10 +1156,10 @@
logger.traceException(ce);
throw new DirectoryException(errorRC, ce.getMessageObject());
}
- catch (JebException e)
+ catch (StorageRuntimeException e)
{
logger.traceException(e);
- throw new DirectoryException(errorRC, e.getMessageObject());
+ throw new DirectoryException(errorRC, LocalizableMessage.raw(e.getMessage()));
}
catch (InitializationException e)
{
@@ -1270,50 +1259,52 @@
/** {@inheritDoc} */
@Override
- public ConfigChangeResult applyConfigurationChange(LocalDBBackendCfg newCfg)
+ public ConfigChangeResult applyConfigurationChange(final LocalDBBackendCfg newCfg)
{
- ResultCode resultCode = ResultCode.SUCCESS;
- ArrayList<LocalizableMessage> messages = new ArrayList<LocalizableMessage>();
-
+ final ConfigChangeResult ccr = new ConfigChangeResult();
try
{
if(rootContainer != null)
{
- SortedSet<DN> newBaseDNs = newCfg.getBaseDN();
- DN[] newBaseDNsArray = newBaseDNs.toArray(new DN[newBaseDNs.size()]);
-
- // Check for changes to the base DNs.
- removeDeletedBaseDNs(newBaseDNs);
- ConfigChangeResult failure = createNewBaseDNs(newBaseDNsArray, messages);
- if (failure != null)
+ rootContainer.getStorage().write(new WriteOperation()
{
- return failure;
- }
+ @Override
+ public void run(WriteableStorage txn) throws Exception
+ {
+ SortedSet<DN> newBaseDNs = newCfg.getBaseDN();
+ DN[] newBaseDNsArray = newBaseDNs.toArray(new DN[newBaseDNs.size()]);
- baseDNs = newBaseDNsArray;
+ // Check for changes to the base DNs.
+ removeDeletedBaseDNs(newBaseDNs, txn);
+ if (!createNewBaseDNs(newBaseDNsArray, ccr, txn))
+ {
+ return;
+ }
+
+ baseDNs = newBaseDNsArray;
+
+ if(cfg.getDiskFullThreshold() != newCfg.getDiskFullThreshold() ||
+ cfg.getDiskLowThreshold() != newCfg.getDiskLowThreshold())
+ {
+ diskMonitor.setFullThreshold(newCfg.getDiskFullThreshold());
+ diskMonitor.setLowThreshold(newCfg.getDiskLowThreshold());
+ }
+
+ // Put the new configuration in place.
+ cfg = newCfg;
+ }
+ });
}
-
- if(cfg.getDiskFullThreshold() != newCfg.getDiskFullThreshold() ||
- cfg.getDiskLowThreshold() != newCfg.getDiskLowThreshold())
- {
- diskMonitor.setFullThreshold(newCfg.getDiskFullThreshold());
- diskMonitor.setLowThreshold(newCfg.getDiskLowThreshold());
- }
-
- // Put the new configuration in place.
- this.cfg = newCfg;
}
catch (Exception e)
{
- messages.add(LocalizableMessage.raw(stackTraceToSingleLineString(e)));
- return new ConfigChangeResult(
- DirectoryServer.getServerErrorResultCode(), false, messages);
+ ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+ ccr.addMessage(LocalizableMessage.raw(stackTraceToSingleLineString(e)));
}
-
- return new ConfigChangeResult(resultCode, false, messages);
+ return ccr;
}
- private void removeDeletedBaseDNs(SortedSet<DN> newBaseDNs) throws DirectoryException
+ private void removeDeletedBaseDNs(SortedSet<DN> newBaseDNs, WriteableStorage txn) throws DirectoryException
{
for (DN baseDN : cfg.getBaseDN())
{
@@ -1323,12 +1314,12 @@
DirectoryServer.deregisterBaseDN(baseDN);
EntryContainer ec = rootContainer.unregisterEntryContainer(baseDN);
ec.close();
- ec.delete();
+ ec.delete(txn);
}
}
}
- private ConfigChangeResult createNewBaseDNs(DN[] newBaseDNsArray, ArrayList<LocalizableMessage> messages)
+ private boolean createNewBaseDNs(DN[] newBaseDNsArray, ConfigChangeResult ccr, WriteableStorage txn)
{
for (DN baseDN : newBaseDNsArray)
{
@@ -1337,7 +1328,7 @@
try
{
// The base DN was added.
- EntryContainer ec = rootContainer.openEntryContainer(baseDN, null);
+ EntryContainer ec = rootContainer.openEntryContainer(baseDN, null, txn);
rootContainer.registerEntryContainer(baseDN, ec);
DirectoryServer.registerBaseDN(baseDN, this, false);
}
@@ -1345,13 +1336,13 @@
{
logger.traceException(e);
- ResultCode resultCode = DirectoryServer.getServerErrorResultCode();
- messages.add(ERR_BACKEND_CANNOT_REGISTER_BASEDN.get(baseDN, e));
- return new ConfigChangeResult(resultCode, false, messages);
+ ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+ ccr.addMessage(ERR_BACKEND_CANNOT_REGISTER_BASEDN.get(baseDN, e));
+ return false;
}
}
}
- return null;
+ return true;
}
/**
@@ -1380,15 +1371,7 @@
public RootContainer getReadOnlyRootContainer()
throws ConfigException, InitializationException
{
- EnvironmentConfig envConfig = parseConfigEntry(cfg);
-
- envConfig.setReadOnly(true);
- envConfig.setAllowCreate(false);
- envConfig.setTransactional(false);
- envConfig.setConfigParam(ENV_IS_LOCKING, "true");
- envConfig.setConfigParam(ENV_RUN_CHECKPOINTER, "true");
-
- return initializeRootContainer(envConfig);
+ return initializeRootContainer();
}
/**
@@ -1397,11 +1380,9 @@
*
* @throws ConfigException If an unrecoverable problem arises in the
* process of performing the initialization.
- *
- * @throws JebException If an error occurs while removing the data.
+ * @throws StorageRuntimeException If an error occurs while removing the data.
*/
- public void clearBackend()
- throws ConfigException, JebException
+ public void clearBackend() throws ConfigException, StorageRuntimeException
{
// Determine the backend database directory.
File parentDirectory = getFileForPath(cfg.getDBDirectory());
@@ -1419,7 +1400,7 @@
*/
DirectoryException createDirectoryException(StorageRuntimeException e)
{
- if (true) {
+ if (true) { // FIXME JNR
throw new NotImplementedException();
}
if (/*e instanceof EnvironmentFailureException && */ !rootContainer.isValid()) {
@@ -1465,12 +1446,12 @@
return cfg.dn();
}
- private RootContainer initializeRootContainer(EnvironmentConfig envConfig)
+ private RootContainer initializeRootContainer()
throws ConfigException, InitializationException {
// Open the database environment
try {
RootContainer rc = new RootContainer(this, cfg);
- rc.open(envConfig);
+ rc.open();
return rc;
}
catch (StorageRuntimeException e)
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DN2URI.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DN2URI.java
index d3d7f78..569fa89 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DN2URI.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DN2URI.java
@@ -104,7 +104,6 @@
* @throws StorageRuntimeException
* If an error occurs in the JE database.
*/
- @SuppressWarnings("unchecked")
DN2URI(TreeName treeName, Storage storage, EntryContainer entryContainer)
throws StorageRuntimeException
{
@@ -502,7 +501,7 @@
{
if (containsReferrals == ConditionResult.UNDEFINED)
{
- containsReferrals = containsReferrals(null);
+ containsReferrals = containsReferrals(txn);
}
if (containsReferrals == ConditionResult.FALSE)
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DatabaseContainer.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DatabaseContainer.java
index 612bbc1..0043a69 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DatabaseContainer.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DatabaseContainer.java
@@ -211,7 +211,7 @@
* @return The count of key/data pairs in the database.
* @throws StorageRuntimeException If an error occurs in the JE operation.
*/
- public long getRecordCount() throws StorageRuntimeException
+ public long getRecordCount(ReadableStorage txn) throws StorageRuntimeException
{
long count = treeName.count();
if (logger.isTraceEnabled())
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DatabaseEnvironmentMonitor.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DatabaseEnvironmentMonitor.java
new file mode 100644
index 0000000..1d8b46d
--- /dev/null
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/DatabaseEnvironmentMonitor.java
@@ -0,0 +1,394 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2006-2010 Sun Microsystems, Inc.
+ * Portions Copyright 2014 ForgeRock AS
+ */
+package org.opends.server.backends.pluggable;
+
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.config.server.ConfigException;
+import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.AttributeSyntax;
+import org.opends.server.api.MonitorProvider;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.types.*;
+import org.opends.server.util.TimeThread;
+
+/**
+ * A monitor provider for a Berkeley DB JE environment.
+ * It uses reflection on the environment statistics object
+ * so that we don't need to keep a list of all the stats.
+ */
+public class DatabaseEnvironmentMonitor
+ extends MonitorProvider<MonitorProviderCfg>
+{
+ private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
+
+ /** Represents the statistical information kept for each search filter. */
+ private static class FilterStats implements Comparable<FilterStats>
+ {
+ private volatile LocalizableMessage failureReason = LocalizableMessage.EMPTY;
+ private long maxMatchingEntries = -1;
+ private final AtomicInteger hits = new AtomicInteger();
+
+ @Override
+ public int compareTo(FilterStats that) {
+ return this.hits.get() - that.hits.get();
+ }
+
+ private void update(int hitCount, LocalizableMessage failureReason)
+ {
+ this.hits.getAndAdd(hitCount);
+ this.failureReason = failureReason;
+ }
+
+ private void update(int hitCount, long matchingEntries)
+ {
+ this.hits.getAndAdd(hitCount);
+ this.failureReason = LocalizableMessage.EMPTY;
+ synchronized(this)
+ {
+ if(matchingEntries > maxMatchingEntries)
+ {
+ maxMatchingEntries = matchingEntries;
+ }
+ }
+ }
+ }
+
+ /** The name of this monitor instance. */
+ private String name;
+
+ /** The root container to be monitored. */
+ private RootContainer rootContainer;
+
+ private int maxEntries = 1024;
+ private boolean filterUseEnabled = false;
+ private String startTimeStamp;
+ private final HashMap<SearchFilter, FilterStats> filterToStats =
+ new HashMap<SearchFilter, FilterStats>();
+ private final AtomicInteger indexedSearchCount = new AtomicInteger();
+ private final AtomicInteger unindexedSearchCount = new AtomicInteger();
+
+ /**
+ * Creates a new database environment monitor.
+ * @param name The monitor instance name.
+ * @param rootContainer A root container handle for the database to be
+ * monitored.
+ */
+ public DatabaseEnvironmentMonitor(String name, RootContainer rootContainer)
+ {
+ this.name = name;
+ this.rootContainer = rootContainer;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void initializeMonitorProvider(MonitorProviderCfg configuration)
+ throws ConfigException, InitializationException
+ {
+ }
+
+ /**
+ * Retrieves the name of this monitor provider. It should be unique among all
+ * monitor providers, including all instances of the same monitor provider.
+ *
+ * @return The name of this monitor provider.
+ */
+ @Override
+ public String getMonitorInstanceName()
+ {
+ return name;
+ }
+
+ /**
+ * Creates monitor attribute values for a given JE statistics object,
+ * using reflection to call all the getter methods of the statistics object.
+ * The attribute type names of the created attribute values are derived from
+ * the names of the getter methods.
+ * @param monitorAttrs The monitor attribute values are inserted into this
+ * attribute list.
+ * @param stats The JE statistics object.
+ * @param attrPrefix A common prefix for the attribute type names of the
+ * monitor attribute values, to distinguish the attributes of one
+ * type of statistical object from another, and to avoid attribute name
+ * collisions.
+ */
+ private void addAttributesForStatsObject(ArrayList<Attribute> monitorAttrs,
+ Object stats, String attrPrefix)
+ {
+ Class<?> c = stats.getClass();
+ Method[] methods = c.getMethods();
+
+ // Iterate through all the statistic class methods.
+ for (Method method : methods)
+ {
+ // Invoke all the getters returning integer values.
+ if (method.getName().startsWith("get"))
+ {
+ Class<?> returnType = method.getReturnType();
+ if (returnType.equals(int.class) || returnType.equals(long.class))
+ {
+ AttributeSyntax<?> integerSyntax =
+ DirectoryServer.getDefaultIntegerSyntax();
+
+ // Remove the 'get' from the method name and add the prefix.
+ String attrName = attrPrefix + method.getName().substring(3);
+
+ try
+ {
+ // Read the statistic.
+ Object statValue = method.invoke(stats);
+
+ // Create an attribute from the statistic.
+ AttributeType attrType =
+ DirectoryServer.getDefaultAttributeType(attrName, integerSyntax);
+ monitorAttrs.add(Attributes.create(attrType, String.valueOf(statValue)));
+
+ } catch (Exception e)
+ {
+ logger.traceException(e);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Retrieves a set of attributes containing monitor data that should be
+ * returned to the client if the corresponding monitor entry is requested.
+ *
+ * @return A set of attributes containing monitor data that should be
+ * returned to the client if the corresponding monitor entry is
+ * requested.
+ */
+ @Override
+ public ArrayList<Attribute> getMonitorData()
+ {
+ ArrayList<Attribute> monitorAttrs = new ArrayList<Attribute>();
+
+ AttributeBuilder needReindex = new AttributeBuilder("need-reindex");
+ for(EntryContainer ec : rootContainer.getEntryContainers())
+ {
+ List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>();
+ ec.listDatabases(databases);
+ for(DatabaseContainer dc : databases)
+ {
+ if(dc instanceof Index && !((Index)dc).isTrusted())
+ {
+ needReindex.add(dc.getName().toString());
+ }
+ }
+ }
+ if(needReindex.size() > 0)
+ {
+ monitorAttrs.add(needReindex.toAttribute());
+ }
+
+ if(filterUseEnabled)
+ {
+ monitorAttrs.add(Attributes.create("filter-use-startTime",
+ startTimeStamp));
+ AttributeBuilder builder = new AttributeBuilder("filter-use");
+
+ StringBuilder stringBuilder = new StringBuilder();
+ synchronized(filterToStats)
+ {
+ for(Map.Entry<SearchFilter, FilterStats> entry :
+ filterToStats.entrySet())
+ {
+ entry.getKey().toString(stringBuilder);
+ stringBuilder.append(" hits:");
+ stringBuilder.append(entry.getValue().hits.get());
+ stringBuilder.append(" maxmatches:");
+ stringBuilder.append(entry.getValue().maxMatchingEntries);
+ stringBuilder.append(" message:");
+ stringBuilder.append(entry.getValue().failureReason);
+ builder.add(stringBuilder.toString());
+ stringBuilder.setLength(0);
+ }
+ }
+ monitorAttrs.add(builder.toAttribute());
+ monitorAttrs.add(Attributes.create("filter-use-indexed",
+ String.valueOf(indexedSearchCount.get())));
+ monitorAttrs.add(Attributes.create("filter-use-unindexed",
+ String.valueOf(unindexedSearchCount.get())));
+ }
+
+ return monitorAttrs;
+ }
+
+
+ /**
+ * Updates the index filter statistics with this latest search filter
+ * and the reason why an index was not used.
+ *
+ * @param searchFilter The search filter that was evaluated.
+ * @param failureMessage The reason why an index was not used.
+ */
+ public void updateStats(SearchFilter searchFilter, LocalizableMessage failureMessage)
+ {
+ if(!filterUseEnabled)
+ {
+ return;
+ }
+
+ FilterStats stats;
+ synchronized(filterToStats)
+ {
+ stats = filterToStats.get(searchFilter);
+
+
+ if(stats != null)
+ {
+ stats.update(1, failureMessage);
+ }
+ else
+ {
+ stats = new FilterStats();
+ stats.update(1, failureMessage);
+ removeLowestHit();
+ filterToStats.put(searchFilter, stats);
+ }
+ }
+ }
+
+ /**
+ * Updates the index filter statistics with this latest search filter
+ * and the number of entries matched by the index lookup.
+ *
+ * @param searchFilter The search filter that was evaluated.
+ * @param matchingEntries The number of entries matched by the successful
+ * index lookup.
+ */
+ public void updateStats(SearchFilter searchFilter, long matchingEntries)
+ {
+ if(!filterUseEnabled)
+ {
+ return;
+ }
+
+ FilterStats stats;
+ synchronized(filterToStats)
+ {
+ stats = filterToStats.get(searchFilter);
+
+
+ if(stats != null)
+ {
+ stats.update(1, matchingEntries);
+ }
+ else
+ {
+ stats = new FilterStats();
+ stats.update(1, matchingEntries);
+ removeLowestHit();
+ filterToStats.put(searchFilter, stats);
+ }
+ }
+ }
+
+ /**
+ * Enable or disable index filter statistics gathering.
+ *
+ * @param enabled <code>true></code> to enable index filter statics gathering.
+ */
+ public void enableFilterUseStats(boolean enabled)
+ {
+ if(enabled && !filterUseEnabled)
+ {
+ startTimeStamp = TimeThread.getGMTTime();
+ indexedSearchCount.set(0);
+ unindexedSearchCount.set(0);
+ }
+ else if(!enabled)
+ {
+ filterToStats.clear();
+ }
+ filterUseEnabled = enabled;
+ }
+
+ /**
+ * Indicates if index filter statistics gathering is enabled.
+ *
+ * @return <code>true</code> If index filter statistics gathering is enabled.
+ */
+ public boolean isFilterUseEnabled()
+ {
+ return filterUseEnabled;
+ }
+
+ /**
+ * Sets the maximum number of search filters statistics entries to keep
+ * before ones with the least hits will be removed.
+ *
+ * @param maxEntries The maximum number of search filters statistics
+ * entries to keep
+ */
+ public void setMaxEntries(int maxEntries) {
+ this.maxEntries = maxEntries;
+ }
+
+ /**
+ * Updates the statistics counter to include an indexed search.
+ */
+ public void updateIndexedSearchCount()
+ {
+ indexedSearchCount.getAndIncrement();
+ }
+
+ /**
+ * Updates the statistics counter to include an unindexed search.
+ */
+ public void updateUnindexedSearchCount()
+ {
+ unindexedSearchCount.getAndIncrement();
+ }
+
+ private void removeLowestHit()
+ {
+ while(!filterToStats.isEmpty() && filterToStats.size() > maxEntries)
+ {
+ Iterator<Map.Entry<SearchFilter, FilterStats>> i =
+ filterToStats.entrySet().iterator();
+ Map.Entry<SearchFilter, FilterStats> lowest = i.next();
+ Map.Entry<SearchFilter, FilterStats> entry;
+ while(lowest.getValue().hits.get() > 1 && i.hasNext())
+ {
+ entry = i.next();
+ if(entry.getValue().hits.get() < lowest.getValue().hits.get())
+ {
+ lowest = entry;
+ }
+ }
+
+ filterToStats.remove(lowest.getKey());
+ }
+ }
+}
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EntryContainer.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EntryContainer.java
index 35716bd..8ad27f7 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EntryContainer.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EntryContainer.java
@@ -27,7 +27,13 @@
*/
package org.opends.server.backends.pluggable;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -60,13 +66,38 @@
import org.opends.server.backends.pluggable.BackendImpl.TreeName;
import org.opends.server.backends.pluggable.BackendImpl.WriteOperation;
import org.opends.server.backends.pluggable.BackendImpl.WriteableStorage;
-import org.opends.server.backends.pluggable.SuffixContainer;
-import org.opends.server.controls.*;
-import org.opends.server.core.*;
-import org.opends.server.types.*;
+import org.opends.server.controls.PagedResultsControl;
+import org.opends.server.controls.ServerSideSortRequestControl;
+import org.opends.server.controls.ServerSideSortResponseControl;
+import org.opends.server.controls.SubtreeDeleteControl;
+import org.opends.server.controls.VLVRequestControl;
+import org.opends.server.core.AddOperation;
+import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.SearchOperation;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.Attributes;
+import org.opends.server.types.CanceledOperationException;
+import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
+import org.opends.server.types.Modification;
+import org.opends.server.types.Operation;
+import org.opends.server.types.Privilege;
+import org.opends.server.types.RDN;
+import org.opends.server.types.SearchFilter;
+import org.opends.server.types.SortKey;
+import org.opends.server.types.VirtualAttributeRule;
import org.opends.server.util.ServerConstants;
import org.opends.server.util.StaticUtils;
+import com.sleepycat.je.TransactionConfig;
+
import static org.opends.messages.JebMessages.*;
import static org.opends.server.backends.pluggable.JebFormat.*;
import static org.opends.server.core.DirectoryServer.*;
@@ -156,6 +187,8 @@
{
try
{
+ // FIXME this should be a read operation, but I cannot change it
+ // because of AttributeIndex ctor.
storage.write(new WriteOperation()
{
@Override
@@ -216,30 +249,35 @@
/** {@inheritDoc} */
@Override
- public ConfigChangeResult applyConfigurationDelete(LocalDBIndexCfg cfg)
+ public ConfigChangeResult applyConfigurationDelete(final LocalDBIndexCfg cfg)
{
- boolean adminActionRequired = false;
- ArrayList<LocalizableMessage> messages = new ArrayList<LocalizableMessage>();
+ final ConfigChangeResult ccr = new ConfigChangeResult();
exclusiveLock.lock();
try
{
- AttributeIndex index = attrIndexMap.get(cfg.getAttribute());
- deleteAttributeIndex(index);
- attrIndexMap.remove(cfg.getAttribute());
+ storage.write(new WriteOperation()
+ {
+ @Override
+ public void run(WriteableStorage txn) throws Exception
+ {
+ AttributeIndex index = attrIndexMap.get(cfg.getAttribute());
+ deleteAttributeIndex(txn, index, ccr);
+ attrIndexMap.remove(cfg.getAttribute());
+ }
+ });
}
- catch(StorageRuntimeException de)
+ catch (Exception de)
{
- messages.add(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(de)));
- return new ConfigChangeResult(
- DirectoryServer.getServerErrorResultCode(), adminActionRequired, messages);
+ ccr.setResultCode(getServerErrorResultCode());
+ ccr.addMessage(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(de)));
}
finally
{
exclusiveLock.unlock();
}
- return new ConfigChangeResult(ResultCode.SUCCESS, adminActionRequired, messages);
+ return ccr;
}
}
@@ -354,31 +392,33 @@
/** {@inheritDoc} */
@Override
- public ConfigChangeResult applyConfigurationDelete(LocalDBVLVIndexCfg cfg)
+ public ConfigChangeResult applyConfigurationDelete(final LocalDBVLVIndexCfg cfg)
{
- boolean adminActionRequired = false;
- List<LocalizableMessage> messages = new ArrayList<LocalizableMessage>();
-
+ final ConfigChangeResult ccr = new ConfigChangeResult();
exclusiveLock.lock();
try
{
- VLVIndex vlvIndex =
- vlvIndexMap.get(cfg.getName().toLowerCase());
- deleteDatabase(vlvIndex);
- vlvIndexMap.remove(cfg.getName());
+ storage.write(new WriteOperation()
+ {
+ @Override
+ public void run(WriteableStorage txn) throws Exception
+ {
+ VLVIndex vlvIndex = vlvIndexMap.get(cfg.getName().toLowerCase());
+ deleteDatabase(txn, vlvIndex);
+ vlvIndexMap.remove(cfg.getName());
+ }
+ });
}
- catch(StorageRuntimeException de)
+ catch (Exception e)
{
- messages.add(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(de)));
- return new ConfigChangeResult(
- DirectoryServer.getServerErrorResultCode(), adminActionRequired, messages);
+ ccr.setResultCode(getServerErrorResultCode());
+ ccr.addMessage(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(e)));
}
finally
{
exclusiveLock.unlock();
}
-
- return new ConfigChangeResult(ResultCode.SUCCESS, adminActionRequired, messages);
+ return ccr;
}
}
@@ -403,7 +443,7 @@
* @param rootContainer The root container this entry container is in.
* @throws ConfigException if a configuration related error occurs.
*/
- public EntryContainer(DN baseDN, String databasePrefix, Backend<?> backend,
+ public EntryContainer(DN baseDN, TreeName databasePrefix, Backend<?> backend,
LocalDBBackendCfg config, Storage env, RootContainer rootContainer)
throws ConfigException
{
@@ -412,8 +452,7 @@
this.config = config;
this.storage = env;
this.rootContainer = rootContainer;
-
- this.databasePrefix = preparePrefix(databasePrefix);
+ this.databasePrefix = databasePrefix;
config.addLocalDBChangeListener(this);
@@ -1316,14 +1355,12 @@
boolean manageDsaIT = isManageDsaITOperation(searchOperation);
boolean continueSearch = true;
- // Set the starting value.
- EntryID begin = null;
if (pageRequest != null && pageRequest.getCookie().length() != 0)
{
// The cookie contains the ID of the next entry to be returned.
try
{
- begin = new EntryID(pageRequest.getCookie());
+ new EntryID(pageRequest.getCookie());
}
catch (Exception e)
{
@@ -1354,10 +1391,8 @@
// Iterate through the index candidates.
if (continueSearch)
{
- for (Iterator<EntryID> it = entryIDList.iterator(begin); it.hasNext();)
+ for (EntryID id : entryIDList)
{
- final EntryID id = it.next();
-
Entry entry;
try
{
@@ -1556,7 +1591,7 @@
EntryID nodeID = dn2id.get(txn, dn, false);
if (nodeID == null)
{
- throw new JebException(ERR_JEB_MISSING_DN2ID_RECORD.get(dn));
+ throw new StorageRuntimeException(ERR_JEB_MISSING_DN2ID_RECORD.get(dn).toString());
}
// Insert into id2subtree for this node.
@@ -1816,7 +1851,7 @@
DN targetDN,
ByteSequence leafDNKey,
EntryID leafID)
- throws StorageRuntimeException, DirectoryException, JebException
+ throws StorageRuntimeException, DirectoryException
{
if(leafID == null || leafDNKey == null)
{
@@ -1884,7 +1919,7 @@
EntryID parentID = dn2id.get(txn, parentDN, false);
if (parentID == null)
{
- throw new JebException(ERR_JEB_MISSING_DN2ID_RECORD.get(parentDN));
+ throw new StorageRuntimeException(ERR_JEB_MISSING_DN2ID_RECORD.get(parentDN).toString());
}
ByteString parentIDBytes = parentID.toByteString();
@@ -2747,14 +2782,12 @@
* @return The number of entries stored in this entry container.
* @throws StorageRuntimeException If an error occurs in the JE database.
*/
- @Override
- public long getEntryCount() throws StorageRuntimeException
+ public long getEntryCount(ReadableStorage txn) throws StorageRuntimeException
{
- EntryID entryID = dn2id.get(null, baseDN, false);
+ final EntryID entryID = dn2id.get(txn, baseDN, false);
if (entryID != null)
{
- EntryIDSet entryIDSet = id2subtree.readKey(entryID.toByteString(), null);
-
+ final EntryIDSet entryIDSet = id2subtree.readKey(entryID.toByteString(), txn);
long count = entryIDSet.size();
if(count != Long.MAX_VALUE)
{
@@ -2764,7 +2797,7 @@
else
{
// The count is not maintained. Fall back to the slow method
- return id2entry.getRecordCount();
+ return id2entry.getRecordCount(txn);
}
}
else
@@ -2910,36 +2943,14 @@
* @throws StorageRuntimeException If an error occurs while removing the entry
* container.
*/
- public void delete() throws StorageRuntimeException
+ public void delete(WriteableStorage txn) throws StorageRuntimeException
{
List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>();
listDatabases(databases);
- if(storage.getConfig().getTransactional())
+ for (DatabaseContainer db : databases)
{
- Transaction txn = beginTransaction();
-
- try
- {
- for(DatabaseContainer db : databases)
- {
- storage.removeDatabase(txn, db.getName());
- }
-
- transactionCommit(txn);
- }
- catch(StorageRuntimeException de)
- {
- transactionAbort(txn);
- throw de;
- }
- }
- else
- {
- for(DatabaseContainer db : databases)
- {
- storage.removeDatabase(null, db.getName());
- }
+ storage.removeDatabase(txn, db.getName());
}
}
@@ -2950,8 +2961,7 @@
* @throws StorageRuntimeException If an error occurs while attempting to delete the
* database.
*/
- public void deleteDatabase(DatabaseContainer database)
- throws StorageRuntimeException
+ public void deleteDatabase(WriteableStorage txn, DatabaseContainer database) throws StorageRuntimeException
{
if(database == state)
{
@@ -2960,31 +2970,10 @@
}
database.close();
- if(storage.getConfig().getTransactional())
+ storage.removeDatabase(txn, database.getName());
+ if(database instanceof Index)
{
- Transaction txn = beginTransaction();
- try
- {
- storage.removeDatabase(txn, database.getName());
- if(database instanceof Index)
- {
- state.removeIndexTrustState(txn, database);
- }
- transactionCommit(txn);
- }
- catch(StorageRuntimeException de)
- {
- transactionAbort(txn);
- throw de;
- }
- }
- else
- {
- storage.removeDatabase(null, database.getName());
- if(database instanceof Index)
- {
- state.removeIndexTrustState(null, database);
- }
+ state.removeIndexTrustState(txn, database);
}
}
@@ -2995,31 +2984,14 @@
* @throws StorageRuntimeException If an JE database error occurs while attempting
* to delete the index.
*/
- private void deleteAttributeIndex(AttributeIndex attributeIndex)
+ private void deleteAttributeIndex(WriteableStorage txn, AttributeIndex attributeIndex, ConfigChangeResult ccr)
throws StorageRuntimeException
{
attributeIndex.close();
- Transaction txn = storage.getConfig().getTransactional()
- ? beginTransaction() : null;
- try
+ for (Index index : attributeIndex.getAllIndexes())
{
- for (Index index : attributeIndex.getAllIndexes())
- {
- storage.removeDatabase(txn, index.getName());
- state.removeIndexTrustState(txn, index);
- }
- if (txn != null)
- {
- transactionCommit(txn);
- }
- }
- catch(StorageRuntimeException de)
- {
- if (txn != null)
- {
- transactionAbort(txn);
- }
- throw de;
+ storage.removeDatabase(txn, index.getName());
+ state.removeIndexTrustState(txn, index);
}
}
@@ -3041,16 +3013,13 @@
*
* @param newDatabasePrefix The new database prefix to use.
* @throws StorageRuntimeException If an error occurs in the JE database.
- * @throws JebException If an error occurs in the JE backend.
*/
- public void setDatabasePrefix(String newDatabasePrefix)
- throws StorageRuntimeException, JebException
-
+ public void setDatabasePrefix(TreeName newDatabasePrefix) throws StorageRuntimeException, StorageRuntimeException
{
- List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>();
+ final List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>();
listDatabases(databases);
- TreeName newDbPrefix = preparePrefix(newDatabasePrefix);
+ final TreeName newDbPrefix = newDatabasePrefix;
// close the containers.
for(DatabaseContainer db : databases)
@@ -3060,11 +3029,10 @@
try
{
- if(storage.getConfig().getTransactional())
+ storage.write(new WriteOperation()
{
- //Rename under transaction
- Transaction txn = beginTransaction();
- try
+ @Override
+ public void run(WriteableStorage txn) throws Exception
{
for(DatabaseContainer db : databases)
{
@@ -3072,52 +3040,60 @@
String newName = oldName.replace(databasePrefix, newDbPrefix);
storage.renameDatabase(txn, oldName, newName);
}
-
- transactionCommit(txn);
-
- for(DatabaseContainer db : databases)
+ }
+ });
+ storage.write(new WriteOperation()
+ {
+ @Override
+ public void run(WriteableStorage txn) throws Exception
+ {
+ for (DatabaseContainer db : databases)
{
TreeName oldName = db.getName();
String newName = oldName.replace(databasePrefix, newDbPrefix);
db.setName(newName);
}
- // Update the prefix.
- this.databasePrefix = newDbPrefix;
+ databasePrefix = newDbPrefix;
}
- catch(Exception e)
- {
- transactionAbort(txn);
-
- String msg = e.getMessage();
- if (msg == null)
- {
- msg = stackTraceToSingleLineString(e);
- }
- LocalizableMessage message = ERR_JEB_UNCHECKED_EXCEPTION.get(msg);
- throw new JebException(message, e);
- }
- }
- else
+ });
+ }
+ catch (Exception e)
+ {
+ String msg = e.getMessage();
+ if (msg == null)
{
- for(DatabaseContainer db : databases)
- {
- TreeName oldName = db.getName();
- String newName = oldName.replace(databasePrefix, newDbPrefix);
- storage.renameDatabase(txn, oldName, newName);
- db.setName(newName);
- }
-
- // Update the prefix.
- this.databasePrefix = newDbPrefix;
+ msg = stackTraceToSingleLineString(e);
}
+ LocalizableMessage message = ERR_JEB_UNCHECKED_EXCEPTION.get(msg);
+ throw new StorageRuntimeException(message.toString(), e);
}
finally
{
- // Open the containers backup.
- for(DatabaseContainer db : databases)
+ try
{
- db.open(txn);
+ storage.write(new WriteOperation()
+ {
+ @Override
+ public void run(WriteableStorage txn) throws Exception
+ {
+ // Open the containers backup.
+ for(DatabaseContainer db : databases)
+ {
+ db.open(txn);
+ }
+ }
+ });
+ }
+ catch (Exception e)
+ {
+ String msg = e.getMessage();
+ if (msg == null)
+ {
+ msg = stackTraceToSingleLineString(e);
+ }
+ LocalizableMessage message = ERR_JEB_UNCHECKED_EXCEPTION.get(msg);
+ throw new StorageRuntimeException(message.toString(), e);
}
}
}
@@ -3232,19 +3208,6 @@
}
/**
- * Get the environment config of the JE environment used in this entry
- * container.
- *
- * @return The environment config of the JE environment.
- * @throws StorageRuntimeException If an error occurs while retrieving the
- * configuration object.
- */
- public EnvironmentConfig getEnvironmentConfig() throws StorageRuntimeException
- {
- return storage.getConfig();
- }
-
- /**
* Clear the contents of this entry container.
*
* @return The number of records deleted.
@@ -3253,7 +3216,28 @@
*/
public long clear() throws StorageRuntimeException
{
- List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>();
+ final AtomicLong count = new AtomicLong();
+ try
+ {
+ storage.write(new WriteOperation()
+ {
+ @Override
+ public void run(WriteableStorage txn) throws Exception
+ {
+ count.set(clear0(txn));
+ }
+ });
+ return count.get();
+ }
+ catch (Exception e)
+ {
+ throw new StorageRuntimeException(e);
+ }
+ }
+
+ private long clear0(WriteableStorage txn) throws StorageRuntimeException
+ {
+ final List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>();
listDatabases(databases);
long count = 0;
@@ -3263,31 +3247,9 @@
}
try
{
- if(storage.getConfig().getTransactional())
+ for (DatabaseContainer db : databases)
{
- Transaction txn = beginTransaction();
-
- try
- {
- for(DatabaseContainer db : databases)
- {
- count += storage.truncateDatabase(txn, db.getName(), true);
- }
-
- transactionCommit(txn);
- }
- catch(StorageRuntimeException de)
- {
- transactionAbort(txn);
- throw de;
- }
- }
- else
- {
- for(DatabaseContainer db : databases)
- {
- count += storage.truncateDatabase(null, db.getName(), true);
- }
+ count += storage.truncateDatabase(txn, db.getName(), true);
}
}
finally
@@ -3297,39 +3259,11 @@
db.open(txn);
}
- Transaction txn = null;
- try
+ for (DatabaseContainer db : databases)
{
- if(storage.getConfig().getTransactional()) {
- txn = beginTransaction();
- }
- for(DatabaseContainer db : databases)
+ if (db instanceof Index)
{
- if (db instanceof Index)
- {
- Index index = (Index)db;
- index.setTrusted(txn, true);
- }
- }
- if(storage.getConfig().getTransactional()) {
- transactionCommit(txn);
- }
- }
- catch(Exception de)
- {
- logger.traceException(de);
-
- // This is mainly used during the unit tests, so it's not essential.
- try
- {
- if (txn != null)
- {
- transactionAbort(txn);
- }
- }
- catch (Exception e)
- {
- logger.traceException(de);
+ ((Index) db).setTrusted(txn, true);
}
}
}
@@ -3343,34 +3277,30 @@
* @param database The database to clear.
* @throws StorageRuntimeException if a JE database error occurs.
*/
- public void clearDatabase(DatabaseContainer database)
- throws StorageRuntimeException
+ public void clearDatabase(final DatabaseContainer database) throws StorageRuntimeException
{
database.close();
try
{
- if(storage.getConfig().getTransactional())
+ storage.write(new WriteOperation()
{
- Transaction txn = beginTransaction();
- try
+ @Override
+ public void run(WriteableStorage txn) throws Exception
{
- storage.removeDatabase(txn, database.getName());
- transactionCommit(txn);
+ try
+ {
+ storage.removeDatabase(txn, database.getName());
+ }
+ finally
+ {
+ database.open(txn);
+ }
}
- catch(StorageRuntimeException de)
- {
- transactionAbort(txn);
- throw de;
- }
- }
- else
- {
- storage.removeDatabase(null, database.getName());
- }
+ });
}
- finally
+ catch (Exception e)
{
- database.open(txn);
+ throw new StorageRuntimeException(e);
}
if(logger.isTraceEnabled())
{
@@ -3507,31 +3437,6 @@
return baseEntry;
}
-
- /**
- * Transform a database prefix string to one usable by the DB.
- * @param databasePrefix the database prefix
- * @return a new string when non letter or digit characters
- * have been replaced with underscore
- */
- private TreeName preparePrefix(String databasePrefix)
- {
- StringBuilder builder = new StringBuilder(databasePrefix.length());
- for (int i = 0; i < databasePrefix.length(); i++)
- {
- char ch = databasePrefix.charAt(i);
- if (Character.isLetterOrDigit(ch))
- {
- builder.append(ch);
- }
- else
- {
- builder.append('_');
- }
- }
- return TreeName.of(builder.toString());
- }
-
/** Get the exclusive lock. */
public void lock() {
exclusiveLock.lock();
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EntryIDSetSorter.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EntryIDSetSorter.java
index b77d737..6febd17 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EntryIDSetSorter.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EntryIDSetSorter.java
@@ -35,7 +35,6 @@
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.SearchScope;
-import org.opends.server.backends.pluggable.SuffixContainer;
import org.opends.server.controls.VLVRequestControl;
import org.opends.server.controls.VLVResponseControl;
import org.opends.server.core.DirectoryServer;
@@ -68,7 +67,7 @@
*
* @throws DirectoryException If an error occurs while performing the sort.
*/
- public static EntryIDSet sort(SuffixContainer suffixContainer,
+ public static EntryIDSet sort(EntryContainer suffixContainer,
EntryIDSet entryIDSet,
SearchOperation searchOperation,
SortOrder sortOrder,
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EnvManager.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EnvManager.java
index 2df136f..caae758 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EnvManager.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/EnvManager.java
@@ -25,14 +25,16 @@
* Portions Copyright 2014 ForgeRock AS
*/
package org.opends.server.backends.pluggable;
-import org.forgerock.i18n.LocalizableMessage;
-
-import org.forgerock.i18n.slf4j.LocalizedLogger;
-import static org.opends.messages.JebMessages.*;
import java.io.File;
import java.io.FilenameFilter;
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.opends.server.backends.pluggable.BackendImpl.StorageRuntimeException;
+
+import static org.opends.messages.JebMessages.*;
+
/**
* A singleton class to manage the life-cycle of a JE database environment.
*/
@@ -40,10 +42,7 @@
{
private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
-
- /**
- * A filename filter to match all kinds of JE files.
- */
+ /** A filename filter to match all kinds of JE files. */
private static final FilenameFilter jeAllFilesFilter;
static
@@ -53,6 +52,7 @@
// here but is not public.
jeAllFilesFilter = new FilenameFilter()
{
+ @Override
public boolean accept(File d, String name)
{
return name.endsWith(".jdb") ||
@@ -68,10 +68,9 @@
* The environment must not be open.
*
* @param homeDir The backend home directory.
- * @throws JebException If an error occurs in the JE backend.
+ * @throws StorageRuntimeException If an error occurs in the JE backend.
*/
- public static void createHomeDir(String homeDir)
- throws JebException
+ public static void createHomeDir(String homeDir) throws StorageRuntimeException
{
File dir = new File(homeDir);
@@ -80,7 +79,7 @@
if (!dir.isDirectory())
{
LocalizableMessage message = ERR_JEB_DIRECTORY_INVALID.get(homeDir);
- throw new JebException(message);
+ throw new StorageRuntimeException(message.toString());
}
removeFiles(homeDir);
}
@@ -94,7 +93,7 @@
{
logger.traceException(e);
LocalizableMessage message = ERR_JEB_CREATE_FAIL.get(e.getMessage());
- throw new JebException(message, e);
+ throw new StorageRuntimeException(message.toString(), e);
}
}
}
@@ -104,22 +103,22 @@
* The environment must not be open.
*
* @param homeDir The backend home directory
- * @throws JebException If an error occurs in the JE backend or if the
- * specified home directory does not exist.
+ * @throws StorageRuntimeException
+ * If an error occurs in the JE backend or if the specified home
+ * directory does not exist.
*/
- public static void removeFiles(String homeDir)
- throws JebException
+ public static void removeFiles(String homeDir) throws StorageRuntimeException
{
File dir = new File(homeDir);
if (!dir.exists())
{
LocalizableMessage message = ERR_JEB_DIRECTORY_DOES_NOT_EXIST.get(homeDir);
- throw new JebException(message);
+ throw new StorageRuntimeException(message.toString());
}
if (!dir.isDirectory())
{
LocalizableMessage message = ERR_JEB_DIRECTORY_INVALID.get(homeDir);
- throw new JebException(message);
+ throw new StorageRuntimeException(message.toString());
}
try
@@ -134,7 +133,7 @@
{
logger.traceException(e);
LocalizableMessage message = ERR_JEB_REMOVE_FAIL.get(e.getMessage());
- throw new JebException(message, e);
+ throw new StorageRuntimeException(message.toString(), e);
}
}
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/ExportJob.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/ExportJob.java
index 739fb30..b7f03e3 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/ExportJob.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/ExportJob.java
@@ -88,12 +88,11 @@
* @param rootContainer The root container to export.
* @throws StorageRuntimeException If an error occurs in the JE database.
* @throws IOException If an I/O error occurs while writing an entry.
- * @throws JebException If an error occurs in the JE backend.
* @throws LDIFException If an error occurs while trying to determine whether
* to write an entry.
*/
public void exportLDIF(RootContainer rootContainer)
- throws IOException, LDIFException, StorageRuntimeException, JebException
+ throws IOException, LDIFException, StorageRuntimeException
{
List<DN> includeBranches = exportConfig.getIncludeBranches();
DN baseDN;
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/Index.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/Index.java
index 257ff78..f26d573 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/Index.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/Index.java
@@ -136,7 +136,7 @@
this.maintainCount = maintainCount;
this.state = state;
- this.trusted = state.getIndexTrustState(null, this);
+ this.trusted = state.getIndexTrustState(txn, this);
if (!trusted && entryContainer.getHighestEntryID(txn).longValue() == 0)
{
// If there are no entries in the entry container then there
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/IndexFilter.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/IndexFilter.java
index d192e15..40a28b3 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/IndexFilter.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/IndexFilter.java
@@ -33,7 +33,6 @@
import org.opends.server.backends.pluggable.AttributeIndex.IndexFilterType;
import org.opends.server.core.SearchOperation;
-import org.opends.server.monitors.DatabaseEnvironmentMonitor;
import org.opends.server.types.AttributeType;
import org.opends.server.types.FilterType;
import org.opends.server.types.SearchFilter;
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/JebException.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/JebException.java
deleted file mode 100644
index 1329cfa..0000000
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/JebException.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
- * or http://forgerock.org/license/CDDLv1.0.html.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at legal-notices/CDDLv1_0.txt.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information:
- * Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- * Copyright 2006-2009 Sun Microsystems, Inc.
- * Portions Copyright 2014 ForgeRock AS
- */
-package org.opends.server.backends.pluggable;
-
-
-
-import org.opends.server.types.IdentifiedException;
-import org.forgerock.i18n.LocalizableMessage;
-
-
-/**
- * This class defines an exception that may be thrown if a problem occurs in the
- * JE backend database.
- */
-public class JebException
- extends IdentifiedException
-{
- /**
- * The serial version identifier required to satisfy the compiler because this
- * class extends <CODE>java.lang.Exception</CODE>, which implements the
- * <CODE>java.io.Serializable</CODE> interface. This value was generated
- * using the <CODE>serialver</CODE> command-line utility included with the
- * Java SDK.
- */
- static final long serialVersionUID = 3110979454298870834L;
-
-
-
- /**
- * Creates a new JE backend exception.
- */
- public JebException()
- {
- super();
- }
-
-
-
- /**
- * Creates a new JE backend exception with the provided message.
- *
- * @param message The message that explains the problem that occurred.
- */
- public JebException(LocalizableMessage message)
- {
- super(message);
- }
-
-
-
- /**
- * Creates a new JE backend exception with the provided message and root
- * cause.
- *
- * @param message The message that explains the problem that occurred.
- * @param cause The exception that was caught to trigger this exception.
- */
- public JebException(LocalizableMessage message, Throwable cause)
- {
- super(message, cause);
- }
-
-
-
-}
-
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/NullIndex.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/NullIndex.java
index d4b5a13..fd13bb9 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/NullIndex.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/NullIndex.java
@@ -251,7 +251,7 @@
/** {@inheritDoc} */
@Override
- public long getRecordCount() throws StorageRuntimeException
+ public long getRecordCount(ReadableStorage txn) throws StorageRuntimeException
{
return 0;
}
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/RootContainer.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/RootContainer.java
index efc4b12..804c101 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/RootContainer.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/RootContainer.java
@@ -34,16 +34,19 @@
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.config.server.ConfigException;
-import org.forgerock.opendj.ldap.ResultCode;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.server.LocalDBBackendCfg;
import org.opends.server.api.Backend;
-import org.opends.server.backends.pluggable.BackendImpl.Storage;
+import org.opends.server.api.CompressedSchema;
+import org.opends.server.backends.persistit.PersistItStorage;
+import org.opends.server.backends.pluggable.BackendImpl.ReadOperation;
+import org.opends.server.backends.pluggable.BackendImpl.ReadableStorage;
import org.opends.server.backends.pluggable.BackendImpl.StorageRuntimeException;
+import org.opends.server.backends.pluggable.BackendImpl.TreeName;
import org.opends.server.backends.pluggable.BackendImpl.WriteOperation;
import org.opends.server.backends.pluggable.BackendImpl.WriteableStorage;
+import org.opends.server.core.DefaultCompressedSchema;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.monitors.DatabaseEnvironmentMonitor;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
import org.opends.server.types.FilePermission;
@@ -64,10 +67,7 @@
private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
/** The JE database environment. */
- private Storage storage;
-
- /** Used to force a checkpoint during import. */
- private final CheckpointConfig importForceCheckPoint = new CheckpointConfig();
+ private PersistItStorage storage; // FIXME JNR do not hardcode here
/** The backend configuration. */
private LocalDBBackendCfg config;
@@ -84,8 +84,9 @@
/** The cached value of the next entry identifier to be assigned. */
private AtomicLong nextid = new AtomicLong(1);
+ // FIXME JNR Switch back to a database persisted implementation of CompressedSchema
/** The compressed schema manager for this backend. */
- private JECompressedSchema compressedSchema;
+ private CompressedSchema compressedSchema;
@@ -106,13 +107,16 @@
getMonitorProvider().setMaxEntries(config.getIndexFilterAnalyzerMaxFilters());
config.addLocalDBChangeListener(this);
- importForceCheckPoint.setForce(true);
+ }
+
+ PersistItStorage getStorage()
+ {
+ return storage;
}
/**
* Opens the root container using the JE configuration object provided.
*
- * @param envConfig The JE environment configuration.
* @throws StorageRuntimeException If a database error occurs when creating
* the environment.
* @throws InitializationException If an initialization error occurs while
@@ -120,7 +124,7 @@
* @throws ConfigException If an configuration error occurs while
* creating the environment.
*/
- public void open(EnvironmentConfig envConfig)
+ public void open()
throws StorageRuntimeException, InitializationException, ConfigException
{
// Determine the backend database directory.
@@ -183,39 +187,26 @@
}
// Open the database environment
- storage = new Storage(backendDirectory, envConfig);
+ storage = new PersistItStorage(backendDirectory, this.config);
- if (logger.isTraceEnabled())
+ compressedSchema = new DefaultCompressedSchema();
+ try
{
- logger.trace("JE (%s) environment opened with the following config: %n%s",
- JEVersion.CURRENT_VERSION, storage.getConfig());
-
- // Get current size of heap in bytes
- long heapSize = Runtime.getRuntime().totalMemory();
-
- // Get maximum size of heap in bytes. The heap cannot grow beyond this size.
- // Any attempt will result in an OutOfMemoryException.
- long heapMaxSize = Runtime.getRuntime().maxMemory();
-
- // Get amount of free memory within the heap in bytes. This size will increase
- // after garbage collection and decrease as new objects are created.
- long heapFreeSize = Runtime.getRuntime().freeMemory();
-
- logger.trace("Current size of heap: %d bytes", heapSize);
- logger.trace("Max size of heap: %d bytes", heapMaxSize);
- logger.trace("Free memory in heap: %d bytes", heapFreeSize);
- }
-
- compressedSchema = new JECompressedSchema(storage);
-
- storage.write(new WriteOperation()
- {
- @Override
- public void run(WriteableStorage txn) throws Exception
+ storage.initialize(null);
+ storage.open();
+ storage.write(new WriteOperation()
{
- openAndRegisterEntryContainers(txn, config.getBaseDN());
- }
- });
+ @Override
+ public void run(WriteableStorage txn) throws Exception
+ {
+ openAndRegisterEntryContainers(txn, config.getBaseDN());
+ }
+ });
+ }
+ catch (Exception e)
+ {
+ throw new StorageRuntimeException(e);
+ }
}
/**
@@ -248,13 +239,26 @@
databasePrefix = name;
}
- EntryContainer ec = new EntryContainer(baseDN, databasePrefix,
+ EntryContainer ec = new EntryContainer(baseDN, toSuffixName(databasePrefix),
backend, config, storage, this);
ec.open(txn);
return ec;
}
/**
+ * Transform a database prefix string to one usable by the DB.
+ *
+ * @param databasePrefix
+ * the database prefix
+ * @return a new string when non letter or digit characters have been replaced
+ * with underscore
+ */
+ private TreeName toSuffixName(String databasePrefix)
+ {
+ return TreeName.of(storage.toSuffixName(databasePrefix));
+ }
+
+ /**
* Registers the entry container for a base DN.
*
* @param baseDN The base DN of the entry container to close.
@@ -325,7 +329,7 @@
*
* @return The compressed schema manager for this backend.
*/
- public JECompressedSchema getCompressedSchema()
+ public CompressedSchema getCompressedSchema()
{
return compressedSchema;
}
@@ -537,35 +541,6 @@
}
/**
- * Get the environment transaction stats of the JE environment used
- * in this root container.
- *
- * @param statsConfig The configuration to use for the EnvironmentStats
- * object.
- * @return The environment status of the JE environment.
- * @throws StorageRuntimeException If an error occurs while retrieving the stats
- * object.
- */
- public TransactionStats getEnvironmentTransactionStats(
- StatsConfig statsConfig) throws StorageRuntimeException
- {
- return storage.getTransactionStats(statsConfig);
- }
-
- /**
- * Get the environment config of the JE environment used in this root
- * container.
- *
- * @return The environment config of the JE environment.
- * @throws StorageRuntimeException If an error occurs while retrieving the
- * configuration object.
- */
- public EnvironmentConfig getEnvironmentConfig() throws StorageRuntimeException
- {
- return storage.getConfig();
- }
-
- /**
* Get the backend configuration used by this root container.
*
* @return The JE backend configuration used by this root container.
@@ -584,21 +559,34 @@
*/
public long getEntryCount() throws StorageRuntimeException
{
- long entryCount = 0;
- for(EntryContainer ec : this.entryContainers.values())
+ try
{
- ec.sharedLock.lock();
- try
+ return storage.read(new ReadOperation<Long>()
{
- entryCount += ec.getEntryCount();
- }
- finally
- {
- ec.sharedLock.unlock();
- }
+ @Override
+ public Long run(ReadableStorage txn) throws Exception
+ {
+ long entryCount = 0;
+ for (EntryContainer ec : entryContainers.values())
+ {
+ ec.sharedLock.lock();
+ try
+ {
+ entryCount += ec.getEntryCount(txn);
+ }
+ finally
+ {
+ ec.sharedLock.unlock();
+ }
+ }
+ return entryCount;
+ }
+ });
}
-
- return entryCount;
+ catch (Exception e)
+ {
+ throw new StorageRuntimeException(e);
+ }
}
/**
@@ -705,81 +693,10 @@
@Override
public ConfigChangeResult applyConfigurationChange(LocalDBBackendCfg cfg)
{
- boolean adminActionRequired = false;
- ArrayList<LocalizableMessage> messages = new ArrayList<LocalizableMessage>();
+ final ConfigChangeResult ccr = new ConfigChangeResult();
try
{
- if(storage != null)
- {
- // Check if any JE non-mutable properties were changed.
- EnvironmentConfig oldEnvConfig = storage.getConfig();
- EnvironmentConfig newEnvConfig =
- ConfigurableEnvironment.parseConfigEntry(cfg);
- Map<?,?> paramsMap = EnvironmentParams.SUPPORTED_PARAMS;
-
- // Iterate through native JE properties.
- SortedSet<String> jeProperties = cfg.getJEProperty();
- for (String jeEntry : jeProperties) {
- // There is no need to validate properties yet again.
- StringTokenizer st = new StringTokenizer(jeEntry, "=");
- if (st.countTokens() == 2) {
- String jePropertyName = st.nextToken();
- String jePropertyValue = st.nextToken();
- ConfigParam param = (ConfigParam) paramsMap.get(jePropertyName);
- if (!param.isMutable()) {
- String oldValue = oldEnvConfig.getConfigParam(param.getName());
- if (!oldValue.equalsIgnoreCase(jePropertyValue)) {
- adminActionRequired = true;
- messages.add(INFO_CONFIG_JE_PROPERTY_REQUIRES_RESTART.get(jePropertyName));
- if(logger.isTraceEnabled()) {
- logger.trace("The change to the following property " +
- "will take effect when the component is restarted: " +
- jePropertyName);
- }
- }
- }
- }
- }
-
- // Iterate through JE configuration attributes.
- for (Object o : paramsMap.values())
- {
- ConfigParam param = (ConfigParam) o;
- if (!param.isMutable())
- {
- String oldValue = oldEnvConfig.getConfigParam(param.getName());
- String newValue = newEnvConfig.getConfigParam(param.getName());
- if (!oldValue.equalsIgnoreCase(newValue))
- {
- adminActionRequired = true;
- String configAttr = ConfigurableEnvironment.
- getAttributeForProperty(param.getName());
- if (configAttr != null)
- {
- messages.add(NOTE_JEB_CONFIG_ATTR_REQUIRES_RESTART.get(configAttr));
- }
- else
- {
- messages.add(NOTE_JEB_CONFIG_ATTR_REQUIRES_RESTART.get(param.getName()));
- }
- if(logger.isTraceEnabled())
- {
- logger.trace("The change to the following property will " +
- "take effect when the backend is restarted: " +
- param.getName());
- }
- }
- }
- }
-
- // This takes care of changes to the JE environment for those
- // properties that are mutable at runtime.
- storage.setMutableConfig(newEnvConfig);
-
- logger.trace("JE database configuration: %s", storage.getConfig());
- }
-
// Create the directory if it doesn't exist.
if(!cfg.getDBDirectory().equals(this.config.getDBDirectory()))
{
@@ -791,31 +708,25 @@
{
if(!backendDirectory.mkdirs())
{
- messages.add(ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath()));
- return new ConfigChangeResult(
- DirectoryServer.getServerErrorResultCode(),
- adminActionRequired,
- messages);
+ ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+ ccr.addMessage(ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath()));
+ return ccr;
}
}
//Make sure the directory is valid.
else if (!backendDirectory.isDirectory())
{
- messages.add(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath()));
- return new ConfigChangeResult(
- DirectoryServer.getServerErrorResultCode(),
- adminActionRequired,
- messages);
+ ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+ ccr.addMessage(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath()));
+ return ccr;
}
- adminActionRequired = true;
- messages.add(NOTE_JEB_CONFIG_DB_DIR_REQUIRES_RESTART.get(
- this.config.getDBDirectory(), cfg.getDBDirectory()));
+ ccr.setAdminActionRequired(true);
+ ccr.addMessage(NOTE_JEB_CONFIG_DB_DIR_REQUIRES_RESTART.get(this.config.getDBDirectory(), cfg.getDBDirectory()));
}
- if(!cfg.getDBDirectoryPermissions().equalsIgnoreCase(
- config.getDBDirectoryPermissions()) ||
- !cfg.getDBDirectory().equals(this.config.getDBDirectory()))
+ if (!cfg.getDBDirectoryPermissions().equalsIgnoreCase(config.getDBDirectoryPermissions())
+ || !cfg.getDBDirectory().equals(this.config.getDBDirectory()))
{
FilePermission backendPermission;
try
@@ -825,25 +736,19 @@
}
catch(Exception e)
{
- messages.add(ERR_CONFIG_BACKEND_MODE_INVALID.get(config.dn()));
- return new ConfigChangeResult(
- DirectoryServer.getServerErrorResultCode(),
- adminActionRequired,
- messages);
+ ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+ ccr.addMessage(ERR_CONFIG_BACKEND_MODE_INVALID.get(config.dn()));
+ return ccr;
}
- //Make sure the mode will allow the server itself access to
- //the database
+ // Make sure the mode will allow the server itself access to the database
if(!backendPermission.isOwnerWritable() ||
!backendPermission.isOwnerReadable() ||
!backendPermission.isOwnerExecutable())
{
- messages.add(ERR_CONFIG_BACKEND_INSANE_MODE.get(
- cfg.getDBDirectoryPermissions()));
- return new ConfigChangeResult(
- DirectoryServer.getServerErrorResultCode(),
- adminActionRequired,
- messages);
+ ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+ ccr.addMessage(ERR_CONFIG_BACKEND_INSANE_MODE.get(cfg.getDBDirectoryPermissions()));
+ return ccr;
}
// Get the backend database backendDirectory permissions and apply
@@ -866,22 +771,18 @@
}
}
- getMonitorProvider().enableFilterUseStats(
- cfg.isIndexFilterAnalyzerEnabled());
- getMonitorProvider()
- .setMaxEntries(cfg.getIndexFilterAnalyzerMaxFilters());
+ getMonitorProvider().enableFilterUseStats(cfg.isIndexFilterAnalyzerEnabled());
+ getMonitorProvider().setMaxEntries(cfg.getIndexFilterAnalyzerMaxFilters());
this.config = cfg;
}
catch (Exception e)
{
- messages.add(LocalizableMessage.raw(stackTraceToSingleLineString(e)));
- return new ConfigChangeResult(DirectoryServer.getServerErrorResultCode(),
- adminActionRequired,
- messages);
+ ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+ ccr.addMessage(LocalizableMessage.raw(stackTraceToSingleLineString(e)));
+ return ccr;
}
-
- return new ConfigChangeResult(ResultCode.SUCCESS, adminActionRequired, messages);
+ return ccr;
}
/**
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/SortValuesSet.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/SortValuesSet.java
index 64d3009..30c55a8 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/SortValuesSet.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/SortValuesSet.java
@@ -99,9 +99,9 @@
* @param sv The sort values to add.
* @param types The types of the values to add.
* @throws DirectoryException If a Directory Server error occurs.
- * @throws DatabaseException If an error occurs in the JE database.
+ * @throws StorageRuntimeException If an error occurs in the JE database.
*/
- void add(SortValues sv) throws DirectoryException
+ void add(SortValues sv) throws StorageRuntimeException, DirectoryException
{
add(sv.getEntryID(), sv.getValues(), sv.getTypes());
}
@@ -587,10 +587,8 @@
* @return The sort values object at the specified index.
* @throws DirectoryException If a Directory Server error occurs.
* @throws StorageRuntimeException If an error occurs in the JE database.
- * @throws JebException If an error occurs in the JE database.
- **/
- public SortValues getSortValues(int index)
- throws JebException, StorageRuntimeException, DirectoryException
+ */
+ public SortValues getSortValues(int index) throws StorageRuntimeException, DirectoryException
{
if(entryIDs == null || entryIDs.length == 0)
{
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/SuffixContainer.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/SuffixContainer.java
index 8103cf3..3e0a691 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/SuffixContainer.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/SuffixContainer.java
@@ -75,12 +75,4 @@
* @return the baseDN that this suffix container is responsible for
*/
DN getBaseDN();
-
- /**
- * Returns the number of entries stored in this suffix container.
- *
- * @return the number of entries stored in this suffix container, or -1 if the
- * count not be determined
- */
- long getEntryCount();
}
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VLVIndex.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VLVIndex.java
index 8325d22..daf6557 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VLVIndex.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VLVIndex.java
@@ -26,7 +26,6 @@
*/
package org.opends.server.backends.pluggable;
-import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -197,7 +196,7 @@
this.comparator = new VLVKeyComparator(orderingRules, ascending);
this.state = state;
- this.trusted = state.getIndexTrustState(null, this);
+ this.trusted = state.getIndexTrustState(txn, this);
if (!trusted && entryContainer.getHighestEntryID(txn).longValue() == 0)
{
// If there are no entries in the entry container then there
@@ -264,12 +263,10 @@
* @return True if the entry ID for the entry are added. False if
* the entry ID already exists.
* @throws StorageRuntimeException If an error occurs in the JE database.
- * @throws org.opends.server.types.DirectoryException If a Directory Server
- * error occurs.
- * @throws JebException If an error occurs in the JE backend.
+ * @throws DirectoryException If a Directory Server error occurs.
*/
public boolean addEntry(WriteableStorage txn, EntryID entryID, Entry entry)
- throws StorageRuntimeException, DirectoryException, JebException
+ throws StorageRuntimeException, DirectoryException
{
return shouldInclude(entry)
&& insertValues(txn, entryID.longValue(), entry);
@@ -470,13 +467,11 @@
* found.
* @throws StorageRuntimeException If an error occurs during an operation on a
* JE database.
- * @throws JebException If an error occurs during an operation on a
- * JE database.
* @throws DirectoryException If a Directory Server error occurs.
*/
public boolean containsValues(ReadableStorage txn, long entryID,
- ByteString[] values, AttributeType[] types) throws JebException,
- StorageRuntimeException, DirectoryException
+ ByteString[] values, AttributeType[] types)
+ throws StorageRuntimeException, DirectoryException
{
SortValuesSet valuesSet = getSortValuesSet(txn, entryID, values, types);
int pos = valuesSet.binarySearch(entryID, values);
@@ -484,7 +479,7 @@
}
private boolean insertValues(WriteableStorage txn, long entryID, Entry entry)
- throws JebException, StorageRuntimeException, DirectoryException
+ throws StorageRuntimeException, DirectoryException
{
ByteString[] values = getSortValues(entry);
AttributeType[] types = getSortTypes();
@@ -545,19 +540,6 @@
return types;
}
- private boolean getSearchKeyRange(ReadableStorage txn, ByteString key)
- {
- Cursor cursor = txn.openCursor(treeName);
- try
- {
- return cursor.positionToKeyOrNext(key);
- }
- finally
- {
- cursor.close();
- }
- }
-
/**
* Update the vlvIndex with the specified values to add and delete.
*
@@ -1279,25 +1261,42 @@
/** {@inheritDoc} */
@Override
- public synchronized ConfigChangeResult applyConfigurationChange(
- LocalDBVLVIndexCfg cfg)
+ public synchronized ConfigChangeResult applyConfigurationChange(final LocalDBVLVIndexCfg cfg)
{
- ResultCode resultCode = ResultCode.SUCCESS;
- boolean adminActionRequired = false;
- ArrayList<LocalizableMessage> messages = new ArrayList<LocalizableMessage>();
+ try
+ {
+ final ConfigChangeResult ccr = new ConfigChangeResult();
+ storage.write(new WriteOperation()
+ {
+ @Override
+ public void run(WriteableStorage txn) throws Exception
+ {
+ applyConfigurationChange0(txn, cfg, ccr);
+ }
+ });
+ return ccr;
+ }
+ catch (Exception e)
+ {
+ throw new StorageRuntimeException(e);
+ }
+ }
+ private synchronized void applyConfigurationChange0(WriteableStorage txn, LocalDBVLVIndexCfg cfg,
+ ConfigChangeResult ccr)
+ {
// Update base DN only if changed..
if(!config.getBaseDN().equals(cfg.getBaseDN()))
{
this.baseDN = cfg.getBaseDN();
- adminActionRequired = true;
+ ccr.setAdminActionRequired(true);
}
// Update scope only if changed.
if(!config.getScope().equals(cfg.getScope()))
{
this.scope = SearchScope.valueOf(cfg.getScope().name());
- adminActionRequired = true;
+ ccr.setAdminActionRequired(true);
}
// Update sort set capacity only if changed.
@@ -1309,7 +1308,7 @@
// Otherwise, we will lazily update the sorted sets.
if (config.getMaxBlockSize() < cfg.getMaxBlockSize())
{
- adminActionRequired = true;
+ ccr.setAdminActionRequired(true);
}
}
@@ -1319,18 +1318,13 @@
try
{
this.filter = SearchFilter.createFilterFromString(cfg.getFilter());
- adminActionRequired = true;
+ ccr.setAdminActionRequired(true);
}
catch(Exception e)
{
- LocalizableMessage msg = ERR_JEB_CONFIG_VLV_INDEX_BAD_FILTER.get(
- config.getFilter(), treeName,
- stackTraceToSingleLineString(e));
- messages.add(msg);
- if(resultCode == ResultCode.SUCCESS)
- {
- resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
- }
+ ccr.addMessage(ERR_JEB_CONFIG_VLV_INDEX_BAD_FILTER.get(
+ config.getFilter(), treeName, stackTraceToSingleLineString(e)));
+ ccr.setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
}
}
@@ -1361,22 +1355,16 @@
}
catch(Exception e)
{
- messages.add(ERR_JEB_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(sortKeys[i], treeName));
- if(resultCode == ResultCode.SUCCESS)
- {
- resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
- }
+ ccr.addMessage(ERR_JEB_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(sortKeys[i], treeName));
+ ccr.setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
}
AttributeType attrType =
DirectoryServer.getAttributeType(sortAttrs[i].toLowerCase());
if(attrType == null)
{
- messages.add(ERR_JEB_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(sortKeys[i], treeName));
- if(resultCode == ResultCode.SUCCESS)
- {
- resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
- }
+ ccr.addMessage(ERR_JEB_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(sortKeys[i], treeName));
+ ccr.setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
}
else
{
@@ -1392,22 +1380,15 @@
entryContainer.exclusiveLock.lock();
try
{
- storage.write(new WriteOperation()
- {
- @Override
- public void run(WriteableStorage txn) throws Exception
- {
- close();
- open(txn);
- }
- });
+ close();
+ open(txn);
}
- catch (Exception e)
+ catch (StorageRuntimeException de)
{
- messages.add(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(e)));
- if(resultCode == ResultCode.SUCCESS)
+ ccr.addMessage(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(de)));
+ if (ccr.getResultCode() == ResultCode.SUCCESS)
{
- resultCode = DirectoryServer.getServerErrorResultCode();
+ ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
}
}
finally
@@ -1415,29 +1396,28 @@
entryContainer.exclusiveLock.unlock();
}
- adminActionRequired = true;
+ ccr.setAdminActionRequired(true);
}
- if(adminActionRequired)
+ if (ccr.adminActionRequired())
{
trusted = false;
- messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(treeName));
+ ccr.addMessage(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(treeName));
try
{
state.putIndexTrustState(null, this, false);
}
catch(StorageRuntimeException de)
{
- messages.add(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(de)));
- if(resultCode == ResultCode.SUCCESS)
+ ccr.addMessage(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(de)));
+ if (ccr.getResultCode() == ResultCode.SUCCESS)
{
- resultCode = DirectoryServer.getServerErrorResultCode();
+ ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
}
}
}
this.config = cfg;
- return new ConfigChangeResult(resultCode, adminActionRequired, messages);
}
}
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VerifyJob.java b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VerifyJob.java
index 5b8ef1e..25bd6a1 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VerifyJob.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VerifyJob.java
@@ -51,7 +51,6 @@
import org.opends.server.backends.pluggable.BackendImpl.Cursor;
import org.opends.server.backends.pluggable.BackendImpl.ReadOperation;
import org.opends.server.backends.pluggable.BackendImpl.ReadableStorage;
-import org.opends.server.backends.pluggable.BackendImpl.Storage;
import org.opends.server.backends.pluggable.BackendImpl.StorageRuntimeException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.Attribute;
@@ -146,16 +145,14 @@
* @param statEntry Optional statistics entry.
* @return The error count.
* @throws StorageRuntimeException If an error occurs in the JE database.
- * @throws JebException If an error occurs in the JE backend.
* @throws DirectoryException If an error occurs while verifying the backend.
*/
public long verifyBackend(final RootContainer rootContainer, final Entry statEntry) throws StorageRuntimeException,
- JebException, DirectoryException
+ DirectoryException
{
- Storage s;
try
{
- return s.read(new ReadOperation<Long>()
+ return rootContainer.getStorage().read(new ReadOperation<Long>()
{
@Override
public Long run(ReadableStorage txn) throws Exception
@@ -171,7 +168,7 @@
}
private long verifyBackend0(ReadableStorage txn, RootContainer rootContainer, Entry statEntry)
- throws StorageRuntimeException, JebException, DirectoryException
+ throws StorageRuntimeException, DirectoryException
{
this.rootContainer = rootContainer;
EntryContainer entryContainer =
@@ -224,7 +221,7 @@
{
LocalizableMessage msg = NOTE_JEB_SUBORDINATE_INDEXES_DISABLED
.get(rootContainer.getConfiguration().getBackendId());
- throw new JebException(msg);
+ throw new StorageRuntimeException(msg.toString());
}
}
else if ("id2subtree".equals(lowerName))
@@ -237,7 +234,7 @@
{
LocalizableMessage msg = NOTE_JEB_SUBORDINATE_INDEXES_DISABLED
.get(rootContainer.getConfiguration().getBackendId());
- throw new JebException(msg);
+ throw new StorageRuntimeException(msg.toString());
}
}
else if(lowerName.startsWith("vlv."))
@@ -245,7 +242,7 @@
if(lowerName.length() < 5)
{
LocalizableMessage msg = ERR_JEB_VLV_INDEX_NOT_CONFIGURED.get(lowerName);
- throw new JebException(msg);
+ throw new StorageRuntimeException(msg.toString());
}
VLVIndex vlvIndex =
@@ -254,35 +251,31 @@
{
LocalizableMessage msg =
ERR_JEB_VLV_INDEX_NOT_CONFIGURED.get(lowerName.substring(4));
- throw new JebException(msg);
+ throw new StorageRuntimeException(msg.toString());
}
vlvIndexList.add(vlvIndex);
}
else
{
- AttributeType attrType =
- DirectoryServer.getAttributeType(lowerName);
+ AttributeType attrType = DirectoryServer.getAttributeType(lowerName);
if (attrType == null)
{
LocalizableMessage msg = ERR_JEB_ATTRIBUTE_INDEX_NOT_CONFIGURED.get(index);
- throw new JebException(msg);
+ throw new StorageRuntimeException(msg.toString());
}
- AttributeIndex attrIndex =
- entryContainer.getAttributeIndex(attrType);
+ AttributeIndex attrIndex = entryContainer.getAttributeIndex(attrType);
if (attrIndex == null)
{
LocalizableMessage msg = ERR_JEB_ATTRIBUTE_INDEX_NOT_CONFIGURED.get(index);
- throw new JebException(msg);
+ throw new StorageRuntimeException(msg.toString());
}
attrIndexList.add(attrIndex);
}
}
}
- entryLimitMap =
- new IdentityHashMap<Index,HashMap<ByteString,Long>>(
- attrIndexList.size());
+ entryLimitMap = new IdentityHashMap<Index, HashMap<ByteString, Long>>(attrIndexList.size());
// We will be updating these files independently of the indexes
// so we need direct access to them rather than going through
@@ -421,7 +414,7 @@
Cursor cursor = id2entry.openCursor(txn);
try
{
- long storedEntryCount = id2entry.getRecordCount();
+ long storedEntryCount = id2entry.getRecordCount(txn);
while (cursor.next())
{
ByteString key = cursor.getKey();
@@ -487,12 +480,10 @@
* index cleanliness. For each ID in the index we check that the
* entry it refers to does indeed contain the expected value.
*
- * @throws JebException If an error occurs in the JE backend.
* @throws StorageRuntimeException If an error occurs in the JE database.
* @throws DirectoryException If an error occurs reading values in the index.
*/
- private void iterateIndex(ReadableStorage txn)
- throws JebException, StorageRuntimeException, DirectoryException
+ private void iterateIndex(ReadableStorage txn) throws StorageRuntimeException, DirectoryException
{
if (verifyDN2ID)
{
@@ -598,10 +589,9 @@
* Iterate through the entries in ID2Children to perform a check for
* index cleanliness.
*
- * @throws JebException If an error occurs in the JE backend.
* @throws StorageRuntimeException If an error occurs in the JE database.
*/
- private void iterateID2Children(ReadableStorage txn) throws JebException, StorageRuntimeException
+ private void iterateID2Children(ReadableStorage txn) throws StorageRuntimeException
{
Cursor cursor = id2c.openCursor(txn);
try
@@ -727,10 +717,9 @@
* Iterate through the entries in ID2Subtree to perform a check for
* index cleanliness.
*
- * @throws JebException If an error occurs in the JE backend.
* @throws StorageRuntimeException If an error occurs in the JE database.
*/
- private void iterateID2Subtree(ReadableStorage txn) throws JebException, StorageRuntimeException
+ private void iterateID2Subtree(ReadableStorage txn) throws StorageRuntimeException
{
Cursor cursor = id2s.openCursor(txn);
try
@@ -906,12 +895,11 @@
*
* @param vlvIndex The VLV index to perform the check against.
* @param verifyID True to verify the IDs against id2entry.
- * @throws JebException If an error occurs in the JE backend.
* @throws StorageRuntimeException If an error occurs in the JE database.
* @throws DirectoryException If an error occurs reading values in the index.
*/
private void iterateVLVIndex(ReadableStorage txn, VLVIndex vlvIndex, boolean verifyID)
- throws JebException, StorageRuntimeException, DirectoryException
+ throws StorageRuntimeException, DirectoryException
{
if(vlvIndex == null)
{
@@ -1012,11 +1000,10 @@
* Iterate through the entries in an attribute index to perform a check for
* index cleanliness.
* @param index The index database to be checked.
- * @throws JebException If an error occurs in the JE backend.
* @throws StorageRuntimeException If an error occurs in the JE database.
*/
private void iterateAttrIndex(ReadableStorage txn, Index index, IndexingOptions options)
- throws JebException, StorageRuntimeException
+ throws StorageRuntimeException
{
if (index == null)
{
@@ -1487,16 +1474,6 @@
}
errorCount++;
}
- catch (JebException e)
- {
- if (logger.isTraceEnabled())
- {
- logger.traceException(e);
- logger.trace("Error reading VLV index %s for entry %s: %s",
- vlvIndex.getName(), entry.getName(), StaticUtils.getBacktrace(e));
- }
- errorCount++;
- }
}
}
--
Gitblit v1.10.0