From c64a67b3d0b51743d9f2a2bf110cb365b8b104af Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Mon, 26 Aug 2013 08:41:18 +0000
Subject: [PATCH] OPENDJ-1116 Introduce abstraction for the changelog DB
---
opends/src/server/org/opends/server/replication/server/ReplicationServer.java | 168 +++++-----
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java | 4
opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogDB.java | 150 +++++++++
opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogDBIterator.java | 78 ++++
opends/src/server/org/opends/server/replication/server/ECLServerHandler.java | 68 ++--
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/changelog/je/DbHandlerTest.java | 46 --
opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDB.java | 7
opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbHandler.java | 203 ++++--------
opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbIterator.java | 40 -
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbHandlerTest.java | 132 +++----
opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java | 39 +-
11 files changed, 512 insertions(+), 423 deletions(-)
diff --git a/opends/src/server/org/opends/server/replication/server/ECLServerHandler.java b/opends/src/server/org/opends/server/replication/server/ECLServerHandler.java
index d6fc6f9..67b977c 100644
--- a/opends/src/server/org/opends/server/replication/server/ECLServerHandler.java
+++ b/opends/src/server/org/opends/server/replication/server/ECLServerHandler.java
@@ -41,9 +41,9 @@
import org.opends.server.replication.common.ServerState;
import org.opends.server.replication.common.ServerStatus;
import org.opends.server.replication.protocol.*;
+import org.opends.server.replication.server.changelog.api.ChangelogDB;
+import org.opends.server.replication.server.changelog.api.ChangelogDBIterator;
import org.opends.server.replication.server.changelog.api.ChangelogException;
-import org.opends.server.replication.server.changelog.je.DraftCNDbHandler;
-import org.opends.server.replication.server.changelog.je.DraftCNDbIterator;
import org.opends.server.types.*;
import org.opends.server.util.ServerConstants;
@@ -66,8 +66,8 @@
*/
private String operationId;
- /** Iterator on the draftCN database. */
- private DraftCNDbIterator draftCNDbIter = null;
+ /** Iterator on the changelogDB database. */
+ private ChangelogDBIterator changelogDBIter = null;
private boolean draftCompat = false;
/**
@@ -99,8 +99,7 @@
* currently processed (thus becoming the "current" cookie just
* before the change is returned.
*/
- private MultiDomainServerState previousCookie =
- new MultiDomainServerState();
+ private MultiDomainServerState previousCookie = new MultiDomainServerState();
/**
* Specifies the excluded DNs (like cn=admin, ...).
*/
@@ -563,16 +562,16 @@
* @throws DirectoryException
* if a database problem occurred
*/
- private String findCookie(int startDraftCN) throws ChangelogException,
+ private String findCookie(final int startDraftCN) throws ChangelogException,
DirectoryException
{
- DraftCNDbHandler draftCNDb = replicationServer.getDraftCNDbHandler();
+ ChangelogDB changelogDB = replicationServer.getChangelogDB();
if (startDraftCN <= 1)
{
// Request filter DOES NOT contain any firstDraftCN
// So we'll generate from the first DraftCN in the DraftCNdb
- if (draftCNDb.isEmpty())
+ if (changelogDB.isEmpty())
{
// FIXME JNR if we find a way to make draftCNDb.isEmpty() a non costly
// operation, then I think we can move this check to the top of this
@@ -581,21 +580,20 @@
return null;
}
- final int firstKey = draftCNDb.getFirstKey();
- String crossDomainStartState = draftCNDb.getValue(firstKey);
- draftCNDbIter = draftCNDb.generateIterator(firstKey);
+ final int firstKey = changelogDB.getFirstKey();
+ String crossDomainStartState = changelogDB.getPreviousCookie(firstKey);
+ changelogDBIter = changelogDB.generateIterator(firstKey);
return crossDomainStartState;
}
// Request filter DOES contain a startDraftCN
// Read the draftCNDb to see whether it contains startDraftCN
- final int startDraftCNKey = startDraftCN;
- String crossDomainStartState = draftCNDb.getValue(startDraftCNKey);
+ String crossDomainStartState = changelogDB.getPreviousCookie(startDraftCN);
if (crossDomainStartState != null)
{
// found the provided startDraftCN, let's return it
- draftCNDbIter = draftCNDb.generateIterator(startDraftCNKey);
+ changelogDBIter = changelogDB.generateIterator(startDraftCN);
return crossDomainStartState;
}
@@ -614,10 +612,10 @@
// the DB, let's use the lower limit.
if (startDraftCN < firstDraftCN)
{
- crossDomainStartState = draftCNDb.getValue(firstDraftCN);
+ crossDomainStartState = changelogDB.getPreviousCookie(firstDraftCN);
if (crossDomainStartState != null)
{
- draftCNDbIter = draftCNDb.generateIterator(firstDraftCN);
+ changelogDBIter = changelogDB.generateIterator(firstDraftCN);
return crossDomainStartState;
}
@@ -629,15 +627,15 @@
{
// startDraftCN is between first and potential last and has never
// been returned yet
- if (draftCNDb.isEmpty())
+ if (changelogDB.isEmpty())
{
isEndOfDraftCNReached = true;
return null;
}
- final int lastKey = draftCNDb.getLastKey();
- crossDomainStartState = draftCNDb.getValue(lastKey);
- draftCNDbIter = draftCNDb.generateIterator(lastKey);
+ final int lastKey = changelogDB.getLastKey();
+ crossDomainStartState = changelogDB.getPreviousCookie(lastKey);
+ changelogDBIter = changelogDB.generateIterator(lastKey);
return crossDomainStartState;
// TODO:ECL ... ok we'll start from the end of the draftCNDb BUT ...
@@ -895,7 +893,7 @@
public void shutdown()
{
if (debugEnabled())
- TRACER.debugInfo(this + " shutdown()" + draftCNDbIter);
+ TRACER.debugInfo(this + " shutdown()");
releaseIterator();
for (DomainContext domainCtxt : domainCtxts) {
if (!domainCtxt.unRegisterHandler()) {
@@ -911,10 +909,10 @@
private void releaseIterator()
{
- if (this.draftCNDbIter != null)
+ if (this.changelogDBIter != null)
{
- this.draftCNDbIter.releaseCursor();
- this.draftCNDbIter = null;
+ this.changelogDBIter.close();
+ this.changelogDBIter = null;
}
}
@@ -1374,8 +1372,8 @@
// the next change from the DraftCN db
- ChangeNumber cnFromDraftCNDb = draftCNDbIter.getChangeNumber();
- String dnFromDraftCNDb = draftCNDbIter.getBaseDN();
+ ChangeNumber cnFromDraftCNDb = changelogDBIter.getChangeNumber();
+ String dnFromDraftCNDb = changelogDBIter.getBaseDN();
if (debugEnabled())
TRACER.debugInfo("getNextECLUpdate generating draftCN "
@@ -1390,10 +1388,10 @@
{
if (debugEnabled())
TRACER.debugInfo("getNextECLUpdate generating draftCN "
- + " assigning draftCN=" + draftCNDbIter.getDraftCN()
+ + " assigning draftCN=" + changelogDBIter.getDraftCN()
+ " to change=" + oldestChange);
- oldestChange.setDraftChangeNumber(draftCNDbIter.getDraftCN());
+ oldestChange.setDraftChangeNumber(changelogDBIter.getDraftCN());
return true;
}
@@ -1422,12 +1420,12 @@
+ " will skip " + cnFromDraftCNDb
+ " and read next change from the DraftCNDb.");
- isEndOfDraftCNReached = !draftCNDbIter.next();
+ isEndOfDraftCNReached = !changelogDBIter.next();
if (debugEnabled())
TRACER.debugInfo("getNextECLUpdate generating draftCN "
- + " has skipped to " + " sn=" + draftCNDbIter.getDraftCN()
- + " cn=" + draftCNDbIter.getChangeNumber()
+ + " has skipped to " + " sn=" + changelogDBIter.getDraftCN()
+ + " cn=" + changelogDBIter.getChangeNumber()
+ " End of draftCNDb ?" + isEndOfDraftCNReached);
}
catch (ChangelogException e)
@@ -1456,10 +1454,10 @@
// generate a new draftCN and assign to this change
change.setDraftChangeNumber(replicationServer.getNewDraftCN());
- // store in DraftCNdb the pair
+ // store in changelogDB the pair
// (DraftCN of the current change, state before this change)
- DraftCNDbHandler draftCNDb = replicationServer.getDraftCNDbHandler();
- draftCNDb.add(
+ ChangelogDB changelogDB = replicationServer.getChangelogDB();
+ changelogDB.add(
change.getDraftChangeNumber(),
previousCookie.toString(),
change.getBaseDN(),
diff --git a/opends/src/server/org/opends/server/replication/server/ReplicationServer.java b/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
index 01afb43..7b16799 100644
--- a/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
+++ b/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
@@ -52,6 +52,7 @@
import org.opends.server.replication.common.*;
import org.opends.server.replication.plugin.MultimasterReplication;
import org.opends.server.replication.protocol.*;
+import org.opends.server.replication.server.changelog.api.ChangelogDB;
import org.opends.server.replication.server.changelog.api.ChangelogException;
import org.opends.server.replication.server.changelog.je.DbHandler;
import org.opends.server.replication.server.changelog.je.DraftCNDbHandler;
@@ -65,6 +66,7 @@
import static org.opends.messages.ReplicationMessages.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.types.ResultCode.*;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
@@ -143,23 +145,22 @@
private long monitoringPublisherPeriod = 3000;
/**
- * The handler of the draft change numbers database, the database used to
- * store the relation between a draft change number ('seqnum') and the
- * associated cookie.
+ * The handler of the changelog database, the database stores the relation
+ * between a draft change number ('seqnum') and the associated cookie.
* <p>
- * Guarded by draftCNLock
+ * Guarded by changelogDBLock
*/
- private DraftCNDbHandler draftCNDbHandler;
+ private ChangelogDB changelogDB;
/**
* The last value generated of the draft change number.
* <p>
- * Guarded by draftCNLock
+ * Guarded by changelogDBLock
**/
private int lastGeneratedDraftCN = 0;
- /** Used for protecting draft CN related state. */
- private final Object draftCNLock = new Object();
+ /** Used for protecting changelogDB related state. */
+ private final Object changelogDBLock = new Object();
/**
* The tracer object for the debug logger.
@@ -183,7 +184,7 @@
private long domainTicket = 0L;
/** BaseDNs excluded for ECL. */
- private Collection<String> excludedBaseDNs = new ArrayList<String>();
+ private Set<String> excludedBaseDNs = new HashSet<String>();
/**
* The weight affected to the replication server.
@@ -470,7 +471,7 @@
private Set<String> getConnectedRSUrls(ReplicationServerDomain domain)
{
- Set<String> results = new LinkedHashSet<String>();
+ Set<String> results = new HashSet<String>();
for (ReplicationServerHandler rsHandler : domain.getConnectedRSs().values())
{
results.add(normalizeServerURL(rsHandler.getServerAddressURL()));
@@ -714,11 +715,11 @@
eclwe.finalizeWorkflowElement();
}
- synchronized (draftCNLock)
+ synchronized (changelogDBLock)
{
- if (draftCNDbHandler != null)
+ if (changelogDB != null)
{
- draftCNDbHandler.shutdown();
+ changelogDB.shutdown();
}
}
}
@@ -900,42 +901,39 @@
{
dbEnv.clearGenerationId(baseDn);
}
- catch (Exception e)
+ catch (Exception ignored)
{
- // Ignore.
if (debugEnabled())
{
- TRACER.debugCaught(DebugLogLevel.WARNING, e);
+ TRACER.debugCaught(DebugLogLevel.WARNING, ignored);
}
}
- synchronized (draftCNLock)
+ synchronized (changelogDBLock)
{
- if (draftCNDbHandler != null)
+ if (changelogDB != null)
{
try
{
- draftCNDbHandler.clear(baseDn);
+ changelogDB.clear(baseDn);
}
- catch (Exception e)
+ catch (Exception ignored)
{
- // Ignore.
if (debugEnabled())
{
- TRACER.debugCaught(DebugLogLevel.WARNING, e);
+ TRACER.debugCaught(DebugLogLevel.WARNING, ignored);
}
}
try
{
- lastGeneratedDraftCN = draftCNDbHandler.getLastKey();
+ lastGeneratedDraftCN = changelogDB.getLastKey();
}
- catch (Exception e)
+ catch (Exception ignored)
{
- // Ignore.
if (debugEnabled())
{
- TRACER.debugCaught(DebugLogLevel.WARNING, e);
+ TRACER.debugCaught(DebugLogLevel.WARNING, ignored);
}
}
}
@@ -1352,12 +1350,10 @@
public void processExportBegin(Backend backend, LDIFExportConfig config)
{
if (debugEnabled())
- TRACER.debugInfo("RS " +getMonitorInstanceName()+
- " Export starts");
+ TRACER.debugInfo("RS " + getMonitorInstanceName() + " Export starts");
if (backend.getBackendID().equals(backendId))
{
// Retrieves the backend related to this replicationServerDomain
- // backend =
ReplicationBackend b =
(ReplicationBackend)DirectoryServer.getBackend(backendId);
b.setServer(this);
@@ -1394,38 +1390,36 @@
rsd.clearDbs();
}
- synchronized (draftCNLock)
+ synchronized (changelogDBLock)
{
- if (draftCNDbHandler != null)
+ if (changelogDB != null)
{
try
{
- draftCNDbHandler.clear();
+ changelogDB.clear();
}
- catch (Exception e)
+ catch (Exception ignored)
{
- // Ignore.
if (debugEnabled())
{
- TRACER.debugCaught(DebugLogLevel.WARNING, e);
+ TRACER.debugCaught(DebugLogLevel.WARNING, ignored);
}
}
try
{
- draftCNDbHandler.shutdown();
+ changelogDB.shutdown();
}
- catch (Exception e)
+ catch (Exception ignored)
{
- // Ignore.
if (debugEnabled())
{
- TRACER.debugCaught(DebugLogLevel.WARNING, e);
+ TRACER.debugCaught(DebugLogLevel.WARNING, ignored);
}
}
lastGeneratedDraftCN = 0;
- draftCNDbHandler = null;
+ changelogDB = null;
}
}
}
@@ -1614,67 +1608,70 @@
ChangeNumber eligibleCN = null;
for (ReplicationServerDomain domain : getReplicationServerDomains())
{
- if ((excludedBaseDNs != null) &&
- excludedBaseDNs.contains(domain.getBaseDn()))
+ if (contains(excludedBaseDNs, domain.getBaseDn()))
continue;
- ChangeNumber domainEligibleCN = domain.getEligibleCN();
- String dates = "";
- if (domainEligibleCN != null)
+ final ChangeNumber domainEligibleCN = domain.getEligibleCN();
+ if (eligibleCN == null
+ || (domainEligibleCN != null && domainEligibleCN.older(eligibleCN)))
{
- if ((eligibleCN == null) || (domainEligibleCN.older(eligibleCN)))
- {
- eligibleCN = domainEligibleCN;
- }
- dates = new Date(domainEligibleCN.getTime()).toString();
+ eligibleCN = domainEligibleCN;
}
- debugLog += "[dn=" + domain.getBaseDn()
- + "] [eligibleCN=" + domainEligibleCN + ", " + dates + "]";
+
+ if (debugEnabled())
+ {
+ final String dates = domainEligibleCN == null ?
+ "" : new Date(domainEligibleCN.getTime()).toString();
+ debugLog += "[baseDN=" + domain.getBaseDn()
+ + "] [eligibleCN=" + domainEligibleCN + ", " + dates + "]";
+ }
}
- if (eligibleCN==null)
+ if (eligibleCN==null )
{
eligibleCN = new ChangeNumber(TimeThread.getTime(), 0, 0);
}
- if (debugEnabled())
+ if (debugEnabled()) {
TRACER.debugInfo("In " + this + " getEligibleCN() ends with " +
" the following domainEligibleCN for each domain :" + debugLog +
" thus CrossDomainEligibleCN=" + eligibleCN +
" ts=" + new Date(eligibleCN.getTime()).toString());
-
+ }
return eligibleCN;
}
-
+ private boolean contains(Set<String> col, String elem)
+ {
+ return col != null && col.contains(elem);
+ }
/**
- * Get or create a handler on a Db on DraftCN for external changelog.
+ * Get (or create) a handler on the ChangelogDB for external changelog.
*
* @return the handler.
* @throws DirectoryException
* when needed.
*/
- public DraftCNDbHandler getDraftCNDbHandler() throws DirectoryException
+ public ChangelogDB getChangelogDB() throws DirectoryException
{
- synchronized (draftCNLock)
+ synchronized (changelogDBLock)
{
try
{
- if (draftCNDbHandler == null)
+ if (changelogDB == null)
{
- draftCNDbHandler = new DraftCNDbHandler(this, this.dbEnv);
+ changelogDB = new DraftCNDbHandler(this, this.dbEnv);
lastGeneratedDraftCN = getLastDraftChangeNumber();
}
- return draftCNDbHandler;
+ return changelogDB;
}
catch (Exception e)
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
MessageBuilder mb = new MessageBuilder();
mb.append(ERR_DRAFT_CHANGENUMBER_DATABASE.get(""));
- throw new DirectoryException(ResultCode.OPERATIONS_ERROR,
- mb.toMessage(), e);
+ throw new DirectoryException(OPERATIONS_ERROR, mb.toMessage(), e);
}
}
}
@@ -1685,11 +1682,11 @@
*/
public int getFirstDraftChangeNumber()
{
- synchronized (draftCNLock)
+ synchronized (changelogDBLock)
{
- if (draftCNDbHandler != null)
+ if (changelogDB != null)
{
- return draftCNDbHandler.getFirstKey();
+ return changelogDB.getFirstKey();
}
return 0;
}
@@ -1701,11 +1698,11 @@
*/
public int getLastDraftChangeNumber()
{
- synchronized (draftCNLock)
+ synchronized (changelogDBLock)
{
- if (draftCNDbHandler != null)
+ if (changelogDB != null)
{
- return draftCNDbHandler.getLastKey();
+ return changelogDB.getLastKey();
}
return 0;
}
@@ -1717,7 +1714,7 @@
*/
public int getNewDraftCN()
{
- synchronized (draftCNLock)
+ synchronized (changelogDBLock)
{
return ++lastGeneratedDraftCN;
}
@@ -1756,12 +1753,11 @@
*/
int lastDraftCN;
- Boolean dbEmpty = false;
- Long newestDate = 0L;
- DraftCNDbHandler draftCNDbH = getDraftCNDbHandler();
+ boolean dbEmpty = false;
+ long newestDate = 0L;
+ ChangelogDB changelogDB = getChangelogDB();
- // Get the first DraftCN from the DraftCNdb
- int firstDraftCN = draftCNDbH.getFirstKey();
+ int firstDraftCN = changelogDB.getFirstKey();
Map<String,ServerState> domainsServerStateForLastSeqnum = null;
ChangeNumber changeNumberForLastSeqnum = null;
String domainForLastSeqnum = null;
@@ -1773,12 +1769,11 @@
}
else
{
- // Get the last DraftCN from the DraftCNdb
- lastDraftCN = draftCNDbH.getLastKey();
+ lastDraftCN = changelogDB.getLastKey();
// Get the generalized state associated with the current last DraftCN
// and initializes from it the startStates table
- String lastSeqnumGenState = draftCNDbH.getValue(lastDraftCN);
+ String lastSeqnumGenState = changelogDB.getPreviousCookie(lastDraftCN);
if ((lastSeqnumGenState != null) && (lastSeqnumGenState.length()>0))
{
domainsServerStateForLastSeqnum = MultiDomainServerState.
@@ -1786,16 +1781,16 @@
}
// Get the changeNumber associated with the current last DraftCN
- changeNumberForLastSeqnum = draftCNDbH.getChangeNumber(lastDraftCN);
+ changeNumberForLastSeqnum = changelogDB.getChangeNumber(lastDraftCN);
// Get the domain associated with the current last DraftCN
- domainForLastSeqnum = draftCNDbH.getBaseDN(lastDraftCN);
+ domainForLastSeqnum = changelogDB.getBaseDN(lastDraftCN);
}
// Domain by domain
for (ReplicationServerDomain rsd : getReplicationServerDomains())
{
- if (excludedBaseDNs.contains(rsd.getBaseDn()))
+ if (contains(excludedBaseDNs, rsd.getBaseDn()))
continue;
// for this domain, have the state in the replchangelog
@@ -1860,15 +1855,12 @@
{
disableEligibility(excludedBaseDNs);
+ // Initialize start state for all running domains with empty state
MultiDomainServerState result = new MultiDomainServerState();
- // Initialize start state for all running domains with empty state
for (ReplicationServerDomain rsd : getReplicationServerDomains())
{
- if ((excludedBaseDNs != null)
- && (excludedBaseDNs.contains(rsd.getBaseDn())))
- continue;
-
- if (rsd.getDbServerState().isEmpty())
+ if (contains(excludedBaseDNs, rsd.getBaseDn())
+ || rsd.getDbServerState().isEmpty())
continue;
result.update(rsd.getBaseDn(), rsd.getEligibleState(getEligibleCN()));
diff --git a/opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogDB.java b/opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogDB.java
new file mode 100644
index 0000000..f5382d7
--- /dev/null
+++ b/opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogDB.java
@@ -0,0 +1,150 @@
+/*
+ * 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
+ *
+ *
+ * Copyright 2013 ForgeRock AS
+ */
+package org.opends.server.replication.server.changelog.api;
+
+import org.opends.server.replication.common.ChangeNumber;
+
+/**
+ * This class stores the changelog information into a database.
+ *
+ * @see <a href=
+ * "https://wikis.forgerock.org/confluence/display/OPENDJ/OpenDJ+Domain+Names"
+ * >OpenDJ Domain Names</a> for more information about the changelog.
+ */
+public interface ChangelogDB extends Runnable
+{
+
+ /**
+ * Get the CN associated to a provided draft change number.
+ *
+ * @param draftCN
+ * the provided draft change number.
+ * @return the associated CN, null when none.
+ */
+ public ChangeNumber getChangeNumber(int draftCN);
+
+ /**
+ * Get the baseDN associated to a provided draft change number.
+ *
+ * @param draftCN
+ * the provided draft change number.
+ * @return the baseDN, null when none.
+ */
+ public String getBaseDN(int draftCN);
+
+ /**
+ * Get the previous cookie associated to a provided draft change number.
+ *
+ * @param draftCN
+ * the provided draft change number.
+ * @return the previous cookie, null when none.
+ */
+ String getPreviousCookie(int draftCN);
+
+ /**
+ * Get the firstChange.
+ *
+ * @return Returns the first draftCN in the DB.
+ */
+ int getFirstKey();
+
+ /**
+ * Get the lastChange.
+ *
+ * @return Returns the last draftCN in the DB
+ */
+ int getLastKey();
+
+ /**
+ * Add an update to the list of messages that must be saved to the db managed
+ * by this db handler.
+ * <p>
+ * This method is blocking if the size of the list of message is larger than
+ * its maximum.
+ *
+ * @param draftCN
+ * The draft change number for this record in the db.
+ * @param previousCookie
+ * The value of the previous cookie.
+ * @param baseDN
+ * The associated baseDN.
+ * @param changeNumber
+ * The associated replication change number.
+ */
+ void add(int draftCN, String previousCookie, String baseDN,
+ ChangeNumber changeNumber);
+
+ /**
+ * Generate a new {@link ChangelogDBIterator} that allows to browse the db
+ * managed by this dbHandler and starting at the position defined by a given
+ * changeNumber.
+ *
+ * @param startDraftCN
+ * The position where the iterator must start.
+ * @return a new ReplicationIterator that allows to browse the db managed by
+ * this dbHandler and starting at the position defined by a given
+ * changeNumber.
+ * @throws ChangelogException
+ * if a database problem happened.
+ */
+ ChangelogDBIterator generateIterator(int startDraftCN)
+ throws ChangelogException;
+
+ /**
+ * Returns whether this database is empty.
+ *
+ * @return <code>true</code> if this database is empty, <code>false</code>
+ * otherwise
+ */
+ boolean isEmpty();
+
+ /**
+ * Clear the changes from this DB (from both memory cache and DB storage).
+ *
+ * @throws ChangelogException
+ * When an exception occurs while removing the changes from the DB.
+ */
+ void clear() throws ChangelogException;
+
+ /**
+ * Clear the changes from this DB (from both memory cache and DB storage) for
+ * the provided baseDN.
+ *
+ * @param baseDNToClear
+ * The baseDN for which we want to remove all records from the
+ * DraftCNDb - null means all.
+ * @throws ChangelogException
+ * When an exception occurs while removing the changes from the DB.
+ */
+ void clear(String baseDNToClear) throws ChangelogException;
+
+ /**
+ * Shutdown this dbHandler.
+ */
+ void shutdown();
+
+}
diff --git a/opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogDBIterator.java b/opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogDBIterator.java
new file mode 100644
index 0000000..e5fe5f9
--- /dev/null
+++ b/opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogDBIterator.java
@@ -0,0 +1,78 @@
+/*
+ * 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
+ *
+ *
+ * Copyright 2013 ForgeRock AS
+ */
+package org.opends.server.replication.server.changelog.api;
+
+import java.io.Closeable;
+
+import org.opends.server.replication.common.ChangeNumber;
+
+/**
+ * Iterator into the changelog database. Once it is not used anymore, a
+ * ChangelogDBIterator must be closed to release all the resources into the
+ * database.
+ */
+public interface ChangelogDBIterator extends Closeable
+{
+
+ /**
+ * Getter for the replication change number field.
+ *
+ * @return The replication change number field.
+ */
+ ChangeNumber getChangeNumber();
+
+ /**
+ * Getter for the baseDN field.
+ *
+ * @return The service ID.
+ */
+ String getBaseDN();
+
+ /**
+ * Getter for the draftCN field.
+ *
+ * @return The draft CN field.
+ */
+ int getDraftCN();
+
+ /**
+ * Skip to the next record of the database.
+ *
+ * @return true if has next, false otherwise
+ * @throws ChangelogException
+ * When database exception raised.
+ */
+ boolean next() throws ChangelogException;
+
+ /**
+ * Release the resources and locks used by this Iterator. This method must be
+ * called when the iterator is no longer used. Failure to do it could cause DB
+ * deadlock.
+ */
+ @Override
+ void close();
+}
diff --git a/opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDB.java b/opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDB.java
index 07161e0..74ad32f 100644
--- a/opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDB.java
+++ b/opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDB.java
@@ -35,7 +35,6 @@
import org.opends.messages.MessageBuilder;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.replication.common.ChangeNumber;
-import org.opends.server.replication.server.ReplicationServer;
import org.opends.server.replication.server.changelog.api.ChangelogException;
import org.opends.server.types.DebugLogLevel;
@@ -61,7 +60,6 @@
private Database db = null;
private ReplicationDbEnv dbenv = null;
- private ReplicationServer replicationServer;
/**
* The lock used to provide exclusive access to the thread that close the db
@@ -72,15 +70,12 @@
/**
* Creates a new database or open existing database that will be used
* to store and retrieve changes from an LDAP server.
- * @param replicationServer The ReplicationServer that needs to be shutdown.
* @param dbenv The Db environment to use to create the db.
* @throws ChangelogException If a database problem happened.
*/
- public DraftCNDB(ReplicationServer replicationServer, ReplicationDbEnv dbenv)
- throws ChangelogException
+ public DraftCNDB(ReplicationDbEnv dbenv) throws ChangelogException
{
this.dbenv = dbenv;
- this.replicationServer = replicationServer;
// Get or create the associated ReplicationServerDomain and Db.
db = dbenv.getOrCreateDraftCNDb();
diff --git a/opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbHandler.java b/opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbHandler.java
index 11760b9..6aac0d9 100644
--- a/opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbHandler.java
+++ b/opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbHandler.java
@@ -45,8 +45,9 @@
import org.opends.server.replication.server.ReplicationServer;
import org.opends.server.replication.server.ReplicationServerDomain;
import org.opends.server.replication.server.changelog.api.ChangelogException;
-import org.opends.server.replication.server.changelog.je.DraftCNDB
- .DraftCNDBCursor;
+import org.opends.server.replication.server.changelog.api.ChangelogDB;
+import org.opends.server.replication.server.changelog.api.ChangelogDBIterator;
+import org.opends.server.replication.server.changelog.je.DraftCNDB.*;
import org.opends.server.types.Attribute;
import org.opends.server.types.Attributes;
import org.opends.server.types.InitializationException;
@@ -61,12 +62,13 @@
* server in the topology.
* It is responsible for efficiently saving the updates that is received from
* each master server into stable storage.
- * This class is also able to generate a ReplicationIterator that can be
+ * This class is also able to generate a ChangelogDBIterator that can be
* used to read all changes from a given ChangeNumber.
- *
- * This class publish some monitoring information below cn=monitor.
+ * <p>
+ * This class publishes some monitoring information below <code>
+ * cn=monitor</code>.
*/
-public class DraftCNDbHandler implements Runnable
+public class DraftCNDbHandler implements ChangelogDB
{
/**
* The tracer object for the debug logger.
@@ -114,7 +116,7 @@
this.trimAge = replicationServer.getTrimAge();
// DB initialization
- db = new DraftCNDB(replicationServer, dbenv);
+ db = new DraftCNDB(dbenv);
firstkey = db.readFirstDraftCN();
lastkey = db.readLastDraftCN();
@@ -127,43 +129,31 @@
DirectoryServer.registerMonitorProvider(dbMonitor);
}
- /**
- * Add an update to the list of messages that must be saved to the db
- * managed by this db handler.
- * This method is blocking if the size of the list of message is larger
- * than its maximum.
- * @param key The key for this record in the db.
- * @param value The associated value.
- * @param baseDN The associated baseDN.
- * @param cn The associated replication change number.
- */
- public synchronized void add(int key, String value, String baseDN,
+ /** {@inheritDoc} */
+ @Override
+ public synchronized void add(int draftCN, String value, String baseDN,
ChangeNumber cn)
{
- db.addEntry(key, value, baseDN, cn);
+ db.addEntry(draftCN, value, baseDN, cn);
if (debugEnabled())
TRACER.debugInfo(
"In DraftCNDbhandler.add, added: "
- + " key=" + key
+ + " key=" + draftCN
+ " value=" + value
+ " baseDN=" + baseDN
+ " cn=" + cn);
}
- /**
- * Get the firstChange.
- * @return Returns the firstChange.
- */
+ /** {@inheritDoc} */
+ @Override
public int getFirstKey()
{
return db.readFirstDraftCN();
}
- /**
- * Get the lastChange.
- * @return Returns the lastChange.
- */
+ /** {@inheritDoc} */
+ @Override
public int getLastKey()
{
return db.readLastDraftCN();
@@ -179,7 +169,7 @@
}
/**
- * Returns whether this database is empty.
+ * {@inheritDoc}
* <p>
* FIXME Find a way to implement this method in a more efficient manner.
* {@link com.sleepycat.je.Database#count()} javadoc mentions:
@@ -193,64 +183,40 @@
* </li>
* <li>call <code>db.readFirstDraftCN() != 0</code></li>
* </ul>
- *
- * @return <code>true</code> if this database is empty, <code>false</code>
- * otherwise
*/
+ @Override
public boolean isEmpty()
{
return count() == 0;
}
/**
- * Get a read cursor on the database from a provided key.
- * The cursor MUST be released after use.
- * @param key The provided key.
+ * Get a read cursor on the database from a provided key. The cursor MUST be
+ * closed after use.
+ * <p>
+ * This method is only used by unit tests.
+ *
+ * @param startingDraftCN
+ * The draft change number from where to start.
* @return the new cursor.
+ * @throws ChangelogException
+ * if a database problem occurs.
*/
- public DraftCNDBCursor getReadCursor(int key)
+ DraftCNDBCursor getReadCursor(int startingDraftCN) throws ChangelogException
{
- try
- {
- return db.openReadCursor(key);
- }
- catch(Exception e)
- {
- return null;
- }
+ return db.openReadCursor(startingDraftCN);
}
- /**
- * Release a provided read cursor.
- * @param cursor The provided read cursor.
- */
- public void releaseReadCursor(DraftCNDBCursor cursor)
- {
- close(cursor);
- }
-
- /**
- * Generate a new ReplicationIterator that allows to browse the db
- * managed by this dbHandler and starting at the position defined
- * by a given changeNumber.
- *
- * @param startDraftCN The position where the iterator must start.
- *
- * @return a new ReplicationIterator that allows to browse the db
- * managed by this dbHandler and starting at the position defined
- * by a given changeNumber.
- *
- * @throws ChangelogException if a database problem happened.
- */
- public DraftCNDbIterator generateIterator(int startDraftCN)
+ /** {@inheritDoc} */
+ @Override
+ public ChangelogDBIterator generateIterator(int startDraftCN)
throws ChangelogException
{
return new DraftCNDbIterator(db, startDraftCN);
}
- /**
- * Shutdown this dbHandler.
- */
+ /** {@inheritDoc} */
+ @Override
public void shutdown()
{
if (shutdown)
@@ -258,7 +224,7 @@
return;
}
- shutdown = true;
+ shutdown = true;
synchronized (this)
{
notifyAll();
@@ -334,14 +300,8 @@
clear(null);
}
- /**
- * Clear the changes from this DB (from both memory cache and DB storage)
- * for the provided baseDN.
- * @param baseDNToClear The baseDN for which we want to remove
- * all records from the DraftCNDb - null means all.
- * @throws ChangelogException When an exception occurs while removing the
- * changes from the DB.
- */
+ /** {@inheritDoc} */
+ @Override
public void clear(String baseDNToClear) throws ChangelogException
{
if (isEmpty())
@@ -365,11 +325,9 @@
return;
}
- ChangeNumber cn = cursor.currentChangeNumber();
-
// From the draftCNDb change record, get the domain and changeNumber
+ ChangeNumber cn = cursor.currentChangeNumber();
String baseDN = cursor.currentBaseDN();
-
if ((baseDNToClear != null)
&& (baseDNToClear.equalsIgnoreCase(baseDN)))
{
@@ -379,7 +337,6 @@
ReplicationServerDomain domain = replicationServer
.getReplicationServerDomain(baseDN, false);
-
if (domain == null)
{
// the domain has been removed since the record was written in the
@@ -391,8 +348,7 @@
ServerState startState = domain.getStartState();
- // We don't use the returned endState but it's updating CN as
- // reading
+ // We don't use the returned endState but it's updating CN as reading
domain.getEligibleState(crossDomainEligibleCN);
ChangeNumber fcn = startState.getChangeNumber(cn.getServerId());
@@ -521,11 +477,8 @@
trimAge = delay;
}
- /**
- * Clear the changes from this DB (from both memory cache and DB storage).
- * @throws ChangelogException When an exception occurs while removing the
- * changes from the DB.
- */
+ /** {@inheritDoc} */
+ @Override
public void clear() throws ChangelogException
{
db.clear();
@@ -541,7 +494,7 @@
*/
public boolean hasLock()
{
- return (lock.getHoldCount() > 0);
+ return lock.getHoldCount() > 0;
}
/**
@@ -561,28 +514,19 @@
lock.unlock();
}
- /**
- * Get the value associated to a provided key.
- * @param key the provided key.
- * @return the associated value, null when none.
- */
- public String getValue(int key)
+ /** {@inheritDoc} */
+ @Override
+ public String getPreviousCookie(int draftCN)
{
DraftCNDBCursor draftCNDBCursor = null;
try
{
- draftCNDBCursor = db.openReadCursor(key);
+ draftCNDBCursor = db.openReadCursor(draftCN);
return draftCNDBCursor.currentValue();
}
catch(Exception e)
{
- if (debugEnabled())
- TRACER.debugInfo("In DraftCNDbHandler.getValue, read: " +
- " key=" + key + " value returned is null" +
- " first=" + db.readFirstDraftCN() +
- " last=" + db.readLastDraftCN() +
- " count=" + db.count() +
- " exception " + e + " " + e.getMessage());
+ debugException("getValue", draftCN, e);
return null;
}
finally
@@ -591,28 +535,19 @@
}
}
- /**
- * Get the CN associated to a provided key.
- * @param key the provided key.
- * @return the associated CN, null when none.
- */
- public ChangeNumber getChangeNumber(int key)
+ /** {@inheritDoc} */
+ @Override
+ public ChangeNumber getChangeNumber(int draftCN)
{
DraftCNDBCursor draftCNDBCursor = null;
try
{
- draftCNDBCursor = db.openReadCursor(key);
+ draftCNDBCursor = db.openReadCursor(draftCN);
return draftCNDBCursor.currentChangeNumber();
}
catch(Exception e)
{
- if (debugEnabled())
- TRACER.debugInfo("In DraftCNDbHandler.getChangeNumber, read: " +
- " key=" + key + " changeNumber returned is null" +
- " first=" + db.readFirstDraftCN() +
- " last=" + db.readLastDraftCN() +
- " count=" + db.count() +
- " exception" + e + " " + e.getMessage());
+ debugException("getChangeNumber", draftCN, e);
return null;
}
finally
@@ -621,28 +556,19 @@
}
}
- /**
- * Get the baseDN associated to a provided key.
- * @param key the provided key.
- * @return the baseDN, null when none.
- */
- public String getBaseDN(int key)
+ /**{@inheritDoc}*/
+ @Override
+ public String getBaseDN(int draftCN)
{
DraftCNDBCursor draftCNDBCursor = null;
try
{
- draftCNDBCursor = db.openReadCursor(key);
+ draftCNDBCursor = db.openReadCursor(draftCN);
return draftCNDBCursor.currentBaseDN();
}
catch(Exception e)
{
- if (debugEnabled())
- TRACER.debugInfo("In DraftCNDbHandler.getBaseDN(), read: " +
- " key=" + key + " baseDN returned is null" +
- " first=" + db.readFirstDraftCN() +
- " last=" + db.readLastDraftCN() +
- " count=" + db.count() +
- " exception" + e + " " + e.getMessage());
+ debugException("getBaseDN", draftCN, e);
return null;
}
finally
@@ -650,4 +576,15 @@
close(draftCNDBCursor);
}
}
+
+ private void debugException(String methodName, int draftCN, Exception e)
+ {
+ if (debugEnabled())
+ TRACER.debugInfo("In DraftCNDbHandler." + methodName + "(), read: "
+ + " key=" + draftCN + " value returned is null"
+ + " first="+ db.readFirstDraftCN()
+ + " last=" + db.readLastDraftCN()
+ + " count=" + db.count()
+ + " exception " + e + " " + e.getMessage());
+ }
}
diff --git a/opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbIterator.java b/opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbIterator.java
index 279ae22..ad8bd0a 100644
--- a/opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbIterator.java
+++ b/opends/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbIterator.java
@@ -31,6 +31,7 @@
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.replication.server.changelog.api.ChangelogException;
+import org.opends.server.replication.server.changelog.api.ChangelogDBIterator;
import org.opends.server.replication.server.changelog.je.DraftCNDB
.DraftCNDBCursor;
import org.opends.server.types.DebugLogLevel;
@@ -41,7 +42,7 @@
* This class allows to iterate through the changes received from a given
* LDAP Server Identifier.
*/
-public class DraftCNDbIterator
+public class DraftCNDbIterator implements ChangelogDBIterator
{
private static final DebugTracer TRACER = getTracer();
private DraftCNDBCursor draftCNDbCursor;
@@ -66,11 +67,8 @@
}
}
- /**
- * Getter for the baseDN field.
- *
- * @return The service ID.
- */
+ /** {@inheritDoc} */
+ @Override
public String getBaseDN()
{
try
@@ -84,10 +82,8 @@
}
}
- /**
- * Getter for the replication change number field.
- * @return The replication change number field.
- */
+ /** {@inheritDoc} */
+ @Override
public ChangeNumber getChangeNumber()
{
try
@@ -101,10 +97,8 @@
}
}
- /**
- * Getter for the draftCN field.
- * @return The draft CN field.
- */
+ /** {@inheritDoc} */
+ @Override
public int getDraftCN()
{
ReplicationDraftCNKey sk = (ReplicationDraftCNKey) draftCNDbCursor.getKey();
@@ -112,11 +106,8 @@
return currentSeqnum;
}
- /**
- * Skip to the next record of the database.
- * @return true if has next, false elsewhere
- * @throws ChangelogException When database exception raised.
- */
+ /** {@inheritDoc} */
+ @Override
public boolean next() throws ChangelogException
{
if (draftCNDbCursor != null)
@@ -126,12 +117,9 @@
return false;
}
- /**
- * Release the resources and locks used by this Iterator.
- * This method must be called when the iterator is no longer used.
- * Failure to do it could cause DB deadlock.
- */
- public void releaseCursor()
+ /** {@inheritDoc} */
+ @Override
+ public void close()
{
synchronized (this)
{
@@ -151,6 +139,6 @@
@Override
protected void finalize()
{
- releaseCursor();
+ close();
}
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
index f82609b..da7b013 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
@@ -28,10 +28,6 @@
*/
package org.opends.server;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
-import static org.testng.Assert.*;
-
import java.io.*;
import java.net.*;
import java.util.*;
@@ -75,9 +71,12 @@
import org.opends.server.util.EmbeddedUtils;
import org.opends.server.util.LDIFReader;
+import static org.opends.server.util.ServerConstants.*;
+import static org.opends.server.util.StaticUtils.*;
+import static org.testng.Assert.*;
+
/**
- * This class defines some utility functions which can be used by test
- * cases.
+ * This class defines some utility functions which can be used by test cases.
*/
@SuppressWarnings("javadoc")
public final class TestCaseUtils {
@@ -348,7 +347,7 @@
File resourceDir = new File(buildRoot, "resource");
File testResourceDir = new File(testSrcRoot, "resource");
// Set the class variable
- testConfigDir = new File(testInstanceRoot, "config");
+ testConfigDir = new File(testInstanceRoot, "config");
File testSchemaDir = new File(testInstanceRoot, "config");
File testClassesDir = new File(testInstanceRoot, "classes");
File testLibDir = new File(testInstallRoot, "lib");
@@ -363,11 +362,8 @@
File snmpResourceDir = new File(buildRoot + File.separator + "src" +
File.separator + "snmp" + File.separator +
"resource");
-
File snmpConfigDir = new File(snmpResourceDir, "config");
-
- File testSnmpResourceDir = new File (testConfigDir + File.separator +
- "snmp");
+ File testSnmpResourceDir = new File (testConfigDir + File.separator + "snmp");
if (Boolean.getBoolean(PROPERTY_COPY_CLASSES_TO_TEST_PKG))
{
@@ -1045,6 +1041,11 @@
* If the directory could not be deleted.
*/
public static void deleteDirectory(File dir) throws IOException {
+ if (dir == null || !dir.exists())
+ {
+ return;
+ }
+
if (dir.isDirectory()) {
// Recursively delete sub-directories and files.
for (String child : dir.list()) {
@@ -1548,15 +1549,10 @@
if (useAdminPort) {
return LDAPModify.mainModify(adminArgs, false, null, null);
- } else {
- return LDAPModify.mainModify(args, false, null, null);
}
+ return LDAPModify.mainModify(args, false, null, null);
}
-
-
-
-
/**
* Creates a temporary text file with the specified contents. It will be
* marked for automatic deletion when the JVM exits.
@@ -1565,8 +1561,7 @@
*
* @throws Exception If an unexpected problem occurs.
*/
- public static String createTempFile(String... lines)
- throws Exception
+ public static String createTempFile(String... lines) throws Exception
{
File f = File.createTempFile("LDAPModifyTestCase", ".txt");
f.deleteOnExit();
@@ -1576,7 +1571,6 @@
{
w.write(s + System.getProperty("line.separator"));
}
-
w.close();
return f.getAbsolutePath();
@@ -1594,8 +1588,9 @@
/**
* Return a Map constructed via alternating key and value pairs.
*/
- public static LinkedHashMap<String,String> makeMap(String... keyValuePairs) {
- LinkedHashMap<String,String> map = new LinkedHashMap<String,String>();
+ public static Map<String, String> makeMap(String... keyValuePairs)
+ {
+ Map<String, String> map = new LinkedHashMap<String, String>();
for (int i = 0; i < keyValuePairs.length; i += 2) {
map.put(keyValuePairs[i], keyValuePairs[i+1]);
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
index 102d42f..2f9eb2d 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
@@ -2755,7 +2755,7 @@
String tn = "ECLPurgeDraftCNDbAfterChangelogClear";
debugInfo(tn, "Starting test\n\n");
{
- DraftCNDbHandler draftdb = replicationServer.getDraftCNDbHandler();
+ DraftCNDbHandler draftdb = (DraftCNDbHandler) replicationServer.getChangelogDB();
assertEquals(draftdb.count(), 8);
draftdb.setPurgeDelay(1000);
@@ -2764,7 +2764,7 @@
// Expect changes purged from the changelog db to be sometimes
// also purged from the DraftCNDb.
- while(draftdb.count()>0)
+ while (!draftdb.isEmpty())
{
debugInfo(tn, "draftdb.count="+draftdb.count());
sleep(200);
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/changelog/je/DbHandlerTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/changelog/je/DbHandlerTest.java
index bff653e..6f27309 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/changelog/je/DbHandlerTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/changelog/je/DbHandlerTest.java
@@ -83,10 +83,9 @@
replicationServer = configureReplicationServer(100);
// create or clean a directory for the dbHandler
- String path = getReplicationDbPath();
- testRoot = createDirectory(path);
+ testRoot = createCleanDir();
- dbEnv = new ReplicationDbEnv(path, replicationServer);
+ dbEnv = new ReplicationDbEnv(testRoot.getPath(), replicationServer);
handler = new DbHandler(1, TEST_ROOT_DN_STRING, replicationServer, dbEnv, 5000);
ChangeNumberGenerator gen = new ChangeNumberGenerator( 1, 0);
@@ -163,9 +162,8 @@
if (dbEnv != null)
dbEnv.shutdown();
if (replicationServer != null)
- replicationServer.remove();
- if (testRoot != null)
- TestCaseUtils.deleteDirectory(testRoot);
+ replicationServer.remove();
+ TestCaseUtils.deleteDirectory(testRoot);
}
}
@@ -178,21 +176,14 @@
return new ReplicationServer(conf);
}
- private String getReplicationDbPath()
+ private File createCleanDir() throws IOException
{
String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
String path = System.getProperty(TestCaseUtils.PROPERTY_BUILD_DIR, buildRoot
+ File.separator + "build");
- return path + File.separator + "unit-tests" + File.separator + "dbHandler";
- }
-
- private File createDirectory(String path) throws IOException
- {
- File testRoot = new File(path);
- if (testRoot.exists())
- {
- TestCaseUtils.deleteDirectory(testRoot);
- }
+ path = path + File.separator + "unit-tests" + File.separator + "dbHandler";
+ final File testRoot = new File(path);
+ TestCaseUtils.deleteDirectory(testRoot);
testRoot.mkdirs();
return testRoot;
}
@@ -262,11 +253,8 @@
replicationServer = configureReplicationServer(100);
- // create or clean a directory for the dbHandler
- String path = getReplicationDbPath();
- testRoot = createDirectory(path);
-
- dbEnv = new ReplicationDbEnv(path, replicationServer);
+ testRoot = createCleanDir();
+ dbEnv = new ReplicationDbEnv(testRoot.getPath(), replicationServer);
handler = new DbHandler(1, TEST_ROOT_DN_STRING, replicationServer, dbEnv, 5000);
// Creates changes added to the dbHandler
@@ -299,8 +287,7 @@
dbEnv.shutdown();
if (replicationServer != null)
replicationServer.remove();
- if (testRoot != null)
- TestCaseUtils.deleteDirectory(testRoot);
+ TestCaseUtils.deleteDirectory(testRoot);
}
}
@@ -362,12 +349,8 @@
replicationServer = configureReplicationServer(100000);
- // create or clean a directory for the dbHandler
- String path = getReplicationDbPath();
- testRoot = createDirectory(path);
-
- dbEnv = new ReplicationDbEnv(path, replicationServer);
-
+ testRoot = createCleanDir();
+ dbEnv = new ReplicationDbEnv(testRoot.getPath(), replicationServer);
handler = new DbHandler(1, TEST_ROOT_DN_STRING, replicationServer, dbEnv, 10);
handler.setCounterWindowSize(counterWindow);
@@ -543,8 +526,7 @@
dbEnv.shutdown();
if (replicationServer != null)
replicationServer.remove();
- if (testRoot != null)
- TestCaseUtils.deleteDirectory(testRoot);
+ TestCaseUtils.deleteDirectory(testRoot);
}
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbHandlerTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbHandlerTest.java
index 16609fb..73e3696 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbHandlerTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/changelog/je/DraftCNDbHandlerTest.java
@@ -27,9 +27,8 @@
*/
package org.opends.server.replication.server.changelog.je;
-import static org.testng.Assert.*;
-
import java.io.File;
+import java.io.IOException;
import org.opends.server.TestCaseUtils;
import org.opends.server.replication.ReplicationTestCase;
@@ -37,12 +36,14 @@
import org.opends.server.replication.common.ChangeNumberGenerator;
import org.opends.server.replication.server.ReplServerFakeConfiguration;
import org.opends.server.replication.server.ReplicationServer;
-import org.opends.server.replication.server.changelog.je.DraftCNDbHandler;
-import org.opends.server.replication.server.changelog.je.DraftCNDbIterator;
-import org.opends.server.replication.server.changelog.je.ReplicationDbEnv;
+import org.opends.server.replication.server.changelog.api.ChangelogException;
+import org.opends.server.replication.server.changelog.api.ChangelogDBIterator;
import org.opends.server.replication.server.changelog.je.DraftCNDB.DraftCNDBCursor;
+import org.opends.server.util.StaticUtils;
import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
/**
* Test the DraftCNDbHandler class with 2 kinds of cleaning of the db :
* - periodic trim
@@ -80,19 +81,8 @@
2, 0, 100, null);
replicationServer = new ReplicationServer(conf);
- // create or clean a directory for the DraftCNDbHandler
- String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
- String path = System.getProperty(TestCaseUtils.PROPERTY_BUILD_DIR,
- buildRoot + File.separator + "build");
- path = path + File.separator + "unit-tests" + File.separator + "DraftCNDbHandler";
- testRoot = new File(path);
- if (testRoot.exists())
- {
- TestCaseUtils.deleteDirectory(testRoot);
- }
- testRoot.mkdirs();
-
- dbEnv = new ReplicationDbEnv(path, replicationServer);
+ testRoot = createCleanDir();
+ dbEnv = new ReplicationDbEnv(testRoot.getPath(), replicationServer);
handler = new DraftCNDbHandler(replicationServer, dbEnv);
handler.setPurgeDelay(0);
@@ -149,7 +139,7 @@
}
finally
{
- handler.releaseReadCursor(dbc);
+ StaticUtils.close(dbc);
}
handler.setPurgeDelay(100);
@@ -170,14 +160,25 @@
if (dbEnv != null)
dbEnv.shutdown();
if (replicationServer != null)
- replicationServer.remove();
- if (testRoot != null)
- TestCaseUtils.deleteDirectory(testRoot);
+ replicationServer.remove();
+ TestCaseUtils.deleteDirectory(testRoot);
}
}
+ private File createCleanDir() throws IOException
+ {
+ String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
+ String path = System.getProperty(TestCaseUtils.PROPERTY_BUILD_DIR, buildRoot
+ + File.separator + "build");
+ path = path + File.separator + "unit-tests" + File.separator + "DraftCNDbHandler";
+ final File testRoot = new File(path);
+ TestCaseUtils.deleteDirectory(testRoot);
+ testRoot.mkdirs();
+ return testRoot;
+ }
+
/**
- * This test makes basic operations of a DraftCNDb and explicitely call
+ * This test makes basic operations of a DraftCNDb and explicitly calls
* the clear() method instead of waiting for the periodic trim to clear
* it.
* - create the db
@@ -205,25 +206,13 @@
2, 0, 100, null);
replicationServer = new ReplicationServer(conf);
- // create or clean a directory for the DraftCNDbHandler
- String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
- String path = System.getProperty(TestCaseUtils.PROPERTY_BUILD_DIR,
- buildRoot + File.separator + "build");
- path = path + File.separator + "unit-tests" + File.separator + "DraftCNDbHandler";
- testRoot = new File(path);
- if (testRoot.exists())
- {
- TestCaseUtils.deleteDirectory(testRoot);
- }
- testRoot.mkdirs();
-
- dbEnv = new ReplicationDbEnv(path, replicationServer);
+ testRoot = createCleanDir();
+ dbEnv = new ReplicationDbEnv(testRoot.getAbsolutePath(), replicationServer);
handler = new DraftCNDbHandler(replicationServer, dbEnv);
handler.setPurgeDelay(0);
- //
- assertTrue(handler.count()==0);
+ assertTrue(handler.isEmpty());
// Prepare data to be stored in the db
int sn1 = 3;
@@ -255,57 +244,25 @@
assertEquals(handler.count(), 3, "Db count");
- assertEquals(handler.getValue(sn1),value1);
- assertEquals(handler.getValue(sn2),value2);
- assertEquals(handler.getValue(sn3),value3);
+ assertEquals(handler.getPreviousCookie(sn1),value1);
+ assertEquals(handler.getPreviousCookie(sn2),value2);
+ assertEquals(handler.getPreviousCookie(sn3),value3);
- DraftCNDbIterator it = handler.generateIterator(sn1);
- try
- {
- assertEquals(it.getDraftCN(), sn1);
- assertTrue(it.next());
- assertEquals(it.getDraftCN(), sn2);
- assertTrue(it.next());
- assertEquals(it.getDraftCN(), sn3);
- assertFalse(it.next());
- }
- finally
- {
- it.releaseCursor();
- }
+ ChangelogDBIterator it = handler.generateIterator(sn1);
+ assertIteratorReadsInOrder(it, sn1, sn2, sn3);
it = handler.generateIterator(sn2);
- try
- {
- assertEquals(it.getDraftCN(), sn2);
- assertTrue(it.next());
- assertEquals(it.getDraftCN(), sn3);
- assertFalse(it.next());
- }
- finally
- {
- it.releaseCursor();
- }
+ assertIteratorReadsInOrder(it, sn2, sn3);
it = handler.generateIterator(sn3);
- try
- {
- assertEquals(it.getDraftCN(), sn3);
- assertFalse(it.next());
- }
- finally
- {
- it.releaseCursor();
- }
+ assertIteratorReadsInOrder(it, sn3);
- // Clear ...
handler.clear();
// Check the db is cleared.
assertEquals(handler.getFirstKey(), 0);
assertEquals(handler.getLastKey(), 0);
assertEquals(handler.count(), 0);
-
} finally
{
if (handler != null)
@@ -314,8 +271,25 @@
dbEnv.shutdown();
if (replicationServer != null)
replicationServer.remove();
- if (testRoot != null)
- TestCaseUtils.deleteDirectory(testRoot);
+ TestCaseUtils.deleteDirectory(testRoot);
+ }
+ }
+
+ private void assertIteratorReadsInOrder(ChangelogDBIterator it, int... sns)
+ throws ChangelogException
+ {
+ try
+ {
+ for (int i = 0; i < sns.length; i++)
+ {
+ assertEquals(it.getDraftCN(), sns[i]);
+ final boolean isNotLast = i + 1 < sns.length;
+ assertEquals(it.next(), isNotLast);
+ }
+ }
+ finally
+ {
+ it.close();
}
}
}
--
Gitblit v1.10.0