KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > dbi > DbCursorDuplicateTest


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: DbCursorDuplicateTest.java,v 1.53 2006/10/30 21:14:43 bostic Exp $
7  */

8
9 package com.sleepycat.je.dbi;
10
11 import java.util.Comparator JavaDoc;
12 import java.util.Hashtable JavaDoc;
13
14 import com.sleepycat.je.Cursor;
15 import com.sleepycat.je.DatabaseEntry;
16 import com.sleepycat.je.DatabaseException;
17 import com.sleepycat.je.LockMode;
18 import com.sleepycat.je.OperationStatus;
19 import com.sleepycat.je.Transaction;
20 import com.sleepycat.je.tree.DuplicateEntryException;
21 import com.sleepycat.je.util.StringDbt;
22
23 /**
24  * Various unit tests for CursorImpl using duplicates.
25  */

26 public class DbCursorDuplicateTest extends DbCursorTestBase {
27
28     public DbCursorDuplicateTest()
29         throws DatabaseException {
30
31         super();
32     }
33
34     /**
35      * Rudimentary insert/retrieve test. Walk over the results forwards.
36      */

37     public void testDuplicateCreationForward()
38     throws Throwable JavaDoc {
39
40         initEnv(true);
41         try {
42             doDuplicateTest(true, false);
43         } catch (Throwable JavaDoc t) {
44             t.printStackTrace();
45             throw t;
46         }
47     }
48
49     /**
50      * Same as testDuplicateCreationForward except uses keylast.
51      */

52     public void testDuplicateCreationForwardKeyLast()
53     throws Throwable JavaDoc {
54
55         initEnv(true);
56         try {
57             doDuplicateTest(true, true);
58         } catch (Throwable JavaDoc t) {
59             t.printStackTrace();
60             throw t;
61         }
62     }
63
64     /**
65      * Rudimentary insert/retrieve test. Walk over the results backwards.
66      */

67     public void testDuplicateCreationBackwards()
68     throws Throwable JavaDoc {
69
70         initEnv(true);
71         try {
72             doDuplicateTest(false, false);
73         } catch (Throwable JavaDoc t) {
74             t.printStackTrace();
75             throw t;
76         }
77     }
78
79     /**
80      * Insert N_KEYS data items into a tree. Set a btreeComparison function.
81      * Iterate through the tree in ascending order. Ensure that the elements
82      * are returned in ascending order.
83      */

84     public void testLargeGetForwardTraverseWithNormalComparisonFunction()
85         throws Throwable JavaDoc {
86
87         try {
88             tearDown();
89             duplicateComparisonFunction = duplicateComparator;
90             setUp();
91             initEnv(true);
92             doDuplicateTest(true, false);
93         } catch (Throwable JavaDoc t) {
94             t.printStackTrace();
95             throw t;
96         }
97     }
98
99     /**
100      * Insert N_KEYS data items into a tree. Set a reverse order
101      * btreeComparison function. Iterate through the tree in ascending order.
102      * Ensure that the elements are returned in ascending order.
103      */

104     public void testLargeGetForwardTraverseWithReverseComparisonFunction()
105         throws Throwable JavaDoc {
106
107         try {
108             tearDown();
109             duplicateComparisonFunction = reverseDuplicateComparator;
110             setUp();
111             initEnv(true);
112             doDuplicateTest(false, false);
113         } catch (Throwable JavaDoc t) {
114             t.printStackTrace();
115             throw t;
116         }
117     }
118
119     /**
120      * Put a bunch of data items into the database in a specific order and
121      * ensure that when read back that we can't putNoDupData without receiving
122      * an error return code.
123      */

124     public void testPutNoDupData()
125     throws Throwable JavaDoc {
126
127         try {
128             initEnv(true);
129             createRandomDuplicateData(null, false);
130
131             DataWalker dw = new DataWalker(simpleDataMap) {
132                     void perData(String JavaDoc foundKey, String JavaDoc foundData)
133                         throws DatabaseException {
134
135                         assertEquals
136                             (OperationStatus.KEYEXIST,
137                              cursor.putNoDupData(new StringDbt(foundKey),
138                                                  new StringDbt(foundData)));
139                     }
140                 };
141             dw.setIgnoreDataMap(true);
142             dw.walkData();
143         } catch (Throwable JavaDoc t) {
144             t.printStackTrace();
145             throw t;
146         }
147     }
148
149     public void testPutNoDupData2()
150     throws Throwable JavaDoc {
151
152         try {
153             initEnv(true);
154         for (int i = 0; i < simpleKeyStrings.length; i++) {
155         OperationStatus status =
156             cursor.putNoDupData(new StringDbt("oneKey"),
157                     new StringDbt(simpleDataStrings[i]));
158         assertEquals(OperationStatus.SUCCESS, status);
159         }
160         } catch (Throwable JavaDoc t) {
161             t.printStackTrace();
162             throw t;
163         }
164     }
165
166     public void testAbortDuplicateTreeCreation()
167     throws Throwable JavaDoc {
168
169         try {
170             initEnvTransactional(true);
171         Transaction txn = exampleEnv.beginTransaction(null, null);
172         Cursor c = exampleDb.openCursor(txn, null);
173         OperationStatus status =
174         c.put(new StringDbt("oneKey"),
175               new StringDbt("firstData"));
176         assertEquals(OperationStatus.SUCCESS, status);
177         c.close();
178         txn.commit();
179         txn = exampleEnv.beginTransaction(null, null);
180         c = exampleDb.openCursor(txn, null);
181         status =
182         c.put(new StringDbt("oneKey"),
183               new StringDbt("secondData"));
184         assertEquals(OperationStatus.SUCCESS, status);
185         c.close();
186         txn.abort();
187         txn = exampleEnv.beginTransaction(null, null);
188         c = exampleDb.openCursor(txn, null);
189         DatabaseEntry keyRet = new DatabaseEntry();
190         DatabaseEntry dataRet = new DatabaseEntry();
191         assertEquals(OperationStatus.SUCCESS,
192              c.getFirst(keyRet, dataRet, LockMode.DEFAULT));
193         assertEquals(1, c.count());
194         assertEquals(OperationStatus.NOTFOUND,
195              c.getNext(keyRet, dataRet, LockMode.DEFAULT));
196         c.close();
197         txn.commit();
198         } catch (Throwable JavaDoc t) {
199             t.printStackTrace();
200             throw t;
201         }
202     }
203
204     /**
205      * Create the usual random duplicate data. Iterate back over it calling
206      * count at each element. Make sure the number of duplicates returned for
207      * a particular key is N_DUPLICATE_PER_KEY. Note that this is somewhat
208      * inefficient, but cautious, in that it calls count for every duplicate
209      * returned, rather than just once for each unique key returned.
210      */

211     public void testDuplicateCount()
212         throws Throwable JavaDoc {
213
214         try {
215             initEnv(true);
216             Hashtable JavaDoc dataMap = new Hashtable JavaDoc();
217
218             createRandomDuplicateData(N_COUNT_TOP_KEYS,
219                                       N_COUNT_DUPLICATES_PER_KEY,
220                                       dataMap, false, true);
221
222             DataWalker dw = new DataWalker(dataMap) {
223                     void perData(String JavaDoc foundKey, String JavaDoc foundData)
224                         throws DatabaseException {
225
226                         assertEquals(N_COUNT_DUPLICATES_PER_KEY,
227                      cursor.count());
228                     }
229                 };
230             dw.setIgnoreDataMap(true);
231             dw.walkData();
232             assertEquals(N_COUNT_DUPLICATES_PER_KEY, dw.nEntries);
233         } catch (Throwable JavaDoc t) {
234             t.printStackTrace();
235             throw t;
236         }
237     }
238
239     public void testDuplicateDuplicates()
240     throws Throwable JavaDoc {
241
242         try {
243             initEnv(true);
244             Hashtable JavaDoc dataMap = new Hashtable JavaDoc();
245
246             String JavaDoc keyString = "aaaa";
247             String JavaDoc dataString = "d1d1";
248             DatabaseEntry keyDbt = new DatabaseEntry();
249             DatabaseEntry dataDbt = new DatabaseEntry();
250             keyDbt.setData(keyString.getBytes());
251             dataDbt.setData(dataString.getBytes());
252             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) ==
253                        OperationStatus.SUCCESS);
254             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) !=
255                        OperationStatus.SUCCESS);
256             assertTrue(cursor.put(keyDbt, dataDbt) ==
257                        OperationStatus.SUCCESS);
258             dataString = "d2d2";
259             dataDbt.setData(dataString.getBytes());
260             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) ==
261                        OperationStatus.SUCCESS);
262             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) !=
263                        OperationStatus.SUCCESS);
264             assertTrue(cursor.put(keyDbt, dataDbt) ==
265                        OperationStatus.SUCCESS);
266             DataWalker dw = new DataWalker(dataMap) {
267                     void perData(String JavaDoc foundKey, String JavaDoc foundData) {
268                     }
269                 };
270             dw.setIgnoreDataMap(true);
271             dw.walkData();
272             assertTrue(dw.nEntries == 2);
273         } catch (Throwable JavaDoc t) {
274             t.printStackTrace();
275             throw t;
276         }
277     }
278
279     public void testDuplicateDuplicatesWithComparators() //cwl
280
throws Throwable JavaDoc {
281
282         try {
283             tearDown();
284             duplicateComparisonFunction = invocationCountingComparator;
285         btreeComparisonFunction = invocationCountingComparator;
286         invocationCountingComparator.setInvocationCount(0);
287             setUp();
288             initEnv(true);
289
290             String JavaDoc keyString = "aaaa";
291             String JavaDoc dataString = "d1d1";
292             DatabaseEntry keyDbt = new DatabaseEntry();
293             DatabaseEntry dataDbt = new DatabaseEntry();
294             keyDbt.setData(keyString.getBytes());
295             dataDbt.setData(dataString.getBytes());
296             assertTrue(cursor.put(keyDbt, dataDbt) ==
297                        OperationStatus.SUCCESS);
298             assertTrue(cursor.put(keyDbt, dataDbt) ==
299                        OperationStatus.SUCCESS);
300
301         InvocationCountingBtreeComparator bTreeICC =
302         (InvocationCountingBtreeComparator)
303         (exampleDb.getConfig().getBtreeComparator());
304
305         InvocationCountingBtreeComparator dupICC =
306         (InvocationCountingBtreeComparator)
307         (exampleDb.getConfig().getDuplicateComparator());
308
309             assertTrue(bTreeICC.getInvocationCount() == 1);
310             assertTrue(dupICC.getInvocationCount() == 2);
311         } catch (Throwable JavaDoc t) {
312             t.printStackTrace();
313             throw t;
314         }
315     }
316
317     public void testDuplicateReplacement()
318     throws Throwable JavaDoc {
319
320         try {
321             initEnv(true);
322             String JavaDoc keyString = "aaaa";
323             String JavaDoc dataString = "d1d1";
324             DatabaseEntry keyDbt = new DatabaseEntry();
325             DatabaseEntry dataDbt = new DatabaseEntry();
326             keyDbt.setData(keyString.getBytes());
327             dataDbt.setData(dataString.getBytes());
328             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) ==
329                OperationStatus.SUCCESS);
330             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) !=
331                OperationStatus.SUCCESS);
332             dataString = "d2d2";
333             dataDbt.setData(dataString.getBytes());
334             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) ==
335                OperationStatus.SUCCESS);
336             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) !=
337                OperationStatus.SUCCESS);
338             DataWalker dw = new DataWalker(null) {
339                     void perData(String JavaDoc foundKey, String JavaDoc foundData)
340                         throws DatabaseException {
341
342                         StringDbt dataDbt = new StringDbt();
343                         dataDbt.setString(foundData);
344                         assertEquals(OperationStatus.SUCCESS,
345                      cursor.putCurrent(dataDbt));
346                     }
347                 };
348             dw.setIgnoreDataMap(true);
349             dw.walkData();
350             assertTrue(dw.nEntries == 2);
351         } catch (Throwable JavaDoc t) {
352             t.printStackTrace();
353             throw t;
354         }
355     }
356
357     public void testDuplicateReplacementFailure()
358     throws Throwable JavaDoc {
359
360         try {
361             initEnv(true);
362             String JavaDoc keyString = "aaaa";
363             String JavaDoc dataString = "d1d1";
364             DatabaseEntry keyDbt = new DatabaseEntry();
365             DatabaseEntry dataDbt = new DatabaseEntry();
366             keyDbt.setData(keyString.getBytes());
367             dataDbt.setData(dataString.getBytes());
368             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) ==
369                        OperationStatus.SUCCESS);
370             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) !=
371                        OperationStatus.SUCCESS);
372             dataString = "d2d2";
373             dataDbt.setData(dataString.getBytes());
374             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) ==
375                        OperationStatus.SUCCESS);
376             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) !=
377                        OperationStatus.SUCCESS);
378             DataWalker dw = new DataWalker(null) {
379                     void perData(String JavaDoc foundKey, String JavaDoc foundData)
380                         throws DatabaseException {
381
382                         StringDbt dataDbt = new StringDbt();
383                         dataDbt.setString("blort");
384                         try {
385                             cursor.putCurrent(dataDbt);
386                             fail("didn't catch DatabaseException");
387                         } catch (DatabaseException DBE) {
388                         }
389                     }
390                 };
391             dw.setIgnoreDataMap(true);
392             dw.walkData();
393             assertTrue(dw.nEntries == 2);
394         } catch (Throwable JavaDoc t) {
395             t.printStackTrace();
396             throw t;
397         }
398     }
399
400     public void testDuplicateReplacementFailure1Dup()
401     throws Throwable JavaDoc {
402
403         try {
404             initEnv(true);
405             String JavaDoc keyString = "aaaa";
406             String JavaDoc dataString = "d1d1";
407             DatabaseEntry keyDbt = new DatabaseEntry();
408             DatabaseEntry dataDbt = new DatabaseEntry();
409             keyDbt.setData(keyString.getBytes());
410             dataDbt.setData(dataString.getBytes());
411             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) ==
412                        OperationStatus.SUCCESS);
413             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) !=
414                        OperationStatus.SUCCESS);
415             DataWalker dw = new DataWalker(null) {
416                     void perData(String JavaDoc foundKey, String JavaDoc foundData)
417                         throws DatabaseException {
418
419                         StringDbt dataDbt = new StringDbt();
420                         dataDbt.setString("blort");
421                         try {
422                             cursor.putCurrent(dataDbt);
423                             fail("didn't catch DatabaseException");
424                         } catch (DatabaseException DBE) {
425                         }
426                     }
427                 };
428             dw.setIgnoreDataMap(true);
429             dw.walkData();
430             assertTrue(dw.nEntries == 1);
431         } catch (Throwable JavaDoc t) {
432             t.printStackTrace();
433             throw t;
434         }
435     }
436
437     public void testDuplicateReplacementWithComparisonFunction()
438     throws Throwable JavaDoc {
439
440         try {
441             tearDown();
442             duplicateComparisonFunction = truncatedComparator;
443             setUp();
444             initEnv(true);
445             String JavaDoc keyString = "aaaa";
446             String JavaDoc dataString = "d1d1";
447             DatabaseEntry keyDbt = new DatabaseEntry();
448             DatabaseEntry dataDbt = new DatabaseEntry();
449             keyDbt.setData(keyString.getBytes());
450             dataDbt.setData(dataString.getBytes());
451             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) ==
452                        OperationStatus.SUCCESS);
453             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) !=
454                        OperationStatus.SUCCESS);
455             dataString = "d2d2";
456             dataDbt.setData(dataString.getBytes());
457             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) ==
458                        OperationStatus.SUCCESS);
459             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) !=
460                        OperationStatus.SUCCESS);
461             DataWalker dw = new DataWalker(null) {
462                     void perData(String JavaDoc foundKey, String JavaDoc foundData)
463                         throws DatabaseException {
464
465                         StringDbt dataDbt = new StringDbt();
466                         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(foundData);
467                         sb.replace(3, 3, "3");
468                         sb.setLength(4);
469                         dataDbt.setString(sb.toString());
470                         assertEquals(OperationStatus.SUCCESS,
471                                      cursor.putCurrent(dataDbt));
472                     }
473                 };
474             dw.setIgnoreDataMap(true);
475             dw.walkData();
476             assertTrue(dw.nEntries == 2);
477         } catch (Throwable JavaDoc t) {
478             t.printStackTrace();
479             throw t;
480         }
481     }
482
483     public void testDuplicateReplacementFailureWithComparisonFunction()
484     throws Throwable JavaDoc {
485
486         try {
487             tearDown();
488             duplicateComparisonFunction = truncatedComparator;
489             setUp();
490             initEnv(true);
491
492             String JavaDoc keyString = "aaaa";
493             String JavaDoc dataString = "d1d1";
494             DatabaseEntry keyDbt = new DatabaseEntry();
495             DatabaseEntry dataDbt = new DatabaseEntry();
496             keyDbt.setData(keyString.getBytes());
497             dataDbt.setData(dataString.getBytes());
498             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) ==
499                        OperationStatus.SUCCESS);
500             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) !=
501                        OperationStatus.SUCCESS);
502             dataString = "d2d2";
503             dataDbt.setData(dataString.getBytes());
504             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) ==
505                        OperationStatus.SUCCESS);
506             assertTrue(cursor.putNoDupData(keyDbt, dataDbt) !=
507                        OperationStatus.SUCCESS);
508             DataWalker dw = new DataWalker(null) {
509                     void perData(String JavaDoc foundKey, String JavaDoc foundData)
510                         throws DatabaseException {
511
512                         StringDbt dataDbt = new StringDbt();
513                         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(foundData);
514                         sb.replace(2, 2, "3");
515                         sb.setLength(4);
516                         dataDbt.setString(sb.toString());
517                         try {
518                             cursor.putCurrent(dataDbt);
519                             fail("didn't catch DatabaseException");
520                         } catch (DatabaseException DBE) {
521                         }
522                     }
523                 };
524             dw.setIgnoreDataMap(true);
525             dw.walkData();
526             assertTrue(dw.nEntries == 2);
527         } catch (Throwable JavaDoc t) {
528             t.printStackTrace();
529             throw t;
530         }
531     }
532
533     private void doDuplicateTest(boolean forward, boolean useKeyLast)
534     throws Throwable JavaDoc {
535
536     Hashtable JavaDoc dataMap = new Hashtable JavaDoc();
537     createRandomDuplicateData(dataMap, useKeyLast);
538
539     DataWalker dw;
540     if (forward) {
541         dw = new DataWalker(dataMap) {
542             void perData(String JavaDoc foundKey, String JavaDoc foundData) {
543             Hashtable JavaDoc ht = (Hashtable JavaDoc) dataMap.get(foundKey);
544             if (ht == null) {
545                 fail("didn't find ht " + foundKey + "/" +
546                  foundData);
547             }
548
549             if (ht.get(foundData) != null) {
550                 ht.remove(foundData);
551                 if (ht.size() == 0) {
552                 dataMap.remove(foundKey);
553                 }
554             } else {
555                 fail("didn't find " + foundKey + "/" + foundData);
556             }
557
558             assertTrue(foundKey.compareTo(prevKey) >= 0);
559
560             if (prevKey.equals(foundKey)) {
561                 if (duplicateComparisonFunction == null) {
562                 assertTrue(foundData.compareTo(prevData) >= 0);
563                 } else {
564                 assertTrue
565                     (duplicateComparisonFunction.compare
566                      (foundData.getBytes(),
567                       prevData.getBytes()) >= 0);
568                 }
569                 prevData = foundData;
570             } else {
571                 prevData = "";
572             }
573
574             prevKey = foundKey;
575             }
576         };
577     } else {
578         dw = new BackwardsDataWalker(dataMap) {
579             void perData(String JavaDoc foundKey, String JavaDoc foundData) {
580             Hashtable JavaDoc ht = (Hashtable JavaDoc) dataMap.get(foundKey);
581             if (ht == null) {
582                 fail("didn't find ht " + foundKey + "/" +
583                  foundData);
584             }
585
586             if (ht.get(foundData) != null) {
587                 ht.remove(foundData);
588                 if (ht.size() == 0) {
589                 dataMap.remove(foundKey);
590                 }
591             } else {
592                 fail("didn't find " + foundKey + "/" + foundData);
593             }
594
595             if (!prevKey.equals("")) {
596                 assertTrue(foundKey.compareTo(prevKey) <= 0);
597             }
598
599             if (prevKey.equals(foundKey)) {
600                 if (!prevData.equals("")) {
601                 if (duplicateComparisonFunction == null) {
602                     assertTrue
603                     (foundData.compareTo(prevData) <= 0);
604                 } else {
605                     assertTrue
606                     (duplicateComparisonFunction.compare
607                      (foundData.getBytes(),
608                       prevData.getBytes()) <= 0);
609                 }
610                 }
611                 prevData = foundData;
612             } else {
613                 prevData = "";
614             }
615
616             prevKey = foundKey;
617             }
618         };
619     }
620     dw.setIgnoreDataMap(true);
621     dw.walkData();
622     assertTrue(dataMap.size() == 0);
623     }
624
625     /**
626      * Create a bunch of random duplicate data. Iterate over it using
627      * getNextDup until the end of the dup set. At end of set, handleEndOfSet
628      * is called to do a getNext onto the next dup set. Verify that ascending
629      * order is maintained and that we reach end of set the proper number of
630      * times.
631      */

632     public void testGetNextDup()
633     throws Throwable JavaDoc {
634
635         try {
636             initEnv(true);
637             Hashtable JavaDoc dataMap = new Hashtable JavaDoc();
638
639             createRandomDuplicateData(dataMap, false);
640
641             DataWalker dw = new DupDataWalker(dataMap) {
642                     void perData(String JavaDoc foundKey, String JavaDoc foundData) {
643                         Hashtable JavaDoc ht = (Hashtable JavaDoc) dataMap.get(foundKey);
644                         if (ht == null) {
645                             fail("didn't find ht " +
646                  foundKey + "/" + foundData);
647                         }
648
649                         if (ht.get(foundData) != null) {
650                             ht.remove(foundData);
651                             if (ht.size() == 0) {
652                                 dataMap.remove(foundKey);
653                             }
654                         } else {
655                             fail("didn't find " + foundKey + "/" + foundData);
656                         }
657
658                         assertTrue(foundKey.compareTo(prevKey) >= 0);
659
660                         if (prevKey.equals(foundKey)) {
661                             if (duplicateComparisonFunction == null) {
662                                 assertTrue(foundData.compareTo(prevData) >= 0);
663                             } else {
664                                 assertTrue
665                                     (duplicateComparisonFunction.compare
666                                      (foundData.getBytes(),
667                                       prevData.getBytes()) >= 0);
668                             }
669                             prevData = foundData;
670                         } else {
671                             prevData = "";
672                         }
673
674                         prevKey = foundKey;
675                     }
676
677                     OperationStatus handleEndOfSet(OperationStatus status)
678                         throws DatabaseException {
679
680                         String JavaDoc foundKeyString = foundKey.getString();
681                         Hashtable JavaDoc ht = (Hashtable JavaDoc) dataMap.get(foundKeyString);
682                         assertNull(ht);
683                         return cursor.getNext(foundKey, foundData,
684                                               LockMode.DEFAULT);
685                     }
686                 };
687             dw.setIgnoreDataMap(true);
688             dw.walkData();
689             assertEquals(N_TOP_LEVEL_KEYS, dw.nHandleEndOfSet);
690             assertTrue(dataMap.size() == 0);
691         } catch (Throwable JavaDoc t) {
692             t.printStackTrace();
693             throw t;
694         }
695     }
696
697     /**
698      * Create a bunch of random duplicate data. Iterate over it using
699      * getNextDup until the end of the dup set. At end of set, handleEndOfSet
700      * is called to do a getNext onto the next dup set. Verify that descending
701      * order is maintained and that we reach end of set the proper number of
702      * times.
703      */

704     public void testGetPrevDup()
705     throws Throwable JavaDoc {
706
707         try {
708             initEnv(true);
709             Hashtable JavaDoc dataMap = new Hashtable JavaDoc();
710
711             createRandomDuplicateData(dataMap, false);
712
713             DataWalker dw = new BackwardsDupDataWalker(dataMap) {
714                     void perData(String JavaDoc foundKey, String JavaDoc foundData) {
715                         Hashtable JavaDoc ht = (Hashtable JavaDoc) dataMap.get(foundKey);
716                         if (ht == null) {
717                             fail("didn't find ht " +
718                  foundKey + "/" + foundData);
719                         }
720
721                         if (ht.get(foundData) != null) {
722                             ht.remove(foundData);
723                             if (ht.size() == 0) {
724                                 dataMap.remove(foundKey);
725                             }
726                         } else {
727                             fail("didn't find " + foundKey + "/" + foundData);
728                         }
729
730                         if (!prevKey.equals("")) {
731                             assertTrue(foundKey.compareTo(prevKey) <= 0);
732                         }
733
734                         if (prevKey.equals(foundKey)) {
735                             if (!prevData.equals("")) {
736                                 if (duplicateComparisonFunction == null) {
737                                     assertTrue(foundData.compareTo
738                            (prevData) <= 0);
739                                 } else {
740                                     assertTrue
741                                         (duplicateComparisonFunction.compare
742                                          (foundData.getBytes(),
743                                           prevData.getBytes()) <= 0);
744                                 }
745                             }
746                             prevData = foundData;
747                         } else {
748                             prevData = "";
749                         }
750
751                         prevKey = foundKey;
752                     }
753
754                     OperationStatus handleEndOfSet(OperationStatus status)
755                         throws DatabaseException {
756
757                         String JavaDoc foundKeyString = foundKey.getString();
758                         Hashtable JavaDoc ht = (Hashtable JavaDoc) dataMap.get(foundKeyString);
759                         assertNull(ht);
760                         return cursor.getPrev(foundKey, foundData,
761                                               LockMode.DEFAULT);
762                     }
763                 };
764             dw.setIgnoreDataMap(true);
765             dw.walkData();
766             assertEquals(N_TOP_LEVEL_KEYS, dw.nHandleEndOfSet);
767             assertTrue(dataMap.size() == 0);
768         } catch (Throwable JavaDoc t) {
769             t.printStackTrace();
770             throw t;
771         }
772     }
773
774     /**
775      * Create a bunch of random duplicate data. Iterate over it using
776      * getNextNoDup until the end of the top level set. Verify that
777      * ascending order is maintained and that we reach see the proper
778      * number of top-level keys.
779      */

780     public void testGetNextNoDup()
781     throws Throwable JavaDoc {
782
783         try {
784             initEnv(true);
785             Hashtable JavaDoc dataMap = new Hashtable JavaDoc();
786
787             createRandomDuplicateData(dataMap, false);
788
789             DataWalker dw = new NoDupDataWalker(dataMap) {
790                     void perData(String JavaDoc foundKey, String JavaDoc foundData) {
791                         Hashtable JavaDoc ht = (Hashtable JavaDoc) dataMap.get(foundKey);
792                         if (ht == null) {
793                             fail("didn't find ht " +
794                  foundKey + "/" + foundData);
795                         }
796
797                         if (ht.get(foundData) != null) {
798                             dataMap.remove(foundKey);
799                         } else {
800                             fail("saw " +
801                  foundKey + "/" + foundData + " twice.");
802                         }
803
804                         assertTrue(foundKey.compareTo(prevKey) > 0);
805                         prevKey = foundKey;
806                     }
807                 };
808             dw.setIgnoreDataMap(true);
809             dw.walkData();
810             assertEquals(N_TOP_LEVEL_KEYS, dw.nEntries);
811             assertTrue(dataMap.size() == 0);
812         } catch (Throwable JavaDoc t) {
813             t.printStackTrace();
814             throw t;
815         }
816     }
817
818     /**
819      * Create a bunch of random duplicate data. Iterate over it using
820      * getNextNoDup until the end of the top level set. Verify that descending
821      * order is maintained and that we reach see the proper number of top-level
822      * keys.
823      */

824     public void testGetPrevNoDup()
825     throws Throwable JavaDoc {
826
827         try {
828             initEnv(true);
829             Hashtable JavaDoc dataMap = new Hashtable JavaDoc();
830
831             createRandomDuplicateData(dataMap, false);
832
833             DataWalker dw = new NoDupBackwardsDataWalker(dataMap) {
834                     void perData(String JavaDoc foundKey, String JavaDoc foundData) {
835                         Hashtable JavaDoc ht = (Hashtable JavaDoc) dataMap.get(foundKey);
836                         if (ht == null) {
837                             fail("didn't find ht " +
838                  foundKey + "/" + foundData);
839                         }
840
841                         if (ht.get(foundData) != null) {
842                             dataMap.remove(foundKey);
843                         } else {
844                             fail("saw " +
845                  foundKey + "/" + foundData + " twice.");
846                         }
847
848                         if (!prevKey.equals("")) {
849                             assertTrue(foundKey.compareTo(prevKey) < 0);
850                         }
851                         prevKey = foundKey;
852                     }
853                 };
854             dw.setIgnoreDataMap(true);
855             dw.walkData();
856             assertEquals(N_TOP_LEVEL_KEYS, dw.nEntries);
857             assertTrue(dataMap.size() == 0);
858         } catch (Throwable JavaDoc t) {
859             t.printStackTrace();
860             throw t;
861         }
862     }
863
864     public void testIllegalDuplicateCreation()
865         throws Throwable JavaDoc {
866
867         try {
868             initEnv(false);
869             Hashtable JavaDoc dataMap = new Hashtable JavaDoc();
870
871             try {
872                 createRandomDuplicateData(dataMap, false);
873                 fail("didn't throw DuplicateEntryException");
874             } catch (DuplicateEntryException DEE) {
875             }
876         } catch (Throwable JavaDoc t) {
877             t.printStackTrace();
878             throw t;
879         }
880     }
881
882     /**
883      * Just use the BtreeComparator that's already available.
884      */

885     private static Comparator JavaDoc duplicateComparator =
886     new DuplicateAscendingComparator();
887
888     private static Comparator JavaDoc reverseDuplicateComparator =
889     new DuplicateReverseComparator();
890
891     private static InvocationCountingBtreeComparator
892     invocationCountingComparator =
893     new InvocationCountingBtreeComparator();
894
895     public static class DuplicateAscendingComparator
896         extends BtreeComparator {
897
898     public DuplicateAscendingComparator() {
899         super();
900     }
901     }
902
903     public static class DuplicateReverseComparator
904         extends ReverseBtreeComparator {
905
906     public DuplicateReverseComparator() {
907         super();
908     }
909     }
910
911     public static class InvocationCountingBtreeComparator
912     extends BtreeComparator {
913
914     private int invocationCount = 0;
915
916     public int compare(Object JavaDoc o1, Object JavaDoc o2) {
917         invocationCount++;
918         return super.compare(o1, o2);
919     }
920
921     public int getInvocationCount() {
922         return invocationCount;
923     }
924
925     public void setInvocationCount(int invocationCount) {
926         this.invocationCount = invocationCount;
927     }
928     }
929
930     /*
931      * A special comparator that only looks at the first length-1 bytes of data
932      * so that the last byte can be changed without affecting "equality". Use
933      * this for putCurrent tests of duplicates.
934      */

935     private static Comparator JavaDoc truncatedComparator = new TruncatedComparator();
936
937     protected static class TruncatedComparator implements Comparator JavaDoc {
938     protected TruncatedComparator() {
939     }
940
941     public int compare(Object JavaDoc o1, Object JavaDoc o2) {
942         byte[] arg1;
943         byte[] arg2;
944         arg1 = (byte[]) o1;
945         arg2 = (byte[]) o2;
946         int a1Len = arg1.length - 1;
947         int a2Len = arg2.length - 1;
948
949         int limit = Math.min(a1Len, a2Len);
950
951         for (int i = 0; i < limit; i++) {
952         byte b1 = arg1[i];
953         byte b2 = arg2[i];
954         if (b1 == b2) {
955             continue;
956         } else {
957             /*
958              * Remember, bytes are signed, so convert to
959              * shorts so that we effectively do an unsigned
960              * byte comparison.
961              */

962             short s1 = (short) (b1 & 0x7F);
963             short s2 = (short) (b2 & 0x7F);
964             if (b1 < 0) {
965             s1 |= 0x80;
966             }
967             if (b2 < 0) {
968             s2 |= 0x80;
969             }
970             return (s1 - s2);
971         }
972         }
973
974         return (a1Len - a2Len);
975     }
976     }
977 }
978
Popular Tags