From 62a518f7d2b432b072de8fdbb97976fb257953cb Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Mon, 23 Dec 2013 18:42:39 +0000
Subject: [PATCH] OPENDJ-1262 NPE in ChangeNumberIndex during server startup
---
opends/src/server/org/opends/server/replication/server/changelog/je/ChangeNumberIndexer.java | 21 ++++++++++++++-------
1 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/opends/src/server/org/opends/server/replication/server/changelog/je/ChangeNumberIndexer.java b/opends/src/server/org/opends/server/replication/server/changelog/je/ChangeNumberIndexer.java
index a9320a4..20d6f64 100644
--- a/opends/src/server/org/opends/server/replication/server/changelog/je/ChangeNumberIndexer.java
+++ b/opends/src/server/org/opends/server/replication/server/changelog/je/ChangeNumberIndexer.java
@@ -296,6 +296,8 @@
// restore the mediumConsistencyRUV from DB
mediumConsistencyRUV.update(
new MultiDomainServerState(newestRecord.getPreviousCookie()));
+ // Do not update with the newestRecord CSN
+ // as it will be used for a sanity check later in the same method
}
// initialize the DB cursor and the last seen updates
@@ -313,7 +315,7 @@
for (Integer serverId : entry.getValue())
{
final CSN csn = mediumConsistencyRUV.getCSN(baseDN, serverId);
- ensureCursorExists(baseDN, serverId, csn);
+ ensureCursorExists(baseDN, serverId, csn, false);
}
ServerState latestKnownState = domainDB.getDomainNewestCSNs(baseDN);
@@ -325,12 +327,15 @@
{
// restore the "previousCookie" state before shutdown
final UpdateMsg record = nextChangeForInsertDBCursor.getRecord();
+ // sanity check: ensure that when initializing the cursors at the previous
+ // cookie, the next change we find is the newest record in the CNIndexDB
if (!record.getCSN().equals(newestRecord.getCSN()))
{
throw new ChangelogException(
ERR_CHANGE_NUMBER_INDEXER_INCONSISTENT_CSN_READ.get(newestRecord
.getCSN().toStringUI(), record.getCSN().toStringUI()));
}
+ // Now we can update the mediumConsistencyRUV
mediumConsistencyRUV.update(newestRecord.getBaseDN(), record.getCSN());
nextChangeForInsertDBCursor.next();
}
@@ -357,8 +362,8 @@
nextChangeForInsertDBCursor = result;
}
- private boolean ensureCursorExists(DN baseDN, Integer serverId, CSN csn)
- throws ChangelogException
+ private boolean ensureCursorExists(DN baseDN, Integer serverId, CSN csn,
+ boolean startFromPrecedingCSN) throws ChangelogException
{
Map<Integer, DBCursor<UpdateMsg>> map = allCursors.get(baseDN);
if (map == null)
@@ -370,9 +375,11 @@
if (cursor == null)
{
final ReplicationDomainDB domainDB = changelogDB.getReplicationDomainDB();
- // use an older CSN because getCursorFrom() starts after the given CSN
- final CSN anOlderCSN = getPrecedingCSN(csn);
- cursor = domainDB.getCursorFrom(baseDN, serverId, anOlderCSN);
+ // start from preceding CSN for publishUpdateMsg(),
+ // or from the actual CSN when initializing from the previous cookie
+ final CSN startAfterCSN =
+ startFromPrecedingCSN ? getPrecedingCSN(csn) : csn;
+ cursor = domainDB.getCursorFrom(baseDN, serverId, startAfterCSN);
map.put(serverId, cursor);
return false;
}
@@ -595,7 +602,7 @@
final Entry<Pair<DN, Integer>, CSN> entry = iter.next();
final DN baseDN = entry.getKey().getFirst();
final CSN csn = entry.getValue();
- if (!ensureCursorExists(baseDN, csn.getServerId(), csn))
+ if (!ensureCursorExists(baseDN, csn.getServerId(), csn, true))
{
newCursorAdded = true;
}
--
Gitblit v1.10.0