File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / test / tt3_checkpoint.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:16 2012 UTC (12 years, 4 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    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>