/ Check-in [e05089aa]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Invoke sqlite3_log() whenever one or more frames are recovered from a WAL file.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:e05089aaefe02ec59a1923812349471a78075d29
User & Date: dan 2010-08-17 14:52:23
Context
2010-08-17
16:06
Add tests for the BETWEEN operator to e_expr.test. check-in: ced6a348 user: dan tags: trunk
14:52
Invoke sqlite3_log() whenever one or more frames are recovered from a WAL file. check-in: e05089aa user: dan tags: trunk
05:55
Fix some non-ANSI C code in test_demovfs.c. Also change the same file so that attempting to delete a file that does not exist does not return an error. check-in: 07570ce3 user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/test1.c.

4945
4946
4947
4948
4949
4950
4951









































4952
4953
4954
4955
4956
4957
4958
....
5168
5169
5170
5171
5172
5173
5174

5175
5176
5177
5178
5179
5180
5181
    zDb = Tcl_GetString(objv[2]);
  }
  rc = sqlite3_wal_checkpoint(db, zDb);
  Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  return TCL_OK;
}











































/*
**     tcl_objproc COMMANDNAME ARGS...
**
** Run a TCL command using its objProc interface.  Throw an error if
** the command has no objProc interface.
*/
................................................................................
     { "sqlite3_blob_write", test_blob_write, 0  },
#endif
     { "pcache_stats",       test_pcache_stats, 0  },
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
     { "sqlite3_unlock_notify", test_unlock_notify, 0  },
#endif
     { "sqlite3_wal_checkpoint", test_wal_checkpoint, 0  },

  };
  static int bitmask_size = sizeof(Bitmask)*8;
  int i;
  extern int sqlite3_sync_count, sqlite3_fullsync_count;
  extern int sqlite3_opentemp_count;
  extern int sqlite3_like_count;
  extern int sqlite3_xferopt_count;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
....
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
    zDb = Tcl_GetString(objv[2]);
  }
  rc = sqlite3_wal_checkpoint(db, zDb);
  Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  return TCL_OK;
}

/*
** tclcmd:  test_sqlite3_log ?SCRIPT?
*/
static struct LogCallback {
  Tcl_Interp *pInterp;
  Tcl_Obj *pObj;
} logcallback = {0, 0};
static void xLogcallback(void *unused, int err, char *zMsg){
  Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj);
  Tcl_IncrRefCount(pNew);
  Tcl_ListObjAppendElement(
      0, pNew, Tcl_NewStringObj(sqlite3TestErrorName(err), -1)
  );
  Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1));
  Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
  Tcl_DecrRefCount(pNew);
}
static int test_sqlite3_log(
  ClientData clientData,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int objc,              /* Number of arguments */
  Tcl_Obj *CONST objv[]  /* Command arguments */
){
  if( objc>2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT");
    return TCL_ERROR;
  }
  if( logcallback.pObj ){
    Tcl_DecrRefCount(logcallback.pObj);
    logcallback.pObj = 0;
    logcallback.pInterp = 0;
    sqlite3_config(SQLITE_CONFIG_LOG, 0, 0);
  }
  if( objc>1 ){
    logcallback.pObj = objv[1];
    Tcl_IncrRefCount(logcallback.pObj);
    logcallback.pInterp = interp;
    sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, 0);
  }
  return TCL_OK;
}

/*
**     tcl_objproc COMMANDNAME ARGS...
**
** Run a TCL command using its objProc interface.  Throw an error if
** the command has no objProc interface.
*/
................................................................................
     { "sqlite3_blob_write", test_blob_write, 0  },
#endif
     { "pcache_stats",       test_pcache_stats, 0  },
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
     { "sqlite3_unlock_notify", test_unlock_notify, 0  },
#endif
     { "sqlite3_wal_checkpoint", test_wal_checkpoint, 0  },
     { "test_sqlite3_log",     test_sqlite3_log, 0  },
  };
  static int bitmask_size = sizeof(Bitmask)*8;
  int i;
  extern int sqlite3_sync_count, sqlite3_fullsync_count;
  extern int sqlite3_opentemp_count;
  extern int sqlite3_like_count;
  extern int sqlite3_xferopt_count;

Changes to src/wal.c.

1158
1159
1160
1161
1162
1163
1164











1165
1166
1167
1168
1169
1170
1171
    ** currently holding locks that exclude all other readers, writers and
    ** checkpointers.
    */
    pInfo = walCkptInfo(pWal);
    pInfo->nBackfill = 0;
    pInfo->aReadMark[0] = 0;
    for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;











  }

recovery_error:
  WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
  walUnlockExclusive(pWal, iLock, nLock);
  return rc;
}







>
>
>
>
>
>
>
>
>
>
>







1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
    ** currently holding locks that exclude all other readers, writers and
    ** checkpointers.
    */
    pInfo = walCkptInfo(pWal);
    pInfo->nBackfill = 0;
    pInfo->aReadMark[0] = 0;
    for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;

    /* If more than one frame was recovered from the log file, report an
    ** event via sqlite3_log(). This is to help with identifying performance
    ** problems caused by applications routinely shutting down without
    ** checkpointing the log file.
    */
    if( pWal->hdr.nPage ){
      sqlite3_log(SQLITE_OK, "Recovered %d frames from WAL file %s",
          pWal->hdr.nPage, pWal->zWalName
      );
    }
  }

recovery_error:
  WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
  walUnlockExclusive(pWal, iLock, nLock);
  return rc;
}

Changes to test/wal.test.

1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470








































1471
} {ok}

#-------------------------------------------------------------------------
# Test reading and writing of databases with different page-sizes.
#
foreach pgsz {512 1024 2048 4096 8192 16384 32768 65536} {
  do_multiclient_test tn [string map [list %PGSZ% $pgsz] {
    do_test e_expr-22.%PGSZ%.$tn.1 {
      sql1 {
        PRAGMA main.page_size = %PGSZ%;
        PRAGMA auto_vacuum = 0;
        PRAGMA journal_mode = WAL;
        CREATE TABLE t1(x UNIQUE);
        INSERT INTO t1 SELECT randomblob(800);
        INSERT INTO t1 SELECT randomblob(800);
        INSERT INTO t1 SELECT randomblob(800);
      }
    } {wal}
    do_test e_expr-22.%PGSZ%.$tn.2 { sql2 { PRAGMA integrity_check } } {ok}
    do_test e_expr-22.%PGSZ%.$tn.3 {
      sql1 {PRAGMA wal_checkpoint}
      expr {[file size test.db] % %PGSZ%}
    } {0}
  }]
}









































finish_test







|










|
|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
} {ok}

#-------------------------------------------------------------------------
# Test reading and writing of databases with different page-sizes.
#
foreach pgsz {512 1024 2048 4096 8192 16384 32768 65536} {
  do_multiclient_test tn [string map [list %PGSZ% $pgsz] {
    do_test wal-22.%PGSZ%.$tn.1 {
      sql1 {
        PRAGMA main.page_size = %PGSZ%;
        PRAGMA auto_vacuum = 0;
        PRAGMA journal_mode = WAL;
        CREATE TABLE t1(x UNIQUE);
        INSERT INTO t1 SELECT randomblob(800);
        INSERT INTO t1 SELECT randomblob(800);
        INSERT INTO t1 SELECT randomblob(800);
      }
    } {wal}
    do_test wal-22.%PGSZ%.$tn.2 { sql2 { PRAGMA integrity_check } } {ok}
    do_test wal-22.%PGSZ%.$tn.3 {
      sql1 {PRAGMA wal_checkpoint}
      expr {[file size test.db] % %PGSZ%}
    } {0}
  }]
}

#-------------------------------------------------------------------------
# Test that when 1 or more pages are recovered from a WAL file, 
# sqlite3_log() is invoked to report this to the user.
#
set walfile [file join [pwd] test.db-wal]
catch {db close}
file delete -force test.db
do_test wal-23.1 {
  faultsim_delete_and_reopen
  execsql {
    CREATE TABLE t1(a, b);
    PRAGMA journal_mode = WAL;
    INSERT INTO t1 VALUES(1, 2);
    INSERT INTO t1 VALUES(3, 4);
  }
  faultsim_save_and_close

  sqlite3_shutdown
  test_sqlite3_log [list lappend ::log]
  set ::log [list]
  sqlite3 db test.db
  execsql { SELECT * FROM t1 }
} {1 2 3 4}
do_test wal-23.2 { set ::log } {}

do_test wal-23.3 {
  db close
  set ::log [list]
  faultsim_restore_and_reopen
  execsql { SELECT * FROM t1 }
} {1 2 3 4}
do_test wal-23.4 { 
  set ::log 
} [list SQLITE_OK "Recovered 2 frames from WAL file $walfile"]

db close
sqlite3_shutdown
test_sqlite3_log
sqlite3_initialize

finish_test