From c51087e0fd110ff0174799aa50e83ec33bf687be Mon Sep 17 00:00:00 2001
From: pgamba <pgamba@localhost>
Date: Tue, 25 Mar 2008 17:20:03 +0000
Subject: [PATCH] The recent lock introduced recently in order to not access the database while it is truncated is sometimes not released correctly. The following fix do not change anything in the logic of the replication processing : it just makes more robust the unlocking whatever exception or problem occurs in the processing.
---
opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDB.java | 162 +++++++++++++++++++++++++++++------------------------
1 files changed, 88 insertions(+), 74 deletions(-)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDB.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDB.java
index dba83f0..e6e67bc 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDB.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDB.java
@@ -253,13 +253,27 @@
return new ReplServerDBCursor();
}
+ private void closeLockedCursor(Cursor cursor)
+ throws DatabaseException
+ {
+ try
+ {
+ if (cursor != null)
+ cursor.close();
+ }
+ finally
+ {
+ dbCloseLock.readLock().unlock();
+ }
+ }
+
/**
* Read the first Change from the database.
* @return the first ChangeNumber.
*/
public ChangeNumber readFirstChange()
{
- Cursor cursor;
+ Cursor cursor = null;
String str = null;
try
@@ -274,35 +288,32 @@
}
try
{
- DatabaseEntry key = new DatabaseEntry();
- DatabaseEntry data = new DatabaseEntry();
- OperationStatus status = cursor.getFirst(key, data, LockMode.DEFAULT);
- cursor.close();
- dbCloseLock.readLock().unlock();
- if (status != OperationStatus.SUCCESS)
- {
- /* database is empty */
- return null;
- }
try
{
- str = new String(key.getData(), "UTF-8");
- } catch (UnsupportedEncodingException e)
- {
- // never happens
+ DatabaseEntry key = new DatabaseEntry();
+ DatabaseEntry data = new DatabaseEntry();
+ OperationStatus status = cursor.getFirst(key, data, LockMode.DEFAULT);
+ if (status != OperationStatus.SUCCESS)
+ {
+ /* database is empty */
+ return null;
+ }
+ try
+ {
+ str = new String(key.getData(), "UTF-8");
+ } catch (UnsupportedEncodingException e)
+ {
+ // never happens
+ }
+ return new ChangeNumber(str);
}
- return new ChangeNumber(str);
- } catch (DatabaseException e)
+ finally
+ {
+ closeLockedCursor(cursor);
+ }
+ }
+ catch (DatabaseException e)
{
- try
- {
- cursor.close();
- dbCloseLock.readLock().unlock();
- }
- catch (DatabaseException dbe)
- {
- // The db is dead - let's only log.
- }
/* database is faulty */
MessageBuilder mb = new MessageBuilder();
mb.append(ERR_CHANGELOG_SHUTDOWN_DATABASE_ERROR.get());
@@ -319,32 +330,39 @@
*/
public ChangeNumber readLastChange()
{
- Cursor cursor;
+ Cursor cursor = null;
String str = null;
try
{
dbCloseLock.readLock().lock();
- cursor = db.openCursor(null, null);
- DatabaseEntry key = new DatabaseEntry();
- DatabaseEntry data = new DatabaseEntry();
- OperationStatus status = cursor.getLast(key, data, LockMode.DEFAULT);
- cursor.close();
- dbCloseLock.readLock().unlock();
- if (status != OperationStatus.SUCCESS)
- {
- /* database is empty */
- return null;
- }
try
{
- str = new String(key.getData(), "UTF-8");
- } catch (UnsupportedEncodingException e)
- {
- // never happens
+ cursor = db.openCursor(null, null);
+ DatabaseEntry key = new DatabaseEntry();
+ DatabaseEntry data = new DatabaseEntry();
+ OperationStatus status = cursor.getLast(key, data, LockMode.DEFAULT);
+ if (status != OperationStatus.SUCCESS)
+ {
+ /* database is empty */
+ return null;
+ }
+ try
+ {
+ str = new String(key.getData(), "UTF-8");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ // never happens
+ }
+ return new ChangeNumber(str);
}
- return new ChangeNumber(str);
- } catch (DatabaseException e)
+ finally
+ {
+ closeLockedCursor(cursor);
+ }
+ }
+ catch (DatabaseException e)
{
MessageBuilder mb = new MessageBuilder();
mb.append(ERR_CHANGELOG_SHUTDOWN_DATABASE_ERROR.get());
@@ -371,6 +389,10 @@
public class ReplServerDBCursor
{
private Cursor cursor = null;
+
+ // The transaction that will protect the actions done with the cursor
+ // Will be let null for a read cursor
+ // Will be set non null for a write cursor
private Transaction txn = null;
DatabaseEntry key = new DatabaseEntry();
DatabaseEntry data = new DatabaseEntry();
@@ -407,8 +429,6 @@
OperationStatus.SUCCESS)
{
// We could not even move the cursor closed to it => failure
- // Unlocking is required before throwing any exception
- dbCloseLock.readLock().unlock();
throw new Exception("ChangeNumber not available");
}
else
@@ -420,17 +440,9 @@
if (cursor.getPrev(key, data, LockMode.DEFAULT) !=
OperationStatus.SUCCESS)
{
- try
- {
- cursor.close();
- cursor = db.openCursor(txn, null);
- }
- catch(Exception e)
- {
- // Unlocking is required before throwing any exception
- dbCloseLock.readLock().unlock();
- throw(e);
- }
+ closeLockedCursor(cursor);
+ dbCloseLock.readLock().lock();
+ cursor = db.openCursor(txn, null);
}
}
}
@@ -438,9 +450,8 @@
}
catch (Exception e)
{
- // Unlocking is required before throwing any exception
- dbCloseLock.readLock().unlock();
- cursor.close();
+ // Unlocking is required before throwing any exception
+ closeLockedCursor(cursor);
throw (e);
}
}
@@ -451,12 +462,25 @@
{
// We'll go on only if no close or no clear is running
dbCloseLock.readLock().lock();
+
+ // Create the transaction that will protect whatever done with this
+ // write cursor.
txn = dbenv.beginTransaction();
+
cursor = db.openCursor(txn, null);
}
catch(DatabaseException e)
{
- dbCloseLock.readLock().unlock();
+ if (txn != null)
+ {
+ try
+ {
+ txn.abort();
+ }
+ catch (DatabaseException dbe)
+ {}
+ }
+ closeLockedCursor(cursor);
throw (e);
}
}
@@ -468,23 +492,17 @@
{
try
{
- if (cursor != null)
- {
- cursor.close();
- cursor = null;
- }
+ closeLockedCursor(cursor);
+ cursor = null;
}
catch (DatabaseException e)
{
- dbCloseLock.readLock().unlock();
-
MessageBuilder mb = new MessageBuilder();
mb.append(ERR_CHANGELOG_SHUTDOWN_DATABASE_ERROR.get());
mb.append(stackTraceToSingleLineString(e));
logError(mb.toMessage());
replicationServer.shutdown();
}
-
if (txn != null)
{
try
@@ -499,7 +517,6 @@
replicationServer.shutdown();
}
}
- dbCloseLock.readLock().unlock();
}
/**
@@ -515,7 +532,7 @@
return;
try
{
- cursor.close();
+ closeLockedCursor(cursor);
cursor = null;
}
catch (DeadlockException e1)
@@ -526,8 +543,6 @@
}
catch (DatabaseException e)
{
- dbCloseLock.readLock().unlock();
-
MessageBuilder mb = new MessageBuilder();
mb.append(ERR_CHANGELOG_SHUTDOWN_DATABASE_ERROR.get());
mb.append(stackTraceToSingleLineString(e));
@@ -548,7 +563,6 @@
replicationServer.shutdown();
}
}
- dbCloseLock.readLock().unlock();
}
/**
--
Gitblit v1.10.0