From 59a0e0cae4a717d92ccf08aa56d427015498becf Mon Sep 17 00:00:00 2001
From: pgamba <pgamba@localhost>
Date: Fri, 07 Sep 2007 08:57:27 +0000
Subject: [PATCH]
---
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java | 4
opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServer.java | 242 +++++++++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java | 193 +++++++
opendj-sdk/opends/src/messages/messages/replication.properties | 9
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationServerListener.java | 5
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/InitOnLineTest.java | 162 ------
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplicationServerTest.java | 64 ++
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java | 17
opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerReader.java | 43 -
opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java | 493 +++++++++++++++++++
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java | 29
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/GenerationIdTest.java | 188 -------
12 files changed, 1,016 insertions(+), 433 deletions(-)
diff --git a/opendj-sdk/opends/src/messages/messages/replication.properties b/opendj-sdk/opends/src/messages/messages/replication.properties
index b319e0d..2b6cbbf 100644
--- a/opendj-sdk/opends/src/messages/messages/replication.properties
+++ b/opendj-sdk/opends/src/messages/messages/replication.properties
@@ -80,7 +80,7 @@
changes that this server has already processed on suffix %s
NOTICE_NEED_MORE_THAN_ONE_CHANGELOG_SERVER_19=More than one replication \
server should be configured
-NOTICE_EXCEPTION_STARTING_SESSION_20=Caught Exception during initial \
+SEVERE_ERR_EXCEPTION_STARTING_SESSION_20=Caught Exception during initial \
communication on domain %s with replication server %s : %s
MILD_ERR_CANNOT_RECOVER_CHANGES_21=Error when searching old changes from the \
database for base DN %s
@@ -224,4 +224,9 @@
SEVERE_ERR_ERROR_CLEARING_DB_87=While clearing the database %s , the following \
error happened: %s
NOTICE_ERR_ROUTING_TO_SERVER_88=Protocol error : a replication server is not expected \
- to be the destination of a message of type %s
\ No newline at end of file
+ to be the destination of a message of type %s
+ SEVERE_ERR_CHECK_CREATE_REPL_BACKEND_FAILED_89=An unexpected error occured when \
+ testing existence or creating the replication backend : %s
+ SEVERE_ERR_DELETE_REPL_BACKEND_FAILED_90=An unexpected error occured when \
+ deleting the replication backend : %s
+
\ No newline at end of file
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
index 82b8b6f..f09fa82 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
@@ -26,10 +26,14 @@
*/
package org.opends.server.replication.plugin;
+import static org.opends.server.replication.plugin.
+ReplicationRepairRequestControl.*;
+
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.opends.messages.Message;
import org.opends.server.admin.server.ConfigurationAddListener;
import org.opends.server.admin.server.ConfigurationDeleteListener;
import org.opends.server.admin.std.server.MultimasterDomainCfg;
@@ -42,7 +46,6 @@
import org.opends.server.api.SynchronizationProvider;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
-
import org.opends.server.types.BackupConfig;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.Control;
@@ -66,10 +69,6 @@
import org.opends.server.types.operation.PreOperationDeleteOperation;
import org.opends.server.types.operation.PreOperationModifyDNOperation;
import org.opends.server.types.operation.PreOperationModifyOperation;
-import org.opends.messages.Message;
-
-import static org.opends.server.replication.plugin.
- ReplicationRepairRequestControl.*;
/**
* This class is used to load the Replication code inside the JVM
@@ -86,7 +85,7 @@
BackupTaskListener, RestoreTaskListener, ImportTaskListener,
ExportTaskListener
{
- private ReplicationServerListener replicationServer = null;
+ private ReplicationServerListener replicationServerListener = null;
private static Map<DN, ReplicationDomain> domains =
new HashMap<DN, ReplicationDomain>() ;
@@ -193,7 +192,7 @@
MultimasterSynchronizationProviderCfg configuration)
throws ConfigException
{
- replicationServer = new ReplicationServerListener(configuration);
+ replicationServerListener = new ReplicationServerListener(configuration);
// Register as an add and delete listener with the root configuration so we
// can be notified if Multimaster domain entries are added or removed.
@@ -438,8 +437,8 @@
}
// shutdown the ReplicationServer Service if necessary
- if (replicationServer != null)
- replicationServer.shutdown();
+ if (replicationServerListener != null)
+ replicationServerListener.shutdown();
DirectoryServer.deregisterBackupTaskListener(this);
DirectoryServer.deregisterRestoreTaskListener(this);
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java
index 6733366..a071d12 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java
@@ -392,7 +392,7 @@
}
catch (Exception e)
{
- Message message = NOTE_EXCEPTION_STARTING_SESSION.get(
+ Message message = ERR_EXCEPTION_STARTING_SESSION.get(
baseDn.toNormalizedString(), server, e.getLocalizedMessage() +
stackTraceToSingleLineString(e));
logError(message);
@@ -733,7 +733,7 @@
if (debugEnabled())
{
debugInfo("ReplicationBroker is stopping. and will" +
- "close the connection");
+ " close the connection");
}
if (session != null)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
index 0724851..c1847bc 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
@@ -212,9 +212,6 @@
// Null when none is being processed.
private IEContext ieContext = null;
- // The backend information necessary to make an import or export.
- private Backend backend;
-
private int listenerThreadNumber = 10;
private Collection<String> replicationServers;
@@ -383,7 +380,7 @@
monitor = new ReplicationMonitor(this);
DirectoryServer.registerMonitorProvider(monitor);
- backend = retrievesBackend(baseDN);
+ Backend backend = retrievesBackend(baseDN);
if (backend == null)
{
throw new ConfigException(ERR_SEARCHING_DOMAIN_BACKEND.get(
@@ -855,8 +852,6 @@
de.getMessageObject());
MessageBuilder mb = new MessageBuilder();
mb.append(de.getMessageObject());
- mb.append("Backend ID: ");
- mb.append(backend.getBackendID());
TRACER.debugInfo(Message.toString(mb.toMessage()));
broker.publish(errorMsg);
}
@@ -2224,10 +2219,8 @@
*/
public long computeGenerationId() throws DirectoryException
{
+ Backend backend = this.retrievesBackend(baseDN);
long bec = backend.getEntryCount();
- if (bec<0)
- backend = this.retrievesBackend(baseDN);
- bec = backend.getEntryCount();
this.acquireIEContext();
ieContext.checksumOutput = true;
ieContext.entryCount = (bec<1000?bec:1000);
@@ -2598,9 +2591,7 @@
protected void exportBackend()
throws DirectoryException
{
- // FIXME Temporary workaround - will probably be fixed when implementing
- // dynamic config
- backend = retrievesBackend(this.baseDN);
+ Backend backend = retrievesBackend(this.baseDN);
// Acquire a shared lock for the backend.
try
@@ -2938,9 +2929,7 @@
{
try
{
- // FIXME Temporary workaround - will probably be fixed when implementing
- // dynamic config
- backend = retrievesBackend(this.baseDN);
+ Backend backend = retrievesBackend(this.baseDN);
if (!backend.supportsLDIFExport())
{
@@ -3027,6 +3016,8 @@
LDIFImportConfig importConfig = null;
DirectoryException de = null;
+ Backend backend = this.retrievesBackend(baseDN);
+
if (!backend.supportsLDIFImport())
{
Message message = ERR_INIT_IMPORT_NOT_SUPPORTED.get(
@@ -3051,7 +3042,7 @@
ieContext.entryLeftCount = initializeMessage.getEntryCount();
ieContext.initImportExportCounters(initializeMessage.getEntryCount());
- preBackendImport(this.backend);
+ preBackendImport(backend);
ieContext.ldifImportInputStream = new ReplLDIFInputStream(this);
importConfig =
@@ -3066,7 +3057,7 @@
// ExistingFileBehavior.OVERWRITE);
// Process import
- this.backend.importLDIF(importConfig);
+ backend.importLDIF(importConfig);
TRACER.debugInfo("The import has ended successfully.");
stateSavingDisabled = false;
@@ -3083,7 +3074,7 @@
importConfig.close();
// Re-enable backend
- closeBackendImport(this.backend);
+ closeBackendImport(backend);
// Update the task that initiated the import
if ((ieContext != null ) && (ieContext.initializeTask != null))
@@ -3202,7 +3193,7 @@
*/
public Backend getBackend()
{
- return backend;
+ return retrievesBackend(baseDN);
}
/**
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationServerListener.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationServerListener.java
index f1bea6d..ccd31fc 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationServerListener.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationServerListener.java
@@ -25,6 +25,7 @@
* Portions Copyright 2007 Sun Microsystems, Inc.
*/
package org.opends.server.replication.plugin;
+
import org.opends.messages.Message;
import java.util.List;
@@ -105,7 +106,7 @@
}
/**
- * Shutdown the Replication servers.
+ * Shutdown the replication server.
*/
public void shutdown()
{
@@ -123,7 +124,7 @@
// replicationServer currently configured.
if (replicationServer != null)
{
- replicationServer.shutdown();
+ replicationServer.remove();
}
return new ConfigChangeResult(ResultCode.SUCCESS, false);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java
new file mode 100644
index 0000000..d02c2c7
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java
@@ -0,0 +1,493 @@
+/*
+ * 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
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * 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
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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
+ *
+ *
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.replication.server;
+import static org.opends.messages.BackendMessages.*;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.loggers.debug.DebugLogger.getTracer;
+import static org.opends.server.util.StaticUtils.getExceptionMessage;
+
+import java.util.HashMap;
+import java.util.HashSet;
+
+import org.opends.messages.Message;
+import org.opends.server.admin.Configuration;
+import org.opends.server.admin.std.server.BackendCfg;
+import org.opends.server.admin.std.server.JEBackendCfg;
+import org.opends.server.api.Backend;
+import org.opends.server.backends.jeb.BackupManager;
+import org.opends.server.config.ConfigException;
+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.loggers.debug.DebugTracer;
+import org.opends.server.types.BackupConfig;
+import org.opends.server.types.BackupDirectory;
+import org.opends.server.types.ConditionResult;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.LDIFExportConfig;
+import org.opends.server.types.LDIFImportConfig;
+import org.opends.server.types.LDIFImportResult;
+import org.opends.server.types.RestoreConfig;
+import org.opends.server.types.ResultCode;
+import org.opends.server.util.Validator;
+
+/**
+ * This class defines a backend that stores its information in an
+ * associated replication server object.
+ * This is primarily intended to take advantage of the backup/restore/
+ * import/export of the backend API, and to provide an LDAP access
+ * to the replication server database.
+ * <BR><BR>
+ * Entries stored in this backend are held in the DB associated with
+ * the replication server.
+ * <BR><BR>
+ * Currently are only implemented the create and restore backup features.
+ *
+ */
+public class ReplicationBackend
+ extends Backend
+{
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = getTracer();
+
+ // The base DNs for this backend.
+ private DN[] baseDNs;
+
+ // The mapping between parent DNs and their immediate children.
+ private HashMap<DN,HashSet<DN>> childDNs;
+
+ // The base DNs for this backend, in a hash set.
+ private HashSet<DN> baseDNSet;
+
+ // The set of supported controls for this backend.
+ private HashSet<String> supportedControls;
+
+ // The set of supported features for this backend.
+ private HashSet<String> supportedFeatures;
+
+ // The directory associated with this backend.
+ private BackupDirectory backendDirectory;
+
+ ReplicationServer server;
+
+ /**
+ * The configuration of this backend.
+ */
+ private JEBackendCfg cfg;
+
+ /**
+ * Creates a new backend with the provided information. All backend
+ * implementations must implement a default constructor that use
+ * <CODE>super()</CODE> to invoke this constructor.
+ */
+ public ReplicationBackend()
+ {
+ super();
+ // Perform all initialization in initializeBackend.
+ }
+
+
+ /**
+ * Set the base DNs for this backend. This is used by the unit tests
+ * to set the base DNs without having to provide a configuration
+ * object when initializing the backend.
+ * @param baseDNs The set of base DNs to be served by this memory backend.
+ */
+ public void setBaseDNs(DN[] baseDNs)
+ {
+ this.baseDNs = baseDNs;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void configureBackend(Configuration config) throws ConfigException
+ {
+ if (config != null)
+ {
+ Validator.ensureTrue(config instanceof BackendCfg);
+ cfg = (JEBackendCfg)config;
+ DN[] baseDNs = new DN[cfg.getBackendBaseDN().size()];
+ cfg.getBackendBaseDN().toArray(baseDNs);
+ setBaseDNs(baseDNs);
+ backendDirectory = new BackupDirectory(
+ cfg.getBackendDirectory(), null);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void initializeBackend()
+ throws ConfigException, InitializationException
+ {
+ if ((baseDNs == null) || (baseDNs.length != 1))
+ {
+ Message message = ERR_MEMORYBACKEND_REQUIRE_EXACTLY_ONE_BASE.get();
+ throw new ConfigException(message);
+ }
+
+ baseDNSet = new HashSet<DN>();
+ for (DN dn : baseDNs)
+ {
+ baseDNSet.add(dn);
+ }
+
+ childDNs = new HashMap<DN,HashSet<DN>>();
+
+ supportedControls = new HashSet<String>();
+ supportedFeatures = new HashSet<String>();
+
+ for (DN dn : baseDNs)
+ {
+ try
+ {
+ DirectoryServer.registerBaseDN(dn, this, false, false);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ Message message = ERR_BACKEND_CANNOT_REGISTER_BASEDN.get(
+ dn.toString(), getExceptionMessage(e));
+ throw new InitializationException(message, e);
+ }
+ }
+ }
+
+
+
+ /**
+ * Removes any data that may have been stored in this backend.
+ */
+ public synchronized void clearMemoryBackend()
+ {
+ childDNs.clear();
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void finalizeBackend()
+ {
+ for (DN dn : baseDNs)
+ {
+ try
+ {
+ DirectoryServer.deregisterBaseDN(dn, false);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN[] getBaseDNs()
+ {
+ return baseDNs;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized long getEntryCount()
+ {
+ return -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isLocal()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized Entry getEntry(DN entryDN)
+ {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized boolean entryExists(DN entryDN)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void addEntry(Entry entry, AddOperation addOperation)
+ throws DirectoryException
+ {
+ Message message = ERR_BACKUP_ADD_NOT_SUPPORTED.get();
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void deleteEntry(DN entryDN,
+ DeleteOperation deleteOperation)
+ throws DirectoryException
+ {
+ Message message = ERR_BACKUP_DELETE_NOT_SUPPORTED.get();
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void replaceEntry(Entry entry,
+ ModifyOperation modifyOperation)
+ throws DirectoryException
+ {
+ Message message = ERR_BACKUP_MODIFY_NOT_SUPPORTED.get();
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void renameEntry(DN currentDN, Entry entry,
+ ModifyDNOperation modifyDNOperation)
+ throws DirectoryException
+ {
+ Message message = ERR_BACKUP_MODIFY_DN_NOT_SUPPORTED.get();
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void search(SearchOperation searchOperation)
+ throws DirectoryException
+ {
+ DN matchedDN = baseDNs[0];
+ DN baseDN = searchOperation.getBaseDN();
+ // FIXME Remove this error message or replace when implementing
+ // the search.
+ Message message =
+ ERR_MEMORYBACKEND_ENTRY_DOESNT_EXIST.get(String.valueOf(baseDN));
+ throw new DirectoryException(
+ ResultCode.NO_SUCH_OBJECT, message, matchedDN, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public HashSet<String> getSupportedControls()
+ {
+ return supportedControls;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public HashSet<String> getSupportedFeatures()
+ {
+ return supportedFeatures;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean supportsLDIFExport()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void exportLDIF(LDIFExportConfig exportConfig)
+ throws DirectoryException
+ {
+ // TODO
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean supportsLDIFImport()
+ {
+ return false;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized LDIFImportResult importLDIF(LDIFImportConfig importConfig)
+ throws DirectoryException
+ {
+ return new LDIFImportResult(0, 0, 0);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean supportsBackup()
+ {
+ // This backend does not provide a backup/restore mechanism.
+ return true;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean supportsBackup(BackupConfig backupConfig,
+ StringBuilder unsupportedReason)
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void createBackup(BackupConfig backupConfig)
+ throws DirectoryException
+ {
+ BackupManager backupManager =
+ new BackupManager(getBackendID());
+ backupManager.createBackup(cfg, backupConfig);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeBackup(BackupDirectory backupDirectory,
+ String backupID)
+ throws DirectoryException
+ {
+ BackupManager backupManager =
+ new BackupManager(getBackendID());
+ backupManager.removeBackup(this.backendDirectory, backupID);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean supportsRestore()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void restoreBackup(RestoreConfig restoreConfig)
+ throws DirectoryException
+ {
+ BackupManager backupManager =
+ new BackupManager(getBackendID());
+ backupManager.restoreBackup(cfg, restoreConfig);
+ }
+
+ /**
+ * Retrieves the number of subordinates for the requested entry.
+ *
+ * @param entryDN The distinguished name of the entry.
+ *
+ * @return The number of subordinate entries for the requested entry
+ * or -1 if it can not be determined.
+ *
+ * @throws DirectoryException If a problem occurs while trying to
+ * retrieve the entry.
+ */
+ public long numSubordinates(DN entryDN)
+ throws DirectoryException
+ {
+ Message message = WARN_ROOTDSE_GET_ENTRY_NONROOT.
+ get(entryDN.toNormalizedString());
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+
+ /**
+ * Indicates whether the requested entry has any subordinates.
+ *
+ * @param entryDN The distinguished name of the entry.
+ *
+ * @return {@code ConditionResult.TRUE} if the entry has one or more
+ * subordinates or {@code ConditionResult.FALSE} otherwise
+ * or {@code ConditionResult.UNDEFINED} if it can not be
+ * determined.
+ *
+ * @throws DirectoryException If a problem occurs while trying to
+ * retrieve the entry.
+ */
+ public ConditionResult hasSubordinates(DN entryDN)
+ throws DirectoryException
+ {
+ Message message = WARN_ROOTDSE_GET_ENTRY_NONROOT.
+ get(entryDN.toNormalizedString());
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+
+ /**
+ * Set the replication server associated with this backend.
+ * @param server The replication server.
+ */
+ public void setServer(ReplicationServer server)
+ {
+ this.server = server;
+ }
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServer.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
index 414dd88..8061015 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
@@ -25,16 +25,16 @@
* Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.replication.server;
-import org.opends.messages.*;
-import static org.opends.server.loggers.ErrorLogger.logError;
import static org.opends.messages.ReplicationMessages.*;
-
-import org.opends.messages.MessageBuilder;
+import static org.opends.server.loggers.ErrorLogger.logError;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.loggers.debug.DebugLogger.getTracer;
+import static org.opends.server.util.ServerConstants.EOL;
import static org.opends.server.util.StaticUtils.getFileForPath;
-import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
import java.io.File;
import java.io.IOException;
+import java.io.StringReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
@@ -47,22 +47,35 @@
import java.util.List;
import java.util.Set;
+import org.opends.messages.Message;
+import org.opends.messages.MessageBuilder;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.server.MonitorProviderCfg;
import org.opends.server.admin.std.server.ReplicationServerCfg;
+import org.opends.server.api.Backend;
+import org.opends.server.api.BackupTaskListener;
+import org.opends.server.api.ExportTaskListener;
+import org.opends.server.api.ImportTaskListener;
import org.opends.server.api.MonitorProvider;
+import org.opends.server.api.RestoreTaskListener;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.replication.protocol.ReplSessionSecurity;
+import org.opends.server.loggers.LogLevel;
+import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.replication.protocol.ProtocolSession;
+import org.opends.server.replication.protocol.ReplSessionSecurity;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
+import org.opends.server.types.BackupConfig;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
+import org.opends.server.types.Entry;
+import org.opends.server.types.LDIFExportConfig;
+import org.opends.server.types.LDIFImportConfig;
+import org.opends.server.types.RestoreConfig;
import org.opends.server.types.ResultCode;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.util.LDIFReader;
import com.sleepycat.je.DatabaseException;
@@ -77,7 +90,9 @@
* It is responsible for creating the replication server cache and managing it
*/
public class ReplicationServer extends MonitorProvider<MonitorProviderCfg>
- implements Runnable, ConfigurationChangeListener<ReplicationServerCfg>
+ implements Runnable, ConfigurationChangeListener<ReplicationServerCfg>,
+ BackupTaskListener, RestoreTaskListener, ImportTaskListener,
+ ExportTaskListener
{
private short serverId;
private String serverURL;
@@ -108,6 +123,12 @@
private boolean stopListen = false;
private ReplSessionSecurity replSessionSecurity;
+ // For the backend associated to this replication server,
+ // DN of the config entry of the backend
+ private DN backendConfigEntryDN;
+ // ID of the backend
+ private static final String backendId = "replicationChanges";
+
/**
* The tracer object for the debug logger.
*/
@@ -120,11 +141,10 @@
* @throws ConfigException When Configuration is invalid.
*/
public ReplicationServer(ReplicationServerCfg configuration)
- throws ConfigException
+ throws ConfigException
{
super("Replication Server" + configuration.getReplicationPort());
- shutdown = false;
replicationPort = configuration.getReplicationPort();
replicationServerId = (short) configuration.getReplicationServerId();
replicationServers = configuration.getReplicationServer();
@@ -162,6 +182,21 @@
initialize(replicationServerId, replicationPort);
configuration.addChangeListener(this);
DirectoryServer.registerMonitorProvider(this);
+
+ try
+ {
+ backendConfigEntryDN = DN.decode(
+ "ds-cfg-backend-id=" + backendId + ",cn=Backends,cn=config");
+ } catch (Exception e) {}
+
+ // Creates the backend associated to this ReplicationServer
+ // if it does not exist.
+ createBackend();
+
+ DirectoryServer.registerBackupTaskListener(this);
+ DirectoryServer.registerRestoreTaskListener(this);
+ DirectoryServer.registerExportTaskListener(this);
+ DirectoryServer.registerImportTaskListener(this);
}
@@ -315,6 +350,8 @@
*/
private void initialize(short changelogId, int changelogPort)
{
+ shutdown = false;
+
try
{
/*
@@ -458,7 +495,7 @@
dbEnv.shutdown();
}
DirectoryServer.deregisterMonitorProvider(getMonitorInstanceName());
- }
+}
/**
@@ -492,10 +529,7 @@
}
catch(Exception e)
{
- TRACER.debugInfo(
- "In RS <" + getMonitorInstanceName() +
- " Exception in clearGenerationId" +
- stackTraceToSingleLineString(e) + e.getLocalizedMessage());
+ TRACER.debugCaught(LogLevel.ALL, e);
}
}
@@ -730,4 +764,180 @@
{
return serverId;
}
+
+ /**
+ * Creates the backend associated to this replication server.
+ * @throws ConfigException
+ */
+ private void createBackend()
+ throws ConfigException
+ {
+ try
+ {
+ String ldif = makeLdif(
+ "dn: ds-cfg-backend-id="+backendId+",cn=Backends,cn=config",
+ "objectClass: top",
+ "objectClass: ds-cfg-backend",
+ "objectClass: ds-cfg-je-backend",
+ "ds-cfg-backend-base-dn: dc="+backendId,
+ "ds-cfg-backend-enabled: true",
+ "ds-cfg-backend-writability-mode: enabled",
+ "ds-cfg-backend-class: " +
+ "org.opends.server.replication.server.ReplicationBackend",
+ "ds-cfg-backend-id: " + backendId,
+ "ds-cfg-backend-import-temp-directory: importTmp",
+ "ds-cfg-backend-directory: " + getFileForPath(dbDirname));
+
+ LDIFImportConfig ldifImportConfig = new LDIFImportConfig(
+ new StringReader(ldif));
+ LDIFReader reader = new LDIFReader(ldifImportConfig);
+ Entry backendConfigEntry = reader.readEntry();
+ if (!DirectoryServer.getConfigHandler().entryExists(backendConfigEntryDN))
+ {
+ // Add the replication backend
+ DirectoryServer.getConfigHandler().addEntry(backendConfigEntry, null);
+ }
+ }
+ catch(Exception e)
+ {
+ MessageBuilder mb = new MessageBuilder();
+ mb.append(e.getLocalizedMessage());
+ Message msg = ERR_CHECK_CREATE_REPL_BACKEND_FAILED.get(mb.toString());
+ throw new ConfigException(msg, e);
+
+ }
+ }
+
+ private static String makeLdif(String... lines)
+ {
+ StringBuilder buffer = new StringBuilder();
+ for (String line : lines) {
+ buffer.append(line).append(EOL);
+ }
+ // Append an extra line so we can append LDIF Strings.
+ buffer.append(EOL);
+ return buffer.toString();
+ }
+
+ /**
+ * Do what needed when the config object related to this replication server
+ * is deleted from the server configuration.
+ */
+ public void remove()
+ {
+ if (debugEnabled())
+ TRACER.debugInfo("RS " +getMonitorInstanceName()+
+ " starts removing");
+
+ shutdown();
+ removeBackend();
+
+ DirectoryServer.deregisterBackupTaskListener(this);
+ DirectoryServer.deregisterRestoreTaskListener(this);
+ DirectoryServer.deregisterExportTaskListener(this);
+ DirectoryServer.deregisterImportTaskListener(this);
+ }
+
+ /**
+ * Removes the backend associated to this Replication Server that has been
+ * created when this replication server was created.
+ */
+ protected void removeBackend()
+ {
+ try
+ {
+ if (!DirectoryServer.getConfigHandler().entryExists(backendConfigEntryDN))
+ {
+ // Delete the replication backend
+ DirectoryServer.getConfigHandler().deleteEntry(backendConfigEntryDN,
+ null);
+ }
+ }
+ catch(Exception e)
+ {
+ MessageBuilder mb = new MessageBuilder();
+ mb.append(e.getLocalizedMessage());
+ Message msg = ERR_DELETE_REPL_BACKEND_FAILED.get(mb.toString());
+ logError(msg);
+ }
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public void processBackupBegin(Backend backend, BackupConfig config)
+ {
+ // Nothing is needed at the moment
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void processBackupEnd(Backend backend, BackupConfig config,
+ boolean successful)
+ {
+ // Nothing is needed at the moment
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void processRestoreBegin(Backend backend, RestoreConfig config)
+ {
+ if (backend.getBackendID().equals(backendId))
+ shutdown();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void processRestoreEnd(Backend backend, RestoreConfig config,
+ boolean successful)
+ {
+ if (backend.getBackendID().equals(backendId))
+ initialize(this.replicationServerId, this.replicationPort);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void processImportBegin(Backend backend, LDIFImportConfig config)
+ {
+ // Nothing is needed at the moment
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void processImportEnd(Backend backend, LDIFImportConfig config,
+ boolean successful)
+ {
+ // Nothing is needed at the moment
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void processExportBegin(Backend backend, LDIFExportConfig config)
+ {
+ if (debugEnabled())
+ TRACER.debugInfo("RS " +getMonitorInstanceName()+
+ " Export starts");
+ if (backend.getBackendID().equals(backendId))
+ {
+ // Retrieves the backend related to this domain
+ // backend =
+ ReplicationBackend b =
+ (ReplicationBackend)DirectoryServer.getBackend(backendId);
+ b.setServer(this);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void processExportEnd(Backend backend, LDIFExportConfig config,
+ boolean successful)
+ {
+ // Nothing is needed at the moment
+ }
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerReader.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerReader.java
index cb66bd2..d582bb7 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerReader.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerReader.java
@@ -100,7 +100,7 @@
if (debugEnabled())
{
TRACER.debugInfo(
- "In RS <" + replicationCache.getReplicationServer().
+ "In RS " + replicationCache.getReplicationServer().
getMonitorInstanceName() +
(handler.isReplicationServer()?" RS ":" LS")+
" reader starting for serverId=" + serverId);
@@ -117,22 +117,11 @@
if (debugEnabled())
{
- if (handler.isReplicationServer())
- {
- TRACER.debugInfo(
- "In RS <" + replicationCache.getReplicationServer().
- getMonitorInstanceName() +
- "> from RS server with serverId=" + serverId +
- " receives " + msg);
- }
- else
- {
- TRACER.debugInfo(
- "In RS <" + replicationCache.getReplicationServer().
- getMonitorInstanceName() +
- "> from LDAP server with serverId=" + serverId +
- " receives " + msg);
- }
+ TRACER.debugInfo(
+ "In RS " + replicationCache.getReplicationServer().
+ getMonitorInstanceName() +
+ (handler.isReplicationServer()?" From RS ":" From LS")+
+ " with serverId=" + serverId + " receives " + msg);
}
if (msg instanceof AckMessage)
{
@@ -271,11 +260,10 @@
*/
if (debugEnabled())
TRACER.debugInfo(
- "In RS <" + replicationCache.getReplicationServer().
+ "In RS " + replicationCache.getReplicationServer().
getMonitorInstanceName() +
- " reader IO EXCEPTION serverID=" + serverId
- + stackTraceToSingleLineString(e) + e.getLocalizedMessage() +
- e.getCause());
+ " reader IO EXCEPTION for serverID=" + serverId
+ + stackTraceToSingleLineString(e) + " " + e.getLocalizedMessage());
Message message = NOTE_SERVER_DISCONNECT.get(handler.toString());
logError(message);
} catch (ClassNotFoundException e)
@@ -316,10 +304,10 @@
*/
if (debugEnabled())
TRACER.debugInfo(
- "In RS <" + replicationCache.getReplicationServer().
+ "In RS " + replicationCache.getReplicationServer().
getMonitorInstanceName() +
- " reader CLOSE serverID=" + serverId
- + stackTraceToSingleLineString(new Exception()));
+ " server reader for serverID=" + serverId +
+ " is closing the session");
try
{
session.close();
@@ -331,10 +319,9 @@
}
if (debugEnabled())
TRACER.debugInfo(
- "In RS <" + replicationCache.getReplicationServer().
+ "In RS " + replicationCache.getReplicationServer().
getMonitorInstanceName() +
- (handler.isReplicationServer()?"RS":"LDAP") +
- " server reader stopped for serverID=" + serverId
- + stackTraceToSingleLineString(new Exception()));
+ (handler.isReplicationServer()?" RS":" LDAP") +
+ " server reader stopped for serverID=" + serverId);
}
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/GenerationIdTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/GenerationIdTest.java
index a6b866f..dc08b55 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/GenerationIdTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/GenerationIdTest.java
@@ -300,186 +300,6 @@
return found;
}
- /**
- * Add a task to the configuration of the current running DS.
- * @param taskEntry The task to add.
- * @param expectedResult The expected result code for the ADD.
- * @param errorMessageID The expected error messageID when the expected
- * result code is not SUCCESS
- */
- private void addTask(Entry taskEntry, ResultCode expectedResult,
- Message errorMessage)
- {
- try
- {
- debugInfo("AddTask/" + taskEntry);
-
- // Change config of DS to launch the total update task
- InternalClientConnection connection =
- InternalClientConnection.getRootConnection();
-
- // Add the task.
-
- AddOperation addOperation =
- connection.processAdd(taskEntry.getDN(),
- taskEntry.getObjectClasses(),
- taskEntry.getUserAttributes(),
- taskEntry.getOperationalAttributes());
-
- assertEquals(addOperation.getResultCode(), expectedResult,
- "Result of ADD operation of the task is: "
- + addOperation.getResultCode()
- + " Expected:"
- + expectedResult + " Details:" + addOperation.getErrorMessage()
- + addOperation.getAdditionalLogMessage());
-
- if (expectedResult != ResultCode.SUCCESS)
- {
- assertTrue(addOperation.getErrorMessage().toString().
- startsWith(errorMessage.toString()),
- "Error MsgID of the task <"
- + addOperation.getErrorMessage()
- + "> equals <"
- + errorMessage + ">");
- debugInfo("Create config task: <"+ errorMessage.getDescriptor().getId()
- + addOperation.getErrorMessage() + ">");
-
- }
- else
- {
- waitTaskState(taskEntry, TaskState.RUNNING, null);
- }
-
- // Entry will be removed at the end of the test
- entryList.addLast(taskEntry.getDN());
-
- debugInfo("AddedTask/" + taskEntry.getDN());
- }
- catch(Exception e)
- {
- fail("Exception when adding task:"+ e.getMessage());
- }
- }
-
- private void waitTaskState(Entry taskEntry, TaskState expectedTaskState,
- Message expectedMessage)
- {
- TaskState taskState = null;
- try
- {
-
- SearchFilter filter =
- SearchFilter.createFilterFromString("(objectclass=*)");
- Entry resultEntry = null;
- do
- {
- InternalSearchOperation searchOperation =
- connection.processSearch(taskEntry.getDN(),
- SearchScope.BASE_OBJECT,
- filter);
- try
- {
- resultEntry = searchOperation.getSearchEntries().getFirst();
- } catch (Exception e)
- {
- fail("Task entry was not returned from the search.");
- continue;
- }
-
- try
- {
- // Check that the task state is as expected.
- AttributeType taskStateType =
- DirectoryServer.getAttributeType(ATTR_TASK_STATE.toLowerCase());
- String stateString =
- resultEntry.getAttributeValue(taskStateType,
- DirectoryStringSyntax.DECODER);
- taskState = TaskState.fromString(stateString);
- }
- catch(Exception e)
- {
- fail("Exception"+ e.getMessage()+e.getStackTrace());
- }
- Thread.sleep(500);
- }
- while ((taskState != expectedTaskState) &&
- (taskState != TaskState.STOPPED_BY_ERROR));
-
- // Check that the task contains some log messages.
- AttributeType logMessagesType = DirectoryServer.getAttributeType(
- ATTR_TASK_LOG_MESSAGES.toLowerCase());
- ArrayList<String> logMessages = new ArrayList<String>();
- resultEntry.getAttributeValues(logMessagesType,
- DirectoryStringSyntax.DECODER,
- logMessages);
-
- if ((taskState != TaskState.COMPLETED_SUCCESSFULLY)
- && (taskState != TaskState.RUNNING))
- {
- if (logMessages.size() == 0)
- {
- fail("No log messages were written to the task entry on a failed task");
- }
- else
- {
- if (expectedMessage != null)
- {
- debugInfo(logMessages.get(0));
- debugInfo(expectedMessage.toString());
- assertTrue(logMessages.get(0).indexOf(
- expectedMessage.toString())>0);
- }
- }
- }
-
- assertEquals(taskState, expectedTaskState, "Task State:" + taskState +
- " Expected task state:" + expectedTaskState);
- }
- catch(Exception e)
- {
- fail("waitTaskState Exception:"+ e.getMessage() + " " + stackTraceToSingleLineString(e));
- }
- }
-
- /**
- * Add to the current DB the entries necessary to the test
- */
- private void addTestEntriesToDB(String[] ldifEntries)
- {
- try
- {
- // Change config of DS to launch the total update task
- InternalClientConnection connection =
- InternalClientConnection.getRootConnection();
-
- for (String ldifEntry : ldifEntries)
- {
- Entry entry = TestCaseUtils.entryFromLdifString(ldifEntry);
- AddOperationBasis addOp = new AddOperationBasis(
- connection,
- InternalClientConnection.nextOperationID(),
- InternalClientConnection.nextMessageID(),
- null,
- entry.getDN(),
- entry.getObjectClasses(),
- entry.getUserAttributes(),
- entry.getOperationalAttributes());
- addOp.setInternalOperation(true);
- addOp.run();
- if (addOp.getResultCode() != ResultCode.SUCCESS)
- {
- debugInfo("addEntry: Failed" + addOp.getResultCode());
- }
- // They will be removed at the end of the test
- entryList.addLast(entry.getDN());
- }
- }
- catch(Exception e)
- {
- fail("addEntries Exception:"+ e.getMessage() + " " + stackTraceToSingleLineString(e));
- }
- }
-
/*
* Creates entries necessary to the test.
*/
@@ -1373,11 +1193,11 @@
broker3 = null;
if (replServer1 != null)
- replServer1.shutdown();
+ replServer1.remove();
if (replServer2 != null)
- replServer2.shutdown();
- if (replServer2 != null)
- replServer2.shutdown();
+ replServer2.remove();
+ if (replServer3 != null)
+ replServer3.remove();
replServer1 = null;
replServer2 = null;
replServer3 = null;
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/InitOnLineTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/InitOnLineTest.java
index 12ddbfc..b4a9b2e 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/InitOnLineTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/InitOnLineTest.java
@@ -278,67 +278,6 @@
}
/**
- * Add a task to the configuration of the current running DS.
- * @param taskEntry The task to add.
- * @param expectedResult The expected result code for the ADD.
- * @param errorMessage The expected error messageID when the expected
- * result code is not SUCCESS
- */
- private void addTask(Entry taskEntry, ResultCode expectedResult,
- Message errorMessage)
- {
- try
- {
- log("AddTask/" + taskEntry);
-
- // Change config of DS to launch the total update task
- InternalClientConnection connection =
- InternalClientConnection.getRootConnection();
-
- // Add the task.
-
- AddOperation addOperation =
- connection.processAdd(taskEntry.getDN(),
- taskEntry.getObjectClasses(),
- taskEntry.getUserAttributes(),
- taskEntry.getOperationalAttributes());
-
- assertEquals(addOperation.getResultCode(), expectedResult,
- "Result of ADD operation of the task is: "
- + addOperation.getResultCode()
- + " Expected:"
- + expectedResult + " Details:" + addOperation.getErrorMessage()
- + addOperation.getAdditionalLogMessage());
-
- if (expectedResult != ResultCode.SUCCESS)
- {
- assertTrue(addOperation.getErrorMessage().toString().
- startsWith(errorMessage.toString()),
- "Error MsgID of the task <"
- + addOperation.getErrorMessage()
- + "> equals <"
- + errorMessage + ">");
- log("Create config task: <"+ errorMessage.getDescriptor().getId()
- + addOperation.getErrorMessage() + ">");
-
- }
- else
- {
- waitTaskState(taskEntry, TaskState.RUNNING, null);
- }
-
- // Entry will be removed at the end of the test
- entryList.addLast(taskEntry.getDN());
-
- log("AddedTask/" + taskEntry.getDN());
- }
- catch(Exception e)
- {
- fail("Exception when adding task:"+ e.getMessage());
- }
- }
-
- /**
* Wait a task to be completed and check the expected state and expected
* stats.
* @param taskEntry The task to process.
@@ -454,107 +393,6 @@
}
}
- private void waitTaskState(Entry taskEntry, TaskState expectedTaskState,
- Message expectedMessage)
- {
- TaskState taskState = null;
- try
- {
-
- SearchFilter filter =
- SearchFilter.createFilterFromString("(objectclass=*)");
- Entry resultEntry = null;
- do
- {
- InternalSearchOperation searchOperation =
- connection.processSearch(taskEntry.getDN(),
- SearchScope.BASE_OBJECT,
- filter);
- try
- {
- resultEntry = searchOperation.getSearchEntries().getFirst();
- } catch (Exception e)
- {
- // FIXME How is this possible? Must be issue 858.
- fail("Task entry was not returned from the search.");
- continue;
- }
-
- try
- {
- // Check that the task state is as expected.
- AttributeType taskStateType =
- DirectoryServer.getAttributeType(ATTR_TASK_STATE.toLowerCase());
- String stateString =
- resultEntry.getAttributeValue(taskStateType,
- DirectoryStringSyntax.DECODER);
- taskState = TaskState.fromString(stateString);
- }
- catch(Exception e)
- {
- fail("Exception"+ e.getMessage()+e.getStackTrace());
- }
-
- try
- {
- // Check that the left counter.
- AttributeType taskStateType =
- DirectoryServer.getAttributeType(ATTR_TASK_INITIALIZE_LEFT, true);
- resultEntry.getAttributeValue(taskStateType,
- DirectoryStringSyntax.DECODER);
-
- // Check that the total counter.
- taskStateType =
- DirectoryServer.getAttributeType(ATTR_TASK_INITIALIZE_DONE, true);
- resultEntry.getAttributeValue(taskStateType,
- DirectoryStringSyntax.DECODER);
- }
- catch(Exception e)
- {
- fail("Exception"+ e.getMessage()+e.getStackTrace());
- }
-
- Thread.sleep(2000);
- }
- while ((taskState != expectedTaskState) &&
- (taskState != TaskState.STOPPED_BY_ERROR));
-
- // Check that the task contains some log messages.
- AttributeType logMessagesType = DirectoryServer.getAttributeType(
- ATTR_TASK_LOG_MESSAGES.toLowerCase());
- ArrayList<String> logMessages = new ArrayList<String>();
- resultEntry.getAttributeValues(logMessagesType,
- DirectoryStringSyntax.DECODER,
- logMessages);
-
- if ((taskState != TaskState.COMPLETED_SUCCESSFULLY)
- && (taskState != TaskState.RUNNING))
- {
- if (logMessages.size() == 0)
- {
- fail("No log messages were written to the task entry on a failed task");
- }
- else
- {
- if (expectedMessage != null)
- {
- log(logMessages.get(0));
- log(expectedMessage.toString());
- assertTrue(logMessages.get(0).indexOf(
- expectedMessage.toString())>=0);
- }
- }
- }
-
- assertEquals(taskState, expectedTaskState, "Task State:" + taskState +
- " Expected task state:" + expectedTaskState);
- }
- catch(Exception e)
- {
- fail("waitTaskState Exception:"+ e.getMessage() + " " + stackTraceToSingleLineString(e));
- }
- }
-
/**
* Add to the current DB the entries necessary to the test
*/
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
index 93193b2..a09b5e7 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
@@ -26,9 +26,10 @@
*/
package org.opends.server.replication;
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_COMPLETION_TIME;
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_STATE;
+import static org.opends.server.config.ConfigConstants.*;
import static org.opends.server.loggers.ErrorLogger.logError;
+import static org.opends.server.loggers.debug.DebugLogger.getTracer;
+import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@@ -51,8 +52,10 @@
import org.opends.server.backends.task.TaskState;
import org.opends.server.config.ConfigException;
import org.opends.server.core.AddOperation;
+import org.opends.server.core.AddOperationBasis;
import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.core.DirectoryServer;
+import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.protocols.ldap.LDAPFilter;
@@ -90,6 +93,9 @@
public abstract class ReplicationTestCase extends DirectoryServerTestCase
{
+ // The tracer object for the debug logger
+ private static final DebugTracer TRACER = getTracer();
+
/**
* The internal connection used for operation
*/
@@ -726,4 +732,187 @@
return new ReplSessionSecurity(null, null, null, true);
}
+ /**
+ * Add a task to the configuration of the current running DS.
+ * @param taskEntry The task to add.
+ * @param expectedResult The expected result code for the ADD.
+ * @param errorMessageID The expected error messageID when the expected
+ * result code is not SUCCESS
+ */
+ protected void addTask(Entry taskEntry, ResultCode expectedResult,
+ Message errorMessage)
+ {
+ try
+ {
+ TRACER.debugInfo("AddTask/" + taskEntry);
+
+ // Change config of DS to launch the total update task
+ InternalClientConnection connection =
+ InternalClientConnection.getRootConnection();
+
+ // Add the task.
+
+ AddOperation addOperation =
+ connection.processAdd(taskEntry.getDN(),
+ taskEntry.getObjectClasses(),
+ taskEntry.getUserAttributes(),
+ taskEntry.getOperationalAttributes());
+
+ assertEquals(addOperation.getResultCode(), expectedResult,
+ "Result of ADD operation of the task is: "
+ + addOperation.getResultCode()
+ + " Expected:"
+ + expectedResult + " Details:" + addOperation.getErrorMessage()
+ + addOperation.getAdditionalLogMessage());
+
+ if (expectedResult != ResultCode.SUCCESS)
+ {
+ assertTrue(addOperation.getErrorMessage().toString().
+ startsWith(errorMessage.toString()),
+ "Error MsgID of the task <"
+ + addOperation.getErrorMessage()
+ + "> equals <"
+ + errorMessage + ">");
+ TRACER.debugInfo("Create config task: <"+ errorMessage.getDescriptor().getId()
+ + addOperation.getErrorMessage() + ">");
+
+ }
+ else
+ {
+ waitTaskState(taskEntry, TaskState.RUNNING, null);
+ }
+
+ // Entry will be removed at the end of the test
+ entryList.addLast(taskEntry.getDN());
+
+ TRACER.debugInfo("AddedTask/" + taskEntry.getDN());
+ }
+ catch(Exception e)
+ {
+ fail("Exception when adding task:"+ e.getMessage());
+ }
+ }
+
+ protected void waitTaskState(Entry taskEntry, TaskState expectedTaskState,
+ Message expectedMessage)
+ {
+ TaskState taskState = null;
+ int cpt=10;
+ try
+ {
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectclass=*)");
+ Entry resultEntry = null;
+ do
+ {
+ InternalSearchOperation searchOperation =
+ connection.processSearch(taskEntry.getDN(),
+ SearchScope.BASE_OBJECT,
+ filter);
+ try
+ {
+ resultEntry = searchOperation.getSearchEntries().getFirst();
+ } catch (Exception e)
+ {
+ fail("Task entry was not returned from the search.");
+ continue;
+ }
+
+ try
+ {
+ // Check that the task state is as expected.
+ AttributeType taskStateType =
+ DirectoryServer.getAttributeType(ATTR_TASK_STATE.toLowerCase());
+ String stateString =
+ resultEntry.getAttributeValue(taskStateType,
+ DirectoryStringSyntax.DECODER);
+ taskState = TaskState.fromString(stateString);
+ }
+ catch(Exception e)
+ {
+ fail("Exception"+ e.getMessage()+e.getStackTrace());
+ }
+ Thread.sleep(500);
+ cpt--;
+ }
+ while ((taskState != expectedTaskState) &&
+ (taskState != TaskState.STOPPED_BY_ERROR) &&
+ (taskState != TaskState.COMPLETED_SUCCESSFULLY) &&
+ (cpt > 0));
+
+ // Check that the task contains some log messages.
+ AttributeType logMessagesType = DirectoryServer.getAttributeType(
+ ATTR_TASK_LOG_MESSAGES.toLowerCase());
+ ArrayList<String> logMessages = new ArrayList<String>();
+ resultEntry.getAttributeValues(logMessagesType,
+ DirectoryStringSyntax.DECODER,
+ logMessages);
+
+ if ((taskState != TaskState.COMPLETED_SUCCESSFULLY)
+ && (taskState != TaskState.RUNNING))
+ {
+ if (logMessages.size() == 0)
+ {
+ fail("No log messages were written to the task entry on a failed task");
+ }
+ else
+ {
+ TRACER.debugInfo(logMessages.get(0));
+ if (expectedMessage != null)
+ {
+ TRACER.debugInfo(expectedMessage.toString());
+ assertTrue(logMessages.get(0).indexOf(
+ expectedMessage.toString())>0);
+ }
+ }
+ }
+
+ assertEquals(taskState, expectedTaskState, "Task State:" + taskState +
+ " Expected task state:" + expectedTaskState);
+ }
+ catch(Exception e)
+ {
+ fail("waitTaskState Exception:"+ e.getMessage() + " " + stackTraceToSingleLineString(e));
+ }
+ }
+
+ /**
+ * Add to the current DB the entries necessary to the test
+ */
+ protected void addTestEntriesToDB(String[] ldifEntries)
+ {
+ try
+ {
+ // Change config of DS to launch the total update task
+ InternalClientConnection connection =
+ InternalClientConnection.getRootConnection();
+
+ for (String ldifEntry : ldifEntries)
+ {
+ Entry entry = TestCaseUtils.entryFromLdifString(ldifEntry);
+ AddOperationBasis addOp = new AddOperationBasis(
+ connection,
+ InternalClientConnection.nextOperationID(),
+ InternalClientConnection.nextMessageID(),
+ null,
+ entry.getDN(),
+ entry.getObjectClasses(),
+ entry.getUserAttributes(),
+ entry.getOperationalAttributes());
+ addOp.setInternalOperation(true);
+ addOp.run();
+ if (addOp.getResultCode() != ResultCode.SUCCESS)
+ {
+ TRACER.debugInfo("Failed to add entry " + entry.getDN() +
+ "Result code = : " + addOp.getResultCode());
+ }
+ // They will be removed at the end of the test
+ entryList.addLast(entry.getDN());
+ }
+ }
+ catch(Exception e)
+ {
+ fail("addEntries Exception:"+ e.getMessage() + " " + stackTraceToSingleLineString(e));
+ }
+ }
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplicationServerTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplicationServerTest.java
index cc54b98..a16d3f8 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplicationServerTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplicationServerTest.java
@@ -34,6 +34,7 @@
import static org.opends.server.loggers.debug.DebugLogger.getTracer;
import static org.opends.server.replication.protocol.OperationContext.*;
+import java.io.File;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
@@ -42,11 +43,10 @@
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
+import java.util.UUID;
-import org.opends.messages.Category;
-import org.opends.messages.Message;
-import org.opends.messages.Severity;
import org.opends.server.TestCaseUtils;
+import org.opends.server.backends.task.TaskState;
import org.opends.server.core.ModifyDNOperationBasis;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.replication.ReplicationTestCase;
@@ -62,6 +62,7 @@
import org.opends.server.types.ModificationType;
import org.opends.server.types.RDN;
import org.opends.server.types.DirectoryConfig;
+import org.opends.server.types.ResultCode;
import org.opends.server.util.TimeThread;
import org.opends.server.workflowelement.localbackend.LocalBackendModifyDNOperation;
import org.testng.annotations.AfterClass;
@@ -413,7 +414,7 @@
@Test(enabled=true, dependsOnMethods = { "changelogBasic" })
public void stopChangelog() throws Exception
{
- replicationServer.shutdown();
+ replicationServer.remove();
configure();
newClient();
newClientWithFirstChanges();
@@ -628,7 +629,7 @@
ReplServerFakeConfiguration conf =
new ReplServerFakeConfiguration(changelogPorts[i], "changelogDb"+i, 0,
changelogIds[i], 0, 100, servers);
- replicationServer = new ReplicationServer(conf);
+ changelogs[i] = new ReplicationServer(conf);
}
ReplicationBroker broker1 = null;
@@ -763,9 +764,9 @@
finally
{
if (changelogs[0] != null)
- changelogs[0].shutdown();
+ changelogs[0].remove();
if (changelogs[1] != null)
- changelogs[1].shutdown();
+ changelogs[1].remove();
if (broker1 != null)
broker1.stop();
if (broker2 != null)
@@ -972,4 +973,53 @@
}
}
}
+
+
+ /*
+ * Test backup and restore of the Replication server backend
+ */
+ @Test(enabled=true)
+ public void backupRestore() throws Exception
+ {
+ debugInfo("Starting backupRestore");
+
+ Entry backupTask = createBackupTask();
+ Entry restoreTask = createRestoreTask();
+
+ addTask(backupTask, ResultCode.SUCCESS, null);
+ waitTaskState(backupTask, TaskState.COMPLETED_SUCCESSFULLY, null);
+
+ addTask(restoreTask, ResultCode.SUCCESS, null);
+ waitTaskState(restoreTask, TaskState.COMPLETED_SUCCESSFULLY, null);
+
+ debugInfo("Ending backupRestore");
+ }
+
+ private Entry createBackupTask()
+ throws Exception
+ {
+ return TestCaseUtils.makeEntry(
+ "dn: ds-task-id=" + UUID.randomUUID() + ",cn=Scheduled Tasks,cn=Tasks",
+ "objectclass: top",
+ "objectclass: ds-task",
+ "objectclass: ds-task-backup",
+ "ds-task-class-name: org.opends.server.tasks.BackupTask",
+ "ds-backup-directory-path: bak" + File.separator +
+ "replicationChanges",
+ "ds-task-backup-backend-id: replicationChanges");
+
+ }
+
+ private Entry createRestoreTask()
+ throws Exception
+ {
+ return TestCaseUtils.makeEntry(
+ "dn: ds-task-id=" + UUID.randomUUID() + ",cn=Scheduled Tasks,cn=Tasks",
+ "objectclass: top",
+ "objectclass: ds-task",
+ "objectclass: ds-task-restore",
+ "ds-task-class-name: org.opends.server.tasks.RestoreTask",
+ "ds-backup-directory-path: bak" + File.separator +
+ "replicationChanges");
+ }
}
--
Gitblit v1.10.0