0001: /*-
0002: * See the file LICENSE for redistribution information.
0003: *
0004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
0005: *
0006: * $Id: DbCursorDuplicateDeleteTest.java,v 1.54.2.5 2008/01/07 15:14:26 cwl Exp $
0007: */
0008:
0009: package com.sleepycat.je.dbi;
0010:
0011: import java.util.Hashtable;
0012:
0013: import com.sleepycat.je.Cursor;
0014: import com.sleepycat.je.DatabaseEntry;
0015: import com.sleepycat.je.DatabaseException;
0016: import com.sleepycat.je.DbInternal;
0017: import com.sleepycat.je.DeadlockException;
0018: import com.sleepycat.je.LockMode;
0019: import com.sleepycat.je.OperationStatus;
0020: import com.sleepycat.je.Transaction;
0021: import com.sleepycat.je.VerifyConfig;
0022: import com.sleepycat.je.junit.JUnitThread;
0023: import com.sleepycat.je.tree.BIN;
0024: import com.sleepycat.je.tree.DIN;
0025: import com.sleepycat.je.util.StringDbt;
0026:
0027: /**
0028: * Various unit tests for CursorImpl using duplicates.
0029: */
0030: public class DbCursorDuplicateDeleteTest extends DbCursorTestBase {
0031:
0032: private volatile int sequence;
0033:
0034: public DbCursorDuplicateDeleteTest() throws DatabaseException {
0035:
0036: super ();
0037: }
0038:
0039: /**
0040: * Create some simple duplicate data. Delete it all. Try to create
0041: * it again.
0042: */
0043: public void testSimpleDeleteInsert() throws Throwable {
0044:
0045: try {
0046: initEnv(true);
0047: doSimpleDuplicatePuts();
0048: DataWalker dw = new DataWalker(null) {
0049: void perData(String foundKey, String foundData)
0050: throws DatabaseException {
0051:
0052: if (prevKey.equals("")) {
0053: prevKey = foundKey;
0054: }
0055: if (!prevKey.equals(foundKey)) {
0056: deletedEntries = 0;
0057: }
0058: prevKey = foundKey;
0059: if (cursor.delete() == OperationStatus.SUCCESS) {
0060: deletedEntries++;
0061: }
0062: assertEquals(simpleKeyStrings.length
0063: - deletedEntries, cursor.count());
0064: }
0065: };
0066: dw.setIgnoreDataMap(true);
0067: dw.walkData();
0068: doSimpleDuplicatePuts();
0069:
0070: dw = new DataWalker(null);
0071: dw.setIgnoreDataMap(true);
0072: dw.walkData();
0073: assertEquals(simpleKeyStrings.length
0074: * simpleKeyStrings.length, dw.nEntries);
0075: } catch (Throwable t) {
0076: t.printStackTrace();
0077: throw t;
0078: }
0079: }
0080:
0081: public void testCountAfterDelete() throws Throwable {
0082: initEnv(true);
0083: DatabaseEntry key = new DatabaseEntry(new byte[] { (byte) 'n',
0084: (byte) 'o', (byte) 0 });
0085: DatabaseEntry val1 = new DatabaseEntry(new byte[] { (byte) 'k',
0086: (byte) '1', (byte) 0 });
0087: DatabaseEntry val2 = new DatabaseEntry(new byte[] { (byte) 'k',
0088: (byte) '2', (byte) 0 });
0089: OperationStatus status = exampleDb
0090: .putNoDupData(null, key, val1);
0091: if (status != OperationStatus.SUCCESS)
0092: throw new Exception("status on put 1=" + status);
0093: status = exampleDb.putNoDupData(null, key, val2);
0094: if (status != OperationStatus.SUCCESS)
0095: throw new Exception("status on put 2=" + status);
0096:
0097: Cursor c = exampleDb.openCursor(null, null);
0098: try {
0099: status = c.getSearchKey(key, new DatabaseEntry(),
0100: LockMode.DEFAULT);
0101: if (status != OperationStatus.SUCCESS)
0102: throw new Exception("status on search=" + status);
0103: assertEquals(2, c.count());
0104: status = c.delete();
0105: if (status != OperationStatus.SUCCESS)
0106: throw new Exception("err on del 1=" + status);
0107: status = c.getNext(key, new DatabaseEntry(),
0108: LockMode.DEFAULT);
0109: if (status != OperationStatus.SUCCESS)
0110: throw new Exception("err on next=" + status);
0111: status = c.delete();
0112: if (status != OperationStatus.SUCCESS)
0113: throw new Exception("err on del 2=" + status);
0114: assertEquals(0, c.count());
0115: } finally {
0116: c.close();
0117: }
0118:
0119: status = exampleDb.putNoDupData(null, key, val1);
0120: if (status != OperationStatus.SUCCESS)
0121: throw new Exception("err on put 3=" + status);
0122:
0123: c = exampleDb.openCursor(null, null);
0124: try {
0125: status = c.getSearchKey(key, new DatabaseEntry(),
0126: LockMode.DEFAULT);
0127: if (status != OperationStatus.SUCCESS)
0128: throw new Exception("err on search=" + status);
0129: assertEquals(1, c.count());
0130: } finally {
0131: c.close();
0132: }
0133: }
0134:
0135: public void testDuplicateDeletionAll() throws Throwable {
0136:
0137: try {
0138: initEnv(true);
0139: Hashtable dataMap = new Hashtable();
0140: createRandomDuplicateData(10, 1000, dataMap, false, false);
0141:
0142: DataWalker dw = new DataWalker(dataMap) {
0143: void perData(String foundKey, String foundData)
0144: throws DatabaseException {
0145:
0146: Hashtable ht = (Hashtable) dataMap.get(foundKey);
0147: if (ht == null) {
0148: fail("didn't find ht " + foundKey + "/"
0149: + foundData);
0150: }
0151:
0152: if (ht.get(foundData) != null) {
0153: ht.remove(foundData);
0154: if (ht.size() == 0) {
0155: dataMap.remove(foundKey);
0156: }
0157: } else {
0158: fail("didn't find " + foundKey + "/"
0159: + foundData);
0160: }
0161:
0162: /* Make sure keys are ascending/descending. */
0163: assertTrue(foundKey.compareTo(prevKey) >= 0);
0164:
0165: /*
0166: * Make sure duplicate items within key are asc/desc.
0167: */
0168: if (prevKey.equals(foundKey)) {
0169: if (duplicateComparisonFunction == null) {
0170: assertTrue(foundData.compareTo(prevData) >= 0);
0171: } else {
0172: assertTrue(duplicateComparisonFunction
0173: .compare(foundData.getBytes(),
0174: prevData.getBytes()) >= 0);
0175: }
0176: prevData = foundData;
0177: } else {
0178: prevData = "";
0179: }
0180:
0181: prevKey = foundKey;
0182: assertTrue(cursor.delete() == OperationStatus.SUCCESS);
0183: assertEquals(ht.size(), cursor.count());
0184: }
0185: };
0186: dw.setIgnoreDataMap(true);
0187: dw.walkData();
0188: assertTrue(dataMap.size() == 0);
0189:
0190: dw = new DataWalker(dataMap) {
0191: void perData(String foundKey, String foundData)
0192: throws DatabaseException {
0193:
0194: fail("data found after deletion: " + foundKey + "/"
0195: + foundData);
0196: }
0197: };
0198: dw.setIgnoreDataMap(true);
0199: dw.walkData();
0200: } catch (Throwable t) {
0201: t.printStackTrace();
0202: throw t;
0203: }
0204: }
0205:
0206: public void testDuplicateDeletionAssorted() throws Throwable {
0207:
0208: try {
0209: initEnv(true);
0210: Hashtable dataMap = new Hashtable();
0211: Hashtable deletedDataMap = new Hashtable();
0212: createRandomDuplicateData(10, 1000, dataMap, false, false);
0213:
0214: /* Use the DataWalker.addedData field for a deleted Data Map. */
0215: DataWalker dw = new DataWalker(dataMap, deletedDataMap) {
0216: void perData(String foundKey, String foundData)
0217: throws DatabaseException {
0218:
0219: Hashtable ht = (Hashtable) dataMap.get(foundKey);
0220: if (ht == null) {
0221: fail("didn't find ht " + foundKey + "/"
0222: + foundData);
0223: }
0224:
0225: /* Make sure keys are ascending/descending. */
0226: assertTrue(foundKey.compareTo(prevKey) >= 0);
0227:
0228: /*
0229: * Make sure duplicate items within key are asc/desc.
0230: */
0231: if (prevKey.equals(foundKey)) {
0232: if (duplicateComparisonFunction == null) {
0233: assertTrue(foundData.compareTo(prevData) >= 0);
0234: } else {
0235: assertTrue(duplicateComparisonFunction
0236: .compare(foundData.getBytes(),
0237: prevData.getBytes()) >= 0);
0238: }
0239: prevData = foundData;
0240: } else {
0241: prevData = "";
0242: }
0243:
0244: prevKey = foundKey;
0245: if (rnd.nextInt(10) < 8) {
0246: Hashtable delht = (Hashtable) addedDataMap
0247: .get(foundKey);
0248: if (delht == null) {
0249: delht = new Hashtable();
0250: addedDataMap.put(foundKey, delht);
0251: }
0252: delht.put(foundData, foundData);
0253: assertTrue(cursor.delete() == OperationStatus.SUCCESS);
0254:
0255: if (ht.get(foundData) == null) {
0256: fail("didn't find " + foundKey + "/"
0257: + foundData);
0258: }
0259: ht.remove(foundData);
0260: assertEquals(ht.size(), cursor.count());
0261: if (ht.size() == 0) {
0262: dataMap.remove(foundKey);
0263: }
0264: }
0265: }
0266: };
0267: dw.setIgnoreDataMap(true);
0268: dw.walkData();
0269:
0270: dw = new DataWalker(dataMap, deletedDataMap) {
0271: void perData(String foundKey, String foundData)
0272: throws DatabaseException {
0273:
0274: Hashtable delht = (Hashtable) addedDataMap
0275: .get(foundKey);
0276: if (delht != null && delht.get(foundData) != null) {
0277: fail("found deleted entry for " + foundKey
0278: + "/" + foundData);
0279: }
0280:
0281: Hashtable ht = (Hashtable) dataMap.get(foundKey);
0282: if (ht == null) {
0283: fail("couldn't find hashtable for " + foundKey);
0284: }
0285: if (ht.get(foundData) == null) {
0286: fail("couldn't find entry for " + foundKey
0287: + "/" + foundData);
0288: }
0289: ht.remove(foundData);
0290: if (ht.size() == 0) {
0291: dataMap.remove(foundKey);
0292: }
0293: }
0294: };
0295: dw.setIgnoreDataMap(true);
0296: dw.walkData();
0297: assertTrue(dataMap.size() == 0);
0298: } catch (Throwable t) {
0299: t.printStackTrace();
0300: throw t;
0301: }
0302: }
0303:
0304: public void testDuplicateDeletionAssortedSR15375() throws Throwable {
0305:
0306: try {
0307: initEnv(true);
0308: Hashtable dataMap = new Hashtable();
0309: Hashtable deletedDataMap = new Hashtable();
0310: createRandomDuplicateData(10, 1000, dataMap, false, false);
0311:
0312: /* Use the DataWalker.addedData field for a deleted Data Map. */
0313: DataWalker dw = new DataWalker(dataMap, deletedDataMap) {
0314: void perData(String foundKey, String foundData)
0315: throws DatabaseException {
0316:
0317: Hashtable ht = (Hashtable) dataMap.get(foundKey);
0318: if (ht == null) {
0319: fail("didn't find ht " + foundKey + "/"
0320: + foundData);
0321: }
0322:
0323: /* Make sure keys are ascending/descending. */
0324: assertTrue(foundKey.compareTo(prevKey) >= 0);
0325:
0326: /*
0327: * Make sure duplicate items within key are asc/desc.
0328: */
0329: if (prevKey.equals(foundKey)) {
0330: if (duplicateComparisonFunction == null) {
0331: assertTrue(foundData.compareTo(prevData) >= 0);
0332: } else {
0333: assertTrue(duplicateComparisonFunction
0334: .compare(foundData.getBytes(),
0335: prevData.getBytes()) >= 0);
0336: }
0337: prevData = foundData;
0338: } else {
0339: prevData = "";
0340: }
0341:
0342: prevKey = foundKey;
0343: if (rnd.nextInt(10) < 8) {
0344: Hashtable delht = (Hashtable) addedDataMap
0345: .get(foundKey);
0346: if (delht == null) {
0347: delht = new Hashtable();
0348: addedDataMap.put(foundKey, delht);
0349: }
0350: delht.put(foundData, foundData);
0351: assertTrue(cursor.delete() == OperationStatus.SUCCESS);
0352:
0353: if (ht.get(foundData) == null) {
0354: fail("didn't find " + foundKey + "/"
0355: + foundData);
0356: }
0357: ht.remove(foundData);
0358: assertEquals(ht.size(), cursor.count());
0359: if (ht.size() == 0) {
0360: dataMap.remove(foundKey);
0361: }
0362:
0363: /*
0364: * Add back in a duplicate for each one deleted.
0365: */
0366: String newDupData = foundData + "x";
0367: StringDbt newDupDBT = new StringDbt(newDupData);
0368: assertTrue(putAndVerifyCursor(cursor,
0369: new StringDbt(foundKey), newDupDBT,
0370: true) == OperationStatus.SUCCESS);
0371: ht.put(newDupData, newDupData);
0372: }
0373: }
0374: };
0375: dw.setIgnoreDataMap(true);
0376: dw.walkData();
0377:
0378: dw = new DataWalker(dataMap, deletedDataMap) {
0379: void perData(String foundKey, String foundData)
0380: throws DatabaseException {
0381:
0382: Hashtable delht = (Hashtable) addedDataMap
0383: .get(foundKey);
0384: if (delht != null && delht.get(foundData) != null) {
0385: fail("found deleted entry for " + foundKey
0386: + "/" + foundData);
0387: }
0388:
0389: Hashtable ht = (Hashtable) dataMap.get(foundKey);
0390: if (ht == null) {
0391: fail("couldn't find hashtable for " + foundKey);
0392: }
0393: if (ht.get(foundData) == null) {
0394: fail("couldn't find entry for " + foundKey
0395: + "/" + foundData);
0396: }
0397: ht.remove(foundData);
0398: if (ht.size() == 0) {
0399: dataMap.remove(foundKey);
0400: }
0401: }
0402: };
0403: dw.setIgnoreDataMap(true);
0404: dw.walkData();
0405: assertTrue(dataMap.size() == 0);
0406: } catch (Throwable t) {
0407: t.printStackTrace();
0408: throw t;
0409: }
0410: }
0411:
0412: public void testDuplicateDeleteFirst() throws Throwable {
0413:
0414: try {
0415: initEnv(true);
0416: Hashtable dataMap = new Hashtable();
0417: Hashtable deletedDataMap = new Hashtable();
0418: createRandomDuplicateData(-10, 10, dataMap, false, false);
0419:
0420: /* Use the DataWalker.addedData field for a deleted Data Map. */
0421: DataWalker dw = new DataWalker(dataMap, deletedDataMap) {
0422: void perData(String foundKey, String foundData)
0423: throws DatabaseException {
0424:
0425: Hashtable ht = (Hashtable) dataMap.get(foundKey);
0426: if (ht == null) {
0427: fail("didn't find ht " + foundKey + "/"
0428: + foundData);
0429: }
0430:
0431: /* Make sure keys are ascending/descending. */
0432: assertTrue(foundKey.compareTo(prevKey) >= 0);
0433:
0434: /*
0435: * Make sure duplicate items within key are asc/desc.
0436: */
0437: if (prevKey.equals(foundKey)) {
0438: if (duplicateComparisonFunction == null) {
0439: assertTrue(foundData.compareTo(prevData) >= 0);
0440: } else {
0441: assertTrue(duplicateComparisonFunction
0442: .compare(foundData.getBytes(),
0443: prevData.getBytes()) >= 0);
0444: }
0445: prevData = foundData;
0446: } else {
0447: prevData = "";
0448: if (cursor.count() > 1) {
0449: Hashtable delht = (Hashtable) addedDataMap
0450: .get(foundKey);
0451: if (delht == null) {
0452: delht = new Hashtable();
0453: addedDataMap.put(foundKey, delht);
0454: }
0455: delht.put(foundData, foundData);
0456: assertTrue(cursor.delete() == OperationStatus.SUCCESS);
0457:
0458: if (ht.get(foundData) == null) {
0459: fail("didn't find " + foundKey + "/"
0460: + foundData);
0461: }
0462: ht.remove(foundData);
0463: assertEquals(ht.size(), cursor.count());
0464: if (ht.size() == 0) {
0465: dataMap.remove(foundKey);
0466: }
0467: }
0468: }
0469:
0470: prevKey = foundKey;
0471: }
0472: };
0473: dw.setIgnoreDataMap(true);
0474: dw.walkData();
0475:
0476: dw = new DataWalker(dataMap, deletedDataMap) {
0477: void perData(String foundKey, String foundData)
0478: throws DatabaseException {
0479:
0480: Hashtable delht = (Hashtable) addedDataMap
0481: .get(foundKey);
0482: if (delht != null && delht.get(foundData) != null) {
0483: fail("found deleted entry for " + foundKey
0484: + "/" + foundData);
0485: }
0486:
0487: Hashtable ht = (Hashtable) dataMap.get(foundKey);
0488: if (ht == null) {
0489: fail("couldn't find hashtable for " + foundKey);
0490: }
0491: if (ht.get(foundData) == null) {
0492: fail("couldn't find entry for " + foundKey
0493: + "/" + foundData);
0494: }
0495: ht.remove(foundData);
0496: if (ht.size() == 0) {
0497: dataMap.remove(foundKey);
0498: }
0499: }
0500: };
0501: dw.setIgnoreDataMap(true);
0502: dw.walkData();
0503: assertTrue(dataMap.size() == 0);
0504: } catch (Throwable t) {
0505: t.printStackTrace();
0506: throw t;
0507: }
0508: }
0509:
0510: /**
0511: * Similar to above test, but there was some question about whether
0512: * this tests new functionality or not. Insert k1/d1 and d1/k1.
0513: * Iterate through the data and delete k1/d1. Reinsert k1/d1 and
0514: * make sure it inserts ok.
0515: */
0516: public void testSimpleSingleElementDupTree()
0517: throws DatabaseException {
0518:
0519: initEnv(true);
0520: StringDbt key = new StringDbt("k1");
0521: StringDbt data1 = new StringDbt("d1");
0522: StringDbt data2 = new StringDbt("d2");
0523:
0524: assertEquals(OperationStatus.SUCCESS, putAndVerifyCursor(
0525: cursor, key, data1, true));
0526: assertEquals(OperationStatus.SUCCESS, putAndVerifyCursor(
0527: cursor, key, data2, true));
0528:
0529: DataWalker dw = new DataWalker(null) {
0530: void perData(String foundKey, String foundData)
0531: throws DatabaseException {
0532:
0533: if (foundKey.equals("k1") && deletedEntries == 0) {
0534: if (cursor.delete() == OperationStatus.SUCCESS) {
0535: deletedEntries++;
0536: }
0537: }
0538: }
0539: };
0540: dw.setIgnoreDataMap(true);
0541: dw.walkData();
0542:
0543: dw = new DataWalker(null) {
0544: void perData(String foundKey, String foundData)
0545: throws DatabaseException {
0546:
0547: deletedEntries++;
0548: }
0549: };
0550: dw.setIgnoreDataMap(true);
0551: dw.walkData();
0552:
0553: assertEquals(1, dw.deletedEntries);
0554: }
0555:
0556: public void testEmptyNodes() throws Throwable {
0557:
0558: initEnv(true);
0559: synchronized (DbInternal.envGetEnvironmentImpl(exampleEnv)
0560: .getINCompressor()) {
0561: writeEmptyNodeData();
0562:
0563: BIN bin = null;
0564: try {
0565: bin = (BIN) DbInternal.dbGetDatabaseImpl(exampleDb)
0566: .getTree().getFirstNode();
0567: DIN dupRoot = (DIN) bin.fetchTarget(0);
0568: bin.releaseLatch();
0569: bin = null;
0570: dupRoot.latch();
0571: bin = (BIN) DbInternal.dbGetDatabaseImpl(exampleDb)
0572: .getTree().getFirstNode(dupRoot);
0573: bin.compress(null, true, null);
0574: bin.releaseLatch();
0575: bin = null;
0576:
0577: Cursor cursor = exampleDb.openCursor(null, null);
0578: DatabaseEntry foundKey = new DatabaseEntry();
0579: DatabaseEntry foundData = new DatabaseEntry();
0580: OperationStatus status = cursor.getFirst(foundKey,
0581: foundData, LockMode.DEFAULT);
0582: cursor.close();
0583: assertEquals(OperationStatus.SUCCESS, status);
0584: } finally {
0585: if (bin != null) {
0586: bin.releaseLatch();
0587: }
0588: }
0589: }
0590: }
0591:
0592: public void testDeletedReplaySR8984() throws DatabaseException {
0593:
0594: initEnvTransactional(true);
0595: Transaction txn = exampleEnv.beginTransaction(null, null);
0596: Cursor c = exampleDb.openCursor(txn, null);
0597: c.put(simpleKeys[0], simpleData[0]);
0598: c.delete();
0599: for (int i = 1; i < 3; i++) {
0600: c.put(simpleKeys[0], simpleData[i]);
0601: }
0602: c.close();
0603: txn.abort();
0604: txn = exampleEnv.beginTransaction(null, null);
0605: c = exampleDb.openCursor(txn, null);
0606: assertEquals(OperationStatus.NOTFOUND, c.getFirst(
0607: new DatabaseEntry(), new DatabaseEntry(),
0608: LockMode.DEFAULT));
0609: c.close();
0610: txn.commit();
0611: }
0612:
0613: public void testDuplicateDeadlockSR9885() throws DatabaseException {
0614:
0615: initEnvTransactional(true);
0616: Transaction txn = exampleEnv.beginTransaction(null, null);
0617: Cursor c = exampleDb.openCursor(txn, null);
0618: for (int i = 0; i < simpleKeyStrings.length; i++) {
0619: c.put(simpleKeys[0], simpleData[i]);
0620: }
0621: c.close();
0622: txn.commit();
0623: sequence = 0;
0624:
0625: JUnitThread tester1 = new JUnitThread("testDuplicateDeadlock1") {
0626: public void testBody() throws DatabaseException {
0627:
0628: DatabaseEntry key = new DatabaseEntry();
0629: DatabaseEntry data = new DatabaseEntry();
0630: Transaction txn1 = exampleEnv.beginTransaction(null,
0631: null);
0632: Cursor cursor1 = exampleDb.openCursor(txn1, null);
0633: try {
0634: cursor1.getFirst(key, data, LockMode.DEFAULT);
0635: sequence++;
0636: while (sequence < 2) {
0637: Thread.yield();
0638: }
0639: cursor1.delete();
0640: sequence++;
0641: while (sequence < 4) {
0642: Thread.yield();
0643: }
0644:
0645: } catch (DeadlockException DBE) {
0646: } finally {
0647: cursor1.close();
0648: txn1.abort();
0649: sequence = 4;
0650: }
0651: }
0652: };
0653:
0654: JUnitThread tester2 = new JUnitThread("testDuplicateDeadlock2") {
0655: public void testBody() throws DatabaseException {
0656:
0657: DatabaseEntry key = new DatabaseEntry();
0658: DatabaseEntry data = new DatabaseEntry();
0659: Transaction txn2 = exampleEnv.beginTransaction(null,
0660: null);
0661: Cursor cursor2 = exampleDb.openCursor(txn2, null);
0662: try {
0663: while (sequence < 1) {
0664: Thread.yield();
0665: }
0666: cursor2.getLast(key, data, LockMode.DEFAULT);
0667: sequence++;
0668: //cursor2.put(key,
0669: //new DatabaseEntry("d1d1d1".getBytes()));
0670: cursor2.delete();
0671: sequence++;
0672: while (sequence < 4) {
0673: Thread.yield();
0674: }
0675:
0676: } catch (DeadlockException DBE) {
0677: } finally {
0678: cursor2.close();
0679: txn2.abort();
0680: sequence = 4;
0681: }
0682: }
0683: };
0684:
0685: try {
0686: tester1.start();
0687: tester2.start();
0688: tester1.finishTest();
0689: tester2.finishTest();
0690: DatabaseImpl dbImpl = DbInternal
0691: .dbGetDatabaseImpl(exampleDb);
0692: assertTrue(dbImpl.verify(new VerifyConfig(), dbImpl
0693: .getEmptyStats()));
0694: } catch (Throwable T) {
0695: fail("testDuplicateDeadlock caught: " + T);
0696: }
0697: }
0698:
0699: public void testSR9992() throws DatabaseException {
0700:
0701: initEnvTransactional(true);
0702: Transaction txn = exampleEnv.beginTransaction(null, null);
0703: Cursor c = exampleDb.openCursor(txn, null);
0704: for (int i = 1; i < simpleKeys.length; i++) {
0705: c.put(simpleKeys[0], simpleData[i]);
0706: }
0707: DatabaseEntry key = new DatabaseEntry();
0708: DatabaseEntry data = new DatabaseEntry();
0709: c.getCurrent(key, data, LockMode.DEFAULT);
0710: c.delete();
0711: /* Expect "Can't replace a duplicate with different data." */
0712: assertEquals(OperationStatus.NOTFOUND, c
0713: .putCurrent(new DatabaseEntry("aaaa".getBytes())));
0714: c.close();
0715: txn.commit();
0716: }
0717:
0718: public void testSR9900() throws DatabaseException {
0719:
0720: initEnvTransactional(true);
0721: Transaction txn = exampleEnv.beginTransaction(null, null);
0722: Cursor c = exampleDb.openCursor(txn, null);
0723: c.put(simpleKeys[0], simpleData[0]);
0724: DatabaseEntry key = new DatabaseEntry();
0725: DatabaseEntry data = new DatabaseEntry();
0726: c.getCurrent(key, data, LockMode.DEFAULT);
0727: c.delete();
0728: /* Expect "Can't replace a duplicate with different data." */
0729: assertEquals(OperationStatus.NOTFOUND, c
0730: .putCurrent(new DatabaseEntry("aaaa".getBytes())));
0731: c.close();
0732: txn.commit();
0733: }
0734:
0735: private void put(int data, int key) throws DatabaseException {
0736:
0737: byte[] keyBytes = new byte[1];
0738: keyBytes[0] = (byte) (key & 0xff);
0739: DatabaseEntry keyDbt = new DatabaseEntry(keyBytes);
0740:
0741: byte[] dataBytes = new byte[1];
0742: if (data == -1) {
0743: dataBytes = new byte[0];
0744: } else {
0745: dataBytes[0] = (byte) (data & 0xff);
0746: }
0747: DatabaseEntry dataDbt = new DatabaseEntry(dataBytes);
0748:
0749: OperationStatus status = exampleDb.put(null, keyDbt, dataDbt);
0750: if (status != OperationStatus.SUCCESS) {
0751: System.out.println("db.put returned " + status
0752: + " for key " + key + "/" + data);
0753: }
0754: }
0755:
0756: private void del(int key) throws DatabaseException {
0757:
0758: byte[] keyBytes = new byte[1];
0759: keyBytes[0] = (byte) (key & 0xff);
0760: DatabaseEntry keyDbt = new DatabaseEntry(keyBytes);
0761:
0762: OperationStatus status = exampleDb.delete(null, keyDbt);
0763: if (status != OperationStatus.SUCCESS) {
0764: System.out.println("db.del returned " + status
0765: + " for key " + key);
0766: }
0767: }
0768:
0769: private void delBoth(int key, int data) throws DatabaseException {
0770:
0771: byte[] keyBytes = new byte[1];
0772: keyBytes[0] = (byte) (key & 0xff);
0773: DatabaseEntry keyDbt = new DatabaseEntry(keyBytes);
0774:
0775: byte[] dataBytes = new byte[1];
0776: dataBytes[0] = (byte) (data & 0xff);
0777: DatabaseEntry dataDbt = new DatabaseEntry(dataBytes);
0778:
0779: Cursor cursor = exampleDb.openCursor(null, null);
0780: OperationStatus status = cursor.getSearchBoth(keyDbt, dataDbt,
0781: LockMode.DEFAULT);
0782: if (status != OperationStatus.SUCCESS) {
0783: System.out.println("getSearchBoth returned " + status
0784: + " for key " + key + "/" + data);
0785: }
0786:
0787: status = cursor.delete();
0788: if (status != OperationStatus.SUCCESS) {
0789: System.out.println("Dbc.delete returned " + status
0790: + " for key " + key + "/" + data);
0791: }
0792: cursor.close();
0793: }
0794:
0795: private void writeEmptyNodeData() throws DatabaseException {
0796:
0797: put(101, 1);
0798: put(102, 2);
0799: put(103, 3);
0800: put(104, 4);
0801: put(105, 5);
0802: put(106, 6);
0803: del(1);
0804: del(3);
0805: del(5);
0806: put(101, 1);
0807: put(103, 3);
0808: put(105, 5);
0809: del(1);
0810: del(3);
0811: del(5);
0812: put(101, 1);
0813: put(103, 3);
0814: put(105, 5);
0815: del(1);
0816: del(3);
0817: del(5);
0818: put(101, 1);
0819: put(103, 3);
0820: put(105, 5);
0821: del(1);
0822: del(2);
0823: del(3);
0824: del(4);
0825: del(5);
0826: del(6);
0827: put(102, 2);
0828: put(104, 4);
0829: put(106, 6);
0830: put(101, 1);
0831: put(103, 3);
0832: put(105, 5);
0833: del(1);
0834: del(2);
0835: del(3);
0836: del(4);
0837: del(5);
0838: del(6);
0839: put(102, 2);
0840: put(104, 4);
0841: put(106, 6);
0842: put(101, 1);
0843: put(103, 3);
0844: put(105, 5);
0845: del(1);
0846: del(2);
0847: del(3);
0848: del(4);
0849: del(5);
0850: del(6);
0851: put(102, 2);
0852: put(104, 4);
0853: put(106, 6);
0854: put(101, 1);
0855: put(103, 3);
0856: put(105, 5);
0857: del(1);
0858: del(2);
0859: del(3);
0860: del(4);
0861: del(5);
0862: del(6);
0863: put(102, 2);
0864: put(104, 4);
0865: put(106, 6);
0866: put(101, 1);
0867: put(103, 3);
0868: put(105, 5);
0869: del(1);
0870: del(2);
0871: del(3);
0872: del(4);
0873: del(5);
0874: del(6);
0875: put(102, 2);
0876: put(104, 4);
0877: put(106, 6);
0878: put(101, 1);
0879: put(103, 3);
0880: put(105, 5);
0881: del(1);
0882: del(2);
0883: del(3);
0884: del(4);
0885: del(5);
0886: del(6);
0887: put(-1, 2);
0888: put(-1, 4);
0889: put(-1, 6);
0890: put(-1, 1);
0891: put(-1, 3);
0892: put(-1, 5);
0893: del(1);
0894: del(2);
0895: del(3);
0896: del(4);
0897: del(5);
0898: del(6);
0899: put(102, 2);
0900: put(104, 4);
0901: put(106, 6);
0902: put(101, 1);
0903: put(103, 3);
0904: put(105, 5);
0905: del(1);
0906: del(2);
0907: del(3);
0908: del(4);
0909: del(5);
0910: del(6);
0911: put(102, 2);
0912: put(104, 4);
0913: put(106, 6);
0914: put(101, 1);
0915: put(103, 3);
0916: put(105, 5);
0917: put(102, 1);
0918: put(103, 1);
0919: put(104, 1);
0920: put(105, 1);
0921: delBoth(1, 101);
0922: delBoth(1, 102);
0923: delBoth(1, 103);
0924: delBoth(1, 104);
0925: delBoth(1, 105);
0926: put(101, 1);
0927: put(102, 1);
0928: put(103, 1);
0929: put(104, 1);
0930: put(105, 1);
0931: delBoth(1, 101);
0932: delBoth(1, 102);
0933: delBoth(1, 103);
0934: delBoth(1, 104);
0935: delBoth(1, 105);
0936: put(101, 1);
0937: put(102, 1);
0938: put(103, 1);
0939: put(104, 1);
0940: put(105, 1);
0941: delBoth(1, 101);
0942: delBoth(1, 102);
0943: delBoth(1, 103);
0944: delBoth(1, 104);
0945: delBoth(1, 105);
0946: put(101, 1);
0947: put(102, 1);
0948: put(103, 1);
0949: put(104, 1);
0950: put(105, 1);
0951: delBoth(1, 102);
0952: delBoth(1, 103);
0953: delBoth(1, 104);
0954: delBoth(1, 105);
0955: put(103, 2);
0956: put(104, 2);
0957: put(105, 2);
0958: put(106, 2);
0959: delBoth(2, 102);
0960: delBoth(2, 103);
0961: delBoth(2, 104);
0962: delBoth(2, 105);
0963: delBoth(2, 106);
0964: put(102, 2);
0965: put(103, 2);
0966: put(104, 2);
0967: put(105, 2);
0968: put(106, 2);
0969: delBoth(2, 102);
0970: delBoth(2, 103);
0971: delBoth(2, 104);
0972: delBoth(2, 105);
0973: delBoth(2, 106);
0974: put(102, 2);
0975: put(103, 2);
0976: put(104, 2);
0977: put(105, 2);
0978: put(106, 2);
0979: delBoth(2, 102);
0980: delBoth(2, 103);
0981: delBoth(2, 104);
0982: delBoth(2, 105);
0983: delBoth(2, 106);
0984: put(102, 2);
0985: put(103, 2);
0986: put(104, 2);
0987: put(105, 2);
0988: put(106, 2);
0989: delBoth(2, 102);
0990: delBoth(2, 103);
0991: delBoth(2, 104);
0992: delBoth(2, 105);
0993: delBoth(2, 106);
0994: put(107, 6);
0995: put(108, 6);
0996: put(109, 6);
0997: put(110, 6);
0998: delBoth(6, 106);
0999: delBoth(6, 107);
1000: delBoth(6, 108);
1001: delBoth(6, 109);
1002: delBoth(6, 110);
1003: put(106, 6);
1004: put(107, 6);
1005: put(108, 6);
1006: put(109, 6);
1007: put(110, 6);
1008: delBoth(6, 106);
1009: delBoth(6, 107);
1010: delBoth(6, 108);
1011: delBoth(6, 109);
1012: delBoth(6, 110);
1013: put(106, 6);
1014: put(107, 6);
1015: put(108, 6);
1016: put(109, 6);
1017: put(110, 6);
1018: delBoth(6, 106);
1019: delBoth(6, 107);
1020: delBoth(6, 108);
1021: delBoth(6, 109);
1022: delBoth(6, 110);
1023: put(106, 6);
1024: put(107, 6);
1025: put(108, 6);
1026: put(109, 6);
1027: put(110, 6);
1028: delBoth(6, 107);
1029: delBoth(6, 108);
1030: delBoth(6, 109);
1031: delBoth(6, 110);
1032: put(106, 5);
1033: put(107, 5);
1034: put(108, 5);
1035: put(109, 5);
1036: delBoth(5, 105);
1037: delBoth(5, 106);
1038: delBoth(5, 107);
1039: delBoth(5, 108);
1040: delBoth(5, 109);
1041: put(105, 5);
1042: put(106, 5);
1043: put(107, 5);
1044: put(108, 5);
1045: put(109, 5);
1046: delBoth(5, 105);
1047: delBoth(5, 106);
1048: delBoth(5, 107);
1049: delBoth(5, 108);
1050: delBoth(5, 109);
1051: put(105, 5);
1052: put(106, 5);
1053: put(107, 5);
1054: put(108, 5);
1055: put(109, 5);
1056: delBoth(5, 105);
1057: delBoth(5, 106);
1058: delBoth(5, 107);
1059: delBoth(5, 108);
1060: delBoth(5, 109);
1061: put(105, 5);
1062: put(106, 5);
1063: put(107, 5);
1064: put(108, 5);
1065: put(109, 5);
1066: delBoth(5, 106);
1067: delBoth(5, 107);
1068: delBoth(5, 108);
1069: delBoth(5, 109);
1070: delBoth(1, 101);
1071: }
1072: }
|