github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/tt3_stress.c (about)

     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_schema;");
    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_schema;");
   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  }