4 ** This file contains tests related to the explicit rollback of database
5 ** transactions and sub-transactions.
10 ** Repeat 2000 times (until the db contains 100,000 entries):
12 ** 1. Open a transaction and insert 500 rows, opening a nested
13 ** sub-transaction each 100 rows.
15 ** 2. Roll back to each sub-transaction savepoint. Check the database
18 ** 3. Every second iteration, roll back the main transaction. Check the
19 ** db checksum is correct. Every other iteration, commit the main
20 ** transaction (increasing the size of the db by 100 rows).
33 CksumDb
*testCksumArrayNew(
45 assert( nLast
>=nFirst
&& ((nLast
-nFirst
)%nStep
)==0 );
47 pRet
= malloc(sizeof(CksumDb
));
48 memset(pRet
, 0, sizeof(CksumDb
));
49 pRet
->nFirst
= nFirst
;
52 nEntry
= 1 + ((nLast
- nFirst
) / nStep
);
54 /* Allocate space so that azCksum is an array of nEntry pointers to
55 ** buffers each TEST_CKSUM_BYTES in size. */
56 pRet
->azCksum
= (char **)malloc(nEntry
* (sizeof(char *) + TEST_CKSUM_BYTES
));
57 for(i
=0; i
<nEntry
; i
++){
58 char *pStart
= (char *)(&pRet
->azCksum
[nEntry
]);
59 pRet
->azCksum
[i
] = &pStart
[i
* TEST_CKSUM_BYTES
];
62 tdb_open("lsm", "tempdb.lsm", 1, &pDb
);
63 testWriteDatasourceRange(pDb
, pData
, 0, nFirst
, &rc
);
64 for(i
=0; i
<nEntry
; i
++){
65 testCksumDatabase(pDb
, pRet
->azCksum
[i
]);
66 if( i
==nEntry
) break;
67 testWriteDatasourceRange(pDb
, pData
, nFirst
+i
*nStep
, nStep
, &rc
);
75 char *testCksumArrayGet(CksumDb
*p
, int nRow
){
77 assert( nRow
>=p
->nFirst
);
78 assert( nRow
<=p
->nLast
);
79 assert( ((nRow
-p
->nFirst
) % p
->nStep
)==0 );
81 i
= (nRow
- p
->nFirst
) / p
->nStep
;
85 void testCksumArrayFree(CksumDb
*p
){
87 memset(p
, 0x55, sizeof(*p
));
91 /* End of CksumDb code.
92 **************************************************************************/
95 ** Test utility function. Write key-value pair $i from datasource pData
98 void testWriteDatasource(TestDb
*pDb
, Datasource
*pData
, int i
, int *pRc
){
100 void *pVal
; int nVal
;
101 testDatasourceEntry(pData
, i
, &pKey
, &nKey
, &pVal
, &nVal
);
102 testWrite(pDb
, pKey
, nKey
, pVal
, nVal
, pRc
);
106 ** Test utility function. Delete datasource pData key $i from database pDb.
108 void testDeleteDatasource(TestDb
*pDb
, Datasource
*pData
, int i
, int *pRc
){
109 void *pKey
; int nKey
;
110 testDatasourceEntry(pData
, i
, &pKey
, &nKey
, 0, 0);
111 testDelete(pDb
, pKey
, nKey
, pRc
);
115 ** This function inserts nWrite key/value pairs into database pDb - the
116 ** nWrite key value pairs starting at iFirst from data source pData.
118 void testWriteDatasourceRange(
119 TestDb
*pDb
, /* Database to write to */
120 Datasource
*pData
, /* Data source to read values from */
121 int iFirst
, /* Index of first key/value pair */
122 int nWrite
, /* Number of key/value pairs to write */
123 int *pRc
/* IN/OUT: Error code */
126 for(i
=0; i
<nWrite
; i
++){
127 testWriteDatasource(pDb
, pData
, iFirst
+i
, pRc
);
131 void testDeleteDatasourceRange(
132 TestDb
*pDb
, /* Database to write to */
133 Datasource
*pData
, /* Data source to read keys from */
134 int iFirst
, /* Index of first key */
135 int nWrite
, /* Number of keys to delete */
136 int *pRc
/* IN/OUT: Error code */
139 for(i
=0; i
<nWrite
; i
++){
140 testDeleteDatasource(pDb
, pData
, iFirst
+i
, pRc
);
144 static char *getName(const char *zSystem
){
146 zRet
= testMallocPrintf("rollback.%s", zSystem
);
150 static int rollback_test_1(
154 const int nRepeat
= 100;
162 zName
= getName(zSystem
);
163 testCaseStart(&rc
, zName
);
166 pCksum
= testCksumArrayNew(pData
, 0, nRepeat
*100, 100);
168 rc
= tdb_open(zSystem
, 0, 1, &pDb
);
169 if( pDb
&& tdb_transaction_support(pDb
)==0 ){
171 goto skip_rollback_test
;
174 for(i
=0; i
<nRepeat
&& rc
==0; i
++){
175 char zCksum
[TEST_CKSUM_BYTES
];
176 int nCurrent
= (((i
+1)/2) * 100);
180 /* Check that the database is the expected size. */
181 nDbRow
= testCountDatabase(pDb
);
182 testCompareInt(nCurrent
, nDbRow
, &rc
);
184 for(iTrans
=2; iTrans
<=6 && rc
==0; iTrans
++){
185 tdb_begin(pDb
, iTrans
);
186 testWriteDatasourceRange(pDb
, pData
, nCurrent
, 100, &rc
);
190 testCksumDatabase(pDb
, zCksum
);
191 testCompareStr(zCksum
, testCksumArrayGet(pCksum
, nCurrent
), &rc
);
193 for(iTrans
=6; iTrans
>2 && rc
==0; iTrans
--){
194 tdb_rollback(pDb
, iTrans
);
196 testCksumDatabase(pDb
, zCksum
);
197 testCompareStr(zCksum
, testCksumArrayGet(pCksum
, nCurrent
), &rc
);
201 tdb_rollback(pDb
, 0);
203 testCksumDatabase(pDb
, zCksum
);
204 testCompareStr(zCksum
, testCksumArrayGet(pCksum
, nCurrent
), &rc
);
213 testCksumArrayFree(pCksum
);
219 const char *zPattern
,
226 char *zName
= getName(zSystem
);
227 bRun
= testGlobMatch(zPattern
, zName
);
232 DatasourceDefn defn
= { TEST_DATASOURCE_RANDOM
, 10, 15, 50, 100 };
233 Datasource
*pData
= testDatasourceNew(&defn
);
234 *pRc
= rollback_test_1(zSystem
, pData
);
235 testDatasourceFree(pData
);