Index: third_party/sqlite/sqlite-src-3170000/test/tt3_stress.c |
diff --git a/third_party/sqlite/sqlite-src-3170000/test/tt3_stress.c b/third_party/sqlite/sqlite-src-3170000/test/tt3_stress.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..cdfab9c09ccc93add56840271bcd9c8b8ac25ed5 |
--- /dev/null |
+++ b/third_party/sqlite/sqlite-src-3170000/test/tt3_stress.c |
@@ -0,0 +1,368 @@ |
+/* |
+** 2014 December 9 |
+** |
+** The author disclaims copyright to this source code. In place of |
+** a legal notice, here is a blessing: |
+** |
+** May you do good and not evil. |
+** May you find forgiveness for yourself and forgive others. |
+** May you share freely, never taking more than you give. |
+** |
+************************************************************************* |
+** |
+** |
+*/ |
+ |
+ |
+/* |
+** Thread 1. CREATE and DROP a table. |
+*/ |
+static char *stress_thread_1(int iTid, void *pArg){ |
+ Error err = {0}; /* Error code and message */ |
+ Sqlite db = {0}; /* SQLite database connection */ |
+ |
+ opendb(&err, &db, "test.db", 0); |
+ while( !timetostop(&err) ){ |
+ sql_script(&err, &db, "CREATE TABLE IF NOT EXISTS t1(a PRIMARY KEY, b)"); |
+ clear_error(&err, SQLITE_LOCKED); |
+ sql_script(&err, &db, "DROP TABLE IF EXISTS t1"); |
+ clear_error(&err, SQLITE_LOCKED); |
+ } |
+ closedb(&err, &db); |
+ print_and_free_err(&err); |
+ return sqlite3_mprintf("ok"); |
+} |
+ |
+/* |
+** Thread 2. Open and close database connections. |
+*/ |
+static char *stress_thread_2(int iTid, void *pArg){ |
+ Error err = {0}; /* Error code and message */ |
+ Sqlite db = {0}; /* SQLite database connection */ |
+ while( !timetostop(&err) ){ |
+ opendb(&err, &db, "test.db", 0); |
+ sql_script(&err, &db, "SELECT * FROM sqlite_master;"); |
+ clear_error(&err, SQLITE_LOCKED); |
+ closedb(&err, &db); |
+ } |
+ print_and_free_err(&err); |
+ return sqlite3_mprintf("ok"); |
+} |
+ |
+/* |
+** Thread 3. Attempt many small SELECT statements. |
+*/ |
+static char *stress_thread_3(int iTid, void *pArg){ |
+ Error err = {0}; /* Error code and message */ |
+ Sqlite db = {0}; /* SQLite database connection */ |
+ |
+ int i1 = 0; |
+ int i2 = 0; |
+ |
+ opendb(&err, &db, "test.db", 0); |
+ while( !timetostop(&err) ){ |
+ sql_script(&err, &db, "SELECT * FROM t1 ORDER BY a;"); |
+ i1++; |
+ if( err.rc ) i2++; |
+ clear_error(&err, SQLITE_LOCKED); |
+ clear_error(&err, SQLITE_ERROR); |
+ } |
+ closedb(&err, &db); |
+ print_and_free_err(&err); |
+ return sqlite3_mprintf("read t1 %d/%d attempts", i2, i1); |
+} |
+ |
+/* |
+** Thread 5. Attempt INSERT statements. |
+*/ |
+static char *stress_thread_4(int iTid, void *pArg){ |
+ Error err = {0}; /* Error code and message */ |
+ Sqlite db = {0}; /* SQLite database connection */ |
+ int i1 = 0; |
+ int i2 = 0; |
+ int iArg = PTR2INT(pArg); |
+ |
+ opendb(&err, &db, "test.db", 0); |
+ while( !timetostop(&err) ){ |
+ if( iArg ){ |
+ closedb(&err, &db); |
+ opendb(&err, &db, "test.db", 0); |
+ } |
+ sql_script(&err, &db, |
+ "WITH loop(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM loop LIMIT 200) " |
+ "INSERT INTO t1 VALUES(randomblob(60), randomblob(60));" |
+ ); |
+ i1++; |
+ if( err.rc ) i2++; |
+ clear_error(&err, SQLITE_LOCKED); |
+ clear_error(&err, SQLITE_ERROR); |
+ } |
+ closedb(&err, &db); |
+ print_and_free_err(&err); |
+ return sqlite3_mprintf("wrote t1 %d/%d attempts", i2, i1); |
+} |
+ |
+/* |
+** Thread 6. Attempt DELETE operations. |
+*/ |
+static char *stress_thread_5(int iTid, void *pArg){ |
+ Error err = {0}; /* Error code and message */ |
+ Sqlite db = {0}; /* SQLite database connection */ |
+ int iArg = PTR2INT(pArg); |
+ |
+ int i1 = 0; |
+ int i2 = 0; |
+ |
+ opendb(&err, &db, "test.db", 0); |
+ while( !timetostop(&err) ){ |
+ i64 i = (i1 % 4); |
+ if( iArg ){ |
+ closedb(&err, &db); |
+ opendb(&err, &db, "test.db", 0); |
+ } |
+ execsql(&err, &db, "DELETE FROM t1 WHERE (rowid % 4)==:i", &i); |
+ i1++; |
+ if( err.rc ) i2++; |
+ clear_error(&err, SQLITE_LOCKED); |
+ } |
+ closedb(&err, &db); |
+ print_and_free_err(&err); |
+ return sqlite3_mprintf("deleted from t1 %d/%d attempts", i2, i1); |
+} |
+ |
+ |
+static void stress1(int nMs){ |
+ Error err = {0}; |
+ Threadset threads = {0}; |
+ |
+ setstoptime(&err, nMs); |
+ sqlite3_enable_shared_cache(1); |
+ |
+ launch_thread(&err, &threads, stress_thread_1, 0); |
+ launch_thread(&err, &threads, stress_thread_1, 0); |
+ |
+ launch_thread(&err, &threads, stress_thread_2, 0); |
+ launch_thread(&err, &threads, stress_thread_2, 0); |
+ |
+ launch_thread(&err, &threads, stress_thread_3, 0); |
+ launch_thread(&err, &threads, stress_thread_3, 0); |
+ |
+ launch_thread(&err, &threads, stress_thread_4, 0); |
+ launch_thread(&err, &threads, stress_thread_4, 0); |
+ |
+ launch_thread(&err, &threads, stress_thread_5, 0); |
+ launch_thread(&err, &threads, stress_thread_5, (void*)1); |
+ |
+ join_all_threads(&err, &threads); |
+ sqlite3_enable_shared_cache(0); |
+ |
+ print_and_free_err(&err); |
+} |
+ |
+/************************************************************************** |
+*************************************************************************** |
+** Start of test case "stress2" |
+*/ |
+ |
+ |
+ |
+/* |
+** 1. CREATE TABLE statements. |
+** 2. DROP TABLE statements. |
+** 3. Small SELECT statements. |
+** 4. Big SELECT statements. |
+** 5. Small INSERT statements. |
+** 6. Big INSERT statements. |
+** 7. Small UPDATE statements. |
+** 8. Big UPDATE statements. |
+** 9. Small DELETE statements. |
+** 10. Big DELETE statements. |
+** 11. VACUUM. |
+** 14. Integrity-check. |
+** 17. Switch the journal mode from delete to wal and back again. |
+** 19. Open and close database connections rapidly. |
+*/ |
+ |
+#define STRESS2_TABCNT 5 /* count1 in SDS test */ |
+ |
+#define STRESS2_COUNT2 200 /* count2 in SDS test */ |
+#define STRESS2_COUNT3 57 /* count2 in SDS test */ |
+ |
+static void stress2_workload1(Error *pErr, Sqlite *pDb, int i){ |
+ int iTab = (i % (STRESS2_TABCNT-1)) + 1; |
+ sql_script_printf(pErr, pDb, |
+ "CREATE TABLE IF NOT EXISTS t%d(x PRIMARY KEY, y, z);", iTab |
+ ); |
+} |
+ |
+static void stress2_workload2(Error *pErr, Sqlite *pDb, int i){ |
+ int iTab = (i % (STRESS2_TABCNT-1)) + 1; |
+ sql_script_printf(pErr, pDb, "DROP TABLE IF EXISTS t%d;", iTab); |
+} |
+ |
+static void stress2_workload3(Error *pErr, Sqlite *pDb, int i){ |
+ sql_script(pErr, pDb, "SELECT * FROM t0 WHERE z = 'small'"); |
+} |
+ |
+static void stress2_workload4(Error *pErr, Sqlite *pDb, int i){ |
+ sql_script(pErr, pDb, "SELECT * FROM t0 WHERE z = 'big'"); |
+} |
+ |
+static void stress2_workload5(Error *pErr, Sqlite *pDb, int i){ |
+ sql_script(pErr, pDb, |
+ "INSERT INTO t0 VALUES(hex(random()), hex(randomblob(200)), 'small');" |
+ ); |
+} |
+ |
+static void stress2_workload6(Error *pErr, Sqlite *pDb, int i){ |
+ sql_script(pErr, pDb, |
+ "INSERT INTO t0 VALUES(hex(random()), hex(randomblob(57)), 'big');" |
+ ); |
+} |
+ |
+static void stress2_workload7(Error *pErr, Sqlite *pDb, int i){ |
+ sql_script_printf(pErr, pDb, |
+ "UPDATE t0 SET y = hex(randomblob(200)) " |
+ "WHERE x LIKE hex((%d %% 5)) AND z='small';" |
+ ,i |
+ ); |
+} |
+static void stress2_workload8(Error *pErr, Sqlite *pDb, int i){ |
+ sql_script_printf(pErr, pDb, |
+ "UPDATE t0 SET y = hex(randomblob(57)) " |
+ "WHERE x LIKE hex(%d %% 5) AND z='big';" |
+ ,i |
+ ); |
+} |
+ |
+static void stress2_workload9(Error *pErr, Sqlite *pDb, int i){ |
+ sql_script_printf(pErr, pDb, |
+ "DELETE FROM t0 WHERE x LIKE hex(%d %% 5) AND z='small';", i |
+ ); |
+} |
+static void stress2_workload10(Error *pErr, Sqlite *pDb, int i){ |
+ sql_script_printf(pErr, pDb, |
+ "DELETE FROM t0 WHERE x LIKE hex(%d %% 5) AND z='big';", i |
+ ); |
+} |
+ |
+static void stress2_workload11(Error *pErr, Sqlite *pDb, int i){ |
+ sql_script(pErr, pDb, "VACUUM"); |
+} |
+ |
+static void stress2_workload14(Error *pErr, Sqlite *pDb, int i){ |
+ sql_script(pErr, pDb, "PRAGMA integrity_check"); |
+} |
+ |
+static void stress2_workload17(Error *pErr, Sqlite *pDb, int i){ |
+ sql_script_printf(pErr, pDb, |
+ "PRAGMA journal_mode = %q", (i%2) ? "delete" : "wal" |
+ ); |
+} |
+ |
+static char *stress2_workload19(int iTid, void *pArg){ |
+ Error err = {0}; /* Error code and message */ |
+ Sqlite db = {0}; /* SQLite database connection */ |
+ const char *zDb = (const char*)pArg; |
+ while( !timetostop(&err) ){ |
+ opendb(&err, &db, zDb, 0); |
+ sql_script(&err, &db, "SELECT * FROM sqlite_master;"); |
+ clear_error(&err, SQLITE_LOCKED); |
+ closedb(&err, &db); |
+ } |
+ print_and_free_err(&err); |
+ return sqlite3_mprintf("ok"); |
+} |
+ |
+ |
+typedef struct Stress2Ctx Stress2Ctx; |
+struct Stress2Ctx { |
+ const char *zDb; |
+ void (*xProc)(Error*, Sqlite*, int); |
+}; |
+ |
+static char *stress2_thread_wrapper(int iTid, void *pArg){ |
+ Stress2Ctx *pCtx = (Stress2Ctx*)pArg; |
+ Error err = {0}; /* Error code and message */ |
+ Sqlite db = {0}; /* SQLite database connection */ |
+ int i1 = 0; |
+ int i2 = 0; |
+ |
+ while( !timetostop(&err) ){ |
+ int cnt; |
+ opendb(&err, &db, pCtx->zDb, 0); |
+ for(cnt=0; err.rc==SQLITE_OK && cnt<STRESS2_TABCNT; cnt++){ |
+ pCtx->xProc(&err, &db, i1); |
+ i2 += (err.rc==SQLITE_OK); |
+ clear_error(&err, SQLITE_LOCKED); |
+ i1++; |
+ } |
+ closedb(&err, &db); |
+ } |
+ |
+ print_and_free_err(&err); |
+ return sqlite3_mprintf("ok %d/%d", i2, i1); |
+} |
+ |
+static void stress2_launch_thread_loop( |
+ Error *pErr, /* IN/OUT: Error code */ |
+ Threadset *pThreads, /* Thread set */ |
+ const char *zDb, /* Database name */ |
+ void (*x)(Error*,Sqlite*,int) /* Run this until error or timeout */ |
+){ |
+ Stress2Ctx *pCtx = sqlite3_malloc(sizeof(Stress2Ctx)); |
+ pCtx->zDb = zDb; |
+ pCtx->xProc = x; |
+ launch_thread(pErr, pThreads, stress2_thread_wrapper, (void*)pCtx); |
+} |
+ |
+static void stress2(int nMs){ |
+ struct Stress2Task { |
+ void (*x)(Error*,Sqlite*,int); |
+ } aTask[] = { |
+ { stress2_workload1 }, |
+ { stress2_workload2 }, |
+ { stress2_workload3 }, |
+ { stress2_workload4 }, |
+ { stress2_workload5 }, |
+ { stress2_workload6 }, |
+ { stress2_workload7 }, |
+ { stress2_workload8 }, |
+ { stress2_workload9 }, |
+ { stress2_workload10 }, |
+ { stress2_workload11 }, |
+ { stress2_workload14 }, |
+ { stress2_workload17 }, |
+ }; |
+ const char *zDb = "test.db"; |
+ |
+ int i; |
+ Error err = {0}; |
+ Sqlite db = {0}; |
+ Threadset threads = {0}; |
+ |
+ /* To make sure the db file is empty before commencing */ |
+ opendb(&err, &db, zDb, 1); |
+ sql_script(&err, &db, |
+ "CREATE TABLE IF NOT EXISTS t0(x PRIMARY KEY, y, z);" |
+ "CREATE INDEX IF NOT EXISTS i0 ON t0(y);" |
+ ); |
+ closedb(&err, &db); |
+ |
+ setstoptime(&err, nMs); |
+ sqlite3_enable_shared_cache(1); |
+ |
+ for(i=0; i<sizeof(aTask)/sizeof(aTask[0]); i++){ |
+ stress2_launch_thread_loop(&err, &threads, zDb, aTask[i].x); |
+ } |
+ launch_thread(&err, &threads, stress2_workload19, (void*)zDb); |
+ launch_thread(&err, &threads, stress2_workload19, (void*)zDb); |
+ |
+ join_all_threads(&err, &threads); |
+ sqlite3_enable_shared_cache(0); |
+ print_and_free_err(&err); |
+} |
+ |
+ |
+ |
+ |