From f8ef0eed366445c5a341dbcc7882a7104c1cac1b Mon Sep 17 00:00:00 2001
From: boli <boli@localhost>
Date: Thu, 26 Jul 2007 16:31:34 +0000
Subject: [PATCH] This fixes issue 1971 and allows partial non-append imports of a backend:
---
opends/src/server/org/opends/server/backends/jeb/EntryContainer.java | 658 ++++++++++++++++++++++++++++++++++++++---------------------
1 files changed, 419 insertions(+), 239 deletions(-)
diff --git a/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java b/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
index 207e6b7..69fb221 100644
--- a/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
+++ b/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
@@ -186,6 +186,7 @@
private int indexEntryLimit;
+ private String databasePrefix;
/**
* A read write lock to handle schema changes and bulk changes.
*/
@@ -198,6 +199,8 @@
*
* @param baseDN The baseDN this entry container will be responsible for
* storing on disk.
+ * @param databasePrefix The prefix to use in the database names used by
+ * this entry container.
* @param backend A reference to the JE backend that is creating this entry
* container. It is needed by the Directory Server entry cache
* methods.
@@ -206,8 +209,9 @@
* @param rootContainer The root container this entry container is in.
* @throws ConfigException if a configuration related error occurs.
*/
- public EntryContainer(DN baseDN, Backend backend, JEBackendCfg config,
- Environment env, RootContainer rootContainer)
+ public EntryContainer(DN baseDN, String databasePrefix, Backend backend,
+ JEBackendCfg config, Environment env,
+ RootContainer rootContainer)
throws ConfigException
{
this.backend = backend;
@@ -215,6 +219,22 @@
this.config = config;
this.env = env;
this.rootContainer = rootContainer;
+
+ 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('_');
+ }
+ }
+ this.databasePrefix = builder.toString();
+
this.deadlockRetryLimit = config.getBackendDeadlockRetryLimit();
this.subtreeDeleteSizeLimit = config.getBackendSubtreeDeleteSizeLimit();
this.subtreeDeleteBatchSize = config.getBackendSubtreeDeleteBatchSize();
@@ -242,28 +262,29 @@
DataConfig entryDataConfig = new DataConfig();
entryDataConfig.setCompressed(config.isBackendEntriesCompressed());
- id2entry = new ID2Entry(ID2ENTRY_DATABASE_NAME, entryDataConfig,
- env, this);
+ id2entry = new ID2Entry(databasePrefix + "_" + ID2ENTRY_DATABASE_NAME,
+ entryDataConfig, env, this);
id2entry.open();
- dn2id = new DN2ID(DN2ID_DATABASE_NAME, env, this);
+ dn2id = new DN2ID(databasePrefix + "_" + DN2ID_DATABASE_NAME, env, this);
dn2id.open();
- state = new State(STATE_DATABASE_NAME, env, this);
+ state = new State(databasePrefix + "_" + STATE_DATABASE_NAME, env, this);
state.open();
- id2children = new Index(ID2CHILDREN_DATABASE_NAME,
+ id2children = new Index(databasePrefix + "_" + ID2CHILDREN_DATABASE_NAME,
new ID2CIndexer(), state,
indexEntryLimit, 0,
env,this);
id2children.open();
- id2subtree = new Index(ID2SUBTREE_DATABASE_NAME,
+ id2subtree = new Index(databasePrefix + "_" + ID2SUBTREE_DATABASE_NAME,
new ID2SIndexer(), state,
indexEntryLimit, 0,
env, this);
id2subtree.open();
- dn2uri = new DN2URI(REFERRAL_DATABASE_NAME, env, this);
+ dn2uri = new DN2URI(databasePrefix + "_" + REFERRAL_DATABASE_NAME,
+ env, this);
dn2uri.open();
for (String idx : config.listJEIndexes())
@@ -297,86 +318,11 @@
public void close()
throws DatabaseException
{
- try
+ List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>();
+ listDatabases(databases);
+ for(DatabaseContainer db : databases)
{
- dn2id.close();
- }
- catch (DatabaseNotFoundException e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
- try
- {
- id2entry.close();
- }
- catch (DatabaseNotFoundException e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
- try
- {
- id2children.close();
- }
- catch (DatabaseNotFoundException e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
- try
- {
- id2subtree.close();
- }
- catch (DatabaseNotFoundException e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
- try
- {
- state.close();
- }
- catch (DatabaseNotFoundException e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
- try
- {
- dn2uri.close();
- }
- catch (DatabaseNotFoundException e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
-
- for (AttributeIndex index : attrIndexMap.values())
- {
- try
- {
- index.close();
- }
- catch (DatabaseNotFoundException e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
+ db.close();
}
config.removeJEChangeListener(this);
@@ -3438,86 +3384,6 @@
}
/**
- * Remove the entry entryContainer from disk. The entryContainer must not be
- * open.
- *
- * @throws DatabaseException If an error occurs in the JE database.
- */
- public void removeContainer() throws DatabaseException
- {
- try
- {
- removeDatabase(dn2id);
- }
- catch (DatabaseNotFoundException e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
- try
- {
- removeDatabase(id2entry);
- }
- catch (DatabaseNotFoundException e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
- try
- {
- removeDatabase(id2children);
- }
- catch (DatabaseNotFoundException e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
- try
- {
- removeDatabase(id2subtree);
- }
- catch (DatabaseNotFoundException e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
- try
- {
- removeDatabase(state);
- }
- catch (DatabaseNotFoundException e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
- for (AttributeIndex index : attrIndexMap.values())
- {
- try
- {
- removeAttributeIndex(index);
- }
- catch (DatabaseNotFoundException e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
- }
- attrIndexMap.clear();
- }
-
- /**
* Get the number of values for which the entry limit has been exceeded
* since the entry entryContainer was opened.
* @return The number of values for which the entry limit has been exceeded.
@@ -3545,6 +3411,7 @@
dbList.add(dn2uri);
dbList.add(id2children);
dbList.add(id2subtree);
+ dbList.add(state);
for(AttributeIndex index : attrIndexMap.values())
{
@@ -3579,19 +3446,6 @@
}
/**
- * Constructs a full JE database name incorporating a entryContainer name.
- *
- * @param builder A string builder to which the full name will be appended.
- * @param name The short database name.
- */
- private void buildDatabaseName(StringBuilder builder, String name)
- {
- builder.append(getContainerName());
- builder.append('_');
- builder.append(name);
- }
-
- /**
* Begin a leaf transaction using the default configuration.
* Provides assertion debug logging.
* @return A JE transaction handle.
@@ -3652,20 +3506,92 @@
}
/**
+ * Delete this entry container from disk. The entry container should be
+ * closed before calling this method.
+ *
+ * @throws DatabaseException If an error occurs while removing the entry
+ * container.
+ */
+ public void delete() throws DatabaseException
+ {
+ List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>();
+ listDatabases(databases);
+
+ for(DatabaseContainer db : databases)
+ {
+ db.close();
+ }
+
+ if(env.getConfig().getTransactional())
+ {
+ Transaction txn = beginTransaction();
+
+ try
+ {
+ for(DatabaseContainer db : databases)
+ {
+ env.removeDatabase(txn, db.getName());
+ }
+
+ transactionCommit(txn);
+ }
+ catch(DatabaseException de)
+ {
+ transactionAbort(txn);
+ throw de;
+ }
+ }
+ else
+ {
+ for(DatabaseContainer db : databases)
+ {
+ env.removeDatabase(null, db.getName());
+ }
+ }
+ }
+
+ /**
* Remove a database from disk.
*
* @param database The database container to remove.
* @throws DatabaseException If an error occurs while attempting to delete the
* database.
*/
- public void removeDatabase(DatabaseContainer database)
+ public void deleteDatabase(DatabaseContainer database)
throws DatabaseException
{
- database.close();
- env.removeDatabase(null, database.getName());
- if(database instanceof Index)
+ if(database == state)
{
- state.removeIndexTrustState(null, (Index)database);
+ // The state database can not be removed individually.
+ return;
+ }
+
+ database.close();
+ if(env.getConfig().getTransactional())
+ {
+ Transaction txn = beginTransaction();
+ try
+ {
+ env.removeDatabase(txn, database.getName());
+ if(database instanceof Index)
+ {
+ state.removeIndexTrustState(txn, (Index)database);
+ }
+ transactionCommit(txn);
+ }
+ catch(DatabaseException de)
+ {
+ transactionAbort(txn);
+ throw de;
+ }
+ }
+ else
+ {
+ env.removeDatabase(null, database.getName());
+ if(database instanceof Index)
+ {
+ state.removeIndexTrustState(null, (Index)database);
+ }
}
}
@@ -3676,34 +3602,75 @@
* @throws DatabaseException If an JE database error occurs while attempting
* to delete the index.
*/
- public void removeAttributeIndex(AttributeIndex index)
+ public void deleteAttributeIndex(AttributeIndex index)
throws DatabaseException
{
index.close();
- if(index.equalityIndex != null)
+ if(env.getConfig().getTransactional())
{
- env.removeDatabase(null, index.equalityIndex.getName());
- state.removeIndexTrustState(null, index.equalityIndex);
+ Transaction txn = beginTransaction();
+ try
+ {
+ if(index.equalityIndex != null)
+ {
+ env.removeDatabase(txn, index.equalityIndex.getName());
+ state.removeIndexTrustState(txn, index.equalityIndex);
+ }
+ if(index.presenceIndex != null)
+ {
+ env.removeDatabase(txn, index.presenceIndex.getName());
+ state.removeIndexTrustState(txn, index.presenceIndex);
+ }
+ if(index.substringIndex != null)
+ {
+ env.removeDatabase(txn, index.substringIndex.getName());
+ state.removeIndexTrustState(txn, index.substringIndex);
+ }
+ if(index.orderingIndex != null)
+ {
+ env.removeDatabase(txn, index.orderingIndex.getName());
+ state.removeIndexTrustState(txn, index.orderingIndex);
+ }
+ if(index.approximateIndex != null)
+ {
+ env.removeDatabase(txn, index.approximateIndex.getName());
+ state.removeIndexTrustState(txn, index.approximateIndex);
+ }
+ transactionCommit(txn);
+ }
+ catch(DatabaseException de)
+ {
+ transactionAbort(txn);
+ throw de;
+ }
}
- if(index.presenceIndex != null)
+ else
{
- env.removeDatabase(null, index.presenceIndex.getName());
- state.removeIndexTrustState(null, index.presenceIndex);
- }
- if(index.substringIndex != null)
- {
- env.removeDatabase(null, index.substringIndex.getName());
- state.removeIndexTrustState(null, index.substringIndex);
- }
- if(index.orderingIndex != null)
- {
- env.removeDatabase(null, index.orderingIndex.getName());
- state.removeIndexTrustState(null, index.orderingIndex);
- }
- if(index.approximateIndex != null)
- {
- env.removeDatabase(null, index.approximateIndex.getName());
- state.removeIndexTrustState(null, index.approximateIndex);
+ if(index.equalityIndex != null)
+ {
+ env.removeDatabase(null, index.equalityIndex.getName());
+ state.removeIndexTrustState(null, index.equalityIndex);
+ }
+ if(index.presenceIndex != null)
+ {
+ env.removeDatabase(null, index.presenceIndex.getName());
+ state.removeIndexTrustState(null, index.presenceIndex);
+ }
+ if(index.substringIndex != null)
+ {
+ env.removeDatabase(null, index.substringIndex.getName());
+ state.removeIndexTrustState(null, index.substringIndex);
+ }
+ if(index.orderingIndex != null)
+ {
+ env.removeDatabase(null, index.orderingIndex.getName());
+ state.removeIndexTrustState(null, index.orderingIndex);
+ }
+ if(index.approximateIndex != null)
+ {
+ env.removeDatabase(null, index.approximateIndex.getName());
+ state.removeIndexTrustState(null, index.approximateIndex);
+ }
}
}
@@ -3714,13 +3681,30 @@
*
* @return The container name for the base DN.
*/
- public String getContainerName()
+ public String getDatabasePrefix()
{
- String normStr = baseDN.toNormalizedString();
- StringBuilder builder = new StringBuilder(normStr.length());
- for (int i = 0; i < normStr.length(); i++)
+ return databasePrefix;
+ }
+
+ /**
+ * Sets a new database prefix for this entry container and rename all
+ * existing databases in use by this entry container.
+ *
+ * @param newDatabasePrefix The new database prefix to use.
+ * @throws DatabaseException If an error occurs in the JE database.
+ * @throws JebException If an error occurs in the JE backend.
+ */
+ public void setDatabasePrefix(String newDatabasePrefix)
+ throws DatabaseException, JebException
+
+ {
+ List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>();
+ listDatabases(databases);
+
+ StringBuilder builder = new StringBuilder(newDatabasePrefix.length());
+ for (int i = 0; i < newDatabasePrefix.length(); i++)
{
- char ch = normStr.charAt(i);
+ char ch = newDatabasePrefix.charAt(i);
if (Character.isLetterOrDigit(ch))
{
builder.append(ch);
@@ -3730,9 +3714,75 @@
builder.append('_');
}
}
- return builder.toString();
+ newDatabasePrefix = builder.toString();
+
+ // close the containers.
+ for(DatabaseContainer db : databases)
+ {
+ db.close();
+ }
+
+ try
+ {
+ if(env.getConfig().getTransactional())
+ {
+ //Rename under transaction
+ Transaction txn = beginTransaction();
+ try
+ {
+ for(DatabaseContainer db : databases)
+ {
+ String oldName = db.getName();
+ String newName = oldName.replace(databasePrefix, newDatabasePrefix);
+ env.renameDatabase(txn, oldName, newName);
+ }
+
+ transactionCommit(txn);
+
+ for(DatabaseContainer db : databases)
+ {
+ String oldName = db.getName();
+ String newName = oldName.replace(databasePrefix, newDatabasePrefix);
+ db.setName(newName);
+ }
+
+ // Update the prefix.
+ this.databasePrefix = newDatabasePrefix;
+ }
+ catch(Exception e)
+ {
+ transactionAbort(txn);
+
+ int messageID = MSGID_JEB_UNCHECKED_EXCEPTION;
+ String message = getMessage(messageID);
+ throw new JebException(messageID, message, e);
+ }
+ }
+ else
+ {
+ for(DatabaseContainer db : databases)
+ {
+ String oldName = db.getName();
+ String newName = oldName.replace(databasePrefix, newDatabasePrefix);
+ env.renameDatabase(null, oldName, newName);
+ db.setName(newName);
+ }
+
+ // Update the prefix.
+ this.databasePrefix = newDatabasePrefix;
+ }
+ }
+ finally
+ {
+ // Open the containers backup.
+ for(DatabaseContainer db : databases)
+ {
+ db.open();
+ }
+ }
}
+
/**
* Get the baseDN this entry container is responsible for.
*
@@ -3876,7 +3926,7 @@
try
{
AttributeIndex index = attrIndexMap.get(cfg.getIndexAttribute());
- removeAttributeIndex(index);
+ deleteAttributeIndex(index);
attrIndexMap.remove(cfg.getIndexAttribute());
}
catch(DatabaseException de)
@@ -3911,19 +3961,99 @@
}
/**
+ * Clear the contents of this entry container.
+ *
+ * @return The number of records deleted.
+ * @throws DatabaseException If an error occurs while removing the entry
+ * container.
+ */
+ public long clear() throws DatabaseException
+ {
+ List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>();
+ listDatabases(databases);
+ long count = 0;
+
+ for(DatabaseContainer db : databases)
+ {
+ db.close();
+ }
+ try
+ {
+ if(env.getConfig().getTransactional())
+ {
+ Transaction txn = beginTransaction();
+
+ try
+ {
+ for(DatabaseContainer db : databases)
+ {
+ count += env.truncateDatabase(txn, db.getName(), true);
+ }
+
+ transactionCommit(txn);
+ }
+ catch(DatabaseException de)
+ {
+ transactionAbort(txn);
+ throw de;
+ }
+ }
+ else
+ {
+ for(DatabaseContainer db : databases)
+ {
+ count += env.truncateDatabase(null, db.getName(), true);
+ }
+ }
+ }
+ finally
+ {
+ for(DatabaseContainer db : databases)
+ {
+ db.open();
+ }
+ }
+
+ return count;
+ }
+
+ /**
* Clear the contents for a database from disk.
*
- * @param txn A transaction object or null if its not required.
* @param database The database to clear.
* @return The number of records deleted.
* @throws DatabaseException if a JE database error occurs.
*/
- public long clearDatabase(Transaction txn, DatabaseContainer database)
+ public long clearDatabase(DatabaseContainer database)
throws DatabaseException
{
+ long count = 0;
database.close();
- long count = env.truncateDatabase(txn, database.getName(), true);
- database.open();
+ try
+ {
+ if(env.getConfig().getTransactional())
+ {
+ Transaction txn = beginTransaction();
+ try
+ {
+ count = env.truncateDatabase(txn, database.getName(), true);
+ transactionCommit(txn);
+ }
+ catch(DatabaseException de)
+ {
+ transactionAbort(txn);
+ throw de;
+ }
+ }
+ else
+ {
+ count = env.truncateDatabase(null, database.getName(), true);
+ }
+ }
+ finally
+ {
+ database.open();
+ }
if(debugEnabled())
{
TRACER.debugVerbose("Cleared %d existing records from the " +
@@ -3935,39 +4065,89 @@
/**
* Clear the contents for a attribute index from disk.
*
- * @param txn A transaction object or null if its not required.
* @param index The attribute index to clear.
* @return The number of records deleted.
* @throws DatabaseException if a JE database error occurs.
*/
- public long clearAttributeIndex(Transaction txn, AttributeIndex index)
+ public long clearAttributeIndex(AttributeIndex index)
throws DatabaseException
{
long count = 0;
index.close();
- if(index.equalityIndex != null)
+ try
{
- count += env.truncateDatabase(txn, index.equalityIndex.getName(), true);
+ if(env.getConfig().getTransactional())
+ {
+ Transaction txn = beginTransaction();
+ try
+ {
+ if(index.equalityIndex != null)
+ {
+ count += env.truncateDatabase(txn, index.equalityIndex.getName(),
+ true);
+ }
+ if(index.presenceIndex != null)
+ {
+ count += env.truncateDatabase(txn, index.presenceIndex.getName(),
+ true);
+ }
+ if(index.substringIndex != null)
+ {
+ count += env.truncateDatabase(txn, index.substringIndex.getName(),
+ true);
+ }
+ if(index.orderingIndex != null)
+ {
+ count += env.truncateDatabase(txn, index.orderingIndex.getName(),
+ true);
+ }
+ if(index.approximateIndex != null)
+ {
+ count += env.truncateDatabase(txn, index.approximateIndex.getName(),
+ true);
+ }
+ transactionCommit(txn);
+ }
+ catch(DatabaseException de)
+ {
+ transactionAbort(txn);
+ throw de;
+ }
+ }
+ else
+ {
+ if(index.equalityIndex != null)
+ {
+ count += env.truncateDatabase(null, index.equalityIndex.getName(),
+ true);
+ }
+ if(index.presenceIndex != null)
+ {
+ count += env.truncateDatabase(null, index.presenceIndex.getName(),
+ true);
+ }
+ if(index.substringIndex != null)
+ {
+ count += env.truncateDatabase(null, index.substringIndex.getName(),
+ true);
+ }
+ if(index.orderingIndex != null)
+ {
+ count += env.truncateDatabase(null, index.orderingIndex.getName(),
+ true);
+ }
+ if(index.approximateIndex != null)
+ {
+ count += env.truncateDatabase(null, index.approximateIndex.getName(),
+ true);
+ }
+ }
}
- if(index.presenceIndex != null)
+ finally
{
- count += env.truncateDatabase(txn, index.presenceIndex.getName(), true);
+ index.open();
}
- if(index.substringIndex != null)
- {
- count += env.truncateDatabase(txn, index.substringIndex.getName(), true);
- }
- if(index.orderingIndex != null)
- {
- count += env.truncateDatabase(txn, index.orderingIndex.getName(), true);
- }
- if(index.approximateIndex != null)
- {
- count += env.truncateDatabase(txn, index.approximateIndex.getName(),
- true);
- }
- index.open();
if(debugEnabled())
{
TRACER.debugVerbose("Cleared %d existing records from the " +
--
Gitblit v1.10.0