modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/lsm1/lsm-test/lsmtest3.c (about)

     1  
     2  
     3  /*
     4  ** This file contains tests related to the explicit rollback of database
     5  ** transactions and sub-transactions.
     6  */
     7  
     8  
     9  /*
    10  ** Repeat 2000 times (until the db contains 100,000 entries):
    11  **
    12  **   1. Open a transaction and insert 500 rows, opening a nested 
    13  **      sub-transaction each 100 rows.
    14  **
    15  **   2. Roll back to each sub-transaction savepoint. Check the database
    16  **      checksum looks Ok.
    17  **
    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).
    21  */
    22  
    23  
    24  #include "lsmtest.h"
    25  
    26  struct CksumDb {
    27    int nFirst;
    28    int nLast;
    29    int nStep;
    30    char **azCksum;
    31  };
    32  
    33  CksumDb *testCksumArrayNew(
    34    Datasource *pData, 
    35    int nFirst, 
    36    int nLast, 
    37    int nStep
    38  ){
    39    TestDb *pDb;
    40    CksumDb *pRet;
    41    int i;
    42    int nEntry;
    43    int rc = 0;
    44  
    45    assert( nLast>=nFirst && ((nLast-nFirst)%nStep)==0 );
    46   
    47    pRet = malloc(sizeof(CksumDb));
    48    memset(pRet, 0, sizeof(CksumDb));
    49    pRet->nFirst = nFirst;
    50    pRet->nLast = nLast;
    51    pRet->nStep = nStep;
    52    nEntry = 1 + ((nLast - nFirst) / nStep);
    53  
    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];
    60    }
    61  
    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);
    68    }
    69  
    70    tdb_close(pDb);
    71  
    72    return pRet;
    73  }
    74  
    75  char *testCksumArrayGet(CksumDb *p, int nRow){
    76    int i;
    77    assert( nRow>=p->nFirst );
    78    assert( nRow<=p->nLast );
    79    assert( ((nRow-p->nFirst) % p->nStep)==0 );
    80  
    81    i = (nRow - p->nFirst) / p->nStep;
    82    return p->azCksum[i];
    83  }
    84  
    85  void testCksumArrayFree(CksumDb *p){
    86    free(p->azCksum);
    87    memset(p, 0x55, sizeof(*p));
    88    free(p);
    89  }
    90  
    91  /* End of CksumDb code.
    92  **************************************************************************/
    93  
    94  /*
    95  ** Test utility function. Write key-value pair $i from datasource pData 
    96  ** into database pDb.
    97  */
    98  void testWriteDatasource(TestDb *pDb, Datasource *pData, int i, int *pRc){
    99    void *pKey; int nKey;
   100    void *pVal; int nVal;
   101    testDatasourceEntry(pData, i, &pKey, &nKey, &pVal, &nVal);
   102    testWrite(pDb, pKey, nKey, pVal, nVal, pRc);
   103  }
   104  
   105  /*
   106  ** Test utility function. Delete datasource pData key $i from database pDb.
   107  */
   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);
   112  }
   113  
   114  /*
   115  ** This function inserts nWrite key/value pairs into database pDb - the
   116  ** nWrite key value pairs starting at iFirst from data source pData.
   117  */
   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 */
   124  ){
   125    int i;
   126    for(i=0; i<nWrite; i++){
   127      testWriteDatasource(pDb, pData, iFirst+i, pRc);
   128    }
   129  }
   130  
   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 */
   137  ){
   138    int i;
   139    for(i=0; i<nWrite; i++){
   140      testDeleteDatasource(pDb, pData, iFirst+i, pRc);
   141    }
   142  }
   143  
   144  static char *getName(const char *zSystem){ 
   145    char *zRet; 
   146    zRet = testMallocPrintf("rollback.%s", zSystem);
   147    return zRet;
   148  }
   149  
   150  static int rollback_test_1(
   151    const char *zSystem,
   152    Datasource *pData
   153  ){
   154    const int nRepeat = 100;
   155  
   156    TestDb *pDb;
   157    int rc;
   158    int i;
   159    CksumDb *pCksum;
   160    char *zName;
   161  
   162    zName = getName(zSystem);
   163    testCaseStart(&rc, zName);
   164    testFree(zName);
   165  
   166    pCksum = testCksumArrayNew(pData, 0, nRepeat*100, 100);
   167    pDb = 0;
   168    rc = tdb_open(zSystem, 0, 1, &pDb);
   169    if( pDb && tdb_transaction_support(pDb)==0 ){
   170      testCaseSkip();
   171      goto skip_rollback_test;
   172    }
   173  
   174    for(i=0; i<nRepeat && rc==0; i++){
   175      char zCksum[TEST_CKSUM_BYTES];
   176      int nCurrent = (((i+1)/2) * 100);
   177      int nDbRow;
   178      int iTrans;
   179  
   180      /* Check that the database is the expected size. */
   181      nDbRow = testCountDatabase(pDb);
   182      testCompareInt(nCurrent, nDbRow, &rc);
   183  
   184      for(iTrans=2; iTrans<=6 && rc==0; iTrans++){
   185        tdb_begin(pDb, iTrans);
   186        testWriteDatasourceRange(pDb, pData, nCurrent, 100, &rc);
   187        nCurrent += 100;
   188      }
   189  
   190      testCksumDatabase(pDb, zCksum);
   191      testCompareStr(zCksum, testCksumArrayGet(pCksum, nCurrent), &rc);
   192  
   193      for(iTrans=6; iTrans>2 && rc==0; iTrans--){
   194        tdb_rollback(pDb, iTrans);
   195        nCurrent -= 100;
   196        testCksumDatabase(pDb, zCksum);
   197        testCompareStr(zCksum, testCksumArrayGet(pCksum, nCurrent), &rc);
   198      }
   199  
   200      if( i%2 ){
   201        tdb_rollback(pDb, 0);
   202        nCurrent -= 100;
   203        testCksumDatabase(pDb, zCksum);
   204        testCompareStr(zCksum, testCksumArrayGet(pCksum, nCurrent), &rc);
   205      }else{
   206        tdb_commit(pDb, 0);
   207      }
   208    }
   209    testCaseFinish(rc);
   210  
   211   skip_rollback_test:
   212    tdb_close(pDb);
   213    testCksumArrayFree(pCksum);
   214    return rc;
   215  }
   216  
   217  void test_rollback(
   218    const char *zSystem, 
   219    const char *zPattern, 
   220    int *pRc
   221  ){
   222    if( *pRc==0 ){
   223      int bRun = 1;
   224  
   225      if( zPattern ){
   226        char *zName = getName(zSystem);
   227        bRun = testGlobMatch(zPattern, zName);
   228        testFree(zName);
   229      }
   230  
   231      if( bRun ){
   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);
   236      }
   237    }
   238  }