xref: /sqlite-3.40.0/ext/lsm1/lsm-test/lsmtest4.c (revision 38d69855)
1 
2 /*
3 ** This file contains test cases involving multiple database clients.
4 */
5 
6 #include "lsmtest.h"
7 
8 /*
9 ** The following code implements test cases "mc1.*".
10 **
11 ** This test case uses one writer and $nReader readers. All connections
12 ** are driven by a single thread. All connections are opened at the start
13 ** of the test and remain open until the test is finished.
14 **
15 ** The test consists of $nStep steps. Each step the following is performed:
16 **
17 **   1. The writer inserts $nWriteStep records into the db.
18 **
19 **   2. The writer checks that the contents of the db are as expected.
20 **
21 **   3. Each reader that currently has an open read transaction also checks
22 **      that the contents of the db are as expected (according to the snapshot
23 **      the read transaction is reading - see below).
24 **
25 ** After step 1, reader 1 opens a read transaction. After step 2, reader
26 ** 2 opens a read transaction, and so on. At step ($nReader+1), reader 1
27 ** closes the current read transaction and opens a new one. And so on.
28 ** The result is that at step N (for N > $nReader), there exists a reader
29 ** with an open read transaction reading the snapshot committed following
30 ** steps (N-$nReader-1) to N.
31 */
32 typedef struct Mctest Mctest;
33 struct Mctest {
34   DatasourceDefn defn;            /* Datasource to use */
35   int nStep;                      /* Total number of steps in test */
36   int nWriteStep;                 /* Number of rows to insert each step */
37   int nReader;                    /* Number of read connections */
38 };
do_mc_test(const char * zSystem,Mctest * pTest,int * pRc)39 static void do_mc_test(
40   const char *zSystem,            /* Database system to test */
41   Mctest *pTest,
42   int *pRc                        /* IN/OUT: return code */
43 ){
44   const int nDomain = pTest->nStep * pTest->nWriteStep;
45   Datasource *pData;              /* Source of data */
46   TestDb *pDb;                    /* First database connection (writer) */
47   int iReader;                    /* Used to iterate through aReader */
48   int iStep;                      /* Current step in test */
49   int iDot = 0;                   /* Current step in test */
50 
51   /* Array of reader connections */
52   struct Reader {
53     TestDb *pDb;                  /* Connection handle */
54     int iLast;                    /* Current snapshot contains keys 0..iLast */
55   } *aReader;
56 
57   /* Create a data source */
58   pData = testDatasourceNew(&pTest->defn);
59 
60   /* Open the writer connection */
61   pDb = testOpen(zSystem, 1, pRc);
62 
63   /* Allocate aReader */
64   aReader = (struct Reader *)testMalloc(sizeof(aReader[0]) * pTest->nReader);
65   for(iReader=0; iReader<pTest->nReader; iReader++){
66     aReader[iReader].pDb = testOpen(zSystem, 0, pRc);
67   }
68 
69   for(iStep=0; iStep<pTest->nStep; iStep++){
70     int iLast;
71     int iBegin;                   /* Start read trans using aReader[iBegin] */
72 
73     /* Insert nWriteStep more records into the database */
74     int iFirst = iStep*pTest->nWriteStep;
75     testWriteDatasourceRange(pDb, pData, iFirst, pTest->nWriteStep, pRc);
76 
77     /* Check that the db is Ok according to the writer */
78     iLast = (iStep+1) * pTest->nWriteStep - 1;
79     testDbContents(pDb, pData, nDomain, 0, iLast, iLast, 1, pRc);
80 
81     /* Have reader (iStep % nReader) open a read transaction here. */
82     iBegin = (iStep % pTest->nReader);
83     if( iBegin<iStep ) tdb_commit(aReader[iBegin].pDb, 0);
84     tdb_begin(aReader[iBegin].pDb, 1);
85     aReader[iBegin].iLast = iLast;
86 
87     /* Check that the db is Ok for each open reader */
88     for(iReader=0; iReader<pTest->nReader && aReader[iReader].iLast; iReader++){
89       iLast = aReader[iReader].iLast;
90       testDbContents(
91           aReader[iReader].pDb, pData, nDomain, 0, iLast, iLast, 1, pRc
92       );
93     }
94 
95     /* Report progress */
96     testCaseProgress(iStep, pTest->nStep, testCaseNDot(), &iDot);
97   }
98 
99   /* Close all readers */
100   for(iReader=0; iReader<pTest->nReader; iReader++){
101     testClose(&aReader[iReader].pDb);
102   }
103   testFree(aReader);
104 
105   /* Close the writer-connection and free the datasource */
106   testClose(&pDb);
107   testDatasourceFree(pData);
108 }
109 
110 
test_mc(const char * zSystem,const char * zPattern,int * pRc)111 void test_mc(
112   const char *zSystem,            /* Database system name */
113   const char *zPattern,           /* Run test cases that match this pattern */
114   int *pRc                        /* IN/OUT: Error code */
115 ){
116   int i;
117   Mctest aTest[] = {
118     { { TEST_DATASOURCE_RANDOM, 10,10, 100,100 }, 100, 10, 5 },
119   };
120 
121   for(i=0; i<ArraySize(aTest); i++){
122     if( testCaseBegin(pRc, zPattern, "mc1.%s.%d", zSystem, i) ){
123       do_mc_test(zSystem, &aTest[i], pRc);
124       testCaseFinish(*pRc);
125     }
126   }
127 }
128