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>