Hi Mark,
Can you give an example of what you're seeing? --
The keys in the database, the key being inserted, and
the nextKey that is locked (incorrectly). Or if you
have one, please send a test program that shows the
problem.
A simple application is sequentially inserting the following keys on behalf of a single transaction: k1, k2, k4 and k5.
The output of the first run:
range-01: k1 -- k1
range-02: k1 -- EOF
range-01: k2 -- k2
range-02: k2 -- k1
range-01: k4 -- k4
range-02: k4 -- k2
range-01: k5 -- k5
range-02: k5 -- k4
The output of successive runs:
range-01: k1 --
range-02: k1 -- k2
range-01: k2 --
range-02: k2 -- k4
range-01: k4 -- k4
range-02: k4 -- k4
range-01: k5 -- k5
range-02: k5 -- k4
I don't understand these values..
By the way, I don't know how to attach files by means of the interface provided in the forum, so I am copying the modifications done to the source code. Let me know if you need any else.
Cheers.
alfranio
=== modified file 'src/com/sleepycat/je/Cursor.java'
--- src/com/sleepycat/je/Cursor.java 2008-06-12 16:21:24 +0000
+ src/com/sleepycat/je/Cursor.java 2008-08-04 19:08:15 +0000
@@ -1375,6 +1375,31 @@
}
}
+ private CursorImpl getCursor(CursorImpl orig) throws DatabaseException {
+ CursorImpl dup = null;
+
+ if (orig != null) {
+ dup = orig.cloneCursor(true);
+ }
+ return (dup);
+ }
+
+ private OperationStatus rangeLockCurrentPosition(DatabaseEntry key, DatabaseEntry data, CursorImpl orig)
+ throws DatabaseException {
+ OperationStatus status = OperationStatus.NOTFOUND;
+ CursorImpl dup = getCursor(orig);
+
+ if (dup != null) {
+ try {
+ status = dup.getCurrent(key, data, LockType.NONE);
+ } finally {
+ dup.close();
+ }
+ }
+
+ return (status);
+ }
+
/**
* Performs the put operation but does not notify triggers (does not
* perform secondary updates). Prevents phantoms.
@@ -1399,7 +1424,45 @@
nextKeyCursor = new CursorImpl(dbImpl, nextKeyLocker);
/* Perform eviction for user cursors. */
nextKeyCursor.setAllowEviction(true);
- nextKeyCursor.lockNextKeyForInsert(key, data);
+
+ DatabaseEntry nextKey = new DatabaseEntry
+ (key.getData(), key.getOffset(), key.getSize());
+ DatabaseEntry nextData = new DatabaseEntry
+ (data.getData(), data.getOffset(), data.getSize());
+ nextKey.setPartial(0, 0, true);
+ nextData.setPartial(0, 0, true);
+
+ nextKeyCursor.lockNextKeyForInsert(key, data, nextKey, nextData);
+
+ if (nextKey.getData() == null) {
+ try {
+ System.out.println("range-01: " + new String(key.getData(),"UTF-8") + " -- EOF");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace(System.err);
+ }
+ } else {
+ try {
+ System.out.println("range-01: " + new String(key.getData(),"UTF-8") + " -- " + new String(nextKey.getData(),"UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace(System.err);
+ }
+ }
+
+ DatabaseEntry endKey = new DatabaseEntry();
+ DatabaseEntry endData = new DatabaseEntry();
+ if (rangeLockCurrentPosition(endKey,endData,nextKeyCursor) != OperationStatus.SUCCESS) {
+ try {
+ System.out.println("range: " + new String(key.getData(),"UTF-8") + " -- EOF");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace(System.err);
+ }
+ } else {
+ try {
+ System.out.println("range: " + new String(key.getData(),"UTF-8") + " -- " + new String(endKey.getData(),"UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace(System.err);
+ }
+ }
}
/* Perform the put operation. */
=== modified file 'src/com/sleepycat/je/dbi/CursorImpl.java'
--- src/com/sleepycat/je/dbi/CursorImpl.java 2008-06-12 16:21:24 +0000
+ src/com/sleepycat/je/dbi/CursorImpl.java 2008-08-04 18:28:04 +0000
@@ -955,15 +955,10 @@
* records following the given key and datum, lock the special EOF node
* for the databaseImpl.
*/
- public void lockNextKeyForInsert(DatabaseEntry key, DatabaseEntry data)
+ public OperationStatus lockNextKeyForInsert(DatabaseEntry key, DatabaseEntry data,
+ DatabaseEntry nextKey, DatabaseEntry nextData)
throws DatabaseException {
-
- DatabaseEntry tempKey = new DatabaseEntry
- (key.getData(), key.getOffset(), key.getSize());
- DatabaseEntry tempData = new DatabaseEntry
- (data.getData(), data.getOffset(), data.getSize());
- tempKey.setPartial(0, 0, true);
- tempData.setPartial(0, 0, true);
+ OperationStatus status = OperationStatus.NOTFOUND;
boolean lockedNextKey = false;
/* Don't search for data if duplicates are not configured. */
@@ -988,7 +983,6 @@
* If we didn't match the key, skip over duplicates to the next
* key with getNextNoDup.
*/
- OperationStatus status;
if ((searchResult & EXACT_KEY) != 0) {
status = getNext
(tempKey, tempData, LockType.RANGE_INSERT, true, true);