/ Check-in [11a85b82]
Login

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

Overview
Comment:Make sure the mutex is held while calling sqlite3ApiExit() in sqlite3_wal_checkpoint(). Other cleanup of WAL logic.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wal
Files: files | file ages | folders
SHA1: 11a85b821abff1ecb7ec8c37bc7783be9fc4ea6d
User & Date: drh 2010-05-03 13:37:30
Context
2010-05-03
14:05
If the sqlite3_wal_checkpoint() API is passed a NULL pointer in place of a database name, attempt to checkpoint all attached databases. Closed-Leaf check-in: 27a5c09c user: dan tags: wal
13:37
Make sure the mutex is held while calling sqlite3ApiExit() in sqlite3_wal_checkpoint(). Other cleanup of WAL logic. check-in: 11a85b82 user: drh tags: wal
12:14
Have sqlite3_wal_checkpoint() populate the database handle error message and error code (as returned by sqlite3_errmsg() and sqlite3_errcode()). check-in: ff234cf5 user: dan tags: wal
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/main.c.

1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197





1198
1199
1200

1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213

1214
1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233

1234
1235
1236
1237
1238
1239
1240
1241



1242

1243
1244
1245
1246
1247



1248
1249
1250
1251
1252
1253
1254
....
1255
1256
1257
1258
1259
1260
1261

1262
1263
1264

1265
1266

1267
1268
1269
1270
1271
1272
1273
....
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
}

#ifndef SQLITE_OMIT_WAL
/*
** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint().
** Return non-zero, indicating to the caller that a checkpoint should be run,
** if the number of frames in the log file is greater than 

** sqlite3.nAutoCheckpoint (the value configured by wal_autocheckpoint()).
*/ 
static int defaultWalHook(void *p, sqlite3 *db, const char *z, int nFrame){
  UNUSED_PARAMETER(p);





  UNUSED_PARAMETER(z);
  return ( nFrame>=db->nAutoCheckpoint );
}


/*
** Configure an sqlite3_wal_hook() callback to automatically checkpoint
** a database after committing a transaction if there are nFrame or
** more frames in the log file. Passing zero or a negative value as the
** nFrame parameter disables automatic checkpoints entirely.
**
** The callback registered by this function replaces any existing callback
** registered using sqlite3_wal_hook(). Likewise, registering a callback
** using sqlite3_wal_hook() disables the automatic checkpoint mechanism
** configured by this function.
*/
int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){

  sqlite3_mutex_enter(db->mutex);
  if( nFrame>0 ){
    sqlite3_wal_hook(db, defaultWalHook, 0);
    db->nAutoCheckpoint = nFrame;
  }else{
    sqlite3_wal_hook(db, 0, 0);
  }
  sqlite3_mutex_leave(db->mutex);

  return SQLITE_OK;
}

/*
** Register a callback to be invoked each time a transaction is written
** into the write-ahead-log by this database connection.
*/
void *sqlite3_wal_hook(
  sqlite3 *db,                    /* Attach the hook to this db handle */
  int(*xCallback)(void *, sqlite3*, const char*, int),
  void *pArg                      /* First argument passed to xCallback() */
){

  void *pRet;
  sqlite3_mutex_enter(db->mutex);
  pRet = db->pWalArg;
  db->xWalCallback = xCallback;
  db->pWalArg = pArg;
  db->nAutoCheckpoint = 0;
  sqlite3_mutex_leave(db->mutex);
  return pRet;



}


/*
** Checkpoint database zDb. If zDb is NULL, the main database is checkpointed.
*/
int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){



  int rc;                         /* Return code */
  int iDb = 0;                    /* sqlite3.aDb[] index of db to checkpoint */

  sqlite3_mutex_enter(db->mutex);
  if( zDb ){
    iDb = sqlite3FindDbName(db, zDb);
  }
................................................................................
  if( iDb<0 ){
    rc = SQLITE_ERROR;
    sqlite3Error(db, SQLITE_ERROR, "unknown database: %s", zDb);
  }else{
    rc = sqlite3Checkpoint(db, iDb);
    sqlite3Error(db, rc, 0);
  }

  sqlite3_mutex_leave(db->mutex);

  return sqlite3ApiExit(db, rc);

}


/*
** Run a checkpoint on database iDb. This is a no-op if database iDb is
** not currently open in WAL mode.
**
** If a transaction is open at either the database handle (db) or b-tree
** level, this function returns SQLITE_LOCKED and a checkpoint is not
** attempted. If an error occurs while running the checkpoint, an SQLite
................................................................................
    sqlite3BtreeEnter(pBt);
    rc = sqlite3PagerCheckpoint(sqlite3BtreePager(pBt));
    sqlite3BtreeLeave(pBt);
  }

  return rc;
}
#else /* ifndef SQLITE_OMIT_WAL */
/*
** If SQLITE_OMIT_WAL is defined, the following API functions are no-ops:
**
**   sqlite3_wal_hook()
**   sqlite3_wal_checkpoint()
**   sqlite3_wal_autocheckpoint()
*/
void *sqlite3_wal_hook(
  sqlite3 *x,
  int(*xCallback)(void *, sqlite3*, const char*, int),
  void *pArg
){
  return 0;
}
int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ return SQLITE_OK; }
int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ return SQLITE_OK; }
#endif

/*
** This function returns true if main-memory should be used instead of
** a temporary file for transient pager files and statement journals.
** The value returned depends on the value of db->temp_store (runtime
** parameter) and the compile time value of SQLITE_TEMP_STORE. The
** following table describes the relationship between these two values







>
|

<
|
>
>
>
>
>
|
|

>













>


|
<




>












>





<


>
>
>

>





>
>
>







 







>

<
|
>


>







 







|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1187
1188
1189
1190
1191
1192
1193
1194
1195
1196

1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223

1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246

1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
....
1269
1270
1271
1272
1273
1274
1275
1276
1277

1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
....
1306
1307
1308
1309
1310
1311
1312
1313

















1314
1315
1316
1317
1318
1319
1320
}

#ifndef SQLITE_OMIT_WAL
/*
** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint().
** Return non-zero, indicating to the caller that a checkpoint should be run,
** if the number of frames in the log file is greater than 
** sqlite3.pWalArg cast to an integer (the value configured by
** wal_autocheckpoint()).
*/ 

int sqlite3WalDefaultHook(
  void *p,               /* Argument */
  sqlite3 *db,           /* Connection */
  const char *zNotUsed,  /* Database */
  int nFrame             /* Size of WAL */
){
  UNUSED_PARAMETER(zNotUsed);
  return ( nFrame>=SQLITE_PTR_TO_INT(p));
}
#endif /* SQLITE_OMIT_WAL */

/*
** Configure an sqlite3_wal_hook() callback to automatically checkpoint
** a database after committing a transaction if there are nFrame or
** more frames in the log file. Passing zero or a negative value as the
** nFrame parameter disables automatic checkpoints entirely.
**
** The callback registered by this function replaces any existing callback
** registered using sqlite3_wal_hook(). Likewise, registering a callback
** using sqlite3_wal_hook() disables the automatic checkpoint mechanism
** configured by this function.
*/
int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){
#ifndef SQLITE_OMIT_WAL
  sqlite3_mutex_enter(db->mutex);
  if( nFrame>0 ){
    sqlite3_wal_hook(db, sqlite3WalDefaultHook, SQLITE_INT_TO_PTR(nFrame));

  }else{
    sqlite3_wal_hook(db, 0, 0);
  }
  sqlite3_mutex_leave(db->mutex);
#endif
  return SQLITE_OK;
}

/*
** Register a callback to be invoked each time a transaction is written
** into the write-ahead-log by this database connection.
*/
void *sqlite3_wal_hook(
  sqlite3 *db,                    /* Attach the hook to this db handle */
  int(*xCallback)(void *, sqlite3*, const char*, int),
  void *pArg                      /* First argument passed to xCallback() */
){
#ifndef SQLITE_OMIT_WAL
  void *pRet;
  sqlite3_mutex_enter(db->mutex);
  pRet = db->pWalArg;
  db->xWalCallback = xCallback;
  db->pWalArg = pArg;

  sqlite3_mutex_leave(db->mutex);
  return pRet;
#else
  return 0;
#endif
}


/*
** Checkpoint database zDb. If zDb is NULL, the main database is checkpointed.
*/
int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
#ifdef SQLITE_OMIT_WAL
  return SQLITE_OK;
#else
  int rc;                         /* Return code */
  int iDb = 0;                    /* sqlite3.aDb[] index of db to checkpoint */

  sqlite3_mutex_enter(db->mutex);
  if( zDb ){
    iDb = sqlite3FindDbName(db, zDb);
  }
................................................................................
  if( iDb<0 ){
    rc = SQLITE_ERROR;
    sqlite3Error(db, SQLITE_ERROR, "unknown database: %s", zDb);
  }else{
    rc = sqlite3Checkpoint(db, iDb);
    sqlite3Error(db, rc, 0);
  }
  rc = sqlite3ApiExit(db, rc);
  sqlite3_mutex_leave(db->mutex);

  return rc;
#endif
}

#ifndef SQLITE_OMIT_WAL
/*
** Run a checkpoint on database iDb. This is a no-op if database iDb is
** not currently open in WAL mode.
**
** If a transaction is open at either the database handle (db) or b-tree
** level, this function returns SQLITE_LOCKED and a checkpoint is not
** attempted. If an error occurs while running the checkpoint, an SQLite
................................................................................
    sqlite3BtreeEnter(pBt);
    rc = sqlite3PagerCheckpoint(sqlite3BtreePager(pBt));
    sqlite3BtreeLeave(pBt);
  }

  return rc;
}
#endif /* SQLITE_OMIT_WAL */


















/*
** This function returns true if main-memory should be used instead of
** a temporary file for transient pager files and statement journals.
** The value returned depends on the value of db->temp_store (runtime
** parameter) and the compile time value of SQLITE_TEMP_STORE. The
** following table describes the relationship between these two values

Changes to src/pragma.c.

1420
1421
1422
1423
1424
1425
1426
1427


1428
1429
1430
1431
1432
1433
1434
  ** of N.
  */
  if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){
    if( zRight ){
      int nAuto = atoi(zRight);
      sqlite3_wal_autocheckpoint(db, nAuto);
    }
    returnSingleInt(pParse, "wal_autocheckpoint", db->nAutoCheckpoint);


  }else
#endif

#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  /*
  ** Report the current state of file logs for all databases
  */







|
>
>







1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
  ** of N.
  */
  if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){
    if( zRight ){
      int nAuto = atoi(zRight);
      sqlite3_wal_autocheckpoint(db, nAuto);
    }
    returnSingleInt(pParse, "wal_autocheckpoint", 
       db->xWalCallback==sqlite3WalDefaultHook ? 
           SQLITE_PTR_TO_INT(db->pWalArg) : 0);
  }else
#endif

#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  /*
  ** Report the current state of file logs for all databases
  */

Changes to src/sqliteInt.h.

820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
....
2996
2997
2998
2999
3000
3001
3002

3003
3004
3005
3006
3007
3008
3009
  void *pCommitArg;                 /* Argument to xCommitCallback() */   
  int (*xCommitCallback)(void*);    /* Invoked at every commit. */
  void *pRollbackArg;               /* Argument to xRollbackCallback() */   
  void (*xRollbackCallback)(void*); /* Invoked at every commit. */
  void *pUpdateArg;
  void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
#ifndef SQLITE_OMIT_WAL
  int nAutoCheckpoint;          /* Value configured by wal_autocheckpoint() */
  int (*xWalCallback)(void *, sqlite3 *, const char *, int);
  void *pWalArg;
#endif
  void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
  void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
  void *pCollNeededArg;
  sqlite3_value *pErr;          /* Most recent error message */
................................................................................
int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
int sqlite3TempInMemory(const sqlite3*);
VTable *sqlite3GetVTable(sqlite3*, Table*);
const char *sqlite3JournalModename(int);
int sqlite3Checkpoint(sqlite3*, int);


/* Declarations for functions in fkey.c. All of these are replaced by
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
** key functionality is available. If OMIT_TRIGGER is defined but
** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In
** this case foreign keys are parsed, but no other functionality is 
** provided (enforcement of FK constraints requires the triggers sub-system).







<







 







>







820
821
822
823
824
825
826

827
828
829
830
831
832
833
....
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
  void *pCommitArg;                 /* Argument to xCommitCallback() */   
  int (*xCommitCallback)(void*);    /* Invoked at every commit. */
  void *pRollbackArg;               /* Argument to xRollbackCallback() */   
  void (*xRollbackCallback)(void*); /* Invoked at every commit. */
  void *pUpdateArg;
  void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
#ifndef SQLITE_OMIT_WAL

  int (*xWalCallback)(void *, sqlite3 *, const char *, int);
  void *pWalArg;
#endif
  void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
  void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
  void *pCollNeededArg;
  sqlite3_value *pErr;          /* Most recent error message */
................................................................................
int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
int sqlite3TempInMemory(const sqlite3*);
VTable *sqlite3GetVTable(sqlite3*, Table*);
const char *sqlite3JournalModename(int);
int sqlite3Checkpoint(sqlite3*, int);
int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);

/* Declarations for functions in fkey.c. All of these are replaced by
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
** key functionality is available. If OMIT_TRIGGER is defined but
** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In
** this case foreign keys are parsed, but no other functionality is 
** provided (enforcement of FK constraints requires the triggers sub-system).