• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/db-4.8.30/test/scr037/
1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2009 Oracle.  All rights reserved.
5 *
6 */
7using System;
8using System.Collections;
9using System.Collections.Generic;
10using System.IO;
11using System.Text;
12using System.Threading;
13using System.Xml;
14using NUnit.Framework;
15using BerkeleyDB;
16
17namespace CsharpAPITest
18{
19	[TestFixture]
20	public class SecondaryCursorTest
21	{
22		private string testFixtureHome;
23		private string testFixtureName;
24		private string testName;
25		private string testHome;
26
27		[TestFixtureSetUp]
28		public void RunBeforeTests()
29		{
30			testFixtureName = "SecondaryCursorTest";
31			testFixtureHome = "./TestOut/" + testFixtureName;
32
33			/*
34			 * Delete existing test ouput directory and files specified
35			 * for the current test fixture and then create a new one.
36			 */
37			Configuration.ClearDir(testFixtureHome);
38		}
39
40		[Test]
41		public void TestDuplicate()
42		{
43			testName = "TestDuplicate";
44			testHome = testFixtureHome + "/" + testName;
45			string dbFileName = testHome + "/" + testName + ".db";
46			string dbSecFileName = testHome + "/" + testName +
47			    "_sec.db";
48
49			Configuration.ClearDir(testHome);
50
51			// Open a primary database.
52			BTreeDatabaseConfig dbConfig =
53			    new BTreeDatabaseConfig();
54			dbConfig.Creation = CreatePolicy.IF_NEEDED;
55			BTreeDatabase db = BTreeDatabase.Open(
56			    dbFileName, dbConfig);
57
58			// Open a secondary database.
59			SecondaryBTreeDatabaseConfig secConfig =
60			    new SecondaryBTreeDatabaseConfig(db,
61			    new SecondaryKeyGenDelegate(SecondaryKeyGen));
62			secConfig.Creation = CreatePolicy.IF_NEEDED;
63			secConfig.Duplicates = DuplicatesPolicy.UNSORTED;
64			SecondaryBTreeDatabase secDB =
65			    SecondaryBTreeDatabase.Open(dbSecFileName,
66			    secConfig);
67
68			// Put a pair of key and data into the database.
69			DatabaseEntry key, data;
70			key = new DatabaseEntry(
71			    ASCIIEncoding.ASCII.GetBytes("key"));
72			data = new DatabaseEntry(
73			    ASCIIEncoding.ASCII.GetBytes("data"));
74			db.Put(key, data);
75
76			// Create a cursor.
77			SecondaryCursor cursor = secDB.SecondaryCursor();
78			cursor.Move(key, true);
79
80			// Duplicate the cursor.
81			SecondaryCursor dupCursor;
82			dupCursor = cursor.Duplicate(true);
83
84			/*
85			 * Confirm that the duplicate cursor has the same
86			 * position as the original one.
87			 */
88			Assert.AreEqual(cursor.Current.Key,
89			    dupCursor.Current.Key);
90			Assert.AreEqual(cursor.Current.Value,
91			    dupCursor.Current.Value);
92
93			// Close the cursor and the duplicate cursor.
94			dupCursor.Close();
95			cursor.Close();
96
97			// Close secondary and primary database.
98			secDB.Close();
99			db.Close();
100		}
101
102		[Test]
103		public void TestDelete()
104		{
105			testName = "TestDelete";
106			testHome = testFixtureHome + "/" + testName;
107			string dbFileName = testHome + "/" + testName + ".db";
108			string dbSecFileName = testHome + "/" + testName +
109			    "_sec.db";
110
111			Configuration.ClearDir(testHome);
112
113			// Open a primary database and its secondary database.
114			BTreeDatabase db;
115			SecondaryBTreeDatabase secDB;
116			OpenSecDB(dbFileName, dbSecFileName, out db, out secDB);
117
118			// Put a pair of key and data into database.
119			DatabaseEntry key, data;
120			key = new DatabaseEntry(
121			    ASCIIEncoding.ASCII.GetBytes("key"));
122			data = new DatabaseEntry(
123			    ASCIIEncoding.ASCII.GetBytes("data"));
124			db.Put(key, data);
125
126			// Delete the pair with cursor.
127			SecondaryCursor secCursor = secDB.SecondaryCursor();
128			Assert.IsTrue(secCursor.MoveFirst());
129			secCursor.Delete();
130
131			// Confirm that the pair is deleted.
132			Assert.IsFalse(db.Exists(key));
133
134			// Close all databases.
135			secDB.Close();
136			db.Close();
137		}
138
139		[Test]
140		public void TestCurrent()
141		{
142			testName = "TestCurrent";
143			testHome = testFixtureHome + "/" + testName;
144			string dbFileName = testHome + "/" + testName + ".db";
145			string dbSecFileName = testHome + "/" + testName +
146			    "_sec.db";
147
148			Configuration.ClearDir(testHome);
149
150			// Open a primary database and its secondary database.
151			BTreeDatabase db;
152			SecondaryBTreeDatabase secDB;
153			OpenSecDB(dbFileName, dbSecFileName, out db, out secDB);
154
155			// Put a pair of key and data into database.
156			DatabaseEntry key, data;
157			key = new DatabaseEntry(
158			    ASCIIEncoding.ASCII.GetBytes("key"));
159			data = new DatabaseEntry(
160			    ASCIIEncoding.ASCII.GetBytes("data"));
161			db.Put(key, data);
162
163			// Delete the pair with cursor.
164			SecondaryCursor secCursor = secDB.SecondaryCursor();
165			Assert.IsTrue(secCursor.Move(data, true));
166
167			// Confirm that the current is the one we put into database.
168			Assert.AreEqual(data.Data, secCursor.Current.Key.Data);
169
170			// Close all databases.
171			secDB.Close();
172			db.Close();
173		}
174
175		[Test]
176		public void TestGetEnumerator()
177		{
178			testName = "TestGetEnumerator";
179			testHome = testFixtureHome + "/" + testName;
180			string dbFileName = testHome + "/" + testName + ".db";
181			string dbSecFileName = testHome + "/" + testName +
182			    "_sec.db";
183
184			Configuration.ClearDir(testHome);
185
186			// Open a primary database and its secondary database.
187			BTreeDatabase db;
188			SecondaryBTreeDatabase secDB;
189			OpenSecDB(dbFileName, dbSecFileName, out db,
190			    out secDB);
191
192			// Write ten records into the database.
193			WriteRecords(db);
194
195			/*
196			 * Get all records from the secondary database and see
197			 * if the records with key other than 10 have the same as
198			 * their primary key.
199			 */
200			SecondaryCursor secCursor = secDB.SecondaryCursor();
201			foreach (KeyValuePair<DatabaseEntry, KeyValuePair<
202			    DatabaseEntry, DatabaseEntry>> secData in secCursor)
203			{
204				if (BitConverter.ToInt32(secData.Key.Data, 0) != 10)
205					Assert.AreEqual(secData.Value.Key.Data,
206					    secData.Value.Value.Data);
207			}
208
209			// Close all cursors and databases.
210			secCursor.Close();
211			secDB.Close();
212			db.Close();
213		}
214
215		[Test]
216		public void TestMoveToKey()
217		{
218			testName = "TestMoveToKey";
219			testHome = testFixtureHome + "/" + testName;
220			string dbFileName = testHome + "/" + testName + ".db";
221			string dbSecFileName = testHome + "/" + testName +
222			    "_sec.db";
223
224			Configuration.ClearDir(testHome);
225
226			MoveToPos(dbFileName, dbSecFileName, false);
227		}
228
229		[Test]
230		public void TestMoveToPair()
231		{
232			testName = "TestMoveToPair";
233			testHome = testFixtureHome + "/" + testName;
234			string dbFileName = testHome + "/" + testName + ".db";
235			string dbSecFileName = testHome + "/" + testName +
236			    "_sec.db";
237
238			Configuration.ClearDir(testHome);
239
240			MoveToPos(dbFileName, dbSecFileName, true);
241		}
242
243		public void MoveToPos(string dbFileName,
244		    string dbSecFileName, bool ifPair)
245		{
246			// Open a primary database and its secondary database.
247			BTreeDatabase db;
248			SecondaryBTreeDatabase secDB;
249			OpenSecDB(dbFileName, dbSecFileName, out db,
250			    out secDB);
251
252			// Write ten records into the database.
253			WriteRecords(db);
254
255			SecondaryCursor secCursor = secDB.SecondaryCursor();
256			DatabaseEntry key = new DatabaseEntry(
257			    BitConverter.GetBytes((int)0));
258			DatabaseEntry notExistingKey = new DatabaseEntry(
259			    BitConverter.GetBytes((int)100));
260			if (ifPair == false)
261			{
262				Assert.IsTrue(secCursor.Move(key, true));
263				Assert.IsFalse(secCursor.Move(notExistingKey, true));
264			}
265			else
266			{
267				KeyValuePair<DatabaseEntry, KeyValuePair<
268				    DatabaseEntry, DatabaseEntry>> pair =
269				    new KeyValuePair<DatabaseEntry,
270				    KeyValuePair<DatabaseEntry, DatabaseEntry>>(key,
271				    new KeyValuePair<DatabaseEntry, DatabaseEntry>(
272				    key, key));
273
274				KeyValuePair<DatabaseEntry, KeyValuePair<
275				    DatabaseEntry, DatabaseEntry>> notExistingPair;
276
277				notExistingPair = new KeyValuePair<DatabaseEntry,
278				    KeyValuePair<DatabaseEntry, DatabaseEntry>>(
279				    notExistingKey, new KeyValuePair<
280				    DatabaseEntry, DatabaseEntry>(
281				    notExistingKey, notExistingKey));
282				Assert.IsTrue(secCursor.Move(pair, true));
283				Assert.IsFalse(secCursor.Move(notExistingPair, true));
284			}
285
286			secCursor.Close();
287			secDB.Close();
288			db.Close();
289		}
290
291		[Test]
292		public void TestMoveToKeyWithLockingInfo()
293		{
294			testName = "TestMoveToKeyWithLockingInfo";
295			testHome = testFixtureHome + "/" + testName;
296			string dbFileName = testName + ".db";
297			string dbSecFileName = testName +  "_sec.db";
298
299			Configuration.ClearDir(testHome);
300
301			MoveToPosWithLockingInfo(testHome, dbFileName,
302			    dbSecFileName, false);
303		}
304
305		[Test]
306		public void TestMoveToPairWithLockingInfo()
307		{
308			testName = "TestMoveToPairWithLockingInfo";
309			testHome = testFixtureHome + "/" + testName;
310			string dbFileName = testName + ".db";
311			string dbSecFileName = testName + "_sec.db";
312
313			Configuration.ClearDir(testHome);
314
315			MoveToPosWithLockingInfo(testHome, dbFileName,
316			    dbSecFileName, true);
317		}
318
319		public void MoveToPosWithLockingInfo(string home,
320		    string dbFileName, string dbSecFileName, bool ifPair)
321		{
322			// Open a primary database and its secondary database.
323			BTreeDatabase db;
324			DatabaseEnvironment env;
325			SecondaryBTreeDatabase secDB;
326			OpenSecDBInTxn(home, dbFileName, dbSecFileName,
327			    out env, out db, out secDB);
328
329			// Write ten records into the database.
330			WriteRecordsInTxn(db, env);
331
332			// Create an secondary cursor.
333			Transaction cursorTxn = env.BeginTransaction();
334			SecondaryCursor secCursor = secDB.SecondaryCursor(
335			    cursorTxn);
336			DatabaseEntry key = new DatabaseEntry(
337			    BitConverter.GetBytes((int)0));
338			LockingInfo lockingInfo = new LockingInfo();
339			lockingInfo.IsolationDegree = Isolation.DEGREE_THREE;
340			lockingInfo.ReadModifyWrite = true;
341			if (ifPair == false)
342			{
343				Assert.IsTrue(secCursor.Move(key, true, lockingInfo));
344			}
345			else
346			{
347				KeyValuePair<DatabaseEntry, KeyValuePair<
348				    DatabaseEntry, DatabaseEntry>> pair;
349
350				pair = new KeyValuePair<DatabaseEntry,
351				    KeyValuePair<DatabaseEntry, DatabaseEntry>>(key,
352				    new KeyValuePair<DatabaseEntry, DatabaseEntry>(
353				    key, key));
354				Assert.IsTrue(secCursor.Move(pair, true, lockingInfo));
355			}
356			secCursor.Close();
357			cursorTxn.Commit();
358
359			secDB.Close();
360			db.Close();
361			env.Close();
362		}
363
364		[Test]
365		public void TestMoveFirst()
366		{
367			testName = "TestMoveFirst";
368			testHome = testFixtureHome + "/" + testName;
369			string dbFileName = testHome + "/" + testName + ".db";
370			string dbSecFileName = testHome + "/" + testName +
371			    "_sec.db";
372
373			Configuration.ClearDir(testHome);
374
375			// Open primary and secondary database.
376			BTreeDatabase db;
377			SecondaryBTreeDatabase secDB;
378			OpenSecDB(dbFileName, dbSecFileName, out db,
379			    out secDB);
380
381
382			// Write ten records into the database.
383			WriteRecords(db);
384
385			// Move the cursor to the first record(0,0).
386			SecondaryCursor cursor = secDB.SecondaryCursor();
387			Assert.IsTrue(cursor.MoveFirst());
388			Assert.AreEqual(BitConverter.GetBytes((int)0),
389			    cursor.Current.Key.Data);
390
391			// Close all.
392			cursor.Close();
393			secDB.Close();
394			db.Close();
395		}
396
397		[Test]
398		public void TestMoveLast()
399		{
400			testName = "TestMoveLast";
401			testHome = testFixtureHome + "/" + testName;
402			string dbFileName = testHome + "/" + testName + ".db";
403			string dbSecFileName = testHome + "/" + testName +
404			    "_sec.db";
405
406			Configuration.ClearDir(testHome);
407
408			BTreeDatabase db;
409			SecondaryBTreeDatabase secDB;
410			OpenSecDB(dbFileName, dbSecFileName, out db,
411			    out secDB);
412			WriteRecords(db);
413
414			SecondaryCursor cursor = secDB.SecondaryCursor();
415			Assert.IsTrue(cursor.MoveLast());
416			Assert.AreEqual(BitConverter.GetBytes((int)10),
417			    cursor.Current.Key.Data);
418
419			cursor.Close();
420			secDB.Close();
421			db.Close();
422		}
423
424		[Test]
425		public void TestMoveNext()
426		{
427			testName = "TestMoveNext";
428			testHome = testFixtureHome + "/" + testName;
429			string dbFileName = testHome + "/" + testName + ".db";
430			string dbSecFileName = testHome + "/" + testName +
431			    "_sec.db";
432
433			Configuration.ClearDir(testHome);
434
435			BTreeDatabase db;
436			SecondaryBTreeDatabase secDB;
437			OpenSecDB(dbFileName, dbSecFileName, out db,
438			    out secDB);
439			WriteRecords(db);
440
441			SecondaryCursor cursor = secDB.SecondaryCursor();
442			cursor.MoveFirst();
443			for (int i = 0; i < 5; i++)
444				Assert.IsTrue(cursor.MoveNext());
445
446			cursor.Close();
447			secDB.Close();
448			db.Close();
449		}
450
451		[Test]
452		public void TestMoveNextDuplicate()
453		{
454			testName = "TestMoveNextDuplicate";
455			testHome = testFixtureHome + "/" + testName;
456			string dbFileName = testHome + "/" + testName + ".db";
457			string dbSecFileName = testHome + "/" + testName +
458			    "_sec.db";
459
460			Configuration.ClearDir(testHome);
461
462			BTreeDatabase db;
463			SecondaryBTreeDatabase secDB;
464			OpenSecDB(dbFileName, dbSecFileName, out db,
465			    out secDB);
466			WriteRecords(db);
467
468			// Create a cursor and move the cursor to duplicate record.
469			SecondaryCursor cursor = secDB.SecondaryCursor();
470			cursor.Move(new DatabaseEntry(
471			    BitConverter.GetBytes((int)10)), true);
472			Assert.IsTrue(cursor.MoveNextDuplicate());
473			Assert.AreEqual(BitConverter.GetBytes((int)10),
474			    cursor.Current.Key.Data);
475
476			cursor.Close();
477			secDB.Close();
478			db.Close();
479		}
480
481		[Test]
482		public void TestMoveNextUnique()
483		{
484			testName = "TestMoveNextUnique";
485			testHome = testFixtureHome + "/" + testName;
486			string dbFileName = testHome + "/" + testName + ".db";
487			string dbSecFileName = testHome + "/" + testName +
488			    "_sec.db";
489
490			Configuration.ClearDir(testHome);
491
492			BTreeDatabase db;
493			SecondaryBTreeDatabase secDB;
494			OpenSecDB(dbFileName, dbSecFileName, out db,
495			    out secDB);
496			WriteRecords(db);
497
498			/*
499			 * Move cursor to duplicate record. Since the duplicate
500			 * record has the largest key, moving to the next
501			 * unique record should fail.
502			 */
503			SecondaryCursor cursor = secDB.SecondaryCursor();
504			cursor.Move(new DatabaseEntry(
505			    BitConverter.GetBytes((int)10)), true);
506			Assert.IsFalse(cursor.MoveNextUnique());
507
508			cursor.Close();
509			secDB.Close();
510			db.Close();
511		}
512
513		[Test]
514		public void TestMovePrev()
515		{
516			testName = "TestMovePrev";
517			testHome = testFixtureHome + "/" + testName;
518			string dbFileName = testHome + "/" + testName + ".db";
519			string dbSecFileName = testHome + "/" + testName +
520			    "_sec.db";
521
522			Configuration.ClearDir(testHome);
523
524			BTreeDatabase db;
525			SecondaryBTreeDatabase secDB;
526			OpenSecDB(dbFileName, dbSecFileName, out db,
527			    out secDB);
528			WriteRecords(db);
529
530			SecondaryCursor cursor = secDB.SecondaryCursor();
531			cursor.MoveLast();
532			for (int i = 0; i < 5; i++)
533				Assert.IsTrue(cursor.MovePrev());
534
535			cursor.Close();
536			secDB.Close();
537			db.Close();
538		}
539
540		[Test]
541		public void TestMovePrevDuplicate()
542		{
543			testName = "TestMovePrevDuplicate";
544			testHome = testFixtureHome + "/" + testName;
545			string dbFileName = testHome + "/" + testName + ".db";
546			string dbSecFileName = testHome + "/" + testName +
547			    "_sec.db";
548
549			Configuration.ClearDir(testHome);
550
551			BTreeDatabase db;
552			SecondaryBTreeDatabase secDB;
553			OpenSecDB(dbFileName, dbSecFileName, out db,
554			    out secDB);
555			WriteRecords(db);
556
557			SecondaryCursor cursor = secDB.SecondaryCursor();
558			KeyValuePair<DatabaseEntry, KeyValuePair<
559			    DatabaseEntry, DatabaseEntry>> pair;
560			DatabaseEntry pKey, pData;
561			pKey = new DatabaseEntry(BitConverter.GetBytes((int)6));
562			pData = new DatabaseEntry(BitConverter.GetBytes((int)10));
563			pair = new KeyValuePair<DatabaseEntry, KeyValuePair<
564			    DatabaseEntry, DatabaseEntry>>(pData,
565			    new KeyValuePair<DatabaseEntry, DatabaseEntry>(
566			    pKey, pData));
567			cursor.Move(pair, true);
568			Assert.IsTrue(cursor.MovePrevDuplicate());
569			Assert.AreEqual(BitConverter.GetBytes((int)10),
570			    cursor.Current.Key.Data);
571
572			cursor.Close();
573			secDB.Close();
574			db.Close();
575		}
576
577
578		[Test]
579		public void TestMovePrevUnique()
580		{
581			testName = "TestMovePrevUnique";
582			testHome = testFixtureHome + "/" + testName;
583			string dbFileName = testHome + "/" + testName + ".db";
584			string dbSecFileName = testHome + "/" + testName +
585			    "_sec.db";
586
587			Configuration.ClearDir(testHome);
588
589			BTreeDatabase db;
590			SecondaryBTreeDatabase secDB;
591			OpenSecDB(dbFileName, dbSecFileName, out db,
592			    out secDB);
593			WriteRecords(db);
594
595			SecondaryCursor cursor = secDB.SecondaryCursor();
596			KeyValuePair<DatabaseEntry, KeyValuePair<
597			    DatabaseEntry, DatabaseEntry>> pair;
598			DatabaseEntry pKey, pData;
599			pKey = new DatabaseEntry(BitConverter.GetBytes((int)6));
600			pData = new DatabaseEntry(BitConverter.GetBytes((int)10));
601			pair = new KeyValuePair<DatabaseEntry, KeyValuePair<
602			    DatabaseEntry, DatabaseEntry>>(pData,
603			    new KeyValuePair<DatabaseEntry, DatabaseEntry>(
604			    pKey, pData));
605			cursor.Move(pair, true);
606			Assert.IsTrue(cursor.MovePrevUnique());
607			Assert.AreNotEqual(BitConverter.GetBytes((int)10),
608			    cursor.Current.Key.Data);
609
610			cursor.Close();
611			secDB.Close();
612			db.Close();
613		}
614
615		[Test]
616		public void TestRefresh()
617		{
618			testName = "TestRefresh";
619			testHome = testFixtureHome + "/" + testName;
620			string dbFileName = testHome + "/" + testName + ".db";
621			string dbSecFileName = testHome + "/" + testName +
622			    "_sec.db";
623
624			Configuration.ClearDir(testHome);
625
626			BTreeDatabase db;
627			SecondaryBTreeDatabase secDB;
628			OpenSecDB(dbFileName, dbSecFileName, out db,
629			    out secDB);
630			WriteRecords(db);
631
632			SecondaryCursor cursor = secDB.SecondaryCursor();
633			KeyValuePair<DatabaseEntry, KeyValuePair<
634			    DatabaseEntry, DatabaseEntry>> pair;
635			DatabaseEntry pKey, pData;
636			pKey = new DatabaseEntry(BitConverter.GetBytes((int)6));
637			pData = new DatabaseEntry(BitConverter.GetBytes((int)10));
638			pair = new KeyValuePair<DatabaseEntry, KeyValuePair<
639			    DatabaseEntry, DatabaseEntry>>(pData,
640			    new KeyValuePair<DatabaseEntry, DatabaseEntry>(
641			    pKey, pData));
642			cursor.Move(pair, true);
643			Assert.IsTrue(cursor.Refresh());
644			Assert.AreEqual(pData.Data, cursor.Current.Key.Data);
645			Assert.AreEqual(pKey.Data, cursor.Current.Value.Key.Data);
646
647			cursor.Close();
648			secDB.Close();
649			db.Close();
650		}
651
652		[Test]
653		public void TestMoveFirstWithLockingInfo()
654		{
655			testName = "TestMoveFirstWithLockingInfo";
656			testHome = testFixtureHome + "/" + testName;
657			string dbFileName = testName + ".db";
658			string dbSecFileName = testName + "_sec.db";
659
660			Configuration.ClearDir(testHome);
661
662			/*
663			 * Open environment, primary database and
664			 * secondary database.
665			 */
666			BTreeDatabase db;
667			DatabaseEnvironment env;
668			SecondaryBTreeDatabase secDB;
669			OpenSecDBInTxn(testHome, dbFileName, dbSecFileName,
670			    out env, out db, out secDB);
671
672			// Write ten records into the database.
673			WriteRecordsInTxn(db, env);
674
675			// Move the cursor to the first record(0, 0).
676			Transaction cursorTxn = env.BeginTransaction();
677			SecondaryCursor cursor =
678			    secDB.SecondaryCursor(cursorTxn);
679			LockingInfo lockingInfo = new LockingInfo();
680			lockingInfo.IsolationDegree = Isolation.DEGREE_THREE;
681			lockingInfo.ReadModifyWrite = true;
682			Assert.IsTrue(cursor.MoveFirst(lockingInfo));
683			Assert.AreEqual(BitConverter.GetBytes((int)0),
684			    cursor.Current.Key.Data);
685			cursor.Close();
686			cursorTxn.Commit();
687
688			// Close all.
689			secDB.Close();
690			db.Close();
691			env.Close();
692		}
693
694		[Test]
695		public void TestMoveLastWithLockingInfo()
696		{
697			testName = "TestMoveLastWithLockingInfo";
698			testHome = testFixtureHome + "/" + testName;
699			string dbFileName = testName + ".db";
700			string dbSecFileName = testName + "_sec.db";
701
702			Configuration.ClearDir(testHome);
703
704			/*
705			 * Open environment, primary database and
706			 * secondary database.
707			 */
708			BTreeDatabase db;
709			DatabaseEnvironment env;
710			SecondaryBTreeDatabase secDB;
711			OpenSecDBInTxn(testHome, dbFileName, dbSecFileName,
712			    out env, out db, out secDB);
713
714			// Write ten records into the database.
715			WriteRecordsInTxn(db, env);
716
717			/*
718			 * Move the cursor to the last record(10, 6), that is
719			 * record(6, 10) in primary database.
720			 */
721			Transaction cursorTxn = env.BeginTransaction();
722			SecondaryCursor cursor =
723			    secDB.SecondaryCursor(cursorTxn);
724			LockingInfo lockingInfo = new LockingInfo();
725			lockingInfo.IsolationDegree = Isolation.DEGREE_THREE;
726			lockingInfo.ReadModifyWrite = true;
727			Assert.IsTrue(cursor.MoveLast(lockingInfo));
728			Assert.AreEqual(BitConverter.GetBytes((int)10),
729			    cursor.Current.Key.Data);
730			cursor.Close();
731			cursorTxn.Commit();
732
733			// Close all.
734			secDB.Close();
735			db.Close();
736			env.Close();
737		}
738
739		[Test]
740		public void TestMoveNextWithLockingInfo()
741		{
742			testName = "TestMoveNextWithLockingInfo";
743			testHome = testFixtureHome + "/" + testName;
744			string dbFileName = testName + ".db";
745			string dbSecFileName = testName + "_sec.db";
746
747			Configuration.ClearDir(testHome);
748
749			/*
750			 * Open environment, primary database and
751			 * secondary database.
752			 */
753			BTreeDatabase db;
754			DatabaseEnvironment env;
755			SecondaryBTreeDatabase secDB;
756			OpenSecDBInTxn(testHome, dbFileName, dbSecFileName,
757			    out env, out db, out secDB);
758
759			// Write ten records into the database.
760			WriteRecordsInTxn(db, env);
761
762			/*
763			 * Move cursor to the first record and move to next
764			 * record for five times.
765			 */
766			Transaction cursorTxn = env.BeginTransaction();
767			SecondaryCursor cursor =
768			    secDB.SecondaryCursor(cursorTxn);
769			LockingInfo lockingInfo = new LockingInfo();
770			lockingInfo.IsolationDegree = Isolation.DEGREE_THREE;
771			lockingInfo.ReadModifyWrite = true;
772			cursor.MoveFirst(lockingInfo);
773			for (int i = 0; i < 5; i++)
774				Assert.IsTrue(cursor.MoveNext(lockingInfo));
775			cursor.Close();
776			cursorTxn.Commit();
777
778			// Close all.
779			secDB.Close();
780			db.Close();
781			env.Close();
782		}
783
784		[Test]
785		public void TestMoveNextDuplicateWithLockingInfo()
786		{
787			testName = "TestMoveNextDuplicateWithLockingInfo";
788			testHome = testFixtureHome + "/" + testName;
789			string dbFileName = testName + ".db";
790			string dbSecFileName = testName + "_sec.db";
791
792			Configuration.ClearDir(testHome);
793
794			/*
795			 * Open environment, primary database and
796			 * secondary database.
797			 */
798			BTreeDatabase db;
799			DatabaseEnvironment env;
800			SecondaryBTreeDatabase secDB;
801			OpenSecDBInTxn(testHome, dbFileName,
802			    dbSecFileName, out env, out db, out secDB);
803
804			// Write ten records into the database.
805			WriteRecordsInTxn(db, env);
806
807			/*
808			 * Create a cursor and move the cursor to duplicate
809			 * record(10, 5), that is record(5,10) in primary database.
810			 * Then move the cursor to the next duplicate record
811			 * (10, 6), that is record(6,10) in primary database.
812			 */
813			Transaction cursorTxn = env.BeginTransaction();
814			SecondaryCursor cursor =
815			    secDB.SecondaryCursor(cursorTxn);
816			LockingInfo lockingInfo = new LockingInfo();
817			lockingInfo.IsolationDegree = Isolation.DEGREE_THREE;
818			lockingInfo.ReadModifyWrite = true;
819			cursor.Move(new DatabaseEntry(
820			    BitConverter.GetBytes((int)10)), true, lockingInfo);
821			Assert.IsTrue(cursor.MoveNextDuplicate(lockingInfo));
822			Assert.AreEqual(BitConverter.GetBytes((int)10),
823			    cursor.Current.Key.Data);
824			cursor.Close();
825			cursorTxn.Commit();
826
827			// Close all.
828			secDB.Close();
829			db.Close();
830			env.Close();
831		}
832
833		[Test]
834		public void TestMoveNextUniqueWithLockingInfo()
835		{
836			testName = "TestMoveNextUniqueWithLockingInfo";
837			testHome = testFixtureHome + "/" + testName;
838			string dbFileName = testName + ".db";
839			string dbSecFileName = testName + "_sec.db";
840
841			Configuration.ClearDir(testHome);
842
843			/*
844			 * Open environment, primary database and
845			 * secondary database.
846			 */
847			BTreeDatabase db;
848			DatabaseEnvironment env;
849			SecondaryBTreeDatabase secDB;
850			OpenSecDBInTxn(testHome, dbFileName,
851			    dbSecFileName, out env, out db, out secDB);
852
853			// Write ten records into the database.
854			WriteRecordsInTxn(db, env);
855
856			/*
857			 * Move cursor to duplicate record. Since the duplicate
858			 * record has the largest key, moving to the next
859			 * unique record should fail.
860			 */
861			Transaction cursorTxn = env.BeginTransaction();
862			SecondaryCursor cursor =
863			    secDB.SecondaryCursor(cursorTxn);
864			LockingInfo lockingInfo = new LockingInfo();
865			lockingInfo.IsolationDegree = Isolation.DEGREE_THREE;
866			lockingInfo.ReadModifyWrite = true;
867			cursor.Move(new DatabaseEntry(
868			    BitConverter.GetBytes((int)10)), true);
869			Assert.IsFalse(cursor.MoveNextUnique());
870			cursor.Close();
871			cursorTxn.Commit();
872
873			// Close all.
874			secDB.Close();
875			db.Close();
876			env.Close();
877		}
878
879		[Test]
880		public void TestMovePrevWithLockingInfo()
881		{
882			testName = "TestMovePrevWithLockingInfo";
883			testHome = testFixtureHome + "/" + testName;
884			string dbFileName = testName + ".db";
885			string dbSecFileName = testName + "_sec.db";
886
887			Configuration.ClearDir(testHome);
888
889			/*
890			 * Open environment, primary database and
891			 * secondary database.
892			 */
893			BTreeDatabase db;
894			DatabaseEnvironment env;
895			SecondaryBTreeDatabase secDB;
896			OpenSecDBInTxn(testHome, dbFileName,
897			    dbSecFileName, out env, out db, out secDB);
898
899			// Write ten records into the database.
900			WriteRecordsInTxn(db, env);
901
902			/*
903			 * Move the cursor to the last record and move to its
904			 * previous record for five times.
905			 */
906			Transaction cursorTxn = env.BeginTransaction();
907			SecondaryCursor cursor =
908			    secDB.SecondaryCursor(cursorTxn);
909			LockingInfo lockingInfo = new LockingInfo();
910			lockingInfo.IsolationDegree = Isolation.DEGREE_TWO;
911			lockingInfo.ReadModifyWrite = true;
912			cursor.MoveLast(lockingInfo);
913			for (int i = 0; i < 5; i++)
914				Assert.IsTrue(cursor.MovePrev(lockingInfo));
915			cursor.Close();
916			cursorTxn.Commit();
917
918			// Close all.
919			secDB.Close();
920			db.Close();
921			env.Close();
922		}
923
924		[Test]
925		public void TestMovePrevDuplicateWithLockingInfo()
926		{
927			testName = "TestMovePrevDuplicateWithLockingInfo";
928			testHome = testFixtureHome + "/" + testName;
929			string dbFileName = testName + ".db";
930			string dbSecFileName = testName + "_sec.db";
931
932			Configuration.ClearDir(testHome);
933
934			/*
935			 * Open environment, primary database and
936			 * secondary database.
937			 */
938			BTreeDatabase db;
939			DatabaseEnvironment env;
940			SecondaryBTreeDatabase secDB;
941			OpenSecDBInTxn(testHome, dbFileName,
942			    dbSecFileName, out env, out db, out secDB);
943
944			// Write ten records into the database.
945			WriteRecordsInTxn(db, env);
946
947			Transaction cursorTxn = env.BeginTransaction();
948			SecondaryCursor cursor =
949			    secDB.SecondaryCursor(cursorTxn);
950			LockingInfo lockingInfo = new LockingInfo();
951			lockingInfo.IsolationDegree = Isolation.DEGREE_TWO;
952			lockingInfo.ReadModifyWrite = true;
953
954			/*
955			 * Move the cursor to the record(10,6), that is the
956			 * record(6, 10) in the primary database. Move to
957			 * its previous duplicate record, that is (10,5).
958			 */
959			KeyValuePair<DatabaseEntry, KeyValuePair<
960			    DatabaseEntry, DatabaseEntry>> pair;
961			DatabaseEntry pKey, pData;
962			pKey = new DatabaseEntry(BitConverter.GetBytes((int)6));
963			pData = new DatabaseEntry(BitConverter.GetBytes((int)10));
964			pair = new KeyValuePair<DatabaseEntry, KeyValuePair<
965			    DatabaseEntry, DatabaseEntry>>(pData,
966			    new KeyValuePair<DatabaseEntry, DatabaseEntry>(
967			    pKey, pData));
968			cursor.Move(pair, true, lockingInfo);
969			Assert.IsTrue(cursor.MovePrevDuplicate(lockingInfo));
970			Assert.AreEqual(BitConverter.GetBytes((int)10),
971			    cursor.Current.Key.Data);
972
973			cursor.Close();
974			cursorTxn.Commit();
975
976			// Close all.
977			secDB.Close();
978			db.Close();
979			env.Close();
980		}
981
982
983		[Test]
984		public void TestMovePrevUniqueWithLockingInfo()
985		{
986			testName = "TestMovePrevUniqueWithLockingInfo";
987			testHome = testFixtureHome + "/" + testName;
988			string dbFileName = testName + ".db";
989			string dbSecFileName = testName + "_sec.db";
990
991			Configuration.ClearDir(testHome);
992
993			/*
994			 * Open environment, primary database and
995			 * secondary database.
996			 */
997			BTreeDatabase db;
998			DatabaseEnvironment env;
999			SecondaryBTreeDatabase secDB;
1000			OpenSecDBInTxn(testHome, dbFileName,
1001			    dbSecFileName, out env, out db, out secDB);
1002
1003			// Write ten records into the database.
1004			WriteRecordsInTxn(db, env);
1005
1006			Transaction cursorTxn = env.BeginTransaction();
1007			SecondaryCursor cursor =
1008			    secDB.SecondaryCursor(cursorTxn);
1009			LockingInfo lockingInfo = new LockingInfo();
1010			lockingInfo.IsolationDegree = Isolation.DEGREE_TWO;
1011			lockingInfo.ReadModifyWrite = true;
1012
1013			/*
1014			 * Move the cursor to the record(10, 6) and move to the
1015			 * previous unique record which has different key from
1016			 * the record(10,6).
1017			 */
1018			KeyValuePair<DatabaseEntry, KeyValuePair<
1019			    DatabaseEntry, DatabaseEntry>> pair;
1020			DatabaseEntry pKey, pData;
1021			pKey = new DatabaseEntry(BitConverter.GetBytes((int)6));
1022			pData = new DatabaseEntry(BitConverter.GetBytes((int)10));
1023			pair = new KeyValuePair<DatabaseEntry, KeyValuePair<
1024			    DatabaseEntry, DatabaseEntry>>(pData,
1025			    new KeyValuePair<DatabaseEntry, DatabaseEntry>(
1026			    pKey, pData));
1027			cursor.Move(pair, true, lockingInfo);
1028			Assert.IsTrue(cursor.MovePrevUnique(lockingInfo));
1029			Assert.AreNotEqual(BitConverter.GetBytes((int)10),
1030			    cursor.Current.Key.Data);
1031
1032			cursor.Close();
1033			cursorTxn.Commit();
1034
1035			// Close all.
1036			secDB.Close();
1037			db.Close();
1038			env.Close();
1039		}
1040
1041		[Test]
1042		public void TestRefreshWithLockingInfo()
1043		{
1044			testName = "TestRefreshWithLockingInfo";
1045			testHome = testFixtureHome + "/" + testName;
1046			string dbFileName = testName + ".db";
1047			string dbSecFileName = testName + "_sec.db";
1048
1049			Configuration.ClearDir(testHome);
1050
1051			/*
1052			 * Open environment, primary database and
1053			 * secondary database.
1054			 */
1055			BTreeDatabase db;
1056			DatabaseEnvironment env;
1057			SecondaryBTreeDatabase secDB;
1058			OpenSecDBInTxn(testHome, dbFileName,
1059			    dbSecFileName, out env, out db, out secDB);
1060
1061			// Write ten records into the database.
1062			WriteRecordsInTxn(db, env);
1063
1064			Transaction cursorTxn = env.BeginTransaction();
1065			SecondaryCursor cursor =
1066			    secDB.SecondaryCursor(cursorTxn);
1067			LockingInfo lockingInfo = new LockingInfo();
1068			lockingInfo.IsolationDegree = Isolation.DEGREE_TWO;
1069			lockingInfo.ReadModifyWrite = true;
1070
1071			// Move cursor to a record and refresh it.
1072			KeyValuePair<DatabaseEntry, KeyValuePair<
1073			    DatabaseEntry, DatabaseEntry>> pair;
1074			DatabaseEntry pKey, pData;
1075			pKey = new DatabaseEntry(BitConverter.GetBytes((int)6));
1076			pData = new DatabaseEntry(BitConverter.GetBytes((int)10));
1077			pair = new KeyValuePair<DatabaseEntry, KeyValuePair<
1078			    DatabaseEntry, DatabaseEntry>>(pData,
1079			    new KeyValuePair<DatabaseEntry, DatabaseEntry>(
1080			    pKey, pData));
1081			cursor.Move(pair, true, lockingInfo);
1082			Assert.IsTrue(cursor.Refresh(lockingInfo));
1083			Assert.AreEqual(pData.Data, cursor.Current.Key.Data);
1084			Assert.AreEqual(pKey.Data, cursor.Current.Value.Key.Data);
1085
1086			cursor.Close();
1087			cursorTxn.Commit();
1088
1089			// Close all.
1090			secDB.Close();
1091			db.Close();
1092			env.Close();
1093		}
1094
1095		public void OpenSecDBInTxn(string home, string dbFileName,
1096		    string dbSecFileName, out DatabaseEnvironment env,
1097		    out BTreeDatabase db, out SecondaryBTreeDatabase secDB)
1098		{
1099			// Open environment.
1100			DatabaseEnvironmentConfig envCfg =
1101			    new DatabaseEnvironmentConfig();
1102			envCfg.Create = true;
1103			envCfg.UseLocking = true;
1104			envCfg.UseLogging = true;
1105			envCfg.UseMPool = true;
1106			envCfg.UseTxns = true;
1107			env = DatabaseEnvironment.Open(
1108			    home, envCfg);
1109
1110			// Open primary and secondary database in a transaction.
1111			Transaction openTxn = env.BeginTransaction();
1112			BTreeDatabaseConfig dbConfig =
1113			    new BTreeDatabaseConfig();
1114			dbConfig.Creation = CreatePolicy.IF_NEEDED;
1115			dbConfig.Env = env;
1116			dbConfig.PageSize = 4096;
1117			dbConfig.Duplicates = DuplicatesPolicy.NONE;
1118			dbConfig.ReadUncommitted = true;
1119			db = BTreeDatabase.Open(dbFileName, dbConfig,
1120			    openTxn);
1121			openTxn.Commit();
1122
1123			openTxn = env.BeginTransaction();
1124			SecondaryBTreeDatabaseConfig secConfig =
1125			    new SecondaryBTreeDatabaseConfig(db,
1126			    new SecondaryKeyGenDelegate(SecondaryKeyGen));
1127			secConfig.Creation = CreatePolicy.IF_NEEDED;
1128			secConfig.Duplicates = DuplicatesPolicy.SORTED;
1129			secConfig.Env = env;
1130			secConfig.ReadUncommitted = true;
1131			secDB = SecondaryBTreeDatabase.Open(dbSecFileName,
1132			    secConfig, openTxn);
1133			openTxn.Commit();
1134		}
1135
1136		public void WriteRecords(BTreeDatabase db)
1137		{
1138			/*
1139			 * Write ten records into the database. The records
1140			 * from 1st to 5th and 8th to 10th are unique in the
1141			 * database. The data in the 6th and 7th records
1142			 * are the same.
1143			 */
1144			for (int i = 0; i < 10; i++)
1145			{
1146				if (i == 5 || i == 6)
1147					db.Put(new DatabaseEntry(
1148					    BitConverter.GetBytes(i)),
1149					    new DatabaseEntry(
1150					    BitConverter.GetBytes((int)10)));
1151				else
1152					db.Put(new DatabaseEntry(
1153					    BitConverter.GetBytes(i)),
1154					    new DatabaseEntry(BitConverter.GetBytes(i)));
1155			}
1156		}
1157
1158		public void WriteRecordsInTxn(BTreeDatabase db,
1159		    DatabaseEnvironment env)
1160		{
1161			Transaction txn = env.BeginTransaction();
1162			/*
1163			 * Write ten records into the database. The records
1164			 * from 1st to 5th and 8th to 10th are unique in the
1165			 * database. The data in the 6th and 7th records
1166			 * are the same.
1167			 */
1168			for (int i = 0; i < 10; i++)
1169			{
1170				if (i == 5 || i == 6)
1171					db.Put(new DatabaseEntry(
1172					    BitConverter.GetBytes(i)),
1173					    new DatabaseEntry(
1174					    BitConverter.GetBytes((int)10)), txn);
1175				else
1176					db.Put(new DatabaseEntry(
1177					    BitConverter.GetBytes(i)),
1178					    new DatabaseEntry(BitConverter.GetBytes(i)), txn);
1179			}
1180
1181			txn.Commit();
1182		}
1183
1184
1185		public void OpenSecDB(string dbFileName,
1186		    string dbSecFileName, out BTreeDatabase db,
1187		    out SecondaryBTreeDatabase secDB)
1188		{
1189			// Open a primary database.
1190			BTreeDatabaseConfig dbConfig =
1191			    new BTreeDatabaseConfig();
1192			dbConfig.Creation = CreatePolicy.IF_NEEDED;
1193			db = BTreeDatabase.Open(dbFileName, dbConfig);
1194
1195			// Open a secondary database.
1196			SecondaryBTreeDatabaseConfig secConfig =
1197			    new SecondaryBTreeDatabaseConfig(db,
1198			    new SecondaryKeyGenDelegate(SecondaryKeyGen));
1199			secConfig.Creation = CreatePolicy.IF_NEEDED;
1200			secConfig.Duplicates = DuplicatesPolicy.SORTED;
1201			secDB = SecondaryBTreeDatabase.Open(dbSecFileName,
1202			    secConfig);
1203		}
1204
1205
1206		public DatabaseEntry SecondaryKeyGen(
1207		    DatabaseEntry key, DatabaseEntry data)
1208		{
1209			DatabaseEntry dbtGen;
1210			dbtGen = new DatabaseEntry(data.Data);
1211			return dbtGen;
1212		}
1213	}
1214}
1215