| Index: third_party/sqlite/sqlite-src-3100200/test/tt3_stress.c
|
| diff --git a/third_party/sqlite/sqlite-src-3100200/test/tt3_stress.c b/third_party/sqlite/sqlite-src-3100200/test/tt3_stress.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cdfab9c09ccc93add56840271bcd9c8b8ac25ed5
|
| --- /dev/null
|
| +++ b/third_party/sqlite/sqlite-src-3100200/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);
|
| +}
|
| +
|
| +
|
| +
|
| +
|
|
|