diff options
Diffstat (limited to 'test/scr037')
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 Binary files differnew file mode 100644 index 0000000..315e94a --- /dev/null +++ b/test/scr037/bdb4.7.db |