summaryrefslogtreecommitdiff
path: root/test/scr037
diff options
context:
space:
mode:
Diffstat (limited to 'test/scr037')
-rw-r--r--test/scr037/AllTestData.xml796
-rw-r--r--test/scr037/BTreeCursorTest.cs1192
-rw-r--r--test/scr037/BTreeDatabaseConfigTest.cs92
-rw-r--r--test/scr037/BTreeDatabaseTest.cs2309
-rw-r--r--test/scr037/Configuration.cs1107
-rw-r--r--test/scr037/CursorConfigTest.cs81
-rw-r--r--test/scr037/CursorTest.cs1459
-rw-r--r--test/scr037/DatabaseConfigTest.cs109
-rw-r--r--test/scr037/DatabaseEnvironmentConfigTest.cs299
-rw-r--r--test/scr037/DatabaseEnvironmentTest.cs1778
-rw-r--r--test/scr037/DatabaseExceptionTest.cs221
-rw-r--r--test/scr037/DatabaseTest.cs109
-rw-r--r--test/scr037/DotNetTest.csproj116
-rw-r--r--test/scr037/ForeignKeyTest.cs280
-rw-r--r--test/scr037/HashCursorTest.cs237
-rw-r--r--test/scr037/HashDatabaseConfigTest.cs85
-rw-r--r--test/scr037/HashDatabaseTest.cs466
-rw-r--r--test/scr037/JoinCursorTest.cs204
-rw-r--r--test/scr037/LockTest.cs116
-rw-r--r--test/scr037/LockingConfigTest.cs162
-rw-r--r--test/scr037/LogConfigTest.cs297
-rw-r--r--test/scr037/LogCursorTest.cs321
-rw-r--r--test/scr037/MPoolConfigTest.cs85
-rw-r--r--test/scr037/MutexConfigTest.cs82
-rw-r--r--test/scr037/MutexTest.cs126
-rw-r--r--test/scr037/QueueDatabaseConfigTest.cs88
-rw-r--r--test/scr037/QueueDatabaseTest.cs646
-rw-r--r--test/scr037/README1
-rw-r--r--test/scr037/RecnoCursorTest.cs257
-rw-r--r--test/scr037/RecnoDatabaseConfigTest.cs131
-rw-r--r--test/scr037/RecnoDatabaseTest.cs487
-rw-r--r--test/scr037/ReplicationConfigTest.cs215
-rw-r--r--test/scr037/ReplicationTest.cs748
-rw-r--r--test/scr037/SecondaryBTreeDatabaseConfigTest.cs115
-rw-r--r--test/scr037/SecondaryBTreeDatabaseTest.cs232
-rw-r--r--test/scr037/SecondaryCursorTest.cs1214
-rw-r--r--test/scr037/SecondaryDatabaseConfigTest.cs83
-rw-r--r--test/scr037/SecondaryDatabaseTest.cs518
-rw-r--r--test/scr037/SecondaryHashDatabaseConfigTest.cs109
-rw-r--r--test/scr037/SecondaryHashDatabaseTest.cs403
-rw-r--r--test/scr037/SecondaryQueueDatabaseConfigTest.cs109
-rw-r--r--test/scr037/SecondaryQueueDatabaseTest.cs227
-rw-r--r--test/scr037/SecondaryRecnoDatabaseConfigTest.cs119
-rw-r--r--test/scr037/SecondaryRecnoDatabaseTest.cs269
-rw-r--r--test/scr037/SequenceConfigTest.cs132
-rw-r--r--test/scr037/SequenceTest.cs406
-rw-r--r--test/scr037/TestException.cs49
-rw-r--r--test/scr037/TransactionConfigTest.cs73
-rw-r--r--test/scr037/TransactionTest.cs435
-rw-r--r--test/scr037/XMLReader.cs48
-rw-r--r--test/scr037/bdb4.7.dbbin0 -> 16384 bytes
51 files changed, 19243 insertions, 0 deletions
diff --git a/test/scr037/AllTestData.xml b/test/scr037/AllTestData.xml
new file mode 100644
index 0000000..93fdd24
--- /dev/null
+++ b/test/scr037/AllTestData.xml
@@ -0,0 +1,796 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<Assembly>
+ <TestFixture name="DatabaseConfigTest">
+ <Test name="TestConfigWithoutEnv">
+ <AutoCommit>True</AutoCommit>
+ <ByteOrder>1234</ByteOrder>
+ <CacheSize>
+ <Bytes>1048576</Bytes>
+ <Gigabytes>0</Gigabytes>
+ <NCaches>1</NCaches>
+ </CacheSize>
+ <DoChecksum>True</DoChecksum>
+ <ErrorPrefix>TestDatabaseConfig</ErrorPrefix>
+ <FreeThreaded>True</FreeThreaded>
+ <NoMMap>True</NoMMap>
+ <NonDurableTxns>True</NonDurableTxns>
+ <PageSize>8196</PageSize>
+ <Priority>HIGH</Priority>
+ <ReadOnly>True</ReadOnly>
+ <ReadUncommitted>True</ReadUncommitted>
+ <Encryption>
+ <password>123</password>
+ <algorithm>AES</algorithm>
+ </Encryption>
+ <Truncate>True</Truncate>
+ <UseEncryption>True</UseEncryption>
+ <UseMVCC>True</UseMVCC>
+ </Test>
+ <Test name="TestConfigWithEnv">
+ <Env>
+ <Create>True</Create>
+ <CreationDir>.//test_DB</CreationDir>
+ <DataDir>.//test_DB</DataDir>
+ <ErrorPrefix>TestDatabaseConfigWithEnv</ErrorPrefix>
+ </Env>
+ </Test>
+ </TestFixture>
+ <TestFixture name="BTreeDatabaseConfigTest">
+ <Test name="TestConfigWithoutEnv">
+ <AutoCommit>False</AutoCommit>
+ <ByteOrder>1234</ByteOrder>
+ <CacheSize>
+ <Bytes>1048576</Bytes>
+ <Gigabytes>0</Gigabytes>
+ <NCaches>1</NCaches>
+ </CacheSize>
+ <Creation>ALWAYS</Creation>
+ <DoChecksum>False</DoChecksum>
+ <Duplicates>UNSORTED</Duplicates>
+ <Encryption>
+ <password>123</password>
+ <algorithm>AES</algorithm>
+ </Encryption>
+ <ErrorPrefix>TestDatabaseConfig</ErrorPrefix>
+ <FreeThreaded>True</FreeThreaded>
+ <MinKeysPerPage>64</MinKeysPerPage>
+ <NoMMap>False</NoMMap>
+ <NonDurableTxns>False</NonDurableTxns>
+ <NoReverseSplitting>True</NoReverseSplitting>
+ <PageSize>8192</PageSize>
+ <Priority>HIGH</Priority>
+ <ReadOnly>False</ReadOnly>
+ <ReadUncommitted>False</ReadUncommitted>
+ <Truncate>False</Truncate>
+ <UseEncryption>True</UseEncryption>
+ <UseMVCC>False</UseMVCC>
+ <UseRecordNumbers>False</UseRecordNumbers>
+ </Test>
+ </TestFixture>
+ <TestFixture name="BTreeDatabaseTest">
+ <Test name="TestOpenNewBtreeDB">
+ <AutoCommit>False</AutoCommit>
+ <ByteOrder>1234</ByteOrder>
+ <CacheSize>
+ <Bytes>1048576</Bytes>
+ <Gigabytes>0</Gigabytes>
+ <NCaches>1</NCaches>
+ </CacheSize>
+ <Creation>ALWAYS</Creation>
+ <DoChecksum>False</DoChecksum>
+ <Duplicates>UNSORTED</Duplicates>
+ <ErrorPrefix>TestDatabaseConfig</ErrorPrefix>
+ <FreeThreaded>True</FreeThreaded>
+ <HasMultiple>True</HasMultiple>
+ <MinKeysPerPage>64</MinKeysPerPage>
+ <NoMMap>False</NoMMap>
+ <NonDurableTxns>False</NonDurableTxns>
+ <NoReverseSplitting>True</NoReverseSplitting>
+ <PageSize>8192</PageSize>
+ <Priority>HIGH</Priority>
+ <ReadOnly>False</ReadOnly>
+ <ReadUncommitted>False</ReadUncommitted>
+ <Encryption>
+ <password>123</password>
+ <algorithm>AES</algorithm>
+ </Encryption>
+ <Truncate>False</Truncate>
+ <UseEncryption>True</UseEncryption>
+ <UseMVCC>False</UseMVCC>
+ <UseRecordNumbers>False</UseRecordNumbers>
+ </Test>
+ </TestFixture>
+ <TestFixture name="HashDatabaseConfigTest">
+ <Test name="TestConfigWithoutEnv">
+ <AutoCommit>False</AutoCommit>
+ <ByteOrder>1234</ByteOrder>
+ <CacheSize>
+ <Bytes>1048576</Bytes>
+ <Gigabytes>0</Gigabytes>
+ <NCaches>1</NCaches>
+ </CacheSize>
+ <Creation>ALWAYS</Creation>
+ <DoChecksum>False</DoChecksum>
+ <Duplicates>UNSORTED</Duplicates>
+ <ErrorPrefix>TestConfigWithoutEnv</ErrorPrefix>
+ <FillFactor>7</FillFactor>
+ <FreeThreaded>False</FreeThreaded>
+ <NoMMap>True</NoMMap>
+ <NonDurableTxns>True</NonDurableTxns>
+ <NumElements>100</NumElements>
+ <PageSize>8192</PageSize>
+ <Priority>HIGH</Priority>
+ <ReadOnly>False</ReadOnly>
+ <ReadUncommitted>False</ReadUncommitted>
+ <Encryption>
+ <password>123</password>
+ <algorithm>AES</algorithm>
+ </Encryption>
+ <Truncate>False</Truncate>
+ <UseEncryption>True</UseEncryption>
+ <UseMVCC>False</UseMVCC>
+ </Test>
+ </TestFixture>
+ <TestFixture name="HashDatabaseTest">
+ <Test name="TestOpenNewHashDB">
+ <AutoCommit>False</AutoCommit>
+ <ByteOrder>1234</ByteOrder>
+ <CacheSize>
+ <Bytes>1048576</Bytes>
+ <Gigabytes>0</Gigabytes>
+ <NCaches>1</NCaches>
+ </CacheSize>
+ <Creation>ALWAYS</Creation>
+ <DoChecksum>False</DoChecksum>
+ <Duplicates>UNSORTED</Duplicates>
+ <ErrorPrefix>TestDatabaseConfig</ErrorPrefix>
+ <FillFactor>2</FillFactor>
+ <FreeThreaded>True</FreeThreaded>
+ <HasMultiple>False</HasMultiple>
+ <NoMMap>False</NoMMap>
+ <NonDurableTxns>False</NonDurableTxns>
+ <NumElements>10</NumElements>
+ <PageSize>8192</PageSize>
+ <Priority>HIGH</Priority>
+ <ReadOnly>False</ReadOnly>
+ <ReadUncommitted>False</ReadUncommitted>
+ <Encryption>
+ <password>123</password>
+ <algorithm>AES</algorithm>
+ </Encryption>
+ <Truncate>False</Truncate>
+ <UseMVCC>False</UseMVCC>
+ </Test>
+ </TestFixture>
+ <TestFixture name="RecnoDatabaseConfigTest">
+ <Test name="TestConfigWithoutEnv">
+ <AutoCommit>False</AutoCommit>
+ <BackingFile>../backing.log</BackingFile>
+ <ByteOrder>1234</ByteOrder>
+ <CacheSize>
+ <Bytes>1048576</Bytes>
+ <Gigabytes>0</Gigabytes>
+ <NCaches>1</NCaches>
+ </CacheSize>
+ <ConsumeInOrder>True</ConsumeInOrder>
+ <Creation>IF_NEEDED</Creation>
+ <Delimiter>10</Delimiter>
+ <DoChecksum>True</DoChecksum>
+ <Duplicates>UNSORTED</Duplicates>
+ <ErrorPrefix>TestDatabaseConfig</ErrorPrefix>
+ <ExtentSize>2</ExtentSize>
+ <FreeThreaded>True</FreeThreaded>
+ <Length>100</Length>
+ <PadByte>10</PadByte>
+ <NoMMap>False</NoMMap>
+ <NonDurableTxns>True</NonDurableTxns>
+ <PageSize>8192</PageSize>
+ <Priority>HIGH</Priority>
+ <ReadOnly>True</ReadOnly>
+ <ReadUncommitted>True</ReadUncommitted>
+ <Renumber>True</Renumber>
+ <Encryption>
+ <password>123</password>
+ <algorithm>AES</algorithm>
+ </Encryption>
+ <Snapshot>True</Snapshot>
+ <Truncate>True</Truncate>
+ <UseEncryption>True</UseEncryption>
+ <UseMVCC>True</UseMVCC>
+ </Test>
+ </TestFixture>
+ <TestFixture name="QueueDatabaseConfigTest">
+ <Test name="TestConfigWithoutEnv">
+ <AutoCommit>False</AutoCommit>
+ <ByteOrder>1234</ByteOrder>
+ <CacheSize>
+ <Bytes>1048576</Bytes>
+ <Gigabytes>0</Gigabytes>
+ <NCaches>1</NCaches>
+ </CacheSize>
+ <ConsumeInOrder>True</ConsumeInOrder>
+ <Creation>ALWAYS</Creation>
+ <DoChecksum>False</DoChecksum>
+ <Duplicates>UNSORTED</Duplicates>
+ <ErrorPrefix>TestDatabaseConfig</ErrorPrefix>
+ <ExtentSize>2</ExtentSize>
+ <FreeThreaded>True</FreeThreaded>
+ <Length>20</Length>
+ <PadByte>10</PadByte>
+ <NoMMap>False</NoMMap>
+ <NonDurableTxns>False</NonDurableTxns>
+ <PageSize>40960</PageSize>
+ <Priority>HIGH</Priority>
+ <ReadOnly>False</ReadOnly>
+ <ReadUncommitted>False</ReadUncommitted>
+ <Encryption>
+ <password>123</password>
+ <algorithm>AES</algorithm>
+ </Encryption>
+ <Truncate>False</Truncate>
+ <UseEncryption>True</UseEncryption>
+ <UseMVCC>False</UseMVCC>
+ </Test>
+ </TestFixture>
+ <TestFixture name="QueueDatabaseTest">
+ <Test name="TestOpenNewQueueDB">
+ <AutoCommit>False</AutoCommit>
+ <ByteOrder>1234</ByteOrder>
+ <CacheSize>
+ <Bytes>1048576</Bytes>
+ <Gigabytes>0</Gigabytes>
+ <NCaches>1</NCaches>
+ </CacheSize>
+ <ConsumeInOrder>True</ConsumeInOrder>
+ <Creation>ALWAYS</Creation>
+ <DoChecksum>False</DoChecksum>
+ <Duplicates>UNSORTED</Duplicates>
+ <ErrorPrefix>TestDatabaseConfig</ErrorPrefix>
+ <ExtentSize>2</ExtentSize>
+ <FreeThreaded>True</FreeThreaded>
+ <HasMultiple>False</HasMultiple>
+ <Length>100</Length>
+ <PadByte>10</PadByte>
+ <NoMMap>False</NoMMap>
+ <NonDurableTxns>False</NonDurableTxns>
+ <PageSize>8192</PageSize>
+ <Priority>HIGH</Priority>
+ <ReadOnly>False</ReadOnly>
+ <ReadUncommitted>False</ReadUncommitted>
+ <Encryption>
+ <password>123</password>
+ <algorithm>AES</algorithm>
+ </Encryption>
+ <Truncate>False</Truncate>
+ <UseEncryption>True</UseEncryption>
+ <UseMVCC>False</UseMVCC>
+ </Test>
+ </TestFixture>
+ <TestFixture name="RecnoDatabaseTest">
+ <Test name="TestOpenNewRecnoDB">
+ <AutoCommit>False</AutoCommit>
+ <ByteOrder>1234</ByteOrder>
+ <CacheSize>
+ <Bytes>1048576</Bytes>
+ <Gigabytes>0</Gigabytes>
+ <NCaches>1</NCaches>
+ </CacheSize>
+ <Creation>ALWAYS</Creation>
+ <Delimiter>100</Delimiter>
+ <DoChecksum>False</DoChecksum>
+ <Duplicates>UNSORTED</Duplicates>
+ <ErrorPrefix>TestDatabaseConfig</ErrorPrefix>
+ <FreeThreaded>True</FreeThreaded>
+ <HasMultiple>True</HasMultiple>
+ <Length>100</Length>
+ <NoMMap>False</NoMMap>
+ <NonDurableTxns>False</NonDurableTxns>
+ <NoReverseSplitting>True</NoReverseSplitting>
+ <PadByte>100</PadByte>
+ <PageSize>8192</PageSize>
+ <Priority>HIGH</Priority>
+ <ReadOnly>False</ReadOnly>
+ <ReadUncommitted>False</ReadUncommitted>
+ <Renumber>False</Renumber>
+ <Encryption>
+ <password>123</password>
+ <algorithm>AES</algorithm>
+ </Encryption>
+ <Snapshot>False</Snapshot>
+ <Truncate>False</Truncate>
+ <UseEncryption>True</UseEncryption>
+ <UseMVCC>False</UseMVCC>
+ <UseRecordNumbers>False</UseRecordNumbers>
+ </Test>
+ </TestFixture>
+ <TestFixture name="LockingConfigTest">
+ <Test name="TestConfig">
+ <Conflicts>
+ <E>
+ <E>1</E>
+ <E>1</E>
+ <E>1</E>
+ </E>
+ <E>
+ <E>1</E>
+ <E>1</E>
+ <E>1</E>
+ </E>
+ <E>
+ <E>1</E>
+ <E>1</E>
+ <E>1</E>
+ </E>
+ </Conflicts>
+ <DeadlockResolution>MAX_LOCKS</DeadlockResolution>
+ <MaxLocks>10</MaxLocks>
+ <MaxLockers>10</MaxLockers>
+ <MaxObjects>10</MaxObjects>
+ <Partitions>3</Partitions>
+ </Test>
+ </TestFixture>
+ <TestFixture name="LogConfigTest">
+ <Test name="TestConfig">
+ <AutoRemove>True</AutoRemove>
+ <BufferSize>4096</BufferSize>
+ <Dir>./</Dir>
+ <FileMode>755</FileMode>
+ <ForceSync>True</ForceSync>
+ <InMemory>True</InMemory>
+ <MaxFileSize>1048576</MaxFileSize>
+ <NoBuffer>True</NoBuffer>
+ <RegionSize>30720</RegionSize>
+ <ZeroOnCreate>True</ZeroOnCreate>
+ </Test>
+ </TestFixture>
+ <TestFixture name="MutexConfigTest">
+ <Test name="TestConfig">
+ <Alignment>256</Alignment>
+ <Increment>10</Increment>
+ <MaxMutexes>50</MaxMutexes>
+ <NumTestAndSetSpins>5</NumTestAndSetSpins>
+ </Test>
+ </TestFixture>
+ <TestFixture name="TransactionConfigTest">
+ <Test name="TestConfig">
+ <IsolationDegree>2</IsolationDegree>
+ <NoWait>True</NoWait>
+ <Snapshot>True</Snapshot>
+ <SyncAction>WRITE_NOSYNC</SyncAction>
+ </Test>
+ </TestFixture>
+ <TestFixture name="MPoolConfigTest">
+ <Test name="TestConfig">
+ <CacheSize>
+ <Bytes>1048576</Bytes>
+ <Gigabytes>0</Gigabytes>
+ <NCaches>1</NCaches>
+ </CacheSize>
+ <MaxCacheSize>
+ <Bytes>10485760</Bytes>
+ <Gigabytes>0</Gigabytes>
+ <NCaches>1</NCaches>
+ </MaxCacheSize>
+ <MaxOpenFiles>10</MaxOpenFiles>
+ <MaxSequentialWrites>
+ <maxWrites>10</maxWrites>
+ <pause>1000</pause>
+ </MaxSequentialWrites>
+ <MMapSize>1048576</MMapSize>
+ </Test>
+ </TestFixture>
+ <TestFixture name="SecondaryDatabaseConfigTest">
+ <Test name="TestConfig">
+ <ImmutableKey>True</ImmutableKey>
+ <Populate>True</Populate>
+ </Test>
+ </TestFixture>
+ <TestFixture name="SecondaryBTreeDatabaseConfigTest">
+ <Test name="TestConfig">
+ <Creation>NEVER</Creation>
+ <Duplicates>SORTED</Duplicates>
+ <NoReverseSplitting>True</NoReverseSplitting>
+ <UseRecordNumbers>True</UseRecordNumbers>
+ <MinKeysPerPage>100</MinKeysPerPage>
+ <ImmutableKey>True</ImmutableKey>
+ <Populate>True</Populate>
+ </Test>
+ </TestFixture>
+ <TestFixture name="SecondaryBTreeDatabaseTest">
+ <Test name="TestOpen">
+ <ImmutableKey>False</ImmutableKey>
+ <Populate>True</Populate>
+ <Creation>ALWAYS</Creation>
+ <Duplicates>SORTED</Duplicates>
+ <NoReverseSplitting>True</NoReverseSplitting>
+ <UseRecordNumbers>False</UseRecordNumbers>
+ <MinKeysPerPage>64</MinKeysPerPage>
+ </Test>
+ </TestFixture>
+ <TestFixture name="SecondaryHashDatabaseConfigTest">
+ <Test name="TestConfig">
+ <ImmutableKey>True</ImmutableKey>
+ <Populate>True</Populate>
+ <Creation>NEVER</Creation>
+ <Duplicates>SORTED</Duplicates>
+ <FillFactor>5</FillFactor>
+ <NumElements>100</NumElements>
+ </Test>
+ </TestFixture>
+ <TestFixture name="SecondaryHashDatabaseTest">
+ <Test name="TestOpen">
+ <ImmutableKey>True</ImmutableKey>
+ <Populate>True</Populate>
+ <Creation>ALWAYS</Creation>
+ <Duplicates>SORTED</Duplicates>
+ <FillFactor>5</FillFactor>
+ <NumElements>100</NumElements>
+ </Test>
+ </TestFixture>
+ <TestFixture name="SecondaryQueueDatabaseConfigTest">
+ <Test name="TestConfig">
+ <ImmutableKey>True</ImmutableKey>
+ <Populate>True</Populate>
+ <Creation>NEVER</Creation>
+ <Length>100</Length>
+ <PadByte>10</PadByte>
+ <ExtentSize>4</ExtentSize>
+ </Test>
+ </TestFixture>
+ <TestFixture name="SecondaryQueueDatabaseTest">
+ <Test name="TestOpen">
+ <ImmutableKey>True</ImmutableKey>
+ <Populate>True</Populate>
+ <Creation>ALWAYS</Creation>
+ <Length>100</Length>
+ <PadByte>10</PadByte>
+ <ExtentSize>4</ExtentSize>
+ </Test>
+ </TestFixture>
+ <TestFixture name="SecondaryRecnoDatabaseConfigTest">
+ <Test name="TestConfig">
+ <ImmutableKey>True</ImmutableKey>
+ <Populate>True</Populate>
+ <BackingFile>.//backing</BackingFile>
+ <Creation>NEVER</Creation>
+ <Delimiter>100</Delimiter>
+ <Length>100</Length>
+ <PadByte>100</PadByte>
+ <Renumber>False</Renumber>
+ <Snapshot>False</Snapshot>
+ </Test>
+ </TestFixture>
+ <TestFixture name="SecondaryRecnoDatabaseTest">
+ <Test name="TestOpen">
+ <ImmutableKey>True</ImmutableKey>
+ <Populate>True</Populate>
+ <Creation>ALWAYS</Creation>
+ <Delimiter>100</Delimiter>
+ <Length>120</Length>
+ <PadByte>50</PadByte>
+ <Renumber>False</Renumber>
+ <Snapshot>False</Snapshot>
+ </Test>
+ </TestFixture>
+ <TestFixture name="SequenceConfigTest">
+ <Test name="TestConfig">
+ <CacheSize>1048576</CacheSize>
+ <Creation>ALWAYS</Creation>
+ <Decrement>True</Decrement>
+ <FreeThreaded>True</FreeThreaded>
+ <Increment>True</Increment>
+ <InitialValue>10</InitialValue>
+ <Max>1000</Max>
+ <Min>17</Min>
+ <Wrap>True</Wrap>
+ </Test>
+ </TestFixture>
+ <TestFixture name="SequenceTest">
+ <Test name="TestConfig">
+ <CacheSize>1048576</CacheSize>
+ <Creation>ALWAYS</Creation>
+ <Decrement>True</Decrement>
+ <FreeThreaded>True</FreeThreaded>
+ <Increment>False</Increment>
+ <InitialValue>10</InitialValue>
+ <Wrap>True</Wrap>
+ </Test>
+ </TestFixture>
+ <TestFixture name="DatabaseEnvironmentConfigTest">
+ <Test name="TestConfig">
+ <AutoCommit>True</AutoCommit>
+ <CDB_ALLDB>True</CDB_ALLDB>
+ <Create>True</Create>
+ <CreationDir>./</CreationDir>
+ <DataDirs>
+ <a>./</a>
+ <a>./TestDbEnv</a>
+ </DataDirs>
+ <ErrorPrefix>TestConfig</ErrorPrefix>
+ <ForceFlush>True</ForceFlush>
+ <FreeThreaded>True</FreeThreaded>
+ <MaxTransactions>10</MaxTransactions>
+ <InitRegions>True</InitRegions>
+ <IntermediateDirMode>rwx------</IntermediateDirMode>
+ <Lockdown>True</Lockdown>
+ <LockTimeout>1000</LockTimeout>
+ <NoBuffer>True</NoBuffer>
+ <NoLocking>True</NoLocking>
+ <NoMMap>True</NoMMap>
+ <NoPanic>True</NoPanic>
+ <Overwrite>True</Overwrite>
+ <Private>True</Private>
+ <Register>True</Register>
+ <RunFatalRecovery>True</RunFatalRecovery>
+ <RunRecovery>True</RunRecovery>
+ <SystemMemory>True</SystemMemory>
+ <TempDir>.//test_DB</TempDir>
+ <TimeNotGranted>True</TimeNotGranted>
+ <TxnNoSync>True</TxnNoSync>
+ <TxnNoWait>True</TxnNoWait>
+ <TxnSnapshot>True</TxnSnapshot>
+ <TxnTimestamp>2008-12-09</TxnTimestamp>
+ <TxnWriteNoSync>True</TxnWriteNoSync>
+ <UseCDB>True</UseCDB>
+ <UseLocking>True</UseLocking>
+ <UseLogging>True</UseLogging>
+ <UseMPool>True</UseMPool>
+ <UseMVCC>True</UseMVCC>
+ <UseReplication>True</UseReplication>
+ <UseTxns>True</UseTxns>
+ <Verbosity>
+ <AllFileOps>True</AllFileOps>
+ <Deadlock>True</Deadlock>
+ <FileOps>True</FileOps>
+ <Recovery>True</Recovery>
+ <Register>True</Register>
+ <Replication>True</Replication>
+ <ReplicationElection>True</ReplicationElection>
+ <ReplicationLease>True</ReplicationLease>
+ <ReplicationMessages>True</ReplicationMessages>
+ <ReplicationMisc>True</ReplicationMisc>
+ <ReplicationSync>True</ReplicationSync>
+ <RepMgrConnectionFailure>True</RepMgrConnectionFailure>
+ <RepMgrMisc>True</RepMgrMisc>
+ <WaitsForTable>True</WaitsForTable>
+ </Verbosity>
+ <YieldCPU>True</YieldCPU>
+ </Test>
+ <Test name="TestConfigLock">
+ <Conflicts>
+ <E>
+ <E>10</E>
+ <E>20</E>
+ </E>
+ <E>
+ <E>30</E>
+ <E>40</E>
+ </E>
+ </Conflicts>
+ <DeadlockResolution>MAX_LOCKS</DeadlockResolution>
+ <MaxLocks>50</MaxLocks>
+ <MaxLockers>60</MaxLockers>
+ <MaxObjects>70</MaxObjects>
+ <Partitions>3</Partitions>
+ </Test>
+ <Test name="TestConfigLog">
+ <AutoRemove>True</AutoRemove>
+ <BufferSize>10240</BufferSize>
+ <Dir>./</Dir>
+ <FileMode>755</FileMode>
+ <ForceSync>True</ForceSync>
+ <InMemory>True</InMemory>
+ <MaxFileSize>1048576</MaxFileSize>
+ <NoBuffer>True</NoBuffer>
+ <RegionSize>20480</RegionSize>
+ <ZeroOnCreate>True</ZeroOnCreate>
+ </Test>
+ <Test name="TestConfigMutex">
+ <Alignment>512</Alignment>
+ <Increment>128</Increment>
+ <MaxMutexes>15</MaxMutexes>
+ <NumTestAndSetSpins>10</NumTestAndSetSpins>
+ </Test>
+ <Test name="TestConfigReplication">
+ <AckTimeout>2000</AckTimeout>
+ <BulkTransfer>True</BulkTransfer>
+ <CheckpointDelay>100</CheckpointDelay>
+ <ConnectionRetry>100</ConnectionRetry>
+ <DelayClientSync>True</DelayClientSync>
+ <ElectionRetry>15</ElectionRetry>
+ <ElectionTimeout>1050</ElectionTimeout>
+ <FullElectionTimeout>5000</FullElectionTimeout>
+ <HeartbeatMonitor>100</HeartbeatMonitor>
+ <HeartbeatSend>50</HeartbeatSend>
+ <LeaseTimeout>1025</LeaseTimeout>
+ <NoAutoInit>True</NoAutoInit>
+ <NoBlocking>True</NoBlocking>
+ <NSites>7</NSites>
+ <Priority>1</Priority>
+ <RepMgrAckPolicy>ALL</RepMgrAckPolicy>
+ <RepMgrLocalSite>
+ <Host>127.0.0.0</Host>
+ <Port>11111</Port>
+ </RepMgrLocalSite>
+ <Strict2Site>True</Strict2Site>
+ <UseMasterLeases>True</UseMasterLeases>
+ </Test>
+ </TestFixture>
+ <TestFixture name="DatabaseEnvironmentTest">
+ <Test name="TestConfigAll">
+ <AutoCommit>True</AutoCommit>
+ <CDB_ALLDB>False</CDB_ALLDB>
+ <Create>True</Create>
+ <CreationDir>./</CreationDir>
+ <DataDirs>
+ <a>./</a>
+ <a>./TestDbEnv</a>
+ </DataDirs>
+ <ErrorPrefix>TestConfigAll</ErrorPrefix>
+ <ForceFlush>False</ForceFlush>
+ <FreeThreaded>True</FreeThreaded>
+ <MaxTransactions>10</MaxTransactions>
+ <InitRegions>True</InitRegions>
+ <IntermediateDirMode>rwx------</IntermediateDirMode>
+ <Lockdown>False</Lockdown>
+ <LockTimeout>1000</LockTimeout>
+ <NoBuffer>False</NoBuffer>
+ <NoLocking>False</NoLocking>
+ <NoMMap>False</NoMMap>
+ <NoPanic>False</NoPanic>
+ <Overwrite>True</Overwrite>
+ <Private>False</Private>
+ <Register>False</Register>
+ <RunFatalRecovery>False</RunFatalRecovery>
+ <RunRecovery>False</RunRecovery>
+ <SystemMemory>False</SystemMemory>
+ <TempDir>.//test_DB</TempDir>
+ <TimeNotGranted>True</TimeNotGranted>
+ <TxnNoSync>False</TxnNoSync>
+ <TxnNoWait>False</TxnNoWait>
+ <TxnSnapshot>False</TxnSnapshot>
+ <TxnTimestamp>2008-12-09</TxnTimestamp>
+ <TxnWriteNoSync>False</TxnWriteNoSync>
+ <UseCDB>False</UseCDB>
+ <UseLocking>True</UseLocking>
+ <UseLogging>True</UseLogging>
+ <UseMPool>True</UseMPool>
+ <UseMVCC>True</UseMVCC>
+ <UseReplication>True</UseReplication>
+ <UseTxns>True</UseTxns>
+ <Verbosity>
+ <AllFileOps>True</AllFileOps>
+ <Deadlock>True</Deadlock>
+ <FileOps>True</FileOps>
+ <Recovery>False</Recovery>
+ <Register>False</Register>
+ <Replication>True</Replication>
+ <ReplicationElection>True</ReplicationElection>
+ <ReplicationLease>True</ReplicationLease>
+ <ReplicationMessages>True</ReplicationMessages>
+ <ReplicationMisc>True</ReplicationMisc>
+ <ReplicationSync>True</ReplicationSync>
+ <RepMgrConnectionFailure>True</RepMgrConnectionFailure>
+ <RepMgrMisc>True</RepMgrMisc>
+ <WaitsForTable>False</WaitsForTable>
+ </Verbosity>
+ <YieldCPU>True</YieldCPU>
+
+ <LockingConfig>
+ <Conflicts>
+ <E>
+ <E>2</E>
+ <E>1</E>
+ </E>
+ <E>
+ <E>1</E>
+ <E>2</E>
+ </E>
+ </Conflicts>
+ <DeadlockResolution>MAX_LOCKS</DeadlockResolution>
+ <MaxLocks>50</MaxLocks>
+ <MaxLockers>10</MaxLockers>
+ <MaxObjects>60</MaxObjects>
+ <Partitions>10</Partitions>
+ </LockingConfig>
+
+ <LogConfig>
+ <AutoRemove>False</AutoRemove>
+ <BufferSize>10240</BufferSize>
+ <Dir>./</Dir>
+ <FileMode>755</FileMode>
+ <ForceSync>True</ForceSync>
+ <InMemory>False</InMemory>
+ <MaxFileSize>1048576</MaxFileSize>
+ <NoBuffer>False</NoBuffer>
+ <RegionSize>204800</RegionSize>
+ <ZeroOnCreate>True</ZeroOnCreate>
+ </LogConfig>
+
+ <MutexConfig>
+ <Alignment>512</Alignment>
+ <Increment>128</Increment>
+ <MaxMutexes>10000</MaxMutexes>
+ <NumTestAndSetSpins>10</NumTestAndSetSpins>
+ </MutexConfig>
+
+ <MPoolConfig>
+ <CacheSize>
+ <Bytes>10485760</Bytes>
+ <Gigabytes>0</Gigabytes>
+ <NCaches>2</NCaches>
+ </CacheSize>
+ <MaxCacheSize>
+ <Bytes>1048576</Bytes>
+ <Gigabytes>0</Gigabytes>
+ <NCaches>0</NCaches>
+ </MaxCacheSize>
+ <MaxOpenFiles>5</MaxOpenFiles>
+ <MaxSequentialWrites>
+ <maxWrites>1</maxWrites>
+ <pause>1000</pause>
+ </MaxSequentialWrites>
+ <MMapSize>1048576</MMapSize>
+ </MPoolConfig>
+
+ <ReplicationConfig>
+ <AckTimeout>2000</AckTimeout>
+ <BulkTransfer>True</BulkTransfer>
+ <CheckpointDelay>100</CheckpointDelay>
+ <ConnectionRetry>100</ConnectionRetry>
+ <DelayClientSync>True</DelayClientSync>
+ <ElectionRetry>15</ElectionRetry>
+ <ElectionTimeout>1050</ElectionTimeout>
+ <FullElectionTimeout>5000</FullElectionTimeout>
+ <HeartbeatMonitor>100</HeartbeatMonitor>
+ <HeartbeatSend>50</HeartbeatSend>
+ <LeaseTimeout>1025</LeaseTimeout>
+ <NoAutoInit>True</NoAutoInit>
+ <NoBlocking>True</NoBlocking>
+ <NSites>7</NSites>
+ <Priority>1</Priority>
+ <RepMgrAckPolicy>ALL</RepMgrAckPolicy>
+ <RepMgrLocalSite>
+ <Host>127.0.0.0</Host>
+ <Port>11111</Port>
+ </RepMgrLocalSite>
+ <Strict2Site>True</Strict2Site>
+ <UseMasterLeases>True</UseMasterLeases>
+ </ReplicationConfig>
+ </Test>
+ </TestFixture>
+ <TestFixture name="CursorConfigTest">
+ <Test name="TestConfig">
+ <IsolationDegree>2</IsolationDegree>
+ <Priority>VERY_HIGH</Priority>
+ <SnapshotIsolation>True</SnapshotIsolation>
+ <WriteCursor>True</WriteCursor>
+ </Test>
+ </TestFixture>
+ <TestFixture name="ReplicationConfigTest">
+ <Test name="TestConfig">
+ <AckTimeout>1000</AckTimeout>
+ <BulkTransfer>True</BulkTransfer>
+ <CheckpointDelay>101</CheckpointDelay>
+ <ConnectionRetry>102</ConnectionRetry>
+ <DelayClientSync>True</DelayClientSync>
+ <ElectionRetry>15</ElectionRetry>
+ <ElectionTimeout>1050</ElectionTimeout>
+ <FullElectionTimeout>5000</FullElectionTimeout>
+ <HeartbeatMonitor>100</HeartbeatMonitor>
+ <HeartbeatSend>50</HeartbeatSend>
+ <LeaseTimeout>1025</LeaseTimeout>
+ <NoAutoInit>True</NoAutoInit>
+ <NoBlocking>True</NoBlocking>
+ <NSites>7</NSites>
+ <Priority>1</Priority>
+ <RepMgrAckPolicy>ALL</RepMgrAckPolicy>
+ <RepMgrLocalSite>
+ <Host>127.0.0.0</Host>
+ <Port>11111</Port>
+ </RepMgrLocalSite>
+ <Strict2Site>True</Strict2Site>
+ <UseMasterLeases>True</UseMasterLeases>
+ </Test>
+ </TestFixture>
+</Assembly> \ No newline at end of file
diff --git a/test/scr037/BTreeCursorTest.cs b/test/scr037/BTreeCursorTest.cs
new file mode 100644
index 0000000..0fb6918
--- /dev/null
+++ b/test/scr037/BTreeCursorTest.cs
@@ -0,0 +1,1192 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class BTreeCursorTest
+ {
+ private string testFixtureName;
+ private string testFixtureHome;
+ private string testName;
+ private string testHome;
+
+ private DatabaseEnvironment paramEnv;
+ private BTreeDatabase paramDB;
+ private EventWaitHandle signal;
+
+ private delegate void BTCursorMoveFuncDelegate(
+ BTreeCursor cursor, LockingInfo lockingInfo);
+ private BTCursorMoveFuncDelegate btCursorFunc;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "BTreeCursorTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+ }
+
+ [Test]
+ public void TestAddKeyFirst()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+
+ testName = "TestAddKeyFirst";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Add record("key", "data") into database.
+ CursorTest.GetCursorInBtreeDBWithoutEnv(
+ testHome, testName, out db, out cursor);
+ CursorTest.AddOneByCursor(db, cursor);
+
+ // Add record("key","data1") as the first of the data item of "key".
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data1")));
+ cursor.Add(pair, Cursor.InsertLocation.FIRST);
+
+ // Confirm the record is added as the first of the data item of "key".
+ cursor.Move(new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")), true);
+ Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("data1"),
+ cursor.Current.Value.Data);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestAddKeyLast()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+
+ testName = "TestAddKeyLast";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Add record("key", "data") into database.
+ CursorTest.GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+ CursorTest.AddOneByCursor(db, cursor);
+
+ // Add new record("key","data1") as the last of the data item of "key".
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data1")));
+ cursor.Add(pair, Cursor.InsertLocation.LAST);
+
+ // Confirm the record is added as the first of the data item of "key".
+ cursor.Move(new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")), true);
+ Assert.AreNotEqual(ASCIIEncoding.ASCII.GetBytes("data1"),
+ cursor.Current.Value.Data);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestAddUnique()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+
+ testName = "TestAddUnique";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database and cursor.
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+
+ // To put no duplicate data, the database should be set to be sorted.
+ dbConfig.Duplicates = DuplicatesPolicy.SORTED;
+ db = BTreeDatabase.Open(testHome + "/" + testName + ".db", dbConfig);
+ cursor = db.Cursor();
+
+ // Add record("key", "data") into database.
+ CursorTest.AddOneByCursor(db, cursor);
+
+ // Fail to add duplicate record("key","data").
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
+ try
+ {
+ cursor.AddUnique(pair);
+ }
+ catch (KeyExistException)
+ {
+ }
+ finally
+ {
+ cursor.Close();
+ db.Close();
+ }
+ }
+
+ [Test]
+ public void TestDuplicateWithSamePos()
+ {
+ BTreeDatabase db;
+ BTreeDatabaseConfig dbConfig;
+ BTreeCursor cursor, dupCursor;
+ DatabaseEnvironment env;
+ DatabaseEnvironmentConfig envConfig;
+ DatabaseEntry key, data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ Transaction txn;
+
+ testName = "TestDuplicateWithSamePos";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ envConfig = new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ envConfig.NoMMap = false;
+ env = DatabaseEnvironment.Open(testHome, envConfig);
+
+ txn = env.BeginTransaction();
+ dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ db = BTreeDatabase.Open(testName + ".db", dbConfig, txn);
+ key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key"));
+ data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data"));
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
+ db.Put(key, data, txn);
+ txn.Commit();
+
+ txn = env.BeginTransaction();
+ cursor = db.Cursor(txn);
+ cursor.Move(key, true);
+
+ //Duplicate a new cursor to the same position.
+ dupCursor = cursor.Duplicate(true);
+
+ // Overwrite the record.
+ dupCursor.Overwrite(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("newdata")));
+
+ // Confirm that the original data doesn't exist.
+ Assert.IsFalse(dupCursor.Move(pair, true));
+
+ dupCursor.Close();
+ cursor.Close();
+ txn.Commit();
+ db.Close();
+ env.Close();
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestDuplicateToDifferentPos()
+ {
+ BTreeDatabase db;
+ BTreeDatabaseConfig dbConfig;
+ BTreeCursor cursor, dupCursor;
+ DatabaseEnvironment env;
+ DatabaseEnvironmentConfig envConfig;
+ DatabaseEntry key, data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ Transaction txn;
+
+ testName = "TestDuplicateToDifferentPos";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ envConfig = new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ envConfig.NoMMap = false;
+ env = DatabaseEnvironment.Open(testHome, envConfig);
+
+ txn = env.BeginTransaction();
+ dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ db = BTreeDatabase.Open(testName + ".db", dbConfig, txn);
+ key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key"));
+ data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data"));
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
+ db.Put(key, data, txn);
+ txn.Commit();
+
+ txn = env.BeginTransaction();
+ cursor = db.Cursor(txn);
+ cursor.Move(key, true);
+
+ //Duplicate a new cursor to the same position.
+ dupCursor = cursor.Duplicate(false);
+
+ /*
+ * The duplicate cursor points to nothing so overwriting the
+ * record is not allowed.
+ */
+ try
+ {
+ dupCursor.Overwrite(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("newdata")));
+ }
+ catch (DatabaseException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ dupCursor.Close();
+ cursor.Close();
+ txn.Commit();
+ db.Close();
+ env.Close();
+ }
+ }
+
+ [Test]
+ public void TestInsertAfter()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ DatabaseEntry data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+
+ testName = "TestInsertAfter";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Add record("key", "data") into database.
+ CursorTest.GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+ CursorTest.AddOneByCursor(db, cursor);
+
+ // Insert the new record("key","data1") after the record("key", "data").
+ data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data1"));
+ cursor.Insert(data, Cursor.InsertLocation.AFTER);
+
+ /*
+ * Move the cursor to the record("key", "data") and confirm that
+ * the next record is the one just inserted.
+ */
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
+ Assert.IsTrue(cursor.Move(pair, true));
+ Assert.IsTrue(cursor.MoveNext());
+ Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("key"), cursor.Current.Key.Data);
+ Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("data1"), cursor.Current.Value.Data);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveFirstMultipleAndMultipleKey()
+ {
+ testName = "TestMoveFirstMultipleAndMultipleKey";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> pair;
+ MultipleKeyDatabaseEntry multiPair;
+ int cnt;
+ int[] size = new int[2];
+ size[0] = 0;
+ size[1] = 1024;
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.ALWAYS;
+ dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ dbConfig.PageSize = 1024;
+ GetMultipleDB(btreeDBFileName, dbConfig, out db, out cursor);
+
+ for (int i = 0; i < 2; i++) {
+ cnt = 0;
+ if (size[i] == 0)
+ cursor.MoveFirstMultiple();
+ else
+ cursor.MoveFirstMultiple(size[i]);
+ pair = cursor.CurrentMultiple;
+ foreach (DatabaseEntry dbt in pair.Value)
+ cnt++;
+ Assert.AreEqual(1, cnt);
+ }
+
+ for (int i = 0; i < 2; i++) {
+ cnt = 0;
+ if (size[i] == 0)
+ cursor.MoveFirstMultipleKey();
+ else
+ cursor.MoveFirstMultipleKey(size[i]);
+ multiPair = cursor.CurrentMultipleKey;
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
+ dbt in multiPair)
+ cnt++;
+ Assert.Less(1, cnt);
+ }
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveMultiple()
+ {
+ testName = "TestMoveMultiple";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ DatabaseEntry key;
+ KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> pair;
+ int cnt;
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.ALWAYS;
+ dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ dbConfig.PageSize = 1024;
+ GetMultipleDB(btreeDBFileName, dbConfig, out db, out cursor);
+
+ // Move cursor to pairs with exact 99 as its key.
+ cnt = 0;
+ key = new DatabaseEntry(BitConverter.GetBytes((int)99));
+ cursor.MoveMultiple(key, true);
+ pair = cursor.CurrentMultiple;
+ Assert.AreEqual(99, BitConverter.ToInt32(pair.Key.Data, 0));
+ foreach (DatabaseEntry dbt in pair.Value)
+ cnt++;
+ Assert.AreEqual(2, cnt);
+
+ // Move cursor to pairs with the smallest key larger than 100.
+ cnt = 0;
+ key = new DatabaseEntry(BitConverter.GetBytes((int)100));
+ cursor.MoveMultiple(key, false);
+ pair = cursor.CurrentMultiple;
+ Assert.AreEqual(101, BitConverter.ToInt32(pair.Key.Data, 0));
+ foreach (DatabaseEntry dbt in pair.Value)
+ cnt++;
+ Assert.AreEqual(1, cnt);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveMultipleKey()
+ {
+ testName = "TestMoveMultipleKey";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ DatabaseEntry key;
+ MultipleKeyDatabaseEntry mulPair; ;
+ int cnt;
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.ALWAYS;
+ dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ dbConfig.PageSize = 1024;
+ GetMultipleDB(btreeDBFileName, dbConfig, out db, out cursor);
+
+ /*
+ * Bulk retrieve key/value pair from the pair whose key
+ * is exact 99.
+ */
+ cnt = 0;
+ key = new DatabaseEntry(BitConverter.GetBytes((int)99));
+ cursor.MoveMultipleKey(key, true);
+ mulPair = cursor.CurrentMultipleKey;
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
+ pair in mulPair) {
+ Assert.GreaterOrEqual(3,
+ BitConverter.ToInt32(pair.Key.Data, 0) - 98);
+ cnt++;
+ }
+ Assert.AreEqual(3, cnt);
+
+ /*
+ * Bulk retrieve key/value pair from the pair whose key
+ * is the smallest one larger than 100.
+ */
+ cnt = 0;
+ key = new DatabaseEntry(BitConverter.GetBytes((int)100));
+ cursor.MoveMultipleKey(key, false);
+ mulPair = cursor.CurrentMultipleKey;
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
+ pair in mulPair) {
+ Assert.AreEqual(101,
+ BitConverter.ToInt32(pair.Key.Data, 0));
+ cnt++;
+ }
+ Assert.LessOrEqual(1, cnt);
+
+ cnt = 0;
+ key = new DatabaseEntry(BitConverter.GetBytes((int)100));
+ cursor.MoveMultipleKey(key, false, 1024);
+ mulPair = cursor.CurrentMultipleKey;
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
+ pair in mulPair) {
+ Assert.AreEqual(101,
+ BitConverter.ToInt32(pair.Key.Data, 0));
+ Assert.AreEqual(101,
+ BitConverter.ToInt32(pair.Value.Data, 0));
+ cnt++;
+ }
+ Assert.LessOrEqual(1, cnt);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveMultipleKeyWithRecno()
+ {
+ testName = "TestMoveMultipleKeyWithRecno";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ MultipleKeyDatabaseEntry multiDBT;
+ int cnt;
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.UseRecordNumbers = true;
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.PageSize = 1024;
+ GetMultipleDB(btreeDBFileName, dbConfig, out db, out cursor);
+
+ cnt = 0;
+ cursor.MoveMultipleKey(98);
+ multiDBT = cursor.CurrentMultipleKey;
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
+ pair in multiDBT)
+ cnt++;
+ Assert.AreEqual(3, cnt);
+
+ cnt = 0;
+ cursor.MoveMultipleKey(98, 1024);
+ multiDBT = cursor.CurrentMultipleKey;
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
+ pair in multiDBT)
+ cnt++;
+ Assert.AreEqual(3, cnt);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveMultiplePairs()
+ {
+ testName = "TestMoveMultiplePairs";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ DatabaseEntry key, data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ MultipleKeyDatabaseEntry multiKeyDBTs1, multiKeyDBTs2;
+ int cnt;
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.ALWAYS;
+ dbConfig.Duplicates = DuplicatesPolicy.SORTED;
+ dbConfig.PageSize = 1024;
+ GetMultipleDB(btreeDBFileName, dbConfig, out db, out cursor);
+
+ /*
+ * Bulk retrieve pairs from the pair whose key/data
+ * is exact 99/99.
+ */
+ cnt = 0;
+ key = new DatabaseEntry(BitConverter.GetBytes((int)99));
+ data = new DatabaseEntry(BitConverter.GetBytes((int)99));
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
+ cursor.MoveMultipleKey(pair, true);
+ multiKeyDBTs1 = cursor.CurrentMultipleKey;
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
+ p in multiKeyDBTs1)
+ cnt++;
+ Assert.AreEqual(3, cnt);
+
+ // Bulk retrieve pairs from the pair whose key is exact 99.
+ cnt = 0;
+ key = new DatabaseEntry(BitConverter.GetBytes((int)99));
+ data = new DatabaseEntry(BitConverter.GetBytes((int)98));
+ cursor.MoveMultipleKey(pair, true);
+ multiKeyDBTs2 = cursor.CurrentMultipleKey;
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
+ dbts in multiKeyDBTs2)
+ cnt++;
+ Assert.AreEqual(3, cnt);
+
+ /*
+ * Bulk retrieve pairs from the pair whose key is
+ * exact 99 in buffer size of 1024k.
+ */
+ cnt = 0;
+ key = new DatabaseEntry(BitConverter.GetBytes((int)99));
+ data = new DatabaseEntry(BitConverter.GetBytes((int)102));
+ cursor.MoveMultipleKey(pair, true, 1024);
+ multiKeyDBTs2 = cursor.CurrentMultipleKey;
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
+ dbts in multiKeyDBTs2)
+ cnt++;
+ Assert.AreEqual(3, cnt);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveMultiplePairWithKey()
+ {
+ testName = "TestMoveMultiplePairWithKey";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ DatabaseEntry key, data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> mulPair;
+ int cnt;
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.ALWAYS;
+ dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ dbConfig.PageSize = 1024;
+ GetMultipleDB(btreeDBFileName, dbConfig, out db, out cursor);
+
+ /*
+ * Move the cursor to pairs with exact 99 as its key
+ * and 99 as its data.
+ */
+ cnt = 0;
+ key = new DatabaseEntry(BitConverter.GetBytes((int)99));
+ data = new DatabaseEntry(BitConverter.GetBytes((int)99));
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
+ cursor.MoveMultiple(pair, true);
+ mulPair = cursor.CurrentMultiple;
+ Assert.AreEqual(99, BitConverter.ToInt32(mulPair.Key.Data, 0));
+ foreach (DatabaseEntry dbt in mulPair.Value) {
+ Assert.AreEqual(99, BitConverter.ToInt32(dbt.Data, 0));
+ cnt++;
+ }
+ Assert.AreEqual(1, cnt);
+
+ // Move cursor to pairs with the smallest key larger than 100.
+ cnt = 0;
+ key = new DatabaseEntry(BitConverter.GetBytes((int)100));
+ data = new DatabaseEntry(BitConverter.GetBytes((int)100));
+ cursor.MoveMultiple(pair, false);
+ mulPair = cursor.CurrentMultiple;
+ Assert.AreEqual(99, BitConverter.ToInt32(mulPair.Key.Data, 0));
+ foreach (DatabaseEntry dbt in mulPair.Value) {
+ Assert.GreaterOrEqual(1,
+ BitConverter.ToInt32(dbt.Data, 0) - 99);
+ cnt++;
+ }
+ Assert.AreEqual(1, cnt);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveMultipleWithRecno()
+ {
+ testName = "TestMoveMultipleWithRecno";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> pair;
+ int cnt;
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.ALWAYS;
+ dbConfig.PageSize = 1024;
+ dbConfig.UseRecordNumbers = true;
+ GetMultipleDB(btreeDBFileName, dbConfig, out db, out cursor);
+
+ // Move cursor to the No.100 record.
+ cnt = 0;
+ cursor.MoveMultiple(100);
+ pair = cursor.CurrentMultiple;
+ Assert.AreEqual(100, BitConverter.ToInt32(pair.Key.Data, 0));
+ foreach (DatabaseEntry dbt in pair.Value)
+ cnt++;
+ Assert.AreEqual(1, cnt);
+
+ // Move cursor to the No.100 record with buffer size of 1024k.
+ cnt = 0;
+ cursor.MoveMultiple(100, 1024);
+ pair = cursor.CurrentMultiple;
+ Assert.AreEqual(100, BitConverter.ToInt32(pair.Key.Data, 0));
+ foreach (DatabaseEntry dbt in pair.Value)
+ cnt++;
+ Assert.AreEqual(1, cnt);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveNextDuplicateMultipleAndMultipleKey()
+ {
+ testName = "TestMoveNextDuplicateMultipleAndMultipleKey";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ DatabaseEntry key, data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> pairs;
+ MultipleKeyDatabaseEntry multiPair;
+ int cnt;
+ int[] size = new int[2];
+ size[0] = 0;
+ size[1] = 1024;
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.ALWAYS;
+ dbConfig.Duplicates = DuplicatesPolicy.SORTED;
+ dbConfig.PageSize = 1024;
+ GetMultipleDB(btreeDBFileName, dbConfig, out db, out cursor);
+
+ key = new DatabaseEntry(BitConverter.GetBytes(99));
+ data = new DatabaseEntry(BitConverter.GetBytes(99));
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
+
+ for (int j = 0; j < 2; j++) {
+ for (int i = 0; i < 2; i++) {
+ cnt = 0;
+ cursor.Move(pair, true);
+ if (j == 0) {
+ if (size[i] == 0)
+ Assert.IsTrue(cursor.MoveNextDuplicateMultiple());
+ else
+ Assert.IsTrue(cursor.MoveNextDuplicateMultiple(size[i]));
+ pairs = cursor.CurrentMultiple;
+ foreach (DatabaseEntry dbt in pairs.Value) {
+ Assert.AreEqual(100, BitConverter.ToInt32(dbt.Data, 0));
+ cnt++;
+ }
+ Assert.AreEqual(1, cnt);
+ } else {
+ if (size[i] == 0)
+ Assert.IsTrue(cursor.MoveNextDuplicateMultipleKey());
+ else
+ Assert.IsTrue(cursor.MoveNextDuplicateMultipleKey(size[i]));
+ multiPair = cursor.CurrentMultipleKey;
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> p in multiPair) {
+ Assert.AreEqual(100, BitConverter.ToInt32(p.Value.Data, 0));
+ cnt++;
+ }
+ Assert.AreEqual(1, cnt);
+ }
+ }
+ }
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveNextUniqueMultipleAndMultipleKey()
+ {
+ testName = "TestMoveNextUniqueMultipleAndMultipleKey";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ DatabaseEntry key, data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> pairs;
+ MultipleKeyDatabaseEntry multiPair;
+ int cnt;
+ int[] size = new int[2];
+ size[0] = 0;
+ size[1] = 1024;
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.ALWAYS;
+ dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ dbConfig.PageSize = 1024;
+ GetMultipleDB(btreeDBFileName, dbConfig, out db, out cursor);
+
+ key = new DatabaseEntry(BitConverter.GetBytes(99));
+ data = new DatabaseEntry(BitConverter.GetBytes(99));
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
+
+ for (int j = 0; j < 2; j++) {
+ for (int i = 0; i < 2; i++) {
+ cnt = 0;
+ cursor.Move(pair, true);
+ if (j == 0) {
+ if (size[i] == 0)
+ Assert.IsTrue(cursor.MoveNextUniqueMultiple());
+ else
+ Assert.IsTrue(cursor.MoveNextUniqueMultiple(size[i]));
+ pairs = cursor.CurrentMultiple;
+ foreach (DatabaseEntry dbt in pairs.Value) {
+ Assert.AreEqual(101, BitConverter.ToInt32(dbt.Data, 0));
+ cnt++;
+ }
+ Assert.AreEqual(1, cnt);
+ } else {
+ if (size[i] == 0)
+ Assert.IsTrue(cursor.MoveNextUniqueMultipleKey());
+ else
+ Assert.IsTrue(cursor.MoveNextUniqueMultipleKey(size[i]));
+ multiPair = cursor.CurrentMultipleKey;
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> p in multiPair) {
+ Assert.AreEqual(101, BitConverter.ToInt32(p.Value.Data, 0));
+ cnt++;
+ }
+ Assert.AreEqual(1, cnt);
+ }
+ }
+ }
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestRefreshMultipleAndMultipleKey()
+ {
+ testName = "TestRefreshMultipleAndMultipleKey";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ DatabaseEntry key, data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> pairs;
+ MultipleKeyDatabaseEntry multiPair;
+ int cnt;
+ int[] size = new int[2];
+ size[0] = 0;
+ size[1] = 1024;
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.ALWAYS;
+ dbConfig.Duplicates = DuplicatesPolicy.SORTED;
+ dbConfig.PageSize = 1024;
+ GetMultipleDB(btreeDBFileName, dbConfig, out db, out cursor);
+
+ key = new DatabaseEntry(BitConverter.GetBytes(99));
+ data = new DatabaseEntry(BitConverter.GetBytes(99));
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
+
+ for (int j = 0; j < 2; j++) {
+ for (int i = 0; i < 2; i++) {
+ cnt = 0;
+ cursor.Move(pair, true);
+ if (j == 0) {
+ if (size[i] == 0)
+ Assert.IsTrue(cursor.RefreshMultiple());
+ else
+ Assert.IsTrue(cursor.RefreshMultiple(size[i]));
+ pairs = cursor.CurrentMultiple;
+ foreach (DatabaseEntry dbt in pairs.Value)
+ cnt++;
+ Assert.AreEqual(2, cnt);
+ } else {
+ if (size[i] == 0)
+ Assert.IsTrue(cursor.RefreshMultipleKey());
+ else
+ Assert.IsTrue(cursor.RefreshMultipleKey(size[i]));
+ multiPair = cursor.CurrentMultipleKey;
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> p in multiPair)
+ cnt++;
+ Assert.AreEqual(3, cnt);
+ }
+ }
+ }
+
+ cursor.Close();
+ db.Close();
+ }
+
+ private void GetMultipleDB(string dbFileName, BTreeDatabaseConfig dbConfig,
+ out BTreeDatabase db, out BTreeCursor cursor)
+ {
+ db = BTreeDatabase.Open(dbFileName, dbConfig);
+ cursor = db.Cursor();
+
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ DatabaseEntry key, data;
+ for (int i = 1; i < 100; i++) {
+ key = new DatabaseEntry(BitConverter.GetBytes(i));
+ data = new DatabaseEntry(BitConverter.GetBytes(i));
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
+ cursor.Add(pair);
+ }
+
+ if (dbConfig.UseRecordNumbers == true) {
+ byte[] bytes = new byte[512];
+ for (int i = 0; i < 512; i++)
+ bytes[i] = (byte)i;
+ key = new DatabaseEntry(BitConverter.GetBytes(100));
+ data = new DatabaseEntry(bytes);
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
+ cursor.Add(pair);
+ } else {
+ if (dbConfig.Duplicates == DuplicatesPolicy.UNSORTED ||
+ dbConfig.Duplicates == DuplicatesPolicy.SORTED) {
+ key = new DatabaseEntry(BitConverter.GetBytes(99));
+ data = new DatabaseEntry(BitConverter.GetBytes(100));
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
+ cursor.Add(pair);
+ }
+
+ key = new DatabaseEntry(BitConverter.GetBytes(101));
+ data = new DatabaseEntry(BitConverter.GetBytes(101));
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
+ cursor.Add(pair);
+ }
+ }
+
+ [Test]
+ public void TestInsertBefore()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ DatabaseEntry data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+
+ testName = "TestInsertBefore";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Add record("key", "data") into database.
+ CursorTest.GetCursorInBtreeDBWithoutEnv(
+ testHome, testName, out db, out cursor);
+ CursorTest.AddOneByCursor(db, cursor);
+
+ // Insert the new record("key","data1") before the record("key", "data").
+ data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data1"));
+ cursor.Insert(data, Cursor.InsertLocation.BEFORE);
+
+ /*
+ * Move the cursor to the record("key", "data") and confirm
+ * that the previous record is the one just inserted.
+ */
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
+ Assert.IsTrue(cursor.Move(pair, true));
+ Assert.IsTrue(cursor.MovePrev());
+ Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("key"),cursor.Current.Key.Data);
+ Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("data1"), cursor.Current.Value.Data);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveToRecno()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestMoveToRecno";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ GetCursorInBtreeDBUsingRecno(testHome, testName,
+ out db, out cursor);
+ for (int i = 0; i < 10; i++)
+ db.Put(
+ new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+
+ MoveCursorToRecno(cursor, null);
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveToRecnoWithRMW()
+ {
+ testName = "TestMoveToRecnoWithRMW";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ btCursorFunc = new BTCursorMoveFuncDelegate(
+ MoveCursorToRecno);
+
+ // Move to a specified key and a key/data pair.
+ MoveWithRMW(testHome, testName);
+ }
+
+ [Test]
+ public void TestRecno()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestRecno";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ GetCursorInBtreeDBUsingRecno(testHome, testName,
+ out db, out cursor);
+ for (int i = 0; i < 10; i++)
+ db.Put(
+ new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+
+ ReturnRecno(cursor, null);
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestRecnoWithRMW()
+ {
+ testName = "TestRecnoWithRMW";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ // Use MoveCursorToRecno() as its move function.
+ btCursorFunc = new BTCursorMoveFuncDelegate(
+ ReturnRecno);
+
+ // Move to a specified key and a key/data pair.
+ MoveWithRMW(testHome, testName);
+ }
+
+ /*
+ * Move the cursor according to recno. The recno
+ * starts from 1 and is increased by 1.
+ */
+ public void MoveCursorToRecno(BTreeCursor cursor,
+ LockingInfo lck)
+ {
+ for (uint i = 1; i <= 5; i++)
+ if (lck == null)
+ Assert.IsTrue(cursor.Move(i));
+ else
+ Assert.IsTrue(cursor.Move(i, lck));
+ }
+
+ /*l
+ * Move the cursor according to a given recno and
+ * return the current record's recno. The given recno
+ * and the one got from the cursor should be the same.
+ */
+ public void ReturnRecno(BTreeCursor cursor,
+ LockingInfo lck)
+ {
+ for (uint i = 1; i <= 5; i++)
+ if (lck == null)
+ {
+ if (cursor.Move(i) == true)
+ Assert.AreEqual(i, cursor.Recno());
+ }
+ else
+ {
+ if (cursor.Move(i, lck) == true)
+ Assert.AreEqual(i, cursor.Recno(lck));
+ }
+ }
+
+ public void GetCursorInBtreeDBUsingRecno(string home,
+ string name, out BTreeDatabase db,
+ out BTreeCursor cursor)
+ {
+ string dbFileName = home + "/" + name + ".db";
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.UseRecordNumbers = true;
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ db = BTreeDatabase.Open(dbFileName, dbConfig);
+ cursor = db.Cursor();
+ }
+
+ public void RdMfWt()
+ {
+ Transaction txn = paramEnv.BeginTransaction();
+ BTreeCursor dbc = paramDB.Cursor(txn);
+
+ try
+ {
+ LockingInfo lck = new LockingInfo();
+ lck.ReadModifyWrite = true;
+
+ // Read record.
+ btCursorFunc(dbc, lck);
+
+ // Block the current thread until event is set.
+ signal.WaitOne();
+
+ // Write new records into database.
+ DatabaseEntry key = new DatabaseEntry(BitConverter.GetBytes(55));
+ DatabaseEntry data = new DatabaseEntry(BitConverter.GetBytes(55));
+ dbc.Add(new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data));
+
+ dbc.Close();
+ txn.Commit();
+ }
+ catch (DeadlockException)
+ {
+ dbc.Close();
+ txn.Abort();
+ }
+ }
+
+
+ public void MoveWithRMW(string home, string name)
+ {
+ paramEnv = null;
+ paramDB = null;
+
+ // Open the environment.
+ DatabaseEnvironmentConfig envCfg =
+ new DatabaseEnvironmentConfig();
+ envCfg.Create = true;
+ envCfg.FreeThreaded = true;
+ envCfg.UseLocking = true;
+ envCfg.UseLogging = true;
+ envCfg.UseMPool = true;
+ envCfg.UseTxns = true;
+ paramEnv = DatabaseEnvironment.Open(home, envCfg);
+
+ // Open database in transaction.
+ Transaction openTxn = paramEnv.BeginTransaction();
+ BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
+ cfg.Creation = CreatePolicy.ALWAYS;
+ cfg.Env = paramEnv;
+ cfg.FreeThreaded = true;
+ cfg.PageSize = 4096;
+ // Use record number.
+ cfg.UseRecordNumbers = true;
+ paramDB = BTreeDatabase.Open(name + ".db", cfg, openTxn);
+ openTxn.Commit();
+
+ /*
+ * Put 10 different, 2 duplicate and another different
+ * records into database.
+ */
+ Transaction txn = paramEnv.BeginTransaction();
+ for (int i = 0; i < 13; i++)
+ {
+ DatabaseEntry key, data;
+ if (i == 10 || i == 11)
+ {
+ key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key"));
+ data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data"));
+ }
+ else
+ {
+ key = new DatabaseEntry(BitConverter.GetBytes(i));
+ data = new DatabaseEntry(BitConverter.GetBytes(i));
+ }
+ paramDB.Put(key, data, txn);
+ }
+
+ txn.Commit();
+
+ // Get a event wait handle.
+ signal = new EventWaitHandle(false,
+ EventResetMode.ManualReset);
+
+ /*
+ * Start RdMfWt() in two threads. RdMfWt() reads
+ * and writes data into database.
+ */
+ Thread t1 = new Thread(new ThreadStart(RdMfWt));
+ Thread t2 = new Thread(new ThreadStart(RdMfWt));
+ t1.Start();
+ t2.Start();
+
+ // Give both threads time to read before signalling them to write.
+ Thread.Sleep(1000);
+
+ // Invoke the write operation in both threads.
+ signal.Set();
+
+ // Return the number of deadlocks.
+ while (t1.IsAlive || t2.IsAlive)
+ {
+ /*
+ * Give both threads time to write before
+ * counting the number of deadlocks.
+ */
+ Thread.Sleep(1000);
+ uint deadlocks = paramEnv.DetectDeadlocks(DeadlockPolicy.DEFAULT);
+
+ // Confirm that there won't be any deadlock.
+ Assert.AreEqual(0, deadlocks);
+ }
+
+ t1.Join();
+ t2.Join();
+ paramDB.Close();
+ paramEnv.Close();
+ }
+
+ }
+}
+
+
diff --git a/test/scr037/BTreeDatabaseConfigTest.cs b/test/scr037/BTreeDatabaseConfigTest.cs
new file mode 100644
index 0000000..69170dd
--- /dev/null
+++ b/test/scr037/BTreeDatabaseConfigTest.cs
@@ -0,0 +1,92 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class BTreeDatabaseConfigTest : DatabaseConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "BTreeDatabaseConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ override public void TestConfigWithoutEnv()
+ {
+ testName = "TestConfigWithoutEnv";
+
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ BTreeDatabaseConfig btreeConfig =
+ new BTreeDatabaseConfig();
+ Config(xmlElem, ref btreeConfig, true);
+ Confirm(xmlElem, btreeConfig, true);
+ }
+
+ public static void Confirm(XmlElement
+ xmlElement, BTreeDatabaseConfig btreeDBConfig,
+ bool compulsory)
+ {
+ DatabaseConfig dbConfig = btreeDBConfig;
+ Confirm(xmlElement, dbConfig, compulsory);
+
+ // Confirm Btree database specific configuration
+ Configuration.ConfirmDuplicatesPolicy(xmlElement,
+ "Duplicates", btreeDBConfig.Duplicates, compulsory);
+ Configuration.ConfirmBool(xmlElement,
+ "NoReverseSplitting",
+ btreeDBConfig.NoReverseSplitting, compulsory);
+ Configuration.ConfirmBool(xmlElement,
+ "UseRecordNumbers", btreeDBConfig.UseRecordNumbers,
+ compulsory);
+ Configuration.ConfirmCreatePolicy(xmlElement,
+ "Creation", btreeDBConfig.Creation, compulsory);
+ Configuration.ConfirmUint(xmlElement, "MinKeysPerPage",
+ btreeDBConfig.MinKeysPerPage, compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref BTreeDatabaseConfig btreeDBConfig, bool compulsory)
+ {
+ uint minKeysPerPage = new uint();
+ DatabaseConfig dbConfig = btreeDBConfig;
+ Config(xmlElement, ref dbConfig, compulsory);
+
+ // Configure specific fields/properties of Btree db
+ Configuration.ConfigDuplicatesPolicy(xmlElement,
+ "Duplicates", ref btreeDBConfig.Duplicates,
+ compulsory);
+ Configuration.ConfigBool(xmlElement,
+ "NoReverseSplitting",
+ ref btreeDBConfig.NoReverseSplitting, compulsory);
+ Configuration.ConfigBool(xmlElement,
+ "UseRecordNumbers",
+ ref btreeDBConfig.UseRecordNumbers, compulsory);
+ Configuration.ConfigCreatePolicy(xmlElement,
+ "Creation", ref btreeDBConfig.Creation, compulsory);
+ if (Configuration.ConfigUint(xmlElement,
+ "MinKeysPerPage", ref minKeysPerPage, compulsory))
+ btreeDBConfig.MinKeysPerPage = minKeysPerPage;
+ }
+ }
+}
diff --git a/test/scr037/BTreeDatabaseTest.cs b/test/scr037/BTreeDatabaseTest.cs
new file mode 100644
index 0000000..2643f41
--- /dev/null
+++ b/test/scr037/BTreeDatabaseTest.cs
@@ -0,0 +1,2309 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class BTreeDatabaseTest : DatabaseTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "BTreeDatabaseTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestCompactWithoutTxn()
+ {
+ int i, nRecs;
+ nRecs = 10000;
+ testName = "TestCompactWithoutTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ // The minimum page size
+ btreeDBConfig.PageSize = 512;
+ btreeDBConfig.BTreeCompare =
+ new EntryComparisonDelegate(dbIntCompare);
+ using (BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBConfig))
+ {
+ DatabaseEntry key;
+ DatabaseEntry data;
+
+ // Fill the database with entries from 0 to 9999
+ for (i = 0; i < nRecs; i++)
+ {
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ btreeDB.Put(key, data);
+ }
+
+ /*
+ * Delete entries below 500, between 3000 and
+ * 5000 and above 7000
+ */
+ for (i = 0; i < nRecs; i++)
+ if (i < 500 || i > 7000 ||
+ (i < 5000 && i > 3000))
+ {
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ btreeDB.Delete(key);
+ }
+
+ btreeDB.Sync();
+ long fileSize = new FileInfo(
+ btreeDBFileName).Length;
+
+ // Compact database
+ CompactConfig cCfg = new CompactConfig();
+ cCfg.FillPercentage = 30;
+ cCfg.Pages = 10;
+ cCfg.Timeout = 1000;
+ cCfg.TruncatePages = true;
+ cCfg.start = new DatabaseEntry(
+ BitConverter.GetBytes(1));
+ cCfg.stop = new DatabaseEntry(
+ BitConverter.GetBytes(7000));
+ CompactData compactData = btreeDB.Compact(cCfg);
+ Assert.IsFalse((compactData.Deadlocks == 0) &&
+ (compactData.Levels == 0) &&
+ (compactData.PagesExamined == 0) &&
+ (compactData.PagesFreed == 0) &&
+ (compactData.PagesTruncated == 0));
+
+ btreeDB.Sync();
+ long compactedFileSize =
+ new FileInfo(btreeDBFileName).Length;
+ Assert.Less(compactedFileSize, fileSize);
+ }
+ }
+
+ [Test]
+ public void TestCompression() {
+ testName = "TestCompression";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
+ cfg.Creation = CreatePolicy.ALWAYS;
+ cfg.SetCompression(compress, decompress);
+ BTreeDatabase db = BTreeDatabase.Open(btreeDBName, cfg);
+ DatabaseEntry key, data;
+ char[] keyData = { 'A', 'A', 'A', 'A' };
+ byte[] dataData = new byte[20];
+ Random generator = new Random();
+ int i;
+ for (i = 0; i < 20000; i++) {
+ // Write random data
+ key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes(keyData));
+ generator.NextBytes(dataData);
+ data = new DatabaseEntry(dataData);
+ db.Put(key, data);
+
+ // Bump the key. Rollover from Z to A if necessary
+ int j = keyData.Length;
+ do {
+ j--;
+ if (keyData[j]++ == 'Z')
+ keyData[j] = 'A';
+ } while (keyData[j] == 'A');
+ }
+ db.Close();
+ }
+
+ bool compress(DatabaseEntry prevKey, DatabaseEntry prevData,
+ DatabaseEntry key, DatabaseEntry data, ref byte[] dest, out int size) {
+ /*
+ * Just a dummy function that doesn't do any compression. It just
+ * writes the 5 byte key and 20 byte data to the buffer.
+ */
+ size = key.Data.Length + data.Data.Length;
+ if (size > dest.Length)
+ return false;
+ key.Data.CopyTo(dest, 0);
+ data.Data.CopyTo(dest, key.Data.Length);
+ return true;
+ }
+
+ KeyValuePair<DatabaseEntry, DatabaseEntry> decompress(
+ DatabaseEntry prevKey, DatabaseEntry prevData, byte[] compressed, out uint bytesRead) {
+ byte[] keyData = new byte[4];
+ byte[] dataData = new byte[20];
+ Array.ConstrainedCopy(compressed, 0, keyData, 0, 4);
+ Array.ConstrainedCopy(compressed, 4, dataData, 0, 20);
+ DatabaseEntry key = new DatabaseEntry(keyData);
+ DatabaseEntry data = new DatabaseEntry(dataData);
+ bytesRead = (uint)(key.Data.Length + data.Data.Length);
+ return new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
+ }
+
+ [Test]
+ public void TestCompressionDefault() {
+ testName = "TestCompressionDefault";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
+ cfg.Creation = CreatePolicy.ALWAYS;
+ BTreeDatabase db = BTreeDatabase.Open(btreeDBName, cfg);
+ DatabaseEntry key, data;
+ char[] keyData = { 'A', 'A', 'A', 'A' };
+ byte[] dataData = new byte[20];
+ Random generator = new Random();
+ int i;
+ for (i = 0; i < 20000; i++) {
+ // Write random data
+ key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes(keyData));
+ generator.NextBytes(dataData);
+ data = new DatabaseEntry(dataData);
+ db.Put(key, data);
+
+ // Bump the key. Rollover from Z to A if necessary
+ int j = keyData.Length;
+ do {
+ j--;
+ if (keyData[j]++ == 'Z')
+ keyData[j] = 'A';
+ } while (keyData[j] == 'A');
+ }
+ db.Close();
+
+ FileInfo dbInfo = new FileInfo(btreeDBName);
+ long uncompressedSize = dbInfo.Length;
+ Configuration.ClearDir(testHome);
+
+ cfg = new BTreeDatabaseConfig();
+ cfg.Creation = CreatePolicy.ALWAYS;
+ cfg.SetCompression();
+ db = BTreeDatabase.Open(btreeDBName, cfg);
+ keyData = new char[]{ 'A', 'A', 'A', 'A' };
+ for (i = 0; i < 20000; i++) {
+ // Write random data
+ key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes(keyData));
+ generator.NextBytes(dataData);
+ data = new DatabaseEntry(dataData);
+ db.Put(key, data);
+
+ // Bump the key. Rollover from Z to A if necessary
+ int j = keyData.Length;
+ do {
+ j--;
+ if (keyData[j]++ == 'Z')
+ keyData[j] = 'A';
+ } while (keyData[j] == 'A');
+ }
+ Cursor dbc = db.Cursor();
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> kvp in dbc)
+ i--;
+ dbc.Close();
+ Assert.AreEqual(i, 0);
+ db.Close();
+
+ dbInfo = new FileInfo(btreeDBName);
+ Assert.Less(dbInfo.Length, uncompressedSize);
+ Console.WriteLine("Uncompressed: {0}", uncompressedSize);
+ Console.WriteLine("Compressed: {0}", dbInfo.Length);
+
+ Configuration.ClearDir(testHome);
+
+ cfg = new BTreeDatabaseConfig();
+ cfg.Creation = CreatePolicy.ALWAYS;
+ cfg.SetCompression();
+ db = BTreeDatabase.Open(btreeDBName, cfg);
+ for (i = 1023; i < 1124; i++){
+ key = new DatabaseEntry(BitConverter.GetBytes(i));
+ data = new DatabaseEntry(BitConverter.GetBytes(i + 3));
+ db.Put(key, data);
+ }
+ dbc = db.Cursor();
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> kvp in dbc){
+ int keyInt = BitConverter.ToInt32(kvp.Key.Data, 0);
+ int dataInt = BitConverter.ToInt32(kvp.Value.Data, 0);
+ Assert.AreEqual(3, dataInt - keyInt);
+ }
+ dbc.Close();
+
+ db.Close();
+ }
+
+ [Test, ExpectedException(typeof(AccessViolationException))]
+ public void TestClose()
+ {
+ testName = "TestClose";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBConfig);
+ btreeDB.Close();
+ DatabaseEntry key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("hi"));
+ DatabaseEntry data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("hi"));
+ btreeDB.Put(key, data);
+ }
+
+ [Test]
+ public void TestCloseWithoutSync()
+ {
+ testName = "TestCloseWithoutSync";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBName = testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.ForceFlush = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ envConfig.UseLogging = true;
+ envConfig.LogSystemCfg = new LogConfig();
+ envConfig.LogSystemCfg.ForceSync = false;
+ envConfig.LogSystemCfg.AutoRemove = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ TransactionConfig txnConfig = new TransactionConfig();
+ txnConfig.SyncAction =
+ TransactionConfig.LogFlush.WRITE_NOSYNC;
+ Transaction txn = env.BeginTransaction(txnConfig);
+
+ BTreeDatabaseConfig btreeConfig =
+ new BTreeDatabaseConfig();
+ btreeConfig.Creation = CreatePolicy.ALWAYS;
+ btreeConfig.Env = env;
+
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBName, btreeConfig, txn);
+
+ DatabaseEntry key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ DatabaseEntry data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ Assert.IsFalse(btreeDB.Exists(key, txn));
+ btreeDB.Put(key, data, txn);
+ btreeDB.Close(false);
+ txn.Commit();
+ env.Close();
+
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.NEVER;
+ using (BTreeDatabase db = BTreeDatabase.Open(
+ testHome + "/" + btreeDBName, dbConfig))
+ {
+ Assert.IsFalse(db.Exists(key));
+ }
+ }
+
+ [Test]
+ public void TestCursorWithoutEnv()
+ {
+ BTreeCursor cursor;
+ BTreeDatabase db;
+ string dbFileName;
+
+ testName = "TestCursorWithoutEnv";
+ testHome = testFixtureHome + "/" + testName;
+ dbFileName = testHome + "/" + testName + ".db";
+
+ // Open btree database.
+ Configuration.ClearDir(testHome);
+ OpenBtreeDB(null, null, dbFileName, out db);
+
+ // Get a cursor.
+ cursor = db.Cursor();
+
+ /*
+ * Add a record to the database with cursor and
+ * confirm that the record exists in the database.
+ */
+ CursorTest.AddOneByCursor(db, cursor);
+
+ // Close cursor and database.
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestCursorWithConfigInTxn()
+ {
+ BTreeCursor cursor;
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ Transaction txn;
+ string dbFileName;
+
+ testName = "TestCursorWithConfigInTxn";
+ testHome = testFixtureHome + "/" + testName;
+ dbFileName = testName + ".db";
+
+ // Open environment and begin a transaction.
+ Configuration.ClearDir(testHome);
+
+ SetUpEnvAndTxn(testHome, out env, out txn);
+ OpenBtreeDB(env, txn, dbFileName, out db);
+
+ // Config and get a cursor.
+ cursor = db.Cursor(new CursorConfig(), txn);
+
+ /*
+ * Add a record to the database with cursor and
+ * confirm that the record exists in the database.
+ */
+ CursorTest.AddOneByCursor(db, cursor);
+
+ /*
+ * Close cursor, database, commit the transaction
+ * and close the environment.
+ */
+ cursor.Close();
+ db.Close();
+ txn.Commit();
+ env.Close();
+ }
+
+ [Test]
+ public void TestCursorWithoutConfigInTxn()
+ {
+ BTreeCursor cursor;
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ Transaction txn;
+ string dbFileName;
+
+ testName = "TestCursorWithoutConfigInTxn";
+ testHome = testFixtureHome + "/" + testName;
+ dbFileName = testName + ".db";
+
+ // Open environment and begin a transaction.
+ Configuration.ClearDir(testHome);
+ SetUpEnvAndTxn(testHome, out env, out txn);
+ OpenBtreeDB(env, txn, dbFileName, out db);
+
+ // Get a cursor in the transaction.
+ cursor = db.Cursor(txn);
+
+ /*
+ * Add a record to the database with cursor and
+ * confirm that the record exists in the database.
+ */
+ CursorTest.AddOneByCursor(db, cursor);
+
+ /*
+ * Close cursor, database, commit the transaction
+ * and close the environment.
+ */
+ cursor.Close();
+ db.Close();
+ txn.Commit();
+ env.Close();
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestDelete()
+ {
+ testName = "TestDelete";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBConfig);
+ DatabaseEntry key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ DatabaseEntry data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ btreeDB.Put(key, data);
+ btreeDB.Delete(key);
+ try
+ {
+ btreeDB.Get(key);
+ }
+ catch (NotFoundException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ btreeDB.Close();
+ }
+ }
+
+ [Test]
+ public void TestExist()
+ {
+ testName = "TestExist";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase btreeDB;
+ using (btreeDB = BTreeDatabase.Open(
+ dbFileName, btreeDBConfig))
+ {
+ DatabaseEntry key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ DatabaseEntry data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+
+ btreeDB.Put(key, data);
+ Assert.IsTrue(btreeDB.Exists(
+ new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"))));
+ Assert.IsFalse(btreeDB.Exists(
+ new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"))));
+ }
+ }
+
+ [Test]
+ public void TestExistWithTxn()
+ {
+ BTreeDatabase btreeDB;
+ Transaction txn;
+ DatabaseEnvironmentConfig envConfig;
+ DatabaseEnvironment env;
+ DatabaseEntry key, data;
+
+ testName = "TestExistWithTxn";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open an environment.
+ envConfig = new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ env = DatabaseEnvironment.Open(testHome, envConfig);
+
+ // Begin a transaction.
+ txn = env.BeginTransaction();
+
+ // Open a database.
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ btreeDBConfig.Env = env;
+ btreeDB = BTreeDatabase.Open(testName + ".db",
+ btreeDBConfig, txn);
+
+ // Put key data pair into database.
+ key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ btreeDB.Put(key, data, txn);
+
+ // Confirm that the pair exists in the database.
+ Assert.IsTrue(btreeDB.Exists(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key")), txn));
+ Assert.IsFalse(btreeDB.Exists(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data")), txn));
+
+ // Dispose all.
+ btreeDB.Close();
+ txn.Commit();
+ env.Close();
+ }
+
+
+ [Test]
+ public void TestExistWithLockingInfo()
+ {
+ BTreeDatabase btreeDB;
+ DatabaseEnvironment env;
+ DatabaseEntry key, data;
+
+ testName = "TestExistWithLockingInfo";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open the environment.
+ DatabaseEnvironmentConfig envCfg =
+ new DatabaseEnvironmentConfig();
+ envCfg.Create = true;
+ envCfg.FreeThreaded = true;
+ envCfg.UseLocking = true;
+ envCfg.UseLogging = true;
+ envCfg.UseMPool = true;
+ envCfg.UseTxns = true;
+ env = DatabaseEnvironment.Open(
+ testHome, envCfg);
+
+ // Open database in transaction.
+ Transaction openTxn = env.BeginTransaction();
+ BTreeDatabaseConfig cfg =
+ new BTreeDatabaseConfig();
+ cfg.Creation = CreatePolicy.ALWAYS;
+ cfg.Env = env;
+ cfg.FreeThreaded = true;
+ cfg.PageSize = 4096;
+ cfg.Duplicates = DuplicatesPolicy.UNSORTED;
+ btreeDB = BTreeDatabase.Open(testName + ".db",
+ cfg, openTxn);
+ openTxn.Commit();
+
+ // Put key data pair into database.
+ Transaction txn = env.BeginTransaction();
+ key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ btreeDB.Put(key, data, txn);
+
+ // Confirm that the pair exists in the database with LockingInfo.
+ LockingInfo lockingInfo = new LockingInfo();
+ lockingInfo.ReadModifyWrite = true;
+
+ // Confirm that the pair exists in the database.
+ Assert.IsTrue(btreeDB.Exists(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key")), txn, lockingInfo));
+ Assert.IsFalse(btreeDB.Exists(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data")), txn, lockingInfo));
+ txn.Commit();
+
+ btreeDB.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestGetByKey()
+ {
+ testName = "TestGetByKey";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ string btreeDBName =
+ Path.GetFileNameWithoutExtension(btreeDBFileName);
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBName, btreeDBConfig);
+
+ DatabaseEntry key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ DatabaseEntry data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ btreeDB.Put(key, data);
+
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair =
+ new KeyValuePair<DatabaseEntry, DatabaseEntry>();
+ pair = btreeDB.Get(key);
+ Assert.AreEqual(pair.Key.Data, key.Data);
+ Assert.AreEqual(pair.Value.Data, data.Data);
+ btreeDB.Close();
+ }
+
+ [Test]
+ public void TestGetByRecno()
+ {
+ testName = "TestGetByRecno";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ string btreeDBName =
+ Path.GetFileNameWithoutExtension(btreeDBFileName);
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ btreeDBConfig.UseRecordNumbers = true;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBName, btreeDBConfig);
+ Assert.IsTrue(btreeDB.RecordNumbers);
+
+ DatabaseEntry key = new DatabaseEntry();
+ DatabaseEntry data = new DatabaseEntry();
+ uint recno, count, value;
+ for (recno = 1; recno <= 100; recno++)
+ {
+ value = 200 - recno;
+ Configuration.dbtFromString(key,
+ Convert.ToString(value));
+ Configuration.dbtFromString(data,
+ Convert.ToString(value));
+ btreeDB.Put(key, data);
+ }
+
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair =
+ new KeyValuePair<DatabaseEntry, DatabaseEntry>();
+
+ for (count = 1; ; count++)
+ {
+ try
+ {
+ pair = btreeDB.Get(count);
+ }
+ catch (NotFoundException)
+ {
+ Assert.AreEqual(101, count);
+ break;
+ }
+ value = 299 - 200 + count;
+ Assert.AreEqual(value.ToString(),
+ Configuration.strFromDBT(pair.Key));
+ }
+
+ btreeDB.Close();
+ }
+
+ [Test, ExpectedException(typeof(NotFoundException))]
+ public void TestGetBoth()
+ {
+ testName = "TestGetBoth";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ string btreeDBName =
+ Path.GetFileNameWithoutExtension(btreeDBFileName);
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ using (BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBName, btreeDBConfig))
+ {
+ DatabaseEntry key = new DatabaseEntry();
+ DatabaseEntry data = new DatabaseEntry();
+
+ Configuration.dbtFromString(key, "key");
+ Configuration.dbtFromString(data, "data");
+ btreeDB.Put(key, data);
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair =
+ new KeyValuePair<DatabaseEntry, DatabaseEntry>();
+ pair = btreeDB.GetBoth(key, data);
+ Assert.AreEqual(key.Data, pair.Key.Data);
+ Assert.AreEqual(data.Data, pair.Value.Data);
+
+ Configuration.dbtFromString(key, "key");
+ Configuration.dbtFromString(data, "key");
+ btreeDB.GetBoth(key, data);
+ }
+ }
+
+ [Test]
+ public void TestGetBothMultiple()
+ {
+ testName = "TestGetBothMultiple";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ string btreeDBName = testName;
+ DatabaseEntry key, data;
+ KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp;
+ int cnt;
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ btreeDBConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ btreeDBConfig.PageSize = 1024;
+ using (BTreeDatabase btreeDB = GetMultipleDB(
+ btreeDBFileName, btreeDBName, btreeDBConfig)) {
+ key = new DatabaseEntry(BitConverter.GetBytes(100));
+ data = new DatabaseEntry(BitConverter.GetBytes(100));
+
+ kvp = btreeDB.GetBothMultiple(key, data);
+ cnt = 0;
+ foreach (DatabaseEntry dbt in kvp.Value)
+ cnt++;
+ Assert.AreEqual(cnt, 10);
+
+ kvp = btreeDB.GetBothMultiple(key, data, 1024);
+ cnt = 0;
+ foreach (DatabaseEntry dbt in kvp.Value)
+ cnt++;
+ Assert.AreEqual(cnt, 10);
+ }
+ }
+
+ [Test]
+ public void TestGetMultiple()
+ {
+ testName = "TestGetMultiple";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ string btreeDBName = testName;
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ btreeDBConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ btreeDBConfig.PageSize = 512;
+
+ using (BTreeDatabase btreeDB = GetMultipleDB(
+ btreeDBFileName, btreeDBName, btreeDBConfig)) {
+ DatabaseEntry key = new DatabaseEntry(
+ BitConverter.GetBytes(10));
+ KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp =
+ btreeDB.GetMultiple(key, 1024);
+ int cnt = 0;
+ foreach (DatabaseEntry dbt in kvp.Value)
+ cnt++;
+ Assert.AreEqual(cnt, 10);
+
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(102));
+ kvp = btreeDB.GetMultiple(key, 1024);
+ cnt = 0;
+ foreach (DatabaseEntry dbt in kvp.Value)
+ cnt++;
+ Assert.AreEqual(cnt, 1);
+ }
+ }
+
+
+ [Test]
+ public void TestGetMultipleByRecno()
+ {
+ testName = "TestGetMultipleByRecno";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ string btreeDBName =
+ Path.GetFileNameWithoutExtension(btreeDBFileName);
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ btreeDBConfig.Duplicates = DuplicatesPolicy.NONE;
+ btreeDBConfig.UseRecordNumbers = true;
+ using (BTreeDatabase btreeDB = GetMultipleDB(
+ btreeDBFileName, btreeDBName, btreeDBConfig)) {
+ int recno = 44;
+ KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp =
+ btreeDB.GetMultiple((uint)recno);
+ int cnt = 0;
+ int kdata = BitConverter.ToInt32(kvp.Key.Data, 0);
+ Assert.AreEqual(kdata, recno);
+ foreach (DatabaseEntry dbt in kvp.Value) {
+ cnt++;
+ int ddata = BitConverter.ToInt32(dbt.Data, 0);
+ Assert.AreEqual(ddata, recno);
+ }
+ Assert.AreEqual(cnt, 1);
+ }
+ }
+
+ [Test]
+ public void TestGetMultipleByRecnoInSize()
+ {
+ testName = "TestGetMultipleByRecnoInSize";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ string btreeDBName =
+ Path.GetFileNameWithoutExtension(btreeDBFileName);
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ btreeDBConfig.Duplicates = DuplicatesPolicy.NONE;
+ btreeDBConfig.UseRecordNumbers = true;
+ btreeDBConfig.PageSize = 512;
+ using (BTreeDatabase btreeDB = GetMultipleDB(
+ btreeDBFileName, btreeDBName, btreeDBConfig)) {
+ int recno = 100;
+ int bufferSize = 1024;
+ KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp =
+ btreeDB.GetMultiple((uint)recno, bufferSize);
+ int cnt = 0;
+ int kdata = BitConverter.ToInt32(kvp.Key.Data, 0);
+ Assert.AreEqual(kdata, recno);
+ foreach (DatabaseEntry dbt in kvp.Value) {
+ cnt++;
+ Assert.AreEqual(dbt.Data.Length, 111);
+ }
+ Assert.AreEqual(1, cnt);
+ }
+ }
+
+ [Test]
+ public void TestGetMultipleInSize()
+ {
+ testName = "TestGetMultipleInSize";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ string btreeDBName =
+ Path.GetFileNameWithoutExtension(btreeDBFileName);
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ btreeDBConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ btreeDBConfig.PageSize = 1024;
+ using (BTreeDatabase btreeDB = GetMultipleDB(
+ btreeDBFileName, btreeDBName, btreeDBConfig)) {
+
+ int num = 101;
+ DatabaseEntry key = new DatabaseEntry(
+ BitConverter.GetBytes(num));
+ int bufferSize = 10240;
+ KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp =
+ btreeDB.GetMultiple(key, bufferSize);
+ int cnt = 0;
+ foreach (DatabaseEntry dbt in kvp.Value) {
+ cnt++;
+ Assert.AreEqual(BitConverter.ToInt32(
+ dbt.Data, 0), num);
+ num++;
+ }
+ Assert.AreEqual(cnt, 923);
+ }
+ }
+
+ [Test]
+ public void TestGetWithTxn()
+ {
+ testName = "TestGetWithTxn";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseLogging = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ try
+ {
+ Transaction openTxn = env.BeginTransaction();
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Env = env;
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase db = BTreeDatabase.Open(
+ testName + ".db", dbConfig, openTxn);
+ openTxn.Commit();
+
+ Transaction putTxn = env.BeginTransaction();
+ try
+ {
+ for (int i = 0; i < 20; i++)
+ db.Put(new DatabaseEntry(
+ BitConverter.GetBytes(i)),
+ new DatabaseEntry(
+ BitConverter.GetBytes(i)), putTxn);
+ putTxn.Commit();
+ }
+ catch (DatabaseException e)
+ {
+ putTxn.Abort();
+ db.Close();
+ throw e;
+ }
+
+ Transaction getTxn = env.BeginTransaction();
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ try
+ {
+ for (int i = 0; i < 20; i++)
+ {
+ pair = db.Get(new DatabaseEntry(
+ BitConverter.GetBytes(i)), getTxn);
+ Assert.AreEqual(BitConverter.GetBytes(i),
+ pair.Key.Data);
+ }
+
+ getTxn.Commit();
+ db.Close();
+ }
+ catch (DatabaseException)
+ {
+ getTxn.Abort();
+ db.Close();
+ throw new TestException();
+ }
+ }
+ catch (DatabaseException)
+ {
+ }
+ finally
+ {
+ env.Close();
+ }
+ }
+
+ [Test]
+ public void TestKeyRange()
+ {
+ testName = "TestKeyRange";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ string btreeDBName = Path.GetFileNameWithoutExtension(
+ btreeDBFileName);
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBName, btreeDBConfig);
+
+ DatabaseEntry key = new DatabaseEntry();
+ DatabaseEntry data = new DatabaseEntry();
+ uint recno;
+ for (recno = 1; recno <= 10; recno++)
+ {
+ Configuration.dbtFromString(key,
+ Convert.ToString(recno));
+ Configuration.dbtFromString(data,
+ Convert.ToString(recno));
+ btreeDB.Put(key, data);
+ }
+
+ Configuration.dbtFromString(key, Convert.ToString(5));
+ KeyRange keyRange = btreeDB.KeyRange(key);
+ Assert.AreEqual(0.5, keyRange.Less);
+ Assert.AreEqual(0.1, keyRange.Equal);
+ Assert.AreEqual(0.4, keyRange.Greater);
+
+ btreeDB.Close();
+ }
+
+ [Test]
+ public void TestOpenExistingBtreeDB()
+ {
+ testName = "TestOpenExistingBtreeDB";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeConfig =
+ new BTreeDatabaseConfig();
+ btreeConfig.Creation = CreatePolicy.ALWAYS;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeConfig);
+ btreeDB.Close();
+
+ DatabaseConfig dbConfig = new DatabaseConfig();
+ Database db = Database.Open(btreeDBFileName,
+ dbConfig);
+ Assert.AreEqual(db.Type, DatabaseType.BTREE);
+ Assert.AreEqual(db.Creation, CreatePolicy.NEVER);
+ db.Close();
+ }
+
+ [Test]
+ public void TestOpenNewBtreeDB()
+ {
+ testName = "TestOpenNewBtreeDB";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ BTreeDatabaseConfig btreeConfig =
+ new BTreeDatabaseConfig();
+ BTreeDatabaseConfigTest.Config(xmlElem,
+ ref btreeConfig, true);
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeConfig);
+ Confirm(xmlElem, btreeDB, true);
+ btreeDB.Close();
+ }
+
+ [Test]
+ public void TestOpenMulDBInSingleFile()
+ {
+ testName = "TestOpenMulDBInSingleFile";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ string[] btreeDBArr = new string[4];
+
+ for (int i = 0; i < 4; i++)
+ btreeDBArr[i] = Path.GetFileNameWithoutExtension(
+ btreeDBFileName) + i;
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+
+ BTreeDatabase btreeDB;
+ for (int i = 0; i < 4; i++)
+ {
+ btreeDB = BTreeDatabase.Open(btreeDBFileName,
+ btreeDBArr[i], btreeDBConfig);
+ Assert.AreEqual(CreatePolicy.IF_NEEDED, btreeDB.Creation);
+ btreeDB.Close();
+ }
+
+ DatabaseConfig dbConfig = new DatabaseConfig();
+ Database db;
+ for (int i = 0; i < 4; i++)
+ {
+ using (db = Database.Open(btreeDBFileName,
+ btreeDBArr[i], dbConfig))
+ {
+ Assert.AreEqual(btreeDBArr[i],
+ db.DatabaseName);
+ Assert.AreEqual(DatabaseType.BTREE,
+ db.Type);
+ }
+ }
+ }
+
+ [Test]
+ public void TestOpenWithTxn()
+ {
+ testName = "TestOpenWithTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBName = testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+ Transaction txn = env.BeginTransaction(
+ new TransactionConfig());
+
+ BTreeDatabaseConfig btreeConfig =
+ new BTreeDatabaseConfig();
+ btreeConfig.Creation = CreatePolicy.ALWAYS;
+ btreeConfig.Env = env;
+
+ /*
+ * If environmnet home is set, the file name in Open()
+ * is the relative path.
+ */
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBName, btreeConfig, txn);
+ Assert.IsTrue(btreeDB.Transactional);
+ btreeDB.Close();
+ txn.Commit();
+ env.Close();
+ }
+
+ [Test]
+ public void TestPrefixCompare()
+ {
+ testName = "TestPrefixCompare";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Duplicates = DuplicatesPolicy.SORTED;
+ dbConfig.BTreeCompare =
+ new EntryComparisonDelegate(dbIntCompare);
+ dbConfig.BTreePrefixCompare =
+ new EntryComparisonDelegate(dbIntCompare);
+ BTreeDatabase db = BTreeDatabase.Open(
+ btreeDBFileName, dbConfig);
+
+ Assert.Greater(0, db.PrefixCompare(new DatabaseEntry(
+ BitConverter.GetBytes(255)), new DatabaseEntry(
+ BitConverter.GetBytes(257))));
+
+ Assert.AreEqual(0, db.PrefixCompare(new DatabaseEntry(
+ BitConverter.GetBytes(255)), new DatabaseEntry(
+ BitConverter.GetBytes(255))));
+
+ db.Close();
+ }
+
+ [Test]
+ public void TestPutWithoutTxn()
+ {
+ testName = "TestPutWithoutTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ DatabaseEntry key, data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ using (BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBConfig))
+ {
+ // Put integer into database
+ key = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ btreeDB.Put(key, data);
+ pair = btreeDB.Get(key);
+ Assert.AreEqual(key.Data, pair.Key.Data);
+ Assert.AreEqual(data.Data, pair.Value.Data);
+ }
+ }
+
+ [Test, ExpectedException(typeof(KeyExistException))]
+ public void TestPutNoOverWrite()
+ {
+ testName = "TestPutNoOverWrite";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ DatabaseEntry key, data, newData;
+ using (BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBConfig))
+ {
+ key = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ newData = new DatabaseEntry(
+ BitConverter.GetBytes((int)1));
+
+ btreeDB.Put(key, data);
+ btreeDB.PutNoOverwrite(key, newData);
+ }
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestPutNoDuplicateWithTxn()
+ {
+ testName = "TestPutNoDuplicateWithTxn";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseLogging = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ Transaction txn = env.BeginTransaction();
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ btreeDBConfig.Env = env;
+ btreeDBConfig.Duplicates = DuplicatesPolicy.SORTED;
+
+ DatabaseEntry key, data;
+ try
+ {
+ using (BTreeDatabase btreeDB =
+ BTreeDatabase.Open(
+ testName + ".db", btreeDBConfig, txn))
+ {
+ key = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+
+ btreeDB.Put(key, data, txn);
+ btreeDB.PutNoDuplicate(key, data, txn);
+ }
+ txn.Commit();
+ }
+ catch (KeyExistException)
+ {
+ txn.Abort();
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ env.Close();
+ }
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestRemoveDBFile()
+ {
+ testName = "TestRemoveDBFile";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ RemoveDBWithoutEnv(testHome, testName, false);
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestRemoveOneDBFromDBFile()
+ {
+ testName = "TestRemoveOneDBFromDBFile";
+ testHome = testFixtureHome + "/" + testName;
+
+ RemoveDBWithoutEnv(testHome, testName, true);
+ }
+
+ public void RemoveDBWithoutEnv(string home, string dbName, bool ifDBName)
+ {
+ string dbFileName = home + "/" + dbName + ".db";
+
+ Configuration.ClearDir(home);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+
+ BTreeDatabase btreeDB;
+ if (ifDBName == false)
+ {
+ btreeDB = BTreeDatabase.Open(dbFileName, btreeDBConfig);
+ btreeDB.Close();
+ BTreeDatabase.Remove(dbFileName);
+ throw new ExpectedTestException();
+ }
+ else
+ {
+ btreeDB = BTreeDatabase.Open(dbFileName, dbName, btreeDBConfig);
+ btreeDB.Close();
+ BTreeDatabase.Remove(dbFileName, dbName);
+ Assert.IsTrue(File.Exists(dbFileName));
+ try
+ {
+ btreeDB = BTreeDatabase.Open(dbFileName, dbName, new BTreeDatabaseConfig());
+ btreeDB.Close();
+ }
+ catch (DatabaseException)
+ {
+ throw new ExpectedTestException();
+ }
+ }
+ }
+
+ [Test]
+ public void TestRemoveDBFromFileInEnv()
+ {
+ testName = "TestRemoveDBFromFileInEnv";
+ testHome = testFixtureHome + "/" + testName;
+
+ RemoveDatabase(testHome, testName, true, true);
+ }
+
+ [Test]
+ public void TestRemoveDBFromEnv()
+ {
+ testName = "TestRemoveDBFromEnv";
+ testHome = testFixtureHome + "/" + testName;
+
+ RemoveDatabase(testHome, testName, true, false);
+ }
+
+ public void RemoveDatabase(string home, string dbName,
+ bool ifEnv, bool ifDBName)
+ {
+ string dbFileName = dbName + ".db";
+
+ Configuration.ClearDir(home);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseCDB = true;
+ envConfig.UseMPool = true;
+
+ DatabaseEnvironment env;
+ env = DatabaseEnvironment.Open(home, envConfig);
+
+ try
+ {
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ btreeDBConfig.Env = env;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ dbFileName, dbName, btreeDBConfig);
+ btreeDB.Close();
+
+ if (ifEnv == true && ifDBName == true)
+ BTreeDatabase.Remove(dbFileName, dbName, env);
+ else if (ifEnv == true)
+ BTreeDatabase.Remove(dbFileName, env);
+ }
+ catch (DatabaseException)
+ {
+ throw new TestException();
+ }
+ finally
+ {
+ try
+ {
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.NEVER;
+ dbConfig.Env = env;
+ BTreeDatabase db = BTreeDatabase.Open(
+ dbFileName, dbName, dbConfig);
+ Assert.AreEqual(db.Creation, CreatePolicy.NEVER);
+ db.Close();
+ throw new TestException();
+ }
+ catch (DatabaseException)
+ {
+ }
+ finally
+ {
+ env.Close();
+ }
+ }
+ }
+
+ [Test]
+ public void TestRenameDB()
+ {
+ testName = "TestRenameDB";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" + testName + ".db";
+ string btreeDBName = testName;
+ string newBtreeDBName = btreeDBName + "1" + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ try
+ {
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBName, btreeDBConfig);
+ btreeDB.Close();
+ BTreeDatabase.Rename(btreeDBFileName,
+ btreeDBName, newBtreeDBName);
+
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.NEVER;
+ BTreeDatabase newDB = BTreeDatabase.Open(
+ btreeDBFileName, newBtreeDBName, dbConfig);
+ newDB.Close();
+ }
+ catch (DatabaseException e)
+ {
+ throw new TestException(e.Message);
+ }
+ finally
+ {
+ try
+ {
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.NEVER;
+ BTreeDatabase db = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBName,
+ dbConfig);
+ throw new TestException(testName);
+ }
+ catch (DatabaseException)
+ {
+ }
+ }
+ }
+
+ [Test]
+ public void TestRenameDBFile()
+ {
+ testName = "TestRenameDB";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ string newBtreeDBFileName = testHome + "/" +
+ testName + "1.db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBConfig);
+ btreeDB.Close();
+
+ BTreeDatabase.Rename(btreeDBFileName,
+ newBtreeDBFileName);
+ Assert.IsFalse(File.Exists(btreeDBFileName));
+ Assert.IsTrue(File.Exists(newBtreeDBFileName));
+ }
+
+ [Test]
+ public void TestSync()
+ {
+ testName = "TestSync";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBName = testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.ForceFlush = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ envConfig.UseLogging = true;
+ envConfig.LogSystemCfg = new LogConfig();
+ envConfig.LogSystemCfg.ForceSync = false;
+ envConfig.LogSystemCfg.AutoRemove = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ TransactionConfig txnConfig = new TransactionConfig();
+ txnConfig.SyncAction =
+ TransactionConfig.LogFlush.WRITE_NOSYNC;
+ Transaction txn = env.BeginTransaction(txnConfig);
+
+ BTreeDatabaseConfig btreeConfig =
+ new BTreeDatabaseConfig();
+ btreeConfig.Creation = CreatePolicy.ALWAYS;
+ btreeConfig.Env = env;
+
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBName, btreeConfig, txn);
+
+ DatabaseEntry key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ DatabaseEntry data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ Assert.IsFalse(btreeDB.Exists(key, txn));
+ btreeDB.Put(key, data, txn);
+ btreeDB.Sync();
+ btreeDB.Close(false);
+ txn.Commit();
+ env.Close();
+
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.NEVER;
+ using (BTreeDatabase db = BTreeDatabase.Open(
+ testHome + "/" + btreeDBName, dbConfig))
+ {
+ Assert.IsTrue(db.Exists(key));
+ }
+ }
+
+ [Test]
+ public void TestTruncate()
+ {
+ testName = "TestTruncate";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ btreeDBConfig.CacheSize =
+ new CacheInfo(0, 30 * 1024, 1);
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBConfig);
+ DatabaseEntry key;
+ DatabaseEntry data;
+ for (int i = 0; i < 100; i++)
+ {
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ btreeDB.Put(key, data);
+ }
+ uint count = btreeDB.Truncate();
+ Assert.AreEqual(100, count);
+ Assert.IsFalse(btreeDB.Exists(new DatabaseEntry(
+ BitConverter.GetBytes((int)50))));
+ btreeDB.Close();
+ }
+
+ [Test]
+ public void TestTruncateInTxn()
+ {
+ testName = "TestTruncateInTxn";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ try
+ {
+ Transaction openTxn = env.BeginTransaction();
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ BTreeDatabase db = BTreeDatabase.Open(
+ testName + ".db", dbConfig, openTxn);
+ openTxn.Commit();
+
+ Transaction putTxn = env.BeginTransaction();
+ try
+ {
+ DatabaseEntry key, data;
+ for (int i = 0; i < 10; i++)
+ {
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ db.Put(key, data, putTxn);
+ }
+
+ putTxn.Commit();
+ }
+ catch (DatabaseException e)
+ {
+ putTxn.Abort();
+ db.Close();
+ throw e;
+ }
+
+ Transaction trunTxn = env.BeginTransaction();
+ try
+ {
+ uint count = db.Truncate(trunTxn);
+ Assert.AreEqual(10, count);
+ Assert.IsFalse(db.Exists(
+ new DatabaseEntry(
+ BitConverter.GetBytes((int)5)), trunTxn));
+ trunTxn.Commit();
+ db.Close();
+ }
+ catch (DatabaseException)
+ {
+ trunTxn.Abort();
+ db.Close();
+ throw new TestException();
+ }
+ }
+ catch (DatabaseException)
+ {
+ }
+ finally
+ {
+ env.Close();
+ }
+ }
+
+ [Test]
+ public void TestTruncateUnusedPages()
+ {
+ testName = "TestTruncateUnusedPages";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.ALWAYS;
+ dbConfig.PageSize = 512;
+ BTreeDatabase db = BTreeDatabase.Open(
+ dbFileName, dbConfig);
+ DatabaseEntry key, data;
+ for (int i = 0; i < 100; i++)
+ {
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ db.Put(key, data);
+ }
+
+ for (int i = 0; i < 80; i++)
+ db.Delete(new DatabaseEntry(
+ BitConverter.GetBytes(i)));
+
+ uint count = db.TruncateUnusedPages();
+ Assert.LessOrEqual(0, count);
+
+ db.Close();
+ }
+
+ [Test]
+ public void TestTruncateUnusedPagesWithTxn()
+ {
+ testName = "TestTruncateUnusedPagesWithTxn";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ BTreeDatabase db;
+ try
+ {
+ Transaction openTxn = env.BeginTransaction();
+ try
+ {
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ dbConfig.PageSize = 512;
+ db = BTreeDatabase.Open(
+ testName + ".db", dbConfig, openTxn);
+ openTxn.Commit();
+ Assert.AreEqual(512, db.Pagesize);
+ }
+ catch (DatabaseException e)
+ {
+ openTxn.Abort();
+ throw e;
+ }
+
+ Transaction putTxn = env.BeginTransaction();
+ try
+ {
+ DatabaseEntry key, data;
+ for (int i = 0; i < 100; i++)
+ {
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ db.Put(key, data, putTxn);
+ }
+
+ putTxn.Commit();
+ }
+ catch (DatabaseException e)
+ {
+ putTxn.Abort();
+ db.Close();
+ throw e;
+ }
+
+ Transaction delTxn = env.BeginTransaction();
+ try
+ {
+ for (int i = 20; i <= 80; i++)
+ db.Delete(new DatabaseEntry(
+ BitConverter.GetBytes(i)), delTxn);
+ delTxn.Commit();
+ }
+ catch (DatabaseException e)
+ {
+ delTxn.Abort();
+ db.Close();
+ throw e;
+ }
+
+ Transaction trunTxn = env.BeginTransaction();
+ try
+ {
+ uint trunPages = db.TruncateUnusedPages(
+ trunTxn);
+ Assert.LessOrEqual(0, trunPages);
+ trunTxn.Commit();
+ db.Close();
+ }
+ catch (DatabaseException)
+ {
+ trunTxn.Abort();
+ db.Close();
+ throw new Exception();
+ }
+ }
+ catch (DatabaseException)
+ {
+ }
+ finally
+ {
+ env.Close();
+ }
+ }
+
+ [Test]
+ public void TestSalvage()
+ {
+ testName = "TestSalvage";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ string printableOutPut = testHome + "/" +
+ "printableOutPut";
+ string inprintableOutPut = testHome + "/" +
+ "inprintableOutPut";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBConfig);
+
+ DatabaseEntry key;
+ DatabaseEntry data;
+
+ for (uint i = 0; i < 10; i++)
+ {
+ key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes(i.ToString()));
+ data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes(i.ToString()));
+ btreeDB.Put(key, data);
+ }
+
+ btreeDB.Close();
+
+ StreamWriter sw1 = new StreamWriter(printableOutPut);
+ StreamWriter sw2 = new StreamWriter(inprintableOutPut);
+ BTreeDatabase.Salvage(btreeDBFileName, btreeDBConfig,
+ true, true, sw1);
+ BTreeDatabase.Salvage(btreeDBFileName, btreeDBConfig,
+ false, true, sw2);
+ sw1.Close();
+ sw2.Close();
+
+ FileStream file1 = new FileStream(printableOutPut,
+ FileMode.Open);
+ FileStream file2 = new FileStream(inprintableOutPut,
+ FileMode.Open);
+ if (file1.Length == file2.Length)
+ {
+ int filebyte1 = 0;
+ int filebyte2 = 0;
+ do
+ {
+ filebyte1 = file1.ReadByte();
+ filebyte2 = file2.ReadByte();
+ } while ((filebyte1 == filebyte2) &&
+ (filebyte1 != -1));
+ Assert.AreNotEqual(filebyte1, filebyte2);
+ }
+
+ file1.Close();
+ file2.Close();
+ }
+
+ [Test]
+ public void TestUpgrade()
+ {
+ testName = "TestUpgrade";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ string srcDBFileName = "../../bdb4.7.db";
+ string testDBFileName = testHome + "/bdb4.7.db";
+
+ FileInfo srcDBFileInfo = new FileInfo(srcDBFileName);
+
+ //Copy the file.
+ srcDBFileInfo.CopyTo(testDBFileName);
+ Assert.IsTrue(File.Exists(testDBFileName));
+
+ BTreeDatabase.Upgrade(testDBFileName,
+ new DatabaseConfig(), true);
+
+ // Open the upgraded database file.
+ BTreeDatabase db = BTreeDatabase.Open(
+ testDBFileName, new BTreeDatabaseConfig());
+ db.Close();
+ }
+
+ [Test, ExpectedException(typeof(TestException))]
+ public void TestVerify()
+ {
+ testName = "TestVerify";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBFileName = testHome + "/" +
+ testName + ".db";
+ string btreeDBName =
+ Path.GetFileNameWithoutExtension(btreeDBFileName);
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ btreeDBFileName, btreeDBName, btreeDBConfig);
+ btreeDB.Close();
+ btreeDBConfig.Duplicates = DuplicatesPolicy.SORTED;
+ BTreeDatabase.Verify(btreeDBFileName, btreeDBConfig,
+ Database.VerifyOperation.NO_ORDER_CHECK);
+ try
+ {
+ BTreeDatabase.Verify(btreeDBFileName,
+ btreeDBConfig,
+ Database.VerifyOperation.ORDER_CHECK_ONLY);
+ }
+ catch (DatabaseException)
+ {
+ throw new TestException(testName);
+ }
+ finally
+ {
+ BTreeDatabase.Verify(btreeDBFileName,
+ btreeDBName, btreeDBConfig,
+ Database.VerifyOperation.ORDER_CHECK_ONLY);
+ }
+
+ }
+
+ [Test]
+ public void TestStats()
+ {
+ testName = "TestStats";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" +
+ testName + ".db";
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ ConfigCase1(dbConfig);
+ BTreeDatabase db = BTreeDatabase.Open(dbFileName,
+ dbConfig);
+
+ BTreeStats stats = db.Stats();
+ ConfirmStatsPart1Case1(stats);
+
+ // Put 500 records into the database.
+ PutRecordCase1(db, null);
+
+ stats = db.Stats();
+ ConfirmStatsPart2Case1(stats);
+
+ // Delete some data to get some free pages.
+ byte[] bigArray = new byte[10240];
+ db.Delete(new DatabaseEntry(bigArray));
+
+ db.PrintStats();
+ db.PrintFastStats();
+
+ db.Close();
+ }
+
+ [Test]
+ public void TestStatsInTxn()
+ {
+ testName = "TestStatsInTxn";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ StatsInTxn(testHome, testName, false);
+ }
+
+ [Test]
+ public void TestStatsWithIsolation()
+ {
+ testName = "TestStatsWithIsolation";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ StatsInTxn(testHome, testName, true);
+ }
+
+ [Test]
+ public void TestMultipleDBSingleFile()
+ {
+ testName = "TestMultipleDBSingleFile";
+ testHome = testFixtureHome + "/" + testName;
+ string btreeDBName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ string dbName = "test";
+
+ /* Create and initialize database object, open the database. */
+ BTreeDatabaseConfig btreeDBconfig = new BTreeDatabaseConfig();
+ btreeDBconfig.Creation = CreatePolicy.IF_NEEDED;
+ btreeDBconfig.ErrorPrefix = testName;
+ btreeDBconfig.UseRecordNumbers = true;
+
+ BTreeDatabase btreeDB = BTreeDatabase.Open(btreeDBName, dbName,
+ btreeDBconfig);
+ btreeDB.Close();
+ btreeDB = BTreeDatabase.Open(btreeDBName, dbName + "2",
+ btreeDBconfig);
+ btreeDB.Close();
+
+ BTreeDatabaseConfig dbcfg = new BTreeDatabaseConfig();
+ dbcfg.ReadOnly = true;
+ BTreeDatabase newDb = BTreeDatabase.Open(btreeDBName, dbcfg);
+ Boolean val = newDb.HasMultiple;
+ Assert.IsTrue(val);
+ }
+
+ public void StatsInTxn(string home, string name, bool ifIsolation)
+ {
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ EnvConfigCase1(envConfig);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConfig);
+
+ Transaction openTxn = env.BeginTransaction();
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ ConfigCase1(dbConfig);
+ dbConfig.Env = env;
+ BTreeDatabase db = BTreeDatabase.Open(name + ".db",
+ dbConfig, openTxn);
+ openTxn.Commit();
+
+ Transaction statsTxn = env.BeginTransaction();
+ BTreeStats stats;
+ BTreeStats fastStats;
+ if (ifIsolation == false)
+ {
+ stats = db.Stats(statsTxn);
+ fastStats = db.FastStats(statsTxn);
+ }
+ else
+ {
+ stats = db.Stats(statsTxn, Isolation.DEGREE_ONE);
+ fastStats = db.FastStats(statsTxn,
+ Isolation.DEGREE_ONE);
+ }
+ ConfirmStatsPart1Case1(stats);
+
+ // Put 500 records into the database.
+ PutRecordCase1(db, statsTxn);
+
+ if (ifIsolation == false)
+ stats = db.Stats(statsTxn);
+ else
+ stats = db.Stats(statsTxn, Isolation.DEGREE_TWO);
+ ConfirmStatsPart2Case1(stats);
+
+ // Delete some data to get some free pages.
+ byte[] bigArray = new byte[10240];
+ db.Delete(new DatabaseEntry(bigArray), statsTxn);
+ if (ifIsolation == false)
+ stats = db.Stats(statsTxn);
+ else
+ stats = db.Stats(statsTxn, Isolation.DEGREE_THREE);
+ ConfirmStatsPart3Case1(stats);
+
+ db.PrintStats(true);
+ Assert.AreEqual(0, stats.EmptyPages);
+
+ statsTxn.Commit();
+ db.Close();
+ env.Close();
+ }
+
+ public void EnvConfigCase1(DatabaseEnvironmentConfig cfg)
+ {
+ cfg.Create = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.UseLogging = true;
+ }
+
+ public void ConfigCase1(BTreeDatabaseConfig dbConfig)
+ {
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ dbConfig.PageSize = 4096;
+ dbConfig.MinKeysPerPage = 10;
+ }
+
+ public void PutRecordCase1(BTreeDatabase db, Transaction txn)
+ {
+ byte[] bigArray = new byte[10240];
+ for (int i = 0; i < 100; i++)
+ {
+ if (txn == null)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+ else
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)), txn);
+ }
+ for (int i = 100; i < 500; i++)
+ {
+ if (txn == null)
+ db.Put(new DatabaseEntry(bigArray),
+ new DatabaseEntry(bigArray));
+ else
+ db.Put(new DatabaseEntry(bigArray),
+ new DatabaseEntry(bigArray), txn);
+ }
+ }
+
+ public void ConfirmStatsPart1Case1(BTreeStats stats)
+ {
+ Assert.AreEqual(1, stats.EmptyPages);
+ Assert.AreNotEqual(0, stats.LeafPagesFreeBytes);
+ Assert.AreEqual(1, stats.Levels);
+ Assert.AreNotEqual(0, stats.MagicNumber);
+ Assert.AreEqual(1, stats.MetadataFlags);
+ Assert.AreEqual(10, stats.MinKey);
+ Assert.AreEqual(2, stats.nPages);
+ Assert.AreEqual(4096, stats.PageSize);
+ Assert.AreEqual(9, stats.Version);
+ }
+
+ public void ConfirmStatsPart2Case1(BTreeStats stats)
+ {
+ Assert.AreNotEqual(0, stats.DuplicatePages);
+ Assert.AreNotEqual(0, stats.DuplicatePagesFreeBytes);
+ Assert.AreNotEqual(0, stats.InternalPages);
+ Assert.AreNotEqual(0, stats.InternalPagesFreeBytes);
+ Assert.AreNotEqual(0, stats.LeafPages);
+ Assert.AreEqual(500, stats.nData);
+ Assert.AreEqual(101, stats.nKeys);
+ Assert.AreNotEqual(0, stats.OverflowPages);
+ Assert.AreNotEqual(0, stats.OverflowPagesFreeBytes);
+ }
+
+ public void ConfirmStatsPart3Case1(BTreeStats stats)
+ {
+ Assert.AreNotEqual(0, stats.FreePages);
+ }
+
+ private int dbIntCompare(DatabaseEntry dbt1,
+ DatabaseEntry dbt2)
+ {
+ int a, b;
+ a = BitConverter.ToInt32(dbt1.Data, 0);
+ b = BitConverter.ToInt32(dbt2.Data, 0);
+ return a - b;
+ }
+
+ public void SetUpEnvAndTxn(string home,
+ out DatabaseEnvironment env, out Transaction txn)
+ {
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ env = DatabaseEnvironment.Open(home, envConfig);
+ txn = env.BeginTransaction();
+ }
+
+ public void OpenBtreeDB(DatabaseEnvironment env,
+ Transaction txn, string dbFileName,
+ out BTreeDatabase db)
+ {
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ if (env != null)
+ {
+ dbConfig.Env = env;
+ dbConfig.NoMMap = false;
+ db = BTreeDatabase.Open(dbFileName, dbConfig, txn);
+ }
+ else
+ {
+ db = BTreeDatabase.Open(dbFileName, dbConfig);
+ }
+ }
+
+ private BTreeDatabase GetMultipleDB(
+ string filename, string dbname, BTreeDatabaseConfig cfg) {
+ BTreeDatabase ret;
+ DatabaseEntry data, key;
+
+ ret = BTreeDatabase.Open(filename, dbname, cfg);
+ key = null;
+ if (cfg.UseRecordNumbers) {
+ /*
+ * Dups aren't allowed with record numbers, so
+ * we have to put different data. Also, record
+ * numbers start at 1, so we do too, which makes
+ * checking results easier.
+ */
+ for (int i = 1; i < 100; i++) {
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ ret.Put(key, data);
+ }
+
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(100));
+ data = new DatabaseEntry();
+ data.Data = new byte[111];
+ for (int i = 0; i < 111; i++)
+ data.Data[i] = (byte)i;
+ ret.Put(key, data);
+ } else {
+ for (int i = 0; i < 100; i++) {
+ if (i % 10 == 0)
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ /* Don't put nulls into the db. */
+ Assert.IsFalse(key == null);
+ Assert.IsFalse(data == null);
+ ret.Put(key, data);
+ }
+
+ if (cfg.Duplicates == DuplicatesPolicy.UNSORTED) {
+ /* Add in duplicates to check GetBothMultiple */
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(100));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(100));
+ for (int i = 0; i < 10; i++)
+ ret.Put(key, data);
+
+ /*
+ * Add duplicates to check GetMultiple
+ * with given buffer size.
+ */
+ for (int i = 101; i < 1024; i++) {
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(101));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ ret.Put(key, data);
+ }
+
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(102));
+ data = new DatabaseEntry();
+ data.Data = new byte[112];
+ for (int i = 0; i < 112; i++)
+ data.Data[i] = (byte)i;
+ ret.Put(key, data);
+ }
+ }
+ return ret;
+ }
+
+ public static void Confirm(XmlElement xmlElem,
+ BTreeDatabase btreeDB, bool compulsory)
+ {
+ DatabaseTest.Confirm(xmlElem, btreeDB, compulsory);
+ Configuration.ConfirmDuplicatesPolicy(xmlElem,
+ "Duplicates", btreeDB.Duplicates, compulsory);
+ Configuration.ConfirmUint(xmlElem, "MinKeysPerPage",
+ btreeDB.MinKeysPerPage, compulsory);
+ /*
+ * BTreeDatabase.RecordNumbers is the value of
+ * BTreeDatabaseConfig.UseRecordNumbers.
+ */
+ Configuration.ConfirmBool(xmlElem, "UseRecordNumbers",
+ btreeDB.RecordNumbers, compulsory);
+ /*
+ * BTreeDatabase.ReverseSplit is the value of
+ * BTreeDatabaseConfig.NoReverseSplitting.
+ */
+ Configuration.ConfirmBool(xmlElem, "NoReverseSplitting",
+ btreeDB.ReverseSplit, compulsory);
+ Assert.AreEqual(DatabaseType.BTREE, btreeDB.Type);
+ string type = btreeDB.ToString();
+ Assert.IsNotNull(type);
+ }
+ }
+}
+
diff --git a/test/scr037/Configuration.cs b/test/scr037/Configuration.cs
new file mode 100644
index 0000000..abf0079
--- /dev/null
+++ b/test/scr037/Configuration.cs
@@ -0,0 +1,1107 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using BerkeleyDB;
+using NUnit.Framework;
+
+namespace CsharpAPITest
+{
+ public class Configuration
+ {
+ /*
+ * Configure the value with data in xml and return true or
+ * false to indicate if the value is configured. If there
+ * is no testing data and it is optional, return false. If
+ * there is no testing data in xml and it is compulsory,
+ * ConfigNotFoundException will be thrown. If any testing
+ * data is provided, the value will be set by the testing
+ * data and true will be returned.
+ */
+ #region Config
+ public static void ConfigAckPolicy(XmlElement xmlElem,
+ string name, ref AckPolicy ackPolicy, bool compulsory)
+ {
+ XmlNode xmlNode = XMLReader.GetNode(xmlElem,
+ name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ string policy = xmlNode.InnerText;
+ if (policy == "ALL")
+ ackPolicy = AckPolicy.ALL;
+ else if (policy == "ALL_PEERS")
+ ackPolicy = AckPolicy.ALL_PEERS;
+ else if (policy == "NONE")
+ ackPolicy = AckPolicy.NONE;
+ else if (policy == "ONE")
+ ackPolicy = AckPolicy.ONE;
+ else if (policy == "ONE_PEER")
+ ackPolicy = AckPolicy.ONE_PEER;
+ else if (policy == "QUORUM")
+ ackPolicy = AckPolicy.QUORUM;
+ else
+ throw new InvalidConfigException(name);
+ }
+ }
+
+ public static bool ConfigBool(XmlElement xmlElem,
+ string name, ref bool value, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ value = bool.Parse(xmlNode.InnerText);
+ return true;
+ }
+
+ public static bool ConfigByteOrder(XmlElement xmlElem,
+ string name, ref ByteOrder byteOrder, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ byteOrder = ByteOrder.FromConst(
+ int.Parse(xmlNode.InnerText));
+ return true;
+ }
+
+ public static bool ConfigByteMatrix(XmlElement xmlElem,
+ string name, ref byte[,] byteMatrix, bool compulsory)
+ {
+ int i, j, matrixLen;
+
+ XmlNode xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ matrixLen = xmlNode.ChildNodes.Count;
+ byte[,] matrix = new byte[matrixLen, matrixLen];
+ for (i = 0; i < matrixLen; i++)
+ {
+ if (xmlNode.ChildNodes[i].ChildNodes.Count != matrixLen)
+ throw new ConfigNotFoundException(name);
+ for (j = 0; j < matrixLen; j++)
+ {
+ matrix[i, j] = byte.Parse(
+ xmlNode.ChildNodes[i].ChildNodes[j].InnerText);
+ }
+ }
+
+ byteMatrix = matrix;
+ return true;
+ }
+
+ public static bool ConfigCacheInfo(XmlElement xmlElem,
+ string name, ref CacheInfo cacheSize, bool compulsory)
+ {
+ XmlNode xmlNode;
+ XmlNode xmlChildNode;
+ uint bytes;
+ uint gigabytes;
+ int nCaches;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ if ((xmlChildNode = XMLReader.GetNode(
+ (XmlElement)xmlNode, "Bytes")) != null)
+ {
+ bytes = uint.Parse(xmlChildNode.InnerText);
+ if ((xmlChildNode = XMLReader.GetNode(
+ (XmlElement)xmlNode, "Gigabytes")) != null)
+ {
+ gigabytes = uint.Parse(xmlChildNode.InnerText);
+ if ((xmlChildNode = XMLReader.GetNode(
+ (XmlElement)xmlNode, "NCaches")) != null)
+ {
+ nCaches = int.Parse(xmlChildNode.InnerText);
+ cacheSize = new CacheInfo(gigabytes,bytes,nCaches);
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static bool ConfigCachePriority(XmlElement xmlElem,
+ string name, ref CachePriority cachePriority, bool compulsory)
+ {
+ XmlNode xmlNode;
+ string priority;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ priority = xmlNode.InnerText;
+ if (priority == "DEFAULT")
+ cachePriority = CachePriority.DEFAULT;
+ else if (priority == "HIGH")
+ cachePriority = CachePriority.HIGH;
+ else if (priority == "LOW")
+ cachePriority = CachePriority.LOW;
+ else if (priority == "VERY_HIGH")
+ cachePriority = CachePriority.VERY_HIGH;
+ else if (priority == "VERY_LOW")
+ cachePriority = CachePriority.VERY_LOW;
+ else
+ throw new InvalidConfigException(name);
+
+ return true;
+ }
+
+ public static bool ConfigCreatePolicy(XmlElement xmlElem,
+ string name, ref CreatePolicy createPolicy, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ if (xmlNode.InnerText == "ALWAYS")
+ createPolicy = CreatePolicy.ALWAYS;
+ else if (xmlNode.InnerText == "IF_NEEDED")
+ createPolicy = CreatePolicy.IF_NEEDED;
+ else if (xmlNode.InnerText == "NEVER")
+ createPolicy = CreatePolicy.NEVER;
+ else
+ throw new InvalidConfigException(name);
+
+ return true;
+ }
+
+ public static bool ConfigDuplicatesPolicy(XmlElement xmlElem,
+ string name, ref DuplicatesPolicy duplicatePolicy,bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ if (xmlNode.InnerText == "NONE")
+ duplicatePolicy = DuplicatesPolicy.NONE;
+ else if (xmlNode.InnerText == "SORTED")
+ duplicatePolicy = DuplicatesPolicy.SORTED;
+ else if (xmlNode.InnerText == "UNSORTED")
+ duplicatePolicy = DuplicatesPolicy.UNSORTED;
+ else
+ throw new InvalidConfigException(name);
+
+ return true;
+ }
+
+ public static bool ConfigDateTime(XmlElement xmlElem,
+ string name, ref DateTime time, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ time = DateTime.Parse(xmlNode.InnerText);
+ return true;
+ }
+
+ public static bool ConfigDeadlockPolicy(XmlElement xmlElem,
+ string name, ref DeadlockPolicy deadlockPolicy, bool compulsory)
+ {
+ XmlNode xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ string policy = xmlNode.InnerText;
+ if (policy == "DEFAULT")
+ deadlockPolicy = DeadlockPolicy.DEFAULT;
+ else if (policy == "EXPIRE")
+ deadlockPolicy = DeadlockPolicy.EXPIRE;
+ else if (policy == "MAX_LOCKS")
+ deadlockPolicy = DeadlockPolicy.MAX_LOCKS;
+ else if (policy == "MAX_WRITE")
+ deadlockPolicy = DeadlockPolicy.MAX_WRITE;
+ else if (policy == "MIN_LOCKS")
+ deadlockPolicy = DeadlockPolicy.MIN_LOCKS;
+ else if (policy == "MIN_WRITE")
+ deadlockPolicy = DeadlockPolicy.MIN_WRITE;
+ else if (policy == "OLDEST")
+ deadlockPolicy = DeadlockPolicy.OLDEST;
+ else if (policy == "RANDOM")
+ deadlockPolicy = DeadlockPolicy.RANDOM;
+ else if (policy == "YOUNGEST")
+ deadlockPolicy = DeadlockPolicy.YOUNGEST;
+ else
+ throw new InvalidConfigException(name);
+ return true;
+ }
+
+ public static bool ConfigEncryption(XmlElement xmlElem,
+ string name, DatabaseConfig dbConfig, bool compulsory)
+ {
+ EncryptionAlgorithm alg;
+ XmlNode xmlNode;
+ string tmp, password;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ password = XMLReader.GetNode((XmlElement)xmlNode,
+ "password").InnerText;
+ tmp = XMLReader.GetNode((XmlElement)xmlNode, "algorithm").InnerText;
+ if (tmp == "AES")
+ alg = EncryptionAlgorithm.AES;
+ else
+ alg = EncryptionAlgorithm.DEFAULT;
+ dbConfig.SetEncryption(password, alg);
+ return true;
+ }
+
+ public static bool ConfigInt(XmlElement xmlElem,
+ string name, ref int value, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ value = int.Parse(xmlNode.InnerText);
+ return true;
+ }
+
+ public static bool ConfigIsolation(XmlElement xmlElem,
+ string name, ref Isolation value, bool compulsory)
+ {
+ XmlNode xmlNode;
+ int isolationDegree;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ isolationDegree = int.Parse(xmlNode.InnerText);
+ if (isolationDegree == 1)
+ value = Isolation.DEGREE_ONE;
+ else if (isolationDegree == 2)
+ value = Isolation.DEGREE_TWO;
+ else if (isolationDegree == 3)
+ value = Isolation.DEGREE_THREE;
+ else
+ throw new InvalidConfigException(name);
+
+ return true;
+ }
+
+ public static bool ConfigLogFlush(XmlElement xmlElem,
+ string name, ref TransactionConfig.LogFlush value,
+ bool compulsory)
+ {
+ XmlNode xmlNode;
+ string logFlush;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ logFlush = xmlNode.InnerText;
+ if (logFlush == "DEFAULT")
+ value = TransactionConfig.LogFlush.DEFAULT;
+ else if (logFlush == "NOSYNC")
+ value = TransactionConfig.LogFlush.NOSYNC;
+ else if (logFlush == "WRITE_NOSYNC")
+ value = TransactionConfig.LogFlush.WRITE_NOSYNC;
+ else if (logFlush == "SYNC")
+ value = TransactionConfig.LogFlush.SYNC;
+ else
+ throw new InvalidConfigException(name);
+
+ return true;
+ }
+
+ public static bool ConfigLong(XmlElement xmlElem,
+ string name, ref long value, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ value = long.Parse(xmlNode.InnerText);
+ return true;
+ }
+
+ public static bool ConfigMaxSequentialWrites(
+ XmlElement xmlElem, string name,
+ MPoolConfig mpoolConfig, bool compulsory)
+ {
+ XmlNode xmlNode;
+ uint pause;
+ int writes;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ pause = uint.Parse(XMLReader.GetNode(
+ (XmlElement)xmlNode, "pause").InnerText);
+ writes = int.Parse(XMLReader.GetNode(
+ (XmlElement)xmlNode,"maxWrites").InnerText);
+ mpoolConfig.SetMaxSequentialWrites(writes, pause);
+ return true;
+ }
+
+ public static bool ConfigReplicationHostAddress(
+ XmlElement xmlElem, string name,
+ ref ReplicationHostAddress address, bool compulsory)
+ {
+ XmlNode xmlNode = XMLReader.GetNode(
+ xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ address.Host = XMLReader.GetNode(
+ (XmlElement)xmlNode, "Host").InnerText;
+ address.Port = uint.Parse(XMLReader.GetNode(
+ (XmlElement)xmlNode, "Port").InnerText);
+ return true;
+ }
+
+ public static bool ConfigString(XmlElement xmlElem,
+ string name, ref string valChar, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ valChar = xmlNode.InnerText;
+ return true;
+ }
+
+ public static bool ConfigStringList(XmlElement xmlElem,
+ string name, ref List<string> strings, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ XmlNodeList list = xmlNode.ChildNodes;
+ for (int i = 0; i < list.Count; i++)
+ strings.Add(list[i].InnerText);
+
+ return true;
+ }
+
+ public static bool ConfigUint(XmlElement xmlElem,
+ string name, ref uint value, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ value = uint.Parse(xmlNode.InnerText);
+ return true;
+ }
+
+ public static bool ConfigVerboseMessages(
+ XmlElement xmlElem, string name,
+ ref VerboseMessages verbose, bool compulsory)
+ {
+ XmlNode xmlNode = XMLReader.GetNode(xmlElem,
+ name);
+ if (xmlNode == null && compulsory == false)
+ return false;
+ else if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+
+ ConfigBool((XmlElement)xmlNode, "AllFileOps",
+ ref verbose.AllFileOps, compulsory);
+ ConfigBool((XmlElement)xmlNode, "Deadlock",
+ ref verbose.Deadlock, compulsory);
+ ConfigBool((XmlElement)xmlNode, "FileOps",
+ ref verbose.FileOps, compulsory);
+ ConfigBool((XmlElement)xmlNode, "Recovery",
+ ref verbose.Recovery, compulsory);
+ ConfigBool((XmlElement)xmlNode, "Register",
+ ref verbose.Register, compulsory);
+ ConfigBool((XmlElement)xmlNode, "Replication",
+ ref verbose.Replication, compulsory);
+ ConfigBool((XmlElement)xmlNode, "ReplicationElection",
+ ref verbose.ReplicationElection, compulsory);
+ ConfigBool((XmlElement)xmlNode, "ReplicationLease",
+ ref verbose.ReplicationLease, compulsory);
+ ConfigBool((XmlElement)xmlNode, "ReplicationMessages",
+ ref verbose.ReplicationMessages, compulsory);
+ ConfigBool((XmlElement)xmlNode, "ReplicationMisc",
+ ref verbose.ReplicationMisc, compulsory);
+ ConfigBool((XmlElement)xmlNode, "ReplicationSync",
+ ref verbose.ReplicationSync, compulsory);
+ ConfigBool((XmlElement)xmlNode, "RepMgrConnectionFailure",
+ ref verbose.RepMgrConnectionFailure, compulsory);
+ ConfigBool((XmlElement)xmlNode, "RepMgrMisc",
+ ref verbose.RepMgrMisc, compulsory);
+ ConfigBool((XmlElement)xmlNode, "WaitsForTable",
+ ref verbose.WaitsForTable, compulsory);
+ return true;
+ }
+
+ #endregion Config
+
+ /*
+ * Confirm that the given value is the same with that in
+ * xml. If there is no testing data in xml and it is
+ * compulsory, the ConfigNotFoundException will be thrown.
+ * If there is no testing data and it is optional, nothing
+ * will be done. If any testing data is provided, the value
+ * will be checked.
+ */
+ #region Confirm
+ public static void ConfirmAckPolicy(XmlElement xmlElem,
+ string name, AckPolicy ackPolicy, bool compulsory)
+ {
+ XmlNode xmlNode = XMLReader.GetNode(xmlElem,
+ name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ string policy = xmlNode.InnerText;
+ if (policy == "ALL")
+ Assert.AreEqual(AckPolicy.ALL,
+ ackPolicy);
+ else if (policy == "ALL_PEERS")
+ Assert.AreEqual(AckPolicy.ALL_PEERS,
+ ackPolicy);
+ else if (policy == "NONE")
+ Assert.AreEqual(AckPolicy.NONE,
+ ackPolicy);
+ else if (policy == "ONE")
+ Assert.AreEqual(AckPolicy.ONE,
+ ackPolicy);
+ else if (policy == "ONE_PEER")
+ Assert.AreEqual(AckPolicy.ONE_PEER,
+ ackPolicy);
+ else if (policy == "QUORUM")
+ Assert.AreEqual(AckPolicy.QUORUM,
+ ackPolicy);
+ else
+ throw new InvalidConfigException(name);
+ }
+ }
+
+ public static void ConfirmBool(XmlElement xmlElem,
+ string name, bool value, bool compulsory)
+ {
+ XmlNode xmlNode;
+ bool expected;
+
+ xmlNode = XMLReader.GetNode(xmlElem,
+ name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ if (xmlNode.ChildNodes.Count > 1)
+ {
+ expected = bool.Parse(
+ xmlNode.FirstChild.NextSibling.InnerText);
+ Assert.AreEqual(expected, value);
+ }
+ }
+ }
+
+ /*
+ * If configure MACHINE, the ByteOrder in database will
+ * switch to LITTLE_ENDIAN or BIG_ENDIAN according to the
+ * current machine.
+ */
+ public static void ConfirmByteOrder(XmlElement xmlElem,
+ string name, ByteOrder byteOrder, bool compulsory)
+ {
+ XmlNode xmlNode;
+ ByteOrder specOrder;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ specOrder = ByteOrder.FromConst(int.Parse(
+ xmlNode.InnerText));
+ if (specOrder == ByteOrder.MACHINE)
+ Assert.AreNotEqual(specOrder, byteOrder);
+ else
+ Assert.AreEqual(specOrder, byteOrder);
+ }
+ }
+
+ public static void ConfirmByteMatrix(XmlElement xmlElem,
+ string name, byte[,] byteMatrix, bool compulsory)
+ {
+ int i, j, matrixLen;
+
+ XmlNode xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ /*
+ * If the length of the 2 matrixes are not
+ * the same, the matrixes are definately
+ * not equal.
+ */
+ matrixLen = xmlNode.ChildNodes.Count;
+ Assert.AreEqual(matrixLen * matrixLen,byteMatrix.Length);
+
+ /*
+ * Go over every element in the matrix to
+ * see if the same with the given xml data.
+ */
+ for (i = 0; i < matrixLen; i++)
+ {
+ if (xmlNode.ChildNodes[i].ChildNodes.Count != matrixLen)
+ throw new ConfigNotFoundException(name);
+ for (j = 0; j < matrixLen; j++)
+ Assert.AreEqual(
+ byte.Parse(xmlNode.ChildNodes[i].ChildNodes[j].InnerText),
+ byteMatrix[i, j]);
+ }
+ }
+ }
+
+ public static void ConfirmCachePriority(XmlElement xmlElem,
+ string name, CachePriority priority, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ if (xmlNode.InnerText == "DEFAULT")
+ Assert.AreEqual(CachePriority.DEFAULT, priority);
+ else if (xmlNode.InnerText == "HIGH")
+ Assert.AreEqual(CachePriority.HIGH, priority);
+ else if (xmlNode.InnerText == "LOW")
+ Assert.AreEqual(CachePriority.LOW, priority);
+ else if (xmlNode.InnerText == "VERY_HIGH")
+ Assert.AreEqual(CachePriority.VERY_HIGH, priority);
+ else if (xmlNode.InnerText == "VERY_LOW")
+ Assert.AreEqual(CachePriority.VERY_LOW, priority);
+ }
+ }
+
+ public static void ConfirmCacheSize(XmlElement xmlElem,
+ string name, CacheInfo cache, bool compulsory)
+ {
+ uint bytes;
+ uint gigabytes;
+ int nCaches;
+ XmlNode xmlNode;
+ XmlNode xmlChildNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ if ((xmlChildNode = XMLReader.GetNode(
+ (XmlElement)xmlNode, "Bytes")) != null)
+ {
+ bytes = uint.Parse(xmlChildNode.InnerText);
+ if ((xmlChildNode = XMLReader.GetNode(
+ (XmlElement)xmlNode, "Gigabytes")) != null)
+ {
+ gigabytes = uint.Parse(xmlChildNode.InnerText);
+ if ((xmlChildNode = XMLReader.GetNode(
+ (XmlElement)xmlNode,
+ "NCaches")) != null)
+ {
+ nCaches = int.Parse(xmlChildNode.InnerText);
+ Assert.LessOrEqual(bytes, cache.Bytes);
+ Assert.AreEqual(gigabytes, cache.Gigabytes);
+ Assert.AreEqual(nCaches, cache.NCaches);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * If bytes in CacheSize is assigned, the bytes in cachesize
+ * couldn't be the default one.
+ */
+ public static void ConfirmCacheSize(XmlElement xmlElem,
+ string name, CacheInfo cache, uint defaultCache,
+ bool compulsory)
+ {
+ uint bytes;
+ uint gigabytes;
+ int nCaches;
+ XmlNode xmlNode;
+ XmlNode xmlChildNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ if ((xmlChildNode = XMLReader.GetNode(
+ (XmlElement)xmlNode, "Bytes")) != null)
+ {
+ bytes = defaultCache;
+ if ((xmlChildNode = XMLReader.GetNode(
+ (XmlElement)xmlNode, "Gigabytes")) != null)
+ {
+ gigabytes = uint.Parse(xmlChildNode.InnerText);
+ if ((xmlChildNode = XMLReader.GetNode(
+ (XmlElement)xmlNode, "NCaches")) != null)
+ {
+ nCaches = int.Parse(xmlChildNode.InnerText);
+ Assert.AreNotEqual(bytes, cache.Bytes);
+ Assert.AreEqual(gigabytes, cache.Gigabytes);
+ Assert.AreEqual(nCaches, cache.NCaches);
+ }
+ }
+ }
+ }
+ }
+
+ public static void ConfirmCreatePolicy(XmlElement xmlElem,
+ string name, CreatePolicy createPolicy, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ if (xmlNode.InnerText == "ALWAYS")
+ Assert.IsTrue(createPolicy.Equals(CreatePolicy.ALWAYS));
+ else if (xmlNode.InnerText == "IF_NEEDED")
+ Assert.IsTrue(createPolicy.Equals(CreatePolicy.IF_NEEDED));
+ else if (xmlNode.InnerText == "NEVER")
+ Assert.IsTrue(createPolicy.Equals(CreatePolicy.NEVER));
+ }
+ }
+
+ public static void ConfirmDataBaseType(XmlElement xmlElem,
+ string name, DatabaseType dbType, bool compulsory)
+ {
+ XmlNode xmlNode;
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ if (xmlNode.InnerText == "BTREE")
+ Assert.AreEqual(dbType, DatabaseType.BTREE);
+ else if (xmlNode.InnerText == "HASH")
+ Assert.AreEqual(dbType, DatabaseType.HASH);
+ else if (xmlNode.InnerText == "QUEUE")
+ Assert.AreEqual(dbType, DatabaseType.QUEUE);
+ else if (xmlNode.InnerText == "RECNO")
+ Assert.AreEqual(dbType, DatabaseType.RECNO);
+ else if (xmlNode.InnerText == "UNKNOWN")
+ Assert.AreEqual(dbType, DatabaseType.UNKNOWN);
+ }
+ }
+
+ public static void ConfirmDateTime(XmlElement xmlElem,
+ string name, DateTime time, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ Assert.AreEqual(DateTime.Parse(
+ xmlNode.InnerText), time);
+ }
+
+ public static void ConfirmDeadlockPolicy(XmlElement xmlElem,
+ string name, DeadlockPolicy deadlockPolicy, bool compulsory)
+ {
+ XmlNode xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ string policy = xmlNode.InnerText;
+ if (policy == "DEFAULT")
+ Assert.AreEqual(DeadlockPolicy.DEFAULT, deadlockPolicy);
+ else if (policy == "EXPIRE")
+ Assert.AreEqual(DeadlockPolicy.EXPIRE, deadlockPolicy);
+ else if (policy == "MAX_LOCKS")
+ Assert.AreEqual(DeadlockPolicy.MAX_LOCKS, deadlockPolicy);
+ else if (policy == "MAX_WRITE")
+ Assert.AreEqual(DeadlockPolicy.MAX_WRITE, deadlockPolicy);
+ else if (policy == "MIN_LOCKS")
+ Assert.AreEqual(DeadlockPolicy.MIN_LOCKS, deadlockPolicy);
+ else if (policy == "MIN_WRITE")
+ Assert.AreEqual(DeadlockPolicy.MIN_WRITE, deadlockPolicy);
+ else if (policy == "OLDEST")
+ Assert.AreEqual(DeadlockPolicy.OLDEST, deadlockPolicy);
+ else if (policy == "RANDOM")
+ Assert.AreEqual(DeadlockPolicy.RANDOM, deadlockPolicy);
+ else if (policy == "YOUNGEST")
+ Assert.AreEqual(DeadlockPolicy.YOUNGEST, deadlockPolicy);
+ else
+ throw new InvalidConfigException(name);
+ }
+ }
+
+ public static void ConfirmDuplicatesPolicy(
+ XmlElement xmlElem, string name,
+ DuplicatesPolicy duplicatedPolicy, bool compulsory)
+ {
+ XmlNode xmlNode;
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ if (xmlNode.InnerText == "NONE")
+ Assert.AreEqual(duplicatedPolicy, DuplicatesPolicy.NONE);
+ else if (xmlNode.InnerText == "SORTED")
+ Assert.AreEqual(duplicatedPolicy, DuplicatesPolicy.SORTED);
+ else if (xmlNode.InnerText == "UNSORTED")
+ Assert.AreEqual(duplicatedPolicy, DuplicatesPolicy.UNSORTED);
+ }
+ }
+
+ public static void ConfirmEncryption(XmlElement xmlElem,
+ string name, string dPwd, EncryptionAlgorithm dAlg, bool compulsory)
+ {
+ EncryptionAlgorithm alg;
+ XmlNode xmlNode = XMLReader.GetNode(xmlElem,
+ name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ string password = XMLReader.GetNode(
+ (XmlElement)xmlNode, "password").InnerText;
+ string tmp = XMLReader.GetNode(
+ (XmlElement)xmlNode, "algorithm").InnerText;
+ if (tmp == "AES")
+ alg = EncryptionAlgorithm.AES;
+ else
+ alg = EncryptionAlgorithm.DEFAULT;
+ Assert.AreEqual(dAlg, alg);
+ Assert.AreEqual(dPwd, dPwd);
+ }
+ }
+
+ public static void ConfirmInt(XmlElement xmlElem,
+ string name, int value, bool compulsory)
+ {
+ XmlNode xmlNode;
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ Assert.AreEqual(int.Parse(xmlNode.InnerText), value);
+ }
+
+ public static void ConfirmIsolation(XmlElement xmlElem,
+ string name, Isolation value, bool compulsory)
+ {
+ XmlNode xmlNode;
+ int isolationDegree;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ isolationDegree = int.Parse(xmlNode.InnerText);
+ if (isolationDegree == 1)
+ Assert.AreEqual(Isolation.DEGREE_ONE, value);
+ else if (isolationDegree == 2)
+ Assert.AreEqual(Isolation.DEGREE_TWO, value);
+ else if (isolationDegree == 3)
+ Assert.AreEqual(Isolation.DEGREE_THREE, value);
+ else
+ throw new InvalidConfigException(name);
+ }
+ }
+
+ public static void ConfirmLogFlush(XmlElement xmlElem,
+ string name, TransactionConfig.LogFlush value,
+ bool compulsory)
+ {
+ XmlNode xmlNode;
+ string logFlush;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ logFlush = xmlNode.InnerText;
+ if (logFlush == "DEFAULT")
+ Assert.AreEqual(TransactionConfig.LogFlush.DEFAULT, value);
+ else if (logFlush == "NOSYNC")
+ Assert.AreEqual(TransactionConfig.LogFlush.NOSYNC, value);
+ else if (logFlush == "WRITE_NOSYNC")
+ Assert.AreEqual(TransactionConfig.LogFlush.WRITE_NOSYNC, value);
+ else if (logFlush == "SYNC")
+ Assert.AreEqual(TransactionConfig.LogFlush.SYNC, value);
+ else
+ throw new InvalidConfigException(name);
+ }
+ }
+
+ public static void ConfirmLong(XmlElement xmlElem,
+ string name, long value, bool compulsory)
+ {
+ XmlNode xmlNode;
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ Assert.AreEqual(long.Parse(xmlNode.InnerText), value);
+ }
+
+ public static void ConfirmMaxSequentialWrites(
+ XmlElement xmlElem, string name,
+ uint mPause, int mWrites, bool compulsory)
+ {
+ XmlNode xmlNode;
+ uint pause;
+ int writes;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ writes = int.Parse(XMLReader.GetNode(
+ (XmlElement)xmlNode, "maxWrites").InnerText);
+ pause = uint.Parse(XMLReader.GetNode(
+ (XmlElement)xmlNode, "pause").InnerText);
+
+ Assert.AreEqual(mPause, pause);
+ Assert.AreEqual(mWrites, writes);
+ }
+ }
+
+ public static void ConfirmReplicationHostAddress(
+ XmlElement xmlElem, string name,
+ ReplicationHostAddress address, bool compulsory)
+ {
+ XmlNode xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ string host = XMLReader.GetNode(
+ (XmlElement)xmlNode, "Host").InnerText;
+ uint port = uint.Parse(XMLReader.GetNode(
+ (XmlElement)xmlNode, "Port").InnerText);
+
+ Assert.AreEqual(host, address.Host);
+ Assert.AreEqual(port, address.Port);
+ }
+ }
+
+ public static void ConfirmString(XmlElement xmlElem,
+ string name, string str, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ if (str != null)
+ {
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ if (xmlNode.HasChildNodes)
+ Assert.AreEqual(
+ xmlNode.FirstChild.InnerText, str);
+ }
+ }
+ }
+
+ public static void ConfirmStringList(XmlElement xmlElem,
+ string name, List<string> strings, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ if (strings != null)
+ {
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ if (xmlNode.HasChildNodes)
+ {
+ XmlNodeList list = xmlNode.ChildNodes;
+ for (int i = 0; i < xmlNode.ChildNodes.Count;i++)
+ Assert.IsTrue(
+ strings.Contains(list[i].InnerText));
+ }
+ }
+ }
+ }
+
+ public static void ConfirmUint(XmlElement xmlElem,
+ string name, uint value, bool compulsory)
+ {
+ XmlNode xmlNode;
+
+ xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ Assert.AreEqual(uint.Parse(xmlNode.InnerText), value);
+ }
+
+ public static void ConfirmVerboseMessages(
+ XmlElement xmlElem, string name,
+ VerboseMessages verbose, bool compulsory)
+ {
+ XmlNode xmlNode = XMLReader.GetNode(xmlElem, name);
+ if (xmlNode == null && compulsory == true)
+ throw new ConfigNotFoundException(name);
+ else if (xmlNode != null)
+ {
+ ConfirmBool((XmlElement)xmlNode, "AllFileOps",
+ verbose.AllFileOps, compulsory);
+ ConfirmBool((XmlElement)xmlNode, "Deadlock",
+ verbose.Deadlock, compulsory);
+ ConfirmBool((XmlElement)xmlNode, "FileOps",
+ verbose.FileOps, compulsory);
+ ConfirmBool((XmlElement)xmlNode, "Recovery",
+ verbose.Recovery, compulsory);
+ ConfirmBool((XmlElement)xmlNode, "Register",
+ verbose.Register, compulsory);
+ ConfirmBool((XmlElement)xmlNode, "Replication",
+ verbose.Replication, compulsory);
+ ConfirmBool((XmlElement)xmlNode, "ReplicationElection",
+ verbose.ReplicationElection, compulsory);
+ ConfirmBool((XmlElement)xmlNode, "ReplicationLease",
+ verbose.ReplicationLease, compulsory);
+ ConfirmBool((XmlElement)xmlNode, "ReplicationMessages",
+ verbose.ReplicationMessages, compulsory);
+ ConfirmBool((XmlElement)xmlNode, "ReplicationMisc",
+ verbose.ReplicationMisc, compulsory);
+ ConfirmBool((XmlElement)xmlNode, "ReplicationSync",
+ verbose.ReplicationSync, compulsory);
+ ConfirmBool((XmlElement)xmlNode, "RepMgrConnectionFailure",
+ verbose.RepMgrConnectionFailure, compulsory);
+ ConfirmBool((XmlElement)xmlNode, "RepMgrMisc",
+ verbose.RepMgrMisc, compulsory);
+ ConfirmBool((XmlElement)xmlNode,"WaitsForTable",
+ verbose.WaitsForTable, compulsory);
+ }
+ }
+ #endregion Confirm
+
+ public static void dbtFromString(DatabaseEntry dbt, string s)
+ {
+ dbt.Data = System.Text.Encoding.ASCII.GetBytes(s);
+ }
+
+ public static string strFromDBT(DatabaseEntry dbt)
+ {
+
+ System.Text.ASCIIEncoding decode = new ASCIIEncoding();
+ return decode.GetString(dbt.Data);
+ }
+
+ /*
+ * Reading params successfully returns true. Unless returns
+ * false. The retrieved Xml fragment is returning in xmlElem.
+ */
+ public static XmlElement TestSetUp(string testFixtureName, string testName)
+ {
+ XMLReader xmlReader = new XMLReader("../../AllTestData.xml");
+ XmlElement xmlElem = xmlReader.GetXmlElement(testFixtureName, testName);
+ if (xmlElem == null)
+ throw new ConfigNotFoundException(testFixtureName + ":" + testName);
+ else
+ return xmlElem;
+ }
+
+ /*
+ * Delete existing test output directory and its files,
+ * then create a new one.
+ */
+ public static void ClearDir(string testDir)
+ {
+ if (Directory.Exists(testDir))
+ Directory.Delete(testDir, true);
+ Directory.CreateDirectory(testDir);
+ }
+ }
+}
diff --git a/test/scr037/CursorConfigTest.cs b/test/scr037/CursorConfigTest.cs
new file mode 100644
index 0000000..1f586dc
--- /dev/null
+++ b/test/scr037/CursorConfigTest.cs
@@ -0,0 +1,81 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class CursorConfigTest
+ {
+ private string testFixtureName;
+ private string testFixtureHome;
+ private string testName;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "CursorConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+ }
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+ /*
+ * Configure the fields/properties and see if
+ * they are updated successfully.
+ */
+ CursorConfig cursorConfig = new CursorConfig();
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ Config(xmlElem, ref cursorConfig, true);
+ Confirm(xmlElem, cursorConfig, true);
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ CursorConfig cursorConfig, bool compulsory)
+ {
+ Configuration.ConfirmIsolation(xmlElement,
+ "IsolationDegree", cursorConfig.IsolationDegree,
+ compulsory);
+ Configuration.ConfirmCachePriority(xmlElement,
+ "Priority", cursorConfig.Priority,
+ compulsory);
+ Configuration.ConfirmBool(xmlElement,
+ "SnapshotIsolation", cursorConfig.SnapshotIsolation,
+ compulsory);
+ Configuration.ConfirmBool(xmlElement,
+ "WriteCursor", cursorConfig.WriteCursor,
+ compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref CursorConfig cursorConfig, bool compulsory)
+ {
+ Configuration.ConfigIsolation(xmlElement,
+ "IsolationDegree", ref cursorConfig.IsolationDegree,
+ compulsory);
+ Configuration.ConfigCachePriority(xmlElement,
+ "Priority", ref cursorConfig.Priority, compulsory);
+ Configuration.ConfigBool(xmlElement,
+ "SnapshotIsolation", ref cursorConfig.SnapshotIsolation,
+ compulsory);
+ Configuration.ConfigBool(xmlElement,
+ "WriteCursor", ref cursorConfig.WriteCursor,
+ compulsory);
+ }
+ }
+}
diff --git a/test/scr037/CursorTest.cs b/test/scr037/CursorTest.cs
new file mode 100644
index 0000000..ec12dec
--- /dev/null
+++ b/test/scr037/CursorTest.cs
@@ -0,0 +1,1459 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class CursorTest
+ {
+ private string testFixtureName;
+ private string testFixtureHome;
+ private string testName;
+ private string testHome;
+ private DatabaseEnvironment paramEnv;
+ private BTreeDatabase paramDB;
+ private Transaction readTxn;
+ private Transaction updateTxn;
+
+ private EventWaitHandle signal;
+
+ private delegate void CursorMoveFuncDelegate(
+ Cursor cursor, LockingInfo lockingInfo);
+ private CursorMoveFuncDelegate cursorFunc;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "CursorTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+ }
+
+ [Test]
+ public void TestAdd()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestAdd";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database and a cursor.
+ GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+
+ // Add a record and confirm that it exists.
+ AddOneByCursor(db, cursor);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestCompare() {
+ BTreeDatabase db;
+ BTreeCursor dbc1, dbc2;
+ DatabaseEntry data, key;
+
+ testName = "TestCompare";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database and a cursor. Then close it.
+ GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out dbc1);
+ dbc2 = db.Cursor();
+
+ for (int i = 0; i < 10; i++) {
+ key = new DatabaseEntry(BitConverter.GetBytes(i));
+ data = new DatabaseEntry(BitConverter.GetBytes(i));
+ db.Put(key, data);
+ }
+ key = new DatabaseEntry(BitConverter.GetBytes(5));
+ Assert.IsTrue(dbc1.Move(key, true));
+ Assert.IsTrue(dbc2.Move(key, true));
+ Assert.IsTrue(dbc1.Compare(dbc2));
+ Assert.IsTrue(dbc1.MoveNext());
+ Assert.IsFalse(dbc1.Compare(dbc2));
+ dbc1.Close();
+ dbc2.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestClose()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestClose";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database and a cursor. Then close it.
+ GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestCount()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestCount";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Write one record into database with cursor.
+ GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+ AddOneByCursor(db, cursor);
+
+ /*
+ * Confirm that that the count operation returns 1 as
+ * the number of records in the database.
+ */
+ Assert.AreEqual(1, cursor.Count());
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestCurrent()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestCurrent";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Write a record into database with cursor.
+ GetCursorInBtreeDBWithoutEnv(testHome,
+ testName, out db, out cursor);
+ AddOneByCursor(db, cursor);
+
+ /*
+ * Confirm the current record that the cursor
+ * points to is the one that just added by the
+ * cursor.
+ */
+ Assert.IsTrue(cursor.MoveFirst());
+ Assert.AreEqual(
+ ASCIIEncoding.ASCII.GetBytes("key"),
+ cursor.Current.Key.Data);
+ Assert.AreEqual(
+ ASCIIEncoding.ASCII.GetBytes("data"),
+ cursor.Current.Value.Data);
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestDelete()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestDelete";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Write a record into database with cursor.
+ GetCursorInBtreeDBWithoutEnv(testHome,
+ testName, out db, out cursor);
+ AddOneByCursor(db, cursor);
+
+ // Delete the current record.
+ cursor.Delete();
+
+ // Confirm that the record no longer exists in the db.
+ Assert.AreEqual(0, cursor.Count());
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestDispose()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestDispose";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Write a record into database with cursor.
+ GetCursorInBtreeDBWithoutEnv(testHome,
+ testName, out db, out cursor);
+
+ // Dispose the cursor.
+ cursor.Dispose();
+
+ db.Close();
+ }
+
+ [Test]
+ public void TestIsolationDegree()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ CursorConfig cursorConfig;
+ DatabaseEnvironment env;
+ Transaction txn;
+
+ testName = "TestIsolationDegree";
+ testHome = testFixtureHome + "/" + testName;
+
+ Isolation[] isolationDegrees = new Isolation[3];
+ isolationDegrees[0] = Isolation.DEGREE_ONE;
+ isolationDegrees[1] = Isolation.DEGREE_TWO;
+ isolationDegrees[2] = Isolation.DEGREE_THREE;
+
+ IsolationDelegate[] delegates = {
+ new IsolationDelegate(CursorReadUncommited),
+ new IsolationDelegate(CursorReadCommited),
+ new IsolationDelegate(CursorRead)};
+
+ cursorConfig = new CursorConfig();
+ for (int i = 0; i < 3; i++)
+ {
+ cursorConfig.IsolationDegree = isolationDegrees[i];
+ GetCursorInBtreeDBInTDS(testHome + "/" + i.ToString(),
+ testName, cursorConfig, out env, out db,
+ out cursor, out txn);
+ cursor.Close();
+ db.Close();
+ txn.Commit();
+ env.Close();
+ }
+ }
+
+ public delegate void IsolationDelegate(
+ DatabaseEnvironment env, BTreeDatabase db,
+ Cursor cursor, Transaction txn);
+
+ /*
+ * Configure a transactional cursor to have degree 2
+ * isolation, which permits data read by this cursor
+ * to be deleted prior to the commit of the transaction
+ * for this cursor.
+ */
+ public void CursorReadCommited(
+ DatabaseEnvironment env, BTreeDatabase db,
+ Cursor cursor, Transaction txn)
+ {
+ Console.WriteLine("CursorReadCommited");
+ }
+
+ /*
+ * Configure a transactional cursor to have degree 1
+ * isolation. The cursor's read operations could return
+ * modified but not yet commited data.
+ */
+ public void CursorReadUncommited(
+ DatabaseEnvironment env, BTreeDatabase db,
+ Cursor cursor, Transaction txn)
+ {
+ Console.WriteLine("CursorReadUncommited");
+ }
+
+ /*
+ * Only return committed data.
+ */
+ public void CursorRead(
+ DatabaseEnvironment env, BTreeDatabase db,
+ Cursor cursor, Transaction txn)
+ {
+ Console.WriteLine("CursorRead");
+ }
+
+
+ [Test]
+ public void TestMoveToExactKey()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestMoveToExactKey";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ GetCursorInBtreeDBWithoutEnv(testHome,
+ testName, out db, out cursor);
+
+ // Add one record into database.
+ DatabaseEntry key = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ DatabaseEntry data = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair =
+ new KeyValuePair<DatabaseEntry,DatabaseEntry>(key, data);
+ cursor.Add(pair);
+
+ // Move the cursor exactly to the specified key.
+ MoveCursor(cursor, false);
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveToExactPair()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+ DatabaseEntry key, data;
+
+ testName = "TestMoveToExactPair";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ GetCursorInBtreeDBWithoutEnv(testHome,
+ testName, out db, out cursor);
+
+ // Add one record into database.
+ key = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair =
+ new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
+ cursor.Add(pair);
+
+ // Move the cursor exactly to the specified key/data pair.
+ MoveCursor(cursor, true);
+ cursor.Close();
+ db.Close();
+
+ }
+
+ [Test]
+ public void TestMoveWithRMW()
+ {
+ testName = "TestMoveWithRMW";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ // Use MoveCursor() as its move function.
+ cursorFunc = new CursorMoveFuncDelegate(MoveCursor);
+
+ // Move to a specified key and a key/data pair.
+ MoveWithRMW(testHome, testName);
+ }
+
+ [Test]
+ public void TestMoveFirst()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestMoveFirst";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+ AddOneByCursor(db, cursor);
+
+ // Move to the first record.
+ MoveCursorToFirst(cursor, null);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveFirstWithRMW()
+ {
+ testName = "TestMoveFirstWithRMW";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ // Use MoveCursorToFirst() as its move function.
+ cursorFunc = new CursorMoveFuncDelegate(MoveCursorToFirst);
+
+ // Read the first record with write lock.
+ MoveWithRMW(testHome, testName);
+ }
+
+ [Test]
+ public void TestMoveLast()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestMoveLast";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+ AddOneByCursor(db, cursor);
+
+ // Move the cursor to the last record.
+ MoveCursorToLast(cursor, null);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveLastWithRMW()
+ {
+ testName = "TestMoveLastWithRMW";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ // Use MoveCursorToLast() as its move function.
+ cursorFunc = new CursorMoveFuncDelegate(MoveCursorToLast);
+
+ // Read the last recod with write lock.
+ MoveWithRMW(testHome, testName);
+ }
+
+ [Test]
+ public void TestMoveNext()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestMoveCursorToNext";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+
+ // Put ten records to the database.
+ for (int i = 0; i < 10; i++)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+
+ // Move the cursor from the first record to the fifth.
+ MoveCursorToNext(cursor, null);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveNextWithRMW()
+ {
+ testName = "TestMoveLastWithRMW";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ // Use MoveCursorToNext() as its move function.
+ cursorFunc = new CursorMoveFuncDelegate(
+ MoveCursorToNext);
+
+ /*
+ * Read the first record to the fifth record with
+ * write lock.
+ */
+ MoveWithRMW(testHome, testName);
+ }
+
+ [Test]
+ public void TestMoveNextDuplicate()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestMoveNextDuplicate";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+
+ // Add ten duplicate records to the database.
+ for (int i = 0; i < 10; i++)
+ db.Put(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(
+ BitConverter.GetBytes(i)));
+
+ /*
+ * Move the cursor from one duplicate record to
+ * another duplicate one.
+ */
+ MoveCursorToNextDuplicate(cursor, null);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveNextDuplicateWithRMW()
+ {
+ testName = "TestMoveNextDuplicateWithRMW";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Use MoveCursorToNextDuplicate() as its
+ * move function.
+ */
+ cursorFunc = new CursorMoveFuncDelegate(
+ MoveCursorToNextDuplicate);
+
+ /*
+ * Read the first record to the fifth record with
+ * write lock.
+ */
+ MoveWithRMW(testHome, testName);
+ }
+
+
+ [Test]
+ public void TestMoveNextUnique()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestMoveNextUnique";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+
+ // Add ten different records to the database.
+ for (int i = 0; i < 10; i++)
+ db.Put(new DatabaseEntry(
+ BitConverter.GetBytes(i)),
+ new DatabaseEntry(
+ BitConverter.GetBytes(i)));
+
+ // Move to five unique records.
+ MoveCursorToNextUnique(cursor, null);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveNextUniqueWithRMW()
+ {
+ testName = "TestMoveNextUniqueWithRMW";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Use MoveCursorToNextUnique() as its
+ * move function.
+ */
+ cursorFunc = new CursorMoveFuncDelegate(
+ MoveCursorToNextUnique);
+
+ /*
+ * Move to five unique records.
+ */
+ MoveWithRMW(testHome, testName);
+ }
+
+ [Test]
+ public void TestMovePrev()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestMovePrev";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+
+ // Add ten records to the database.
+ for (int i = 0; i < 10; i++)
+ AddOneByCursor(db, cursor);
+
+ // Move the cursor to previous five records
+ MoveCursorToPrev(cursor, null);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMovePrevWithRMW()
+ {
+ testName = "TestMovePrevWithRMW";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Use MoveCursorToNextDuplicate() as its
+ * move function.
+ */
+ cursorFunc = new CursorMoveFuncDelegate(
+ MoveCursorToPrev);
+
+ // Read previous record in write lock.
+ MoveWithRMW(testHome, testName);
+ }
+
+
+ [Test]
+ public void TestMovePrevDuplicate()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestMovePrevDuplicate";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+
+ // Add ten records to the database.
+ for (int i = 0; i < 10; i++)
+ AddOneByCursor(db, cursor);
+
+ // Move the cursor to previous duplicate records.
+ MoveCursorToPrevDuplicate(cursor, null);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMovePrevDuplicateWithRMW()
+ {
+ testName = "TestMovePrevDuplicateWithRMW";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Use MoveCursorToNextDuplicate() as its
+ * move function.
+ */
+ cursorFunc = new CursorMoveFuncDelegate(
+ MoveCursorToPrevDuplicate);
+
+ // Read the previous duplicate record in write lock.
+ MoveWithRMW(testHome, testName);
+ }
+
+
+ [Test]
+ public void TestMovePrevUnique()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestMovePrevUnique";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+
+ // Add ten records to the database.
+ for (int i = 0; i < 10; i++)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+
+ // Move the cursor to previous unique records.
+ MoveCursorToPrevUnique(cursor, null);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMovePrevUniqueWithRMW()
+ {
+ testName = "TestMovePrevDuplicateWithRMW";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Use MoveCursorToPrevUnique() as its
+ * move function.
+ */
+ cursorFunc = new CursorMoveFuncDelegate(
+ MoveCursorToPrevUnique);
+
+ // Read the previous unique record in write lock.
+ MoveWithRMW(testHome, testName);
+ }
+
+ [Test]
+ public void TestPriority()
+ {
+ BTreeCursor cursor;
+ BTreeDatabase db;
+ CachePriority[] priorities;
+ CursorConfig cursorConfig;
+ DatabaseEnvironment env;
+
+ cursorConfig = new CursorConfig();
+
+ priorities = new CachePriority[5];
+ priorities[0] = CachePriority.DEFAULT;
+ priorities[1] = CachePriority.HIGH;
+ priorities[2] = CachePriority.LOW;
+ priorities[3] = CachePriority.VERY_HIGH;
+ priorities[4] = CachePriority.VERY_LOW;
+
+ testName = "TestPriority";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ for (int i = 0; i < 5; i++)
+ {
+ // Configure the cursor priority.
+ cursorConfig.Priority = priorities[i];
+
+ // Open a database to test a specified priority.
+ GetCursorInBtreeDBInCDS(testHome, testName,
+ cursorConfig, out env, out db, out cursor);
+ Assert.AreEqual(priorities[i], cursorConfig.Priority);
+ cursor.Close();
+ db.Close();
+ env.Close();
+ }
+ }
+
+ [Test]
+ public void TestRefresh()
+ {
+ BTreeDatabase db;
+ BTreeCursor cursor;
+
+ testName = "TestRefresh";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ GetCursorInBtreeDBWithoutEnv(testHome, testName,
+ out db, out cursor);
+
+ // Write a record with cursor and Refresh the cursor.
+ MoveCursorToCurrentRec(cursor, null);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestRefreshWithRMW()
+ {
+ testName = "TestRefreshWithRMW";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ cursorFunc = new CursorMoveFuncDelegate(
+ MoveCursorToCurrentRec);
+
+ // Read the previous unique record in write lock.
+ MoveWithRMW(testHome, testName);
+ }
+
+ [Test]
+ public void TestSnapshotIsolation()
+ {
+ BTreeDatabaseConfig dbConfig;
+ DatabaseEntry key, data;
+ DatabaseEnvironmentConfig envConfig;
+ Thread readThread, updateThread;
+ Transaction txn;
+
+ updateTxn = null;
+ readTxn = null;
+ paramDB = null;
+ paramEnv = null;
+ testName = "TestSnapshotIsolation";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open environment with DB_MULTIVERSION
+ * which is required by DB_TXN_SNAPSHOT.
+ */
+ envConfig = new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseMVCC = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ envConfig.UseLocking = true;
+ envConfig.TxnTimeout = 1000;
+ paramEnv = DatabaseEnvironment.Open(
+ testHome, envConfig);
+ paramEnv.DetectDeadlocks(DeadlockPolicy.YOUNGEST);
+
+ /*
+ * Open a transactional database and put 1000 records
+ * into it within transaction.
+ */
+ txn = paramEnv.BeginTransaction();
+ dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.UseMVCC = true;
+ dbConfig.Env = paramEnv;
+ paramDB = BTreeDatabase.Open(
+ testName + ".db", dbConfig, txn);
+ for (int i = 0; i < 256; i++)
+ {
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ paramDB.Put(key, data, txn);
+ }
+ txn.Commit();
+
+ /*
+ * Begin two threads, read and update thread.
+ * The update thread runs a update transaction
+ * using full read/write locking. The read thread
+ * set DB_TXN_SNAPSHOT on read-only cursor.
+ */
+ readThread = new Thread(new ThreadStart(ReadTxn));
+ updateThread = new Thread(new ThreadStart(UpdateTxn));
+ updateThread.Start();
+ Thread.Sleep(1000);
+ readThread.Start();
+ readThread.Join();
+ updateThread.Join();
+
+ // Commit transacion in both two threads.
+ if (updateTxn != null)
+ updateTxn.Commit();
+ if (readTxn != null)
+ readTxn.Commit();
+
+ /*
+ * Confirm that the overwrite operation works.
+ */
+ ConfirmOverwrite();
+
+ paramDB.Close();
+ paramEnv.Close();
+ }
+
+ public void ReadTxn()
+ {
+ // Get a new transaction for reading the db.
+ TransactionConfig txnConfig =
+ new TransactionConfig();
+ txnConfig.Snapshot = true;
+ readTxn = paramEnv.BeginTransaction(
+ txnConfig);
+
+ // Get a new cursor for putting record into db.
+ CursorConfig cursorConfig = new CursorConfig();
+ cursorConfig.WriteCursor = false;
+ BTreeCursor cursor = paramDB.Cursor(
+ cursorConfig, readTxn);
+
+ // Continually reading record from db.
+ try
+ {
+ Assert.IsTrue(cursor.MoveFirst());
+ int i = 0;
+ do
+ {
+ Assert.AreEqual(
+ BitConverter.ToInt32(
+ cursor.Current.Key.Data, 0),
+ BitConverter.ToInt32(
+ cursor.Current.Value.Data, 0));
+ } while (i <= 1000 && cursor.MoveNext());
+ }
+ catch (DeadlockException)
+ {
+ }
+ finally
+ {
+ cursor.Close();
+ }
+ }
+
+ public void UpdateTxn()
+ {
+ int int32Value;
+ DatabaseEntry data;
+
+ // Get a new transaction for updating the db.
+ TransactionConfig txnConfig =
+ new TransactionConfig();
+ txnConfig.IsolationDegree =
+ Isolation.DEGREE_THREE;
+
+ updateTxn =
+ paramEnv.BeginTransaction(txnConfig);
+
+ // Continually putting record to db.
+
+ BTreeCursor cursor =
+ paramDB.Cursor(updateTxn);
+
+ // Move the cursor to the first record.
+ Assert.IsTrue(cursor.MoveFirst());
+ int i = 0;
+ try
+ {
+ do
+ {
+
+ int32Value = BitConverter.ToInt32(
+ cursor.Current.Value.Data, 0);
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(int32Value - 1));
+ cursor.Overwrite(data);
+ } while (i <= 1000 && cursor.MoveNext());
+ }
+ catch (DeadlockException)
+ {
+ }
+ finally
+ {
+ cursor.Close();
+ }
+ }
+
+
+ [Test]
+ public void TestWriteCursor()
+ {
+ BTreeCursor cursor;
+ BTreeDatabase db;
+ CursorConfig cursorConfig;
+ DatabaseEnvironment env;
+
+ testName = "TestWriteCursor";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ cursorConfig = new CursorConfig();
+ cursorConfig.WriteCursor = true;
+
+ GetCursorInBtreeDBInCDS(testHome, testName,
+ cursorConfig, out env, out db, out cursor);
+
+ /*
+ * Add a record by cursor to the database. If the
+ * WriteCursor doesn't work, exception will be
+ * throwed in the environment which is configured
+ * with DB_INIT_CDB.
+ */
+ try
+ {
+ AddOneByCursor(db, cursor);
+ }
+ catch (DatabaseException)
+ {
+ throw new TestException();
+ }
+ finally
+ {
+ cursor.Close();
+ db.Close();
+ env.Close();
+ }
+ }
+
+ public void ConfirmOverwrite()
+ {
+ Transaction confirmTxn = paramEnv.BeginTransaction();
+ BTreeCursor cursor = paramDB.Cursor(confirmTxn);
+
+ int i = 0;
+ Assert.IsTrue(cursor.MoveFirst());
+ do
+ {
+ Assert.AreNotEqual(
+ cursor.Current.Key.Data,
+ cursor.Current.Value.Data);
+ } while (i <= 1000 && cursor.MoveNext());
+
+ cursor.Close();
+ confirmTxn.Commit();
+ }
+
+ public static void AddOneByCursor(Database db, Cursor cursor)
+ {
+ DatabaseEntry key, data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+
+ // Add a record to db via cursor.
+ key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key"));
+ data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data"));
+ pair = new KeyValuePair<DatabaseEntry,DatabaseEntry>(key, data);
+ cursor.Add(pair);
+
+ // Confirm that the record has been put to the database.
+ Assert.IsTrue(db.Exists(key));
+ }
+
+
+ public static void GetCursorInBtreeDBWithoutEnv(
+ string home, string name, out BTreeDatabase db,
+ out BTreeCursor cursor)
+ {
+ string dbFileName = home + "/" + name + ".db";
+
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ db = BTreeDatabase.Open(dbFileName, dbConfig);
+ cursor = db.Cursor();
+ }
+
+ public static void GetCursorInBtreeDBInTDS(
+ string home, string name,
+ CursorConfig cursorConfig,
+ out DatabaseEnvironment env, out BTreeDatabase db,
+ out BTreeCursor cursor, out Transaction txn)
+ {
+ string dbFileName = name + ".db";
+
+ Configuration.ClearDir(home);
+
+ // Open an environment.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ envConfig.NoMMap = false;
+ envConfig.UseLocking = true;
+ env = DatabaseEnvironment.Open(home, envConfig);
+
+ // Begin a transaction.
+ txn = env.BeginTransaction();
+
+ /*
+ * Open an btree database. The underlying database
+ * should be opened with ReadUncommitted if the
+ * cursor's isolation degree will be set to be 1.
+ */
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ if (cursorConfig.IsolationDegree == Isolation.DEGREE_ONE)
+ dbConfig.ReadUncommitted = true;
+
+ db = BTreeDatabase.Open(dbFileName, dbConfig, txn);
+
+ // Get a cursor in the transaction.
+ cursor = db.Cursor(cursorConfig, txn);
+ }
+
+ // Get a cursor in CDS.
+ public static void GetCursorInBtreeDBInCDS(
+ string home, string name,
+ CursorConfig cursorConfig,
+ out DatabaseEnvironment env, out BTreeDatabase db,
+ out BTreeCursor cursor)
+ {
+ string dbFileName = name + ".db";
+
+ // Open an environment.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseCDB = true;
+ envConfig.UseMPool = true;
+ env = DatabaseEnvironment.Open(home, envConfig);
+
+ /*
+ * Open an btree database. The underlying database
+ * should be opened with ReadUncommitted if the
+ * cursor's isolation degree will be set to be 1.
+ */
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+
+ if (cursorConfig.IsolationDegree == Isolation.DEGREE_ONE)
+ dbConfig.ReadUncommitted = true;
+
+ db = BTreeDatabase.Open(dbFileName, dbConfig);
+
+ // Get a cursor in the transaction.
+ cursor = db.Cursor(cursorConfig);
+ }
+
+ public void RdMfWt()
+ {
+ Transaction txn = paramEnv.BeginTransaction();
+ Cursor dbc = paramDB.Cursor(txn);
+
+ try
+ {
+ LockingInfo lck = new LockingInfo();
+ lck.ReadModifyWrite = true;
+
+ // Read record.
+ cursorFunc(dbc, lck);
+
+ // Block the current thread until event is set.
+ signal.WaitOne();
+
+ // Write new records into database.
+ DatabaseEntry key = new DatabaseEntry(
+ BitConverter.GetBytes(55));
+ DatabaseEntry data = new DatabaseEntry(
+ BitConverter.GetBytes(55));
+ dbc.Add(new KeyValuePair<DatabaseEntry,
+ DatabaseEntry>(key, data));
+
+ dbc.Close();
+ txn.Commit();
+ }
+ catch (DeadlockException)
+ {
+ dbc.Close();
+ txn.Abort();
+ }
+ }
+
+
+ public void MoveWithRMW(string home, string name)
+ {
+ paramEnv = null;
+ paramDB = null;
+
+ // Open the environment.
+ DatabaseEnvironmentConfig envCfg =
+ new DatabaseEnvironmentConfig();
+ envCfg.Create = true;
+ envCfg.FreeThreaded = true;
+ envCfg.UseLocking = true;
+ envCfg.UseLogging = true;
+ envCfg.UseMPool = true;
+ envCfg.UseTxns = true;
+ paramEnv = DatabaseEnvironment.Open(home, envCfg);
+
+ // Open database in transaction.
+ Transaction openTxn = paramEnv.BeginTransaction();
+ BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
+ cfg.Creation = CreatePolicy.ALWAYS;
+ cfg.Env = paramEnv;
+ cfg.FreeThreaded = true;
+ cfg.PageSize = 4096;
+ cfg.Duplicates = DuplicatesPolicy.UNSORTED;
+ paramDB = BTreeDatabase.Open(name + ".db", cfg, openTxn);
+ openTxn.Commit();
+
+ /*
+ * Put 10 different, 2 duplicate and another different
+ * records into database.
+ */
+ Transaction txn = paramEnv.BeginTransaction();
+ for (int i = 0; i < 13; i++)
+ {
+ DatabaseEntry key, data;
+ if (i == 10 || i == 11)
+ {
+ key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ }
+ else
+ {
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ }
+ paramDB.Put(key, data, txn);
+ }
+
+ txn.Commit();
+
+ // Get a event wait handle.
+ signal = new EventWaitHandle(false, EventResetMode.ManualReset);
+
+ /*
+ * Start RdMfWt() in two threads. RdMfWt() reads
+ * and writes data into database.
+ */
+ Thread t1 = new Thread(new ThreadStart(RdMfWt));
+ Thread t2 = new Thread(new ThreadStart(RdMfWt));
+ t1.Start();
+ t2.Start();
+
+ /*
+ * Give both threads time to read before signalling
+ * them to write.
+ */
+ Thread.Sleep(1000);
+
+ // Invoke the write operation in both threads.
+ signal.Set();
+
+ // Return the number of deadlocks.
+ while (t1.IsAlive || t2.IsAlive)
+ {
+ /*
+ * Give both threads time to write before
+ * counting the number of deadlocks.
+ */
+ Thread.Sleep(1000);
+ uint deadlocks = paramEnv.DetectDeadlocks(
+ DeadlockPolicy.DEFAULT);
+
+ // Confirm that there won't be any deadlock.
+ Assert.AreEqual(0, deadlocks);
+ }
+
+ t1.Join();
+ t2.Join();
+ paramDB.Close();
+ paramEnv.Close();
+ }
+
+ /*
+ * Move the cursor to an exisiting key or key/data pair.
+ */
+ public void MoveCursor(Cursor dbc, bool ifPair)
+ {
+ DatabaseEntry key, data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+
+ key = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ if (ifPair == false)
+ Assert.IsTrue(dbc.Move(key, true));
+ else
+ {
+ data = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ pair = new KeyValuePair<DatabaseEntry,
+ DatabaseEntry>(key, data);
+ Assert.IsTrue(dbc.Move(pair, true));
+ }
+ }
+
+ /*
+ * Move the cursor to an exisiting key and key/data
+ * pair with LockingInfo.
+ */
+ public void MoveCursor(Cursor dbc, LockingInfo lck)
+ {
+ DatabaseEntry key, data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+
+ key = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ data = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ pair = new KeyValuePair<DatabaseEntry,
+ DatabaseEntry>(key, data);
+
+ // Move to an existing key.
+ Assert.IsTrue(dbc.Move(key, true, lck));
+
+ // Move to an existing key/data pair.
+ Assert.IsTrue(dbc.Move(pair, true, lck));
+ }
+
+ /*
+ * Move the cursor to the first record in a nonempty
+ * database. The returning value should be true.
+ */
+ public void MoveCursorToFirst(Cursor dbc, LockingInfo lck)
+ {
+ if (lck == null)
+ Assert.IsTrue(dbc.MoveFirst());
+ else
+ Assert.IsTrue(dbc.MoveFirst(lck));
+ }
+
+ /*
+ * Move the cursor to last record in a nonempty
+ * database. The returning value should be true.
+ */
+ public void MoveCursorToLast(Cursor dbc, LockingInfo lck)
+ {
+ if (lck == null)
+ Assert.IsTrue(dbc.MoveLast());
+ else
+ Assert.IsTrue(dbc.MoveLast(lck));
+ }
+
+ /*
+ * Move the cursor to the next record in the database
+ * with more than five records. The returning values of
+ * every move operation should be true.
+ */
+ public void MoveCursorToNext(Cursor dbc, LockingInfo lck)
+ {
+ for (int i = 0; i < 5; i++)
+ if (lck == null)
+ Assert.IsTrue(dbc.MoveNext());
+ else
+ Assert.IsTrue(dbc.MoveNext(lck));
+ }
+
+ /*
+ * Move the cursor to the next duplicate record in
+ * the database which has more than 2 duplicate
+ * records. The returning value should be true.
+ */
+ public void MoveCursorToNextDuplicate(Cursor dbc,
+ LockingInfo lck)
+ {
+ DatabaseEntry key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+
+ /*
+ * The cursor should point to any record in the
+ * database before it move to the next duplicate
+ * record.
+ */
+ if (lck == null)
+ {
+ dbc.Move(key, true);
+ Assert.IsTrue(dbc.MoveNextDuplicate());
+ }
+ else
+ {
+ /*
+ * Both the move and move next duplicate
+ * operation should use LockingInfo. If any
+ * one doesn't use LockingInfo, deadlock still
+ * occurs.
+ */
+ dbc.Move(key, true, lck);
+ Assert.IsTrue(dbc.MoveNextDuplicate(lck));
+ }
+ }
+
+ /*
+ * Move the cursor to next unique record in the database.
+ * The returning value should be true.
+ */
+ public void MoveCursorToNextUnique(Cursor dbc,
+ LockingInfo lck)
+ {
+ for (int i = 0; i < 5; i++)
+ {
+ if (lck == null)
+ Assert.IsTrue(dbc.MoveNextUnique());
+ else
+ Assert.IsTrue(dbc.MoveNextUnique(lck));
+ }
+ }
+
+ /*
+ * Move the cursor to previous record in the database.
+ * The returning value should be true;
+ */
+ public void MoveCursorToPrev(Cursor dbc,
+ LockingInfo lck)
+ {
+ if (lck == null)
+ {
+ dbc.MoveLast();
+ for (int i = 0; i < 5; i++)
+ Assert.IsTrue(dbc.MovePrev());
+ }
+ else
+ {
+ dbc.MoveLast(lck);
+ for (int i = 0; i < 5; i++)
+ Assert.IsTrue(dbc.MovePrev(lck));
+ }
+
+ }
+
+ /*
+ * Move the cursor to a duplicate record and then to
+ * another duplicate one. And finally move to it previous
+ * one. Since the previous duplicate one exist, the return
+ * value of move previous duplicate record should be
+ * true;
+ */
+ public void MoveCursorToPrevDuplicate(Cursor dbc,
+ LockingInfo lck)
+ {
+ if (lck == null)
+ {
+ dbc.Move(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key")), true);
+ dbc.MoveNextDuplicate();
+ Assert.IsTrue(dbc.MovePrevDuplicate());
+ }
+ else
+ {
+ dbc.Move(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key")),true, lck);
+ dbc.MoveNextDuplicate(lck);
+ Assert.IsTrue(dbc.MovePrevDuplicate(lck));
+ }
+ }
+
+ /*
+ * Move the cursor to previous unique record in a
+ * database with more than 2 records. The returning
+ * value should be true.
+ */
+ public void MoveCursorToPrevUnique(Cursor dbc,
+ LockingInfo lck)
+ {
+ for (int i = 0; i < 5; i++)
+ if (lck == null)
+ dbc.MovePrevUnique();
+ else
+ dbc.MovePrevUnique(lck);
+ }
+
+ /*
+ * Move the cursor to current existing record. The returning
+ * value should be true.
+ */
+ public void MoveCursorToCurrentRec(Cursor dbc,
+ LockingInfo lck)
+ {
+ // Add a record to the database.
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ pair = new KeyValuePair<DatabaseEntry,DatabaseEntry>(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")));
+ dbc.Add(pair);
+
+ if (lck == null)
+ dbc.Refresh();
+ else
+ dbc.Refresh(lck);
+
+ Assert.IsNotNull(dbc.Current.Key);
+ }
+ }
+}
diff --git a/test/scr037/DatabaseConfigTest.cs b/test/scr037/DatabaseConfigTest.cs
new file mode 100644
index 0000000..8b1c01f
--- /dev/null
+++ b/test/scr037/DatabaseConfigTest.cs
@@ -0,0 +1,109 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class DatabaseConfigTest
+ {
+ [Test]
+ virtual public void TestConfigWithoutEnv()
+ {
+ string testName = "TestConfigWithoutEnv";
+ string testFixtureName = "DatabaseConfigTest";
+
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ DatabaseConfig dbConfig = new DatabaseConfig();
+ Config(xmlElem, ref dbConfig, true);
+ Confirm(xmlElem, dbConfig, true);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref DatabaseConfig dbConfig, bool compulsory)
+ {
+ uint pageSize = new uint();
+
+ Configuration.ConfigBool(xmlElement, "AutoCommit",
+ ref dbConfig.AutoCommit, compulsory);
+ Configuration.ConfigByteOrder(xmlElement, "ByteOrder",
+ ref dbConfig.ByteOrder, compulsory);
+ Configuration.ConfigCacheInfo(xmlElement, "CacheSize",
+ ref dbConfig.CacheSize, compulsory);
+ Configuration.ConfigBool(xmlElement, "DoChecksum",
+ ref dbConfig.DoChecksum, compulsory);
+ Configuration.ConfigString(xmlElement, "ErrorPrefix",
+ ref dbConfig.ErrorPrefix, compulsory);
+ Configuration.ConfigBool(xmlElement, "FreeThreaded",
+ ref dbConfig.FreeThreaded, compulsory);
+ Configuration.ConfigBool(xmlElement, "NoMMap",
+ ref dbConfig.NoMMap, compulsory);
+ Configuration.ConfigBool(xmlElement, "NonDurableTxns",
+ ref dbConfig.NonDurableTxns, compulsory);
+ if (Configuration.ConfigUint(xmlElement, "PageSize",
+ ref pageSize, compulsory))
+ dbConfig.PageSize = pageSize;
+ Configuration.ConfigCachePriority(xmlElement,
+ "Priority", ref dbConfig.Priority, compulsory);
+ Configuration.ConfigBool(xmlElement, "ReadOnly",
+ ref dbConfig.ReadOnly, compulsory);
+ Configuration.ConfigBool(xmlElement, "ReadUncommitted",
+ ref dbConfig.ReadUncommitted, compulsory);
+ Configuration.ConfigEncryption(xmlElement,
+ "Encryption", dbConfig, compulsory);
+ Configuration.ConfigBool(xmlElement, "Truncate",
+ ref dbConfig.Truncate, compulsory);
+ Configuration.ConfigBool(xmlElement, "UseMVCC",
+ ref dbConfig.UseMVCC, compulsory);
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ DatabaseConfig dbConfig, bool compulsory)
+ {
+ Configuration.ConfirmBool(xmlElement, "AutoCommit",
+ dbConfig.AutoCommit, compulsory);
+ Configuration.ConfirmByteOrder(xmlElement, "ByteOrder",
+ dbConfig.ByteOrder, compulsory);
+ Configuration.ConfirmCacheSize(xmlElement, "CacheSize",
+ dbConfig.CacheSize, compulsory);
+ Configuration.ConfirmBool(xmlElement, "DoChecksum",
+ dbConfig.DoChecksum, compulsory);
+ Configuration.ConfirmEncryption(xmlElement, "Encryption",
+ dbConfig.EncryptionPassword,
+ dbConfig.EncryptAlgorithm, compulsory);
+ Configuration.ConfirmString(xmlElement, "ErrorPrefix",
+ dbConfig.ErrorPrefix, compulsory);
+ Configuration.ConfirmBool(xmlElement, "FreeThreaded",
+ dbConfig.FreeThreaded, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoMMap",
+ dbConfig.NoMMap, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NonDurableTxns",
+ dbConfig.NonDurableTxns, compulsory);
+ Configuration.ConfirmUint(xmlElement, "PageSize",
+ dbConfig.PageSize, compulsory);
+ Configuration.ConfirmCachePriority(xmlElement,
+ "Priority", dbConfig.Priority, compulsory);
+ Configuration.ConfirmBool(xmlElement, "ReadOnly",
+ dbConfig.ReadOnly, compulsory);
+ Configuration.ConfirmBool(xmlElement, "ReadUncommitted",
+ dbConfig.ReadUncommitted, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Truncate",
+ dbConfig.Truncate, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseMVCC",
+ dbConfig.UseMVCC, compulsory);
+ }
+ }
+}
+
diff --git a/test/scr037/DatabaseEnvironmentConfigTest.cs b/test/scr037/DatabaseEnvironmentConfigTest.cs
new file mode 100644
index 0000000..f092ae4
--- /dev/null
+++ b/test/scr037/DatabaseEnvironmentConfigTest.cs
@@ -0,0 +1,299 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using BerkeleyDB;
+using NUnit.Framework;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class DatabaseEnvironmentConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "DatabaseEnvironmentConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ Config(xmlElem, ref envConfig, true);
+ Confirm(xmlElem, envConfig, true);
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ DatabaseEnvironmentConfig envConfig, bool compulsory)
+ {
+ Configuration.ConfirmBool(xmlElement, "AutoCommit",
+ envConfig.AutoCommit, compulsory);
+ Configuration.ConfirmBool(xmlElement, "CDB_ALLDB",
+ envConfig.CDB_ALLDB, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Create",
+ envConfig.Create, compulsory);
+ Configuration.ConfirmStringList(xmlElement, "DataDirs",
+ envConfig.DataDirs, compulsory);
+ Configuration.ConfirmString(xmlElement, "ErrorPrefix",
+ envConfig.ErrorPrefix, compulsory);
+ Configuration.ConfirmBool(xmlElement, "ForceFlush",
+ envConfig.ForceFlush, compulsory);
+ Configuration.ConfirmBool(xmlElement, "FreeThreaded",
+ envConfig.FreeThreaded, compulsory);
+ Configuration.ConfirmBool(xmlElement, "InitRegions",
+ envConfig.InitRegions, compulsory);
+ Configuration.ConfirmString(xmlElement,
+ "IntermediateDirMode",
+ envConfig.IntermediateDirMode, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Lockdown",
+ envConfig.Lockdown, compulsory);
+ Configuration.ConfirmUint(xmlElement, "LockTimeout",
+ envConfig.LockTimeout, compulsory);
+ Configuration.ConfirmUint(xmlElement, "MaxTransactions",
+ envConfig.MaxTransactions, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoBuffer",
+ envConfig.NoBuffer, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoLocking",
+ envConfig.NoLocking, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoMMap",
+ envConfig.NoMMap, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoLocking",
+ envConfig.NoLocking, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoPanic",
+ envConfig.NoPanic, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Overwrite",
+ envConfig.Overwrite, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Private",
+ envConfig.Private, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Register",
+ envConfig.Register, compulsory);
+ Configuration.ConfirmBool(xmlElement, "RunFatalRecovery",
+ envConfig.RunFatalRecovery, compulsory);
+ Configuration.ConfirmBool(xmlElement, "RunRecovery",
+ envConfig.RunRecovery, compulsory);
+ Configuration.ConfirmBool(xmlElement, "SystemMemory",
+ envConfig.SystemMemory, compulsory);
+ Configuration.ConfirmString(xmlElement, "TempDir",
+ envConfig.TempDir, compulsory);
+ Configuration.ConfirmBool(xmlElement, "TimeNotGranted",
+ envConfig.TimeNotGranted, compulsory);
+ Configuration.ConfirmBool(xmlElement, "TxnNoSync",
+ envConfig.TxnNoSync, compulsory);
+ Configuration.ConfirmBool(xmlElement, "TxnNoWait",
+ envConfig.TxnNoWait, compulsory);
+ Configuration.ConfirmBool(xmlElement, "TxnSnapshot",
+ envConfig.TxnSnapshot, compulsory);
+ Configuration.ConfirmDateTime(xmlElement,"TxnTimestamp",
+ envConfig.TxnTimestamp, compulsory);
+ Configuration.ConfirmBool(xmlElement, "TxnWriteNoSync",
+ envConfig.TxnWriteNoSync, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseCDB",
+ envConfig.UseCDB, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseLocking",
+ envConfig.UseLocking, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseLogging",
+ envConfig.UseLogging, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseMPool",
+ envConfig.UseMPool, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseMVCC",
+ envConfig.UseMVCC, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseReplication",
+ envConfig.UseReplication, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseTxns",
+ envConfig.UseTxns, compulsory);
+ envConfig.Verbosity = new VerboseMessages();
+ Configuration.ConfirmVerboseMessages(xmlElement,
+ "Verbosity", envConfig.Verbosity, compulsory);
+ Configuration.ConfirmBool(xmlElement, "YieldCPU",
+ envConfig.YieldCPU, compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref DatabaseEnvironmentConfig envConfig, bool compulsory)
+ {
+ uint value = new uint();
+ DateTime time = new DateTime();
+
+ Configuration.ConfigBool(xmlElement, "AutoCommit",
+ ref envConfig.AutoCommit, compulsory);
+ Configuration.ConfigBool(xmlElement, "CDB_ALLDB",
+ ref envConfig.CDB_ALLDB, compulsory);
+ Configuration.ConfigBool(xmlElement, "Create",
+ ref envConfig.Create, compulsory);
+ Configuration.ConfigString(xmlElement, "CreationDir",
+ ref envConfig.CreationDir, compulsory);
+ Configuration.ConfigStringList(xmlElement, "DataDirs",
+ ref envConfig.DataDirs, compulsory);
+ Configuration.ConfigString(xmlElement, "ErrorPrefix",
+ ref envConfig.ErrorPrefix, compulsory);
+ Configuration.ConfigBool(xmlElement, "ForceFlush",
+ ref envConfig.ForceFlush, compulsory);
+ Configuration.ConfigBool(xmlElement, "FreeThreaded",
+ ref envConfig.FreeThreaded, compulsory);
+ Configuration.ConfigBool(xmlElement, "InitRegions",
+ ref envConfig.InitRegions, compulsory);
+ Configuration.ConfigString(xmlElement, "IntermediateDirMode",
+ ref envConfig.IntermediateDirMode, compulsory);
+ Configuration.ConfigBool(xmlElement, "Lockdown",
+ ref envConfig.Lockdown, compulsory);
+ if (Configuration.ConfigUint(xmlElement, "LockTimeout",
+ ref value, compulsory))
+ envConfig.LockTimeout = value;
+ if (Configuration.ConfigUint(xmlElement, "MaxTransactions",
+ ref value, compulsory))
+ envConfig.MaxTransactions = value;
+ Configuration.ConfigBool(xmlElement, "NoBuffer",
+ ref envConfig.NoBuffer, compulsory);
+ Configuration.ConfigBool(xmlElement, "NoLocking",
+ ref envConfig.NoLocking, compulsory);
+ Configuration.ConfigBool(xmlElement, "NoMMap",
+ ref envConfig.NoMMap, compulsory);
+ Configuration.ConfigBool(xmlElement, "NoLocking",
+ ref envConfig.NoLocking, compulsory);
+ Configuration.ConfigBool(xmlElement, "NoPanic",
+ ref envConfig.NoPanic, compulsory);
+ Configuration.ConfigBool(xmlElement, "Overwrite",
+ ref envConfig.Overwrite, compulsory);
+ Configuration.ConfigBool(xmlElement, "Private",
+ ref envConfig.Private, compulsory);
+ Configuration.ConfigBool(xmlElement, "Register",
+ ref envConfig.Register, compulsory);
+ Configuration.ConfigBool(xmlElement, "RunFatalRecovery",
+ ref envConfig.RunFatalRecovery, compulsory);
+ Configuration.ConfigBool(xmlElement, "RunRecovery",
+ ref envConfig.RunRecovery, compulsory);
+ Configuration.ConfigBool(xmlElement, "SystemMemory",
+ ref envConfig.SystemMemory, compulsory);
+ Configuration.ConfigString(xmlElement, "TempDir",
+ ref envConfig.TempDir, compulsory);
+ Configuration.ConfigBool(xmlElement, "TimeNotGranted",
+ ref envConfig.TimeNotGranted, compulsory);
+ Configuration.ConfigBool(xmlElement, "TxnNoSync",
+ ref envConfig.TxnNoSync, compulsory);
+ Configuration.ConfigBool(xmlElement, "TxnNoWait",
+ ref envConfig.TxnNoWait, compulsory);
+ Configuration.ConfigBool(xmlElement, "TxnSnapshot",
+ ref envConfig.TxnSnapshot, compulsory);
+ if (Configuration.ConfigDateTime(xmlElement, "TxnTimestamp",
+ ref time, compulsory))
+ envConfig.TxnTimestamp = time;
+ Configuration.ConfigBool(xmlElement, "TxnWriteNoSync",
+ ref envConfig.TxnWriteNoSync, compulsory);
+ Configuration.ConfigBool(xmlElement, "UseLocking",
+ ref envConfig.UseLocking, compulsory);
+ Configuration.ConfigBool(xmlElement, "UseLogging",
+ ref envConfig.UseLogging, compulsory);
+ Configuration.ConfigBool(xmlElement, "UseMPool",
+ ref envConfig.UseMPool, compulsory);
+ Configuration.ConfigBool(xmlElement, "UseMVCC",
+ ref envConfig.UseMVCC, compulsory);
+ Configuration.ConfigBool(xmlElement, "UseReplication",
+ ref envConfig.UseReplication, compulsory);
+ Configuration.ConfigBool(xmlElement, "UseTxns",
+ ref envConfig.UseTxns, compulsory);
+ envConfig.Verbosity = new VerboseMessages();
+ Configuration.ConfigVerboseMessages(xmlElement,
+ "Verbosity", ref envConfig.Verbosity, compulsory);
+ Configuration.ConfigBool(xmlElement, "YieldCPU",
+ ref envConfig.YieldCPU, compulsory);
+ }
+
+ [Test]
+ public void TestConfigLock()
+ {
+ testName = "TestConfigLock";
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.LockSystemCfg = new LockingConfig();
+ LockingConfigTest.Config(xmlElem,
+ ref cfg.LockSystemCfg, true);
+ LockingConfigTest.Confirm(xmlElem,
+ cfg.LockSystemCfg, true);
+ }
+
+ [Test]
+ public void TestConfigLog()
+ {
+ testName = "TestConfigLog";
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.LogSystemCfg = new LogConfig();
+ LogConfigTest.Config(xmlElem, ref cfg.LogSystemCfg, true);
+ LogConfigTest.Confirm(xmlElem, cfg.LogSystemCfg, true);
+ }
+
+ [Test]
+ public void TestConfigMutex()
+ {
+ testName = "TestConfigMutex";
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.MutexSystemCfg = new MutexConfig();
+ MutexConfigTest.Config(xmlElem, ref cfg.MutexSystemCfg, true);
+ MutexConfigTest.Confirm(xmlElem, cfg.MutexSystemCfg, true);
+ }
+
+ [Test]
+ public void TestConfigReplication()
+ {
+ testName = "TestConfigReplication";
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.RepSystemCfg = new ReplicationConfig();
+ ReplicationConfigTest.Config(xmlElem,
+ ref cfg.RepSystemCfg, true);
+ ReplicationConfigTest.Confirm(xmlElem,
+ cfg.RepSystemCfg, true);
+ }
+
+ [Test]
+ public void TestSetEncryption()
+ {
+ testName = "TestSetEncryption";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.SetEncryption("key", EncryptionAlgorithm.AES);
+ Assert.AreEqual("key", envConfig.EncryptionPassword);
+ Assert.AreEqual(EncryptionAlgorithm.AES, envConfig.EncryptAlgorithm);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+ Assert.AreEqual(EncryptionAlgorithm.AES, env.EncryptAlgorithm);
+ env.Close();
+ }
+
+ }
+}
+
diff --git a/test/scr037/DatabaseEnvironmentTest.cs b/test/scr037/DatabaseEnvironmentTest.cs
new file mode 100644
index 0000000..570bdc2
--- /dev/null
+++ b/test/scr037/DatabaseEnvironmentTest.cs
@@ -0,0 +1,1778 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class DatabaseEnvironmentTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ private DatabaseEnvironment testBeginTransactionEnv;
+ private BTreeDatabase testBeginTransactionDB;
+
+ private DatabaseEnvironment testCheckpointEnv;
+ private BTreeDatabase testCheckpointDB;
+
+ private DatabaseEnvironment testDetectDeadlocksEnv;
+ private BTreeDatabase testDetectDeadlocksDB;
+
+ private DatabaseEnvironment testFailCheckEnv;
+
+ private EventWaitHandle signal;
+
+ [TestFixtureSetUp]
+ public void SetUp()
+ {
+ testFixtureName = "DatabaseEnvironmentTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+ try
+ {
+ Configuration.ClearDir(testFixtureHome);
+ }
+ catch (Exception)
+ {
+ throw new TestException(
+ "Please clean the directory");
+ }
+ }
+
+ [Test]
+ public void TestArchivableDatabaseFiles()
+ {
+ testName = "TestArchivableDatabaseFiles";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName1 = testName + "1.db";
+ string dbFileName2 = testName + "2.db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open an environment.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.AutoCommit = true;
+ envConfig.Create = true;
+ envConfig.UseMPool = true;
+ envConfig.UseLogging = true;
+ envConfig.UseTxns = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ // Open two databases.
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ BTreeDatabase db1 = BTreeDatabase.Open(dbFileName1, dbConfig);
+ db1.Close();
+ BTreeDatabase db2 = BTreeDatabase.Open(dbFileName2, dbConfig);
+ db2.Close();
+
+ /*
+ * Get all database files name in the environment.
+ * Two database file name should be returned and
+ * the same as the ones when opening the databases.
+ */
+ List<string> dbFiles = env.ArchivableDatabaseFiles(false);
+ Assert.AreEqual(2, dbFiles.Count);
+ Assert.IsTrue(dbFiles.Contains(dbFileName1));
+ Assert.IsTrue(dbFiles.Contains(dbFileName2));
+
+ /*
+ * Get all database file's abosolute path in the
+ * environment. Confirm those files exist.
+ */
+ List<string> dbFilesPath = env.ArchivableDatabaseFiles(true);
+ Assert.IsTrue(File.Exists(dbFilesPath[0]));
+ Assert.IsTrue(File.Exists(dbFilesPath[1]));
+
+ env.Close();
+ }
+
+ [Test]
+ public void TestArchivableLogFiles()
+ {
+ testName = "TestArchivableLogFiles";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open an environment.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.AutoCommit = true;
+ envConfig.Create = true;
+ envConfig.UseMPool = true;
+ envConfig.UseLogging = true;
+ envConfig.UseTxns = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ // Open a databases.
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ BTreeDatabase db = BTreeDatabase.Open(
+ dbFileName, dbConfig);
+
+ /*
+ * Put 1000 records into the database to generate
+ * more than one log files.
+ */
+ byte[] byteArr = new byte[1024];
+ for (int i = 0; i < 1000; i++)
+ db.Put(new DatabaseEntry(
+ BitConverter.GetBytes(i)),
+ new DatabaseEntry(byteArr));
+
+ db.Close();
+
+ List<string> logFiles = env.ArchivableLogFiles(false);
+
+ List<string> logFilesPath =
+ env.ArchivableLogFiles(true);
+ for (int i = 0; i < logFilesPath.Count; i++)
+ Assert.IsTrue(File.Exists(logFilesPath[i]));
+
+ env.Close();
+ }
+
+ [Test]
+ public void TestBeginCDSGroup()
+ {
+ testName = "TestBeginCDSGroup";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.Create = true;
+ cfg.UseCDB = true;
+ cfg.UseMPool = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, cfg);
+ Transaction txn = env.BeginCDSGroup();
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ BTreeDatabase db = BTreeDatabase.Open(
+ testName + ".db", dbConfig, txn);
+ db.Put(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data")), txn);
+ db.Close();
+ txn.Commit();
+ env.Close();
+ }
+
+ [Test]
+ public void TestBeginTransaction()
+ {
+ testName = "TestBeginTransaction";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open an environment.
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.Create = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.UseLogging = true;
+ cfg.UseLocking = true;
+ cfg.NoLocking = false;
+ cfg.FreeThreaded = true;
+ testBeginTransactionEnv = DatabaseEnvironment.Open(testHome, cfg);
+ testBeginTransactionEnv.DeadlockResolution = DeadlockPolicy.OLDEST;
+
+ // Open btree database.
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.AutoCommit = true;
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = testBeginTransactionEnv;
+ dbConfig.Duplicates = DuplicatesPolicy.NONE;
+ dbConfig.FreeThreaded = true;
+ testBeginTransactionDB = BTreeDatabase.Open(
+ testName + ".db", dbConfig);
+
+ testBeginTransactionDB.Put(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
+
+ // Begin two threads to run dead lock detection.
+ Thread thread1 = new Thread(new ThreadStart(
+ DeadLockThreadWithLockTimeOut));
+ Thread thread2 = new Thread(new ThreadStart(
+ DeadLockThreadWithTxnTimeout));
+ signal = new EventWaitHandle(false, EventResetMode.ManualReset);
+ thread1.Start();
+ thread2.Start();
+ Thread.Sleep(1000);
+ signal.Set();
+ thread1.Join();
+ thread2.Join();
+
+ // Close all.
+ testBeginTransactionDB.Close();
+ testBeginTransactionEnv.Close();
+ }
+
+ public void DeadLockThreadWithLockTimeOut()
+ {
+ // Configure and begin a transaction.
+ TransactionConfig txnConfig = new TransactionConfig();
+ txnConfig.LockTimeout = 5000;
+ txnConfig.Name = "DeadLockThreadWithLockTimeOut";
+ Transaction txn =
+ testBeginTransactionEnv.BeginTransaction(txnConfig, null);
+ try
+ {
+ testBeginTransactionDB.Put(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
+ signal.WaitOne();
+ testBeginTransactionDB.Put(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("newkey")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("newdata")),
+ txn);
+ txn.Commit();
+ }
+ catch (DeadlockException)
+ {
+ try
+ {
+ txn.Abort();
+ }
+ catch (DatabaseException)
+ {
+ throw new TestException();
+ }
+ }
+ catch (DatabaseException)
+ {
+ try
+ {
+ txn.Abort();
+ }
+ catch (DatabaseException)
+ {
+ throw new TestException();
+ }
+ }
+ }
+
+ public void DeadLockThreadWithTxnTimeout()
+ {
+ // Configure and begin a transaction.
+ TransactionConfig txnConfig = new TransactionConfig();
+ txnConfig.TxnTimeout = 5000;
+ txnConfig.Name = "DeadLockThreadWithTxnTimeout";
+ Transaction txn =
+ testBeginTransactionEnv.BeginTransaction(txnConfig, null);
+ try
+ {
+ testBeginTransactionDB.Put(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
+ signal.WaitOne();
+ testBeginTransactionDB.Put(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("newkey")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("newdata")),
+ txn);
+ txn.Commit();
+ }
+ catch (DeadlockException)
+ {
+ try
+ {
+ txn.Abort();
+ }
+ catch (DatabaseException)
+ {
+ throw new TestException();
+ }
+ }
+ catch (DatabaseException)
+ {
+ try
+ {
+ txn.Abort();
+ }
+ catch (DatabaseException)
+ {
+ throw new TestException();
+ }
+ }
+ }
+
+ [Test]
+ public void TestCheckpoint()
+ {
+ testName = "TestCheckpoint";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open an environment.
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.Create = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.UseLogging = true;
+ cfg.UseLocking = true;
+ cfg.NoLocking = false;
+ cfg.FreeThreaded = true;
+ testCheckpointEnv = DatabaseEnvironment.Open(testHome, cfg);
+
+ // Open btree database.
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.AutoCommit = true;
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = testCheckpointEnv;
+ dbConfig.FreeThreaded = true;
+ testCheckpointDB = BTreeDatabase.Open(testName + ".db", dbConfig);
+
+
+ // Run a thread to put records into database.
+ Thread thread1 = new Thread(new ThreadStart(PutRecordsThread));
+
+ /*
+ * Run a thread to do checkpoint periodically and
+ * finally do a checkpoint to flush all in memory pool
+ * to log files.
+ */
+ Thread thread2 = new Thread(new ThreadStart(CheckpointThread));
+
+ thread1.Start();
+ thread2.Start();
+ thread1.Join();
+ thread2.Join();
+
+ // Close all.
+ testCheckpointDB.Close();
+ testCheckpointEnv.Close();
+ }
+
+ public void PutRecordsThread()
+ {
+ Transaction txn = testCheckpointEnv.BeginTransaction();
+ byte[] byteArr = new byte[1024];
+ for (int i = 0; i < 1000; i++)
+ testCheckpointDB.Put(
+ new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(byteArr), txn);
+ txn.Commit();
+ }
+
+ public void CheckpointThread()
+ {
+ uint bytes = 64;
+ uint minutes = 1;
+ uint count = 1;
+ while (count < 3)
+ {
+ testCheckpointEnv.Checkpoint(bytes, minutes);
+ count++;
+ }
+ Thread.Sleep(500);
+ testCheckpointEnv.Checkpoint();
+ }
+
+ [Test]
+ public void TestClose()
+ {
+ testName = "TestClose";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.Create = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, cfg);
+ env.Close();
+ }
+
+ [Test]
+ public void TestConfigAll()
+ {
+ testName = "TestConfigAll";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+
+ /*
+ * Open a new environment with all properties,
+ * fields and subsystems configured.
+ */
+ DatabaseEnvironmentConfig envConig =
+ new DatabaseEnvironmentConfig();
+ Config(xmlElem, ref envConig, true, true, true,
+ true, true, true);
+
+ // Configure with methods.
+ ReplicationHostAddress address =
+ new ReplicationHostAddress("127.0.0.0", 11111);
+ envConig.RepSystemCfg.Clockskew(102, 100);
+ envConig.RepSystemCfg.RetransmissionRequest(10, 100);
+ envConig.RepSystemCfg.TransmitLimit(1, 1024);
+
+ // Open the environment.
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConig);
+
+ // Confirm environment status with its configuration.
+ Confirm(xmlElem, env, true, true, true, true, true, true);
+
+ // Print statistics of the current environment.
+ env.PrintStats(true, true);
+
+ // Print statistics of all subsytems.
+ env.PrintSubsystemStats(true, true);
+
+ env.Close();
+ }
+
+ [Test]
+ public void TestDeadlockPolicy()
+ {
+ testName = "TestDeadlockPolicy";
+ testHome = testFixtureHome + "/" + testName;
+
+ DetectDeadlockPolicy(testHome + "_DEFAULT",
+ DeadlockPolicy.DEFAULT);
+
+ DetectDeadlockPolicy(testHome + "_EXPIRE",
+ DeadlockPolicy.EXPIRE);
+ DetectDeadlockPolicy(testHome + "_MAX_LOCKS",
+ DeadlockPolicy.MAX_LOCKS);
+ DetectDeadlockPolicy(testHome + "_MAX_WRITE",
+ DeadlockPolicy.MAX_WRITE);
+ DetectDeadlockPolicy(testHome + "_MIN_LOCKS",
+ DeadlockPolicy.MIN_LOCKS);
+ DetectDeadlockPolicy(testHome + "_MIN_WRITE",
+ DeadlockPolicy.MIN_WRITE);
+ DetectDeadlockPolicy(testHome + "_OLDEST",
+ DeadlockPolicy.OLDEST);
+ DetectDeadlockPolicy(testHome + "_RANDOM",
+ DeadlockPolicy.RANDOM);
+ DetectDeadlockPolicy(testHome + "_YOUNGEST",
+ DeadlockPolicy.YOUNGEST);
+ }
+
+ public void DetectDeadlockPolicy(
+ string home, DeadlockPolicy deadlock)
+ {
+ Configuration.ClearDir(home);
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseLocking = true;
+ envConfig.UseLogging = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConfig);
+ env.DeadlockResolution = deadlock;
+ Assert.AreEqual(deadlock, env.DeadlockResolution);
+ env.DetectDeadlocks(deadlock);
+ env.Close();
+ }
+
+ [Test]
+ public void TestDetectDeadlocks()
+ {
+ testName = "TestDetectDeadlocks";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open an environment.
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.Create = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.UseLogging = true;
+ cfg.UseLocking = true;
+ cfg.FreeThreaded = true;
+ testDetectDeadlocksEnv = DatabaseEnvironment.Open(
+ testHome, cfg);
+
+ // Open btree database.
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.AutoCommit = true;
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = testDetectDeadlocksEnv;
+ dbConfig.Duplicates = DuplicatesPolicy.NONE;
+ dbConfig.FreeThreaded = true;
+ testDetectDeadlocksDB = BTreeDatabase.Open(
+ testName + ".db", dbConfig);
+
+ // Put one record("key", "data") into database.
+ testDetectDeadlocksDB.Put(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
+
+ // Begin two threads to read and write record.
+ Thread thread1 = new Thread(new ThreadStart(ReadAndPutRecordThread));
+ Thread thread2 = new Thread(new ThreadStart(ReadAndPutRecordThread));
+ signal = new EventWaitHandle(false, EventResetMode.ManualReset);
+ thread1.Start();
+ thread2.Start();
+
+ // Give enough time for threads to read record.
+ Thread.Sleep(1000);
+
+ /*
+ * Let the two threads apply for write lock
+ * synchronously.
+ */
+ signal.Set();
+
+ // Confirm that there is deadlock in the environment.
+ Thread.Sleep(1000);
+ uint deadlockNum = testDetectDeadlocksEnv.DetectDeadlocks(
+ DeadlockPolicy.DEFAULT);
+ Assert.Less(0, deadlockNum);
+
+ thread1.Join();
+ thread2.Join();
+
+ // Close all.
+ testDetectDeadlocksDB.Close(false);
+ testDetectDeadlocksEnv.Close();
+ }
+
+ public void ReadAndPutRecordThread()
+ {
+ Transaction txn =
+ testDetectDeadlocksEnv.BeginTransaction();
+ try
+ {
+ testDetectDeadlocksDB.GetBoth(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")), txn);
+ signal.WaitOne();
+ testDetectDeadlocksDB.Put(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("newKey")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("newData")),
+ txn);
+ txn.Commit();
+ }
+ catch (DeadlockException)
+ {
+ txn.Abort();
+ }
+ }
+
+ [Test]
+ public void TestFailCheck()
+ {
+ testName = "TestFailCheck";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.Create = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.UseLogging = true;
+ cfg.UseLocking = true;
+ cfg.FreeThreaded = true;
+ cfg.ThreadIsAlive = new ThreadIsAliveDelegate(ThrdAlive);
+ cfg.SetThreadID = new SetThreadIDDelegate(SetThrdID);
+ cfg.ThreadCount = 10;
+ testFailCheckEnv = DatabaseEnvironment.Open(testHome, cfg);
+
+ Thread thread = new Thread(new ThreadStart(WriteThreadWithoutTxnCommit));
+ thread.Start();
+ thread.Join();
+ testFailCheckEnv.FailCheck();
+ testFailCheckEnv.Close();
+ }
+
+ public void WriteThreadWithoutTxnCommit()
+ {
+ Transaction txn = testFailCheckEnv.BeginTransaction();
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = testFailCheckEnv;
+ BTreeDatabase db = BTreeDatabase.Open("TestFailCheck.db", dbConfig, txn);
+ db.Close();
+ txn.Commit();
+ }
+
+ public bool ThrdAlive(DbThreadID info, bool procOnly)
+ {
+ Process pcs = Process.GetProcessById(info.processID);
+ if (pcs.HasExited == true)
+ return false;
+ else if (procOnly)
+ return true;
+ ProcessThreadCollection thrds = pcs.Threads;
+ foreach (ProcessThread pcsThrd in thrds)
+ {
+ if (pcsThrd.Id == info.threadID)
+ {
+ /*
+ * We have to use the fully qualified name, ThreadState
+ * defaults to System.Threading.ThreadState.
+ */
+ return (pcsThrd.ThreadState !=
+ System.Diagnostics.ThreadState.Terminated);
+ }
+ }
+ // If we can't find the thread, we say it's not alive
+ return false;
+ }
+
+ public DbThreadID SetThrdID()
+ {
+ DbThreadID threadID;
+
+ int pid = Process.GetCurrentProcess().Id;
+ uint tid = (uint)AppDomain.GetCurrentThreadId();
+ threadID = new DbThreadID(pid, tid);
+ return threadID;
+ }
+
+ [Test]
+ public void TestFeedback()
+ {
+ testName = "TestFeedback";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open the environment.
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.AutoCommit = true;
+ cfg.UseLocking = true;
+ cfg.UseLogging = true;
+ cfg.UseMPool = true;
+ cfg.UseTxns = true;
+ cfg.Create = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, cfg);
+
+ env.Feedback = new EnvironmentFeedbackDelegate(
+ EnvRecovery10PercentFeedback);
+ env.Feedback(EnvironmentFeedbackEvent.RECOVERY, 10);
+
+ env.Close();
+ }
+
+ public void EnvRecovery10PercentFeedback(
+ EnvironmentFeedbackEvent opcode, int percent)
+ {
+ Assert.AreEqual(opcode, EnvironmentFeedbackEvent.RECOVERY);
+ Assert.AreEqual(10, percent);
+ }
+
+ [Test]
+ public void TestMutexSystemStats()
+ {
+ testName = "TestMutexSystemStats";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.Create = true;
+ cfg.UseLogging = true;
+ cfg.UseLocking = true;
+ cfg.UseMPool = true;
+ cfg.UseTxns = true;
+ cfg.MutexSystemCfg = new MutexConfig();
+ cfg.MutexSystemCfg.Alignment = 512;
+ cfg.MutexSystemCfg.Increment = 128;
+ cfg.MutexSystemCfg.MaxMutexes = 150;
+ cfg.MutexSystemCfg.NumTestAndSetSpins = 10;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, cfg);
+
+ MutexStats stats = env.MutexSystemStats();
+ env.PrintMutexSystemStats(true, true);
+ Assert.AreEqual(512, stats.Alignment);
+ Assert.AreEqual(stats.Count, stats.Available + stats.InUse);
+ Assert.LessOrEqual(stats.InUse, stats.MaxInUse);
+ Assert.AreNotEqual(0, stats.RegionSize);
+ Assert.AreEqual(0, stats.RegionWait);
+ Assert.AreEqual(10, stats.TASSpins);
+ ulong regionNoWait = stats.RegionNoWait;
+
+ BTreeDatabaseConfig dbCfg = new BTreeDatabaseConfig();
+ dbCfg.Creation = CreatePolicy.IF_NEEDED;
+ dbCfg.Env = env;
+ BTreeDatabase db = BTreeDatabase.Open(testName + ".db", dbCfg);
+ for (int i = 0; i < 1000; i++)
+ {
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+ stats = env.MutexSystemStats();
+ }
+ Assert.LessOrEqual(regionNoWait, stats.RegionNoWait);
+ regionNoWait = stats.RegionNoWait;
+
+ stats = env.MutexSystemStats(true);
+ env.PrintMutexSystemStats();
+ stats = env.MutexSystemStats();
+ Assert.GreaterOrEqual(regionNoWait, stats.RegionNoWait);
+
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestLogFile()
+ {
+ testName = "TestLogFile";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open environment and configure logging subsystem.
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.Create = true;
+ cfg.UseTxns = true;
+ cfg.AutoCommit = true;
+ cfg.UseLocking = true;
+ cfg.UseMPool = true;
+ cfg.UseLogging = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 1048576, 1);
+ cfg.LogSystemCfg = new LogConfig();
+ cfg.LogSystemCfg.AutoRemove = false;
+ cfg.LogSystemCfg.BufferSize = 10240;
+ cfg.LogSystemCfg.Dir = "./";
+ cfg.LogSystemCfg.FileMode = 755;
+ cfg.LogSystemCfg.ForceSync = true;
+ cfg.LogSystemCfg.InMemory = false;
+ cfg.LogSystemCfg.MaxFileSize = 1048576;
+ cfg.LogSystemCfg.NoBuffer = false;
+ cfg.LogSystemCfg.RegionSize = 204800;
+ cfg.LogSystemCfg.ZeroOnCreate = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, cfg);
+
+ // Open database.
+ Transaction allTxn = env.BeginTransaction();
+ TransactionConfig txnConfig = new TransactionConfig();
+ txnConfig.Name = "OpenTransaction";
+ Transaction openTxn = env.BeginTransaction(txnConfig, allTxn);
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ BTreeDatabase db = BTreeDatabase.Open(
+ testName + ".db", dbConfig, openTxn);
+
+ List<ActiveTransaction> activeTxns =
+ env.TransactionSystemStats().Transactions;
+ for (int i = 0; i < activeTxns.Count; i++)
+ if (activeTxns[i].Name == "OpenTransaction")
+ {
+ LSN lsn = new LSN(
+ activeTxns[i].Begun.LogFileNumber,
+ activeTxns[i].Begun.Offset);
+ env.LogFlush(lsn);
+ string fileName = env.LogFile(lsn);
+ }
+
+ openTxn.Commit();
+
+ // Write "##" to log before putting data into database.
+ env.WriteToLog("##");
+
+ // Write 1000 records into database.
+ TransactionConfig writeTxnConfig = new TransactionConfig();
+ writeTxnConfig.Name = "WriteTxn";
+ Transaction writeTxn = env.BeginTransaction(writeTxnConfig);
+ byte[] byteArr = new byte[1024];
+ for (int i = 0; i < 1000; i++)
+ {
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(byteArr), writeTxn);
+ env.LogFlush();
+ env.WriteToLog("#" + i.ToString(), writeTxn);
+ }
+
+ activeTxns = env.TransactionSystemStats().Transactions;
+ for (int i = 0; i < activeTxns.Count; i++)
+ if (activeTxns[i].Name == "WriteTxn")
+ {
+ LSN lsn = new LSN(
+ activeTxns[i].Begun.LogFileNumber,
+ activeTxns[i].Begun.Offset);
+ env.LogFlush(lsn);
+ string fileName = env.LogFile(lsn);
+ }
+
+
+ writeTxn.Commit();
+ db.Close();
+
+ // Write "##" after data has been put.
+ env.WriteToLog("##");
+
+ List<string> logFiles = env.LogFiles(true);
+
+ env.LogWrite(new DatabaseEntry(), true);
+
+ env.RemoveUnusedLogFiles();
+
+ allTxn.Commit();
+ env.Close();
+ }
+
+ [Test]
+ public void TestOpen()
+ {
+ testName = "TestOpen";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.Create = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, cfg);
+
+ // Confirm that the environment is initialized.
+ Assert.IsNotNull(env);
+
+ // Confirm the environment home directory.
+ Assert.AreEqual(testHome, env.Home);
+
+ // Print statistics of the current environment.
+ env.PrintStats();
+
+ // Print statistics of all subsytems.
+ env.PrintSubsystemStats();
+
+ env.Close();
+ }
+
+ [Test]
+ public void TestMPoolSystemStats()
+ {
+ testName = "TestMPoolSystemStats";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.AutoCommit = true;
+ envConfig.MPoolSystemCfg = new MPoolConfig();
+ envConfig.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 1048576, 3);
+ envConfig.Create = true;
+ envConfig.UseLocking = true;
+ envConfig.UseLogging = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ envConfig.UseLogging = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ MPoolStats stats = env.MPoolSystemStats();
+ env.PrintMPoolSystemStats();
+
+ Assert.AreEqual(0, stats.BlockedOperations);
+ Assert.AreEqual(0, stats.BucketsCheckedDuringAlloc);
+ Assert.AreEqual(3, stats.CacheRegions);
+ Assert.LessOrEqual(1048576, stats.CacheSettings.Bytes);
+ Assert.AreEqual(0, stats.CacheSettings.Gigabytes);
+ Assert.AreEqual(3, stats.CacheSettings.NCaches);
+ Assert.AreEqual(0, stats.CleanPages);
+ Assert.AreEqual(0, stats.CleanPagesEvicted);
+ Assert.AreEqual(0, stats.DirtyPages);
+ Assert.AreEqual(0, stats.DirtyPagesEvicted);
+ Assert.IsNotNull(stats.Files);
+ Assert.AreEqual(0, stats.FrozenBuffers);
+ Assert.AreEqual(0, stats.FrozenBuffersFreed);
+ Assert.LessOrEqual(37, stats.HashBuckets);
+ Assert.LessOrEqual(0, stats.HashChainSearches);
+ Assert.AreEqual(0, stats.HashEntriesSearched);
+ Assert.AreEqual(0, stats.HashLockNoWait);
+ Assert.AreEqual(0, stats.HashLockWait);
+ Assert.AreEqual(0, stats.LongestHashChainSearch);
+ Assert.AreEqual(0, stats.MappedPages);
+ Assert.AreEqual(0, stats.MaxBucketsCheckedDuringAlloc);
+ Assert.AreEqual(0, stats.MaxBufferWrites);
+ Assert.AreEqual(0, stats.MaxBufferWritesSleep);
+ Assert.AreEqual(0, stats.MaxHashLockNoWait);
+ Assert.AreEqual(0, stats.MaxHashLockWait);
+ Assert.AreEqual(0, stats.MaxMMapSize);
+ Assert.AreEqual(0, stats.MaxOpenFileDescriptors);
+ Assert.AreEqual(0, stats.MaxPagesCheckedDuringAlloc);
+ Assert.AreEqual(0, stats.PageAllocations);
+ Assert.AreEqual(0, stats.Pages);
+ Assert.AreEqual(0, stats.PagesCheckedDuringAlloc);
+ Assert.LessOrEqual(0, stats.PagesCreatedInCache);
+ Assert.AreEqual(0, stats.PagesInCache);
+ Assert.AreEqual(0, stats.PagesNotInCache);
+ Assert.AreEqual(0, stats.PagesRead);
+ Assert.AreEqual(0, stats.PagesTrickled);
+ Assert.AreEqual(0, stats.PagesWritten);
+ Assert.AreNotEqual(0, stats.RegionLockNoWait);
+ Assert.AreEqual(0, stats.RegionLockWait);
+ Assert.LessOrEqual(0, stats.RegionSize);
+ Assert.AreEqual(0, stats.ThawedBuffers);
+
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ dbConfig.PageSize = 4096;
+ BTreeDatabase db = BTreeDatabase.Open(
+ testName + ".db", dbConfig);
+
+ byte[] largeByte = new byte[1088576];
+ for (int i = 0; i < 10; i++)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(largeByte));
+ db.Put(new DatabaseEntry(largeByte), new DatabaseEntry(largeByte));
+
+ db.Close();
+
+ // Clean the stats after printing.
+ stats = env.MPoolSystemStats(true);
+ env.PrintMPoolSystemStats(true, true);
+ stats = env.MPoolSystemStats();
+ env.PrintMPoolSystemStats(true, true, true);
+
+ env.Close();
+ }
+
+ [Test]
+ public void TestRemove()
+ {
+ testName = "TestRemove";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open new environment.
+ DatabaseEnvironmentConfig envConig =
+ new DatabaseEnvironmentConfig();
+ envConig.Create = true;
+ envConig.ErrorPrefix = testFixtureName + ":" + testName;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConig);
+ env.Close();
+
+ // Remove the existing environment.
+ DatabaseEnvironment.Remove(testHome);
+
+ // Confirm that the __db.001 is removed.
+ Assert.IsFalse(File.Exists(testHome + "__db.001"));
+ }
+
+ [Test]
+ public void TestRemoveCorruptedEnv()
+ {
+ testName = "TestRemoveCorruptedEnv";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open new environment.
+ DatabaseEnvironmentConfig envConig =
+ new DatabaseEnvironmentConfig();
+ envConig.Create = true;
+ envConig.ErrorPrefix = testFixtureName + ":" + testName;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, envConig);
+
+ // Panic the environment.
+ env.Panic();
+
+ // Remove the corrupted environment.
+ DatabaseEnvironment.Remove(testHome, true);
+
+ // Confirm that the __db.001 is removed.
+ Assert.IsFalse(File.Exists(testHome + "__db.001"));
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestRenameDB()
+ {
+ testName = "TestRenameDB";
+ testHome = testFixtureHome + "/" + testName;
+
+ RenameDB(testHome, testName, false);
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestRenameDBWithTxn()
+ {
+ testName = "TestRenameDBWithTxn";
+ testHome = testFixtureHome + "/" + testName;
+
+ RenameDB(testHome, testName, true);
+ }
+
+ public void RenameDB(string home, string name, bool ifTxn)
+ {
+ string dbFileName = name + ".db";
+ string dbName = "db1";
+ string dbNewName = "db2";
+
+ Configuration.ClearDir(home);
+
+ DatabaseEnvironmentConfig envConig =
+ new DatabaseEnvironmentConfig();
+ envConig.Create = true;
+ envConig.UseTxns = true;
+ envConig.UseLogging = true;
+ envConig.UseMPool = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConig);
+
+ Transaction openTxn = env.BeginTransaction();
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ BTreeDatabase db = BTreeDatabase.Open(
+ dbFileName, dbName, dbConfig, openTxn);
+ db.Close();
+ openTxn.Commit();
+
+ // Open the database.
+ if (ifTxn == false)
+ env.RenameDB(dbFileName, dbName, dbNewName, true);
+ else
+ {
+ Transaction renameTxn = env.BeginTransaction();
+ env.RenameDB(dbFileName, dbName, dbNewName, false, renameTxn);
+ renameTxn.Commit();
+ }
+
+ // Confirm that the database are renamed.
+ Transaction reopenTxn = env.BeginTransaction();
+ try
+ {
+ Database db1 = Database.Open(
+ dbFileName, new DatabaseConfig());
+ db1.Close();
+ }
+ catch (DatabaseException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ reopenTxn.Commit();
+ env.Close();
+ }
+ }
+
+ [Test]
+ public void TestResetFileID()
+ {
+ testName = "TestResetFileID";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbNewFileName = testName + "_new.db";
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseMPool = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ // Opening a new database.
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ BTreeDatabase db = BTreeDatabase.Open(
+ dbFileName, dbConfig);
+ db.Close();
+
+ // Copy the physical database file.
+ File.Copy(testHome + "/" + dbFileName,
+ testHome + "/" + dbNewFileName);
+
+ // Reset the file ID.
+ env.ResetFileID(dbNewFileName, false);
+
+ // Open the exisiting database in copied database file.
+ BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
+ cfg.Creation = CreatePolicy.NEVER;
+ cfg.Env = env;
+ BTreeDatabase newDB = BTreeDatabase.Open(
+ dbNewFileName, cfg);
+ newDB.Close();
+ env.Close();
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestRemoveDB()
+ {
+ testName = "TestRemoveDB";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ RmDBWithoutTxn(testHome, testName, false);
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestRemoveDBWithAutoCommit()
+ {
+ testName = "TestRemoveDBWithAutoCommit";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ RmDBWithoutTxn(testHome, testName, true);
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestRemoveDBWithinTxn()
+ {
+ testName = "TestRemoveDBWithinTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbName1 = testName + "1";
+ string dbName2 = testName + "2";
+
+ Configuration.ClearDir(testHome);
+
+ // Open environment.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ envConfig.UseLogging = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+ Transaction txn = env.BeginTransaction();
+
+ // Create two databases in the environment.
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ BTreeDatabase btreeDB1 = BTreeDatabase.Open(
+ dbFileName, dbName1, dbConfig, txn);
+ btreeDB1.Close();
+ BTreeDatabase btreeDB2 = BTreeDatabase.Open(
+ dbFileName, dbName2, dbConfig, txn);
+ btreeDB2.Close();
+
+ // Remove one database from the environment.
+ env.RemoveDB(dbFileName, dbName2, false, txn);
+
+ // Try to open the existing database.
+ DatabaseConfig cfg = new DatabaseConfig();
+ cfg.Env = env;
+ Database db1 = Database.Open(dbFileName, dbName1, cfg, txn);
+ db1.Close();
+
+ /*
+ * Attempting to open the removed database should
+ * cause error.
+ */
+ try
+ {
+ Database db2 = Database.Open(
+ dbFileName, dbName2, cfg, txn);
+ db2.Close();
+ }
+ catch (DatabaseException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ txn.Commit();
+ env.Close();
+ }
+ }
+
+ public void RmDBWithoutTxn(string home, string dbName,
+ bool ifAutoCommit)
+ {
+ string dbFileName = dbName + ".db";
+ string dbName1 = dbName + "1";
+ string dbName2 = dbName + "2";
+
+ // Open environment.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseMPool = true;
+ if (ifAutoCommit == true)
+ {
+ envConfig.AutoCommit = true;
+ envConfig.UseTxns = true;
+ }
+
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConfig);
+
+ // Create two databases in the environment.
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ BTreeDatabase btreeDB1 = BTreeDatabase.Open(
+ dbFileName, dbName1, dbConfig);
+ btreeDB1.Close();
+ BTreeDatabase btreeDB2 = BTreeDatabase.Open(
+ dbFileName, dbName2, dbConfig);
+ btreeDB2.Close();
+
+ // Remove one database from the environment.
+ env.RemoveDB(dbFileName, dbName2, false);
+
+ // Try to open the existing database.
+ DatabaseConfig cfg = new DatabaseConfig();
+ cfg.Env = env;
+ Database db1 = Database.Open(dbFileName, dbName1, cfg);
+ db1.Close();
+
+ /*
+ * Attempting to open the removed database should
+ * cause error.
+ */
+ try
+ {
+ Database db2 = Database.Open(
+ dbFileName, dbName2, cfg);
+ db2.Close();
+ }
+ catch (DatabaseException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ env.Close();
+ }
+ }
+
+
+ [Test]
+ public void TestTransactionSystemStats()
+ {
+ testName = "TestTransactionSystemStats";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ TransactionStats stats;
+ BTreeDatabase db;
+ Transaction openTxn = null;
+
+ // Open an environment.
+ long dateTime;
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.MaxTransactions = 50;
+ envConfig.UseLogging = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ envConfig.TxnNoSync = false;
+ envConfig.TxnNoWait = true;
+ envConfig.TxnSnapshot = true;
+ envConfig.TxnTimestamp = DateTime.Now;
+ envConfig.TxnWriteNoSync = false;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ try
+ {
+ try
+ {
+ // Confirm initial transaction subsystem statistics.
+ stats = env.TransactionSystemStats();
+ env.PrintTransactionSystemStats(true, true);
+ Assert.AreEqual(0, stats.Aborted);
+ Assert.AreEqual(0, stats.Active);
+ Assert.AreEqual(0, stats.Begun);
+ Assert.AreEqual(0, stats.Committed);
+ Assert.AreEqual(0, stats.LastCheckpoint.LogFileNumber);
+ Assert.AreEqual(0, stats.LastCheckpoint.Offset);
+ Assert.AreEqual(50, stats.MaxTransactions);
+ Assert.AreNotEqual(0, stats.RegionSize);
+ Assert.AreEqual(0, stats.Transactions.Count);
+ }
+ catch (AssertionException e)
+ {
+ throw e;
+ }
+
+ try
+ {
+ //Begin a transaction called openTxn and open a database.
+ TransactionConfig openTxnCfg = new TransactionConfig();
+ openTxnCfg.Name = "openTxn";
+ openTxn = env.BeginTransaction(openTxnCfg);
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ db = BTreeDatabase.Open(testName + ".db", dbConfig, openTxn);
+ }
+ catch (DatabaseException e)
+ {
+ if (openTxn != null)
+ openTxn.Abort();
+ throw e;
+ }
+
+ try
+ {
+ // At least there is one transaction that is alive.
+ env.Checkpoint();
+ stats = env.TransactionSystemStats();
+ env.PrintTransactionSystemStats();
+ Assert.AreNotEqual(0, stats.Active);
+ Assert.AreNotEqual(0, stats.Transactions.Count);
+ Assert.AreNotEqual(0, stats.Transactions.Capacity);
+ Assert.AreNotEqual(0, stats.RegionLockNoWait);
+ dateTime = stats.LastCheckpointTime;
+
+ // Begin an embedded transaction called putTxn.
+ TransactionConfig putTxnCfg =
+ new TransactionConfig();
+ putTxnCfg.Name = "putTxn";
+ putTxnCfg.NoWait = false;
+ Transaction putTxn = env.BeginTransaction(
+ putTxnCfg, openTxn);
+
+ try
+ {
+ // Put some records into database within putTxn.
+ for (int i = 0; i < 50; i++)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)), putTxn);
+ stats = env.TransactionSystemStats();
+ Assert.AreNotEqual(0, stats.MaxActive);
+ Assert.AreNotEqual(0, stats.MaxTransactions);
+ Assert.AreEqual(0, stats.MaxSnapshot);
+ Assert.AreEqual(0, stats.Snapshot);
+ Assert.AreEqual(stats.Begun,
+ stats.Aborted + stats.Active + stats.Committed);
+ Assert.AreEqual(2, stats.Transactions.Count);
+
+ /*
+ * Both of LogFileNumber and Offset in active transaction
+ * couldn't be 0.
+ */
+ uint logFileNumbers = 0;
+ uint offSets = 0;
+ for (int i = 0; i < stats.Transactions.Count;i++)
+ {
+ logFileNumbers += stats.Transactions[i].Begun.LogFileNumber;
+ offSets += stats.Transactions[i].Begun.Offset;
+ }
+ Assert.AreNotEqual(0, logFileNumbers);
+ Assert.AreNotEqual(0, offSets);
+
+ // All active transactions are run by the same process and thread.
+
+ Assert.AreEqual(stats.Transactions[0].ThreadID,
+ stats.Transactions[1].ThreadID);
+ Assert.AreEqual(stats.Transactions[0].ProcessID,
+ stats.Transactions[1].ProcessID);
+
+ // All transactions are alive.
+ Assert.AreEqual(ActiveTransaction.TransactionStatus.RUNNING,
+ stats.Transactions[0].Status);
+ Assert.AreEqual(ActiveTransaction.TransactionStatus.RUNNING,
+ stats.Transactions[1].Status);
+
+ /*
+ * Find the openTxn in active transactions, which is the
+ * parent transaction of putTxn.
+ */
+ int parentPos = 0;
+ if (stats.Transactions[0].Name == "putTxn")
+ parentPos = 1;
+
+ // putTxn's parent id should be the openTxn.
+ Assert.AreEqual(stats.Transactions[parentPos].ID,
+ stats.Transactions[1 - parentPos].ParentID);
+
+ // Other stats should be an positive integer.
+ for (int i = 0; i < stats.Transactions.Count - 1; i++)
+ {
+ Assert.LessOrEqual(0,
+ stats.Transactions[i].BufferCopiesInCache);
+ Assert.LessOrEqual(0,
+ stats.Transactions[i].SnapshotReads.LogFileNumber);
+ Assert.LessOrEqual(0,
+ stats.Transactions[i].SnapshotReads.Offset);
+ Assert.IsNotNull(stats.Transactions[i].GlobalID);
+ }
+
+ // Commit putTxn.
+ putTxn.Commit();
+ }
+ catch (DatabaseException e)
+ {
+ putTxn.Abort();
+ throw e;
+ }
+
+ stats = env.TransactionSystemStats();
+ Assert.AreNotEqual(0, stats.LastCheckpoint.LogFileNumber);
+ Assert.AreNotEqual(0, stats.LastCheckpoint.Offset);
+ Assert.AreEqual(dateTime, stats.LastCheckpointTime);
+
+ openTxn.Commit();
+ }
+ catch (DatabaseException e)
+ {
+ openTxn.Abort();
+ throw e;
+ }
+ finally
+ {
+ db.Close();
+ }
+ }
+ finally
+ {
+ env.Close();
+ }
+ }
+
+ /*
+ * Configure an environment. Here only configure those that could be
+ * set before environment open.
+ */
+ public void Config(XmlElement xmlElem,
+ ref DatabaseEnvironmentConfig envConfig, bool compulsory,
+ bool logging, bool locking, bool mutex, bool mpool, bool replication)
+ {
+ XmlNode childNode;
+
+ // Configure environment without any subsystems.
+ DatabaseEnvironmentConfigTest.Config(xmlElem, ref envConfig, compulsory);
+
+ // Configure environment with logging subsystem.
+ if (logging == true)
+ {
+ childNode = XMLReader.GetNode(xmlElem, "LogConfig");
+ envConfig.LogSystemCfg = new LogConfig();
+ LogConfigTest.Config((XmlElement)childNode,
+ ref envConfig.LogSystemCfg, compulsory);
+ }
+
+ // Configure environment with locking subsystem.
+ if (locking == true)
+ {
+ childNode = XMLReader.GetNode(xmlElem, "LockingConfig");
+ envConfig.LockSystemCfg = new LockingConfig();
+ LockingConfigTest.Config((XmlElement)childNode,
+ ref envConfig.LockSystemCfg, compulsory);
+ }
+
+ // Configure environment with mutex subsystem.
+ if (mutex == true)
+ {
+ childNode = XMLReader.GetNode(xmlElem, "MutexConfig");
+ envConfig.MutexSystemCfg = new MutexConfig();
+ MutexConfigTest.Config((XmlElement)childNode,
+ ref envConfig.MutexSystemCfg, compulsory);
+ }
+
+ if (mpool == true)
+ {
+ childNode = XMLReader.GetNode(xmlElem, "MPoolConfig");
+ envConfig.MPoolSystemCfg = new MPoolConfig();
+ MPoolConfigTest.Config((XmlElement)childNode,
+ ref envConfig.MPoolSystemCfg, compulsory);
+ }
+
+ // Configure environment with replication.
+ if (replication == true)
+ {
+ childNode = XMLReader.GetNode(xmlElem, "ReplicationConfig");
+ envConfig.RepSystemCfg = new ReplicationConfig();
+ ReplicationConfigTest.Config((XmlElement)childNode,
+ ref envConfig.RepSystemCfg, compulsory);
+ }
+ }
+
+ /*
+ * Confirm the fields/properties in the environment.
+ * Those set by setting functions are not checked here.
+ */
+ public static void Confirm(XmlElement xmlElement,
+ DatabaseEnvironment env, bool compulsory,
+ bool logging, bool locking, bool mutex, bool mpool,
+ bool replication)
+ {
+ XmlElement childElem;
+ CacheInfo cacheInfo = new CacheInfo(0, 0, 0);
+
+ // Confirm environment configuration.
+ Configuration.ConfirmBool(xmlElement, "AutoCommit",
+ env.AutoCommit, compulsory);
+ Configuration.ConfirmBool(xmlElement, "CDB_ALLDB",
+ env.CDB_ALLDB, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Create",
+ env.Create, compulsory);
+ Configuration.ConfirmStringList(xmlElement, "DataDirs",
+ env.DataDirs, compulsory);
+ Configuration.ConfirmString(xmlElement, "ErrorPrefix",
+ env.ErrorPrefix, compulsory);
+ Configuration.ConfirmBool(xmlElement, "ForceFlush",
+ env.ForceFlush, compulsory);
+ Configuration.ConfirmBool(xmlElement, "FreeThreaded",
+ env.FreeThreaded, compulsory);
+ Configuration.ConfirmBool(xmlElement, "InitRegions",
+ env.InitRegions, compulsory);
+ Configuration.ConfirmString(xmlElement, "IntermediateDirMode",
+ env.IntermediateDirMode, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Lockdown",
+ env.Lockdown, compulsory);
+ Configuration.ConfirmUint(xmlElement, "LockTimeout",
+ env.LockTimeout, compulsory);
+ Configuration.ConfirmUint(xmlElement, "MaxTransactions",
+ env.MaxTransactions, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoBuffer",
+ env.NoBuffer, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoLocking",
+ env.NoLocking, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoMMap",
+ env.NoMMap, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoPanic",
+ env.NoPanic, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Overwrite",
+ env.Overwrite, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Private",
+ env.Private, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Register",
+ env.Register, compulsory);
+ Configuration.ConfirmBool(xmlElement, "RunFatalRecovery",
+ env.RunFatalRecovery, compulsory);
+ Configuration.ConfirmBool(xmlElement, "RunRecovery",
+ env.RunRecovery, compulsory);
+ Configuration.ConfirmBool(xmlElement, "SystemMemory",
+ env.SystemMemory, compulsory);
+ Configuration.ConfirmString(xmlElement, "TempDir",
+ env.TempDir, compulsory);
+ Configuration.ConfirmBool(xmlElement, "TimeNotGranted",
+ env.TimeNotGranted, compulsory);
+ Configuration.ConfirmBool(xmlElement, "TxnNoSync",
+ env.TxnNoSync, compulsory);
+ Configuration.ConfirmBool(xmlElement, "TxnNoWait",
+ env.TxnNoWait, compulsory);
+ Configuration.ConfirmBool(xmlElement, "TxnSnapshot",
+ env.TxnSnapshot, compulsory);
+ Configuration.ConfirmDateTime(xmlElement, "TxnTimestamp",
+ env.TxnTimestamp, compulsory);
+ Configuration.ConfirmBool(xmlElement, "TxnWriteNoSync",
+ env.TxnWriteNoSync, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseMVCC",
+ env.UseMVCC, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseCDB",
+ env.UsingCDB, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseLocking",
+ env.UsingLocking, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseLogging",
+ env.UsingLogging, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseMPool",
+ env.UsingMPool, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseReplication",
+ env.UsingReplication, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseTxns",
+ env.UsingTxns, compulsory);
+ env.Verbosity = new VerboseMessages();
+ Configuration.ConfirmVerboseMessages(xmlElement,
+ "Verbosity", env.Verbosity, compulsory);
+ Configuration.ConfirmBool(xmlElement, "YieldCPU",
+ env.YieldCPU, compulsory);
+
+ /*
+ * If the locking subsystem is set, check the
+ * field/properties set in LockingConfig.
+ */
+ if (locking == true)
+ {
+ childElem = (XmlElement)XMLReader.GetNode(
+ xmlElement, "LockingConfig");
+ Configuration.ConfirmByteMatrix(childElem,
+ "Conflicts", env.LockConflictMatrix,
+ compulsory);
+ Configuration.ConfirmDeadlockPolicy(
+ childElem, "DeadlockResolution",
+ env.DeadlockResolution, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "Partitions", env.LockPartitions,
+ compulsory);
+ Configuration.ConfirmUint(childElem,
+ "MaxLockers", env.MaxLockers, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "MaxLocks", env.MaxLocks, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "MaxObjects", env.MaxObjects, compulsory);
+ }
+
+ /*
+ * If the locking subsystem is set, check the
+ * field/properties set in LogConfig.
+ */
+ if (logging == true)
+ {
+ childElem = (XmlElement)XMLReader.GetNode(
+ xmlElement, "LogConfig");
+ Configuration.ConfirmBool(childElem,
+ "AutoRemove", env.LogAutoRemove,
+ compulsory);
+ Configuration.ConfirmUint(childElem,
+ "BufferSize", env.LogBufferSize,
+ compulsory);
+ Configuration.ConfirmString(childElem,
+ "Dir", env.LogDir, compulsory);
+ Configuration.ConfirmInt(childElem,
+ "FileMode", env.LogFileMode, compulsory);
+ Configuration.ConfirmBool(childElem,
+ "ForceSync", env.LogForceSync, compulsory);
+ Configuration.ConfirmBool(childElem,
+ "InMemory", env.LogInMemory, compulsory);
+ Configuration.ConfirmBool(childElem,
+ "NoBuffer", env.LogNoBuffer, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "RegionSize", env.LogRegionSize,
+ compulsory);
+ Configuration.ConfirmBool(childElem,
+ "ZeroOnCreate", env.LogZeroOnCreate,
+ compulsory);
+ Configuration.ConfirmUint(childElem,
+ "MaxFileSize", env.MaxLogFileSize,
+ compulsory);
+ }
+
+ /*
+ * If the locking subsystem is set, check the
+ * field/properties set in MutexConfig.
+ */
+ if (mutex == true)
+ {
+ childElem = (XmlElement)XMLReader.GetNode(
+ xmlElement, "MutexConfig");
+ Configuration.ConfirmUint(childElem,
+ "Alignment", env.MutexAlignment,
+ compulsory);
+ Configuration.ConfirmUint(childElem,
+ "MaxMutexes", env.MaxMutexes, compulsory);
+ try
+ {
+ Configuration.ConfirmUint(childElem,
+ "Increment", env.MutexIncrement,
+ compulsory);
+ }
+ catch (AssertionException)
+ {
+ Assert.AreEqual(0, env.MutexIncrement);
+ }
+
+ Configuration.ConfirmUint(childElem,
+ "NumTestAndSetSpins",
+ env.NumTestAndSetSpins, compulsory);
+ }
+
+ if (mpool == true)
+ {
+ childElem = (XmlElement)XMLReader.GetNode(
+ xmlElement, "MPoolConfig");
+ Configuration.ConfirmCacheSize(childElem,
+ "CacheSize", env.CacheSize, compulsory);
+ if (env.UsingMPool == false)
+ Configuration.ConfirmCacheSize(childElem,
+ "MaxCacheSize", env.MaxCacheSize, compulsory);
+ Configuration.ConfirmInt(childElem,
+ "MaxOpenFiles", env.MaxOpenFiles, compulsory);
+ Configuration.ConfirmMaxSequentialWrites(childElem,
+ "MaxSequentialWrites", env.SequentialWritePause,
+ env.MaxSequentialWrites, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "MMapSize", env.MMapSize, compulsory);
+ }
+
+ if (replication == true)
+ {
+ childElem = (XmlElement)XMLReader.GetNode(
+ xmlElement, "ReplicationConfig");
+ Configuration.ConfirmUint(childElem,
+ "AckTimeout", env.RepAckTimeout, compulsory);
+ Configuration.ConfirmBool(childElem,
+ "BulkTransfer", env.RepBulkTransfer, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "CheckpointDelay", env.RepCheckpointDelay, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "ConnectionRetry", env.RepConnectionRetry, compulsory);
+ Configuration.ConfirmBool(childElem,
+ "DelayClientSync", env.RepDelayClientSync, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "ElectionRetry", env.RepElectionRetry, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "ElectionTimeout", env.RepElectionTimeout, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "FullElectionTimeout", env.RepFullElectionTimeout,compulsory);
+ Configuration.ConfirmUint(childElem,
+ "HeartbeatMonitor", env.RepHeartbeatMonitor, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "HeartbeatSend", env.RepHeartbeatSend, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "LeaseTimeout", env.RepLeaseTimeout, compulsory);
+ Configuration.ConfirmBool(childElem,
+ "NoAutoInit", env.RepNoAutoInit, compulsory);
+ Configuration.ConfirmBool(childElem,
+ "NoBlocking", env.RepNoBlocking, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "NSites", env.RepNSites, compulsory);
+ Configuration.ConfirmUint(childElem,
+ "Priority", env.RepPriority, compulsory);
+ Configuration.ConfirmAckPolicy(childElem,
+ "RepMgrAckPolicy", env.RepMgrAckPolicy, compulsory);
+ Configuration.ConfirmBool(childElem,
+ "Strict2Site", env.RepStrict2Site, compulsory);
+ Configuration.ConfirmBool(childElem,
+ "UseMasterLeases", env.RepUseMasterLeases, compulsory);
+ }
+ }
+ }
+}
diff --git a/test/scr037/DatabaseExceptionTest.cs b/test/scr037/DatabaseExceptionTest.cs
new file mode 100644
index 0000000..4e662eb
--- /dev/null
+++ b/test/scr037/DatabaseExceptionTest.cs
@@ -0,0 +1,221 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class DatabaseExceptionTest
+ {
+ [Test]
+ public void TestDB_REP_DUPMASTER()
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_REP_DUPMASTER);
+ }
+
+ [Test]
+ public void TestDB_REP_HOLDELECTION()
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_REP_HOLDELECTION);
+ }
+
+ [Test]
+ public void TestDB_REP_IGNORE()
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_REP_IGNORE);
+ }
+
+ [Test]
+ public void TestDB_REP_ISPERM()
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_REP_ISPERM);
+ }
+
+ [Test]
+ public void TestDB_REP_JOIN_FAILURE()
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_REP_JOIN_FAILURE);
+ }
+
+ [Test]
+ public void TestDB_REP_NEWSITE()
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_REP_NEWSITE);
+ }
+
+ [Test]
+ public void TestDB_REP_NOTPERM()
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_REP_NOTPERM);
+ }
+
+ [Test]
+ public void TestDeadlockException()
+ {
+ try
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_LOCK_DEADLOCK);
+ }
+ catch (DeadlockException e)
+ {
+ Assert.AreEqual(ErrorCodes.DB_LOCK_DEADLOCK, e.ErrorCode);
+ }
+ }
+
+ [Test]
+ public void TestForeignConflictException()
+ {
+ try
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_FOREIGN_CONFLICT);
+ }
+ catch (ForeignConflictException e)
+ {
+ Assert.AreEqual(ErrorCodes.DB_FOREIGN_CONFLICT, e.ErrorCode);
+ }
+ }
+
+ [Test]
+ public void TestKeyEmptyException()
+ {
+ try
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_KEYEMPTY);
+ }
+ catch (KeyEmptyException e)
+ {
+ Assert.AreEqual(ErrorCodes.DB_KEYEMPTY, e.ErrorCode);
+ }
+ }
+
+ [Test]
+ public void TestKeyExistException()
+ {
+ try
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_KEYEXIST);
+ }
+ catch (KeyExistException e)
+ {
+ Assert.AreEqual(ErrorCodes.DB_KEYEXIST, e.ErrorCode);
+ }
+ }
+
+ [Test]
+ public void TestLeaseExpiredException()
+ {
+ try
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_REP_LEASE_EXPIRED);
+ }
+ catch (LeaseExpiredException e)
+ {
+ Assert.AreEqual(ErrorCodes.DB_REP_LEASE_EXPIRED, e.ErrorCode);
+ }
+ }
+
+ [Test]
+ public void TestLockNotGrantedException()
+ {
+ try
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_LOCK_NOTGRANTED);
+ }
+ catch (LockNotGrantedException e)
+ {
+ Assert.AreEqual(ErrorCodes.DB_LOCK_NOTGRANTED, e.ErrorCode);
+ }
+ }
+
+ [Test]
+ public void TestNotFoundException()
+ {
+ try
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_NOTFOUND);
+ }
+ catch (NotFoundException e)
+ {
+ Assert.AreEqual(ErrorCodes.DB_NOTFOUND, e.ErrorCode);
+ }
+ }
+
+ [Test]
+ public void TestOldVersionException()
+ {
+ try
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_OLD_VERSION);
+ }
+ catch (OldVersionException e)
+ {
+ Assert.AreEqual(ErrorCodes.DB_OLD_VERSION, e.ErrorCode);
+ }
+ }
+
+ [Test]
+ public void TestPageNotFoundException()
+ {
+ try
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_PAGE_NOTFOUND);
+ }
+ catch (PageNotFoundException e)
+ {
+ Assert.AreEqual(ErrorCodes.DB_PAGE_NOTFOUND, e.ErrorCode);
+ }
+ }
+
+ [Test]
+ public void TestRunRecoveryException()
+ {
+ try
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_RUNRECOVERY);
+ }
+ catch (RunRecoveryException e)
+ {
+ Assert.AreEqual(ErrorCodes.DB_RUNRECOVERY, e.ErrorCode);
+ }
+
+ }
+
+ [Test]
+ public void TestVerificationException()
+ {
+ try
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_VERIFY_BAD);
+ }
+ catch (VerificationException e)
+ {
+ Assert.AreEqual(ErrorCodes.DB_VERIFY_BAD, e.ErrorCode);
+ }
+ }
+
+ [Test]
+ public void TestVersionMismatchException()
+ {
+ try
+ {
+ DatabaseException.ThrowException(ErrorCodes.DB_VERSION_MISMATCH);
+ }
+ catch (VersionMismatchException e)
+ {
+ Assert.AreEqual(ErrorCodes.DB_VERSION_MISMATCH, e.ErrorCode);
+ }
+ }
+ }
+}
diff --git a/test/scr037/DatabaseTest.cs b/test/scr037/DatabaseTest.cs
new file mode 100644
index 0000000..07634a6
--- /dev/null
+++ b/test/scr037/DatabaseTest.cs
@@ -0,0 +1,109 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ public class DatabaseTest
+ {
+ public static uint getDefaultCacheSizeBytes()
+ {
+ uint defaultCacheSizeBytes;
+
+ string fixtureHome = "./TestOut/DatabaseTest";
+ string dbName = fixtureHome + "/" + "getDefaultCacheSizeBytes" + ".db";
+
+ Configuration.ClearDir(fixtureHome);
+
+ BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
+ cfg.Creation = CreatePolicy.ALWAYS;
+ using (BTreeDatabase db = BTreeDatabase.Open(dbName, cfg))
+ {
+ defaultCacheSizeBytes = db.CacheSize.Bytes;
+ }
+
+ return defaultCacheSizeBytes;
+ }
+
+ public static ByteOrder getMachineByteOrder()
+ {
+ string fixtureHome = "./TestOut/DatabaseTest";
+ string dbName = fixtureHome + "/" + "getMachineByteOrder" + ".db";
+
+ Configuration.ClearDir(fixtureHome);
+
+ ByteOrder byteOrder;
+
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.ByteOrder = ByteOrder.MACHINE;
+ dbConfig.Creation = CreatePolicy.ALWAYS;
+ using (BTreeDatabase db = BTreeDatabase.Open(dbName, dbConfig))
+ {
+ byteOrder = db.Endianness;
+ }
+ return byteOrder;
+ }
+
+ public static void Confirm(XmlElement xmlElement, Database db, bool compulsory)
+ {
+ uint defaultBytes;
+ defaultBytes = getDefaultCacheSizeBytes();
+
+ Configuration.ConfirmBool(xmlElement, "AutoCommit",
+ db.AutoCommit, compulsory);
+ Configuration.ConfirmCacheSize(xmlElement, "CacheSize",
+ db.CacheSize, defaultBytes, compulsory);
+ Configuration.ConfirmCreatePolicy(xmlElement, "Creation",
+ db.Creation, compulsory);
+ Configuration.ConfirmString(xmlElement, "DatabaseName",
+ db.DatabaseName, compulsory);
+ Configuration.ConfirmBool(xmlElement, "DoChecksum",
+ db.DoChecksum, compulsory);
+ // Encrypted and EncryptWithAES?
+ Configuration.ConfirmByteOrder(xmlElement, "ByteOrder",
+ db.Endianness, compulsory);
+ Configuration.ConfirmString(xmlElement, "ErrorPrefix",
+ db.ErrorPrefix, compulsory);
+ // File name is confirmed in functiion, not here.
+ Configuration.ConfirmBool(xmlElement, "FreeThreaded",
+ db.FreeThreaded, compulsory);
+ Configuration.ConfirmBool(xmlElement, "HasMultiple",
+ db.HasMultiple, compulsory);
+ if (db.Endianness == getMachineByteOrder())
+ Assert.IsTrue(db.InHostOrder);
+ else
+ Assert.IsFalse(db.InHostOrder);
+ Configuration.ConfirmBool(xmlElement, "NoMMap",
+ db.NoMMap, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NonDurableTxns",
+ db.NonDurableTxns, compulsory);
+ Configuration.ConfirmUint(xmlElement, "PageSize",
+ db.Pagesize, compulsory);
+ Configuration.ConfirmCachePriority(xmlElement,
+ "Priority", db.Priority, compulsory);
+ Configuration.ConfirmBool(xmlElement, "ReadOnly",
+ db.ReadOnly, compulsory);
+ Configuration.ConfirmBool(xmlElement, "ReadUncommitted",
+ db.ReadUncommitted, compulsory);
+ /*
+ * Database.Truncated is the value set in
+ * DatabaseConfig.Truncate.
+ */
+ Configuration.ConfirmBool(xmlElement, "Truncate",
+ db.Truncated, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseMVCC",
+ db.UseMVCC, compulsory);
+ }
+ }
+
+}
diff --git a/test/scr037/DotNetTest.csproj b/test/scr037/DotNetTest.csproj
new file mode 100644
index 0000000..0269b6f
--- /dev/null
+++ b/test/scr037/DotNetTest.csproj
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{08D940C7-AAF5-413A-95E3-58A46880DC4D}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>DotNetTest</RootNamespace>
+ <AssemblyName>DotNetTest</AssemblyName>
+ <StartupObject>
+ </StartupObject>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ItemGroup>
+ <Compile Include="BTreeCursorTest.cs" />
+ <Compile Include="BTreeDatabaseConfigTest.cs" />
+ <Compile Include="BTreeDatabaseTest.cs" />
+ <Compile Include="Configuration.cs" />
+ <Compile Include="CursorConfigTest.cs" />
+ <Compile Include="CursorTest.cs" />
+ <Compile Include="DatabaseConfigTest.cs" />
+ <Compile Include="DatabaseEnvironmentConfigTest.cs" />
+ <Compile Include="DatabaseEnvironmentTest.cs" />
+ <Compile Include="DatabaseExceptionTest.cs" />
+ <Compile Include="DatabaseTest.cs" />
+ <Compile Include="ForeignKeyTest.cs" />
+ <Compile Include="HashCursorTest.cs" />
+ <Compile Include="HashDatabaseConfigTest.cs" />
+ <Compile Include="HashDatabaseTest.cs" />
+ <Compile Include="JoinCursorTest.cs" />
+ <Compile Include="LockingConfigTest.cs" />
+ <Compile Include="LockTest.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="LogConfigTest.cs" />
+ <Compile Include="MPoolConfigTest.cs" />
+ <Compile Include="MutexConfigTest.cs" />
+ <Compile Include="QueueDatabaseConfigTest.cs" />
+ <Compile Include="QueueDatabaseTest.cs" />
+ <Compile Include="RecnoCursorTest.cs" />
+ <Compile Include="RecnoDatabaseConfigTest.cs" />
+ <Compile Include="RecnoDatabaseTest.cs" />
+ <Compile Include="ReplicationConfigTest.cs" />
+ <Compile Include="ReplicationTest.cs" />
+ <Compile Include="SecondaryBTreeDatabaseConfigTest.cs" />
+ <Compile Include="SecondaryBTreeDatabaseTest.cs" />
+ <Compile Include="SecondaryCursorTest.cs" />
+ <Compile Include="SecondaryDatabaseConfigTest.cs" />
+ <Compile Include="SecondaryDatabaseTest.cs" />
+ <Compile Include="SecondaryHashDatabaseConfigTest.cs" />
+ <Compile Include="SecondaryHashDatabaseTest.cs" />
+ <Compile Include="SecondaryQueueDatabaseConfigTest.cs" />
+ <Compile Include="SecondaryQueueDatabaseTest.cs" />
+ <Compile Include="SecondaryRecnoDatabaseConfigTest.cs" />
+ <Compile Include="SecondaryRecnoDatabaseTest.cs" />
+ <Compile Include="SequenceConfigTest.cs" />
+ <Compile Include="SequenceTest.cs" />
+ <Compile Include="TestException.cs" />
+ <Compile Include="TransactionConfigTest.cs" />
+ <Compile Include="TransactionTest.cs" />
+ <Compile Include="XMLReader.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\csharp\db_dotnet.csproj">
+ <Project>{4696FB1E-1E5F-40B9-BD8C-A54D3BDA00F6}</Project>
+ <Name>db_dotnet</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="nunit.framework, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.XML" />
+ </ItemGroup>
+ <PropertyGroup>
+ <PreBuildEvent>IF $(ConfigurationName) == Debug SET LIBEXT=d
+IF $(ConfigurationName) == Release SET LIBEXT
+
+copy /B "$(SolutionDir)Win32\$(ConfigurationName)\libdb48%25LIBEXT%25.dll" "$(TargetDir)"
+copy /B "$(SolutionDir)Win32\$(ConfigurationName)\libdb_csharp48%25LIBEXT%25.dll" "$(TargetDir)"
+copy "$(ProjectDir)AllTestData.xml" "$(TargetDir)"</PreBuildEvent>
+ </PropertyGroup>
+ <ItemGroup>
+ <Content Include="AllTestData.xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="bdb4.7.db" />
+ </ItemGroup>
+</Project>
diff --git a/test/scr037/ForeignKeyTest.cs b/test/scr037/ForeignKeyTest.cs
new file mode 100644
index 0000000..e140d7b
--- /dev/null
+++ b/test/scr037/ForeignKeyTest.cs
@@ -0,0 +1,280 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest {
+ [TestFixture]
+ public class ForeignKeyTest {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests() {
+ testFixtureName = "ForeignKeyTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ }
+
+ [Test]
+ public void TestAbortBTree() {
+ testName = "TestAbortBTree";
+ testHome = testFixtureHome + "/" + testName;
+ TestForeignKeyDelete(DatabaseType.BTREE, ForeignKeyDeleteAction.ABORT);
+ }
+ [Test]
+ public void TestAbortHash() {
+ testName = "TestAbortHash";
+ testHome = testFixtureHome + "/" + testName;
+ TestForeignKeyDelete(DatabaseType.HASH, ForeignKeyDeleteAction.ABORT);
+ }
+ [Test]
+ public void TestAbortQueue() {
+ testName = "TestAbortQueue";
+ testHome = testFixtureHome + "/" + testName;
+ TestForeignKeyDelete(DatabaseType.QUEUE, ForeignKeyDeleteAction.ABORT);
+ }
+ [Test]
+ public void TestAbortRecno() {
+ testName = "TestAbortRecno";
+ testHome = testFixtureHome + "/" + testName;
+ TestForeignKeyDelete(DatabaseType.RECNO, ForeignKeyDeleteAction.ABORT);
+ }
+
+ [Test]
+ public void TestCascadeBTree() {
+ testName = "TestCascadeBTree";
+ testHome = testFixtureHome + "/" + testName;
+ TestForeignKeyDelete(DatabaseType.BTREE, ForeignKeyDeleteAction.CASCADE);
+ }
+
+ [Test]
+ public void TestCascadeHash() {
+ testName = "TestCascadeHash";
+ testHome = testFixtureHome + "/" + testName;
+ TestForeignKeyDelete(DatabaseType.HASH, ForeignKeyDeleteAction.CASCADE);
+ }
+
+ [Test]
+ public void TestCascadeQueue() {
+ testName = "TestCascadeQueue";
+ testHome = testFixtureHome + "/" + testName;
+ TestForeignKeyDelete(DatabaseType.QUEUE, ForeignKeyDeleteAction.CASCADE);
+ }
+
+ [Test]
+ public void TestCascadeRecno() {
+ testName = "TestCascadeRecno";
+ testHome = testFixtureHome + "/" + testName;
+ TestForeignKeyDelete(DatabaseType.RECNO, ForeignKeyDeleteAction.CASCADE);
+ }
+
+ [Test]
+ public void TestNullifyBTree() {
+ testName = "TestNullifyBTree";
+ testHome = testFixtureHome + "/" + testName;
+ TestForeignKeyDelete(DatabaseType.BTREE, ForeignKeyDeleteAction.NULLIFY);
+ }
+
+ [Test]
+ public void TestNullifyHash() {
+ testName = "TestNullifyHash";
+ testHome = testFixtureHome + "/" + testName;
+ TestForeignKeyDelete(DatabaseType.HASH, ForeignKeyDeleteAction.NULLIFY);
+ }
+
+ [Test]
+ public void TestNullifyQueue() {
+ testName = "TestNullifyQueue";
+ testHome = testFixtureHome + "/" + testName;
+ TestForeignKeyDelete(DatabaseType.QUEUE, ForeignKeyDeleteAction.NULLIFY);
+ }
+
+ [Test]
+ public void TestNullifyRecno() {
+ testName = "TestNullifyRecno";
+ testHome = testFixtureHome + "/" + testName;
+ TestForeignKeyDelete(DatabaseType.RECNO, ForeignKeyDeleteAction.NULLIFY);
+ }
+
+ public void TestForeignKeyDelete(DatabaseType dbtype, ForeignKeyDeleteAction action) {
+ string dbFileName = testHome + "/" + testName + ".db";
+ string fdbFileName = testHome + "/" + testName + "foreign.db";
+ string sdbFileName = testHome + "/" + testName + "sec.db";
+ Configuration.ClearDir(testHome);
+
+ Database primaryDB, fdb;
+ SecondaryDatabase secDB;
+
+ // Open primary database.
+ if (dbtype == DatabaseType.BTREE) {
+ BTreeDatabaseConfig btConfig = new BTreeDatabaseConfig();
+ btConfig.Creation = CreatePolicy.ALWAYS;
+ primaryDB = BTreeDatabase.Open(dbFileName, btConfig);
+ fdb = BTreeDatabase.Open(fdbFileName, btConfig);
+ } else if (dbtype == DatabaseType.HASH) {
+ HashDatabaseConfig hConfig = new HashDatabaseConfig();
+ hConfig.Creation = CreatePolicy.ALWAYS;
+ primaryDB = HashDatabase.Open(dbFileName, hConfig);
+ fdb = HashDatabase.Open(fdbFileName, hConfig);
+ } else if (dbtype == DatabaseType.QUEUE) {
+ QueueDatabaseConfig qConfig = new QueueDatabaseConfig();
+ qConfig.Creation = CreatePolicy.ALWAYS;
+ qConfig.Length = 4;
+ primaryDB = QueueDatabase.Open(dbFileName, qConfig);
+ fdb = QueueDatabase.Open(fdbFileName, qConfig);
+ } else if (dbtype == DatabaseType.RECNO) {
+ RecnoDatabaseConfig rConfig = new RecnoDatabaseConfig();
+ rConfig.Creation = CreatePolicy.ALWAYS;
+ primaryDB = RecnoDatabase.Open(dbFileName, rConfig);
+ fdb = RecnoDatabase.Open(fdbFileName, rConfig);
+ } else {
+ throw new ArgumentException("Invalid DatabaseType");
+ }
+
+ // Open secondary database.
+ if (dbtype == DatabaseType.BTREE) {
+ SecondaryBTreeDatabaseConfig secbtConfig =
+ new SecondaryBTreeDatabaseConfig(primaryDB,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secbtConfig.Creation = CreatePolicy.ALWAYS;
+ secbtConfig.Duplicates = DuplicatesPolicy.SORTED;
+ if (action == ForeignKeyDeleteAction.NULLIFY)
+ secbtConfig.SetForeignKeyConstraint(fdb, action, new ForeignKeyNullifyDelegate(Nullify));
+ else
+ secbtConfig.SetForeignKeyConstraint(fdb, action);
+ secDB = SecondaryBTreeDatabase.Open(sdbFileName, secbtConfig);
+ } else if (dbtype == DatabaseType.HASH) {
+ SecondaryHashDatabaseConfig sechConfig =
+ new SecondaryHashDatabaseConfig(primaryDB,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ sechConfig.Creation = CreatePolicy.ALWAYS;
+ sechConfig.Duplicates = DuplicatesPolicy.SORTED;
+ if (action == ForeignKeyDeleteAction.NULLIFY)
+ sechConfig.SetForeignKeyConstraint(fdb, action, new ForeignKeyNullifyDelegate(Nullify));
+ else
+ sechConfig.SetForeignKeyConstraint(fdb, action);
+ secDB = SecondaryHashDatabase.Open(sdbFileName, sechConfig);
+ } else if (dbtype == DatabaseType.QUEUE) {
+ SecondaryQueueDatabaseConfig secqConfig =
+ new SecondaryQueueDatabaseConfig(primaryDB,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secqConfig.Creation = CreatePolicy.ALWAYS;
+ secqConfig.Length = 4;
+ if (action == ForeignKeyDeleteAction.NULLIFY)
+ secqConfig.SetForeignKeyConstraint(fdb, action, new ForeignKeyNullifyDelegate(Nullify));
+ else
+ secqConfig.SetForeignKeyConstraint(fdb, action);
+ secDB = SecondaryQueueDatabase.Open(sdbFileName, secqConfig);
+ } else if (dbtype == DatabaseType.RECNO) {
+ SecondaryRecnoDatabaseConfig secrConfig =
+ new SecondaryRecnoDatabaseConfig(primaryDB,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secrConfig.Creation = CreatePolicy.ALWAYS;
+ if (action == ForeignKeyDeleteAction.NULLIFY)
+ secrConfig.SetForeignKeyConstraint(fdb, action, new ForeignKeyNullifyDelegate(Nullify));
+ else
+ secrConfig.SetForeignKeyConstraint(fdb, action);
+ secDB = SecondaryRecnoDatabase.Open(sdbFileName, secrConfig);
+ } else {
+ throw new ArgumentException("Invalid DatabaseType");
+ }
+
+ /* Use integer keys for Queue/Recno support. */
+ fdb.Put(new DatabaseEntry(BitConverter.GetBytes(100)),
+ new DatabaseEntry(BitConverter.GetBytes(1001)));
+ fdb.Put(new DatabaseEntry(BitConverter.GetBytes(200)),
+ new DatabaseEntry(BitConverter.GetBytes(2002)));
+ fdb.Put(new DatabaseEntry(BitConverter.GetBytes(300)),
+ new DatabaseEntry(BitConverter.GetBytes(3003)));
+
+ primaryDB.Put(new DatabaseEntry(BitConverter.GetBytes(1)),
+ new DatabaseEntry(BitConverter.GetBytes(100)));
+ primaryDB.Put(new DatabaseEntry(BitConverter.GetBytes(2)),
+ new DatabaseEntry(BitConverter.GetBytes(200)));
+ if (dbtype == DatabaseType.BTREE || dbtype == DatabaseType.HASH)
+ primaryDB.Put(new DatabaseEntry(BitConverter.GetBytes(3)),
+ new DatabaseEntry(BitConverter.GetBytes(100)));
+
+ try {
+ fdb.Delete(new DatabaseEntry(BitConverter.GetBytes(100)));
+ } catch (ForeignConflictException) {
+ Assert.AreEqual(action, ForeignKeyDeleteAction.ABORT);
+ }
+ if (action == ForeignKeyDeleteAction.ABORT) {
+ Assert.IsTrue(secDB.Exists(new DatabaseEntry(BitConverter.GetBytes(100))));
+ Assert.IsTrue(primaryDB.Exists(new DatabaseEntry(BitConverter.GetBytes(1))));
+ Assert.IsTrue(fdb.Exists(new DatabaseEntry(BitConverter.GetBytes(100))));
+ } else if (action == ForeignKeyDeleteAction.CASCADE) {
+ try {
+ Assert.IsFalse(secDB.Exists(new DatabaseEntry(BitConverter.GetBytes(100))));
+ } catch (KeyEmptyException) {
+ Assert.IsTrue(dbtype == DatabaseType.QUEUE || dbtype == DatabaseType.RECNO);
+ }
+ try {
+ Assert.IsFalse(primaryDB.Exists(new DatabaseEntry(BitConverter.GetBytes(1))));
+ } catch (KeyEmptyException) {
+ Assert.IsTrue(dbtype == DatabaseType.QUEUE || dbtype == DatabaseType.RECNO);
+ }
+ try {
+ Assert.IsFalse(fdb.Exists(new DatabaseEntry(BitConverter.GetBytes(100))));
+ } catch (KeyEmptyException) {
+ Assert.IsTrue(dbtype == DatabaseType.QUEUE || dbtype == DatabaseType.RECNO);
+ }
+ } else if (action == ForeignKeyDeleteAction.NULLIFY) {
+ try {
+ Assert.IsFalse(secDB.Exists(new DatabaseEntry(BitConverter.GetBytes(100))));
+ } catch (KeyEmptyException) {
+ Assert.IsTrue(dbtype == DatabaseType.QUEUE || dbtype == DatabaseType.RECNO);
+ }
+ Assert.IsTrue(primaryDB.Exists(new DatabaseEntry(BitConverter.GetBytes(1))));
+ try {
+ Assert.IsFalse(fdb.Exists(new DatabaseEntry(BitConverter.GetBytes(100))));
+ } catch (KeyEmptyException) {
+ Assert.IsTrue(dbtype == DatabaseType.QUEUE || dbtype == DatabaseType.RECNO);
+ }
+ }
+
+ // Close secondary database.
+ secDB.Close();
+
+ // Close primary database.
+ primaryDB.Close();
+
+ // Close foreign database
+ fdb.Close();
+ }
+
+ public DatabaseEntry SecondaryKeyGen(
+ DatabaseEntry key, DatabaseEntry data) {
+ DatabaseEntry dbtGen;
+
+ int skey = BitConverter.ToInt32(data.Data, 0);
+ // don't index secondary key of 0
+ if (skey == 0)
+ return null;
+
+ dbtGen = new DatabaseEntry(data.Data);
+ return dbtGen;
+ }
+
+ public DatabaseEntry Nullify(DatabaseEntry key, DatabaseEntry data, DatabaseEntry fkey) {
+ DatabaseEntry ret = new DatabaseEntry(BitConverter.GetBytes(0));
+ return ret;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/test/scr037/HashCursorTest.cs b/test/scr037/HashCursorTest.cs
new file mode 100644
index 0000000..1dd4cfb
--- /dev/null
+++ b/test/scr037/HashCursorTest.cs
@@ -0,0 +1,237 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class HashCursorTest
+ {
+ private string testFixtureName;
+ private string testFixtureHome;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "HashCursorTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+ }
+
+ [Test]
+ public void TestAddToLoc()
+ {
+ HashDatabase db;
+ HashCursor cursor;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+
+ testName = "TestAddToLoc";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open a hash database and cursor and then
+ * add record("key", "data") into database.
+ */
+ GetHashDBAndCursor(testHome, testName, out db, out cursor);
+ AddOneByCursor(cursor);
+
+ /*
+ * Add the new record("key","data1") as the first
+ * of the data item of "key".
+ */
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data1")));
+ cursor.Add(pair, Cursor.InsertLocation.FIRST);
+
+ /*
+ * Confirm that the new record is added as the first of
+ * the data item of "key".
+ */
+ cursor.Move(new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")), true);
+ Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("data1"),
+ cursor.Current.Value.Data);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestAddUnique()
+ {
+ HashDatabase db;
+ HashCursor cursor;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+
+ testName = "TestAddUnique";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database and cursor.
+ HashDatabaseConfig dbConfig = new HashDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+
+ /*
+ * To put no duplicate data, the database should be
+ * set to be sorted.
+ */
+ dbConfig.Duplicates = DuplicatesPolicy.SORTED;
+ db = HashDatabase.Open(
+ testHome + "/" + testName + ".db", dbConfig);
+ cursor = db.Cursor();
+
+ // Add record("key", "data") into database.
+ AddOneByCursor(cursor);
+
+ /*
+ * Fail to add duplicate record("key","data").
+ */
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
+ try
+ {
+ cursor.AddUnique(pair);
+ }
+ catch (KeyExistException)
+ {
+ }
+ finally
+ {
+ cursor.Close();
+ db.Close();
+ }
+ }
+
+ [Test]
+ public void TestDuplicate()
+ {
+ HashDatabase db;
+ HashCursor cursor, dupCursor;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+
+ testName = "TestDuplicate";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ GetHashDBAndCursor(testHome, testName,
+ out db, out cursor);
+
+ /*
+ * Add a record("key", "data") by cursor and move
+ * the cursor to the current record.
+ */
+ AddOneByCursor(cursor);
+ cursor.Refresh();
+
+ //Duplicate a new cursor to the same position.
+ dupCursor = cursor.Duplicate(true);
+
+ // Overwrite the record.
+ dupCursor.Overwrite(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("newdata")));
+
+ // Confirm that the original data doesn't exist.
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
+ Assert.IsFalse(dupCursor.Move(pair, true));
+
+ dupCursor.Close();
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestInsertToLoc()
+ {
+ HashDatabase db;
+ HashDatabaseConfig dbConfig;
+ HashCursor cursor;
+ DatabaseEntry data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ string dbFileName;
+
+ testName = "TestInsertToLoc";
+ testHome = testFixtureHome + "/" + testName;
+ dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open database and cursor.
+ dbConfig = new HashDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+
+ /*
+ * The database should be set to be unsorted to
+ * insert before/after a certain record.
+ */
+ dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ db = HashDatabase.Open(dbFileName, dbConfig);
+ cursor = db.Cursor();
+
+ // Add record("key", "data") into database.
+ AddOneByCursor(cursor);
+
+ /*
+ * Insert the new record("key","data1") after the
+ * record("key", "data").
+ */
+ data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data1"));
+ cursor.Insert(data, Cursor.InsertLocation.AFTER);
+
+ /*
+ * Move the cursor to the record("key", "data") and
+ * confirm that the next record is the one just inserted.
+ */
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
+ Assert.IsTrue(cursor.Move(pair, true));
+ Assert.IsTrue(cursor.MoveNext());
+ Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("key"),
+ cursor.Current.Key.Data);
+ Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("data1"),
+ cursor.Current.Value.Data);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ public void GetHashDBAndCursor(string home, string name,
+ out HashDatabase db, out HashCursor cursor)
+ {
+ string dbFileName = home + "/" + name + ".db";
+ HashDatabaseConfig dbConfig = new HashDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ db = HashDatabase.Open(dbFileName, dbConfig);
+ cursor = db.Cursor();
+ }
+
+ public void AddOneByCursor(HashCursor cursor)
+ {
+ DatabaseEntry key, data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key"));
+ data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data"));
+ pair = new KeyValuePair<DatabaseEntry,DatabaseEntry>(key, data);
+ cursor.Add(pair);
+ }
+ }
+}
diff --git a/test/scr037/HashDatabaseConfigTest.cs b/test/scr037/HashDatabaseConfigTest.cs
new file mode 100644
index 0000000..ef18f8c
--- /dev/null
+++ b/test/scr037/HashDatabaseConfigTest.cs
@@ -0,0 +1,85 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class HashDatabaseConfigTest : DatabaseConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "HashDatabaseConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ override public void TestConfigWithoutEnv()
+ {
+ testName = "TestConfigWithoutEnv";
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ HashDatabaseConfig hashConfig = new HashDatabaseConfig();
+ Config(xmlElem, ref hashConfig, true);
+ Confirm(xmlElem, hashConfig, true);
+ }
+
+
+ public static void Confirm(XmlElement xmlElement,
+ HashDatabaseConfig hashDBConfig, bool compulsory)
+ {
+ DatabaseConfig dbConfig = hashDBConfig;
+ Confirm(xmlElement, dbConfig, compulsory);
+
+ // Confirm Hash database specific configuration.
+ Configuration.ConfirmCreatePolicy(xmlElement,
+ "Creation", hashDBConfig.Creation, compulsory);
+ Configuration.ConfirmDuplicatesPolicy(xmlElement,
+ "Duplicates", hashDBConfig.Duplicates, compulsory);
+ Configuration.ConfirmUint(xmlElement, "FillFactor",
+ hashDBConfig.FillFactor, compulsory);
+ Configuration.ConfirmUint(xmlElement, "NumElements",
+ hashDBConfig.TableSize, compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref HashDatabaseConfig hashDBConfig, bool compulsory)
+ {
+ uint fillFactor = new uint();
+ uint numElements = new uint();
+ DatabaseConfig dbConfig = hashDBConfig;
+ Config(xmlElement, ref dbConfig, compulsory);
+
+ // Configure specific fields/properties of Hash db
+ Configuration.ConfigCreatePolicy(xmlElement,
+ "Creation", ref hashDBConfig.Creation,
+ compulsory);
+ Configuration.ConfigDuplicatesPolicy(xmlElement,
+ "Duplicates", ref hashDBConfig.Duplicates,
+ compulsory);
+ if (Configuration.ConfigUint(xmlElement, "FillFactor",
+ ref fillFactor, compulsory))
+ hashDBConfig.FillFactor = fillFactor;
+ if (Configuration.ConfigUint(xmlElement, "NumElements",
+ ref numElements, compulsory))
+ hashDBConfig.TableSize = numElements;
+ }
+ }
+}
diff --git a/test/scr037/HashDatabaseTest.cs b/test/scr037/HashDatabaseTest.cs
new file mode 100644
index 0000000..b53ab62
--- /dev/null
+++ b/test/scr037/HashDatabaseTest.cs
@@ -0,0 +1,466 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class HashDatabaseTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "HashDatabaseTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestHashComparison()
+ {
+ testName = "TestHashComparison";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ Configuration.ClearDir(testHome);
+
+ HashDatabaseConfig dbConfig = new HashDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.HashComparison = new EntryComparisonDelegate(EntryComparison);
+ HashDatabase db = HashDatabase.Open(dbFileName,dbConfig);
+ int ret;
+
+ /*
+ * Comparison gets the value that lowest byte of the
+ * former dbt minus that of the latter one.
+ */
+ ret = db.Compare(new DatabaseEntry(BitConverter.GetBytes(2)),
+ new DatabaseEntry(BitConverter.GetBytes(2)));
+ Assert.AreEqual(0, ret);
+
+ ret = db.Compare(new DatabaseEntry(BitConverter.GetBytes(256)),
+ new DatabaseEntry(BitConverter.GetBytes(1)));
+ Assert.Greater(0, ret);
+
+ db.Close();
+ }
+
+ public int EntryComparison(DatabaseEntry dbt1,
+ DatabaseEntry dbt2)
+ {
+ return dbt1.Data[0] - dbt2.Data[0];
+ }
+
+ [Test]
+ public void TestHashFunction()
+ {
+ testName = "TestHashFunction";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ Configuration.ClearDir(testHome);
+
+ HashDatabaseConfig dbConfig = new HashDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.HashFunction = new HashFunctionDelegate(HashFunction);
+ HashDatabase db = HashDatabase.Open(dbFileName, dbConfig);
+
+ // Hash function will change the lowest byte to 0;
+ uint data = db.HashFunction(BitConverter.GetBytes(1));
+ Assert.AreEqual(0, data);
+ db.Close();
+ }
+
+ public uint HashFunction(byte[] data)
+ {
+ data[0] = 0;
+ return BitConverter.ToUInt32(data, 0);
+ }
+
+ [Test]
+ public void TestOpenExistingHashDB()
+ {
+ testName = "TestOpenExistingHashDB";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ HashDatabaseConfig hashConfig =
+ new HashDatabaseConfig();
+ hashConfig.Creation = CreatePolicy.ALWAYS;
+ HashDatabase hashDB = HashDatabase.Open(dbFileName, hashConfig);
+ hashDB.Close();
+
+ DatabaseConfig dbConfig = new DatabaseConfig();
+ Database db = Database.Open(dbFileName, dbConfig);
+ Assert.AreEqual(db.Type, DatabaseType.HASH);
+ db.Close();
+ }
+
+ [Test]
+ public void TestOpenNewHashDB()
+ {
+ testName = "TestOpenNewHashDB";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ XmlElement xmlElem = Configuration.TestSetUp(testFixtureName, testName);
+ HashDatabaseConfig hashConfig = new HashDatabaseConfig();
+ HashDatabaseConfigTest.Config(xmlElem, ref hashConfig, true);
+ HashDatabase hashDB = HashDatabase.Open(dbFileName, hashConfig);
+ Confirm(xmlElem, hashDB, true);
+ hashDB.Close();
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestPutNoDuplicateWithUnsortedDuplicate()
+ {
+ testName = "TestPutNoDuplicateWithUnsortedDuplicate";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ HashDatabaseConfig hashConfig = new HashDatabaseConfig();
+ hashConfig.Creation = CreatePolicy.ALWAYS;
+ hashConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ hashConfig.ErrorPrefix = testName;
+
+ HashDatabase hashDB = HashDatabase.Open(dbFileName, hashConfig);
+ DatabaseEntry key, data;
+ key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("1"));
+ data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("1"));
+
+ try
+ {
+ hashDB.PutNoDuplicate(key, data);
+ }
+ catch (DatabaseException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ hashDB.Close();
+ }
+ }
+
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestKeyExistException()
+ {
+ testName = "TestKeyExistException";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ HashDatabaseConfig hashConfig = new HashDatabaseConfig();
+ hashConfig.Creation = CreatePolicy.ALWAYS;
+ hashConfig.Duplicates = DuplicatesPolicy.SORTED;
+ HashDatabase hashDB = HashDatabase.Open(dbFileName, hashConfig);
+
+ // Put the same record into db twice.
+ DatabaseEntry key, data;
+ key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("1"));
+ data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("1"));
+ try
+ {
+ hashDB.PutNoDuplicate(key, data);
+ hashDB.PutNoDuplicate(key, data);
+ }
+ catch (KeyExistException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ hashDB.Close();
+ }
+ }
+
+ [Test]
+ public void TestPutNoDuplicate()
+ {
+ testName = "TestPutNoDuplicate";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ HashDatabaseConfig hashConfig =
+ new HashDatabaseConfig();
+ hashConfig.Creation = CreatePolicy.ALWAYS;
+ hashConfig.Duplicates = DuplicatesPolicy.SORTED;
+ hashConfig.TableSize = 20;
+ HashDatabase hashDB = HashDatabase.Open(dbFileName, hashConfig);
+
+ DatabaseEntry key, data;
+ for (int i = 1; i <= 10; i++)
+ {
+ key = new DatabaseEntry(BitConverter.GetBytes(i));
+ data = new DatabaseEntry(BitConverter.GetBytes(i));
+ hashDB.PutNoDuplicate(key, data);
+ }
+
+ Assert.IsTrue(hashDB.Exists(
+ new DatabaseEntry(BitConverter.GetBytes((int)5))));
+
+ hashDB.Close();
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestPutNoDuplicateWithTxn()
+ {
+ testName = "TestPutNoDuplicateWithTxn";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open an environment.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseLogging = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ // Open a hash database within a transaction.
+ Transaction txn = env.BeginTransaction();
+ HashDatabaseConfig dbConfig = new HashDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Duplicates = DuplicatesPolicy.SORTED;
+ dbConfig.Env = env;
+ HashDatabase db = HashDatabase.Open(testName + ".db", dbConfig, txn);
+
+ DatabaseEntry dbt = new DatabaseEntry(BitConverter.GetBytes((int)100));
+ db.PutNoDuplicate(dbt, dbt, txn);
+ try
+ {
+ db.PutNoDuplicate(dbt, dbt, txn);
+ }
+ catch (KeyExistException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ // Close all.
+ db.Close();
+ txn.Commit();
+ env.Close();
+ }
+ }
+
+ [Test]
+ public void TestStats()
+ {
+ testName = "TestStats";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ Configuration.ClearDir(testHome);
+
+ HashDatabaseConfig dbConfig = new HashDatabaseConfig();
+ ConfigCase1(dbConfig);
+ HashDatabase db = HashDatabase.Open(dbFileName, dbConfig);
+
+ HashStats stats = db.Stats();
+ HashStats fastStats = db.FastStats();
+ ConfirmStatsPart1Case1(stats);
+ ConfirmStatsPart1Case1(fastStats);
+
+ // Put 100 records into the database.
+ PutRecordCase1(db, null);
+
+ stats = db.Stats();
+ ConfirmStatsPart2Case1(stats);
+
+ // Delete some data to get some free pages.
+ byte[] bigArray = new byte[262144];
+ db.Delete(new DatabaseEntry(bigArray));
+ stats = db.Stats();
+ ConfirmStatsPart3Case1(stats);
+
+ db.Close();
+ }
+
+ [Test]
+ public void TestStatsInTxn()
+ {
+ testName = "TestStatsInTxn";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ StatsInTxn(testHome, testName, false);
+ }
+
+ [Test]
+ public void TestStatsWithIsolation()
+ {
+ testName = "TestStatsWithIsolation";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ StatsInTxn(testHome, testName, true);
+ }
+
+ public void StatsInTxn(string home, string name, bool ifIsolation)
+ {
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ EnvConfigCase1(envConfig);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(home, envConfig);
+
+ Transaction openTxn = env.BeginTransaction();
+ HashDatabaseConfig dbConfig = new HashDatabaseConfig();
+ ConfigCase1(dbConfig);
+ dbConfig.Env = env;
+ HashDatabase db = HashDatabase.Open(name + ".db", dbConfig, openTxn);
+ openTxn.Commit();
+
+ Transaction statsTxn = env.BeginTransaction();
+ HashStats stats;
+ HashStats fastStats;
+ if (ifIsolation == false)
+ {
+ stats = db.Stats(statsTxn);
+ fastStats = db.Stats(statsTxn);
+ }
+ else
+ {
+ stats = db.Stats(statsTxn, Isolation.DEGREE_ONE);
+ fastStats = db.Stats(statsTxn, Isolation.DEGREE_ONE);
+ }
+
+ ConfirmStatsPart1Case1(stats);
+
+ // Put 100 records into the database.
+ PutRecordCase1(db, statsTxn);
+
+ if (ifIsolation == false)
+ stats = db.Stats(statsTxn);
+ else
+ stats = db.Stats(statsTxn, Isolation.DEGREE_TWO);
+ ConfirmStatsPart2Case1(stats);
+
+ // Delete some data to get some free pages.
+ byte[] bigArray = new byte[262144];
+ db.Delete(new DatabaseEntry(bigArray), statsTxn);
+ if (ifIsolation == false)
+ stats = db.Stats(statsTxn);
+ else
+ stats = db.Stats(statsTxn, Isolation.DEGREE_THREE);
+ ConfirmStatsPart3Case1(stats);
+
+ statsTxn.Commit();
+ db.Close();
+ env.Close();
+ }
+
+ public void EnvConfigCase1(DatabaseEnvironmentConfig cfg)
+ {
+ cfg.Create = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.UseLogging = true;
+ }
+
+ public void ConfigCase1(HashDatabaseConfig dbConfig)
+ {
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ dbConfig.FillFactor = 10;
+ dbConfig.TableSize = 20;
+ dbConfig.PageSize = 4096;
+ }
+
+ public void PutRecordCase1(HashDatabase db, Transaction txn)
+ {
+ byte[] bigArray = new byte[262144];
+ for (int i = 0; i < 50; i++)
+ {
+ if (txn == null)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+ else
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)), txn);
+ }
+ for (int i = 50; i < 100; i++)
+ {
+ if (txn == null)
+ db.Put(new DatabaseEntry(bigArray),
+ new DatabaseEntry(bigArray));
+ else
+ db.Put(new DatabaseEntry(bigArray),
+ new DatabaseEntry(bigArray), txn);
+ }
+ }
+
+ public void ConfirmStatsPart1Case1(HashStats stats)
+ {
+ Assert.AreEqual(10, stats.FillFactor);
+ Assert.AreEqual(4096, stats.PageSize);
+ Assert.AreNotEqual(0, stats.Version);
+ }
+
+ public void ConfirmStatsPart2Case1(HashStats stats)
+ {
+ Assert.AreNotEqual(0, stats.BigPages);
+ Assert.AreNotEqual(0, stats.BigPagesFreeBytes);
+ Assert.AreNotEqual(0, stats.BucketPagesFreeBytes);
+ Assert.AreNotEqual(0, stats.DuplicatePages);
+ Assert.AreNotEqual(0, stats.DuplicatePagesFreeBytes);
+ Assert.AreNotEqual(0, stats.MagicNumber);
+ Assert.AreNotEqual(0, stats.MetadataFlags);
+ Assert.AreEqual(100, stats.nData);
+ Assert.AreNotEqual(0, stats.nHashBuckets);
+ Assert.AreEqual(51, stats.nKeys);
+ Assert.AreNotEqual(0, stats.nPages);
+ Assert.AreEqual(0, stats.OverflowPages);
+ Assert.AreEqual(0, stats.OverflowPagesFreeBytes);
+ }
+
+ public void ConfirmStatsPart3Case1(HashStats stats)
+ {
+ Assert.AreNotEqual(0, stats.FreePages);
+ }
+
+ public static void Confirm(XmlElement xmlElem,
+ HashDatabase hashDB, bool compulsory)
+ {
+ DatabaseTest.Confirm(xmlElem, hashDB, compulsory);
+ Configuration.ConfirmCreatePolicy(xmlElem,
+ "Creation", hashDB.Creation, compulsory);
+ Configuration.ConfirmDuplicatesPolicy(xmlElem,
+ "Duplicates", hashDB.Duplicates, compulsory);
+ Configuration.ConfirmUint(xmlElem,
+ "FillFactor", hashDB.FillFactor, compulsory);
+ Configuration.ConfirmUint(xmlElem,
+ "NumElements", hashDB.TableSize * hashDB.FillFactor,
+ compulsory);
+ Assert.AreEqual(DatabaseType.HASH, hashDB.Type);
+ string type = hashDB.Type.ToString();
+ Assert.IsNotNull(type);
+ }
+ }
+}
diff --git a/test/scr037/JoinCursorTest.cs b/test/scr037/JoinCursorTest.cs
new file mode 100644
index 0000000..15f8ade
--- /dev/null
+++ b/test/scr037/JoinCursorTest.cs
@@ -0,0 +1,204 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class JoinCursorTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "JoinCursorTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestJoin()
+ {
+ testName = "TestJoin";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string secFileName1 = testHome + "/" + "sec_" + testName + "1.db";
+ string secFileName2 = testHome + "/" + "sec_" + testName + "2.db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a primary database.
+ BTreeDatabaseConfig dbCfg = new BTreeDatabaseConfig();
+ dbCfg.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase db = BTreeDatabase.Open(dbFileName, dbCfg);
+
+ /*
+ * Open two databases, their secondary databases and
+ * secondary cursors.
+ */
+ SecondaryBTreeDatabase secDB1, secDB2;
+ SecondaryCursor[] cursors = new SecondaryCursor[2];
+ GetSecCursor(db, secFileName1,
+ new SecondaryKeyGenDelegate(KeyGenOnBigByte),
+ out secDB1, out cursors[0], false, null);
+ GetSecCursor(db, secFileName2,
+ new SecondaryKeyGenDelegate(KeyGenOnLittleByte),
+ out secDB2, out cursors[1], true, null);
+
+ // Get join cursor.
+ JoinCursor joinCursor = db.Join(cursors, true);
+
+ // Close all.
+ joinCursor.Close();
+ cursors[0].Close();
+ cursors[1].Close();
+ secDB1.Close();
+ secDB2.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveJoinCursor()
+ {
+ testName = "TestMoveJoinCursor";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string secFileName1 = testHome + "/" + "sec_" + testName + "1.db";
+ string secFileName2 = testHome + "/" + "sec_" + testName + "2.db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a primary database.
+ BTreeDatabaseConfig dbCfg = new BTreeDatabaseConfig();
+ dbCfg.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase db = BTreeDatabase.Open(dbFileName, dbCfg);
+
+ /*
+ * Open a secondary database on high byte of
+ * its data and another secondary database on
+ * little byte of its data.
+ */
+ SecondaryBTreeDatabase secDB1, secDB2;
+ SecondaryCursor[] cursors = new SecondaryCursor[2];
+ byte[] byteValue = new byte[1];
+
+ byteValue[0] = 0;
+ GetSecCursor(db, secFileName1,
+ new SecondaryKeyGenDelegate(KeyGenOnBigByte),
+ out secDB1, out cursors[0], false,
+ new DatabaseEntry(byteValue));
+
+ byteValue[0] = 1;
+ GetSecCursor(db, secFileName2,
+ new SecondaryKeyGenDelegate(KeyGenOnLittleByte),
+ out secDB2, out cursors[1], true,
+ new DatabaseEntry(byteValue));
+
+ // Get join cursor.
+ JoinCursor joinCursor = db.Join(cursors, true);
+
+ /*
+ * MoveNextJoinItem do not use data value found
+ * in all of the cursor so the data in Current won't be
+ * changed.
+ */
+ Assert.IsTrue(joinCursor.MoveNextItem());
+ Assert.AreEqual(0, joinCursor.Current.Key.Data[
+ joinCursor.Current.Key.Data.Length - 1]);
+ Assert.AreEqual(1, joinCursor.Current.Key.Data[0]);
+ Assert.IsNull(joinCursor.Current.Value.Data);
+
+ // Iterate on join cursor.
+ foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> pair in joinCursor)
+ {
+ /*
+ * Confirm that the key got by join cursor has 0 at
+ * its highest byte and 1 at its lowest byte.
+ */
+ Assert.AreEqual(0, pair.Key.Data[pair.Key.Data.Length - 1]);
+ Assert.AreEqual(1, pair.Key.Data[0]);
+ }
+
+ Assert.IsFalse(joinCursor.MoveNext());
+
+ // Close all.
+ joinCursor.Close();
+ cursors[0].Close();
+ cursors[1].Close();
+ secDB1.Close();
+ secDB2.Close();
+ db.Close();
+ }
+
+ public void GetSecCursor(BTreeDatabase db,
+ string secFileName, SecondaryKeyGenDelegate keyGen,
+ out SecondaryBTreeDatabase secDB,
+ out SecondaryCursor cursor, bool ifCfg,
+ DatabaseEntry data)
+ {
+ // Open secondary database.
+ SecondaryBTreeDatabaseConfig secCfg =
+ new SecondaryBTreeDatabaseConfig(db, keyGen);
+ secCfg.Creation = CreatePolicy.IF_NEEDED;
+ secCfg.Duplicates = DuplicatesPolicy.SORTED;
+ secDB = SecondaryBTreeDatabase.Open(secFileName, secCfg);
+
+ int[] intArray = new int[4];
+ intArray[0] = 0;
+ intArray[1] = 1;
+ intArray[2] = 2049;
+ intArray[3] = 65537;
+ for (int i = 0; i < 4; i++)
+ {
+ DatabaseEntry record = new DatabaseEntry(
+ BitConverter.GetBytes(intArray[i]));
+ db.Put(record, record);
+ }
+
+ // Get secondary cursor on the secondary database.
+ if (ifCfg == false)
+ cursor = secDB.SecondaryCursor();
+ else
+ cursor = secDB.SecondaryCursor(new CursorConfig());
+
+ // Position the cursor.
+ if (data != null)
+ Assert.IsTrue(cursor.Move(data, true));
+ }
+
+ public DatabaseEntry KeyGenOnLittleByte(
+ DatabaseEntry key, DatabaseEntry data)
+ {
+ byte[] byteArr = new byte[1];
+ byteArr[0] = data.Data[0];
+ DatabaseEntry dbtGen = new DatabaseEntry(byteArr);
+ return dbtGen;
+ }
+
+ public DatabaseEntry KeyGenOnBigByte(
+ DatabaseEntry key, DatabaseEntry data)
+ {
+ byte[] byteArr = new byte[1];
+ byteArr[0] = data.Data[data.Data.Length - 1];
+ DatabaseEntry dbtGen = new DatabaseEntry(byteArr);
+ return dbtGen;
+ }
+ }
+}
diff --git a/test/scr037/LockTest.cs b/test/scr037/LockTest.cs
new file mode 100644
index 0000000..bc4e3ad
--- /dev/null
+++ b/test/scr037/LockTest.cs
@@ -0,0 +1,116 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest {
+ [TestFixture]
+ public class LockTest {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests() {
+ testFixtureName = "LockTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ /*
+ * Delete existing test ouput directory and files specified
+ * for the current test fixture and then create a new one.
+ */
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestLockStats() {
+ testName = "TestLockManyAndStats";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ // Configure locking subsystem.
+ LockingConfig lkConfig = new LockingConfig();
+ lkConfig.MaxLockers = 60;
+ lkConfig.MaxLocks = 50;
+ lkConfig.MaxObjects = 70;
+ lkConfig.Partitions = 20;
+
+ // Configure and open environment.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.MPoolSystemCfg = new MPoolConfig();
+ envConfig.Create = true;
+ envConfig.LockSystemCfg = lkConfig;
+ envConfig.UseLocking = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ envConfig.ErrorPrefix = testName;
+ envConfig.NoLocking = false;
+ envConfig.LockTimeout = 1000;
+ envConfig.TxnTimeout = 2000;
+ envConfig.MPoolSystemCfg.CacheSize = new CacheInfo(0, 10485760, 1);
+ DatabaseEnvironment env =
+ DatabaseEnvironment.Open(testHome, envConfig);
+
+ // Get and confirm locking subsystem statistics.
+ LockStats stats = env.LockingSystemStats();
+ env.PrintLockingSystemStats(true, true);
+ Assert.AreEqual(1000, stats.LockTimeoutLength);
+ Assert.AreEqual(60, stats.MaxLockersInTable);
+ Assert.AreEqual(50, stats.MaxLocksInTable);
+ Assert.AreEqual(70, stats.MaxObjectsInTable);
+ Assert.AreNotEqual(0, stats.MaxUnusedID);
+ Assert.AreEqual(20, stats.nPartitions);
+ Assert.AreNotEqual(0, stats.RegionNoWait);
+ Assert.AreNotEqual(0, stats.RegionSize);
+ Assert.AreEqual(0, stats.RegionWait);
+ Assert.AreEqual(2000, stats.TxnTimeoutLength);
+
+ env.PrintLockingSystemStats();
+
+ env.Close();
+ }
+
+ public static void LockingEnvSetUp(string testHome,
+ string testName, out DatabaseEnvironment env,
+ uint maxLock, uint maxLocker, uint maxObject,
+ uint partition) {
+ // Configure env and locking subsystem.
+ LockingConfig lkConfig = new LockingConfig();
+ /*
+ * If the maximum number of locks/lockers/objects
+ * is given, then the LockingConfig is set. Unless,
+ * it is not set to any value.
+ */
+ if (maxLock != 0)
+ lkConfig.MaxLocks = maxLock;
+ if (maxLocker != 0)
+ lkConfig.MaxLockers = maxLocker;
+ if (maxObject != 0)
+ lkConfig.MaxObjects = maxObject;
+ if (partition != 0)
+ lkConfig.Partitions = partition;
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.LockSystemCfg = lkConfig;
+ envConfig.UseLocking = true;
+ envConfig.ErrorPrefix = testName;
+
+ env = DatabaseEnvironment.Open(testHome, envConfig);
+ }
+ }
+}
diff --git a/test/scr037/LockingConfigTest.cs b/test/scr037/LockingConfigTest.cs
new file mode 100644
index 0000000..82cf630
--- /dev/null
+++ b/test/scr037/LockingConfigTest.cs
@@ -0,0 +1,162 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class LockingConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "LockingConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+
+ // Configure the fields/properties.
+ LockingConfig lockingConfig = new LockingConfig();
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+
+ // Configure LockingConfig
+ Config(xmlElem, ref lockingConfig, true);
+
+ // Confirm LockingConfig
+ Confirm(xmlElem, lockingConfig, true);
+ }
+
+ [Test]
+ public void TestMaxLock() {
+ testName = "TestMaxLock";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironment env;
+ uint maxLocks;
+ DatabaseEntry obj;
+
+ maxLocks = 1;
+ obj = new DatabaseEntry();
+
+ /*
+ * Initialize environment using locking subsystem. The max number
+ * of locks should be larger than environment's partitions. So in
+ * order to make the MaxLock work, the environment paritition is
+ * set to be the same value as MaxLock.
+ */
+ LockTest.LockingEnvSetUp(testHome, testName, out env,
+ maxLocks, 0, 0, maxLocks);
+ Assert.AreEqual(maxLocks, env.MaxLocks);
+
+ env.Close();
+ }
+
+ [Test]
+ public void TestMaxLocker() {
+ testName = "TestMaxLocker";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironment env;
+ uint maxLockers;
+
+ maxLockers = 1;
+ LockTest.LockingEnvSetUp(testHome, testName, out env,
+ 0, maxLockers, 0, 0);
+ Assert.AreEqual(maxLockers, env.MaxLockers);
+ env.Close();
+ }
+
+ [Test]
+ public void TestMaxObjects() {
+ testName = "TestMaxObjects";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironment env;
+ uint maxObjects;
+
+ maxObjects = 1;
+
+ /*
+ * Initialize environment using locking subsystem. The max number
+ * of objects should be larger than environment's partitions. So
+ * in order to make the MaxObject work, the environment paritition
+ * is set to be the same value as MaxObject.
+ */
+ LockTest.LockingEnvSetUp(testHome, testName, out env, 0, 0,
+ maxObjects, maxObjects);
+ Assert.AreEqual(maxObjects, env.MaxObjects);
+ env.Close();
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ LockingConfig lockingConfig, bool compulsory)
+ {
+ Configuration.ConfirmByteMatrix(xmlElement, "Conflicts",
+ lockingConfig.Conflicts, compulsory);
+ Configuration.ConfirmDeadlockPolicy(xmlElement,
+ "DeadlockResolution",
+ lockingConfig.DeadlockResolution, compulsory);
+ Configuration.ConfirmUint(xmlElement, "MaxLockers",
+ lockingConfig.MaxLockers, compulsory);
+ Configuration.ConfirmUint(xmlElement, "MaxLocks",
+ lockingConfig.MaxLocks, compulsory);
+ Configuration.ConfirmUint(xmlElement, "MaxObjects",
+ lockingConfig.MaxObjects, compulsory);
+ Configuration.ConfirmUint(xmlElement, "Partitions",
+ lockingConfig.Partitions, compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref LockingConfig lockingConfig, bool compulsory)
+ {
+ byte[,] matrix = new byte[6, 6];
+ uint value = new uint();
+
+ if (Configuration.ConfigByteMatrix(xmlElement, "Conflicts",
+ ref matrix, compulsory) == true)
+ lockingConfig.Conflicts = matrix;
+
+ Configuration.ConfigDeadlockPolicy(xmlElement, "DeadlockResolution",
+ ref lockingConfig.DeadlockResolution, compulsory);
+ if (Configuration.ConfigUint(xmlElement, "MaxLockers",
+ ref value, compulsory))
+ lockingConfig.MaxLockers = value;
+ if (Configuration.ConfigUint(xmlElement, "MaxLocks",
+ ref value, compulsory))
+ lockingConfig.MaxLocks = value;
+ if (Configuration.ConfigUint(xmlElement, "MaxObjects",
+ ref value, compulsory))
+ lockingConfig.MaxObjects = value;
+ if (Configuration.ConfigUint(xmlElement, "Partitions",
+ ref value, compulsory))
+ lockingConfig.Partitions = value;
+ }
+
+ }
+}
diff --git a/test/scr037/LogConfigTest.cs b/test/scr037/LogConfigTest.cs
new file mode 100644
index 0000000..a49196f
--- /dev/null
+++ b/test/scr037/LogConfigTest.cs
@@ -0,0 +1,297 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class LogConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "LogConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+ /*
+ * Configure the fields/properties and see if
+ * they are updated successfully.
+ */
+ LogConfig logConfig = new LogConfig();
+ XmlElement xmlElem = Configuration.TestSetUp(testFixtureName, testName);
+ Config(xmlElem, ref logConfig, true);
+ Confirm(xmlElem, logConfig, true);
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestFullLogBufferException()
+ {
+ testName = "TestFullLogBufferException";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Open an environment and configured log subsystem.
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.Create = true;
+ cfg.TxnNoSync = true;
+ cfg.UseTxns = true;
+ cfg.UseLocking = true;
+ cfg.UseMPool = true;
+ cfg.UseLogging = true;
+ cfg.LogSystemCfg = new LogConfig();
+ cfg.LogSystemCfg.AutoRemove = false;
+ cfg.LogSystemCfg.BufferSize = 409600;
+ cfg.LogSystemCfg.MaxFileSize = 10480;
+ cfg.LogSystemCfg.NoBuffer = false;
+ cfg.LogSystemCfg.ZeroOnCreate = true;
+ cfg.LogSystemCfg.InMemory = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, cfg);
+
+ BTreeDatabase db;
+ try
+ {
+ Transaction openTxn = env.BeginTransaction();
+ try
+ {
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ db = BTreeDatabase.Open(testName + ".db", dbConfig, openTxn);
+ openTxn.Commit();
+ }
+ catch (DatabaseException e)
+ {
+ openTxn.Abort();
+ throw e;
+ }
+
+ Transaction writeTxn = env.BeginTransaction();
+ try
+ {
+ /*
+ * Writing 10 large records into in-memory logging
+ * database should throw FullLogBufferException since
+ * the amount of put data is larger than buffer size.
+ */
+ byte[] byteArr = new byte[204800];
+ for (int i = 0; i < 10; i++)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(byteArr), writeTxn);
+ writeTxn.Commit();
+ }
+ catch (Exception e)
+ {
+ writeTxn.Abort();
+ throw e;
+ }
+ finally
+ {
+ db.Close(true);
+ }
+ }
+ catch (FullLogBufferException e)
+ {
+ Assert.AreEqual(ErrorCodes.DB_LOG_BUFFER_FULL, e.ErrorCode);
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ env.Close();
+ }
+ }
+
+ [Test]
+ public void TestLoggingSystemStats()
+ {
+ testName = "TestLoggingSystemStats";
+ testHome = testFixtureHome + "/" + testName;
+ string logDir = "./";
+
+ Configuration.ClearDir(testHome);
+ Directory.CreateDirectory(testHome + "/" + logDir);
+
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.Create = true;
+ cfg.UseTxns = true;
+ cfg.AutoCommit = true;
+ cfg.UseLocking = true;
+ cfg.UseMPool = true;
+ cfg.UseLogging = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize = new CacheInfo(0, 1048576, 1);
+
+ cfg.LogSystemCfg = new LogConfig();
+ cfg.LogSystemCfg.AutoRemove = false;
+ cfg.LogSystemCfg.BufferSize = 10240;
+ cfg.LogSystemCfg.Dir = logDir;
+ cfg.LogSystemCfg.FileMode = 755;
+ cfg.LogSystemCfg.ForceSync = true;
+ cfg.LogSystemCfg.InMemory = false;
+ cfg.LogSystemCfg.MaxFileSize = 1048576;
+ cfg.LogSystemCfg.NoBuffer = false;
+ cfg.LogSystemCfg.RegionSize = 204800;
+ cfg.LogSystemCfg.ZeroOnCreate = true;
+
+ DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, cfg);
+
+ LogStats stats = env.LoggingSystemStats();
+ env.PrintLoggingSystemStats();
+ Assert.AreEqual(10240, stats.BufferSize);
+ Assert.AreEqual(1, stats.CurrentFile);
+ Assert.AreNotEqual(0, stats.CurrentOffset);
+ Assert.AreEqual(1048576, stats.FileSize);
+ Assert.AreNotEqual(0, stats.MagicNumber);
+ Assert.AreNotEqual(0, stats.PermissionsMode);
+ Assert.AreEqual(1, stats.Records);
+ Assert.AreNotEqual(0, stats.RegionLockNoWait);
+ Assert.LessOrEqual(204800, stats.RegionSize);
+ Assert.AreNotEqual(0, stats.Version);
+
+ Transaction openTxn = env.BeginTransaction();
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ BTreeDatabase db = BTreeDatabase.Open(testName + ".db", dbConfig, openTxn);
+ openTxn.Commit();
+
+ Transaction writeTxn = env.BeginTransaction();
+ byte[] byteArr = new byte[1024];
+ for (int i = 0; i < 1000; i++)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(byteArr), writeTxn);
+ writeTxn.Commit();
+
+ stats = env.LoggingSystemStats();
+ Assert.AreNotEqual(0, stats.Bytes);
+ Assert.AreNotEqual(0, stats.BytesSinceCheckpoint);
+ Assert.AreNotEqual(0, stats.DiskFileNumber);
+ Assert.AreNotEqual(0, stats.DiskOffset);
+ Assert.AreNotEqual(0, stats.MaxCommitsPerFlush);
+ Assert.AreNotEqual(0, stats.MBytes);
+ Assert.AreNotEqual(0, stats.MBytesSinceCheckpoint);
+ Assert.AreNotEqual(0, stats.MinCommitsPerFlush);
+ Assert.AreNotEqual(0, stats.OverflowWrites);
+ Assert.AreNotEqual(0, stats.Syncs);
+ Assert.AreNotEqual(0, stats.Writes);
+ Assert.AreEqual(0, stats.Reads);
+ Assert.AreEqual(0, stats.RegionLockWait);
+
+ stats = env.LoggingSystemStats(true);
+ stats = env.LoggingSystemStats();
+ Assert.AreEqual(0, stats.Bytes);
+ Assert.AreEqual(0, stats.BytesSinceCheckpoint);
+ Assert.AreEqual(0, stats.MaxCommitsPerFlush);
+ Assert.AreEqual(0, stats.MBytes);
+ Assert.AreEqual(0, stats.MBytesSinceCheckpoint);
+ Assert.AreEqual(0, stats.MinCommitsPerFlush);
+ Assert.AreEqual(0, stats.OverflowWrites);
+ Assert.AreEqual(0, stats.Syncs);
+ Assert.AreEqual(0, stats.Writes);
+ Assert.AreEqual(0, stats.Reads);
+
+ env.PrintLoggingSystemStats(true, true);
+
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestLsn()
+ {
+ testName = "TestLsn";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ LSN lsn = new LSN(12, 411);
+ Assert.AreEqual(12, lsn.LogFileNumber);
+ Assert.AreEqual(411, lsn.Offset);
+
+ LSN newLsn = new LSN(15, 410);
+ Assert.AreEqual(0, LSN.Compare(lsn, lsn));
+ Assert.Greater(0, LSN.Compare(lsn, newLsn));
+ }
+
+ public static void Confirm(XmlElement
+ xmlElement, LogConfig logConfig, bool compulsory)
+ {
+ Configuration.ConfirmBool(xmlElement, "AutoRemove",
+ logConfig.AutoRemove, compulsory);
+ Configuration.ConfirmUint(xmlElement, "BufferSize",
+ logConfig.BufferSize, compulsory);
+ Configuration.ConfirmString(xmlElement, "Dir",
+ logConfig.Dir, compulsory);
+ Configuration.ConfirmInt(xmlElement, "FileMode",
+ logConfig.FileMode, compulsory);
+ Configuration.ConfirmBool(xmlElement, "ForceSync",
+ logConfig.ForceSync, compulsory);
+ Configuration.ConfirmBool(xmlElement, "InMemory",
+ logConfig.InMemory, compulsory);
+ Configuration.ConfirmUint(xmlElement, "MaxFileSize",
+ logConfig.MaxFileSize, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoBuffer",
+ logConfig.NoBuffer, compulsory);
+ Configuration.ConfirmUint(xmlElement, "RegionSize",
+ logConfig.RegionSize, compulsory);
+ Configuration.ConfirmBool(xmlElement, "ZeroOnCreate",
+ logConfig.ZeroOnCreate, compulsory);
+ }
+
+ public static void Config(XmlElement
+ xmlElement, ref LogConfig logConfig, bool compulsory)
+ {
+ uint uintValue = new uint();
+ int intValue = new int();
+
+ Configuration.ConfigBool(xmlElement, "AutoRemove",
+ ref logConfig.AutoRemove, compulsory);
+ if (Configuration.ConfigUint(xmlElement, "BufferSize",
+ ref uintValue, compulsory))
+ logConfig.BufferSize = uintValue;
+ Configuration.ConfigString(xmlElement, "Dir",
+ ref logConfig.Dir, compulsory);
+ if (Configuration.ConfigInt(xmlElement, "FileMode",
+ ref intValue, compulsory))
+ logConfig.FileMode = intValue;
+ Configuration.ConfigBool(xmlElement, "ForceSync",
+ ref logConfig.ForceSync, compulsory);
+ Configuration.ConfigBool(xmlElement, "InMemory",
+ ref logConfig.InMemory, compulsory);
+ if (Configuration.ConfigUint(xmlElement, "MaxFileSize",
+ ref uintValue, compulsory))
+ logConfig.MaxFileSize = uintValue;
+ Configuration.ConfigBool(xmlElement, "NoBuffer",
+ ref logConfig.NoBuffer, compulsory);
+ if (Configuration.ConfigUint(xmlElement, "RegionSize",
+ ref uintValue, compulsory))
+ logConfig.RegionSize = uintValue;
+ Configuration.ConfigBool(xmlElement, "ZeroOnCreate",
+ ref logConfig.ZeroOnCreate, compulsory);
+ }
+ }
+}
diff --git a/test/scr037/LogCursorTest.cs b/test/scr037/LogCursorTest.cs
new file mode 100644
index 0000000..32a793a
--- /dev/null
+++ b/test/scr037/LogCursorTest.cs
@@ -0,0 +1,321 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class LogCursorTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+ DatabaseEnvironment env;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "LogCursorTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ /*
+ * Delete existing test ouput directory and files specified
+ * for the current test fixture and then create a new one.
+ */
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestClose()
+ {
+ testName = "TestClose";
+ testHome = testFixtureHome + "/" + testName;
+ DatabaseEnvironment env;
+ LogCursor logCursor;
+ RecnoDatabase db;
+
+ Logging(testHome, testName, out env, out db);
+
+ // Get log cursor to read/write log.
+ logCursor = env.GetLogCursor();
+
+ // Close the log cursor and env.
+ logCursor.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TesCurrentLSN()
+ {
+ testName = "TesCurrentLSN";
+ testHome = testFixtureHome + "/" + testName;
+ RecnoDatabase db;
+
+ Logging(testHome, testName, out env, out db);
+
+ // Get log cursor to read/write log.
+ LogCursor logCursor = env.GetLogCursor();
+
+ /*
+ * Move the cursor to the beginning of the #1 log file.
+ * Get the current LSN and confirm that is the position
+ * the cursor is moved to.
+ */
+ LSN lsn = new LSN(1, 0);
+ logCursor.Move(lsn);
+ Assert.AreEqual(lsn.LogFileNumber,
+ logCursor.CurrentLSN.LogFileNumber);
+ Assert.AreEqual(lsn.Offset, logCursor.CurrentLSN.Offset);
+
+ // Close all.
+ logCursor.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestCurrentRecord()
+ {
+ testName = "TestCurrentRecord";
+ testHome = testFixtureHome + "/" + testName;
+ DatabaseEnvironment env;
+ RecnoDatabase db;
+
+ Logging(testHome, testName, out env, out db);
+
+ // Get log cursor to read/write log.
+ LogCursor logCursor = env.GetLogCursor();
+
+ /*
+ * Move the cursor to the beginning of the #1 log file.
+ * Get the current LSN and confirm that is the position
+ * the cursor is moved to.
+ */
+ LSN lsn = new LSN(1, 0);
+ logCursor.Move(lsn);
+ Assert.IsNotNull(logCursor.CurrentRecord.Data);
+
+ // Close all.
+ logCursor.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestMove()
+ {
+ testName = "TestMove";
+ testHome = testFixtureHome + "/" + testName;
+ DatabaseEnvironment env;
+ RecnoDatabase db;
+
+ Logging(testHome, testName, out env, out db);
+
+ // Get log cursor to read/write log.
+ LogCursor logCursor = env.GetLogCursor();
+
+ // Move the cursor to specified location in log files.
+ LSN lsn = new LSN(1, 0);
+ Assert.IsTrue(logCursor.Move(lsn));
+
+ // Close all.
+ logCursor.Close();
+ db.Close();
+ env.Close();
+ }
+
+ /*
+ [Test]
+ public void TestMoveFirst()
+ {
+ testName = "TestMoveFirst";
+ testHome = testFixtureHome + "/" + testName;
+ DatabaseEnvironment env;
+ RecnoDatabase db;
+
+ Logging(testHome, testName, out env, out db);
+
+ // Get log cursor to read/write log.
+ LogCursor logCursor = env.GetLogCursor();
+
+ // Move to the first LSN in log file.
+ Assert.IsTrue(logCursor.MoveFirst());
+
+ // Confirm offset of the fist LSN should be 0.
+ Assert.AreEqual(0, logCursor.CurrentLSN.Offset);
+
+ // Close all.
+ logCursor.Close();
+ db.Close();
+ env.Close();
+ }
+ */
+
+ [Test]
+ public void TestMoveLast()
+ {
+ testName = "TestMoveLast";
+ testHome = testFixtureHome + "/" + testName;
+ DatabaseEnvironment env;
+ RecnoDatabase db;
+
+ Logging(testHome, testName, out env, out db);
+
+ // Get log cursor to read/write log.
+ LogCursor logCursor = env.GetLogCursor();
+
+ // Move to the last LSN in log file.
+ Assert.IsTrue(logCursor.MoveLast());
+
+ // The offset of last LSN shouldn't be 0.
+ Assert.AreNotEqual(0, logCursor.CurrentLSN.Offset);
+
+ // Close all.
+ logCursor.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestMoveNext()
+ {
+ testName = "TestMoveNext";
+ testHome = testFixtureHome + "/" + testName;
+ DatabaseEnvironment env;
+ RecnoDatabase db;
+
+ Logging(testHome, testName, out env, out db);
+
+ // Get log cursor to read/write log.
+ LogCursor logCursor = env.GetLogCursor();
+
+ logCursor.MoveLast();
+ DatabaseEntry curRec = logCursor.CurrentRecord;
+ for (int i = 0; i < 1000; i++)
+ db.Append(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("new data")));
+
+ Assert.IsTrue(logCursor.MoveNext());
+
+ logCursor.MoveNext();
+
+ // Close the log cursor.
+ logCursor.Close();
+ db.Close();
+ env.Close();
+ }
+
+
+ [Test]
+ public void TestMovePrev()
+ {
+ testName = "TestMovePrev";
+ testHome = testFixtureHome + "/" + testName;
+ DatabaseEnvironment env;
+ LSN lsn;
+ RecnoDatabase db;
+
+ Logging(testHome, testName, out env, out db);
+
+ // Get log cursor to read/write log.
+ LogCursor logCursor = env.GetLogCursor();
+
+ // Get the last two LSN in log file.
+ logCursor.MoveLast();
+ Assert.IsTrue(logCursor.MovePrev());
+
+ // Close all.
+ logCursor.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestRefresh()
+ {
+ testName = "TestRefresh";
+ testHome = testFixtureHome + "/" + testName;
+ DatabaseEnvironment env;
+ LSN lsn;
+ RecnoDatabase db;
+
+ Logging(testHome, testName, out env, out db);
+
+ // Get log cursor to read/write log.
+ LogCursor logCursor = env.GetLogCursor();
+
+ // Move the cursor to the last record.
+ logCursor.MoveLast();
+ DatabaseEntry curRec = logCursor.CurrentRecord;
+
+ // Put some new records into database.
+ for (int i = 0; i < 10; i++)
+ db.Append(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("new data")));
+
+ // Get the current record that cursor points to.
+ logCursor.Refresh();
+
+ // It shouldn't be changed.
+ Assert.AreEqual(curRec.Data,
+ logCursor.CurrentRecord.Data);
+
+ // Close all.
+ logCursor.Close();
+ db.Close();
+ env.Close();
+ }
+
+ /*
+ * Open environment, database and write data into database.
+ * Generated log files are put under testHome.
+ */
+ public void Logging(string home, string dbName,
+ out DatabaseEnvironment env, out RecnoDatabase recnoDB)
+ {
+ string dbFileName = dbName + ".db";
+
+ Configuration.ClearDir(home);
+
+ // Open environment with logging subsystem.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseLogging = true;
+ envConfig.LogSystemCfg = new LogConfig();
+ envConfig.LogSystemCfg.FileMode = 755;
+ envConfig.LogSystemCfg.ZeroOnCreate = true;
+ envConfig.UseMPool = true;
+ env = DatabaseEnvironment.Open(home, envConfig);
+
+ /*
+ * Open recno database, write 100000 records into
+ * the database and close it.
+ */
+ RecnoDatabaseConfig recnoConfig =
+ new RecnoDatabaseConfig();
+ recnoConfig.Creation = CreatePolicy.IF_NEEDED;
+ recnoConfig.Env = env;
+ // The db needs mpool to open.
+ recnoConfig.NoMMap = false;
+ recnoDB = RecnoDatabase.Open(dbFileName,
+ recnoConfig);
+ for (int i = 0; i < 1000; i++)
+ recnoDB.Append(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key")));
+ }
+ }
+}
diff --git a/test/scr037/MPoolConfigTest.cs b/test/scr037/MPoolConfigTest.cs
new file mode 100644
index 0000000..e92e4c0
--- /dev/null
+++ b/test/scr037/MPoolConfigTest.cs
@@ -0,0 +1,85 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class MPoolConfigTest
+ {
+ private string testFixtureName;
+ private string testName;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "MPoolConfigTest";
+ }
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+
+ // Config and confirm mpool subsystem configuration.
+ MPoolConfig mpoolConfig = new MPoolConfig();
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ Config(xmlElem, ref mpoolConfig, true);
+ Confirm(xmlElem, mpoolConfig, true);
+ }
+
+
+ public static void Confirm(XmlElement
+ xmlElement, MPoolConfig mpoolConfig, bool compulsory)
+ {
+ Configuration.ConfirmCacheSize(xmlElement,
+ "CacheSize", mpoolConfig.CacheSize, compulsory);
+ Configuration.ConfirmCacheSize(xmlElement,
+ "MaxCacheSize", mpoolConfig.MaxCacheSize,
+ compulsory);
+ Configuration.ConfirmInt(xmlElement, "MaxOpenFiles",
+ mpoolConfig.MaxOpenFiles, compulsory);
+ Configuration.ConfirmUint(xmlElement,
+ "MMapSize",
+ mpoolConfig.MMapSize, compulsory);
+ Configuration.ConfirmMaxSequentialWrites(xmlElement,
+ "MaxSequentialWrites",
+ mpoolConfig.SequentialWritePause,
+ mpoolConfig.MaxSequentialWrites, compulsory);
+ }
+
+ public static void Config(XmlElement
+ xmlElement, ref MPoolConfig mpoolConfig, bool compulsory)
+ {
+ uint uintValue = new uint();
+ int intValue = new int();
+
+ Configuration.ConfigCacheInfo(xmlElement,
+ "CacheSize", ref mpoolConfig.CacheSize, compulsory);
+ Configuration.ConfigCacheInfo(xmlElement,
+ "MaxCacheSize", ref mpoolConfig.MaxCacheSize,
+ compulsory);
+ if (Configuration.ConfigInt(xmlElement, "MaxOpenFiles",
+ ref intValue, compulsory))
+ mpoolConfig.MaxOpenFiles = intValue;
+ Configuration.ConfigMaxSequentialWrites(
+ xmlElement, "MaxSequentialWrites", mpoolConfig,
+ compulsory);
+ if (Configuration.ConfigUint(xmlElement,
+ "MMapSize", ref uintValue, compulsory))
+ mpoolConfig.MMapSize = uintValue;
+ }
+ }
+}
diff --git a/test/scr037/MutexConfigTest.cs b/test/scr037/MutexConfigTest.cs
new file mode 100644
index 0000000..d2d7e5f
--- /dev/null
+++ b/test/scr037/MutexConfigTest.cs
@@ -0,0 +1,82 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class MutexConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "MutexConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+
+ /*
+ * Configure the fields/properties and see if
+ * they are updated successfully.
+ */
+ MutexConfig lockingConfig = new MutexConfig();
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ Config(xmlElem, ref lockingConfig, true);
+ Confirm(xmlElem, lockingConfig, true);
+ }
+
+
+ public static void Confirm(XmlElement
+ xmlElement, MutexConfig mutexConfig, bool compulsory)
+ {
+ Configuration.ConfirmUint(xmlElement, "Alignment",
+ mutexConfig.Alignment, compulsory);
+ Configuration.ConfirmUint(xmlElement, "Increment",
+ mutexConfig.Increment, compulsory);
+ Configuration.ConfirmUint(xmlElement, "MaxMutexes",
+ mutexConfig.MaxMutexes, compulsory);
+ Configuration.ConfirmUint(xmlElement,
+ "NumTestAndSetSpins",
+ mutexConfig.NumTestAndSetSpins, compulsory);
+ }
+
+ public static void Config(XmlElement
+ xmlElement, ref MutexConfig mutexConfig, bool compulsory)
+ {
+ uint value = new uint();
+ if (Configuration.ConfigUint(xmlElement, "Alignment",
+ ref value, compulsory))
+ mutexConfig.Alignment = value;
+ if (Configuration.ConfigUint(xmlElement, "Increment",
+ ref value, compulsory))
+ mutexConfig.Increment = value;
+ if (Configuration.ConfigUint(xmlElement, "MaxMutexes",
+ ref value, compulsory))
+ mutexConfig.MaxMutexes = value;
+ if (Configuration.ConfigUint(xmlElement,
+ "NumTestAndSetSpins", ref value, compulsory))
+ mutexConfig.NumTestAndSetSpins = value;
+ }
+ }
+}
diff --git a/test/scr037/MutexTest.cs b/test/scr037/MutexTest.cs
new file mode 100644
index 0000000..0c9ddc6
--- /dev/null
+++ b/test/scr037/MutexTest.cs
@@ -0,0 +1,126 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class MutexTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ private BTreeDatabase TestDB;
+ private BerkeleyDB.Mutex TestMutex;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "MutexTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestGetAndFreeMutex()
+ {
+ testName = "TestGetAndFreeMutex";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseMPool = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+ BerkeleyDB.Mutex mutex = env.GetMutex(true, true);
+ mutex.Dispose();
+ env.Close();
+ }
+
+ [Test]
+ public void TestLockAndUnlockMutex()
+ {
+ testName = "TestLockAndUnlockMutex";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open an environment without locking and
+ * deadlock detection.
+ */
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.FreeThreaded = true;
+ envConfig.UseLogging = true;
+ envConfig.Create = true;
+ envConfig.UseMPool = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ // Open a database.
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ TestDB = BTreeDatabase.Open(
+ testName + ".db", dbConfig);
+
+ // Get a mutex which will be used in two threads.
+ TestMutex = env.GetMutex(true, false);
+
+ // Begin two threads to write records into database.
+ Thread mutexThread1 = new Thread(
+ new ThreadStart(MutexThread1));
+ Thread mutexThread2 = new Thread(
+ new ThreadStart(MutexThread2));
+ mutexThread1.Start();
+ mutexThread2.Start();
+ mutexThread1.Join();
+ mutexThread2.Join();
+
+ // Free the mutex.
+ TestMutex.Dispose();
+
+ // Close all.
+ TestDB.Close();
+ env.Close();
+ }
+
+ public void MutexThread1()
+ {
+ TestMutex.Lock();
+ for (int i = 0; i < 100; i++)
+ TestDB.Put(new DatabaseEntry(
+ BitConverter.GetBytes(i)),
+ new DatabaseEntry(new byte[102400]));
+ TestMutex.Unlock();
+ }
+
+ public void MutexThread2()
+ {
+ TestMutex.Lock();
+ for (int i = 0; i < 100; i++)
+ TestDB.Put(new DatabaseEntry(
+ BitConverter.GetBytes(i)),
+ new DatabaseEntry(new byte[102400]));
+ TestMutex.Unlock();
+ }
+ }
+}
diff --git a/test/scr037/QueueDatabaseConfigTest.cs b/test/scr037/QueueDatabaseConfigTest.cs
new file mode 100644
index 0000000..9586602
--- /dev/null
+++ b/test/scr037/QueueDatabaseConfigTest.cs
@@ -0,0 +1,88 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class QueueDatabaseConfigTest : DatabaseConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "QueueDatabaseConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ new public void TestConfigWithoutEnv()
+ {
+ testName = "TestConfigWithoutEnv";
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ QueueDatabaseConfig queueDBConfig =
+ new QueueDatabaseConfig();
+ Config(xmlElem, ref queueDBConfig, true);
+ Confirm(xmlElem, queueDBConfig, true);
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ QueueDatabaseConfig queueDBConfig, bool compulsory)
+ {
+ DatabaseConfig dbConfig = queueDBConfig;
+ Confirm(xmlElement, dbConfig, compulsory);
+
+ // Confirm Queue database specific configuration
+ Configuration.ConfirmBool(xmlElement, "ConsumeInOrder",
+ queueDBConfig.ConsumeInOrder, compulsory);
+ Configuration.ConfirmCreatePolicy(xmlElement, "Creation",
+ queueDBConfig.Creation, compulsory);
+ Configuration.ConfirmUint(xmlElement, "Length",
+ queueDBConfig.Length, compulsory);
+ Configuration.ConfirmInt(xmlElement, "PadByte",
+ queueDBConfig.PadByte, compulsory);
+ Configuration.ConfirmUint(xmlElement, "ExtentSize",
+ queueDBConfig.ExtentSize, compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref QueueDatabaseConfig queueDBConfig, bool compulsory)
+ {
+ uint uintValue = new uint();
+ int intValue = new int();
+ DatabaseConfig dbConfig = queueDBConfig;
+ Config(xmlElement, ref dbConfig, compulsory);
+
+ // Configure specific fields/properties of Queue database
+ Configuration.ConfigBool(xmlElement, "ConsumeInOrder",
+ ref queueDBConfig.ConsumeInOrder, compulsory);
+ Configuration.ConfigCreatePolicy(xmlElement, "Creation",
+ ref queueDBConfig.Creation, compulsory);
+ if (Configuration.ConfigUint(xmlElement, "Length",
+ ref uintValue, compulsory))
+ queueDBConfig.Length = uintValue;
+ if (Configuration.ConfigInt(xmlElement, "PadByte",
+ ref intValue, compulsory))
+ queueDBConfig.PadByte = intValue;
+ if (Configuration.ConfigUint(xmlElement, "ExtentSize",
+ ref uintValue, compulsory))
+ queueDBConfig.ExtentSize = uintValue;
+ }
+ }
+}
diff --git a/test/scr037/QueueDatabaseTest.cs b/test/scr037/QueueDatabaseTest.cs
new file mode 100644
index 0000000..4a0b03b
--- /dev/null
+++ b/test/scr037/QueueDatabaseTest.cs
@@ -0,0 +1,646 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class QueueDatabaseTest : DatabaseTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "QueueDatabaseTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestAppendWithoutTxn()
+ {
+ testName = "TestAppendWithoutTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string queueDBFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ QueueDatabaseConfig queueConfig = new QueueDatabaseConfig();
+ queueConfig.Creation = CreatePolicy.ALWAYS;
+ queueConfig.Length = 1000;
+ QueueDatabase queueDB = QueueDatabase.Open(
+ queueDBFileName, queueConfig);
+
+ byte[] byteArr = new byte[4];
+ byteArr = BitConverter.GetBytes((int)1);
+ DatabaseEntry data = new DatabaseEntry(byteArr);
+ uint recno = queueDB.Append(data);
+
+ // Confirm that the recno is larger than 0.
+ Assert.AreNotEqual(0, recno);
+
+ // Confirm that the record exists in the database.
+ byteArr = BitConverter.GetBytes(recno);
+ DatabaseEntry key = new DatabaseEntry();
+ key.Data = byteArr;
+ Assert.IsTrue(queueDB.Exists(key));
+ queueDB.Close();
+ }
+
+ [Test]
+ public void TestAppendWithTxn()
+ {
+ testName = "TestAppendWithTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string queueDBFileName = testHome + "/" + testName + ".db";
+ string queueDBName =
+ Path.GetFileNameWithoutExtension(queueDBFileName);
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+ Transaction txn = env.BeginTransaction();
+
+ QueueDatabaseConfig queueConfig = new QueueDatabaseConfig();
+ queueConfig.Creation = CreatePolicy.ALWAYS;
+ queueConfig.Env = env;
+ queueConfig.Length = 1000;
+
+ /* If environmnet home is set, the file name in
+ * Open() is the relative path.
+ */
+ QueueDatabase queueDB = QueueDatabase.Open(
+ queueDBName, queueConfig, txn);
+ DatabaseEntry data;
+ int i = 1000;
+ try
+ {
+ while (i > 0)
+ {
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ queueDB.Append(data, txn);
+ i--;
+ }
+ txn.Commit();
+ }
+ catch
+ {
+ txn.Abort();
+ }
+ finally
+ {
+ queueDB.Close();
+ env.Close();
+ }
+
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestConsumeWithTxn()
+ {
+ testName = "TestConsumeWithTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string queueDBFileName = testHome + "/" + testName + ".db";
+ string queueDBName = Path.GetFileName(queueDBFileName);
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+ Transaction txn = env.BeginTransaction();
+
+ QueueDatabaseConfig queueConfig =
+ new QueueDatabaseConfig();
+ queueConfig.Creation = CreatePolicy.ALWAYS;
+ queueConfig.Env = env;
+ queueConfig.Length = 1000;
+ QueueDatabase queueDB = QueueDatabase.Open(
+ queueDBName, queueConfig, txn);
+
+ int i = 1;
+ DatabaseEntry data;
+ DatabaseEntry getData = new DatabaseEntry();
+ while (i <= 10)
+ {
+ data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes(i.ToString()));
+ queueDB.Append(data, txn);
+ if (i == 5)
+ {
+ getData = data;
+ }
+ i++;
+ }
+
+ KeyValuePair<uint, DatabaseEntry> pair = queueDB.Consume(false, txn);
+
+ queueDB.Close();
+ txn.Commit();
+ env.Close();
+
+ Database db = Database.Open(queueDBFileName,
+ new QueueDatabaseConfig());
+ try
+ {
+ DatabaseEntry key =
+ new DatabaseEntry(BitConverter.GetBytes(pair.Key));
+ db.Get(key);
+ }
+ catch (NotFoundException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ db.Close();
+ }
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestConsumeWithoutTxn()
+ {
+ testName = "TestConsumeWithoutTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string queueDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ QueueDatabaseConfig queueConfig =
+ new QueueDatabaseConfig();
+ queueConfig.Creation = CreatePolicy.ALWAYS;
+ queueConfig.ErrorPrefix = testName;
+ queueConfig.Length = 1000;
+
+ QueueDatabase queueDB = QueueDatabase.Open(
+ queueDBFileName, queueConfig);
+ DatabaseEntry data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ queueDB.Append(data);
+
+ DatabaseEntry consumeData = new DatabaseEntry();
+ KeyValuePair<uint, DatabaseEntry> pair = queueDB.Consume(false);
+ try
+ {
+ DatabaseEntry key =
+ new DatabaseEntry(BitConverter.GetBytes(pair.Key));
+ queueDB.Get(key);
+ }
+ catch (NotFoundException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ queueDB.Close();
+ }
+ }
+
+ public void TestCursor()
+ {
+ testName = "TestCursor";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ GetCursur(testHome + "/" + testName + ".db", false);
+ }
+
+ public void TestCursorWithConfig()
+ {
+ testName = "TestCursorWithConfig";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ GetCursur(testHome + "/" + testName + ".db", true);
+ }
+
+ public void GetCursur(string dbFileName, bool ifConfig)
+ {
+ QueueDatabaseConfig dbConfig = new QueueDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Length = 100;
+ QueueDatabase db = QueueDatabase.Open(dbFileName, dbConfig);
+ Cursor cursor;
+ if (ifConfig == false)
+ cursor = db.Cursor();
+ else
+ cursor = db.Cursor(new CursorConfig());
+ cursor.Close();
+ db.Close();
+ }
+
+ //[Test]
+ //public void TestDupCompare()
+ //{
+ // testName = "TestDupCompare";
+ // testHome = testFixtureHome + "/" + testName;
+ // string dbFileName = testHome + "/" + testName + ".db";
+
+ // Configuration.ClearDir(testHome);
+
+ // QueueDatabaseConfig dbConfig = new QueueDatabaseConfig();
+ // dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ // dbConfig.DuplicateCompare = new EntryComparisonDelegate(dbIntCompare);
+ // dbConfig.Length = 10;
+ // dbConfig.PageSize = 40860;
+ // try
+ // {
+ // QueueDatabase db = QueueDatabase.Open(dbFileName, dbConfig);
+ // int ret = db.DupCompare(new DatabaseEntry(BitConverter.GetBytes(255)),
+ // new DatabaseEntry(BitConverter.GetBytes(257)));
+ // Assert.Greater(0, ret);
+ // db.Close();
+ // }
+ // catch (DatabaseException e)
+ // {
+ // Console.WriteLine(e.Message);
+ // }
+ //}
+
+ private int dbIntCompare(DatabaseEntry dbt1,
+ DatabaseEntry dbt2)
+ {
+ int a, b;
+ a = BitConverter.ToInt16(dbt1.Data, 0);
+ b = BitConverter.ToInt16(dbt2.Data, 0);
+ return a - b;
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestKeyEmptyException()
+ {
+ testName = "TestKeyEmptyException";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseLocking = true;
+ envConfig.UseLogging = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ QueueDatabase db;
+ try
+ {
+ Transaction openTxn = env.BeginTransaction();
+ try
+ {
+ QueueDatabaseConfig queueConfig =
+ new QueueDatabaseConfig();
+ queueConfig.Creation = CreatePolicy.IF_NEEDED;
+ queueConfig.Length = 10;
+ queueConfig.Env = env;
+ db = QueueDatabase.Open(testName + ".db",
+ queueConfig, openTxn);
+ openTxn.Commit();
+ }
+ catch (DatabaseException e)
+ {
+ openTxn.Abort();
+ throw e;
+ }
+
+ Transaction cursorTxn = env.BeginTransaction();
+ Cursor cursor;
+ try
+ {
+ /*
+ * Put a record into queue database with
+ * cursor and abort the operation.
+ */
+ cursor = db.Cursor(cursorTxn);
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ new DatabaseEntry(BitConverter.GetBytes((int)10)),
+ new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
+ cursor.Add(pair);
+ cursor.Close();
+ cursorTxn.Abort();
+ }
+ catch (DatabaseException e)
+ {
+ cursorTxn.Abort();
+ db.Close();
+ throw e;
+ }
+
+ Transaction delTxn = env.BeginTransaction();
+ try
+ {
+ /*
+ * The put operation is aborted in the queue
+ * database so querying if the record still exists
+ * throws KeyEmptyException.
+ */
+ db.Exists(new DatabaseEntry(
+ BitConverter.GetBytes((int)10)), delTxn);
+ delTxn.Commit();
+ }
+ catch (DatabaseException e)
+ {
+ delTxn.Abort();
+ throw e;
+ }
+ finally
+ {
+ db.Close();
+ }
+ }
+ catch (KeyEmptyException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ env.Close();
+ }
+ }
+
+ [Test]
+ public void TestOpenExistingQueueDB()
+ {
+ testName = "TestOpenExistingQueueDB";
+ testHome = testFixtureHome + "/" + testName;
+ string queueDBFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ QueueDatabaseConfig queueConfig = new QueueDatabaseConfig();
+ queueConfig.Creation = CreatePolicy.ALWAYS;
+ QueueDatabase queueDB = QueueDatabase.Open(
+ queueDBFileName, queueConfig);
+ queueDB.Close();
+
+ DatabaseConfig dbConfig = new DatabaseConfig();
+ Database db = Database.Open(queueDBFileName, dbConfig);
+ Assert.AreEqual(db.Type, DatabaseType.QUEUE);
+ db.Close();
+ }
+
+ [Test]
+ public void TestOpenNewQueueDB()
+ {
+ testName = "TestOpenNewQueueDB";
+ testHome = testFixtureHome + "/" + testName;
+ string queueDBFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Configure all fields/properties in queue database.
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ QueueDatabaseConfig queueConfig = new QueueDatabaseConfig();
+ QueueDatabaseConfigTest.Config(xmlElem, ref queueConfig, true);
+ queueConfig.Feedback = new DatabaseFeedbackDelegate(DbFeedback);
+
+ // Open the queue database with above configuration.
+ QueueDatabase queueDB = QueueDatabase.Open(
+ queueDBFileName, queueConfig);
+
+ // Check the fields/properties in opened queue database.
+ Confirm(xmlElem, queueDB, true);
+
+ queueDB.Close();
+ }
+
+ private void DbFeedback(DatabaseFeedbackEvent opcode, int percent)
+ {
+ if (opcode == DatabaseFeedbackEvent.UPGRADE)
+ Console.WriteLine("Update for %d%", percent);
+
+ if (opcode == DatabaseFeedbackEvent.VERIFY)
+ Console.WriteLine("Vertify for %d", percent);
+ }
+
+ [Test, ExpectedException(typeof(NotFoundException))]
+ public void TestPutToQueue()
+ {
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+
+ testName = "TestPutQueue";
+ testHome = testFixtureHome + "/" + testName;
+ string queueDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ QueueDatabaseConfig queueConfig =
+ new QueueDatabaseConfig();
+ queueConfig.Length = 512;
+ queueConfig.Creation = CreatePolicy.ALWAYS;
+ using (QueueDatabase queueDB = QueueDatabase.Open(
+ queueDBFileName, queueConfig))
+ {
+ DatabaseEntry key = new DatabaseEntry();
+ key.Data = BitConverter.GetBytes((int)100);
+ DatabaseEntry data = new DatabaseEntry(
+ BitConverter.GetBytes((int)1));
+ queueDB.Put(key, data);
+ pair = queueDB.GetBoth(key, data);
+ }
+ }
+
+ [Test]
+ public void TestStats()
+ {
+ testName = "TestStats";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" +
+ testName + ".db";
+ Configuration.ClearDir(testHome);
+
+ QueueDatabaseConfig dbConfig =
+ new QueueDatabaseConfig();
+ ConfigCase1(dbConfig);
+ QueueDatabase db = QueueDatabase.Open(dbFileName, dbConfig);
+
+ QueueStats stats = db.Stats();
+ ConfirmStatsPart1Case1(stats);
+ db.PrintFastStats(true);
+
+ // Put 500 records into the database.
+ PutRecordCase1(db, null);
+
+ stats = db.Stats();
+ ConfirmStatsPart2Case1(stats);
+ db.PrintFastStats();
+
+ db.Close();
+ }
+
+ [Test]
+ public void TestStatsInTxn()
+ {
+ testName = "TestStatsInTxn";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ StatsInTxn(testHome, testName, false);
+ }
+
+ [Test]
+ public void TestStatsWithIsolation()
+ {
+ testName = "TestStatsWithIsolation";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ StatsInTxn(testHome, testName, true);
+ }
+
+ public void StatsInTxn(string home, string name, bool ifIsolation)
+ {
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ EnvConfigCase1(envConfig);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConfig);
+
+ Transaction openTxn = env.BeginTransaction();
+ QueueDatabaseConfig dbConfig =
+ new QueueDatabaseConfig();
+ ConfigCase1(dbConfig);
+ dbConfig.Env = env;
+ QueueDatabase db = QueueDatabase.Open(name + ".db",
+ dbConfig, openTxn);
+ openTxn.Commit();
+
+ Transaction statsTxn = env.BeginTransaction();
+ QueueStats stats;
+ if (ifIsolation == false)
+ stats = db.Stats(statsTxn);
+ else
+ stats = db.Stats(statsTxn, Isolation.DEGREE_ONE);
+
+ ConfirmStatsPart1Case1(stats);
+ db.PrintStats(true);
+
+ // Put 500 records into the database.
+ PutRecordCase1(db, statsTxn);
+
+ if (ifIsolation == false)
+ stats = db.Stats(statsTxn);
+ else
+ stats = db.Stats(statsTxn, Isolation.DEGREE_TWO);
+ ConfirmStatsPart2Case1(stats);
+ db.PrintStats();
+
+ statsTxn.Commit();
+ db.Close();
+ env.Close();
+ }
+
+ public void EnvConfigCase1(DatabaseEnvironmentConfig cfg)
+ {
+ cfg.Create = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.UseLogging = true;
+ }
+
+ public void ConfigCase1(QueueDatabaseConfig dbConfig)
+ {
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.PageSize = 4096;
+ dbConfig.ExtentSize = 1024;
+ dbConfig.Length = 4000;
+ dbConfig.PadByte = 32;
+ }
+
+ public void PutRecordCase1(QueueDatabase db, Transaction txn)
+ {
+ byte[] bigArray = new byte[4000];
+ for (int i = 1; i <= 100; i++)
+ {
+ if (txn == null)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+ else
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)), txn);
+ }
+ DatabaseEntry key = new DatabaseEntry(BitConverter.GetBytes((int)100));
+ for (int i = 100; i <= 500; i++)
+ {
+ if (txn == null)
+ db.Put(key, new DatabaseEntry(bigArray));
+ else
+ db.Put(key, new DatabaseEntry(bigArray), txn);
+ }
+ }
+
+ public void ConfirmStatsPart1Case1(QueueStats stats)
+ {
+ Assert.AreEqual(1, stats.FirstRecordNumber);
+ Assert.AreNotEqual(0, stats.MagicNumber);
+ Assert.AreEqual(1, stats.NextRecordNumber);
+ Assert.AreEqual(4096, stats.PageSize);
+ Assert.AreEqual(1024, stats.PagesPerExtent);
+ Assert.AreEqual(4000, stats.RecordLength);
+ Assert.AreEqual(32, stats.RecordPadByte);
+ Assert.AreEqual(4, stats.Version);
+ }
+
+ public void ConfirmStatsPart2Case1(QueueStats stats)
+ {
+ Assert.AreNotEqual(0, stats.DataPages);
+ Assert.AreEqual(0, stats.DataPagesBytesFree);
+ Assert.AreEqual(0, stats.MetadataFlags);
+ Assert.AreEqual(100, stats.nData);
+ Assert.AreEqual(100, stats.nKeys);
+ }
+
+ public static void Confirm(XmlElement xmlElem,
+ QueueDatabase queueDB, bool compulsory)
+ {
+ DatabaseTest.Confirm(xmlElem, queueDB, compulsory);
+
+ // Confirm queue database specific field/property
+ Configuration.ConfirmUint(xmlElem, "ExtentSize",
+ queueDB.ExtentSize, compulsory);
+ Configuration.ConfirmBool(xmlElem, "ConsumeInOrder",
+ queueDB.InOrder, compulsory);
+ Configuration.ConfirmInt(xmlElem, "PadByte",
+ queueDB.PadByte, compulsory);
+ Assert.AreEqual(DatabaseType.QUEUE, queueDB.Type);
+ string type = queueDB.Type.ToString();
+ Assert.IsNotNull(type);
+ }
+ }
+}
diff --git a/test/scr037/README b/test/scr037/README
new file mode 100644
index 0000000..3e02730
--- /dev/null
+++ b/test/scr037/README
@@ -0,0 +1 @@
+test/scr037 is reserved for the forthcoming C# API tests \ No newline at end of file
diff --git a/test/scr037/RecnoCursorTest.cs b/test/scr037/RecnoCursorTest.cs
new file mode 100644
index 0000000..790372b
--- /dev/null
+++ b/test/scr037/RecnoCursorTest.cs
@@ -0,0 +1,257 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class RecnoCursorTest
+ {
+ private string testFixtureName;
+ private string testFixtureHome;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "RecnoCursorTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+ }
+
+ [Test]
+ public void TestCursor()
+ {
+ testName = "TestCursor";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ GetCursorWithImplicitTxn(testHome,
+ testName + ".db", false);
+ }
+
+ [Test]
+ public void TestCursorWithConfig()
+ {
+ testName = "TestCursorWithConfig";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ GetCursorWithImplicitTxn(testHome,
+ testName + ".db", true);
+ }
+
+ public void GetCursorWithImplicitTxn(string home,
+ string dbFile, bool ifConfig)
+ {
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseCDB = true;
+ envConfig.UseMPool = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConfig);
+
+ RecnoDatabaseConfig dbConfig =
+ new RecnoDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ RecnoDatabase db = RecnoDatabase.Open(dbFile,
+ dbConfig);
+
+ RecnoCursor cursor;
+ if (ifConfig == false)
+ cursor = db.Cursor();
+ else
+ cursor = db.Cursor(new CursorConfig());
+
+ cursor.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestCursorInTxn()
+ {
+ testName = "TestCursorInTxn";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ GetCursorWithExplicitTxn(testHome,
+ testName + ".db", false);
+ }
+
+ [Test]
+ public void TestConfigedCursorInTxn()
+ {
+ testName = "TestConfigedCursorInTxn";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ GetCursorWithExplicitTxn(testHome,
+ testName + ".db", true);
+ }
+
+ public void GetCursorWithExplicitTxn(string home,
+ string dbFile, bool ifConfig)
+ {
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConfig);
+
+ Transaction openTxn = env.BeginTransaction();
+ RecnoDatabaseConfig dbConfig =
+ new RecnoDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ RecnoDatabase db = RecnoDatabase.Open(dbFile,
+ dbConfig, openTxn);
+ openTxn.Commit();
+
+ Transaction cursorTxn = env.BeginTransaction();
+ RecnoCursor cursor;
+ if (ifConfig == false)
+ cursor = db.Cursor(cursorTxn);
+ else
+ cursor = db.Cursor(new CursorConfig(), cursorTxn);
+ cursor.Close();
+ cursorTxn.Commit();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestDuplicate()
+ {
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ RecnoDatabase db;
+ RecnoDatabaseConfig dbConfig;
+ RecnoCursor cursor, dupCursor;
+ string dbFileName;
+
+ testName = "TestDuplicate";
+ testHome = testFixtureHome + "/" + testName;
+ dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ dbConfig = new RecnoDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ db = RecnoDatabase.Open(dbFileName, dbConfig);
+ cursor = db.Cursor();
+
+ /*
+ * Add a record(1, 1) by cursor and move
+ * the cursor to the current record.
+ */
+ AddOneByCursor(cursor);
+ cursor.Refresh();
+
+ //Duplicate a new cursor to the same position.
+ dupCursor = cursor.Duplicate(true);
+
+ // Overwrite the record.
+ dupCursor.Overwrite(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("newdata")));
+
+ // Confirm that the original data doesn't exist.
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ new DatabaseEntry(
+ BitConverter.GetBytes((int)1)),
+ new DatabaseEntry(
+ BitConverter.GetBytes((int)1)));
+ Assert.IsFalse(dupCursor.Move(pair, true));
+
+ dupCursor.Close();
+ cursor.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestInsertToLoc()
+ {
+ RecnoDatabase db;
+ RecnoDatabaseConfig dbConfig;
+ RecnoCursor cursor;
+ DatabaseEntry data;
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ string dbFileName;
+
+ testName = "TestInsertToLoc";
+ testHome = testFixtureHome + "/" + testName;
+ dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open database and cursor.
+ dbConfig = new RecnoDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Renumber = true;
+ db = RecnoDatabase.Open(dbFileName, dbConfig);
+ cursor = db.Cursor();
+
+ // Add record(1,1) into database.
+ /*
+ * Add a record(1, 1) by cursor and move
+ * the cursor to the current record.
+ */
+ AddOneByCursor(cursor);
+ cursor.Refresh();
+
+ /*
+ * Insert the new record(1,10) after the
+ * record(1,1).
+ */
+ data = new DatabaseEntry(
+ BitConverter.GetBytes((int)10));
+ cursor.Insert(data, Cursor.InsertLocation.AFTER);
+
+ /*
+ * Move the cursor to the record(1,1) and
+ * confirm that the next record is the one just inserted.
+ */
+ pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ new DatabaseEntry(
+ BitConverter.GetBytes((int)1)),
+ new DatabaseEntry(
+ BitConverter.GetBytes((int)1)));
+ Assert.IsTrue(cursor.Move(pair, true));
+ Assert.IsTrue(cursor.MoveNext());
+ Assert.AreEqual(BitConverter.GetBytes((int)10),
+ cursor.Current.Value.Data);
+
+ cursor.Close();
+ db.Close();
+ }
+
+ public void AddOneByCursor(RecnoCursor cursor)
+ {
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair =
+ new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ new DatabaseEntry(
+ BitConverter.GetBytes((int)1)),
+ new DatabaseEntry(
+ BitConverter.GetBytes((int)1)));
+ cursor.Add(pair);
+ }
+ }
+}
diff --git a/test/scr037/RecnoDatabaseConfigTest.cs b/test/scr037/RecnoDatabaseConfigTest.cs
new file mode 100644
index 0000000..87e29a5
--- /dev/null
+++ b/test/scr037/RecnoDatabaseConfigTest.cs
@@ -0,0 +1,131 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class RecnoDatabaseConfigTest : DatabaseConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "RecnoDatabaseConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ override public void TestConfigWithoutEnv()
+ {
+ testName = "TestConfigWithoutEnv";
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+
+ RecnoDatabaseConfig recnoDBConfig =
+ new RecnoDatabaseConfig();
+ Config(xmlElem, ref recnoDBConfig, true);
+ Confirm(xmlElem, recnoDBConfig, true);
+ }
+
+ [Test]
+ public void TestAppend()
+ {
+ uint recno;
+
+ testName = "TestAppend";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ RecnoDatabaseConfig recnoConfig =
+ new RecnoDatabaseConfig();
+ recnoConfig.Creation = CreatePolicy.IF_NEEDED;
+ recnoConfig.Append = new AppendRecordDelegate(
+ AppendRecord);
+ RecnoDatabase recnoDB = RecnoDatabase.Open(
+ dbFileName, recnoConfig);
+ recno = recnoDB.Append(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data")));
+
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ pair = recnoDB.Get(
+ new DatabaseEntry(BitConverter.GetBytes(recno)));
+ Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("data"),
+ pair.Value.Data);
+
+ recnoDB.Close();
+ }
+
+ public void AppendRecord(DatabaseEntry data, uint recno)
+ {
+ data.Data = BitConverter.GetBytes(recno);
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ RecnoDatabaseConfig recnoDBConfig, bool compulsory)
+ {
+ DatabaseConfig dbConfig = recnoDBConfig;
+ Confirm(xmlElement, dbConfig, compulsory);
+
+ // Confirm Recno database specific configuration
+ Configuration.ConfirmString(xmlElement, "BackingFile",
+ recnoDBConfig.BackingFile, compulsory);
+ Configuration.ConfirmCreatePolicy(xmlElement,
+ "Creation", recnoDBConfig.Creation, compulsory);
+ Configuration.ConfirmInt(xmlElement, "Delimiter",
+ recnoDBConfig.Delimiter, compulsory);
+ Configuration.ConfirmUint(xmlElement, "Length",
+ recnoDBConfig.Length, compulsory);
+ Configuration.ConfirmInt(xmlElement, "PadByte",
+ recnoDBConfig.PadByte, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Renumber",
+ recnoDBConfig.Renumber, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Snapshot",
+ recnoDBConfig.Snapshot, compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref RecnoDatabaseConfig recnoDBConfig, bool compulsory)
+ {
+ int intValue = new int();
+ uint uintValue = new uint();
+ DatabaseConfig dbConfig = recnoDBConfig;
+ Config(xmlElement, ref dbConfig, compulsory);
+
+ // Configure specific fields/properties of Recno database
+ Configuration.ConfigCreatePolicy(xmlElement, "Creation",
+ ref recnoDBConfig.Creation, compulsory);
+ if (Configuration.ConfigInt(xmlElement, "Delimiter",
+ ref intValue, compulsory))
+ recnoDBConfig.Delimiter = intValue;
+ if (Configuration.ConfigUint(xmlElement, "Length",
+ ref uintValue, compulsory))
+ recnoDBConfig.Length = uintValue;
+ if (Configuration.ConfigInt(xmlElement, "PadByte",
+ ref intValue, compulsory))
+ recnoDBConfig.PadByte = intValue;
+ Configuration.ConfigBool(xmlElement, "Renumber",
+ ref recnoDBConfig.Renumber, compulsory);
+ Configuration.ConfigBool(xmlElement, "Snapshot",
+ ref recnoDBConfig.Snapshot, compulsory);
+ }
+ }
+}
diff --git a/test/scr037/RecnoDatabaseTest.cs b/test/scr037/RecnoDatabaseTest.cs
new file mode 100644
index 0000000..12238d7
--- /dev/null
+++ b/test/scr037/RecnoDatabaseTest.cs
@@ -0,0 +1,487 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class RecnoDatabaseTest : DatabaseTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "RecnoDatabaseTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestOpenExistingRecnoDB()
+ {
+ testName = "TestOpenExistingRecnoDB";
+ testHome = testFixtureHome + "/" + testName;
+ string recnoDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ RecnoDatabaseConfig recConfig =
+ new RecnoDatabaseConfig();
+ recConfig.Creation = CreatePolicy.ALWAYS;
+ RecnoDatabase recDB = RecnoDatabase.Open(
+ recnoDBFileName, recConfig);
+ recDB.Close();
+
+ RecnoDatabaseConfig dbConfig = new RecnoDatabaseConfig();
+ string backingFile = testHome + "/backingFile";
+ File.Copy(recnoDBFileName, backingFile);
+ dbConfig.BackingFile = backingFile;
+ RecnoDatabase db = RecnoDatabase.Open(recnoDBFileName, dbConfig);
+ Assert.AreEqual(db.Type, DatabaseType.RECNO);
+ db.Close();
+ }
+
+ [Test]
+ public void TestOpenNewRecnoDB()
+ {
+ RecnoDatabase recnoDB;
+ RecnoDatabaseConfig recnoConfig;
+
+ testName = "TestOpenNewRecnoDB";
+ testHome = testFixtureHome + "/" + testName;
+ string recnoDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ recnoConfig = new RecnoDatabaseConfig();
+ RecnoDatabaseConfigTest.Config(xmlElem,
+ ref recnoConfig, true);
+ recnoDB = RecnoDatabase.Open(recnoDBFileName,
+ recnoConfig);
+ Confirm(xmlElem, recnoDB, true);
+ recnoDB.Close();
+ }
+
+ [Test]
+ public void TestAppendWithoutTxn()
+ {
+ testName = "TestAppendWithoutTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string recnoDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ RecnoDatabaseConfig recnoConfig =
+ new RecnoDatabaseConfig();
+ recnoConfig.Creation = CreatePolicy.ALWAYS;
+ RecnoDatabase recnoDB = RecnoDatabase.Open(
+ recnoDBFileName, recnoConfig);
+
+ DatabaseEntry data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ uint num = recnoDB.Append(data);
+ DatabaseEntry key = new DatabaseEntry(
+ BitConverter.GetBytes(num));
+ Assert.IsTrue(recnoDB.Exists(key));
+ KeyValuePair<DatabaseEntry, DatabaseEntry> record =
+ recnoDB.Get(key);
+ Assert.IsTrue(data.Data.Length ==
+ record.Value.Data.Length);
+ for (int i = 0; i < data.Data.Length; i++)
+ Assert.IsTrue(data.Data[i] ==
+ record.Value.Data[i]);
+ recnoDB.Close();
+ }
+
+ [Test]
+ public void TestCompact()
+ {
+ testName = "TestCompact";
+ testHome = testFixtureHome + "/" + testName;
+ string recnoDBFileName = testHome + "/" +
+ testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ RecnoDatabaseConfig recnoConfig =
+ new RecnoDatabaseConfig();
+ recnoConfig.Creation = CreatePolicy.ALWAYS;
+ recnoConfig.Length = 512;
+
+ DatabaseEntry key, data;
+ RecnoDatabase recnoDB;
+ using (recnoDB = RecnoDatabase.Open(
+ recnoDBFileName, recnoConfig))
+ {
+ for (int i = 1; i <= 5000; i++)
+ {
+ data = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ recnoDB.Append(data);
+ }
+
+ for (int i = 1; i <= 5000; i++)
+ {
+ if (i > 500 && (i % 5 != 0))
+ {
+ key = new DatabaseEntry(
+ BitConverter.GetBytes(i));
+ recnoDB.Delete(key);
+ }
+ }
+
+ int startInt = 1;
+ int stopInt = 2500;
+ DatabaseEntry start, stop;
+
+ start = new DatabaseEntry(
+ BitConverter.GetBytes(startInt));
+ stop = new DatabaseEntry(
+ BitConverter.GetBytes(stopInt));
+ Assert.IsTrue(recnoDB.Exists(start));
+ Assert.IsTrue(recnoDB.Exists(stop));
+
+ CompactConfig cCfg = new CompactConfig();
+ cCfg.start = start;
+ cCfg.stop = stop;
+ cCfg.FillPercentage = 30;
+ cCfg.Pages = 1;
+ cCfg.returnEnd = true;
+ cCfg.Timeout = 5000;
+ cCfg.TruncatePages = true;
+ CompactData compactData = recnoDB.Compact(cCfg);
+
+ Assert.IsNotNull(compactData.End);
+ Assert.AreNotEqual(0, compactData.PagesExamined);
+ }
+ }
+
+ [Test]
+ public void TestStats()
+ {
+ testName = "TestStats";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" +
+ testName + ".db";
+ Configuration.ClearDir(testHome);
+
+ RecnoDatabaseConfig dbConfig =
+ new RecnoDatabaseConfig();
+ ConfigCase1(dbConfig);
+ RecnoDatabase db = RecnoDatabase.Open(dbFileName,
+ dbConfig);
+ RecnoStats stats = db.Stats();
+ ConfirmStatsPart1Case1(stats);
+
+ // Put 1000 records into the database.
+ PutRecordCase1(db, null);
+ stats = db.Stats();
+ ConfirmStatsPart2Case1(stats);
+
+ // Delete 500 records.
+ for (int i = 250; i <= 750; i++)
+ db.Delete(new DatabaseEntry(BitConverter.GetBytes(i)));
+ stats = db.Stats();
+ ConfirmStatsPart3Case1(stats);
+
+ db.Close();
+ }
+
+ [Test]
+ public void TestStatsInTxn()
+ {
+ testName = "TestStatsInTxn";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ StatsInTxn(testHome, testName, false);
+ }
+
+ [Test]
+ public void TestStatsWithIsolation()
+ {
+ testName = "TestStatsWithIsolation";
+ testHome = testFixtureHome + "/" + testName;
+ Configuration.ClearDir(testHome);
+
+ StatsInTxn(testHome, testName, true);
+ }
+
+ public void StatsInTxn(string home, string name, bool ifIsolation)
+ {
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ EnvConfigCase1(envConfig);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConfig);
+
+ Transaction openTxn = env.BeginTransaction();
+ RecnoDatabaseConfig dbConfig =
+ new RecnoDatabaseConfig();
+ ConfigCase1(dbConfig);
+ dbConfig.Env = env;
+ RecnoDatabase db = RecnoDatabase.Open(name + ".db",
+ dbConfig, openTxn);
+ openTxn.Commit();
+
+ Transaction statsTxn = env.BeginTransaction();
+ RecnoStats stats;
+ RecnoStats fastStats;
+ if (ifIsolation == false)
+ {
+ stats = db.Stats(statsTxn);
+ fastStats = db.FastStats(statsTxn);
+ }
+ else
+ {
+ stats = db.Stats(statsTxn, Isolation.DEGREE_ONE);
+ fastStats = db.FastStats(statsTxn,
+ Isolation.DEGREE_ONE);
+ }
+ ConfirmStatsPart1Case1(stats);
+
+ // Put 1000 records into the database.
+ PutRecordCase1(db, statsTxn);
+
+ if (ifIsolation == false)
+ {
+ stats = db.Stats(statsTxn);
+ fastStats = db.FastStats(statsTxn);
+ }
+ else
+ {
+ stats = db.Stats(statsTxn, Isolation.DEGREE_TWO);
+ fastStats = db.FastStats(statsTxn,
+ Isolation.DEGREE_TWO);
+ }
+ ConfirmStatsPart2Case1(stats);
+
+ // Delete 500 records.
+ for (int i = 250; i <= 750; i++)
+ db.Delete(new DatabaseEntry(BitConverter.GetBytes(i)),
+ statsTxn);
+
+ if (ifIsolation == false)
+ {
+ stats = db.Stats(statsTxn);
+ fastStats = db.FastStats(statsTxn);
+ }
+ else
+ {
+ stats = db.Stats(statsTxn, Isolation.DEGREE_THREE);
+ fastStats = db.FastStats(statsTxn,
+ Isolation.DEGREE_THREE);
+ }
+ ConfirmStatsPart3Case1(stats);
+
+ statsTxn.Commit();
+ db.Close();
+ env.Close();
+ }
+
+ public void EnvConfigCase1(DatabaseEnvironmentConfig cfg)
+ {
+ cfg.Create = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.UseLogging = true;
+ }
+
+ public void ConfigCase1(RecnoDatabaseConfig dbConfig)
+ {
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.PageSize = 4096;
+ dbConfig.Length = 4000;
+ dbConfig.PadByte = 256;
+ }
+
+ public void PutRecordCase1(RecnoDatabase db, Transaction txn)
+ {
+ for (int i = 1; i <= 1000; i++)
+ {
+ if (txn == null)
+ db.Put(new DatabaseEntry(
+ BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+ else
+ db.Put(new DatabaseEntry(
+ BitConverter.GetBytes(i)),
+ new DatabaseEntry(
+ BitConverter.GetBytes(i)), txn);
+ }
+ }
+
+ public void ConfirmStatsPart1Case1(RecnoStats stats)
+ {
+ Assert.AreEqual(1, stats.EmptyPages);
+ Assert.AreEqual(1, stats.Levels);
+ Assert.AreNotEqual(0, stats.MagicNumber);
+ Assert.AreEqual(10, stats.MetadataFlags);
+ Assert.AreEqual(2, stats.MinKey);
+ Assert.AreEqual(2, stats.nPages);
+ Assert.AreEqual(4096, stats.PageSize);
+ Assert.AreEqual(4000, stats.RecordLength);
+ Assert.AreEqual(256, stats.RecordPadByte);
+ Assert.AreEqual(9, stats.Version);
+ }
+
+ public void ConfirmStatsPart2Case1(RecnoStats stats)
+ {
+ Assert.AreEqual(0, stats.DuplicatePages);
+ Assert.AreEqual(0, stats.DuplicatePagesFreeBytes);
+ Assert.AreNotEqual(0, stats.InternalPages);
+ Assert.AreNotEqual(0, stats.InternalPagesFreeBytes);
+ Assert.AreNotEqual(0, stats.LeafPages);
+ Assert.AreNotEqual(0, stats.LeafPagesFreeBytes);
+ Assert.AreEqual(1000, stats.nData);
+ Assert.AreEqual(1000, stats.nKeys);
+ Assert.AreNotEqual(0, stats.OverflowPages);
+ Assert.AreNotEqual(0, stats.OverflowPagesFreeBytes);
+ }
+
+ public void ConfirmStatsPart3Case1(RecnoStats stats)
+ {
+ Assert.AreNotEqual(0, stats.FreePages);
+ }
+
+ [Test]
+ public void TestTruncateUnusedPages()
+ {
+ testName = "TestTruncateUnusedPages";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseCDB = true;
+ envConfig.UseMPool = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ RecnoDatabaseConfig dbConfig =
+ new RecnoDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ dbConfig.PageSize = 512;
+ RecnoDatabase db = RecnoDatabase.Open(
+ testName + ".db", dbConfig);
+
+ ModifyRecordsInDB(db, null);
+ Assert.Less(0, db.TruncateUnusedPages());
+
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestTruncateUnusedPagesInTxn()
+ {
+ testName = "TestTruncateUnusedPagesInTxn";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseLogging = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ testHome, envConfig);
+
+ Transaction openTxn = env.BeginTransaction();
+ RecnoDatabaseConfig dbConfig =
+ new RecnoDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ dbConfig.PageSize = 512;
+ RecnoDatabase db = RecnoDatabase.Open(
+ testName + ".db", dbConfig, openTxn);
+ openTxn.Commit();
+
+ Transaction modifyTxn = env.BeginTransaction();
+ ModifyRecordsInDB(db, modifyTxn);
+ Assert.Less(0, db.TruncateUnusedPages(modifyTxn));
+ modifyTxn.Commit();
+
+ db.Close();
+ env.Close();
+ }
+
+ public void ModifyRecordsInDB(RecnoDatabase db,
+ Transaction txn)
+ {
+ uint[] recnos = new uint[100];
+
+ if (txn == null)
+ {
+ // Add a lot of records into database.
+ for (int i = 0; i < 100; i++)
+ recnos[i] = db.Append(new DatabaseEntry(
+ new byte[10240]));
+
+ // Remove some records from database.
+ for (int i = 30; i < 100; i++)
+ db.Delete(new DatabaseEntry(
+ BitConverter.GetBytes(recnos[i])));
+ }
+ else
+ {
+ // Add a lot of records into database in txn.
+ for (int i = 0; i < 100; i++)
+ recnos[i] = db.Append(new DatabaseEntry(
+ new byte[10240]), txn);
+
+ // Remove some records from database in txn.
+ for (int i = 30; i < 100; i++)
+ db.Delete(new DatabaseEntry(
+ BitConverter.GetBytes(recnos[i])), txn);
+ }
+ }
+
+ public static void Confirm(XmlElement xmlElem,
+ RecnoDatabase recnoDB, bool compulsory)
+ {
+ DatabaseTest.Confirm(xmlElem, recnoDB, compulsory);
+
+ // Confirm recno database specific field/property
+ Configuration.ConfirmInt(xmlElem, "Delimiter",
+ recnoDB.RecordDelimiter, compulsory);
+ Configuration.ConfirmUint(xmlElem, "Length",
+ recnoDB.RecordLength, compulsory);
+ Configuration.ConfirmInt(xmlElem, "PadByte",
+ recnoDB.RecordPad, compulsory);
+ Configuration.ConfirmBool(xmlElem, "Renumber",
+ recnoDB.Renumber, compulsory);
+ Configuration.ConfirmBool(xmlElem, "Snapshot",
+ recnoDB.Snapshot, compulsory);
+ Assert.AreEqual(DatabaseType.RECNO, recnoDB.Type);
+ string type = recnoDB.Type.ToString();
+ Assert.IsNotNull(type);
+ }
+ }
+}
+
diff --git a/test/scr037/ReplicationConfigTest.cs b/test/scr037/ReplicationConfigTest.cs
new file mode 100644
index 0000000..3310c50
--- /dev/null
+++ b/test/scr037/ReplicationConfigTest.cs
@@ -0,0 +1,215 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class ReplicationConfigTest
+ {
+ private string testFixtureName;
+ private string testName;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "ReplicationConfigTest";
+ }
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+
+ ReplicationConfig repConfig = new ReplicationConfig();
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ Config(xmlElem, ref repConfig, true);
+ Confirm(xmlElem, repConfig, true);
+
+ repConfig.Clockskew(102, 100);
+ Assert.AreEqual(102, repConfig.ClockskewFast);
+ Assert.AreEqual(100, repConfig.ClockskewSlow);
+
+ repConfig.TransmitLimit(1, 1024);
+ Assert.AreEqual(1, repConfig.TransmitLimitGBytes);
+ Assert.AreEqual(1024, repConfig.TransmitLimitBytes);
+
+ repConfig.RetransmissionRequest(10, 100);
+ Assert.AreEqual(100, repConfig.RetransmissionRequestMax);
+ Assert.AreEqual(10, repConfig.RetransmissionRequestMin);
+ }
+
+ [Test]
+ public void TestRepMgrLocalSite()
+ {
+ string host = "127.0.0.0";
+ uint port = 8888;
+ testName = "TestRepMgrLocalSite";
+
+ ReplicationConfig repConfig1 = new ReplicationConfig();
+ repConfig1.RepMgrLocalSite = new ReplicationHostAddress();
+ repConfig1.RepMgrLocalSite.Host = host;
+ repConfig1.RepMgrLocalSite.Port = port;
+ Assert.AreEqual(host, repConfig1.RepMgrLocalSite.Host);
+ Assert.AreEqual(port, repConfig1.RepMgrLocalSite.Port);
+
+ ReplicationConfig repConfig2 = new ReplicationConfig();
+ repConfig2.RepMgrLocalSite =
+ new ReplicationHostAddress(host, port);
+ Assert.AreEqual(host, repConfig2.RepMgrLocalSite.Host);
+ Assert.AreEqual(port, repConfig2.RepMgrLocalSite.Port);
+
+ ReplicationConfig repConfig3 = new ReplicationConfig();
+ repConfig3.RepMgrLocalSite =
+ new ReplicationHostAddress(host + ":" + port);
+ Assert.AreEqual(host, repConfig3.RepMgrLocalSite.Host);
+ Assert.AreEqual(port, repConfig3.RepMgrLocalSite.Port);
+ }
+
+ [Test]
+ public void TestRepMgrAckPolicy()
+ {
+ testName = "TestRepMgrAckPolicy";
+
+ ReplicationConfig repConfig = new ReplicationConfig();
+ repConfig.RepMgrAckPolicy = AckPolicy.ALL;
+ Assert.AreEqual(AckPolicy.ALL,
+ repConfig.RepMgrAckPolicy);
+
+ repConfig.RepMgrAckPolicy = AckPolicy.ALL_PEERS;
+ Assert.AreEqual(AckPolicy.ALL_PEERS,
+ repConfig.RepMgrAckPolicy);
+
+ repConfig.RepMgrAckPolicy = AckPolicy.NONE;
+ Assert.AreEqual(AckPolicy.NONE,
+ repConfig.RepMgrAckPolicy);
+
+ repConfig.RepMgrAckPolicy = AckPolicy.ONE;
+ Assert.AreEqual(AckPolicy.ONE,
+ repConfig.RepMgrAckPolicy);
+
+ repConfig.RepMgrAckPolicy = AckPolicy.ONE_PEER;
+ Assert.AreEqual(AckPolicy.ONE_PEER,
+ repConfig.RepMgrAckPolicy);
+
+ repConfig.RepMgrAckPolicy = AckPolicy.QUORUM;
+ Assert.AreEqual(AckPolicy.QUORUM,
+ repConfig.RepMgrAckPolicy);
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ ReplicationConfig cfg, bool compulsory)
+ {
+ Configuration.ConfirmUint(xmlElement,
+ "AckTimeout", cfg.AckTimeout,
+ compulsory);
+ Configuration.ConfirmBool(xmlElement, "BulkTransfer",
+ cfg.BulkTransfer, compulsory);
+ Configuration.ConfirmUint(xmlElement, "CheckpointDelay",
+ cfg.CheckpointDelay, compulsory);
+ Configuration.ConfirmUint(xmlElement, "ConnectionRetry",
+ cfg.ConnectionRetry, compulsory);
+ Configuration.ConfirmBool(xmlElement, "DelayClientSync",
+ cfg.DelayClientSync, compulsory);
+ Configuration.ConfirmUint(xmlElement, "ElectionRetry",
+ cfg.ElectionRetry, compulsory);
+ Configuration.ConfirmUint(xmlElement, "ElectionTimeout",
+ cfg.ElectionTimeout, compulsory);
+ Configuration.ConfirmUint(xmlElement, "FullElectionTimeout",
+ cfg.FullElectionTimeout, compulsory);
+ Configuration.ConfirmUint(xmlElement, "HeartbeatMonitor",
+ cfg.HeartbeatMonitor, compulsory);
+ Configuration.ConfirmUint(xmlElement, "HeartbeatSend",
+ cfg.HeartbeatSend, compulsory);
+ Configuration.ConfirmUint(xmlElement, "LeaseTimeout",
+ cfg.LeaseTimeout, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoAutoInit",
+ cfg.NoAutoInit, compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoBlocking",
+ cfg.NoBlocking, compulsory);
+ Configuration.ConfirmUint(xmlElement, "NSites",
+ cfg.NSites, compulsory);
+ Configuration.ConfirmUint(xmlElement, "Priority",
+ cfg.Priority, compulsory);
+ Configuration.ConfirmAckPolicy(xmlElement,
+ "RepMgrAckPolicy", cfg.RepMgrAckPolicy, compulsory);
+ Configuration.ConfirmReplicationHostAddress(xmlElement,
+ "RepMgrLocalSite", cfg.RepMgrLocalSite, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Strict2Site",
+ cfg.Strict2Site, compulsory);
+ Configuration.ConfirmBool(xmlElement, "UseMasterLeases",
+ cfg.UseMasterLeases, compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref ReplicationConfig cfg, bool compulsory)
+ {
+ uint uintValue = new uint();
+
+ if (Configuration.ConfigUint(xmlElement, "AckTimeout",
+ ref uintValue, compulsory))
+ cfg.AckTimeout = uintValue;
+ Configuration.ConfigBool(xmlElement, "BulkTransfer",
+ ref cfg.BulkTransfer, compulsory);
+ if (Configuration.ConfigUint(xmlElement, "CheckpointDelay",
+ ref uintValue, compulsory))
+ cfg.CheckpointDelay = uintValue;
+ if (Configuration.ConfigUint(xmlElement, "ConnectionRetry",
+ ref uintValue, compulsory))
+ cfg.ConnectionRetry = uintValue;
+ Configuration.ConfigBool(xmlElement, "DelayClientSync",
+ ref cfg.DelayClientSync, compulsory);
+ if (Configuration.ConfigUint(xmlElement, "ElectionRetry",
+ ref uintValue, compulsory))
+ cfg.ElectionRetry = uintValue;
+ if (Configuration.ConfigUint(xmlElement, "ElectionTimeout",
+ ref uintValue, compulsory))
+ cfg.ElectionTimeout = uintValue;
+ if (Configuration.ConfigUint(xmlElement, "FullElectionTimeout",
+ ref uintValue, compulsory))
+ cfg.FullElectionTimeout = uintValue;
+ if (Configuration.ConfigUint(xmlElement, "HeartbeatMonitor",
+ ref uintValue, compulsory))
+ cfg.HeartbeatMonitor = uintValue;
+ if (Configuration.ConfigUint(xmlElement, "HeartbeatSend",
+ ref uintValue, compulsory))
+ cfg.HeartbeatSend = uintValue;
+ if (Configuration.ConfigUint(xmlElement, "LeaseTimeout",
+ ref uintValue, compulsory))
+ cfg.LeaseTimeout = uintValue;
+ Configuration.ConfigBool(xmlElement, "NoAutoInit",
+ ref cfg.NoAutoInit, compulsory);
+ Configuration.ConfigBool(xmlElement, "NoBlocking",
+ ref cfg.NoBlocking, compulsory);
+ if (Configuration.ConfigUint(xmlElement, "NSites",
+ ref uintValue, compulsory))
+ cfg.NSites = uintValue;
+ if (Configuration.ConfigUint(xmlElement, "Priority",
+ ref uintValue, compulsory))
+ cfg.Priority = uintValue;
+ Configuration.ConfigAckPolicy(xmlElement,
+ "RepMgrAckPolicy", ref cfg.RepMgrAckPolicy,
+ compulsory);
+ cfg.RepMgrLocalSite = new ReplicationHostAddress();
+ Configuration.ConfigReplicationHostAddress(xmlElement,
+ "RepMgrLocalSite", ref cfg.RepMgrLocalSite, compulsory);
+ Configuration.ConfigBool(xmlElement, "Strict2Site",
+ ref cfg.Strict2Site, compulsory);
+ Configuration.ConfigBool(xmlElement, "UseMasterLeases",
+ ref cfg.UseMasterLeases, compulsory);
+ }
+
+ }
+} \ No newline at end of file
diff --git a/test/scr037/ReplicationTest.cs b/test/scr037/ReplicationTest.cs
new file mode 100644
index 0000000..938689b
--- /dev/null
+++ b/test/scr037/ReplicationTest.cs
@@ -0,0 +1,748 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class ReplicationTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ private EventWaitHandle clientStartSignal;
+ private EventWaitHandle masterCloseSignal;
+
+ private EventWaitHandle client1StartSignal;
+ private EventWaitHandle client1ReadySignal;
+ private EventWaitHandle client2StartSignal;
+ private EventWaitHandle client2ReadySignal;
+ private EventWaitHandle client3StartSignal;
+ private EventWaitHandle client3ReadySignal;
+ private EventWaitHandle masterLeaveSignal;
+
+ [TestFixtureSetUp]
+ public void SetUp()
+ {
+ testFixtureName = "ReplicationTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+ try
+ {
+ Configuration.ClearDir(testFixtureHome);
+ }
+ catch (Exception)
+ {
+ throw new TestException("Please clean the directory");
+ }
+ }
+
+ [Test]
+ public void TestRepMgr()
+ {
+ testName = "TestRepMgr";
+ testHome = testFixtureHome + "/" + testName;
+
+ clientStartSignal = new AutoResetEvent(false);
+ masterCloseSignal = new AutoResetEvent(false);
+
+ Thread thread1 = new Thread(new ThreadStart(Master));
+ Thread thread2 = new Thread(new ThreadStart(Client));
+
+ // Start master thread before client thread.
+ thread1.Start();
+ Thread.Sleep(1000);
+ thread2.Start();
+ thread2.Join();
+ thread1.Join();
+
+ clientStartSignal.Close();
+ masterCloseSignal.Close();
+ }
+
+ public void Master()
+ {
+ string home = testHome + "/Master";
+ string dbName = "rep.db";
+ Configuration.ClearDir(home);
+
+ /*
+ * Configure and open environment with replication
+ * application.
+ */
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.UseReplication = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 20485760, 1);
+ cfg.UseLocking = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.Create = true;
+ cfg.UseLogging = true;
+ cfg.RunRecovery = true;
+ cfg.TxnNoSync = true;
+ cfg.FreeThreaded = true;
+ cfg.RepSystemCfg = new ReplicationConfig();
+ cfg.RepSystemCfg.RepMgrLocalSite =
+ new ReplicationHostAddress("127.0.0.1", 8870);
+ cfg.RepSystemCfg.Priority = 100;
+ cfg.RepSystemCfg.NSites = 2;
+ cfg.RepSystemCfg.BulkTransfer = true;
+ cfg.RepSystemCfg.AckTimeout = 2000;
+ cfg.RepSystemCfg.BulkTransfer = true;
+ cfg.RepSystemCfg.CheckpointDelay = 1500;
+ cfg.RepSystemCfg.Clockskew(102, 100);
+ cfg.RepSystemCfg.ConnectionRetry = 10;
+ cfg.RepSystemCfg.DelayClientSync = false;
+ cfg.RepSystemCfg.ElectionRetry = 5;
+ cfg.RepSystemCfg.ElectionTimeout = 3000;
+ cfg.RepSystemCfg.FullElectionTimeout = 5000;
+ cfg.RepSystemCfg.HeartbeatMonitor = 100;
+ cfg.RepSystemCfg.HeartbeatSend = 10;
+ cfg.RepSystemCfg.LeaseTimeout = 1300;
+ cfg.RepSystemCfg.NoAutoInit = false;
+ cfg.RepSystemCfg.NoBlocking = false;
+ cfg.RepSystemCfg.RepMgrAckPolicy =
+ AckPolicy.ALL_PEERS;
+ cfg.RepSystemCfg.RetransmissionRequest(10, 100);
+ cfg.RepSystemCfg.Strict2Site = true;
+ cfg.RepSystemCfg.UseMasterLeases = false;
+ cfg.EventNotify = new EventNotifyDelegate(stuffHappened);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, cfg);
+
+ // Get initial replication stats.
+ ReplicationStats repStats = env.ReplicationSystemStats();
+ env.PrintReplicationSystemStats();
+ Assert.AreEqual(100, repStats.EnvPriority);
+ Assert.AreEqual(1,
+ repStats.CurrentElectionGenerationNumber);
+ Assert.AreEqual(0, repStats.CurrentGenerationNumber);
+ Assert.AreEqual(0, repStats.AppliedTransactions);
+
+ // Start a master site with replication manager.
+ env.RepMgrStartMaster(3);
+
+ // Open a btree database and write some data.
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.AutoCommit = true;
+ dbConfig.Env = env;
+ dbConfig.PageSize = 512;
+ BTreeDatabase db = BTreeDatabase.Open(dbName,
+ dbConfig);
+ for (int i = 0; i < 5; i++)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+
+ Console.WriteLine(
+ "Master: Finished initialization and data#1.");
+
+ // Client site could enter now.
+ clientStartSignal.Set();
+ Console.WriteLine(
+ "Master: Wait for Client to join and get #1.");
+
+ Console.WriteLine("...");
+
+ // Put some new data into master site.
+ for (int i = 10; i < 15; i++)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+ Console.WriteLine(
+ "Master: Write something new, data #2.");
+ Console.WriteLine("Master: Wait for client to read #2...");
+
+ // Get the stats.
+ repStats = env.ReplicationSystemStats(true);
+ env.PrintReplicationSystemStats();
+ Assert.LessOrEqual(0, repStats.AppliedTransactions);
+ Assert.LessOrEqual(0, repStats.AwaitedLSN.LogFileNumber);
+ Assert.LessOrEqual(0, repStats.AwaitedLSN.Offset);
+ Assert.LessOrEqual(0, repStats.AwaitedPage);
+ Assert.LessOrEqual(0, repStats.BadGenerationMessages);
+ Assert.LessOrEqual(0, repStats.BulkBufferFills);
+ Assert.LessOrEqual(0, repStats.BulkBufferOverflows);
+ Assert.LessOrEqual(0, repStats.BulkBufferTransfers);
+ Assert.LessOrEqual(0, repStats.BulkRecordsStored);
+ Assert.LessOrEqual(0, repStats.ClientServiceRequests);
+ Assert.LessOrEqual(0, repStats.ClientServiceRequestsMissing);
+ Assert.IsInstanceOfType(typeof(bool), repStats.ClientStartupComplete);
+ Assert.AreEqual(2, repStats.CurrentElectionGenerationNumber);
+ Assert.AreEqual(1, repStats.CurrentGenerationNumber);
+ Assert.LessOrEqual(0, repStats.CurrentQueuedLogRecords);
+ Assert.LessOrEqual(0, repStats.CurrentWinner);
+ Assert.LessOrEqual(0, repStats.CurrentWinnerMaxLSN.LogFileNumber);
+ Assert.LessOrEqual(0, repStats.CurrentWinnerMaxLSN.Offset);
+ Assert.LessOrEqual(0, repStats.DuplicateLogRecords);
+ Assert.LessOrEqual(0, repStats.DuplicatePages);
+ Assert.LessOrEqual(0, repStats.DupMasters);
+ Assert.LessOrEqual(0, repStats.ElectionGenerationNumber);
+ Assert.LessOrEqual(0, repStats.ElectionPriority);
+ Assert.LessOrEqual(0, repStats.Elections);
+ Assert.LessOrEqual(0, repStats.ElectionStatus);
+ Assert.LessOrEqual(0, repStats.ElectionsWon);
+ Assert.LessOrEqual(0, repStats.ElectionTiebreaker);
+ Assert.LessOrEqual(0, repStats.ElectionTimeSec);
+ Assert.LessOrEqual(0, repStats.ElectionTimeUSec);
+ Assert.AreEqual(repStats.EnvID, repStats.MasterEnvID);
+ Assert.LessOrEqual(0, repStats.EnvPriority);
+ Assert.LessOrEqual(0, repStats.FailedMessageSends);
+ Assert.LessOrEqual(0, repStats.ForcedRerequests);
+ Assert.LessOrEqual(0, repStats.IgnoredMessages);
+ Assert.LessOrEqual(0, repStats.MasterChanges);
+ Assert.LessOrEqual(0, repStats.MasterEnvID);
+ Assert.LessOrEqual(0, repStats.MaxLeaseSec);
+ Assert.LessOrEqual(0, repStats.MaxLeaseUSec);
+ Assert.LessOrEqual(0, repStats.MaxPermanentLSN.Offset);
+ Assert.LessOrEqual(0, repStats.MaxQueuedLogRecords);
+ Assert.LessOrEqual(0, repStats.MessagesSent);
+ Assert.LessOrEqual(0, repStats.MissedLogRecords);
+ Assert.LessOrEqual(0, repStats.MissedPages);
+ Assert.LessOrEqual(0, repStats.NewSiteMessages);
+ Assert.LessOrEqual(repStats.MaxPermanentLSN.LogFileNumber,
+ repStats.NextLSN.LogFileNumber);
+ if (repStats.MaxPermanentLSN.LogFileNumber ==
+ repStats.NextLSN.LogFileNumber)
+ Assert.Less(repStats.MaxPermanentLSN.Offset,
+ repStats.NextLSN.Offset);
+ Assert.LessOrEqual(0, repStats.NextPage);
+ Assert.LessOrEqual(0, repStats.Outdated);
+ Assert.LessOrEqual(0, repStats.QueuedLogRecords);
+ Assert.LessOrEqual(0, repStats.ReceivedLogRecords);
+ Assert.LessOrEqual(0, repStats.ReceivedMessages);
+ Assert.LessOrEqual(0, repStats.ReceivedPages);
+ Assert.LessOrEqual(0, repStats.RegisteredSites);
+ Assert.LessOrEqual(0, repStats.RegisteredSitesNeeded);
+ Assert.LessOrEqual(0, repStats.Sites);
+ Assert.LessOrEqual(0, repStats.StartSyncMessagesDelayed);
+ Assert.AreEqual(2, repStats.Status);
+ Assert.LessOrEqual(0, repStats.Throttled);
+ Assert.LessOrEqual(0, repStats.Votes);
+
+ // Get replication manager statistics.
+ RepMgrStats repMgrStats = env.RepMgrSystemStats(true);
+ Assert.LessOrEqual(0, repMgrStats.DroppedConnections);
+ Assert.LessOrEqual(0, repMgrStats.DroppedMessages);
+ Assert.LessOrEqual(0, repMgrStats.FailedConnections);
+ Assert.LessOrEqual(0, repMgrStats.FailedMessages);
+ Assert.LessOrEqual(0, repMgrStats.QueuedMessages);
+
+ // Print them out.
+ env.PrintRepMgrSystemStats();
+
+ // Wait until client has finished reading.
+ masterCloseSignal.WaitOne();
+ Console.WriteLine("Master: Leave as well.");
+
+ // Close all.
+ db.Close(false);
+ env.LogFlush();
+ env.Close();
+ }
+
+ public void Client()
+ {
+ string home = testHome + "/Client";
+ Configuration.ClearDir(home);
+
+ clientStartSignal.WaitOne();
+ Console.WriteLine("Client: Join the replication");
+
+ // Open a environment.
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.UseReplication = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 20485760, 1);
+ cfg.UseLocking = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.Create = true;
+ cfg.UseLogging = true;
+ cfg.RunRecovery = true;
+ cfg.TxnNoSync = true;
+ cfg.FreeThreaded = true;
+ cfg.LockTimeout = 50000;
+ cfg.RepSystemCfg = new ReplicationConfig();
+ cfg.RepSystemCfg.RepMgrLocalSite =
+ new ReplicationHostAddress("127.0.0.1", 6870);
+ cfg.RepSystemCfg.Priority = 10;
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 8870), false);
+ cfg.RepSystemCfg.NSites = 2;
+ cfg.EventNotify = new EventNotifyDelegate(stuffHappened);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, cfg);
+
+ // Start a client site with replication manager.
+ env.RepMgrStartClient(3, false);
+
+ // Leave enough time to sync.
+ Thread.Sleep(20000);
+
+ // Open database.
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.NEVER;
+ dbConfig.AutoCommit = true;
+ dbConfig.Env = env;
+ dbConfig.PageSize = 512;
+ BTreeDatabase db = BTreeDatabase.Open("rep.db",
+ dbConfig);
+
+ // Write data into database.
+ Console.WriteLine("Client: Start reading data #1.");
+ for (int i = 0; i < 5; i++)
+ db.GetBoth(new DatabaseEntry(
+ BitConverter.GetBytes(i)), new DatabaseEntry(
+ BitConverter.GetBytes(i)));
+
+ // Leave sometime for client to read new data from master.
+ Thread.Sleep(20000);
+
+ /*
+ * Read the data. All data exists in master site should
+ * appear in the client site.
+ */
+ Console.WriteLine("Client: Start reading data #2.");
+ for (int i = 10; i < 15; i++)
+ db.GetBoth(new DatabaseEntry(
+ BitConverter.GetBytes(i)), new DatabaseEntry(
+ BitConverter.GetBytes(i)));
+
+ // Get the latest replication subsystem statistics.
+ ReplicationStats repStats = env.ReplicationSystemStats();
+ Assert.IsTrue(repStats.ClientStartupComplete);
+ Assert.AreEqual(1, repStats.DuplicateLogRecords);
+ Assert.LessOrEqual(0, repStats.EnvID);
+ Assert.LessOrEqual(0, repStats.NextPage);
+ Assert.LessOrEqual(0, repStats.ReceivedPages);
+ Assert.AreEqual(1, repStats.Status);
+
+ // Close all.
+ db.Close(false);
+ env.LogFlush();
+ env.Close();
+ Console.WriteLine(
+ "Client: All data is read. Leaving the replication");
+
+ // The master is closed after client's close.
+ masterCloseSignal.Set();
+ }
+
+ private void stuffHappened(NotificationEvent eventCode, byte[] info)
+ {
+ switch (eventCode)
+ {
+ case NotificationEvent.REP_CLIENT:
+ Console.WriteLine("CLIENT");
+ break;
+ case NotificationEvent.REP_MASTER:
+ Console.WriteLine("MASTER");
+ break;
+ case NotificationEvent.REP_NEWMASTER:
+ Console.WriteLine("NEWMASTER");
+ break;
+ case NotificationEvent.REP_STARTUPDONE:
+ /* We don't care about these */
+ break;
+ case NotificationEvent.REP_PERM_FAILED:
+ Console.WriteLine("Insufficient Acks.");
+ break;
+ default:
+ Console.WriteLine("Event: {0}", eventCode);
+ break;
+ }
+ }
+
+ [Test]
+ public void TestElection()
+ {
+ testName = "TestElection";
+ testHome = testFixtureHome + "/" + testName;
+
+ client1StartSignal = new AutoResetEvent(false);
+ client2StartSignal = new AutoResetEvent(false);
+ client1ReadySignal = new AutoResetEvent(false);
+ client2ReadySignal = new AutoResetEvent(false);
+ client3StartSignal = new AutoResetEvent(false);
+ client3ReadySignal = new AutoResetEvent(false);
+ masterLeaveSignal = new AutoResetEvent(false);
+
+ Thread thread1 = new Thread(
+ new ThreadStart(UnstableMaster));
+ Thread thread2 = new Thread(
+ new ThreadStart(StableClient1));
+ Thread thread3 = new Thread(
+ new ThreadStart(StableClient2));
+ Thread thread4 = new Thread(
+ new ThreadStart(StableClient3));
+
+ thread1.Start();
+ Thread.Sleep(1000);
+ thread2.Start();
+ thread3.Start();
+ thread4.Start();
+
+ thread4.Join();
+ thread3.Join();
+ thread2.Join();
+ thread1.Join();
+
+ client1StartSignal.Close();
+ client2StartSignal.Close();
+ client1ReadySignal.Close();
+ client2ReadySignal.Close();
+ client3ReadySignal.Close();
+ client3StartSignal.Close();
+ masterLeaveSignal.Close();
+ }
+
+ public void UnstableMaster()
+ {
+ string home = testHome + "/UnstableMaster";
+ Configuration.ClearDir(home);
+
+ // Open environment with replication configuration.
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.UseReplication = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 20485760, 1);
+ cfg.UseLocking = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.Create = true;
+ cfg.UseLogging = true;
+ cfg.RunRecovery = true;
+ cfg.TxnNoSync = true;
+ cfg.FreeThreaded = true;
+ cfg.RepSystemCfg = new ReplicationConfig();
+ cfg.RepSystemCfg.RepMgrLocalSite =
+ new ReplicationHostAddress("127.0.0.1", 8888);
+ cfg.RepSystemCfg.Priority = 200;
+ cfg.RepSystemCfg.NSites = 4;
+ cfg.RepSystemCfg.ElectionRetry = 10;
+ cfg.RepSystemCfg.RepMgrAckPolicy = AckPolicy.ALL;
+ cfg.EventNotify = new EventNotifyDelegate(stuffHappened);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, cfg);
+ env.DeadlockResolution = DeadlockPolicy.DEFAULT;
+
+ // Start as master site.
+ env.RepMgrStartMaster(3);
+
+ Console.WriteLine("Master: Finish initialization");
+
+ // Notify clients to join.
+ client1StartSignal.Set();
+ client2StartSignal.Set();
+ client3StartSignal.Set();
+
+ // Wait for initialization of all clients.
+ client1ReadySignal.WaitOne();
+ client2ReadySignal.WaitOne();
+ client3ReadySignal.WaitOne();
+
+ List<uint> ports = new List<uint>();
+ ports.Add(5888);
+ ports.Add(6888);
+ ports.Add(7888);
+ foreach (RepMgrSite site in env.RepMgrRemoteSites)
+ {
+ Assert.AreEqual("127.0.0.1", site.Address.Host);
+ Assert.IsTrue(ports.Contains(site.Address.Port));
+ Assert.Greater(4, site.EId);
+ Assert.IsTrue(site.isConnected);
+ }
+
+ // After all of them are ready, close the current master.
+ Console.WriteLine("Master: Unexpected leave.");
+ env.LogFlush();
+ env.Close();
+ masterLeaveSignal.Set();
+ }
+
+ public void StableClient1()
+ {
+ string home = testHome + "/StableClient1";
+ Configuration.ClearDir(home);
+
+ // Get notification from master and start the #1 client.
+ client1StartSignal.WaitOne();
+ Console.WriteLine("Client1: Join the replication");
+
+ // Open the environment.
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.UseReplication = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 20485760, 1);
+ cfg.UseLocking = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.Create = true;
+ cfg.UseLogging = true;
+ cfg.RunRecovery = true;
+ cfg.TxnNoSync = true;
+ cfg.FreeThreaded = true;
+ cfg.LockTimeout = 50000;
+ cfg.RepSystemCfg = new ReplicationConfig();
+ cfg.RepSystemCfg.RepMgrLocalSite =
+ new ReplicationHostAddress("127.0.0.1", 7888);
+ cfg.RepSystemCfg.Priority = 10;
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 8888), false);
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 5888), true);
+ cfg.RepSystemCfg.NSites = 4;
+ cfg.RepSystemCfg.ElectionRetry = 10;
+ cfg.RepSystemCfg.RepMgrAckPolicy = AckPolicy.NONE;
+ cfg.EventNotify = new EventNotifyDelegate(stuffHappened);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, cfg);
+ env.DeadlockResolution = DeadlockPolicy.DEFAULT;
+
+ // Start the client who won't raise any election.
+ env.RepMgrStartClient(3, false);
+
+ // Leave enough time to sync.
+ Thread.Sleep(20000);
+
+ // The current client site is fully initialized.
+ client1ReadySignal.Set();
+
+ // Wait for master's leave signal.
+ masterLeaveSignal.WaitOne();
+
+ /*
+ * Set the master's leave signal so that other clients
+ * could be informed.
+ */
+ masterLeaveSignal.Set();
+
+ // Leave sometime for client to hold election.
+ Thread.Sleep(10000);
+
+ env.LogFlush();
+ env.Close();
+ Console.WriteLine("Client1: Leaving the replication");
+ }
+
+
+ public void StableClient2()
+ {
+ string home = testHome + "/StableClient2";
+ Configuration.ClearDir(home);
+
+ client2StartSignal.WaitOne();
+ Console.WriteLine("Client2: Join the replication");
+
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.UseReplication = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 20485760, 1);
+ cfg.UseLocking = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.Create = true;
+ cfg.UseLogging = true;
+ cfg.RunRecovery = true;
+ cfg.TxnNoSync = true;
+ cfg.FreeThreaded = true;
+ cfg.LockTimeout = 50000;
+ cfg.RepSystemCfg = new ReplicationConfig();
+ cfg.RepSystemCfg.RepMgrLocalSite =
+ new ReplicationHostAddress("127.0.0.1", 6888);
+ cfg.RepSystemCfg.Priority = 20;
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 8888), false);
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 7888), true);
+ cfg.RepSystemCfg.NSites = 4;
+ cfg.RepSystemCfg.ElectionRetry = 10;
+ cfg.RepSystemCfg.RepMgrAckPolicy =
+ AckPolicy.ONE_PEER;
+ cfg.EventNotify = new EventNotifyDelegate(stuffHappened);
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, cfg);
+ env.DeadlockResolution = DeadlockPolicy.DEFAULT;
+
+ // Start the client who will raise election if no master.
+ env.RepMgrStartClient(3, true);
+
+ // Leave enough time to sync.
+ Thread.Sleep(20000);
+
+ // The current client site is fully initialized.
+ client2ReadySignal.Set();
+
+ // Wait for master's leave signal.
+ masterLeaveSignal.WaitOne();
+
+ /*
+ * Set the master's leave signal so that other clients
+ * could be informed.
+ */
+ masterLeaveSignal.Set();
+
+ // Leave sometime for client to hold election.
+ Thread.Sleep(5000);
+
+ env.LogFlush();
+ env.Close();
+ Console.WriteLine("Client2: Leaving the replication");
+ }
+
+ public void StableClient3()
+ {
+ string home = testHome + "/StableClient3";
+ Configuration.ClearDir(home);
+
+ client3StartSignal.WaitOne();
+ Console.WriteLine("Client3: Join the replication");
+
+ DatabaseEnvironmentConfig cfg =
+ new DatabaseEnvironmentConfig();
+ cfg.UseReplication = true;
+ cfg.MPoolSystemCfg = new MPoolConfig();
+ cfg.MPoolSystemCfg.CacheSize =
+ new CacheInfo(0, 20485760, 1);
+ cfg.UseLocking = true;
+ cfg.UseTxns = true;
+ cfg.UseMPool = true;
+ cfg.Create = true;
+ cfg.UseLogging = true;
+ cfg.RunRecovery = true;
+ cfg.TxnNoSync = true;
+ cfg.FreeThreaded = true;
+ cfg.LockTimeout = 50000;
+ cfg.RepSystemCfg = new ReplicationConfig();
+ cfg.RepSystemCfg.RepMgrLocalSite =
+ new ReplicationHostAddress("127.0.0.1", 5888);
+ cfg.RepSystemCfg.Priority = 80;
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 8888), false);
+ cfg.RepSystemCfg.AddRemoteSite(
+ new ReplicationHostAddress("127.0.0.1", 6888), true);
+ cfg.RepSystemCfg.NSites = 4;
+ cfg.EventNotify = new EventNotifyDelegate(stuffHappened);
+ cfg.RepSystemCfg.ElectionRetry = 10;
+ cfg.RepSystemCfg.RepMgrAckPolicy = AckPolicy.QUORUM;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, cfg);
+ env.DeadlockResolution = DeadlockPolicy.DEFAULT;
+
+ env.RepMgrStartClient(3, false);
+
+ // Leave enough time to sync with master.
+ Thread.Sleep(20000);
+
+ // The current client site is fully initialized.
+ client3ReadySignal.Set();
+
+ // Wait for master's leave signal.
+ masterLeaveSignal.WaitOne();
+
+ /*
+ * Set the master's leave signal so that other clients
+ * could be informed.
+ */
+ masterLeaveSignal.Set();
+
+ /*
+ * Master will leave the replication after all clients'
+ * initialization. Leave sometime for master to leave
+ * and for clients elect.
+ */
+ Thread.Sleep(5000);
+
+ ReplicationStats repStats = env.ReplicationSystemStats();
+ Assert.LessOrEqual(0, repStats.Elections);
+ Assert.LessOrEqual(0, repStats.ElectionTiebreaker);
+ Assert.LessOrEqual(0,
+ repStats.ElectionTimeSec + repStats.ElectionTimeUSec);
+ Assert.LessOrEqual(0, repStats.MasterChanges);
+ Assert.LessOrEqual(0, repStats.NewSiteMessages);
+ Assert.LessOrEqual(0, repStats.ReceivedLogRecords);
+ Assert.LessOrEqual(0, repStats.ReceivedMessages);
+ Assert.LessOrEqual(0, repStats.ReceivedPages);
+ Assert.GreaterOrEqual(4, repStats.RegisteredSitesNeeded);
+ Assert.LessOrEqual(0, repStats.Sites);
+
+ /*
+ * Client 3 will be the new master. The Elected master should wait
+ * until all other clients leave.
+ */
+ Thread.Sleep(10000);
+
+ env.LogFlush();
+ env.Close();
+ Console.WriteLine("Client3: Leaving the replication");
+ }
+
+ [Test]
+ public void TestAckPolicy()
+ {
+ testName = "TestAckPolicy";
+ testHome = testFixtureHome + "/" + testName;
+
+ SetRepMgrAckPolicy(testHome + "_ALL", AckPolicy.ALL);
+ SetRepMgrAckPolicy(testHome + "_ALL_PEERS",
+ AckPolicy.ALL_PEERS);
+ SetRepMgrAckPolicy(testHome + "_NONE",
+ AckPolicy.NONE);
+ SetRepMgrAckPolicy(testHome + "_ONE",
+ AckPolicy.ONE);
+ SetRepMgrAckPolicy(testHome + "_ONE_PEER",
+ AckPolicy.ONE_PEER);
+ SetRepMgrAckPolicy(testHome + "_QUORUM",
+ AckPolicy.QUORUM);
+ SetRepMgrAckPolicy(testHome + "_NULL", null);
+ }
+
+ public void SetRepMgrAckPolicy(string home, AckPolicy policy)
+ {
+ Configuration.ClearDir(home);
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseLocking = true;
+ envConfig.UseLogging = true;
+ envConfig.UseMPool = true;
+ envConfig.UseReplication = true;
+ envConfig.UseTxns = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConfig);
+ if (policy != null)
+ {
+ env.RepMgrAckPolicy = policy;
+ Assert.AreEqual(policy, env.RepMgrAckPolicy);
+ }
+ env.Close();
+ }
+ }
+}
diff --git a/test/scr037/SecondaryBTreeDatabaseConfigTest.cs b/test/scr037/SecondaryBTreeDatabaseConfigTest.cs
new file mode 100644
index 0000000..09724af
--- /dev/null
+++ b/test/scr037/SecondaryBTreeDatabaseConfigTest.cs
@@ -0,0 +1,115 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class SecondaryBTreeDatabaseConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "SecondaryBTreeDatabaseConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+
+ // Open a primary btree database.
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ dbFileName, btreeDBConfig);
+
+ SecondaryBTreeDatabaseConfig secDBConfig =
+ new SecondaryBTreeDatabaseConfig(btreeDB, null);
+
+ Config(xmlElem, ref secDBConfig, true);
+ Confirm(xmlElem, secDBConfig, true);
+
+ // Close the primary btree database.
+ btreeDB.Close();
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ SecondaryBTreeDatabaseConfig secBtreeDBConfig,
+ bool compulsory)
+ {
+ SecondaryDatabaseConfig secDBConfig =
+ secBtreeDBConfig;
+ SecondaryDatabaseConfigTest.Confirm(xmlElement,
+ secDBConfig, compulsory);
+
+ // Confirm secondary btree database specific configuration.
+ Configuration.ConfirmCreatePolicy(xmlElement,
+ "Creation", secBtreeDBConfig.Creation, compulsory);
+ Configuration.ConfirmDuplicatesPolicy(xmlElement,
+ "Duplicates", secBtreeDBConfig.Duplicates, compulsory);
+ Configuration.ConfirmUint(xmlElement, "MinKeysPerPage",
+ secBtreeDBConfig.MinKeysPerPage, compulsory);
+ Configuration.ConfirmBool(xmlElement,
+ "NoReverseSplitting",
+ secBtreeDBConfig.NoReverseSplitting, compulsory);
+ Configuration.ConfirmBool(xmlElement,
+ "UseRecordNumbers",
+ secBtreeDBConfig.UseRecordNumbers,
+ compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref SecondaryBTreeDatabaseConfig secBtreeDBConfig,
+ bool compulsory)
+ {
+ uint minKeysPerPage = new uint();
+
+ SecondaryDatabaseConfig secDBConfig = secBtreeDBConfig;
+ SecondaryDatabaseConfigTest.Config(xmlElement,
+ ref secDBConfig, compulsory);
+
+ // Configure specific fields/properties of Btree db
+ Configuration.ConfigCreatePolicy(xmlElement,
+ "Creation", ref secBtreeDBConfig.Creation, compulsory);
+ Configuration.ConfigDuplicatesPolicy(xmlElement,
+ "Duplicates", ref secBtreeDBConfig.Duplicates,
+ compulsory);
+ if (Configuration.ConfigUint(xmlElement,
+ "MinKeysPerPage", ref minKeysPerPage, compulsory))
+ secBtreeDBConfig.MinKeysPerPage = minKeysPerPage;
+ Configuration.ConfigBool(xmlElement,
+ "NoReverseSplitting",
+ ref secBtreeDBConfig.NoReverseSplitting, compulsory);
+ Configuration.ConfigBool(xmlElement,
+ "UseRecordNumbers",
+ ref secBtreeDBConfig.UseRecordNumbers, compulsory);
+ }
+ }
+}
diff --git a/test/scr037/SecondaryBTreeDatabaseTest.cs b/test/scr037/SecondaryBTreeDatabaseTest.cs
new file mode 100644
index 0000000..5c1fdfb
--- /dev/null
+++ b/test/scr037/SecondaryBTreeDatabaseTest.cs
@@ -0,0 +1,232 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class SecondaryBTreeDatabaseTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "SecondaryBTreeDatabaseTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestOpen()
+ {
+ testName = "TestOpen";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" +
+ testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+
+ // Open a primary btree database.
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ dbFileName, btreeDBConfig);
+
+ // Open a secondary btree database.
+ SecondaryBTreeDatabaseConfig secDBConfig =
+ new SecondaryBTreeDatabaseConfig(btreeDB, null);
+
+ SecondaryBTreeDatabaseConfigTest.Config(xmlElem,
+ ref secDBConfig, true);
+ SecondaryBTreeDatabase secDB =
+ SecondaryBTreeDatabase.Open(dbSecFileName,
+ secDBConfig);
+
+ // Confirm its flags configured in secDBConfig.
+ Confirm(xmlElem, secDB, true);
+
+ secDB.Close();
+ btreeDB.Close();
+ }
+
+ [Test]
+ public void TestCompare()
+ {
+ testName = "TestCompare";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a primary btree database.
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ dbFileName, btreeDBConfig);
+
+ // Open a secondary btree database.
+ SecondaryBTreeDatabaseConfig secBtreeDBConfig =
+ new SecondaryBTreeDatabaseConfig(null, null);
+ secBtreeDBConfig.Primary = btreeDB;
+ secBtreeDBConfig.Compare =
+ new EntryComparisonDelegate(
+ SecondaryEntryComparison);
+ secBtreeDBConfig.KeyGen =
+ new SecondaryKeyGenDelegate(SecondaryKeyGen);
+ SecondaryBTreeDatabase secDB =
+ SecondaryBTreeDatabase.Open(
+ dbFileName, secBtreeDBConfig);
+
+ /*
+ * Get the compare function set in the configuration
+ * and run it in a comparison to see if it is alright.
+ */
+ EntryComparisonDelegate cmp =
+ secDB.Compare;
+ DatabaseEntry dbt1, dbt2;
+ dbt1 = new DatabaseEntry(
+ BitConverter.GetBytes((int)257));
+ dbt2 = new DatabaseEntry(
+ BitConverter.GetBytes((int)255));
+ Assert.Less(0, cmp(dbt1, dbt2));
+
+ secDB.Close();
+ btreeDB.Close();
+ }
+
+ [Test]
+ public void TestDuplicates()
+ {
+ testName = "TestDuplicates";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName
+ + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a primary btree database.
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ dbFileName, btreeDBConfig);
+
+ // Open a secondary btree database.
+ SecondaryBTreeDatabaseConfig secBtreeDBConfig =
+ new SecondaryBTreeDatabaseConfig(btreeDB, null);
+ secBtreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ secBtreeDBConfig.Duplicates = DuplicatesPolicy.SORTED;
+ SecondaryBTreeDatabase secDB =
+ SecondaryBTreeDatabase.Open(dbSecFileName,
+ secBtreeDBConfig);
+
+ secDB.Close();
+ btreeDB.Close();
+ }
+
+ [Test]
+ public void TestPrefixCompare()
+ {
+ testName = "TestPrefixCompare";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a primary btree database.
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.ALWAYS;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ dbFileName, btreeDBConfig);
+
+ // Open a secondary btree database.
+ SecondaryBTreeDatabaseConfig secBtreeDBConfig =
+ new SecondaryBTreeDatabaseConfig(btreeDB, null);
+ secBtreeDBConfig.Primary = btreeDB;
+ secBtreeDBConfig.Compare =
+ new EntryComparisonDelegate(
+ SecondaryEntryComparison);
+ secBtreeDBConfig.PrefixCompare =
+ new EntryComparisonDelegate(
+ SecondaryEntryComparison);
+ secBtreeDBConfig.KeyGen =
+ new SecondaryKeyGenDelegate(
+ SecondaryKeyGen);
+ SecondaryBTreeDatabase secDB =
+ SecondaryBTreeDatabase.Open(
+ dbFileName, secBtreeDBConfig);
+
+ /*
+ * Get the prefix compare function set in the
+ * configuration and run it in a comparison to
+ * see if it is alright.
+ */
+ EntryComparisonDelegate cmp =
+ secDB.PrefixCompare;
+ DatabaseEntry dbt1, dbt2;
+ dbt1 = new DatabaseEntry(
+ BitConverter.GetBytes((int)1));
+ dbt2 = new DatabaseEntry(
+ BitConverter.GetBytes((int)129));
+ Assert.Greater(0, cmp(dbt1, dbt2));
+
+ secDB.Close();
+ btreeDB.Close();
+ }
+
+ public int SecondaryEntryComparison(
+ DatabaseEntry dbt1, DatabaseEntry dbt2)
+ {
+ int a, b;
+ a = BitConverter.ToInt32(dbt1.Data, 0);
+ b = BitConverter.ToInt32(dbt2.Data, 0);
+ return a - b;
+ }
+
+ public DatabaseEntry SecondaryKeyGen(
+ DatabaseEntry key, DatabaseEntry data)
+ {
+ DatabaseEntry dbtGen;
+ dbtGen = new DatabaseEntry(data.Data);
+ return dbtGen;
+ }
+
+ public static void Confirm(XmlElement xmlElem,
+ SecondaryBTreeDatabase secDB, bool compulsory)
+ {
+ Configuration.ConfirmDuplicatesPolicy(xmlElem,
+ "Duplicates", secDB.Duplicates, compulsory);
+ Configuration.ConfirmUint(xmlElem, "MinKeysPerPage",
+ secDB.MinKeysPerPage, compulsory);
+ Configuration.ConfirmBool(xmlElem, "NoReverseSplitting",
+ secDB.ReverseSplit, compulsory);
+ Configuration.ConfirmBool(xmlElem, "UseRecordNumbers",
+ secDB.RecordNumbers, compulsory);
+ }
+ }
+}
diff --git a/test/scr037/SecondaryCursorTest.cs b/test/scr037/SecondaryCursorTest.cs
new file mode 100644
index 0000000..1c3ca6d
--- /dev/null
+++ b/test/scr037/SecondaryCursorTest.cs
@@ -0,0 +1,1214 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class SecondaryCursorTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "SecondaryCursorTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ /*
+ * Delete existing test ouput directory and files specified
+ * for the current test fixture and then create a new one.
+ */
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestDuplicate()
+ {
+ testName = "TestDuplicate";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a primary database.
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase db = BTreeDatabase.Open(
+ dbFileName, dbConfig);
+
+ // Open a secondary database.
+ SecondaryBTreeDatabaseConfig secConfig =
+ new SecondaryBTreeDatabaseConfig(db,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secConfig.Creation = CreatePolicy.IF_NEEDED;
+ secConfig.Duplicates = DuplicatesPolicy.UNSORTED;
+ SecondaryBTreeDatabase secDB =
+ SecondaryBTreeDatabase.Open(dbSecFileName,
+ secConfig);
+
+ // Put a pair of key and data into the database.
+ DatabaseEntry key, data;
+ key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ db.Put(key, data);
+
+ // Create a cursor.
+ SecondaryCursor cursor = secDB.SecondaryCursor();
+ cursor.Move(key, true);
+
+ // Duplicate the cursor.
+ SecondaryCursor dupCursor;
+ dupCursor = cursor.Duplicate(true);
+
+ /*
+ * Confirm that the duplicate cursor has the same
+ * position as the original one.
+ */
+ Assert.AreEqual(cursor.Current.Key,
+ dupCursor.Current.Key);
+ Assert.AreEqual(cursor.Current.Value,
+ dupCursor.Current.Value);
+
+ // Close the cursor and the duplicate cursor.
+ dupCursor.Close();
+ cursor.Close();
+
+ // Close secondary and primary database.
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestDelete()
+ {
+ testName = "TestDelete";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a primary database and its secondary database.
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDB(dbFileName, dbSecFileName, out db, out secDB);
+
+ // Put a pair of key and data into database.
+ DatabaseEntry key, data;
+ key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ db.Put(key, data);
+
+ // Delete the pair with cursor.
+ SecondaryCursor secCursor = secDB.SecondaryCursor();
+ Assert.IsTrue(secCursor.MoveFirst());
+ secCursor.Delete();
+
+ // Confirm that the pair is deleted.
+ Assert.IsFalse(db.Exists(key));
+
+ // Close all databases.
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestCurrent()
+ {
+ testName = "TestCurrent";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a primary database and its secondary database.
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDB(dbFileName, dbSecFileName, out db, out secDB);
+
+ // Put a pair of key and data into database.
+ DatabaseEntry key, data;
+ key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ db.Put(key, data);
+
+ // Delete the pair with cursor.
+ SecondaryCursor secCursor = secDB.SecondaryCursor();
+ Assert.IsTrue(secCursor.Move(data, true));
+
+ // Confirm that the current is the one we put into database.
+ Assert.AreEqual(data.Data, secCursor.Current.Key.Data);
+
+ // Close all databases.
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestGetEnumerator()
+ {
+ testName = "TestGetEnumerator";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a primary database and its secondary database.
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDB(dbFileName, dbSecFileName, out db,
+ out secDB);
+
+ // Write ten records into the database.
+ WriteRecords(db);
+
+ /*
+ * Get all records from the secondary database and see
+ * if the records with key other than 10 have the same as
+ * their primary key.
+ */
+ SecondaryCursor secCursor = secDB.SecondaryCursor();
+ foreach (KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>> secData in secCursor)
+ {
+ if (BitConverter.ToInt32(secData.Key.Data, 0) != 10)
+ Assert.AreEqual(secData.Value.Key.Data,
+ secData.Value.Value.Data);
+ }
+
+ // Close all cursors and databases.
+ secCursor.Close();
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveToKey()
+ {
+ testName = "TestMoveToKey";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ MoveToPos(dbFileName, dbSecFileName, false);
+ }
+
+ [Test]
+ public void TestMoveToPair()
+ {
+ testName = "TestMoveToPair";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ MoveToPos(dbFileName, dbSecFileName, true);
+ }
+
+ public void MoveToPos(string dbFileName,
+ string dbSecFileName, bool ifPair)
+ {
+ // Open a primary database and its secondary database.
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDB(dbFileName, dbSecFileName, out db,
+ out secDB);
+
+ // Write ten records into the database.
+ WriteRecords(db);
+
+ SecondaryCursor secCursor = secDB.SecondaryCursor();
+ DatabaseEntry key = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ DatabaseEntry notExistingKey = new DatabaseEntry(
+ BitConverter.GetBytes((int)100));
+ if (ifPair == false)
+ {
+ Assert.IsTrue(secCursor.Move(key, true));
+ Assert.IsFalse(secCursor.Move(notExistingKey, true));
+ }
+ else
+ {
+ KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>> pair =
+ new KeyValuePair<DatabaseEntry,
+ KeyValuePair<DatabaseEntry, DatabaseEntry>>(key,
+ new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ key, key));
+
+ KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>> notExistingPair;
+
+ notExistingPair = new KeyValuePair<DatabaseEntry,
+ KeyValuePair<DatabaseEntry, DatabaseEntry>>(
+ notExistingKey, new KeyValuePair<
+ DatabaseEntry, DatabaseEntry>(
+ notExistingKey, notExistingKey));
+ Assert.IsTrue(secCursor.Move(pair, true));
+ Assert.IsFalse(secCursor.Move(notExistingPair, true));
+ }
+
+ secCursor.Close();
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveToKeyWithLockingInfo()
+ {
+ testName = "TestMoveToKeyWithLockingInfo";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ MoveToPosWithLockingInfo(testHome, dbFileName,
+ dbSecFileName, false);
+ }
+
+ [Test]
+ public void TestMoveToPairWithLockingInfo()
+ {
+ testName = "TestMoveToPairWithLockingInfo";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ MoveToPosWithLockingInfo(testHome, dbFileName,
+ dbSecFileName, true);
+ }
+
+ public void MoveToPosWithLockingInfo(string home,
+ string dbFileName, string dbSecFileName, bool ifPair)
+ {
+ // Open a primary database and its secondary database.
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDBInTxn(home, dbFileName, dbSecFileName,
+ out env, out db, out secDB);
+
+ // Write ten records into the database.
+ WriteRecordsInTxn(db, env);
+
+ // Create an secondary cursor.
+ Transaction cursorTxn = env.BeginTransaction();
+ SecondaryCursor secCursor = secDB.SecondaryCursor(
+ cursorTxn);
+ DatabaseEntry key = new DatabaseEntry(
+ BitConverter.GetBytes((int)0));
+ LockingInfo lockingInfo = new LockingInfo();
+ lockingInfo.IsolationDegree = Isolation.DEGREE_THREE;
+ lockingInfo.ReadModifyWrite = true;
+ if (ifPair == false)
+ {
+ Assert.IsTrue(secCursor.Move(key, true, lockingInfo));
+ }
+ else
+ {
+ KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>> pair;
+
+ pair = new KeyValuePair<DatabaseEntry,
+ KeyValuePair<DatabaseEntry, DatabaseEntry>>(key,
+ new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ key, key));
+ Assert.IsTrue(secCursor.Move(pair, true, lockingInfo));
+ }
+ secCursor.Close();
+ cursorTxn.Commit();
+
+ secDB.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestMoveFirst()
+ {
+ testName = "TestMoveFirst";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open primary and secondary database.
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDB(dbFileName, dbSecFileName, out db,
+ out secDB);
+
+
+ // Write ten records into the database.
+ WriteRecords(db);
+
+ // Move the cursor to the first record(0,0).
+ SecondaryCursor cursor = secDB.SecondaryCursor();
+ Assert.IsTrue(cursor.MoveFirst());
+ Assert.AreEqual(BitConverter.GetBytes((int)0),
+ cursor.Current.Key.Data);
+
+ // Close all.
+ cursor.Close();
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveLast()
+ {
+ testName = "TestMoveLast";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDB(dbFileName, dbSecFileName, out db,
+ out secDB);
+ WriteRecords(db);
+
+ SecondaryCursor cursor = secDB.SecondaryCursor();
+ Assert.IsTrue(cursor.MoveLast());
+ Assert.AreEqual(BitConverter.GetBytes((int)10),
+ cursor.Current.Key.Data);
+
+ cursor.Close();
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveNext()
+ {
+ testName = "TestMoveNext";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDB(dbFileName, dbSecFileName, out db,
+ out secDB);
+ WriteRecords(db);
+
+ SecondaryCursor cursor = secDB.SecondaryCursor();
+ cursor.MoveFirst();
+ for (int i = 0; i < 5; i++)
+ Assert.IsTrue(cursor.MoveNext());
+
+ cursor.Close();
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveNextDuplicate()
+ {
+ testName = "TestMoveNextDuplicate";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDB(dbFileName, dbSecFileName, out db,
+ out secDB);
+ WriteRecords(db);
+
+ // Create a cursor and move the cursor to duplicate record.
+ SecondaryCursor cursor = secDB.SecondaryCursor();
+ cursor.Move(new DatabaseEntry(
+ BitConverter.GetBytes((int)10)), true);
+ Assert.IsTrue(cursor.MoveNextDuplicate());
+ Assert.AreEqual(BitConverter.GetBytes((int)10),
+ cursor.Current.Key.Data);
+
+ cursor.Close();
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveNextUnique()
+ {
+ testName = "TestMoveNextUnique";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDB(dbFileName, dbSecFileName, out db,
+ out secDB);
+ WriteRecords(db);
+
+ /*
+ * Move cursor to duplicate record. Since the duplicate
+ * record has the largest key, moving to the next
+ * unique record should fail.
+ */
+ SecondaryCursor cursor = secDB.SecondaryCursor();
+ cursor.Move(new DatabaseEntry(
+ BitConverter.GetBytes((int)10)), true);
+ Assert.IsFalse(cursor.MoveNextUnique());
+
+ cursor.Close();
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMovePrev()
+ {
+ testName = "TestMovePrev";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDB(dbFileName, dbSecFileName, out db,
+ out secDB);
+ WriteRecords(db);
+
+ SecondaryCursor cursor = secDB.SecondaryCursor();
+ cursor.MoveLast();
+ for (int i = 0; i < 5; i++)
+ Assert.IsTrue(cursor.MovePrev());
+
+ cursor.Close();
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMovePrevDuplicate()
+ {
+ testName = "TestMovePrevDuplicate";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDB(dbFileName, dbSecFileName, out db,
+ out secDB);
+ WriteRecords(db);
+
+ SecondaryCursor cursor = secDB.SecondaryCursor();
+ KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>> pair;
+ DatabaseEntry pKey, pData;
+ pKey = new DatabaseEntry(BitConverter.GetBytes((int)6));
+ pData = new DatabaseEntry(BitConverter.GetBytes((int)10));
+ pair = new KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>>(pData,
+ new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ pKey, pData));
+ cursor.Move(pair, true);
+ Assert.IsTrue(cursor.MovePrevDuplicate());
+ Assert.AreEqual(BitConverter.GetBytes((int)10),
+ cursor.Current.Key.Data);
+
+ cursor.Close();
+ secDB.Close();
+ db.Close();
+ }
+
+
+ [Test]
+ public void TestMovePrevUnique()
+ {
+ testName = "TestMovePrevUnique";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDB(dbFileName, dbSecFileName, out db,
+ out secDB);
+ WriteRecords(db);
+
+ SecondaryCursor cursor = secDB.SecondaryCursor();
+ KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>> pair;
+ DatabaseEntry pKey, pData;
+ pKey = new DatabaseEntry(BitConverter.GetBytes((int)6));
+ pData = new DatabaseEntry(BitConverter.GetBytes((int)10));
+ pair = new KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>>(pData,
+ new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ pKey, pData));
+ cursor.Move(pair, true);
+ Assert.IsTrue(cursor.MovePrevUnique());
+ Assert.AreNotEqual(BitConverter.GetBytes((int)10),
+ cursor.Current.Key.Data);
+
+ cursor.Close();
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestRefresh()
+ {
+ testName = "TestRefresh";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDB(dbFileName, dbSecFileName, out db,
+ out secDB);
+ WriteRecords(db);
+
+ SecondaryCursor cursor = secDB.SecondaryCursor();
+ KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>> pair;
+ DatabaseEntry pKey, pData;
+ pKey = new DatabaseEntry(BitConverter.GetBytes((int)6));
+ pData = new DatabaseEntry(BitConverter.GetBytes((int)10));
+ pair = new KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>>(pData,
+ new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ pKey, pData));
+ cursor.Move(pair, true);
+ Assert.IsTrue(cursor.Refresh());
+ Assert.AreEqual(pData.Data, cursor.Current.Key.Data);
+ Assert.AreEqual(pKey.Data, cursor.Current.Value.Key.Data);
+
+ cursor.Close();
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestMoveFirstWithLockingInfo()
+ {
+ testName = "TestMoveFirstWithLockingInfo";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open environment, primary database and
+ * secondary database.
+ */
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDBInTxn(testHome, dbFileName, dbSecFileName,
+ out env, out db, out secDB);
+
+ // Write ten records into the database.
+ WriteRecordsInTxn(db, env);
+
+ // Move the cursor to the first record(0, 0).
+ Transaction cursorTxn = env.BeginTransaction();
+ SecondaryCursor cursor =
+ secDB.SecondaryCursor(cursorTxn);
+ LockingInfo lockingInfo = new LockingInfo();
+ lockingInfo.IsolationDegree = Isolation.DEGREE_THREE;
+ lockingInfo.ReadModifyWrite = true;
+ Assert.IsTrue(cursor.MoveFirst(lockingInfo));
+ Assert.AreEqual(BitConverter.GetBytes((int)0),
+ cursor.Current.Key.Data);
+ cursor.Close();
+ cursorTxn.Commit();
+
+ // Close all.
+ secDB.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestMoveLastWithLockingInfo()
+ {
+ testName = "TestMoveLastWithLockingInfo";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open environment, primary database and
+ * secondary database.
+ */
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDBInTxn(testHome, dbFileName, dbSecFileName,
+ out env, out db, out secDB);
+
+ // Write ten records into the database.
+ WriteRecordsInTxn(db, env);
+
+ /*
+ * Move the cursor to the last record(10, 6), that is
+ * record(6, 10) in primary database.
+ */
+ Transaction cursorTxn = env.BeginTransaction();
+ SecondaryCursor cursor =
+ secDB.SecondaryCursor(cursorTxn);
+ LockingInfo lockingInfo = new LockingInfo();
+ lockingInfo.IsolationDegree = Isolation.DEGREE_THREE;
+ lockingInfo.ReadModifyWrite = true;
+ Assert.IsTrue(cursor.MoveLast(lockingInfo));
+ Assert.AreEqual(BitConverter.GetBytes((int)10),
+ cursor.Current.Key.Data);
+ cursor.Close();
+ cursorTxn.Commit();
+
+ // Close all.
+ secDB.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestMoveNextWithLockingInfo()
+ {
+ testName = "TestMoveNextWithLockingInfo";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open environment, primary database and
+ * secondary database.
+ */
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDBInTxn(testHome, dbFileName, dbSecFileName,
+ out env, out db, out secDB);
+
+ // Write ten records into the database.
+ WriteRecordsInTxn(db, env);
+
+ /*
+ * Move cursor to the first record and move to next
+ * record for five times.
+ */
+ Transaction cursorTxn = env.BeginTransaction();
+ SecondaryCursor cursor =
+ secDB.SecondaryCursor(cursorTxn);
+ LockingInfo lockingInfo = new LockingInfo();
+ lockingInfo.IsolationDegree = Isolation.DEGREE_THREE;
+ lockingInfo.ReadModifyWrite = true;
+ cursor.MoveFirst(lockingInfo);
+ for (int i = 0; i < 5; i++)
+ Assert.IsTrue(cursor.MoveNext(lockingInfo));
+ cursor.Close();
+ cursorTxn.Commit();
+
+ // Close all.
+ secDB.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestMoveNextDuplicateWithLockingInfo()
+ {
+ testName = "TestMoveNextDuplicateWithLockingInfo";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open environment, primary database and
+ * secondary database.
+ */
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDBInTxn(testHome, dbFileName,
+ dbSecFileName, out env, out db, out secDB);
+
+ // Write ten records into the database.
+ WriteRecordsInTxn(db, env);
+
+ /*
+ * Create a cursor and move the cursor to duplicate
+ * record(10, 5), that is record(5,10) in primary database.
+ * Then move the cursor to the next duplicate record
+ * (10, 6), that is record(6,10) in primary database.
+ */
+ Transaction cursorTxn = env.BeginTransaction();
+ SecondaryCursor cursor =
+ secDB.SecondaryCursor(cursorTxn);
+ LockingInfo lockingInfo = new LockingInfo();
+ lockingInfo.IsolationDegree = Isolation.DEGREE_THREE;
+ lockingInfo.ReadModifyWrite = true;
+ cursor.Move(new DatabaseEntry(
+ BitConverter.GetBytes((int)10)), true, lockingInfo);
+ Assert.IsTrue(cursor.MoveNextDuplicate(lockingInfo));
+ Assert.AreEqual(BitConverter.GetBytes((int)10),
+ cursor.Current.Key.Data);
+ cursor.Close();
+ cursorTxn.Commit();
+
+ // Close all.
+ secDB.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestMoveNextUniqueWithLockingInfo()
+ {
+ testName = "TestMoveNextUniqueWithLockingInfo";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open environment, primary database and
+ * secondary database.
+ */
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDBInTxn(testHome, dbFileName,
+ dbSecFileName, out env, out db, out secDB);
+
+ // Write ten records into the database.
+ WriteRecordsInTxn(db, env);
+
+ /*
+ * Move cursor to duplicate record. Since the duplicate
+ * record has the largest key, moving to the next
+ * unique record should fail.
+ */
+ Transaction cursorTxn = env.BeginTransaction();
+ SecondaryCursor cursor =
+ secDB.SecondaryCursor(cursorTxn);
+ LockingInfo lockingInfo = new LockingInfo();
+ lockingInfo.IsolationDegree = Isolation.DEGREE_THREE;
+ lockingInfo.ReadModifyWrite = true;
+ cursor.Move(new DatabaseEntry(
+ BitConverter.GetBytes((int)10)), true);
+ Assert.IsFalse(cursor.MoveNextUnique());
+ cursor.Close();
+ cursorTxn.Commit();
+
+ // Close all.
+ secDB.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestMovePrevWithLockingInfo()
+ {
+ testName = "TestMovePrevWithLockingInfo";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open environment, primary database and
+ * secondary database.
+ */
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDBInTxn(testHome, dbFileName,
+ dbSecFileName, out env, out db, out secDB);
+
+ // Write ten records into the database.
+ WriteRecordsInTxn(db, env);
+
+ /*
+ * Move the cursor to the last record and move to its
+ * previous record for five times.
+ */
+ Transaction cursorTxn = env.BeginTransaction();
+ SecondaryCursor cursor =
+ secDB.SecondaryCursor(cursorTxn);
+ LockingInfo lockingInfo = new LockingInfo();
+ lockingInfo.IsolationDegree = Isolation.DEGREE_TWO;
+ lockingInfo.ReadModifyWrite = true;
+ cursor.MoveLast(lockingInfo);
+ for (int i = 0; i < 5; i++)
+ Assert.IsTrue(cursor.MovePrev(lockingInfo));
+ cursor.Close();
+ cursorTxn.Commit();
+
+ // Close all.
+ secDB.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestMovePrevDuplicateWithLockingInfo()
+ {
+ testName = "TestMovePrevDuplicateWithLockingInfo";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open environment, primary database and
+ * secondary database.
+ */
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDBInTxn(testHome, dbFileName,
+ dbSecFileName, out env, out db, out secDB);
+
+ // Write ten records into the database.
+ WriteRecordsInTxn(db, env);
+
+ Transaction cursorTxn = env.BeginTransaction();
+ SecondaryCursor cursor =
+ secDB.SecondaryCursor(cursorTxn);
+ LockingInfo lockingInfo = new LockingInfo();
+ lockingInfo.IsolationDegree = Isolation.DEGREE_TWO;
+ lockingInfo.ReadModifyWrite = true;
+
+ /*
+ * Move the cursor to the record(10,6), that is the
+ * record(6, 10) in the primary database. Move to
+ * its previous duplicate record, that is (10,5).
+ */
+ KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>> pair;
+ DatabaseEntry pKey, pData;
+ pKey = new DatabaseEntry(BitConverter.GetBytes((int)6));
+ pData = new DatabaseEntry(BitConverter.GetBytes((int)10));
+ pair = new KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>>(pData,
+ new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ pKey, pData));
+ cursor.Move(pair, true, lockingInfo);
+ Assert.IsTrue(cursor.MovePrevDuplicate(lockingInfo));
+ Assert.AreEqual(BitConverter.GetBytes((int)10),
+ cursor.Current.Key.Data);
+
+ cursor.Close();
+ cursorTxn.Commit();
+
+ // Close all.
+ secDB.Close();
+ db.Close();
+ env.Close();
+ }
+
+
+ [Test]
+ public void TestMovePrevUniqueWithLockingInfo()
+ {
+ testName = "TestMovePrevUniqueWithLockingInfo";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open environment, primary database and
+ * secondary database.
+ */
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDBInTxn(testHome, dbFileName,
+ dbSecFileName, out env, out db, out secDB);
+
+ // Write ten records into the database.
+ WriteRecordsInTxn(db, env);
+
+ Transaction cursorTxn = env.BeginTransaction();
+ SecondaryCursor cursor =
+ secDB.SecondaryCursor(cursorTxn);
+ LockingInfo lockingInfo = new LockingInfo();
+ lockingInfo.IsolationDegree = Isolation.DEGREE_TWO;
+ lockingInfo.ReadModifyWrite = true;
+
+ /*
+ * Move the cursor to the record(10, 6) and move to the
+ * previous unique record which has different key from
+ * the record(10,6).
+ */
+ KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>> pair;
+ DatabaseEntry pKey, pData;
+ pKey = new DatabaseEntry(BitConverter.GetBytes((int)6));
+ pData = new DatabaseEntry(BitConverter.GetBytes((int)10));
+ pair = new KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>>(pData,
+ new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ pKey, pData));
+ cursor.Move(pair, true, lockingInfo);
+ Assert.IsTrue(cursor.MovePrevUnique(lockingInfo));
+ Assert.AreNotEqual(BitConverter.GetBytes((int)10),
+ cursor.Current.Key.Data);
+
+ cursor.Close();
+ cursorTxn.Commit();
+
+ // Close all.
+ secDB.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestRefreshWithLockingInfo()
+ {
+ testName = "TestRefreshWithLockingInfo";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open environment, primary database and
+ * secondary database.
+ */
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ SecondaryBTreeDatabase secDB;
+ OpenSecDBInTxn(testHome, dbFileName,
+ dbSecFileName, out env, out db, out secDB);
+
+ // Write ten records into the database.
+ WriteRecordsInTxn(db, env);
+
+ Transaction cursorTxn = env.BeginTransaction();
+ SecondaryCursor cursor =
+ secDB.SecondaryCursor(cursorTxn);
+ LockingInfo lockingInfo = new LockingInfo();
+ lockingInfo.IsolationDegree = Isolation.DEGREE_TWO;
+ lockingInfo.ReadModifyWrite = true;
+
+ // Move cursor to a record and refresh it.
+ KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>> pair;
+ DatabaseEntry pKey, pData;
+ pKey = new DatabaseEntry(BitConverter.GetBytes((int)6));
+ pData = new DatabaseEntry(BitConverter.GetBytes((int)10));
+ pair = new KeyValuePair<DatabaseEntry, KeyValuePair<
+ DatabaseEntry, DatabaseEntry>>(pData,
+ new KeyValuePair<DatabaseEntry, DatabaseEntry>(
+ pKey, pData));
+ cursor.Move(pair, true, lockingInfo);
+ Assert.IsTrue(cursor.Refresh(lockingInfo));
+ Assert.AreEqual(pData.Data, cursor.Current.Key.Data);
+ Assert.AreEqual(pKey.Data, cursor.Current.Value.Key.Data);
+
+ cursor.Close();
+ cursorTxn.Commit();
+
+ // Close all.
+ secDB.Close();
+ db.Close();
+ env.Close();
+ }
+
+ public void OpenSecDBInTxn(string home, string dbFileName,
+ string dbSecFileName, out DatabaseEnvironment env,
+ out BTreeDatabase db, out SecondaryBTreeDatabase secDB)
+ {
+ // Open environment.
+ DatabaseEnvironmentConfig envCfg =
+ new DatabaseEnvironmentConfig();
+ envCfg.Create = true;
+ envCfg.UseLocking = true;
+ envCfg.UseLogging = true;
+ envCfg.UseMPool = true;
+ envCfg.UseTxns = true;
+ env = DatabaseEnvironment.Open(
+ home, envCfg);
+
+ // Open primary and secondary database in a transaction.
+ Transaction openTxn = env.BeginTransaction();
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ dbConfig.PageSize = 4096;
+ dbConfig.Duplicates = DuplicatesPolicy.NONE;
+ dbConfig.ReadUncommitted = true;
+ db = BTreeDatabase.Open(dbFileName, dbConfig,
+ openTxn);
+ openTxn.Commit();
+
+ openTxn = env.BeginTransaction();
+ SecondaryBTreeDatabaseConfig secConfig =
+ new SecondaryBTreeDatabaseConfig(db,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secConfig.Creation = CreatePolicy.IF_NEEDED;
+ secConfig.Duplicates = DuplicatesPolicy.SORTED;
+ secConfig.Env = env;
+ secConfig.ReadUncommitted = true;
+ secDB = SecondaryBTreeDatabase.Open(dbSecFileName,
+ secConfig, openTxn);
+ openTxn.Commit();
+ }
+
+ public void WriteRecords(BTreeDatabase db)
+ {
+ /*
+ * Write ten records into the database. The records
+ * from 1st to 5th and 8th to 10th are unique in the
+ * database. The data in the 6th and 7th records
+ * are the same.
+ */
+ for (int i = 0; i < 10; i++)
+ {
+ if (i == 5 || i == 6)
+ db.Put(new DatabaseEntry(
+ BitConverter.GetBytes(i)),
+ new DatabaseEntry(
+ BitConverter.GetBytes((int)10)));
+ else
+ db.Put(new DatabaseEntry(
+ BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+ }
+ }
+
+ public void WriteRecordsInTxn(BTreeDatabase db,
+ DatabaseEnvironment env)
+ {
+ Transaction txn = env.BeginTransaction();
+ /*
+ * Write ten records into the database. The records
+ * from 1st to 5th and 8th to 10th are unique in the
+ * database. The data in the 6th and 7th records
+ * are the same.
+ */
+ for (int i = 0; i < 10; i++)
+ {
+ if (i == 5 || i == 6)
+ db.Put(new DatabaseEntry(
+ BitConverter.GetBytes(i)),
+ new DatabaseEntry(
+ BitConverter.GetBytes((int)10)), txn);
+ else
+ db.Put(new DatabaseEntry(
+ BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)), txn);
+ }
+
+ txn.Commit();
+ }
+
+
+ public void OpenSecDB(string dbFileName,
+ string dbSecFileName, out BTreeDatabase db,
+ out SecondaryBTreeDatabase secDB)
+ {
+ // Open a primary database.
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ db = BTreeDatabase.Open(dbFileName, dbConfig);
+
+ // Open a secondary database.
+ SecondaryBTreeDatabaseConfig secConfig =
+ new SecondaryBTreeDatabaseConfig(db,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secConfig.Creation = CreatePolicy.IF_NEEDED;
+ secConfig.Duplicates = DuplicatesPolicy.SORTED;
+ secDB = SecondaryBTreeDatabase.Open(dbSecFileName,
+ secConfig);
+ }
+
+
+ public DatabaseEntry SecondaryKeyGen(
+ DatabaseEntry key, DatabaseEntry data)
+ {
+ DatabaseEntry dbtGen;
+ dbtGen = new DatabaseEntry(data.Data);
+ return dbtGen;
+ }
+ }
+}
diff --git a/test/scr037/SecondaryDatabaseConfigTest.cs b/test/scr037/SecondaryDatabaseConfigTest.cs
new file mode 100644
index 0000000..eef4abf
--- /dev/null
+++ b/test/scr037/SecondaryDatabaseConfigTest.cs
@@ -0,0 +1,83 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class SecondaryDatabaseConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "SecondaryDatabaseConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ virtual public void TestConfig()
+ {
+ testName = "TestConfig";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+
+
+ // Open a primary btree database.
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ dbFileName, btreeDBConfig);
+
+ SecondaryDatabaseConfig secDBConfig =
+ new SecondaryDatabaseConfig(btreeDB, null);
+ Config(xmlElem, ref secDBConfig, true);
+ Confirm(xmlElem, secDBConfig, true);
+ btreeDB.Close();
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref SecondaryDatabaseConfig secDBConfig,
+ bool compulsory)
+ {
+ Configuration.ConfigBool(xmlElement, "ImmutableKey",
+ ref secDBConfig.ImmutableKey, compulsory);
+ Configuration.ConfigBool(xmlElement, "Populate",
+ ref secDBConfig.Populate, compulsory);
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ SecondaryDatabaseConfig secDBConfig,
+ bool compulsory)
+ {
+ Configuration.ConfirmBool(xmlElement, "ImmutableKey",
+ secDBConfig.ImmutableKey, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Populate",
+ secDBConfig.Populate, compulsory);
+ }
+ }
+}
diff --git a/test/scr037/SecondaryDatabaseTest.cs b/test/scr037/SecondaryDatabaseTest.cs
new file mode 100644
index 0000000..40f54fe
--- /dev/null
+++ b/test/scr037/SecondaryDatabaseTest.cs
@@ -0,0 +1,518 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class SecondaryDatabaseTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "SecondaryDatabaseTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestKeyGen()
+ {
+ testName = "TestKeyGen";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open primary database.
+ BTreeDatabaseConfig primaryDBConfig =
+ new BTreeDatabaseConfig();
+ primaryDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase primaryDB =
+ BTreeDatabase.Open(dbFileName, primaryDBConfig);
+
+ // Open secondary database.
+ SecondaryBTreeDatabaseConfig secDBConfig =
+ new SecondaryBTreeDatabaseConfig(primaryDB,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ SecondaryBTreeDatabase secDB =
+ SecondaryBTreeDatabase.Open(dbFileName,
+ secDBConfig);
+
+ primaryDB.Put(new DatabaseEntry(
+ BitConverter.GetBytes((int)1)),
+ new DatabaseEntry(BitConverter.GetBytes((int)11)));
+
+ KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
+ pair = secDB.Get(new DatabaseEntry(
+ BitConverter.GetBytes((int)11)));
+ Assert.IsNotNull(pair.Value);
+
+ // Close secondary database.
+ secDB.Close();
+
+ // Close primary database.
+ primaryDB.Close();
+ }
+
+ [Test]
+ public void TestSecondaryCursor()
+ {
+ testName = "TestSecondaryCursor";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open primary database.
+ BTreeDatabaseConfig primaryDBConfig =
+ new BTreeDatabaseConfig();
+ primaryDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase primaryDB =
+ BTreeDatabase.Open(dbFileName, primaryDBConfig);
+
+ // Open secondary database.
+ SecondaryBTreeDatabaseConfig secDBConfig =
+ new SecondaryBTreeDatabaseConfig(primaryDB,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ SecondaryBTreeDatabase secDB =
+ SecondaryBTreeDatabase.Open(dbFileName,
+ secDBConfig);
+
+ primaryDB.Put(new DatabaseEntry(
+ BitConverter.GetBytes((int)1)),
+ new DatabaseEntry(BitConverter.GetBytes((int)11)));
+
+
+ SecondaryCursor cursor = secDB.SecondaryCursor();
+ cursor.Move(new DatabaseEntry(
+ BitConverter.GetBytes((int)11)), true);
+ Assert.AreEqual(BitConverter.GetBytes((int)11),
+ cursor.Current.Key.Data);
+
+ // Close the cursor.
+ cursor.Close();
+
+ // Close secondary database.
+ secDB.Close();
+
+ // Close primary database.
+ primaryDB.Close();
+ }
+
+ [Test]
+ public void TestSecondaryCursorWithConfig()
+ {
+ testName = "TestSecondaryCursorWithConfig";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabase db;
+ SecondaryBTreeDatabase secDB;
+ OpenPrimaryAndSecondaryDB(dbFileName, out db, out secDB);
+
+ for (int i = 0; i < 10; i++)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes((int)i)));
+
+ CursorConfig cursorConfig = new CursorConfig();
+ cursorConfig.WriteCursor = false;
+ SecondaryCursor cursor =
+ secDB.SecondaryCursor(cursorConfig);
+
+ cursor.Move(new DatabaseEntry(
+ BitConverter.GetBytes((int)5)), true);
+
+ Assert.AreEqual(1, cursor.Count());
+
+ // Close the cursor.
+ cursor.Close();
+
+ // Close secondary database.
+ secDB.Close();
+
+ // Close primary database.
+ db.Close();
+ }
+
+ [Test]
+ public void TestSecondaryCursorWithTxn()
+ {
+ testName = "TestSecondaryCursorWithTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ GetSecondaryCursurWithTxn(testHome, testName, false);
+ }
+
+ [Test]
+ public void TestSecondaryCursorWithConfigAndTxn()
+ {
+ testName = "TestSecondaryCursorWithConfigAndTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+ GetSecondaryCursurWithTxn(testHome, testName, true);
+ }
+
+ public void GetSecondaryCursurWithTxn(string home,
+ string name, bool ifCfg)
+ {
+ string dbFileName = name + ".db";
+ SecondaryCursor cursor;
+
+ // Open env.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(home,
+ envConfig);
+
+
+ // Open primary/secondary database.
+ Transaction txn = env.BeginTransaction();
+ BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ BTreeDatabase db = BTreeDatabase.Open(dbFileName,
+ dbConfig, txn);
+
+ SecondaryBTreeDatabaseConfig secDBConfig = new
+ SecondaryBTreeDatabaseConfig(db,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secDBConfig.Env = env;
+ SecondaryBTreeDatabase secDB =
+ SecondaryBTreeDatabase.Open(dbFileName,
+ secDBConfig, txn);
+
+ for (int i = 0; i < 10; i++)
+ db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes((int)i)), txn);
+
+
+ // Create secondary cursor.
+ if (ifCfg == false)
+ secDB.SecondaryCursor(txn);
+ else if (ifCfg == true)
+ {
+ CursorConfig cursorConfig = new CursorConfig();
+ cursorConfig.WriteCursor = false;
+ cursor = secDB.SecondaryCursor(cursorConfig, txn);
+ cursor.Close();
+ }
+
+ secDB.Close();
+ db.Close();
+ txn.Commit();
+ env.Close();
+ }
+
+ [Test]
+ public void TestOpen()
+ {
+ testName = "TestOpen";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" +
+ testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecQueueDB(dbFileName, dbSecFileName, false);
+ }
+
+ [Test]
+ public void TestOpenWithDBName()
+ {
+ testName = "TestOpenWithDBName";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" +
+ testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+ OpenSecQueueDB(dbFileName, dbSecFileName, true);
+ }
+
+ public void OpenSecQueueDB(string dbFileName,
+ string dbSecFileName, bool ifDBName)
+ {
+ // Open a primary btree database.
+ BTreeDatabaseConfig primaryDBConfig =
+ new BTreeDatabaseConfig();
+ primaryDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase primaryDB;
+
+ /*
+ * If secondary database name is given, the primary
+ * database is also opened with database name.
+ */
+ if (ifDBName == false)
+ primaryDB = BTreeDatabase.Open(dbFileName,
+ primaryDBConfig);
+ else
+ primaryDB = BTreeDatabase.Open(dbFileName,
+ "primary", primaryDBConfig);
+
+ try
+ {
+ // Open a new secondary database.
+ SecondaryBTreeDatabaseConfig secBTDBConfig =
+ new SecondaryBTreeDatabaseConfig(
+ primaryDB, null);
+ secBTDBConfig.Creation =
+ CreatePolicy.IF_NEEDED;
+
+ SecondaryBTreeDatabase secBTDB;
+ if (ifDBName == false)
+ secBTDB = SecondaryBTreeDatabase.Open(
+ dbSecFileName, secBTDBConfig);
+ else
+ secBTDB = SecondaryBTreeDatabase.Open(
+ dbSecFileName, "secondary",
+ secBTDBConfig);
+
+ // Close the secondary database.
+ secBTDB.Close();
+
+ // Open the existing secondary database.
+ SecondaryDatabaseConfig secDBConfig =
+ new SecondaryDatabaseConfig(
+ primaryDB, null);
+
+ SecondaryDatabase secDB;
+ if (ifDBName == false)
+ secDB = SecondaryBTreeDatabase.Open(
+ dbSecFileName, secDBConfig);
+ else
+ secDB = SecondaryBTreeDatabase.Open(
+ dbSecFileName, "secondary", secDBConfig);
+
+ // Close secondary database.
+ secDB.Close();
+ }
+ catch (DatabaseException)
+ {
+ throw new TestException();
+ }
+ finally
+ {
+ // Close primary database.
+ primaryDB.Close();
+ }
+ }
+
+ [Test]
+ public void TestOpenWithinTxn()
+ {
+ testName = "TestOpenWithinTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecQueueDBWithinTxn(testHome, dbFileName,
+ dbSecFileName, false);
+ }
+
+ [Test]
+ public void TestOpenDBNameWithinTxn()
+ {
+ testName = "TestOpenDBNameWithinTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecQueueDBWithinTxn(testHome, dbFileName,
+ dbSecFileName, true);
+ }
+
+ public void OpenSecQueueDBWithinTxn(string home,
+ string dbFileName, string dbSecFileName, bool ifDbName)
+ {
+ // Open an environment.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ envConfig.UseLogging = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConfig);
+
+ // Open a primary btree database.
+ Transaction openDBTxn = env.BeginTransaction();
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ BTreeDatabase db = BTreeDatabase.Open(
+ dbFileName, dbConfig, openDBTxn);
+ openDBTxn.Commit();
+
+ // Open a secondary btree database.
+ Transaction openSecTxn = env.BeginTransaction();
+ SecondaryBTreeDatabaseConfig secDBConfig =
+ new SecondaryBTreeDatabaseConfig(db,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secDBConfig.Env = env;
+ secDBConfig.Creation = CreatePolicy.IF_NEEDED;
+
+ SecondaryBTreeDatabase secDB;
+ if (ifDbName == false)
+ secDB = SecondaryBTreeDatabase.Open(
+ dbSecFileName, secDBConfig, openSecTxn);
+ else
+ secDB = SecondaryBTreeDatabase.Open(
+ dbSecFileName, "secondary", secDBConfig,
+ openSecTxn);
+ openSecTxn.Commit();
+ secDB.Close();
+
+ // Open the existing secondary database.
+ Transaction secTxn = env.BeginTransaction();
+ SecondaryDatabaseConfig secConfig =
+ new SecondaryDatabaseConfig(db,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secConfig.Env = env;
+
+ SecondaryDatabase secExDB;
+ if (ifDbName == false)
+ secExDB = SecondaryBTreeDatabase.Open(
+ dbSecFileName, secConfig, secTxn);
+ else
+ secExDB = SecondaryBTreeDatabase.Open(
+ dbSecFileName, "secondary", secConfig,
+ secTxn);
+ secExDB.Close();
+ secTxn.Commit();
+
+ db.Close();
+ env.Close();
+ }
+
+ public void OpenPrimaryAndSecondaryDB(string dbFileName,
+ out BTreeDatabase primaryDB,
+ out SecondaryBTreeDatabase secDB)
+ {
+ // Open primary database.
+ BTreeDatabaseConfig primaryDBConfig =
+ new BTreeDatabaseConfig();
+ primaryDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ primaryDB =
+ BTreeDatabase.Open(dbFileName, primaryDBConfig);
+
+ // Open secondary database.
+ SecondaryBTreeDatabaseConfig secDBConfig =
+ new SecondaryBTreeDatabaseConfig(primaryDB,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secDB = SecondaryBTreeDatabase.Open(dbFileName,
+ secDBConfig);
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestBadSecondaryException()
+ {
+ testName = "TestBadSecondaryException";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string secDBFileName = testHome + "/" +
+ testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open primary database.
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase btreeDB =
+ BTreeDatabase.Open(dbFileName, btreeDBConfig);
+
+ // Open secondary database.
+ SecondaryBTreeDatabaseConfig secBtDbConfig =
+ new SecondaryBTreeDatabaseConfig(btreeDB,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secBtDbConfig.Creation = CreatePolicy.IF_NEEDED;
+ SecondaryBTreeDatabase secBtDb =
+ SecondaryBTreeDatabase.Open(secDBFileName,
+ secBtDbConfig);
+
+ // Put some data into primary database.
+ for (int i = 0; i < 10; i++)
+ btreeDB.Put(new DatabaseEntry(
+ BitConverter.GetBytes(i)),
+ new DatabaseEntry(BitConverter.GetBytes(i)));
+
+ // Close the secondary database.
+ secBtDb.Close();
+
+ // Delete record(5, 5) in primary database.
+ btreeDB.Delete(new DatabaseEntry(
+ BitConverter.GetBytes((int)5)));
+
+ // Reopen the secondary database.
+ SecondaryDatabase secDB = SecondaryDatabase.Open(
+ secDBFileName,
+ new SecondaryDatabaseConfig(btreeDB,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen)));
+
+ /*
+ * Getting record(5, 5) by secondary database should
+ * throw BadSecondaryException since it has been
+ * deleted in the primary database.
+ */
+ try
+ {
+ secDB.Exists(new DatabaseEntry(
+ BitConverter.GetBytes((int)5)));
+ }
+ catch (BadSecondaryException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ secDB.Close();
+ btreeDB.Close();
+ }
+ }
+
+ public DatabaseEntry SecondaryKeyGen(
+ DatabaseEntry key, DatabaseEntry data)
+ {
+ DatabaseEntry dbtGen;
+ dbtGen = new DatabaseEntry(data.Data);
+ return dbtGen;
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/test/scr037/SecondaryHashDatabaseConfigTest.cs b/test/scr037/SecondaryHashDatabaseConfigTest.cs
new file mode 100644
index 0000000..7125a94
--- /dev/null
+++ b/test/scr037/SecondaryHashDatabaseConfigTest.cs
@@ -0,0 +1,109 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class SecondaryHashDatabaseConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "SecondaryHashDatabaseConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ // Open a primary btree database.
+ HashDatabaseConfig hashDBConfig =
+ new HashDatabaseConfig();
+ hashDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ HashDatabase hashDB = HashDatabase.Open(
+ dbFileName, hashDBConfig);
+
+ SecondaryHashDatabaseConfig secDBConfig =
+ new SecondaryHashDatabaseConfig(hashDB, null);
+
+ Config(xmlElem, ref secDBConfig, true);
+ Confirm(xmlElem, secDBConfig, true);
+
+ // Close the primary btree database.
+ hashDB.Close();
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ SecondaryHashDatabaseConfig secHashDBConfig,
+ bool compulsory)
+ {
+ SecondaryDatabaseConfig secDBConfig =
+ secHashDBConfig;
+ SecondaryDatabaseConfigTest.Confirm(xmlElement,
+ secDBConfig, compulsory);
+
+ // Confirm secondary hash database specific configuration.
+ Configuration.ConfirmCreatePolicy(xmlElement,
+ "Creation", secHashDBConfig.Creation, compulsory);
+ Configuration.ConfirmDuplicatesPolicy(xmlElement,
+ "Duplicates", secHashDBConfig.Duplicates, compulsory);
+ Configuration.ConfirmUint(xmlElement, "FillFactor",
+ secHashDBConfig.FillFactor, compulsory);
+ Configuration.ConfirmUint(xmlElement,
+ "NumElements",
+ secHashDBConfig.TableSize, compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref SecondaryHashDatabaseConfig secHashDBConfig,
+ bool compulsory)
+ {
+ uint fillFactor = new uint();
+ uint numElements = new uint();
+
+ SecondaryDatabaseConfig secDBConfig = secHashDBConfig;
+ SecondaryDatabaseConfigTest.Config(xmlElement,
+ ref secDBConfig, compulsory);
+
+ // Configure specific fields/properties of hash db
+ Configuration.ConfigCreatePolicy(xmlElement,
+ "Creation", ref secHashDBConfig.Creation, compulsory);
+ Configuration.ConfigDuplicatesPolicy(xmlElement,
+ "Duplicates", ref secHashDBConfig.Duplicates, compulsory);
+ if (Configuration.ConfigUint(xmlElement, "FillFactor",
+ ref fillFactor, compulsory))
+ secHashDBConfig.FillFactor = fillFactor;
+ if (Configuration.ConfigUint(xmlElement, "NumElements",
+ ref numElements, compulsory))
+ secHashDBConfig.TableSize = numElements;
+ }
+ }
+}
+
diff --git a/test/scr037/SecondaryHashDatabaseTest.cs b/test/scr037/SecondaryHashDatabaseTest.cs
new file mode 100644
index 0000000..839e8c9
--- /dev/null
+++ b/test/scr037/SecondaryHashDatabaseTest.cs
@@ -0,0 +1,403 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class SecondaryHashDatabaseTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "SecondaryHashDatabaseTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestHashFunction()
+ {
+ testName = "TestHashFunction";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" +
+ testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a primary hash database.
+ HashDatabaseConfig dbConfig =
+ new HashDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ HashDatabase hashDB = HashDatabase.Open(
+ dbFileName, dbConfig);
+
+ /*
+ * Define hash function and open a secondary
+ * hash database.
+ */
+ SecondaryHashDatabaseConfig secDBConfig =
+ new SecondaryHashDatabaseConfig(hashDB, null);
+ secDBConfig.HashFunction =
+ new HashFunctionDelegate(HashFunction);
+ secDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ SecondaryHashDatabase secDB =
+ SecondaryHashDatabase.Open(dbSecFileName,
+ secDBConfig);
+
+ /*
+ * Confirm the hash function defined in the configuration.
+ * Call the hash function and the one from secondary
+ * database. If they return the same value, then the hash
+ * function is configured successfully.
+ */
+ uint data = secDB.HashFunction(BitConverter.GetBytes(1));
+ Assert.AreEqual(0, data);
+
+ // Close all.
+ secDB.Close();
+ hashDB.Close();
+ }
+
+ public uint HashFunction(byte[] data)
+ {
+ data[0] = 0;
+ return BitConverter.ToUInt32(data, 0);
+ }
+
+ [Test]
+ public void TestCompare()
+ {
+ testName = "TestCompare";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName +
+ "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a primary hash database.
+ HashDatabaseConfig dbConfig =
+ new HashDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.ALWAYS;
+ HashDatabase db = HashDatabase.Open(
+ dbFileName, dbConfig);
+
+ // Open a secondary hash database.
+ SecondaryHashDatabaseConfig secConfig =
+ new SecondaryHashDatabaseConfig(null, null);
+ secConfig.Creation = CreatePolicy.IF_NEEDED;
+ secConfig.Primary = db;
+ secConfig.Compare =
+ new EntryComparisonDelegate(SecondaryEntryComparison);
+ SecondaryHashDatabase secDB =
+ SecondaryHashDatabase.Open(dbSecFileName, secConfig);
+
+ /*
+ * Get the compare function set in the configuration
+ * and run it in a comparison to see if it is alright.
+ */
+ DatabaseEntry dbt1, dbt2;
+ dbt1 = new DatabaseEntry(
+ BitConverter.GetBytes((int)257));
+ dbt2 = new DatabaseEntry(
+ BitConverter.GetBytes((int)255));
+ Assert.Less(0, secDB.Compare(dbt1, dbt2));
+
+ secDB.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestDuplicates()
+ {
+ testName = "TestDuplicates";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" + testName
+ + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a primary hash database.
+ HashDatabaseConfig dbConfig =
+ new HashDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.ALWAYS;
+ HashDatabase db = HashDatabase.Open(
+ dbFileName, dbConfig);
+
+ // Open a secondary hash database.
+ SecondaryHashDatabaseConfig secConfig =
+ new SecondaryHashDatabaseConfig(null, null);
+ secConfig.Primary = db;
+ secConfig.Duplicates = DuplicatesPolicy.SORTED;
+ secConfig.Creation = CreatePolicy.IF_NEEDED;
+ SecondaryHashDatabase secDB =
+ SecondaryHashDatabase.Open(
+ dbSecFileName, secConfig);
+
+ // Confirm the duplicate in opened secondary database.
+ Assert.AreEqual(DuplicatesPolicy.SORTED,
+ secDB.Duplicates);
+
+ secDB.Close();
+ db.Close();
+ }
+
+
+ /*
+ * Tests to all Open() share the same configuration in
+ * AllTestData.xml.
+ */
+ [Test]
+ public void TestOpen()
+ {
+ testName = "TestOpen";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" +
+ testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecHashDB(testFixtureName, "TestOpen",
+ dbFileName, dbSecFileName, false);
+ }
+
+ [Test]
+ public void TestOpenWithDBName()
+ {
+ testName = "TestOpenWithDBName";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" +
+ testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecHashDB(testFixtureName, "TestOpen",
+ dbFileName, dbSecFileName, true);
+ }
+
+ public void OpenSecHashDB(string className,
+ string funName, string dbFileName, string dbSecFileName,
+ bool ifDBName)
+ {
+ XmlElement xmlElem = Configuration.TestSetUp(
+ className, funName);
+
+ // Open a primary recno database.
+ HashDatabaseConfig primaryDBConfig =
+ new HashDatabaseConfig();
+ primaryDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ HashDatabase primaryDB;
+
+ /*
+ * If secondary database name is given, the primary
+ * database is also opened with database name.
+ */
+ if (ifDBName == false)
+ primaryDB = HashDatabase.Open(dbFileName,
+ primaryDBConfig);
+ else
+ primaryDB = HashDatabase.Open(dbFileName,
+ "primary", primaryDBConfig);
+
+ try
+ {
+ // Open a new secondary database.
+ SecondaryHashDatabaseConfig secHashDBConfig =
+ new SecondaryHashDatabaseConfig(
+ primaryDB, null);
+ SecondaryHashDatabaseConfigTest.Config(
+ xmlElem, ref secHashDBConfig, false);
+ secHashDBConfig.Creation =
+ CreatePolicy.IF_NEEDED;
+
+ SecondaryHashDatabase secHashDB;
+ if (ifDBName == false)
+ secHashDB = SecondaryHashDatabase.Open(
+ dbSecFileName, secHashDBConfig);
+ else
+ secHashDB = SecondaryHashDatabase.Open(
+ dbSecFileName, "secondary",
+ secHashDBConfig);
+
+ // Close the secondary database.
+ secHashDB.Close();
+
+ // Open the existing secondary database.
+ SecondaryDatabaseConfig secDBConfig =
+ new SecondaryDatabaseConfig(
+ primaryDB, null);
+
+ SecondaryDatabase secDB;
+ if (ifDBName == false)
+ secDB = SecondaryHashDatabase.Open(
+ dbSecFileName, secDBConfig);
+ else
+ secDB = SecondaryHashDatabase.Open(
+ dbSecFileName, "secondary", secDBConfig);
+
+ // Close secondary database.
+ secDB.Close();
+ }
+ catch (DatabaseException)
+ {
+ throw new TestException();
+ }
+ finally
+ {
+ // Close primary database.
+ primaryDB.Close();
+ }
+ }
+
+ [Test]
+ public void TestOpenWithinTxn()
+ {
+ testName = "TestOpenWithinTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecHashDBWithinTxn(testFixtureName,
+ "TestOpen", testHome, dbFileName,
+ dbSecFileName, false);
+ }
+
+ [Test]
+ public void TestOpenDBNameWithinTxn()
+ {
+ testName = "TestOpenDBNameWithinTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecHashDBWithinTxn(testFixtureName,
+ "TestOpen", testHome, dbFileName,
+ dbSecFileName, true);
+ }
+
+ public void OpenSecHashDBWithinTxn(string className,
+ string funName, string home, string dbFileName,
+ string dbSecFileName, bool ifDbName)
+ {
+ XmlElement xmlElem = Configuration.TestSetUp(
+ className, funName);
+
+ // Open an environment.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ envConfig.UseLogging = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConfig);
+
+ // Open a primary hash database.
+ Transaction openDBTxn = env.BeginTransaction();
+ HashDatabaseConfig dbConfig =
+ new HashDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ HashDatabase db = HashDatabase.Open(
+ dbFileName, dbConfig, openDBTxn);
+ openDBTxn.Commit();
+
+ // Open a secondary hash database.
+ Transaction openSecTxn = env.BeginTransaction();
+ SecondaryHashDatabaseConfig secDBConfig =
+ new SecondaryHashDatabaseConfig(db,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ SecondaryHashDatabaseConfigTest.Config(xmlElem,
+ ref secDBConfig, false);
+ secDBConfig.HashFunction = null;
+ secDBConfig.Env = env;
+ SecondaryHashDatabase secDB;
+ if (ifDbName == false)
+ secDB = SecondaryHashDatabase.Open(
+ dbSecFileName, secDBConfig, openSecTxn);
+ else
+ secDB = SecondaryHashDatabase.Open(
+ dbSecFileName, "secondary", secDBConfig,
+ openSecTxn);
+ openSecTxn.Commit();
+
+ // Confirm its flags configured in secDBConfig.
+ Confirm(xmlElem, secDB, true);
+ secDB.Close();
+
+ // Open the existing secondary database.
+ Transaction secTxn = env.BeginTransaction();
+ SecondaryDatabaseConfig secConfig =
+ new SecondaryDatabaseConfig(db,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secConfig.Env = env;
+
+ SecondaryDatabase secExDB;
+ if (ifDbName == false)
+ secExDB = SecondaryHashDatabase.Open(
+ dbSecFileName, secConfig, secTxn);
+ else
+ secExDB = SecondaryHashDatabase.Open(
+ dbSecFileName, "secondary", secConfig,
+ secTxn);
+ secExDB.Close();
+ secTxn.Commit();
+
+ db.Close();
+ env.Close();
+ }
+
+ public DatabaseEntry SecondaryKeyGen(
+ DatabaseEntry key, DatabaseEntry data)
+ {
+ DatabaseEntry dbtGen;
+ dbtGen = new DatabaseEntry(data.Data);
+ return dbtGen;
+ }
+
+ public int SecondaryEntryComparison(
+ DatabaseEntry dbt1, DatabaseEntry dbt2)
+ {
+ int a, b;
+ a = BitConverter.ToInt32(dbt1.Data, 0);
+ b = BitConverter.ToInt32(dbt2.Data, 0);
+ return a - b;
+ }
+
+ public static void Confirm(XmlElement xmlElem,
+ SecondaryHashDatabase secDB, bool compulsory)
+ {
+ Configuration.ConfirmUint(xmlElem, "FillFactor",
+ secDB.FillFactor, compulsory);
+ Configuration.ConfirmUint(xmlElem, "NumElements",
+ secDB.TableSize * secDB.FillFactor, compulsory);
+ }
+ }
+}
diff --git a/test/scr037/SecondaryQueueDatabaseConfigTest.cs b/test/scr037/SecondaryQueueDatabaseConfigTest.cs
new file mode 100644
index 0000000..4807335
--- /dev/null
+++ b/test/scr037/SecondaryQueueDatabaseConfigTest.cs
@@ -0,0 +1,109 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class SecondaryQueueDatabaseConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "SecondaryQueueDatabaseConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+
+ // Open a primary btree database.
+ QueueDatabaseConfig queueDBConfig =
+ new QueueDatabaseConfig();
+ queueDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ QueueDatabase queueDB = QueueDatabase.Open(
+ dbFileName, queueDBConfig);
+
+ SecondaryQueueDatabaseConfig secDBConfig =
+ new SecondaryQueueDatabaseConfig(queueDB, null);
+
+ Config(xmlElem, ref secDBConfig, true);
+ Confirm(xmlElem, secDBConfig, true);
+
+ // Close the primary btree database.
+ queueDB.Close();
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ SecondaryQueueDatabaseConfig secQueueDBConfig,
+ bool compulsory)
+ {
+ SecondaryDatabaseConfig secDBConfig =
+ secQueueDBConfig;
+ SecondaryDatabaseConfigTest.Confirm(xmlElement,
+ secDBConfig, compulsory);
+
+ // Confirm secondary hash database specific configuration.
+ Configuration.ConfirmCreatePolicy(xmlElement,
+ "Creation", secQueueDBConfig.Creation, compulsory);
+ Configuration.ConfirmUint(xmlElement,
+ "ExtentSize", secQueueDBConfig.ExtentSize, compulsory);
+ Configuration.ConfirmUint(xmlElement, "Length",
+ secQueueDBConfig.Length, compulsory);
+ Configuration.ConfirmInt(xmlElement, "PadByte",
+ secQueueDBConfig.PadByte, compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref SecondaryQueueDatabaseConfig secQueueDBConfig,
+ bool compulsory)
+ {
+ uint uintValue = new uint();
+ int intValue = new int();
+ SecondaryDatabaseConfig secConfig = secQueueDBConfig;
+ SecondaryDatabaseConfigTest.Config(xmlElement,
+ ref secConfig, compulsory);
+
+ // Configure specific fields/properties of Queue database
+ Configuration.ConfigCreatePolicy(xmlElement, "Creation",
+ ref secQueueDBConfig.Creation, compulsory);
+ if (Configuration.ConfigUint(xmlElement, "Length",
+ ref uintValue, compulsory))
+ secQueueDBConfig.Length = uintValue;
+ if (Configuration.ConfigInt(xmlElement, "PadByte",
+ ref intValue, compulsory))
+ secQueueDBConfig.PadByte = intValue;
+ if (Configuration.ConfigUint(xmlElement, "ExtentSize",
+ ref uintValue, compulsory))
+ secQueueDBConfig.ExtentSize = uintValue;
+ }
+ }
+}
+
diff --git a/test/scr037/SecondaryQueueDatabaseTest.cs b/test/scr037/SecondaryQueueDatabaseTest.cs
new file mode 100644
index 0000000..7a6a0a3
--- /dev/null
+++ b/test/scr037/SecondaryQueueDatabaseTest.cs
@@ -0,0 +1,227 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class SecondaryQueueDatabaseTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "SecondaryQueueDatabaseTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ /*
+ * Tests to all Open() share the same configuration in
+ * AllTestData.xml.
+ */
+ [Test]
+ public void TestOpen()
+ {
+ testName = "TestOpen";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" +
+ testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecQueueDB(testFixtureName, "TestOpen",
+ dbFileName, dbSecFileName);
+ }
+
+ public void OpenSecQueueDB(string className,
+ string funName, string dbFileName, string dbSecFileName)
+ {
+ XmlElement xmlElem = Configuration.TestSetUp(
+ className, funName);
+
+ // Open a primary queue database.
+ QueueDatabaseConfig primaryDBConfig =
+ new QueueDatabaseConfig();
+ primaryDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ QueueDatabase primaryDB;
+
+ /*
+ * If secondary database name is given, the primary
+ * database is also opened with database name.
+ */
+ primaryDB = QueueDatabase.Open(dbFileName,
+ primaryDBConfig);
+
+ try
+ {
+ // Open a new secondary database.
+ SecondaryQueueDatabaseConfig secQueueDBConfig =
+ new SecondaryQueueDatabaseConfig(
+ primaryDB, null);
+ SecondaryQueueDatabaseConfigTest.Config(
+ xmlElem, ref secQueueDBConfig, false);
+ secQueueDBConfig.Creation =
+ CreatePolicy.IF_NEEDED;
+
+ SecondaryQueueDatabase secQueueDB;
+ secQueueDB = SecondaryQueueDatabase.Open(
+ dbSecFileName, secQueueDBConfig);
+
+ // Close the secondary database.
+ secQueueDB.Close();
+
+ // Open the existing secondary database.
+ SecondaryDatabaseConfig secDBConfig =
+ new SecondaryQueueDatabaseConfig(
+ primaryDB, null);
+
+ SecondaryDatabase secDB;
+ secDB = SecondaryQueueDatabase.Open(
+ dbSecFileName, secDBConfig);
+
+ // Close secondary database.
+ secDB.Close();
+ }
+ catch (DatabaseException)
+ {
+ throw new TestException();
+ }
+ finally
+ {
+ // Close primary database.
+ primaryDB.Close();
+ }
+ }
+
+ [Test]
+ public void TestOpenWithinTxn()
+ {
+ testName = "TestOpenWithinTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecQueueDBWithinTxn(testFixtureName,
+ "TestOpen", testHome, dbFileName,
+ dbSecFileName);
+ }
+
+ [Test]
+ public void TestOpenDBNameWithinTxn()
+ {
+ testName = "TestOpenDBNameWithinTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecQueueDBWithinTxn(testFixtureName,
+ "TestOpen", testHome, dbFileName,
+ dbSecFileName);
+ }
+
+ public void OpenSecQueueDBWithinTxn(string className,
+ string funName, string home, string dbFileName,
+ string dbSecFileName)
+ {
+ XmlElement xmlElem = Configuration.TestSetUp(
+ className, funName);
+
+ // Open an environment.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ envConfig.UseLogging = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConfig);
+
+ // Open a primary queue database.
+ Transaction openDBTxn = env.BeginTransaction();
+ QueueDatabaseConfig dbConfig =
+ new QueueDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ QueueDatabase db = QueueDatabase.Open(
+ dbFileName, dbConfig, openDBTxn);
+ openDBTxn.Commit();
+
+ // Open a secondary queue database.
+ Transaction openSecTxn = env.BeginTransaction();
+ SecondaryQueueDatabaseConfig secDBConfig =
+ new SecondaryQueueDatabaseConfig(db,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ SecondaryQueueDatabaseConfigTest.Config(xmlElem,
+ ref secDBConfig, true);
+ secDBConfig.Env = env;
+ SecondaryQueueDatabase secDB;
+ secDB = SecondaryQueueDatabase.Open(
+ dbSecFileName, secDBConfig, openSecTxn);
+
+ openSecTxn.Commit();
+
+ // Confirm its flags configured in secDBConfig.
+ Confirm(xmlElem, secDB, true);
+ secDB.Close();
+
+ // Open the existing secondary database.
+ Transaction secTxn = env.BeginTransaction();
+ SecondaryDatabaseConfig secConfig =
+ new SecondaryDatabaseConfig(db,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secConfig.Env = env;
+
+ SecondaryDatabase secExDB;
+ secExDB = SecondaryQueueDatabase.Open(
+ dbSecFileName, secConfig, secTxn);
+
+ secExDB.Close();
+ secTxn.Commit();
+
+ db.Close();
+ env.Close();
+ }
+
+ public DatabaseEntry SecondaryKeyGen(
+ DatabaseEntry key, DatabaseEntry data)
+ {
+ DatabaseEntry dbtGen;
+ dbtGen = new DatabaseEntry(data.Data);
+ return dbtGen;
+ }
+
+ public static void Confirm(XmlElement xmlElem,
+ SecondaryQueueDatabase secDB, bool compulsory)
+ {
+ Configuration.ConfirmUint(xmlElem,
+ "ExtentSize", secDB.ExtentSize, compulsory);
+ Configuration.ConfirmUint(xmlElem, "Length",
+ secDB.Length, compulsory);
+ Configuration.ConfirmInt(xmlElem, "PadByte",
+ secDB.PadByte, compulsory);
+ }
+ }
+}
diff --git a/test/scr037/SecondaryRecnoDatabaseConfigTest.cs b/test/scr037/SecondaryRecnoDatabaseConfigTest.cs
new file mode 100644
index 0000000..fe1159f
--- /dev/null
+++ b/test/scr037/SecondaryRecnoDatabaseConfigTest.cs
@@ -0,0 +1,119 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class SecondaryRecnoDatabaseConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "SecondaryRecnoDatabaseConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+
+ // Open a primary btree database.
+ RecnoDatabaseConfig recDBConfig =
+ new RecnoDatabaseConfig();
+ recDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ RecnoDatabase recDB = RecnoDatabase.Open(
+ dbFileName, recDBConfig);
+
+ SecondaryRecnoDatabaseConfig secDBConfig =
+ new SecondaryRecnoDatabaseConfig(recDB, null);
+
+ Config(xmlElem, ref secDBConfig, true);
+ Confirm(xmlElem, secDBConfig, true);
+
+ // Close the primary btree database.
+ recDB.Close();
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ SecondaryRecnoDatabaseConfig secRecDBConfig,
+ bool compulsory)
+ {
+ SecondaryDatabaseConfig secDBConfig =
+ secRecDBConfig;
+ SecondaryDatabaseConfigTest.Confirm(xmlElement,
+ secDBConfig, compulsory);
+
+ // Confirm secondary hash database specific configuration.
+ Configuration.ConfirmString(xmlElement, "BackingFile",
+ secRecDBConfig.BackingFile, compulsory);
+ Configuration.ConfirmCreatePolicy(xmlElement, "Creation",
+ secRecDBConfig.Creation, compulsory);
+ Configuration.ConfirmInt(xmlElement, "Delimiter",
+ secRecDBConfig.Delimiter, compulsory);
+ Configuration.ConfirmUint(xmlElement, "Length",
+ secRecDBConfig.Length, compulsory);
+ Configuration.ConfirmInt(xmlElement, "PadByte",
+ secRecDBConfig.PadByte, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Renumber",
+ secRecDBConfig.Renumber, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Snapshot",
+ secRecDBConfig.Snapshot, compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref SecondaryRecnoDatabaseConfig secRecDBConfig,
+ bool compulsory)
+ {
+ int intValue = new int();
+ uint uintValue = new uint();
+ SecondaryDatabaseConfig secDBConfig = secRecDBConfig;
+ SecondaryDatabaseConfigTest.Config(xmlElement,
+ ref secDBConfig, compulsory);
+
+ // Configure specific fields/properties of Recno database
+ Configuration.ConfigCreatePolicy(xmlElement, "Creation",
+ ref secRecDBConfig.Creation, compulsory);
+ if (Configuration.ConfigInt(xmlElement, "Delimiter",
+ ref intValue, compulsory))
+ secRecDBConfig.Delimiter = intValue;
+ if (Configuration.ConfigUint(xmlElement, "Length",
+ ref uintValue, compulsory))
+ secRecDBConfig.Length = uintValue;
+ if (Configuration.ConfigInt(xmlElement, "PadByte",
+ ref intValue, compulsory))
+ secRecDBConfig.PadByte = intValue;
+ Configuration.ConfigBool(xmlElement, "Renumber",
+ ref secRecDBConfig.Renumber, compulsory);
+ Configuration.ConfigBool(xmlElement, "Snapshot",
+ ref secRecDBConfig.Snapshot, compulsory);
+ }
+ }
+}
+
diff --git a/test/scr037/SecondaryRecnoDatabaseTest.cs b/test/scr037/SecondaryRecnoDatabaseTest.cs
new file mode 100644
index 0000000..ac22115
--- /dev/null
+++ b/test/scr037/SecondaryRecnoDatabaseTest.cs
@@ -0,0 +1,269 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class SecondaryRecnoDatabaseTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "SecondaryRecnoDatabaseTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ /*
+ * Tests to all Open() share the same configuration in
+ * AllTestData.xml.
+ */
+ [Test]
+ public void TestOpen()
+ {
+ testName = "TestOpen";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" +
+ testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecRecnoDB(testFixtureName, "TestOpen",
+ dbFileName, dbSecFileName, false);
+ }
+
+ [Test]
+ public void TestOpenWithDBName()
+ {
+ testName = "TestOpenWithDBName";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ string dbSecFileName = testHome + "/" +
+ testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecRecnoDB(testFixtureName, "TestOpen",
+ dbFileName, dbSecFileName, true);
+ }
+
+ public void OpenSecRecnoDB(string className,
+ string funName, string dbFileName, string dbSecFileName,
+ bool ifDBName)
+ {
+ XmlElement xmlElem = Configuration.TestSetUp(
+ className, funName);
+
+ // Open a primary recno database.
+ RecnoDatabaseConfig primaryDBConfig =
+ new RecnoDatabaseConfig();
+ primaryDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ RecnoDatabase primaryDB;
+
+ /*
+ * If secondary database name is given, the primary
+ * database is also opened with database name.
+ */
+ if (ifDBName == false)
+ primaryDB = RecnoDatabase.Open(dbFileName,
+ primaryDBConfig);
+ else
+ primaryDB = RecnoDatabase.Open(dbFileName,
+ "primary", primaryDBConfig);
+
+ try
+ {
+ // Open a new secondary database.
+ SecondaryRecnoDatabaseConfig secRecnoDBConfig =
+ new SecondaryRecnoDatabaseConfig(
+ primaryDB, null);
+ SecondaryRecnoDatabaseConfigTest.Config(
+ xmlElem, ref secRecnoDBConfig, false);
+ secRecnoDBConfig.Creation =
+ CreatePolicy.IF_NEEDED;
+
+ SecondaryRecnoDatabase secRecnoDB;
+ if (ifDBName == false)
+ secRecnoDB = SecondaryRecnoDatabase.Open(
+ dbSecFileName, secRecnoDBConfig);
+ else
+ secRecnoDB = SecondaryRecnoDatabase.Open(
+ dbSecFileName, "secondary",
+ secRecnoDBConfig);
+
+ // Close the secondary database.
+ secRecnoDB.Close();
+
+ // Open the existing secondary database.
+ SecondaryDatabaseConfig secDBConfig =
+ new SecondaryDatabaseConfig(
+ primaryDB, null);
+
+ SecondaryDatabase secDB;
+ if (ifDBName == false)
+ secDB = SecondaryRecnoDatabase.Open(
+ dbSecFileName, secDBConfig);
+ else
+ secDB = SecondaryRecnoDatabase.Open(
+ dbSecFileName, "secondary", secDBConfig);
+
+ // Close secondary database.
+ secDB.Close();
+ }
+ catch (DatabaseException)
+ {
+ throw new TestException();
+ }
+ finally
+ {
+ // Close primary database.
+ primaryDB.Close();
+ }
+ }
+
+ [Test]
+ public void TestOpenWithinTxn()
+ {
+ testName = "TestOpenWithinTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecRecnoDBWithinTxn(testFixtureName,
+ "TestOpen", testHome, dbFileName,
+ dbSecFileName, false);
+ }
+
+ [Test]
+ public void TestOpenDBNameWithinTxn()
+ {
+ testName = "TestOpenDBNameWithinTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+ string dbSecFileName = testName + "_sec.db";
+
+ Configuration.ClearDir(testHome);
+
+ OpenSecRecnoDBWithinTxn(testFixtureName,
+ "TestOpen", testHome, dbFileName,
+ dbSecFileName, true);
+ }
+
+ public void OpenSecRecnoDBWithinTxn(string className,
+ string funName, string home, string dbFileName,
+ string dbSecFileName, bool ifDbName)
+ {
+ XmlElement xmlElem = Configuration.TestSetUp(
+ className, funName);
+
+ // Open an environment.
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ envConfig.UseLogging = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(
+ home, envConfig);
+
+ // Open a primary recno database.
+ Transaction openDBTxn = env.BeginTransaction();
+ RecnoDatabaseConfig dbConfig =
+ new RecnoDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+
+ dbConfig.Env = env;
+ RecnoDatabase db = RecnoDatabase.Open(
+ dbFileName, dbConfig, openDBTxn);
+ openDBTxn.Commit();
+
+ // Open a secondary recno database.
+ Transaction openSecTxn = env.BeginTransaction();
+ SecondaryRecnoDatabaseConfig secDBConfig =
+ new SecondaryRecnoDatabaseConfig(db,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ SecondaryRecnoDatabaseConfigTest.Config(xmlElem,
+ ref secDBConfig, false);
+ secDBConfig.Env = env;
+ SecondaryRecnoDatabase secDB;
+ if (ifDbName == false)
+ secDB = SecondaryRecnoDatabase.Open(
+ dbSecFileName, secDBConfig, openSecTxn);
+ else
+ secDB = SecondaryRecnoDatabase.Open(
+ dbSecFileName, "secondary", secDBConfig,
+ openSecTxn);
+ openSecTxn.Commit();
+
+ // Confirm its flags configured in secDBConfig.
+ Confirm(xmlElem, secDB, true);
+ secDB.Close();
+
+ // Open the existing secondary database.
+ Transaction secTxn = env.BeginTransaction();
+ SecondaryDatabaseConfig secConfig =
+ new SecondaryDatabaseConfig(db,
+ new SecondaryKeyGenDelegate(SecondaryKeyGen));
+ secConfig.Env = env;
+
+ SecondaryDatabase secExDB;
+ if (ifDbName == false)
+ secExDB = SecondaryRecnoDatabase.Open(
+ dbSecFileName, secConfig, secTxn);
+ else
+ secExDB = SecondaryRecnoDatabase.Open(
+ dbSecFileName, "secondary", secConfig,
+ secTxn);
+ secExDB.Close();
+ secTxn.Commit();
+
+ db.Close();
+ env.Close();
+ }
+
+ public DatabaseEntry SecondaryKeyGen(
+ DatabaseEntry key, DatabaseEntry data)
+ {
+ DatabaseEntry dbtGen;
+ dbtGen = new DatabaseEntry(data.Data);
+ return dbtGen;
+ }
+
+ public static void Confirm(XmlElement xmlElem,
+ SecondaryRecnoDatabase secDB, bool compulsory)
+ {
+ Configuration.ConfirmInt(xmlElem, "Delimiter",
+ secDB.Delimiter, compulsory);
+ Configuration.ConfirmUint(xmlElem, "Length",
+ secDB.Length, compulsory);
+ Configuration.ConfirmInt(xmlElem, "PadByte",
+ secDB.PadByte, compulsory);
+ Configuration.ConfirmBool(xmlElem,
+ "Renumber", secDB.Renumber, compulsory);
+ Configuration.ConfirmBool(xmlElem, "Snapshot",
+ secDB.Snapshot, compulsory);
+ }
+ }
+}
diff --git a/test/scr037/SequenceConfigTest.cs b/test/scr037/SequenceConfigTest.cs
new file mode 100644
index 0000000..d8e4bc0
--- /dev/null
+++ b/test/scr037/SequenceConfigTest.cs
@@ -0,0 +1,132 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class SequenceConfigTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "SequenceConfigTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+
+ SequenceConfig seqConfig = new SequenceConfig();
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ Config(xmlElem, ref seqConfig, true);
+ Confirm(xmlElem, seqConfig, true);
+ }
+
+ [Test]
+ public void TestConfigObj()
+ {
+ testName = "TestConfigObj";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database.
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ dbFileName, btreeDBConfig);
+
+ /* Configure and initialize sequence. */
+ SequenceConfig seqConfig = new SequenceConfig();
+ seqConfig.BackingDatabase = btreeDB;
+ seqConfig.Creation = CreatePolicy.IF_NEEDED;
+ seqConfig.key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ seqConfig.SetRange(Int64.MinValue, Int64.MaxValue);
+ Sequence seq = new Sequence(seqConfig);
+
+ // Confirm the objects set in SequenceConfig.
+ Assert.AreEqual(dbFileName,
+ seq.BackingDatabase.FileName);
+ Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("key"),
+ seq.Key.Data);
+ Assert.AreEqual(Int64.MinValue, seq.Min);
+ Assert.AreEqual(Int64.MaxValue, seq.Max);
+
+ /* Close sequence, database and environment. */
+ seq.Close();
+ btreeDB.Close();
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ SequenceConfig seqConfig, bool compulsory)
+ {
+ Configuration.ConfirmInt(xmlElement, "CacheSize",
+ seqConfig.CacheSize, compulsory);
+ Configuration.ConfirmCreatePolicy(xmlElement, "Creation",
+ seqConfig.Creation, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Decrement",
+ seqConfig.Decrement, compulsory);
+ Configuration.ConfirmBool(xmlElement, "FreeThreaded",
+ seqConfig.FreeThreaded, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Increment",
+ seqConfig.Increment, compulsory);
+ Configuration.ConfirmLong(xmlElement, "InitialValue",
+ seqConfig.InitialValue, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Wrap",
+ seqConfig.Wrap, compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref SequenceConfig seqConfig, bool compulsory)
+ {
+ int intValue = new int();
+ bool boolValue = new bool();
+ long longValue = new long();
+
+ if (Configuration.ConfigInt(xmlElement, "CacheSize",
+ ref intValue, compulsory))
+ seqConfig.CacheSize = intValue;
+ Configuration.ConfigCreatePolicy(xmlElement, "Creation",
+ ref seqConfig.Creation, compulsory);
+ if (Configuration.ConfigBool(xmlElement, "Decrement",
+ ref boolValue, compulsory))
+ seqConfig.Decrement = boolValue;
+ Configuration.ConfigBool(xmlElement, "FreeThreaded",
+ ref seqConfig.FreeThreaded, compulsory);
+ if (Configuration.ConfigBool(xmlElement, "Increment",
+ ref boolValue, compulsory))
+ seqConfig.Increment = boolValue;
+ if (Configuration.ConfigLong(xmlElement, "InitialValue",
+ ref longValue, compulsory))
+ seqConfig.InitialValue = longValue;
+ Configuration.ConfigBool(xmlElement, "Wrap",
+ ref seqConfig.Wrap, compulsory);
+ }
+ }
+}
diff --git a/test/scr037/SequenceTest.cs b/test/scr037/SequenceTest.cs
new file mode 100644
index 0000000..92f8cc0
--- /dev/null
+++ b/test/scr037/SequenceTest.cs
@@ -0,0 +1,406 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class SequenceTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "SequenceTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ Configuration.ClearDir(testFixtureHome);
+ }
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database.
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(
+ dbFileName, btreeDBConfig);
+
+ // Configure and initialize sequence.
+ SequenceConfig seqConfig = new SequenceConfig();
+ seqConfig.BackingDatabase = btreeDB;
+ seqConfig.Creation = CreatePolicy.IF_NEEDED;
+ seqConfig.key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ seqConfig.SetRange(Int64.MinValue, Int64.MaxValue);
+ SequenceConfigTest.Config(xmlElem, ref seqConfig, true);
+ Sequence seq = new Sequence(seqConfig);
+
+
+ /*
+ * Confirm that the squence is opened with the
+ * configuration that we set.
+ */
+ Confirm(xmlElem, seq, true);
+
+ /* Close sequence, database and environment. */
+ seq.Close();
+ btreeDB.Close();
+ }
+
+ [Test]
+ public void TestClose()
+ {
+ testName = "TestClose";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabase db;
+ Sequence seq;
+ OpenNewSequence(dbFileName, out db, out seq);
+ seq.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestDispose()
+ {
+ testName = "TestDispose";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ BTreeDatabase db;
+ Sequence seq;
+ OpenNewSequence(dbFileName, out db, out seq);
+ seq.Dispose();
+ db.Close();
+ }
+
+ [Test]
+ public void TestGet()
+ {
+ testName = "TestGet";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database and an increase sequence.
+ BTreeDatabase db;
+ Sequence seq;
+ OpenNewSequence(dbFileName, out db, out seq);
+
+ /*
+ * Check the delta of two sequence number get
+ * from sequence.
+ */
+ int delta = 100;
+ long seqNum1 = seq.Get(delta);
+ long seqNum2 = seq.Get(delta);
+ Assert.AreEqual(delta, seqNum2 - seqNum1);
+
+ // Close all.
+ seq.Close();
+ db.Close();
+ }
+
+ [Test]
+ public void TestGetWithNoSync()
+ {
+ testName = "TestGetWithNoSync";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database and an increase sequence.
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ Sequence seq;
+ OpenNewSequenceInEnv(testHome, testName, out env,
+ out db, out seq);
+
+ /*
+ * Check the delta of two sequence number get
+ * from sequence.
+ */
+ int delta = 100;
+ long seqNum1 = seq.Get(delta, true);
+ long seqNum2 = seq.Get(delta, true);
+ Assert.AreEqual(delta, seqNum2 - seqNum1);
+
+ // Close all.
+ seq.Close();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestGetWithinTxn()
+ {
+ testName = "TestGetWithinTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database and an increase sequence.
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ Sequence seq;
+ OpenNewSequenceInEnv(testHome, testName, out env,
+ out db, out seq);
+
+ /*
+ * Check the delta of two sequence number get
+ * from sequence.
+ */
+ int delta = 100;
+ Transaction txn = env.BeginTransaction();
+ long seqNum1 = seq.Get(delta, txn);
+ long seqNum2 = seq.Get(delta, txn);
+ Assert.AreEqual(delta, seqNum2 - seqNum1);
+ txn.Commit();
+
+ // Close all.
+ seq.Close();
+ db.Close();
+ env.Close();
+ }
+
+
+ [Test]
+ public void TestRemove()
+ {
+ testName = "TestRemove";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database and an increase sequence.
+ BTreeDatabase db;
+ Sequence seq;
+ OpenNewSequence(dbFileName, out db, out seq);
+
+ /*
+ * Remove the sequence. The sequence handle can not
+ * be accessed again.
+ */
+ seq.Remove();
+ db.Close();
+ }
+
+ [Test]
+ public void TestRemoveWithNoSync()
+ {
+ testName = "TestRemoveWithNoSync";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database and an increase sequence.
+ DatabaseEnvironmentConfig envConfig = new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseLogging = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, envConfig);
+
+ /* Configure and open sequence's database. */
+ BTreeDatabaseConfig btreeDBConfig = new BTreeDatabaseConfig();
+ btreeDBConfig.AutoCommit = true;
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ btreeDBConfig.Env = env;
+ BTreeDatabase btreeDB = BTreeDatabase.Open(dbFileName, btreeDBConfig);
+
+ /* Configure and initialize sequence. */
+ SequenceConfig seqConfig = new SequenceConfig();
+ seqConfig.BackingDatabase = btreeDB;
+ seqConfig.Creation = CreatePolicy.IF_NEEDED;
+ seqConfig.Increment = true;
+ seqConfig.InitialValue = Int64.MaxValue;
+ seqConfig.key = new DatabaseEntry();
+ seqConfig.SetRange(Int64.MinValue, Int64.MaxValue);
+ seqConfig.Wrap = true;
+ seqConfig.key = new DatabaseEntry();
+ seqConfig.key.Data = ASCIIEncoding.ASCII.GetBytes("ex_csharp_sequence");
+ Sequence seq = new Sequence(seqConfig);
+
+ /*
+ * Remove the sequence. The sequence handle can not
+ * be accessed again.
+ */
+ seq.Remove(true);
+ btreeDB.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestRemoveWithInTxn()
+ {
+ testName = "TestRemoveWithInTxn";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database and an increase sequence.
+ BTreeDatabase db;
+ DatabaseEnvironment env;
+ Sequence seq;
+ OpenNewSequenceInEnv(testHome, testName, out env,
+ out db, out seq);
+
+ //Remove the sequence.
+ Transaction txn = env.BeginTransaction();
+ seq.Remove(txn);
+ txn.Commit();
+ db.Close();
+ env.Close();
+ }
+
+ [Test]
+ public void TestStats()
+ {
+ testName = "TestStats";
+ testHome = testFixtureHome + "/" + testName;
+ string dbFileName = testHome + "/" + testName + ".db";
+
+ Configuration.ClearDir(testHome);
+
+ // Open a database and an increase sequence.
+ BTreeDatabase db;
+ Sequence seq;
+ OpenNewSequence(dbFileName, out db, out seq);
+
+ // Get a value from sequence.
+ seq.Get(100);
+
+ // Get sequence statistics.
+ SequenceStats stats = seq.Stats();
+ seq.PrintStats(true);
+ Assert.AreEqual(200, stats.CachedValue);
+ Assert.AreEqual(1000, stats.CacheSize);
+ Assert.AreNotEqual(0, stats.Flags);
+ Assert.AreEqual(1099, stats.LastCachedValue);
+ Assert.AreEqual(Int64.MaxValue, stats.Max);
+ Assert.AreEqual(Int64.MinValue, stats.Min);
+ Assert.AreEqual(1100, stats.StoredValue);
+
+ stats = seq.Stats(true);
+ seq.PrintStats();
+ stats = seq.Stats();
+ Assert.AreEqual(0, stats.LockNoWait);
+ Assert.AreEqual(0, stats.LockWait);
+
+ seq.Close();
+ db.Close();
+ }
+
+ public void OpenNewSequence(string dbFileName,
+ out BTreeDatabase db, out Sequence seq)
+ {
+ // Open a database.
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ db = BTreeDatabase.Open(dbFileName, btreeDBConfig);
+
+ // Configure and initialize sequence.
+ SequenceConfig seqConfig = new SequenceConfig();
+ seqConfig.BackingDatabase = db;
+ seqConfig.CacheSize = 1000;
+ seqConfig.Creation = CreatePolicy.ALWAYS;
+ seqConfig.Decrement = false;
+ seqConfig.FreeThreaded = true;
+ seqConfig.Increment = true;
+ seqConfig.InitialValue = 100;
+ seqConfig.key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ seqConfig.SetRange(Int64.MinValue, Int64.MaxValue);
+ seqConfig.Wrap = true;
+ seq = new Sequence(seqConfig);
+ }
+
+ public void OpenNewSequenceInEnv(string home, string dbname,
+ out DatabaseEnvironment env, out BTreeDatabase db,
+ out Sequence seq)
+ {
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ envConfig.UseLogging = true;
+ env = DatabaseEnvironment.Open(home, envConfig);
+
+ Transaction openTxn = env.BeginTransaction();
+ BTreeDatabaseConfig dbConfig =
+ new BTreeDatabaseConfig();
+ dbConfig.Creation = CreatePolicy.IF_NEEDED;
+ dbConfig.Env = env;
+ db = BTreeDatabase.Open(dbname + ".db", dbConfig,
+ openTxn);
+ openTxn.Commit();
+
+ Transaction seqTxn = env.BeginTransaction();
+ SequenceConfig seqConfig = new SequenceConfig();
+ seqConfig.BackingDatabase = db;
+ seqConfig.Creation = CreatePolicy.ALWAYS;
+ seqConfig.Decrement = false;
+ seqConfig.FreeThreaded = true;
+ seqConfig.Increment = true;
+ seqConfig.InitialValue = 0;
+ seqConfig.key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ seqConfig.SetRange(Int64.MinValue, Int64.MaxValue);
+ seqConfig.Wrap = true;
+ seq = new Sequence(seqConfig);
+ seqTxn.Commit();
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ Sequence seq, bool compulsory)
+ {
+ Configuration.ConfirmInt(xmlElement, "CacheSize",
+ seq.Cachesize, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Decrement",
+ seq.Decrement, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Increment",
+ seq.Increment, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Wrap",
+ seq.Wrap, compulsory);
+ }
+ }
+}
diff --git a/test/scr037/TestException.cs b/test/scr037/TestException.cs
new file mode 100644
index 0000000..adf6e75
--- /dev/null
+++ b/test/scr037/TestException.cs
@@ -0,0 +1,49 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CsharpAPITest
+{
+
+ public class TestException : ApplicationException
+ {
+ public TestException(string name)
+ : base(name)
+ {
+ }
+
+ public TestException() : base()
+ {
+ }
+ }
+
+ public class ConfigNotFoundException : TestException
+ {
+ public ConfigNotFoundException(string name)
+ : base(name)
+ {
+ }
+ }
+
+ public class InvalidConfigException : TestException
+ {
+ public InvalidConfigException(string name)
+ : base(name)
+ {
+ }
+ }
+
+ public class ExpectedTestException : TestException
+ {
+ public ExpectedTestException()
+ : base()
+ {
+ }
+ }
+}
diff --git a/test/scr037/TransactionConfigTest.cs b/test/scr037/TransactionConfigTest.cs
new file mode 100644
index 0000000..8f84da2
--- /dev/null
+++ b/test/scr037/TransactionConfigTest.cs
@@ -0,0 +1,73 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class TransactionConfigTest
+ {
+ private string testFixtureName;
+ private string testName;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "TransactionConfigTest";
+ }
+
+ [Test]
+ public void TestConfig()
+ {
+ testName = "TestConfig";
+ /*
+ * Configure the fields/properties and see if
+ * they are updated successfully.
+ */
+ TransactionConfig txnConfig = new TransactionConfig();
+ XmlElement xmlElem = Configuration.TestSetUp(
+ testFixtureName, testName);
+ Config(xmlElem, ref txnConfig, true);
+ Confirm(xmlElem, txnConfig, true);
+ }
+
+ public static void Confirm(XmlElement xmlElement,
+ TransactionConfig txnConfig, bool compulsory)
+ {
+ Configuration.ConfirmIsolation(xmlElement,
+ "IsolationDegree", txnConfig.IsolationDegree,
+ compulsory);
+ Configuration.ConfirmBool(xmlElement, "NoWait",
+ txnConfig.NoWait, compulsory);
+ Configuration.ConfirmBool(xmlElement, "Snapshot",
+ txnConfig.Snapshot, compulsory);
+ Configuration.ConfirmLogFlush(xmlElement, "SyncAction",
+ txnConfig.SyncAction, compulsory);
+ }
+
+ public static void Config(XmlElement xmlElement,
+ ref TransactionConfig txnConfig, bool compulsory)
+ {
+ Configuration.ConfigIsolation(xmlElement,
+ "IsolationDegree", ref txnConfig.IsolationDegree,
+ compulsory);
+ Configuration.ConfigBool(xmlElement, "NoWait",
+ ref txnConfig.NoWait, compulsory);
+ Configuration.ConfigBool(xmlElement, "Snapshot",
+ ref txnConfig.Snapshot, compulsory);
+ Configuration.ConfigLogFlush(xmlElement, "SyncAction",
+ ref txnConfig.SyncAction, compulsory);
+ }
+ }
+}
diff --git a/test/scr037/TransactionTest.cs b/test/scr037/TransactionTest.cs
new file mode 100644
index 0000000..23ca34c
--- /dev/null
+++ b/test/scr037/TransactionTest.cs
@@ -0,0 +1,435 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using NUnit.Framework;
+using BerkeleyDB;
+
+namespace CsharpAPITest
+{
+ [TestFixture]
+ public class TransactionTest
+ {
+ private string testFixtureHome;
+ private string testFixtureName;
+ private string testName;
+ private string testHome;
+
+ private DatabaseEnvironment deadLockEnv;
+
+ [TestFixtureSetUp]
+ public void RunBeforeTests()
+ {
+ testFixtureName = "TransactionTest";
+ testFixtureHome = "./TestOut/" + testFixtureName;
+
+ DatabaseEnvironment.Remove(testFixtureHome);
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestAbort()
+ {
+ testName = "TestAbort";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironment env;
+ Transaction txn;
+ BTreeDatabase db;
+
+ /*
+ * Open an environment and begin a transaction. Open
+ * a db and write a record the db within this transaction.
+ */
+ PutRecordWithTxn(out env, testHome, testName, out txn);
+
+ // Abort the transaction.
+ txn.Abort();
+
+ /*
+ * Undo all operations in the transaction so the
+ * database couldn't be reopened.
+ */
+ try
+ {
+ OpenBtreeDBInEnv(testName + ".db", env,
+ out db, false, null);
+ }
+ catch (DatabaseException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ env.Close();
+ }
+ }
+
+ [Test]
+ public void TestCommit()
+ {
+ testName = "TestCommit";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ DatabaseEnvironment env;
+ Transaction txn;
+ BTreeDatabase db;
+
+ /*
+ * Open an environment and begin a transaction. Open
+ * a db and write a record the db within this transaction.
+ */
+ PutRecordWithTxn(out env, testHome, testName, out txn);
+
+ // Commit the transaction.
+ txn.Commit();
+
+ // Reopen the database.
+ OpenBtreeDBInEnv(testName + ".db", env,
+ out db, false, null);
+
+ /*
+ * Confirm that the record("key", "data") exists in the
+ * database.
+ */
+ try
+ {
+ db.GetBoth(new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key")),
+ new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data")));
+ }
+ catch (DatabaseException)
+ {
+ throw new TestException();
+ }
+ finally
+ {
+ db.Close();
+ env.Close();
+ }
+ }
+
+ [Test, ExpectedException(typeof(ExpectedTestException))]
+ public void TestDiscard()
+ {
+ DatabaseEnvironment env;
+ byte[] gid;
+
+ testName = "TestDiscard";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open an environment and begin a transaction
+ * called "transaction". Within the transacion, open a
+ * database, write a record and close it. Then prepare
+ * the transaction and panic the environment.
+ */
+ PanicPreparedTxn(testHome, testName, out env, out gid);
+
+ /*
+ * Recover the environment. Log and db files are not
+ * destoyed so run normal recovery. Recovery should
+ * use DB_CREATE and DB_INIT_TXN flags when
+ * opening the environment.
+ */
+ DatabaseEnvironmentConfig envConfig
+ = new DatabaseEnvironmentConfig();
+ envConfig.RunRecovery = true;
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ env = DatabaseEnvironment.Open(testHome, envConfig);
+
+ PreparedTransaction[] preparedTxns
+ = new PreparedTransaction[10];
+ preparedTxns = env.Recover(10, true);
+
+ Assert.AreEqual(gid, preparedTxns[0].GlobalID);
+ preparedTxns[0].Txn.Discard();
+ try
+ {
+ preparedTxns[0].Txn.Commit();
+ }
+ catch (AccessViolationException)
+ {
+ throw new ExpectedTestException();
+ }
+ finally
+ {
+ env.Close();
+ }
+ }
+
+ [Test]
+ public void TestPrepare()
+ {
+ testName = "TestPrepare";
+ testHome = testFixtureHome + "/" + testName;
+
+ DatabaseEnvironment env;
+ byte[] gid;
+
+ Configuration.ClearDir(testHome);
+
+ /*
+ * Open an environment and begin a transaction
+ * called "transaction". Within the transacion, open a
+ * database, write a record and close it. Then prepare
+ * the transaction and panic the environment.
+ */
+ PanicPreparedTxn(testHome, testName, out env, out gid);
+
+ /*
+ * Recover the environment. Log and db files are not
+ * destoyed so run normal recovery. Recovery should
+ * use DB_CREATE and DB_INIT_TXN flags when
+ * opening the environment.
+ */
+ DatabaseEnvironmentConfig envConfig
+ = new DatabaseEnvironmentConfig();
+ envConfig.RunRecovery = true;
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ env = DatabaseEnvironment.Open(testHome, envConfig);
+
+ // Reopen the database.
+ BTreeDatabase db;
+ OpenBtreeDBInEnv(testName + ".db", env, out db,
+ false, null);
+
+ /*
+ * Confirm that record("key", "data") exists in the
+ * database.
+ */
+ DatabaseEntry key, data;
+ key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ try
+ {
+ db.GetBoth(key, data);
+ }
+ catch (DatabaseException)
+ {
+ throw new TestException();
+ }
+ finally
+ {
+ db.Close();
+ env.Close();
+ }
+
+ }
+
+ public void PanicPreparedTxn(string home, string dbName,
+ out DatabaseEnvironment env, out byte[] globalID)
+ {
+ Transaction txn;
+
+ // Put record into database within transaction.
+ PutRecordWithTxn(out env, home, dbName, out txn);
+
+ /*
+ * Generate global ID for the transaction. Copy
+ * transaction ID to the first 4 tyes in global ID.
+ */
+ globalID = new byte[Transaction.GlobalIdLength];
+ byte[] txnID = new byte[4];
+ txnID = BitConverter.GetBytes(txn.Id);
+ for (int i = 0; i < txnID.Length; i++)
+ globalID[i] = txnID[i];
+
+ // Prepare the transaction.
+ txn.Prepare(globalID);
+
+ // Panic the environment.
+ env.Panic();
+
+ }
+
+ [Test]
+ public void TestTxnName()
+ {
+ DatabaseEnvironment env;
+ Transaction txn;
+
+ testName = "TestTxnName";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ SetUpTransactionalEnv(testHome, out env);
+ txn = env.BeginTransaction();
+ txn.Name = testName;
+ Assert.AreEqual(testName, txn.Name);
+ txn.Commit();
+ env.Close();
+ }
+
+ [Test]
+ public void TestSetLockTimeout()
+ {
+ testName = "TestSetLockTimeout";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Set lock timeout.
+ TestTimeOut(true);
+
+ }
+
+ [Test]
+ public void TestSetTxnTimeout()
+ {
+ testName = "TestSetTxnTimeout";
+ testHome = testFixtureHome + "/" + testName;
+
+ Configuration.ClearDir(testHome);
+
+ // Set transaction time out.
+ TestTimeOut(false);
+
+ }
+
+ /*
+ * ifSetLock is used to indicate which timeout function
+ * is used, SetLockTimeout or SetTxnTimeout.
+ */
+ public void TestTimeOut(bool ifSetLock)
+ {
+ // Open environment and begin transaction.
+ Transaction txn;
+ deadLockEnv = null;
+ SetUpEnvWithTxnAndLocking(testHome,
+ out deadLockEnv, out txn, 0, 0, 0, 0);
+
+ // Define deadlock detection and resolve policy.
+ deadLockEnv.DeadlockResolution =
+ DeadlockPolicy.YOUNGEST;
+ if (ifSetLock == true)
+ txn.SetLockTimeout(10);
+ else
+ txn.SetTxnTimeout(10);
+
+ txn.Commit();
+ deadLockEnv.Close();
+ }
+
+ public static void SetUpEnvWithTxnAndLocking(string envHome,
+ out DatabaseEnvironment env, out Transaction txn,
+ uint maxLock, uint maxLocker, uint maxObject, uint partition)
+ {
+ // Configure env and locking subsystem.
+ LockingConfig lkConfig = new LockingConfig();
+
+ /*
+ * If the maximum number of locks/lockers/objects
+ * is given, then the LockingConfig is set. Unless,
+ * it is not set to any value.
+ */
+ if (maxLock != 0)
+ lkConfig.MaxLocks = maxLock;
+ if (maxLocker != 0)
+ lkConfig.MaxLockers = maxLocker;
+ if (maxObject != 0)
+ lkConfig.MaxObjects = maxObject;
+ if (partition != 0)
+ lkConfig.Partitions = partition;
+
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseTxns = true;
+ envConfig.UseMPool = true;
+ envConfig.LockSystemCfg = lkConfig;
+ envConfig.UseLocking = true;
+ envConfig.NoLocking = false;
+ env = DatabaseEnvironment.Open(envHome, envConfig);
+ txn = env.BeginTransaction();
+ }
+
+ public void PutRecordWithTxn(out DatabaseEnvironment env,
+ string home, string dbName, out Transaction txn)
+ {
+ BTreeDatabase db;
+
+ // Open a new environment and begin a transaction.
+ SetUpTransactionalEnv(home, out env);
+ TransactionConfig txnConfig = new TransactionConfig();
+ txnConfig.Name = "Transaction";
+ txn = env.BeginTransaction(txnConfig);
+ Assert.AreEqual("Transaction", txn.Name);
+
+ // Open a new database within the transaction.
+ OpenBtreeDBInEnv(dbName + ".db", env, out db, true, txn);
+
+ // Write to the database within the transaction.
+ WriteOneIntoBtreeDBWithTxn(db, txn);
+
+ // Close the database.
+ db.Close();
+ }
+
+ public void SetUpTransactionalEnv(string home,
+ out DatabaseEnvironment env)
+ {
+ DatabaseEnvironmentConfig envConfig =
+ new DatabaseEnvironmentConfig();
+ envConfig.Create = true;
+ envConfig.UseLogging = true;
+ envConfig.UseMPool = true;
+ envConfig.UseTxns = true;
+ env = DatabaseEnvironment.Open(
+ home, envConfig);
+ }
+
+ public void OpenBtreeDBInEnv(string dbName,
+ DatabaseEnvironment env, out BTreeDatabase db,
+ bool create, Transaction txn)
+ {
+ BTreeDatabaseConfig btreeDBConfig =
+ new BTreeDatabaseConfig();
+ btreeDBConfig.Env = env;
+ if (create == true)
+ btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
+ else
+ btreeDBConfig.Creation = CreatePolicy.NEVER;
+ if (txn == null)
+ db = BTreeDatabase.Open(dbName,
+ btreeDBConfig);
+ else
+ db = BTreeDatabase.Open(dbName,
+ btreeDBConfig, txn);
+ }
+
+ public void WriteOneIntoBtreeDBWithTxn(BTreeDatabase db,
+ Transaction txn)
+ {
+ DatabaseEntry key, data;
+
+ key = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("key"));
+ data = new DatabaseEntry(
+ ASCIIEncoding.ASCII.GetBytes("data"));
+ db.Put(key, data, txn);
+ }
+ }
+}
diff --git a/test/scr037/XMLReader.cs b/test/scr037/XMLReader.cs
new file mode 100644
index 0000000..6bdaa3e
--- /dev/null
+++ b/test/scr037/XMLReader.cs
@@ -0,0 +1,48 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace CsharpAPITest
+{
+ public class XMLReader
+ {
+ private static string path;
+
+ public XMLReader(string XmlFileName)
+ {
+ path = XmlFileName;
+ }
+
+ public XmlElement GetXmlElement(string className, string testName)
+ {
+ XmlDocument doc = new XmlDocument();
+ doc.Load(path);
+
+ string xpath = string.Format("/Assembly/TestFixture[@name=\"{0}\"]/Test[@name=\"{1}\"]", className, testName);
+ XmlElement testCase = doc.SelectSingleNode(xpath) as XmlElement;
+ if (testCase == null)
+ return null;
+ else
+ return testCase;
+ }
+
+ public static XmlNode GetNode(XmlElement xmlElement,
+ string nodeName)
+ {
+ XmlNodeList xmlNodeList = xmlElement.SelectNodes(nodeName);
+ if (xmlNodeList.Count > 1)
+ throw new Exception(nodeName + " Configuration Error");
+ else
+ return xmlNodeList.Item(0);
+ }
+
+ }
+}
diff --git a/test/scr037/bdb4.7.db b/test/scr037/bdb4.7.db
new file mode 100644
index 0000000..315e94a
--- /dev/null
+++ b/test/scr037/bdb4.7.db
Binary files differ