Annotation of embedaddon/sqlite3/test/tt3_checkpoint.c, revision 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>