From 3aaa6c602ae74b348c8f6870324b8e74d89c7f2f Mon Sep 17 00:00:00 2001
From: pgamba <pgamba@localhost>
Date: Wed, 12 Sep 2007 09:09:12 +0000
Subject: [PATCH] #793 / Ability to export replication backend
---
opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java | 2
opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServer.java | 14 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java | 6
opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerWriter.java | 2
opendj-sdk/opends/src/messages/messages/replication.properties | 4
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplicationServerTest.java | 190 ++++++++++++++++
opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java | 406 ++++++++++++++++++++++++++++++++++++
opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java | 9
opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyDNMsg.java | 2
9 files changed, 619 insertions(+), 16 deletions(-)
diff --git a/opendj-sdk/opends/src/messages/messages/replication.properties b/opendj-sdk/opends/src/messages/messages/replication.properties
index 2b6cbbf..177234b 100644
--- a/opendj-sdk/opends/src/messages/messages/replication.properties
+++ b/opendj-sdk/opends/src/messages/messages/replication.properties
@@ -229,4 +229,8 @@
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
+ SEVERE_ERR_EXPORT_CANNOT_WRITE_ENTRY_TO_LDIF_91=An error occured when \
+ exporting to LDIF the entry %s : %s
+SEVERE_ERR_BACKEND_CANNOT_CREATE_LDIF_WRITER_92 =An error occured when \
+ creating the LDIF writer to export backend : %s
\ No newline at end of file
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java
index 307e619..5234eda 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java
@@ -288,4 +288,13 @@
{
parentUniqueId = uid;
}
+
+ /**
+ * Get the parent unique id of this add msg.
+ * @return the parent unique id.
+ */
+ public String getParentUid()
+ {
+ return parentUniqueId;
+ }
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyDNMsg.java b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyDNMsg.java
index b6ba1de..5c3757d 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyDNMsg.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyDNMsg.java
@@ -235,7 +235,7 @@
@Override
public String toString()
{
- return ("Modify DN " + getDn() + " " + newRDN + " " + newSuperior + " " +
+ return ("MODDN " + getDn() + " " + newRDN + " " + newSuperior + " " +
getChangeNumber());
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java
index d9c185e..21167fb 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java
@@ -232,6 +232,6 @@
@Override
public String toString()
{
- return("Modify " + getDn() + " " + getChangeNumber());
+ return("MOD " + getDn() + " " + getChangeNumber());
}
}
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
index d02c2c7..5ce0a43 100644
--- 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
@@ -26,12 +26,23 @@
*/
package org.opends.server.replication.server;
import static org.opends.messages.BackendMessages.*;
+import static org.opends.messages.JebMessages.INFO_JEB_EXPORT_FINAL_STATUS;
+import static org.opends.messages.JebMessages.INFO_JEB_EXPORT_PROGRESS_REPORT;
+import static org.opends.messages.ReplicationMessages.*;
+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.StaticUtils.getExceptionMessage;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
import org.opends.messages.Message;
import org.opends.server.admin.Configuration;
@@ -47,6 +58,15 @@
import org.opends.server.core.ModifyOperation;
import org.opends.server.core.SearchOperation;
import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.replication.protocol.AddMsg;
+import org.opends.server.replication.protocol.DeleteMsg;
+import org.opends.server.replication.protocol.ModifyDNMsg;
+import org.opends.server.replication.protocol.ModifyMsg;
+import org.opends.server.replication.protocol.UpdateMessage;
+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.BackupDirectory;
import org.opends.server.types.ConditionResult;
@@ -58,8 +78,14 @@
import org.opends.server.types.LDIFExportConfig;
import org.opends.server.types.LDIFImportConfig;
import org.opends.server.types.LDIFImportResult;
+import org.opends.server.types.RawAttribute;
import org.opends.server.types.RestoreConfig;
import org.opends.server.types.ResultCode;
+import org.opends.server.util.AddChangeRecordEntry;
+import org.opends.server.util.DeleteChangeRecordEntry;
+import org.opends.server.util.LDIFWriter;
+import org.opends.server.util.ModifyChangeRecordEntry;
+import org.opends.server.util.ModifyDNChangeRecordEntry;
import org.opends.server.util.Validator;
/**
@@ -83,6 +109,8 @@
*/
private static final DebugTracer TRACER = getTracer();
+ private static final String EXPORT_BASE_DN = "dc=replicationChanges";
+
// The base DNs for this backend.
private DN[] baseDNs;
@@ -109,6 +137,21 @@
private JEBackendCfg cfg;
/**
+ * The number of milliseconds between job progress reports.
+ */
+ private long progressInterval = 10000;
+
+ /**
+ * The current number of entries exported.
+ */
+ private long exportedCount = 0;
+
+ /**
+ * The current number of entries skipped.
+ */
+ private long skippedCount = 0;
+
+ /**
* 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.
@@ -345,16 +388,323 @@
*/
public boolean supportsLDIFExport()
{
- return false;
+ return true;
}
/**
* {@inheritDoc}
*/
public synchronized void exportLDIF(LDIFExportConfig exportConfig)
- throws DirectoryException
+ throws DirectoryException
{
- // TODO
+ List<DN> includeBranches = exportConfig.getIncludeBranches();
+ DN baseDN;
+ ArrayList<ReplicationCache> exportContainers =
+ new ArrayList<ReplicationCache>();
+
+ Iterator<ReplicationCache> rcachei = server.getCacheIterator();
+ if (rcachei != null)
+ {
+ while (rcachei.hasNext())
+ {
+ ReplicationCache rc = rcachei.next();
+
+ // Skip containers that are not covered by the include branches.
+ baseDN = DN.decode(rc.getBaseDn().toString() + "," + EXPORT_BASE_DN);
+
+ if (includeBranches == null || includeBranches.isEmpty())
+ {
+ exportContainers.add(rc);
+ }
+ else
+ {
+ for (DN includeBranch : includeBranches)
+ {
+ if (includeBranch.isDescendantOf(baseDN) ||
+ includeBranch.isAncestorOf(baseDN))
+ {
+ exportContainers.add(rc);
+ }
+ }
+ }
+ }
+ }
+
+ // Make a note of the time we started.
+ long startTime = System.currentTimeMillis();
+
+ // Start a timer for the progress report.
+ Timer timer = new Timer();
+ TimerTask progressTask = new ProgressTask();
+ timer.scheduleAtFixedRate(progressTask, progressInterval,
+ progressInterval);
+
+ // Create the LDIF writer.
+ LDIFWriter ldifWriter;
+ try
+ {
+ ldifWriter = new LDIFWriter(exportConfig);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ Message message =
+ ERR_BACKEND_CANNOT_CREATE_LDIF_WRITER.get(String.valueOf(e));
+ throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+ message, e);
+ }
+
+ exportRootChanges(exportContainers, exportConfig, ldifWriter);
+
+ // Iterate through the containers.
+ try
+ {
+ for (ReplicationCache exportContainer : exportContainers)
+ {
+ exportContainer(exportContainer, exportConfig, ldifWriter);
+ }
+ }
+ finally
+ {
+ timer.cancel();
+
+ // Close the LDIF writer
+ try
+ {
+ ldifWriter.close();
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+ }
+
+ long finishTime = System.currentTimeMillis();
+ long totalTime = (finishTime - startTime);
+
+ float rate = 0;
+ if (totalTime > 0)
+ {
+ rate = 1000f*exportedCount / totalTime;
+ }
+
+ Message message = INFO_JEB_EXPORT_FINAL_STATUS.get(
+ exportedCount, skippedCount, totalTime/1000, rate);
+ logError(message);
+ }
+
+ /*
+ * Exports the root changes of the export, and one entry by domain.
+ */
+ private void exportRootChanges(List<ReplicationCache> exportContainers,
+ LDIFExportConfig exportConfig, LDIFWriter ldifWriter)
+ {
+ Map<AttributeType,List<Attribute>> attributes =
+ new HashMap<AttributeType,List<Attribute>>();
+ ArrayList<Attribute> ldapAttrList = new ArrayList<Attribute>();
+
+ AttributeType ocType=
+ DirectoryServer.getAttributeType("objectclass", true);
+ LinkedHashSet<AttributeValue> ocValues =
+ new LinkedHashSet<AttributeValue>();
+ ocValues.add(new AttributeValue(ocType, "top"));
+ ocValues.add(new AttributeValue(ocType, "domain"));
+ Attribute ocAttr = new Attribute(ocType, "objectclass", ocValues);
+ ldapAttrList.add(ocAttr);
+ attributes.put(ocType, ldapAttrList);
+
+ try
+ {
+ AddChangeRecordEntry changeRecord =
+ new AddChangeRecordEntry(DN.decode(EXPORT_BASE_DN),
+ attributes);
+ ldifWriter.writeChangeRecord(changeRecord);
+ }
+ catch (Exception e) {}
+
+ for (ReplicationCache exportContainer : exportContainers)
+ {
+ attributes.clear();
+ ldapAttrList.clear();
+
+ ldapAttrList.add(ocAttr);
+
+ AttributeType stateType=
+ DirectoryServer.getAttributeType("state", true);
+ LinkedHashSet<AttributeValue> stateValues =
+ new LinkedHashSet<AttributeValue>();
+ stateValues.add(new AttributeValue(stateType,
+ exportContainer.getDbServerState().toString()));
+ TRACER.debugInfo("State=" +
+ exportContainer.getDbServerState().toString());
+ Attribute stateAttr = new Attribute(ocType, "state", stateValues);
+ ldapAttrList.add(stateAttr);
+
+ AttributeType genidType=
+ DirectoryServer.getAttributeType("generation-id", true);
+ LinkedHashSet<AttributeValue> genidValues =
+ new LinkedHashSet<AttributeValue>();
+ genidValues.add(new AttributeValue(genidType,
+ String.valueOf(exportContainer.getGenerationId())+
+ exportContainer.getBaseDn()));
+ Attribute genidAttr = new Attribute(ocType, "generation-id", genidValues);
+ ldapAttrList.add(genidAttr);
+ attributes.put(genidType, ldapAttrList);
+
+ try
+ {
+ AddChangeRecordEntry changeRecord =
+ new AddChangeRecordEntry(DN.decode(
+ exportContainer.getBaseDn() + "," + EXPORT_BASE_DN),
+ attributes);
+ ldifWriter.writeChangeRecord(changeRecord);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ Message message = ERR_EXPORT_CANNOT_WRITE_ENTRY_TO_LDIF.get(
+ exportContainer.getBaseDn() + "," + EXPORT_BASE_DN,
+ String.valueOf(e));
+ logError(message);
+ }
+ }
+ }
+
+ /**
+ * Export the changes for a given ReplicationCache.
+ */
+ private void exportContainer(ReplicationCache rc,
+ LDIFExportConfig exportConfig, LDIFWriter ldifWriter)
+ {
+ StringBuilder buffer = new StringBuilder();
+
+ // Walk through the servers
+ for (Short serverId : rc.getServers())
+ {
+ ReplicationIterator ri = rc.getChangelogIterator(serverId,
+ null);
+
+ if (ri == null)
+ break;
+
+ // Walk through the changes
+ while (ri.getChange() != null)
+ {
+ UpdateMessage msg = ri.getChange();
+ exportChange(buffer, msg, exportConfig, ldifWriter);
+ if (!ri.next())
+ break;
+ }
+ }
+ }
+
+ /**
+ * Export one change.
+ */
+ private void exportChange(StringBuilder buffer, UpdateMessage msg,
+ LDIFExportConfig exportConfig, LDIFWriter ldifWriter)
+ {
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ String dn = null;
+ try
+ {
+ if (msg instanceof AddMsg)
+ {
+ AddMsg addMsg = (AddMsg)msg;
+ AddOperation op = (AddOperation)msg.createOperation(conn);
+ dn = "puid=" + addMsg.getParentUid() + "," +
+ "changeNumber=" + msg.getChangeNumber().toString() + "," +
+ msg.getDn() +","+ "dc=replicationChanges";
+
+ Map<AttributeType,List<Attribute>> attributes =
+ new HashMap<AttributeType,List<Attribute>>();
+
+ for (RawAttribute a : op.getRawAttributes())
+ {
+ Attribute attr = a.toAttribute();
+ AttributeType attrType = attr.getAttributeType();
+ List<Attribute> attrs = attributes.get(attrType);
+ if (attrs == null)
+ {
+ attrs = new ArrayList<Attribute>(1);
+ attrs.add(attr);
+ attributes.put(attrType, attrs);
+ }
+ else
+ {
+ attrs.add(attr);
+ }
+ }
+ AddChangeRecordEntry changeRecord =
+ new AddChangeRecordEntry(DN.decode(dn), attributes);
+ ldifWriter.writeChangeRecord(changeRecord);
+ }
+ else if (msg instanceof DeleteMsg)
+ {
+ DeleteMsg delMsg = (DeleteMsg)msg;
+ // DN
+ dn = "uuid=" + msg.getUniqueId() + "," +
+ "changeNumber=" + delMsg.getChangeNumber().toString()+ "," +
+ msg.getDn() +","+
+ "dc=replicationChanges";
+ DeleteChangeRecordEntry changeRecord =
+ new DeleteChangeRecordEntry(DN.decode(dn));
+ ldifWriter.writeChangeRecord(changeRecord);
+ }
+ else if (msg instanceof ModifyMsg)
+ {
+ ModifyOperation op = (ModifyOperation)msg.createOperation(conn);
+ // DN
+ dn = "uuid=" + msg.getUniqueId() + "," +
+ "changeNumber=" + msg.getChangeNumber().toString()+ "," +
+ msg.getDn() +","+
+ "dc=replicationChanges";
+ op.setInternalOperation(true);
+ ModifyChangeRecordEntry changeRecord =
+ new ModifyChangeRecordEntry(DN.decode(dn),
+ op.getRawModifications());
+ ldifWriter.writeChangeRecord(changeRecord);
+ }
+ else if (msg instanceof ModifyDNMsg)
+ {
+ ModifyDNOperation op = (ModifyDNOperation)msg.createOperation(conn);
+ // DN
+ dn = "uuid=" + msg.getUniqueId() + "," +
+ "changeNumber=" + msg.getChangeNumber().toString()+ "," +
+ msg.getDn() +","+
+ "dc=replicationChanges";
+ op.setInternalOperation(true);
+ ModifyDNChangeRecordEntry changeRecord =
+ new ModifyDNChangeRecordEntry(DN.decode(dn),
+ op.getNewRDN(), op.deleteOldRDN(),
+ op.getNewSuperior());
+ ldifWriter.writeChangeRecord(changeRecord);
+ }
+ this.exportedCount++;
+ }
+ catch (Exception e)
+ {
+ this.skippedCount++;
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ Message message = ERR_EXPORT_CANNOT_WRITE_ENTRY_TO_LDIF.get(
+ dn, String.valueOf(e));
+ logError(message);
+
+ }
}
/**
@@ -490,4 +840,54 @@
{
this.server = server;
}
+
+ /**
+ * This class reports progress of the export job at fixed intervals.
+ */
+ class ProgressTask extends TimerTask
+ {
+ /**
+ * The number of entries that had been exported at the time of the
+ * previous progress report.
+ */
+ private long previousCount = 0;
+
+ /**
+ * The time in milliseconds of the previous progress report.
+ */
+ private long previousTime;
+
+ /**
+ * Create a new export progress task.
+ */
+ public ProgressTask()
+ {
+ previousTime = System.currentTimeMillis();
+ }
+
+ /**
+ * The action to be performed by this timer task.
+ */
+ public void run()
+ {
+ long latestCount = exportedCount;
+ long deltaCount = (latestCount - previousCount);
+ long latestTime = System.currentTimeMillis();
+ long deltaTime = latestTime - previousTime;
+
+ if (deltaTime == 0)
+ {
+ return;
+ }
+
+ float rate = 1000f*deltaCount / deltaTime;
+
+ Message message =
+ INFO_JEB_EXPORT_PROGRESS_REPORT.get(latestCount, skippedCount, rate);
+ logError(message);
+
+ previousCount = latestCount;
+ previousTime = latestTime;
+ }
+ };
}
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 8061015..7a445bf 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
@@ -43,6 +43,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -940,4 +941,17 @@
{
// Nothing is needed at the moment
}
+
+ /**
+ * Returns an iterator on the list of replicationCache.
+ * Returns null if none.
+ * @return the iterator.
+ */
+ public Iterator<ReplicationCache> getCacheIterator()
+ {
+ if (!baseDNs.isEmpty())
+ return baseDNs.values().iterator();
+ else
+ return null;
+ }
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerWriter.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerWriter.java
index b051836..3fd0503 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerWriter.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerWriter.java
@@ -122,7 +122,7 @@
"In " + replicationCache.getReplicationServer().
getMonitorInstanceName() +
", writer to " + this.handler.getMonitorInstanceName() +
- " publishes" + update.toString() +
+ " publishes msg=" + update.toString() +
" refgenId=" + referenceGenerationId +
" server=" + handler.getServerId() +
" generationId=" + handler.getGenerationId());
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 a09b5e7..566dda4 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
@@ -855,8 +855,9 @@
{
fail("No log messages were written to the task entry on a failed task");
}
- else
- {
+ }
+ if (logMessages.size() != 0)
+ {
TRACER.debugInfo(logMessages.get(0));
if (expectedMessage != null)
{
@@ -864,7 +865,6 @@
assertTrue(logMessages.get(0).indexOf(
expectedMessage.toString())>0);
}
- }
}
assertEquals(taskState, expectedTaskState, "Task State:" + taskState +
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 a16d3f8..5d350b9 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
@@ -26,13 +26,12 @@
*/
package org.opends.server.replication.server;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.fail;
-
import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
import static org.opends.server.loggers.debug.DebugLogger.getTracer;
-import static org.opends.server.replication.protocol.OperationContext.*;
+import static org.opends.server.replication.protocol.OperationContext.SYNCHROCONTEXT;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
import java.io.File;
import java.net.InetAddress;
@@ -54,14 +53,27 @@
import org.opends.server.replication.common.ChangeNumberGenerator;
import org.opends.server.replication.common.ServerState;
import org.opends.server.replication.plugin.ReplicationBroker;
-import org.opends.server.replication.protocol.*;
+import org.opends.server.replication.protocol.AddMsg;
+import org.opends.server.replication.protocol.DeleteMsg;
+import org.opends.server.replication.protocol.ModifyDNMsg;
+import org.opends.server.replication.protocol.ModifyDnContext;
+import org.opends.server.replication.protocol.ModifyMsg;
+import org.opends.server.replication.protocol.ProtocolSession;
+import org.opends.server.replication.protocol.ProtocolVersion;
+import org.opends.server.replication.protocol.ReplServerStartMessage;
+import org.opends.server.replication.protocol.ReplSessionSecurity;
+import org.opends.server.replication.protocol.ReplicationMessage;
+import org.opends.server.replication.protocol.ServerStartMessage;
+import org.opends.server.replication.protocol.UpdateMessage;
+import org.opends.server.replication.protocol.WindowMessage;
+import org.opends.server.replication.protocol.WindowProbe;
import org.opends.server.types.Attribute;
import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryConfig;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
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;
@@ -995,6 +1007,56 @@
debugInfo("Ending backupRestore");
}
+ /*
+ * Test export of the Replication server backend
+ * - Creates 2 brokers connecting to the replication for 2 differents baseDN
+ * - Make these brokers publish changes to the replication server
+ * - Launch a full export
+ * - Launch a partial export on one of the 2 domains
+ */
+ @Test(enabled=true)
+ public void exportBackend() throws Exception
+ {
+ debugInfo("Starting exportBackend");
+
+ ReplicationBroker server1 = null;
+ ReplicationBroker server2 = null;
+
+ try {
+ server1 = openReplicationSession(
+ DN.decode("dc=example,dc=com"), (short) 1, 100, replicationServerPort,
+ 1000, true);
+ server2 = openReplicationSession(
+ DN.decode("dc=example2,dc=com"), (short) 2, 100, replicationServerPort,
+ 1000, true);
+ }
+ catch(Exception e) {}
+
+ debugInfo("Publish changes");
+ List<UpdateMessage> msgs = createChanges("dc=example,dc=com", (short)1);
+ for(UpdateMessage msg : msgs )
+ {
+ server1.publish(msg);
+ }
+ List<UpdateMessage> msgs2 = createChanges("dc=example2,dc=com", (short)2);
+ for(UpdateMessage msg : msgs2 )
+ {
+ server2.publish(msg);
+ }
+
+ debugInfo("Export all");
+ Entry exportTask = createExportAllTask();
+ addTask(exportTask, ResultCode.SUCCESS, null);
+ waitTaskState(exportTask, TaskState.COMPLETED_SUCCESSFULLY, null);
+
+ debugInfo("Export domain");
+ exportTask = createExportDomainTask("dc=example2,dc=com");
+ addTask(exportTask, ResultCode.SUCCESS, null);
+ waitTaskState(exportTask, TaskState.COMPLETED_SUCCESSFULLY, null);
+
+ debugInfo("Ending export");
+ }
+
private Entry createBackupTask()
throws Exception
{
@@ -1022,4 +1084,118 @@
"ds-backup-directory-path: bak" + File.separator +
"replicationChanges");
}
+
+ private Entry createExportAllTask()
+ throws Exception
+ {
+ String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
+ String path = buildRoot + File.separator + "build" +
+ File.separator + "unit-tests" + File.separator +
+ "package"+ File.separator + "exportLDIF.ldif";
+ return TestCaseUtils.makeEntry(
+ "dn: ds-task-id=" + UUID.randomUUID() + ",cn=Scheduled Tasks,cn=Tasks",
+ "objectclass: top",
+ "objectclass: ds-task",
+ "objectclass: ds-task-export",
+ "ds-task-class-name: org.opends.server.tasks.ExportTask",
+ "ds-task-export-ldif-file: " + path,
+ "ds-task-export-backend-id: replicationChanges",
+ "ds-task-export-include-branch: dc=replicationChanges");
+ }
+
+ private Entry createExportDomainTask(String suffix)
+ throws Exception
+ {
+ String root = suffix.substring(suffix.indexOf('=')+1, suffix.indexOf(','));
+ String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
+ String path = buildRoot + File.separator + "build" +
+ File.separator + "unit-tests" + File.separator +
+ "package"+ File.separator + "exportLDIF" + root +".ldif";
+ return TestCaseUtils.makeEntry(
+ "dn: ds-task-id=" + UUID.randomUUID() + ",cn=Scheduled Tasks,cn=Tasks",
+ "objectclass: top",
+ "objectclass: ds-task",
+ "objectclass: ds-task-export",
+ "ds-task-class-name: org.opends.server.tasks.ExportTask",
+ "ds-task-export-ldif-file: " + path,
+ "ds-task-export-backend-id: replicationChanges",
+ "ds-task-export-include-branch: "+suffix+",dc=replicationChanges");
+ }
+
+ private List<UpdateMessage> createChanges(String suffix, short serverId)
+ {
+ List<UpdateMessage> l = new ArrayList<UpdateMessage>();
+ long time = TimeThread.getTime();
+ int ts = 1;
+ ChangeNumber cn;
+
+ try
+ {
+ String user1entryUUID = "33333333-3333-3333-3333-333333333333";
+ String baseUUID = "22222222-2222-2222-2222-222222222222";
+
+ // - Add
+ String lentry = new String("dn: "+suffix+"\n"
+ + "objectClass: top\n"
+ + "objectClass: domain\n"
+ + "entryUUID: 11111111-1111-1111-1111-111111111111\n");
+ Entry entry = TestCaseUtils.entryFromLdifString(lentry);
+ cn = new ChangeNumber(time, ts++, serverId);
+ AddMsg addMsg = new AddMsg(cn, "o=test,"+suffix,
+ user1entryUUID, baseUUID, entry.getObjectClassAttribute(), entry
+ .getAttributes(), new ArrayList<Attribute>());
+ l.add(addMsg);
+
+ // - Add
+ String luentry = new String(
+ "dn: uid=new person,ou=People,"+suffix+"\n"
+ + "objectClass: top\n"
+ + "objectclass: person\n"
+ + "objectclass: organizationalPerson\n"
+ + "objectclass: inetOrgPerson\n"
+ + "cn: Fiona Jensen\n"
+ + "sn: Jensen\n"
+ + "uid: new person\n"
+ + "telephonenumber: +1 408 555 1212\n"
+ + "entryUUID: " + user1entryUUID +"\n");
+ Entry uentry = TestCaseUtils.entryFromLdifString(luentry);
+ cn = new ChangeNumber(time, ts++, serverId);
+ AddMsg addMsg2 = new AddMsg(
+ cn,
+ "uid=new person,ou=People,"+suffix,
+ user1entryUUID,
+ baseUUID,
+ uentry.getObjectClassAttribute(),
+ uentry.getAttributes(),
+ new ArrayList<Attribute>());
+ l.add(addMsg2);
+
+ // - Modify
+ Attribute attr1 = new Attribute("description", "new value");
+ Modification mod1 = new Modification(ModificationType.REPLACE, attr1);
+ List<Modification> mods = new ArrayList<Modification>();
+ mods.add(mod1);
+ cn = new ChangeNumber(time, ts++, serverId);
+ DN dn = DN.decode("o=test,"+suffix);
+ ModifyMsg modMsg = new ModifyMsg(cn, dn,
+ mods, "fakeuniqueid");
+ l.add(modMsg);
+
+ // Modify DN
+ cn = new ChangeNumber(time, ts++, serverId);
+ ModifyDNMsg modDnMsg = new ModifyDNMsg(
+ "uid=new person,ou=People,"+suffix, cn,
+ user1entryUUID, baseUUID, false,
+ "uid=wrong, ou=people,"+suffix,
+ "uid=newrdn");
+ l.add(modDnMsg);
+
+ // Del
+ cn = new ChangeNumber(time, ts++, serverId);
+ DeleteMsg delMsg = new DeleteMsg("o=test,"+suffix, cn, "uid");
+ l.add(delMsg);
+ }
+ catch(Exception e) {};
+ return l;
+ }
}
--
Gitblit v1.10.0