From 715bf2629d654ce0427a7edf564bbdd390c5bc88 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Mon, 23 Dec 2013 13:54:49 +0000
Subject: [PATCH] Fix OPENDJ-1115: Internal errors from ModifyOperation - change number was not found in pending list
---
opends/src/server/org/opends/server/replication/plugin/RemotePendingChanges.java | 13 ++++++++-----
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java | 43 ++++++++++++++++++++++++++++---------------
2 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java b/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
index b3c75db..754dcec 100644
--- a/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
+++ b/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -2129,14 +2129,8 @@
return;
}
- try
- {
- addEntryAttributesForCL(msg,op);
- }
- catch(Exception e)
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
+ addEntryAttributesForCL(msg,op);
+
// If assured replication is configured, this will prepare blocking
// mechanism. If assured replication is disabled, this returns
// immediately
@@ -3783,12 +3777,17 @@
return DirectoryServer.getBackend(baseDN);
}
+
+
/**
* Process backend before import.
- * @param backend The backend.
- * @throws Exception
+ *
+ * @param backend
+ * The backend.
+ * @throws DirectoryException
+ * If the backend could not be disabled or locked exclusively.
*/
- private void preBackendImport(Backend backend) throws Exception
+ private void preBackendImport(Backend backend) throws DirectoryException
{
// Stop saving state
stateSavingDisabled = true;
@@ -4549,8 +4548,23 @@
{
LDAPUpdateMsg msg = (LDAPUpdateMsg) updateMsg;
- // put the UpdateMsg in the RemotePendingChanges list.
- remotePendingChanges.putRemoteUpdate(msg);
+ // Put the UpdateMsg in the RemotePendingChanges list.
+ if (!remotePendingChanges.putRemoteUpdate(msg))
+ {
+ /*
+ * Already received this change so ignore it. This may happen if there
+ * are uncommitted changes in the queue and session failover occurs
+ * causing a recovery of all changes since the current committed server
+ * state. See OPENDJ-1115.
+ */
+ if (debugEnabled())
+ {
+ TRACER.debugInfo(
+ "LDAPReplicationDomain.processUpdate: ignoring "
+ + "duplicate change %s", msg.getCSN());
+ }
+ return true;
+ }
// Put update message into the replay queue
// (block until some place in the queue is available)
@@ -4646,10 +4660,9 @@
* attributes to the UpdateMsg.
* @param msg an replication update message
* @param op the operation in progress
- * @throws DirectoryException
*/
private void addEntryAttributesForCL(UpdateMsg msg,
- PostOperationOperation op) throws DirectoryException
+ PostOperationOperation op)
{
if (op instanceof PostOperationDeleteOperation)
{
diff --git a/opends/src/server/org/opends/server/replication/plugin/RemotePendingChanges.java b/opends/src/server/org/opends/server/replication/plugin/RemotePendingChanges.java
index e8815cc..52c79ca 100644
--- a/opends/src/server/org/opends/server/replication/plugin/RemotePendingChanges.java
+++ b/opends/src/server/org/opends/server/replication/plugin/RemotePendingChanges.java
@@ -53,7 +53,7 @@
/**
* A map used to store the pending changes.
*/
- private SortedMap<CSN, PendingChange> pendingChanges =
+ private final SortedMap<CSN, PendingChange> pendingChanges =
new TreeMap<CSN, PendingChange>();
/**
@@ -61,13 +61,13 @@
* not been replayed correctly because they are dependent on
* another change to be completed.
*/
- private SortedSet<PendingChange> dependentChanges =
+ private final SortedSet<PendingChange> dependentChanges =
new TreeSet<PendingChange>();
/**
* The ServerState that will be updated when LDAPUpdateMsg are fully replayed.
*/
- private ServerState state;
+ private final ServerState state;
/**
* Creates a new RemotePendingChanges using the provided ServerState.
@@ -96,11 +96,14 @@
*
* @param update The LDAPUpdateMsg that was received from the replication
* server and that will be added to the pending list.
+ * @return {@code false} if the update was already registered in the pending
+ * changes.
*/
- public synchronized void putRemoteUpdate(LDAPUpdateMsg update)
+ public synchronized boolean putRemoteUpdate(LDAPUpdateMsg update)
{
CSN csn = update.getCSN();
- pendingChanges.put(csn, new PendingChange(csn, null, update));
+ return pendingChanges.put(csn,
+ new PendingChange(csn, null, update)) == null;
}
/**
--
Gitblit v1.10.0