OLD | NEW |
(Empty) | |
| 1 /* |
| 2 ** 2014 December 9 |
| 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 ** |
| 13 ** |
| 14 */ |
| 15 |
| 16 |
| 17 /* |
| 18 ** Thread 1. CREATE and DROP a table. |
| 19 */ |
| 20 static char *stress_thread_1(int iTid, void *pArg){ |
| 21 Error err = {0}; /* Error code and message */ |
| 22 Sqlite db = {0}; /* SQLite database connection */ |
| 23 |
| 24 opendb(&err, &db, "test.db", 0); |
| 25 while( !timetostop(&err) ){ |
| 26 sql_script(&err, &db, "CREATE TABLE IF NOT EXISTS t1(a PRIMARY KEY, b)"); |
| 27 clear_error(&err, SQLITE_LOCKED); |
| 28 sql_script(&err, &db, "DROP TABLE IF EXISTS t1"); |
| 29 clear_error(&err, SQLITE_LOCKED); |
| 30 } |
| 31 closedb(&err, &db); |
| 32 print_and_free_err(&err); |
| 33 return sqlite3_mprintf("ok"); |
| 34 } |
| 35 |
| 36 /* |
| 37 ** Thread 2. Open and close database connections. |
| 38 */ |
| 39 static char *stress_thread_2(int iTid, void *pArg){ |
| 40 Error err = {0}; /* Error code and message */ |
| 41 Sqlite db = {0}; /* SQLite database connection */ |
| 42 while( !timetostop(&err) ){ |
| 43 opendb(&err, &db, "test.db", 0); |
| 44 sql_script(&err, &db, "SELECT * FROM sqlite_master;"); |
| 45 clear_error(&err, SQLITE_LOCKED); |
| 46 closedb(&err, &db); |
| 47 } |
| 48 print_and_free_err(&err); |
| 49 return sqlite3_mprintf("ok"); |
| 50 } |
| 51 |
| 52 /* |
| 53 ** Thread 3. Attempt many small SELECT statements. |
| 54 */ |
| 55 static char *stress_thread_3(int iTid, void *pArg){ |
| 56 Error err = {0}; /* Error code and message */ |
| 57 Sqlite db = {0}; /* SQLite database connection */ |
| 58 |
| 59 int i1 = 0; |
| 60 int i2 = 0; |
| 61 |
| 62 opendb(&err, &db, "test.db", 0); |
| 63 while( !timetostop(&err) ){ |
| 64 sql_script(&err, &db, "SELECT * FROM t1 ORDER BY a;"); |
| 65 i1++; |
| 66 if( err.rc ) i2++; |
| 67 clear_error(&err, SQLITE_LOCKED); |
| 68 clear_error(&err, SQLITE_ERROR); |
| 69 } |
| 70 closedb(&err, &db); |
| 71 print_and_free_err(&err); |
| 72 return sqlite3_mprintf("read t1 %d/%d attempts", i2, i1); |
| 73 } |
| 74 |
| 75 /* |
| 76 ** Thread 5. Attempt INSERT statements. |
| 77 */ |
| 78 static char *stress_thread_4(int iTid, void *pArg){ |
| 79 Error err = {0}; /* Error code and message */ |
| 80 Sqlite db = {0}; /* SQLite database connection */ |
| 81 int i1 = 0; |
| 82 int i2 = 0; |
| 83 int iArg = PTR2INT(pArg); |
| 84 |
| 85 opendb(&err, &db, "test.db", 0); |
| 86 while( !timetostop(&err) ){ |
| 87 if( iArg ){ |
| 88 closedb(&err, &db); |
| 89 opendb(&err, &db, "test.db", 0); |
| 90 } |
| 91 sql_script(&err, &db, |
| 92 "WITH loop(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM loop LIMIT 200) " |
| 93 "INSERT INTO t1 VALUES(randomblob(60), randomblob(60));" |
| 94 ); |
| 95 i1++; |
| 96 if( err.rc ) i2++; |
| 97 clear_error(&err, SQLITE_LOCKED); |
| 98 clear_error(&err, SQLITE_ERROR); |
| 99 } |
| 100 closedb(&err, &db); |
| 101 print_and_free_err(&err); |
| 102 return sqlite3_mprintf("wrote t1 %d/%d attempts", i2, i1); |
| 103 } |
| 104 |
| 105 /* |
| 106 ** Thread 6. Attempt DELETE operations. |
| 107 */ |
| 108 static char *stress_thread_5(int iTid, void *pArg){ |
| 109 Error err = {0}; /* Error code and message */ |
| 110 Sqlite db = {0}; /* SQLite database connection */ |
| 111 int iArg = PTR2INT(pArg); |
| 112 |
| 113 int i1 = 0; |
| 114 int i2 = 0; |
| 115 |
| 116 opendb(&err, &db, "test.db", 0); |
| 117 while( !timetostop(&err) ){ |
| 118 i64 i = (i1 % 4); |
| 119 if( iArg ){ |
| 120 closedb(&err, &db); |
| 121 opendb(&err, &db, "test.db", 0); |
| 122 } |
| 123 execsql(&err, &db, "DELETE FROM t1 WHERE (rowid % 4)==:i", &i); |
| 124 i1++; |
| 125 if( err.rc ) i2++; |
| 126 clear_error(&err, SQLITE_LOCKED); |
| 127 } |
| 128 closedb(&err, &db); |
| 129 print_and_free_err(&err); |
| 130 return sqlite3_mprintf("deleted from t1 %d/%d attempts", i2, i1); |
| 131 } |
| 132 |
| 133 |
| 134 static void stress1(int nMs){ |
| 135 Error err = {0}; |
| 136 Threadset threads = {0}; |
| 137 |
| 138 setstoptime(&err, nMs); |
| 139 sqlite3_enable_shared_cache(1); |
| 140 |
| 141 launch_thread(&err, &threads, stress_thread_1, 0); |
| 142 launch_thread(&err, &threads, stress_thread_1, 0); |
| 143 |
| 144 launch_thread(&err, &threads, stress_thread_2, 0); |
| 145 launch_thread(&err, &threads, stress_thread_2, 0); |
| 146 |
| 147 launch_thread(&err, &threads, stress_thread_3, 0); |
| 148 launch_thread(&err, &threads, stress_thread_3, 0); |
| 149 |
| 150 launch_thread(&err, &threads, stress_thread_4, 0); |
| 151 launch_thread(&err, &threads, stress_thread_4, 0); |
| 152 |
| 153 launch_thread(&err, &threads, stress_thread_5, 0); |
| 154 launch_thread(&err, &threads, stress_thread_5, (void*)1); |
| 155 |
| 156 join_all_threads(&err, &threads); |
| 157 sqlite3_enable_shared_cache(0); |
| 158 |
| 159 print_and_free_err(&err); |
| 160 } |
| 161 |
| 162 /************************************************************************** |
| 163 *************************************************************************** |
| 164 ** Start of test case "stress2" |
| 165 */ |
| 166 |
| 167 |
| 168 |
| 169 /* |
| 170 ** 1. CREATE TABLE statements. |
| 171 ** 2. DROP TABLE statements. |
| 172 ** 3. Small SELECT statements. |
| 173 ** 4. Big SELECT statements. |
| 174 ** 5. Small INSERT statements. |
| 175 ** 6. Big INSERT statements. |
| 176 ** 7. Small UPDATE statements. |
| 177 ** 8. Big UPDATE statements. |
| 178 ** 9. Small DELETE statements. |
| 179 ** 10. Big DELETE statements. |
| 180 ** 11. VACUUM. |
| 181 ** 14. Integrity-check. |
| 182 ** 17. Switch the journal mode from delete to wal and back again. |
| 183 ** 19. Open and close database connections rapidly. |
| 184 */ |
| 185 |
| 186 #define STRESS2_TABCNT 5 /* count1 in SDS test */ |
| 187 |
| 188 #define STRESS2_COUNT2 200 /* count2 in SDS test */ |
| 189 #define STRESS2_COUNT3 57 /* count2 in SDS test */ |
| 190 |
| 191 static void stress2_workload1(Error *pErr, Sqlite *pDb, int i){ |
| 192 int iTab = (i % (STRESS2_TABCNT-1)) + 1; |
| 193 sql_script_printf(pErr, pDb, |
| 194 "CREATE TABLE IF NOT EXISTS t%d(x PRIMARY KEY, y, z);", iTab |
| 195 ); |
| 196 } |
| 197 |
| 198 static void stress2_workload2(Error *pErr, Sqlite *pDb, int i){ |
| 199 int iTab = (i % (STRESS2_TABCNT-1)) + 1; |
| 200 sql_script_printf(pErr, pDb, "DROP TABLE IF EXISTS t%d;", iTab); |
| 201 } |
| 202 |
| 203 static void stress2_workload3(Error *pErr, Sqlite *pDb, int i){ |
| 204 sql_script(pErr, pDb, "SELECT * FROM t0 WHERE z = 'small'"); |
| 205 } |
| 206 |
| 207 static void stress2_workload4(Error *pErr, Sqlite *pDb, int i){ |
| 208 sql_script(pErr, pDb, "SELECT * FROM t0 WHERE z = 'big'"); |
| 209 } |
| 210 |
| 211 static void stress2_workload5(Error *pErr, Sqlite *pDb, int i){ |
| 212 sql_script(pErr, pDb, |
| 213 "INSERT INTO t0 VALUES(hex(random()), hex(randomblob(200)), 'small');" |
| 214 ); |
| 215 } |
| 216 |
| 217 static void stress2_workload6(Error *pErr, Sqlite *pDb, int i){ |
| 218 sql_script(pErr, pDb, |
| 219 "INSERT INTO t0 VALUES(hex(random()), hex(randomblob(57)), 'big');" |
| 220 ); |
| 221 } |
| 222 |
| 223 static void stress2_workload7(Error *pErr, Sqlite *pDb, int i){ |
| 224 sql_script_printf(pErr, pDb, |
| 225 "UPDATE t0 SET y = hex(randomblob(200)) " |
| 226 "WHERE x LIKE hex((%d %% 5)) AND z='small';" |
| 227 ,i |
| 228 ); |
| 229 } |
| 230 static void stress2_workload8(Error *pErr, Sqlite *pDb, int i){ |
| 231 sql_script_printf(pErr, pDb, |
| 232 "UPDATE t0 SET y = hex(randomblob(57)) " |
| 233 "WHERE x LIKE hex(%d %% 5) AND z='big';" |
| 234 ,i |
| 235 ); |
| 236 } |
| 237 |
| 238 static void stress2_workload9(Error *pErr, Sqlite *pDb, int i){ |
| 239 sql_script_printf(pErr, pDb, |
| 240 "DELETE FROM t0 WHERE x LIKE hex(%d %% 5) AND z='small';", i |
| 241 ); |
| 242 } |
| 243 static void stress2_workload10(Error *pErr, Sqlite *pDb, int i){ |
| 244 sql_script_printf(pErr, pDb, |
| 245 "DELETE FROM t0 WHERE x LIKE hex(%d %% 5) AND z='big';", i |
| 246 ); |
| 247 } |
| 248 |
| 249 static void stress2_workload11(Error *pErr, Sqlite *pDb, int i){ |
| 250 sql_script(pErr, pDb, "VACUUM"); |
| 251 } |
| 252 |
| 253 static void stress2_workload14(Error *pErr, Sqlite *pDb, int i){ |
| 254 sql_script(pErr, pDb, "PRAGMA integrity_check"); |
| 255 } |
| 256 |
| 257 static void stress2_workload17(Error *pErr, Sqlite *pDb, int i){ |
| 258 sql_script_printf(pErr, pDb, |
| 259 "PRAGMA journal_mode = %q", (i%2) ? "delete" : "wal" |
| 260 ); |
| 261 } |
| 262 |
| 263 static char *stress2_workload19(int iTid, void *pArg){ |
| 264 Error err = {0}; /* Error code and message */ |
| 265 Sqlite db = {0}; /* SQLite database connection */ |
| 266 const char *zDb = (const char*)pArg; |
| 267 while( !timetostop(&err) ){ |
| 268 opendb(&err, &db, zDb, 0); |
| 269 sql_script(&err, &db, "SELECT * FROM sqlite_master;"); |
| 270 clear_error(&err, SQLITE_LOCKED); |
| 271 closedb(&err, &db); |
| 272 } |
| 273 print_and_free_err(&err); |
| 274 return sqlite3_mprintf("ok"); |
| 275 } |
| 276 |
| 277 |
| 278 typedef struct Stress2Ctx Stress2Ctx; |
| 279 struct Stress2Ctx { |
| 280 const char *zDb; |
| 281 void (*xProc)(Error*, Sqlite*, int); |
| 282 }; |
| 283 |
| 284 static char *stress2_thread_wrapper(int iTid, void *pArg){ |
| 285 Stress2Ctx *pCtx = (Stress2Ctx*)pArg; |
| 286 Error err = {0}; /* Error code and message */ |
| 287 Sqlite db = {0}; /* SQLite database connection */ |
| 288 int i1 = 0; |
| 289 int i2 = 0; |
| 290 |
| 291 while( !timetostop(&err) ){ |
| 292 int cnt; |
| 293 opendb(&err, &db, pCtx->zDb, 0); |
| 294 for(cnt=0; err.rc==SQLITE_OK && cnt<STRESS2_TABCNT; cnt++){ |
| 295 pCtx->xProc(&err, &db, i1); |
| 296 i2 += (err.rc==SQLITE_OK); |
| 297 clear_error(&err, SQLITE_LOCKED); |
| 298 i1++; |
| 299 } |
| 300 closedb(&err, &db); |
| 301 } |
| 302 |
| 303 print_and_free_err(&err); |
| 304 return sqlite3_mprintf("ok %d/%d", i2, i1); |
| 305 } |
| 306 |
| 307 static void stress2_launch_thread_loop( |
| 308 Error *pErr, /* IN/OUT: Error code */ |
| 309 Threadset *pThreads, /* Thread set */ |
| 310 const char *zDb, /* Database name */ |
| 311 void (*x)(Error*,Sqlite*,int) /* Run this until error or timeout */ |
| 312 ){ |
| 313 Stress2Ctx *pCtx = sqlite3_malloc(sizeof(Stress2Ctx)); |
| 314 pCtx->zDb = zDb; |
| 315 pCtx->xProc = x; |
| 316 launch_thread(pErr, pThreads, stress2_thread_wrapper, (void*)pCtx); |
| 317 } |
| 318 |
| 319 static void stress2(int nMs){ |
| 320 struct Stress2Task { |
| 321 void (*x)(Error*,Sqlite*,int); |
| 322 } aTask[] = { |
| 323 { stress2_workload1 }, |
| 324 { stress2_workload2 }, |
| 325 { stress2_workload3 }, |
| 326 { stress2_workload4 }, |
| 327 { stress2_workload5 }, |
| 328 { stress2_workload6 }, |
| 329 { stress2_workload7 }, |
| 330 { stress2_workload8 }, |
| 331 { stress2_workload9 }, |
| 332 { stress2_workload10 }, |
| 333 { stress2_workload11 }, |
| 334 { stress2_workload14 }, |
| 335 { stress2_workload17 }, |
| 336 }; |
| 337 const char *zDb = "test.db"; |
| 338 |
| 339 int i; |
| 340 Error err = {0}; |
| 341 Sqlite db = {0}; |
| 342 Threadset threads = {0}; |
| 343 |
| 344 /* To make sure the db file is empty before commencing */ |
| 345 opendb(&err, &db, zDb, 1); |
| 346 sql_script(&err, &db, |
| 347 "CREATE TABLE IF NOT EXISTS t0(x PRIMARY KEY, y, z);" |
| 348 "CREATE INDEX IF NOT EXISTS i0 ON t0(y);" |
| 349 ); |
| 350 closedb(&err, &db); |
| 351 |
| 352 setstoptime(&err, nMs); |
| 353 sqlite3_enable_shared_cache(1); |
| 354 |
| 355 for(i=0; i<sizeof(aTask)/sizeof(aTask[0]); i++){ |
| 356 stress2_launch_thread_loop(&err, &threads, zDb, aTask[i].x); |
| 357 } |
| 358 launch_thread(&err, &threads, stress2_workload19, (void*)zDb); |
| 359 launch_thread(&err, &threads, stress2_workload19, (void*)zDb); |
| 360 |
| 361 join_all_threads(&err, &threads); |
| 362 sqlite3_enable_shared_cache(0); |
| 363 print_and_free_err(&err); |
| 364 } |
| 365 |
| 366 |
| 367 |
| 368 |
OLD | NEW |