Annotation of embedaddon/sqlite3/test/tt3_checkpoint.c, revision 1.1.1.1

1.1       misho       1: /*
                      2: ** 2001 September 15
                      3: **
                      4: ** The author disclaims copyright to this source code.  In place of
                      5: ** a legal notice, here is a blessing:
                      6: **
                      7: **    May you do good and not evil.
                      8: **    May you find forgiveness for yourself and forgive others.
                      9: **    May you share freely, never taking more than you give.
                     10: **
                     11: *************************************************************************
                     12: ** This file is part of the test program "threadtest3". Despite being a C
                     13: ** file it is not compiled separately, but included by threadtest3.c using
                     14: ** the #include directive normally used with header files.
                     15: **
                     16: ** This file contains the implementation of test cases:
                     17: **
                     18: **     checkpoint_starvation_1
                     19: **     checkpoint_starvation_2
                     20: */
                     21: 
                     22: /*
                     23: ** Both test cases involve 1 writer/checkpointer thread and N reader threads.
                     24: ** 
                     25: ** Each reader thread performs a series of read transactions, one after 
                     26: ** another. Each read transaction lasts for 100 ms.
                     27: **
                     28: ** The writer writes transactions as fast as possible. It uses a callback
                     29: ** registered with sqlite3_wal_hook() to try to keep the WAL-size limited to 
                     30: ** around 50 pages.
                     31: **
                     32: ** In test case checkpoint_starvation_1, the auto-checkpoint uses 
                     33: ** SQLITE_CHECKPOINT_PASSIVE. In checkpoint_starvation_2, it uses RESTART.
                     34: ** The expectation is that in the first case the WAL file will grow very 
                     35: ** large, and in the second will be limited to the 50 pages or thereabouts.
                     36: ** However, the overall transaction throughput will be lower for 
                     37: ** checkpoint_starvation_2, as every checkpoint will block for up to 200 ms
                     38: ** waiting for readers to clear.
                     39: */
                     40: 
                     41: /* Frame limit used by the WAL hook for these tests. */
                     42: #define CHECKPOINT_STARVATION_FRAMELIMIT 50
                     43: 
                     44: /* Duration in ms of each read transaction */
                     45: #define CHECKPOINT_STARVATION_READMS    100
                     46: 
                     47: struct CheckpointStarvationCtx {
                     48:   int eMode;
                     49:   int nMaxFrame;
                     50: };
                     51: typedef struct CheckpointStarvationCtx CheckpointStarvationCtx;
                     52: 
                     53: static int checkpoint_starvation_walhook(
                     54:   void *pCtx, 
                     55:   sqlite3 *db, 
                     56:   const char *zDb, 
                     57:   int nFrame
                     58: ){
                     59:   CheckpointStarvationCtx *p = (CheckpointStarvationCtx *)pCtx;
                     60:   if( nFrame>p->nMaxFrame ){
                     61:     p->nMaxFrame = nFrame;
                     62:   }
                     63:   if( nFrame>=CHECKPOINT_STARVATION_FRAMELIMIT ){
                     64:     sqlite3_wal_checkpoint_v2(db, zDb, p->eMode, 0, 0);
                     65:   }
                     66:   return SQLITE_OK;
                     67: }
                     68: 
                     69: static char *checkpoint_starvation_reader(int iTid, int iArg){
                     70:   Error err = {0};
                     71:   Sqlite db = {0};
                     72: 
                     73:   opendb(&err, &db, "test.db", 0);
                     74:   while( !timetostop(&err) ){
                     75:     i64 iCount1, iCount2;
                     76:     sql_script(&err, &db, "BEGIN");
                     77:     iCount1 = execsql_i64(&err, &db, "SELECT count(x) FROM t1");
                     78:     usleep(CHECKPOINT_STARVATION_READMS*1000);
                     79:     iCount2 = execsql_i64(&err, &db, "SELECT count(x) FROM t1");
                     80:     sql_script(&err, &db, "COMMIT");
                     81: 
                     82:     if( iCount1!=iCount2 ){
                     83:       test_error(&err, "Isolation failure - %lld %lld", iCount1, iCount2);
                     84:     }
                     85:   }
                     86:   closedb(&err, &db);
                     87: 
                     88:   print_and_free_err(&err);
                     89:   return 0;
                     90: }
                     91: 
                     92: static void checkpoint_starvation_main(int nMs, CheckpointStarvationCtx *p){
                     93:   Error err = {0};
                     94:   Sqlite db = {0};
                     95:   Threadset threads = {0};
                     96:   int nInsert = 0;
                     97:   int i;
                     98: 
                     99:   opendb(&err, &db, "test.db", 1);
                    100:   sql_script(&err, &db, 
                    101:       "PRAGMA page_size = 1024;"
                    102:       "PRAGMA journal_mode = WAL;"
                    103:       "CREATE TABLE t1(x);"
                    104:   );
                    105: 
                    106:   setstoptime(&err, nMs);
                    107: 
                    108:   for(i=0; i<4; i++){
                    109:     launch_thread(&err, &threads, checkpoint_starvation_reader, 0);
                    110:     usleep(CHECKPOINT_STARVATION_READMS*1000/4);
                    111:   }
                    112: 
                    113:   sqlite3_wal_hook(db.db, checkpoint_starvation_walhook, (void *)p);
                    114:   while( !timetostop(&err) ){
                    115:     sql_script(&err, &db, "INSERT INTO t1 VALUES(randomblob(1200))");
                    116:     nInsert++;
                    117:   }
                    118: 
                    119:   printf(" Checkpoint mode  : %s\n",
                    120:       p->eMode==SQLITE_CHECKPOINT_PASSIVE ? "PASSIVE" : "RESTART"
                    121:   );
                    122:   printf(" Peak WAL         : %d frames\n", p->nMaxFrame);
                    123:   printf(" Transaction count: %d transactions\n", nInsert);
                    124: 
                    125:   join_all_threads(&err, &threads);
                    126:   closedb(&err, &db);
                    127:   print_and_free_err(&err);
                    128: }
                    129: 
                    130: static void checkpoint_starvation_1(int nMs){
                    131:   Error err = {0};
                    132:   CheckpointStarvationCtx ctx = { SQLITE_CHECKPOINT_PASSIVE, 0 };
                    133:   checkpoint_starvation_main(nMs, &ctx);
                    134:   if( ctx.nMaxFrame<(CHECKPOINT_STARVATION_FRAMELIMIT*10) ){
                    135:     test_error(&err, "WAL failed to grow - %d frames", ctx.nMaxFrame);
                    136:   }
                    137:   print_and_free_err(&err);
                    138: }
                    139: 
                    140: static void checkpoint_starvation_2(int nMs){
                    141:   Error err = {0};
                    142:   CheckpointStarvationCtx ctx = { SQLITE_CHECKPOINT_RESTART, 0 };
                    143:   checkpoint_starvation_main(nMs, &ctx);
                    144:   if( ctx.nMaxFrame>CHECKPOINT_STARVATION_FRAMELIMIT+10 ){
                    145:     test_error(&err, "WAL grew too large - %d frames", ctx.nMaxFrame);
                    146:   }
                    147:   print_and_free_err(&err);
                    148: }
                    149: 
                    150: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>