Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Many improvements to the mptest program. Added a simple test script. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | mptest |
Files: | files | file ages | folders |
SHA1: | 07b0401a9b61b1664fc6dcddac3b5969 |
User & Date: | drh 2013-04-06 13:09:11 |
Context
2013-04-06
| ||
14:04 | Get the mptest program running on windows. check-in: 3966b332 user: drh tags: mptest | |
13:09 | Many improvements to the mptest program. Added a simple test script. check-in: 07b0401a user: drh tags: mptest | |
00:19 | Add a prototype TH3-script-style test harness that starts multiple processes operating on the same database file at the same time. check-in: c318fafe user: drh tags: mptest | |
Changes
Added mptest/config01.test.
1 +/* 2 +** Configure five tasks in different ways, then run tests. 3 +*/ 4 +PRAGMA page_size=8192; 5 +--task 1 6 + PRAGMA journal_mode=PERSIST; 7 + PRAGMA mmap_limit=0; 8 +--end 9 +--task 2 10 + PRAGMA journal_mode=TRUNCATE; 11 + PRAGMA mmap_limit=28672; 12 +--end 13 +--task 3 14 + PRAGMA journal_mode=MEMORY; 15 +--end 16 +--task 4 17 + PRAGMA journal_mode=OFF; 18 +--end 19 +--source multiwrite01.test
Changes to mptest/mptest.c.
53 53 char *zLog; /* Name of output log file */ 54 54 FILE *pLog; /* Where to write log messages */ 55 55 char zName[12]; /* Symbolic name of this process */ 56 56 int taskId; /* Task ID. 0 means supervisor. */ 57 57 int iTrace; /* Tracing level */ 58 58 int bSqlTrace; /* True to trace SQL commands */ 59 59 int nError; /* Number of errors */ 60 + int nTest; /* Number of --match operators */ 61 + int iTimeout; /* Milliseconds until a busy timeout */ 60 62 } g; 61 63 64 +/* Default timeout */ 65 +#define DEFAULT_TIMEOUT 10000 66 + 62 67 /* 63 68 ** Print a message adding zPrefix[] to the beginning of every line. 64 69 */ 65 70 static void printWithPrefix(FILE *pOut, const char *zPrefix, const char *zMsg){ 66 71 while( zMsg && zMsg[0] ){ 67 72 int i; 68 73 for(i=0; zMsg[i] && zMsg[i]!='\n' && zMsg[i]!='\r'; i++){} ................................................................................ 222 227 printWithPrefix(g.pErrLog, zPrefix, zMsg); 223 228 fflush(g.pErrLog); 224 229 maybeClose(g.pErrLog); 225 230 } 226 231 sqlite3_free(zMsg); 227 232 if( g.db ){ 228 233 int nTry = 0; 229 - while( trySql("CREATE TABLE halt(x);")==SQLITE_BUSY && (nTry++)<100 ){ 234 + g.iTimeout = 0; 235 + while( trySql("UPDATE client SET wantHalt=1;")==SQLITE_BUSY 236 + && (nTry++)<100 ){ 230 237 sqlite3_sleep(10); 231 238 } 232 239 } 233 240 sqlite3_close(g.db); 234 241 exit(1); 235 242 } 236 243 ................................................................................ 257 264 ** Return the length of a string omitting trailing whitespace 258 265 */ 259 266 static int clipLength(const char *z){ 260 267 int n = (int)strlen(z); 261 268 while( n>0 && isspace(z[n-1]) ){ n--; } 262 269 return n; 263 270 } 271 + 272 +/* 273 +** Busy handler with a g.iTimeout-millisecond timeout 274 +*/ 275 +static int busyHandler(void *pCD, int count){ 276 + if( count*10>g.iTimeout ){ 277 + if( g.iTimeout>0 ) errorMessage("timeout after %dms", g.iTimeout); 278 + return 0; 279 + } 280 + sqlite3_sleep(10); 281 + return 1; 282 +} 264 283 265 284 /* 266 285 ** SQL Trace callback 267 286 */ 268 287 static void sqlTraceCallback(void *NotUsed1, const char *zSql){ 269 288 logMessage("[%.*s]", clipLength(zSql), zSql); 270 289 } ................................................................................ 404 423 va_list ap; 405 424 char *zSql; 406 425 int rc; 407 426 char *zErrMsg = 0; 408 427 va_start(ap, zFormat); 409 428 zSql = sqlite3_vmprintf(zFormat, ap); 410 429 va_end(ap); 430 + assert( g.iTimeout>0 ); 411 431 rc = sqlite3_exec(g.db, zSql, evalCallback, p, &zErrMsg); 412 432 sqlite3_free(zSql); 413 433 if( rc ){ 414 434 char zErr[30]; 415 435 sqlite3_snprintf(sizeof(zErr), zErr, "error(%d)", rc); 416 436 stringAppendTerm(p, zErr); 417 437 if( zErrMsg ){ ................................................................................ 431 451 int iClient, /* The client number */ 432 452 char **pzScript, /* Write task script here */ 433 453 int *pTaskId /* Write task number here */ 434 454 ){ 435 455 sqlite3_stmt *pStmt = 0; 436 456 int taskId; 437 457 int rc; 458 + int totalTime = 0; 438 459 439 460 *pzScript = 0; 461 + g.iTimeout = 0; 440 462 while(1){ 441 - if( trySql("SELECT * FROM halt")==SQLITE_OK ) return SQLITE_DONE; 442 463 rc = trySql("BEGIN IMMEDIATE"); 443 464 if( rc==SQLITE_BUSY ){ 444 465 sqlite3_sleep(10); 466 + totalTime += 10; 445 467 continue; 446 468 } 447 469 if( rc!=SQLITE_OK ){ 448 470 fatalError("%s\nBEGIN IMMEDIATE", sqlite3_errmsg(g.db)); 449 471 } 450 - if( g.nError ){ 451 - runSql("UPDATE clienterror SET cnt=cnt+%d", g.nError); 472 + if( g.nError || g.nTest ){ 473 + runSql("UPDATE counters SET nError=nError+%d, nTest=nTest+%d", 474 + g.nError, g.nTest); 452 475 g.nError = 0; 476 + g.nTest = 0; 477 + } 478 + pStmt = prepareSql("SELECT 1 FROM client WHERE id=%d AND wantHalt",iClient); 479 + rc = sqlite3_step(pStmt); 480 + sqlite3_finalize(pStmt); 481 + if( rc==SQLITE_ROW ){ 482 + runSql("DELETE FROM client WHERE id=%d", iClient); 483 + runSql("COMMIT"); 484 + g.iTimeout = DEFAULT_TIMEOUT; 485 + return SQLITE_DONE; 453 486 } 454 487 pStmt = prepareSql( 455 488 "SELECT script, id FROM task" 456 489 " WHERE client=%d AND starttime IS NULL" 457 490 " ORDER BY id LIMIT 1", iClient); 458 491 rc = sqlite3_step(pStmt); 459 492 if( rc==SQLITE_ROW ){ ................................................................................ 462 495 strcpy(*pzScript, (const char*)sqlite3_column_text(pStmt, 0)); 463 496 *pTaskId = taskId = sqlite3_column_int(pStmt, 1); 464 497 sqlite3_finalize(pStmt); 465 498 runSql("UPDATE task" 466 499 " SET starttime=strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')" 467 500 " WHERE id=%d;", taskId); 468 501 runSql("COMMIT;"); 502 + g.iTimeout = DEFAULT_TIMEOUT; 469 503 return SQLITE_OK; 470 504 } 471 505 sqlite3_finalize(pStmt); 472 506 if( rc==SQLITE_DONE ){ 507 + if( totalTime>30000 ){ 508 + errorMessage("Waited over 30 seconds with no work. Giving up."); 509 + runSql("DELETE FROM client WHERE id=%d; COMMIT;", iClient); 510 + sqlite3_close(g.db); 511 + exit(1); 512 + } 473 513 runSql("COMMIT;"); 474 514 sqlite3_sleep(100); 515 + totalTime += 100; 475 516 continue; 476 517 } 477 518 fatalError("%s", sqlite3_errmsg(g.db)); 478 519 } 520 + g.iTimeout = DEFAULT_TIMEOUT; 521 +} 522 + 523 +/* 524 +** Mark a script as having finished. Remove the CLIENT table entry 525 +** if bShutdown is true. 526 +*/ 527 +static int finishScript(int iClient, int taskId, int bShutdown){ 528 + runSql("UPDATE task" 529 + " SET endtime=strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')" 530 + " WHERE id=%d;", taskId); 531 + if( bShutdown ){ 532 + runSql("DELETE FROM client WHERE id=%d", iClient); 533 + } 534 + return SQLITE_OK; 479 535 } 480 536 481 537 /* 482 -** Mark a script as having finished. 538 +** Start up a client process for iClient, if it is not already 539 +** running. If the client is already running, then this routine 540 +** is a no-op. 483 541 */ 484 -static int finishScript(int taskId){ 485 - sqlite3_stmt *pStmt; 486 - int rc; 487 - pStmt = prepareSql( 488 - "UPDATE task" 489 - " SET endtime=strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')" 490 - " WHERE id=%d;", taskId); 491 - do{ 492 - rc = sqlite3_step(pStmt); 493 - sqlite3_reset(pStmt); 494 - }while( rc==SQLITE_BUSY ); 495 - sqlite3_finalize(pStmt); 496 - if( rc!=SQLITE_DONE ){ 497 - fatalError("%s\n", sqlite3_errmsg(g.db)); 542 +static void startClient(int iClient){ 543 + runSql("INSERT OR IGNORE INTO client VALUES(%d,0)", iClient); 544 + if( sqlite3_changes(g.db) ){ 545 + char *zSys; 546 + zSys = sqlite3_mprintf( 547 + "%s \"%s\" --client %d --trace %d %s&", 548 + g.argv0, g.zDbFile, iClient, g.iTrace, 549 + g.bSqlTrace ? "--sqltrace " : ""); 550 + 551 + system(zSys); 552 + sqlite3_free(zSys); 498 553 } 499 - return rc; 500 554 } 501 555 502 556 /* 503 557 ** Read the entire content of a file into memory 504 558 */ 505 559 static char *readFile(const char *zFilename){ 506 560 FILE *in = fopen(zFilename, "rb"); ................................................................................ 593 647 ** Wait for a client process to complete all its tasks 594 648 */ 595 649 static void waitForClient(int iClient, int iTimeout, char *zErrPrefix){ 596 650 sqlite3_stmt *pStmt; 597 651 int rc; 598 652 if( iClient>0 ){ 599 653 pStmt = prepareSql( 600 - "SELECT 1 FROM task WHERE client=%d AND endtime IS NULL", 654 + "SELECT 1 FROM task" 655 + " WHERE client=%d" 656 + " AND client IN (SELECT id FROM client)" 657 + " AND endtime IS NULL", 601 658 iClient); 602 659 }else{ 603 660 pStmt = prepareSql( 604 - "SELECT 1 FROM task WHERE client=%d AND endtime IS NULL", 605 - iClient); 661 + "SELECT 1 FROM task" 662 + " WHERE client IN (SELECT id FROM client)" 663 + " AND endtime IS NULL"); 606 664 } 665 + g.iTimeout = 0; 607 666 while( ((rc = sqlite3_step(pStmt))==SQLITE_BUSY || rc==SQLITE_ROW) 608 667 && iTimeout>0 609 668 ){ 610 669 sqlite3_reset(pStmt); 611 670 sqlite3_sleep(50); 612 671 iTimeout -= 50; 613 672 } 614 673 sqlite3_finalize(pStmt); 674 + g.iTimeout = DEFAULT_TIMEOUT; 615 675 if( rc!=SQLITE_DONE ){ 616 676 if( zErrPrefix==0 ) zErrPrefix = ""; 617 677 if( iClient>0 ){ 618 678 errorMessage("%stimeout waiting for client %d", zErrPrefix, iClient); 619 679 }else{ 620 680 errorMessage("%stimeout waiting for all clients", zErrPrefix); 621 681 } ................................................................................ 635 695 char *zFilename /* File from which script was read. */ 636 696 ){ 637 697 int lineno = 1; 638 698 int prevLine = 1; 639 699 int ii = 0; 640 700 int iBegin = 0; 641 701 int n, c, j; 642 - int rc; 643 702 int len; 644 703 int nArg; 645 704 String sResult; 646 705 char zCmd[30]; 647 706 char zError[1000]; 648 707 char azArg[MX_ARG][100]; 649 - unsigned char isRunning[100]; 650 708 651 - memset(isRunning, 0, sizeof(isRunning)); 652 709 memset(&sResult, 0, sizeof(sResult)); 653 710 stringReset(&sResult); 654 711 while( (c = zScript[ii])!=0 ){ 655 712 prevLine = lineno; 656 713 len = tokenLength(zScript+ii, &lineno); 657 714 if( isspace(c) || (c=='/' && zScript[ii+1]=='*') ){ 658 715 ii += len; ................................................................................ 695 752 ** --exit N 696 753 ** 697 754 ** Exit this process. If N>0 then exit without shutting down 698 755 ** SQLite. (In other words, simulate a crash.) 699 756 */ 700 757 if( strcmp(zCmd, "exit")==0 ){ 701 758 int rc = atoi(azArg[0]); 702 - finishScript(taskId); 759 + finishScript(iClient, taskId, 1); 703 760 if( rc==0 ) sqlite3_close(g.db); 704 761 exit(rc); 705 762 }else 706 763 707 764 /* 708 765 ** --result 709 766 ** ................................................................................ 723 780 char *zAns = zScript+ii; 724 781 for(jj=7; jj<len-1 && isspace(zAns[jj]); jj++){} 725 782 zAns += jj; 726 783 if( strncmp(sResult.z, zAns, len-jj-1) ){ 727 784 errorMessage("line %d of %s:\nExpected [%.*s]\n Got [%s]", 728 785 prevLine, zFilename, len-jj-1, zAns, sResult.z); 729 786 } 787 + g.nTest++; 730 788 stringReset(&sResult); 731 789 }else 732 790 733 791 /* 734 792 ** --source FILENAME 735 793 ** 736 794 ** Run a subscript from a separate file. 737 795 */ 738 796 if( strcmp(zCmd, "source")==0 ){ 739 - char *zNewFile = azArg[1]; 797 + char *zNewFile = azArg[0]; 740 798 char *zNewScript = readFile(zNewFile); 741 799 if( g.iTrace ) logMessage("begin script [%s]\n", zNewFile); 742 800 runScript(0, 0, zNewScript, zNewFile); 743 801 sqlite3_free(zNewScript); 744 802 if( g.iTrace ) logMessage("end script [%s]\n", zNewFile); 745 803 }else 746 804 ................................................................................ 758 816 /* 759 817 ** --start CLIENT 760 818 ** 761 819 ** Start up the given client. 762 820 */ 763 821 if( strcmp(zCmd, "start")==0 ){ 764 822 int iNewClient = atoi(azArg[0]); 765 - char *zSys; 766 - if( iNewClient<1 || iNewClient>=sizeof(isRunning) ){ 767 - errorMessage("line %d of %s: bad client number: %d", 768 - prevLine, zFilename, iNewClient); 769 - goto start_error; 823 + if( iNewClient>0 ){ 824 + startClient(iNewClient); 770 825 } 771 - if( isRunning[iNewClient] ){ 772 - errorMessage("line %d of %s: client already running: %d", 773 - prevLine, zFilename, iNewClient); 774 - goto start_error; 775 - } 776 - zSys = sqlite3_mprintf( 777 - "%s \"%s\" --client %d --trace %d %s&", 778 - g.argv0, g.zDbFile, iNewClient, g.iTrace, 779 - g.bSqlTrace ? "--sqltrace " : ""); 780 - 781 - system(zSys); 782 - sqlite3_free(zSys); 783 - isRunning[iNewClient] = 1; 784 - start_error: {/* no-op */} 785 826 }else 786 827 787 828 /* 788 829 ** --wait CLIENT TIMEOUT 789 830 ** 790 831 ** Wait until all tasks complete for the given client. If CLIENT is 791 832 ** "all" then wait for all clients to complete. Wait no longer than ................................................................................ 799 840 }else 800 841 801 842 /* 802 843 ** --task CLIENT 803 844 ** <task-content-here> 804 845 ** --end 805 846 ** 806 - ** Assign work to a client. 847 + ** Assign work to a client. Start the client if it is not running 848 + ** already. 807 849 */ 808 850 if( strcmp(zCmd, "task")==0 ){ 809 851 int iTarget = atoi(azArg[0]); 810 852 int iEnd; 811 853 char *zTask; 812 - sqlite3_stmt *pStmt; 813 854 iEnd = findEnd(zScript+ii+len, &lineno); 814 - if( iTarget<0 || iTarget>=sizeof(isRunning) 815 - || !isRunning[iTarget] ){ 816 - errorMessage("line %d of %s: client %d is not running", 855 + if( iTarget<0 ){ 856 + errorMessage("line %d of %s: bad client number: %d", 817 857 prevLine, zFilename, iTarget); 818 - goto task_error; 858 + }else{ 859 + zTask = sqlite3_mprintf("%.*s", iEnd, zScript+ii+len); 860 + startClient(iTarget); 861 + runSql("INSERT INTO task(client,script)" 862 + " VALUES(%d,'%q')", iTarget, zTask); 863 + sqlite3_free(zTask); 819 864 } 820 - zTask = sqlite3_mprintf("%.*s", iEnd, zScript+ii+len); 821 - pStmt = prepareSql("INSERT INTO task(client,script)" 822 - " VALUES(%d,'%q')", iTarget, zTask); 823 - sqlite3_free(zTask); 824 - while( (rc = sqlite3_step(pStmt))==SQLITE_BUSY ){ 825 - sqlite3_reset(pStmt); 826 - sqlite3_sleep(10); 827 - } 828 - sqlite3_finalize(pStmt); 829 - task_error: 830 865 iEnd += tokenLength(zScript+ii+len+iEnd, &lineno); 831 866 len += iEnd; 832 867 iBegin = ii+len; 833 868 }else 834 869 835 870 /* error */{ 836 871 errorMessage("line %d of %s: unknown command --%s", ................................................................................ 960 995 }else{ 961 996 iClient = 0; 962 997 unlink(g.zDbFile); 963 998 openFlags |= SQLITE_OPEN_CREATE; 964 999 } 965 1000 rc = sqlite3_open_v2(g.zDbFile, &g.db, openFlags, g.zVfs); 966 1001 if( rc ) fatalError("cannot open [%s]", g.zDbFile); 1002 + sqlite3_busy_handler(g.db, busyHandler, 0); 1003 + g.iTimeout = DEFAULT_TIMEOUT; 967 1004 if( g.bSqlTrace ) sqlite3_trace(g.db, sqlTraceCallback, 0); 968 1005 if( iClient>0 ){ 969 1006 if( n>0 ) unrecognizedArguments(argv[0], n, argv+2); 970 1007 if( g.iTrace ) logMessage("start-client"); 971 1008 while(1){ 972 1009 char zTaskName[50]; 973 1010 rc = startScript(iClient, &zScript, &taskId); 974 1011 if( rc==SQLITE_DONE ) break; 975 1012 if( g.iTrace ) logMessage("begin task %d", taskId); 976 1013 sqlite3_snprintf(sizeof(zTaskName), zTaskName, "client%02d-task-%d", 977 1014 iClient, taskId); 978 1015 runScript(iClient, taskId, zScript, zTaskName); 979 1016 if( g.iTrace ) logMessage("end task %d", taskId); 980 - finishScript(taskId); 1017 + finishScript(iClient, taskId, 0); 981 1018 sqlite3_sleep(10); 982 1019 } 983 1020 if( g.iTrace ) logMessage("end-client"); 984 1021 }else{ 985 1022 sqlite3_stmt *pStmt; 1023 + int iTimeout; 986 1024 if( n==0 ){ 987 1025 fatalError("missing script filename"); 988 1026 } 989 1027 if( n>1 ) unrecognizedArguments(argv[0], n, argv+2); 990 1028 runSql( 991 1029 "CREATE TABLE task(\n" 992 1030 " id INTEGER PRIMARY KEY,\n" 993 1031 " client INTEGER,\n" 994 1032 " starttime DATE,\n" 995 1033 " endtime DATE,\n" 996 1034 " script TEXT\n" 997 1035 ");" 998 - "CREATE TABLE clienterror(cnt);\n" 999 - "INSERT INTO clienterror VALUES(0);\n" 1036 + "CREATE INDEX task_i1 ON task(client, starttime);\n" 1037 + "CREATE INDEX task_i2 ON task(client, endtime);\n" 1038 + "CREATE TABLE counters(nError,nTest);\n" 1039 + "INSERT INTO counters VALUES(0,0);\n" 1040 + "CREATE TABLE client(id INTEGER PRIMARY KEY, wantHalt);\n" 1000 1041 ); 1001 1042 zScript = readFile(argv[2]); 1002 1043 if( g.iTrace ) logMessage("begin script [%s]\n", argv[2]); 1003 1044 runScript(0, 0, zScript, argv[2]); 1004 1045 sqlite3_free(zScript); 1005 1046 if( g.iTrace ) logMessage("end script [%s]\n", argv[2]); 1006 1047 waitForClient(0, 2000, "during shutdown...\n"); 1007 - while( trySql("CREATE TABLE halt(x);")==SQLITE_BUSY ){ 1048 + trySql("UPDATE client SET wantHalt=1"); 1049 + sqlite3_sleep(10); 1050 + g.iTimeout = 0; 1051 + iTimeout = 1000; 1052 + while( ((rc = trySql("SELECT 1 FROM client"))==SQLITE_BUSY 1053 + || rc==SQLITE_ROW) && iTimeout>0 ){ 1008 1054 sqlite3_sleep(10); 1055 + iTimeout -= 10; 1009 1056 } 1010 1057 sqlite3_sleep(100); 1011 - pStmt = prepareSql("SELECT cnt FROM clienterror"); 1012 - while( (rc = sqlite3_step(pStmt))==SQLITE_BUSY ){ 1058 + pStmt = prepareSql("SELECT nError, nTest FROM counters"); 1059 + iTimeout = 1000; 1060 + while( (rc = sqlite3_step(pStmt))==SQLITE_BUSY && iTimeout>0 ){ 1013 1061 sqlite3_sleep(10); 1062 + iTimeout -= 10; 1014 1063 } 1015 1064 if( rc==SQLITE_ROW ){ 1016 1065 g.nError += sqlite3_column_int(pStmt, 0); 1066 + g.nTest += sqlite3_column_int(pStmt, 1); 1017 1067 } 1018 1068 sqlite3_finalize(pStmt); 1019 1069 } 1020 1070 sqlite3_close(g.db); 1021 1071 maybeClose(g.pLog); 1022 1072 maybeClose(g.pErrLog); 1023 1073 if( iClient==0 ){ 1024 - if( g.nError ){ 1025 - printf("ERRORS: %d\n", g.nError); 1026 - }else if( g.iTrace ){ 1027 - printf("All OK\n"); 1028 - } 1074 + printf("Summary: %d errors in %d tests\n", g.nError, g.nTest); 1029 1075 } 1030 1076 return g.nError>0; 1031 1077 }
Added mptest/multiwrite01.test.
1 +/* 2 +** This script sets up five different tasks all writing and updating 3 +** the database at the same time, but each in its own table. 4 +*/ 5 +--task 1 6 + DROP TABLE IF EXISTS t1; 7 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 8 + --sleep 1 9 + INSERT INTO t1 VALUES(1, randomblob(2000)); 10 + INSERT INTO t1 VALUES(2, randomblob(1000)); 11 + --sleep 1 12 + INSERT INTO t1 SELECT a+2, randomblob(1500) FROM t1; 13 + INSERT INTO t1 SELECT a+4, randomblob(1500) FROM t1; 14 + INSERT INTO t1 SELECT a+8, randomblob(1500) FROM t1; 15 + --sleep 1 16 + INSERT INTO t1 SELECT a+16, randomblob(1500) FROM t1; 17 + --sleep 1 18 + INSERT INTO t1 SELECT a+32, randomblob(1500) FROM t1; 19 + SELECT count(*) FROM t1; 20 + --match 64 21 + SELECT avg(length(b)) FROM t1; 22 + --match 1500.0 23 + --sleep 2 24 + UPDATE t1 SET b='x'||a||'y'; 25 + SELECT total(length(b)) FROM t1; 26 + --match 247 27 +--end 28 + 29 + 30 +--task 2 31 + DROP TABLE IF EXISTS t2; 32 + CREATE TABLE t2(a INTEGER PRIMARY KEY, b); 33 + --sleep 1 34 + INSERT INTO t2 VALUES(1, randomblob(2000)); 35 + INSERT INTO t2 VALUES(2, randomblob(1000)); 36 + --sleep 1 37 + INSERT INTO t2 SELECT a+2, randomblob(1500) FROM t2; 38 + INSERT INTO t2 SELECT a+4, randomblob(1500) FROM t2; 39 + INSERT INTO t2 SELECT a+8, randomblob(1500) FROM t2; 40 + --sleep 1 41 + INSERT INTO t2 SELECT a+16, randomblob(1500) FROM t2; 42 + --sleep 1 43 + INSERT INTO t2 SELECT a+32, randomblob(1500) FROM t2; 44 + SELECT count(*) FROM t2; 45 + --match 64 46 + SELECT avg(length(b)) FROM t2; 47 + --match 1500.0 48 + --sleep 2 49 + UPDATE t2 SET b='x'||a||'y'; 50 + SELECT total(length(b)) FROM t2; 51 + --match 247 52 +--end 53 + 54 +--task 3 55 + DROP TABLE IF EXISTS t3; 56 + CREATE TABLE t3(a INTEGER PRIMARY KEY, b); 57 + --sleep 1 58 + INSERT INTO t3 VALUES(1, randomblob(2000)); 59 + INSERT INTO t3 VALUES(2, randomblob(1000)); 60 + --sleep 1 61 + INSERT INTO t3 SELECT a+2, randomblob(1500) FROM t3; 62 + INSERT INTO t3 SELECT a+4, randomblob(1500) FROM t3; 63 + INSERT INTO t3 SELECT a+8, randomblob(1500) FROM t3; 64 + --sleep 1 65 + INSERT INTO t3 SELECT a+16, randomblob(1500) FROM t3; 66 + --sleep 1 67 + INSERT INTO t3 SELECT a+32, randomblob(1500) FROM t3; 68 + SELECT count(*) FROM t3; 69 + --match 64 70 + SELECT avg(length(b)) FROM t3; 71 + --match 1500.0 72 + --sleep 2 73 + UPDATE t3 SET b='x'||a||'y'; 74 + SELECT total(length(b)) FROM t3; 75 + --match 247 76 +--end 77 + 78 +--task 4 79 + DROP TABLE IF EXISTS t4; 80 + CREATE TABLE t4(a INTEGER PRIMARY KEY, b); 81 + --sleep 1 82 + INSERT INTO t4 VALUES(1, randomblob(2000)); 83 + INSERT INTO t4 VALUES(2, randomblob(1000)); 84 + --sleep 1 85 + INSERT INTO t4 SELECT a+2, randomblob(1500) FROM t4; 86 + INSERT INTO t4 SELECT a+4, randomblob(1500) FROM t4; 87 + INSERT INTO t4 SELECT a+8, randomblob(1500) FROM t4; 88 + --sleep 1 89 + INSERT INTO t4 SELECT a+16, randomblob(1500) FROM t4; 90 + --sleep 1 91 + INSERT INTO t4 SELECT a+32, randomblob(1500) FROM t4; 92 + SELECT count(*) FROM t4; 93 + --match 64 94 + SELECT avg(length(b)) FROM t4; 95 + --match 1500.0 96 + --sleep 2 97 + UPDATE t4 SET b='x'||a||'y'; 98 + SELECT total(length(b)) FROM t4; 99 + --match 247 100 +--end 101 + 102 +--task 5 103 + DROP TABLE IF EXISTS t5; 104 + CREATE TABLE t5(a INTEGER PRIMARY KEY, b); 105 + --sleep 1 106 + INSERT INTO t5 VALUES(1, randomblob(2000)); 107 + INSERT INTO t5 VALUES(2, randomblob(1000)); 108 + --sleep 1 109 + INSERT INTO t5 SELECT a+2, randomblob(1500) FROM t5; 110 + INSERT INTO t5 SELECT a+4, randomblob(1500) FROM t5; 111 + INSERT INTO t5 SELECT a+8, randomblob(1500) FROM t5; 112 + --sleep 1 113 + INSERT INTO t5 SELECT a+16, randomblob(1500) FROM t5; 114 + --sleep 1 115 + INSERT INTO t5 SELECT a+32, randomblob(1500) FROM t5; 116 + SELECT count(*) FROM t5; 117 + --match 64 118 + SELECT avg(length(b)) FROM t5; 119 + --match 1500.0 120 + --sleep 2 121 + UPDATE t5 SET b='x'||a||'y'; 122 + SELECT total(length(b)) FROM t5; 123 + --match 247 124 +--end 125 + 126 +--wait all 127 +SELECT count(*), total(length(b)) FROM t1; 128 +--match 64 247 129 +SELECT count(*), total(length(b)) FROM t2; 130 +--match 64 247 131 +SELECT count(*), total(length(b)) FROM t3; 132 +--match 64 247 133 +SELECT count(*), total(length(b)) FROM t4; 134 +--match 64 247 135 +SELECT count(*), total(length(b)) FROM t5; 136 +--match 64 247 137 +DROP TABLE t1; 138 +DROP TABLE t2; 139 +DROP TABLE t3; 140 +DROP TABLE t4; 141 +DROP TABLE t5;