mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Add infrastructure to support for using F_SETLKW with a timeout on system
that support that functionality. Requires SQLITE_ENABLE_SETLK_TIMEOUT. FossilOrigin-Name: 2e54a7433ece4eb27e71bda6f2d121d5aa46ddd5a481357d8543d1432aaad689
This commit is contained in:
55
src/main.c
55
src/main.c
@@ -1476,21 +1476,38 @@ const char *sqlite3ErrStr(int rc){
|
||||
** again until a timeout value is reached. The timeout value is
|
||||
** an integer number of milliseconds passed in as the first
|
||||
** argument.
|
||||
**
|
||||
** Return non-zero to retry the lock. Return zero to stop trying
|
||||
** and cause SQLite to return SQLITE_BUSY.
|
||||
*/
|
||||
static int sqliteDefaultBusyCallback(
|
||||
void *ptr, /* Database connection */
|
||||
int count /* Number of times table has been busy */
|
||||
void *ptr, /* Database connection */
|
||||
int count, /* Number of times table has been busy */
|
||||
sqlite3_file *pFile /* The file on which the lock occurred */
|
||||
){
|
||||
#if SQLITE_OS_WIN || HAVE_USLEEP
|
||||
/* This case is for systems that have support for sleeping for fractions of
|
||||
** a second. Examples: All windows systems, unix systems with usleep() */
|
||||
static const u8 delays[] =
|
||||
{ 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 };
|
||||
static const u8 totals[] =
|
||||
{ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 };
|
||||
# define NDELAY ArraySize(delays)
|
||||
sqlite3 *db = (sqlite3 *)ptr;
|
||||
int timeout = db->busyTimeout;
|
||||
int tmout = db->busyTimeout;
|
||||
int delay, prior;
|
||||
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){
|
||||
if( count ){
|
||||
tmout = 0;
|
||||
sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout);
|
||||
return 0;
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
assert( count>=0 );
|
||||
if( count < NDELAY ){
|
||||
delay = delays[count];
|
||||
@@ -1499,16 +1516,18 @@ static int sqliteDefaultBusyCallback(
|
||||
delay = delays[NDELAY-1];
|
||||
prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));
|
||||
}
|
||||
if( prior + delay > timeout ){
|
||||
delay = timeout - prior;
|
||||
if( prior + delay > tmout ){
|
||||
delay = tmout - prior;
|
||||
if( delay<=0 ) return 0;
|
||||
}
|
||||
sqlite3OsSleep(db->pVfs, delay*1000);
|
||||
return 1;
|
||||
#else
|
||||
/* This case for unix systems that lack usleep() support. Sleeping
|
||||
** must be done in increments of whole seconds */
|
||||
sqlite3 *db = (sqlite3 *)ptr;
|
||||
int timeout = ((sqlite3 *)ptr)->busyTimeout;
|
||||
if( (count+1)*1000 > timeout ){
|
||||
int tmout = ((sqlite3 *)ptr)->busyTimeout;
|
||||
if( (count+1)*1000 > tmout ){
|
||||
return 0;
|
||||
}
|
||||
sqlite3OsSleep(db->pVfs, 1000000);
|
||||
@@ -1519,14 +1538,25 @@ static int sqliteDefaultBusyCallback(
|
||||
/*
|
||||
** Invoke the given busy handler.
|
||||
**
|
||||
** This routine is called when an operation failed with a lock.
|
||||
** This routine is called when an operation failed to acquire a
|
||||
** lock on VFS file pFile.
|
||||
**
|
||||
** If this routine returns non-zero, the lock is retried. If it
|
||||
** returns 0, the operation aborts with an SQLITE_BUSY error.
|
||||
*/
|
||||
int sqlite3InvokeBusyHandler(BusyHandler *p){
|
||||
int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){
|
||||
int rc;
|
||||
if( p->xBusyHandler==0 || p->nBusy<0 ) return 0;
|
||||
rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
|
||||
if( p->bExtraFileArg ){
|
||||
/* Add an extra parameter with the pFile pointer to the end of the
|
||||
** callback argument list */
|
||||
int (*xTra)(void*,int,sqlite3_file*);
|
||||
xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler;
|
||||
rc = xTra(p->pBusyArg, p->nBusy, pFile);
|
||||
}else{
|
||||
/* Legacy style busy handler callback */
|
||||
rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
|
||||
}
|
||||
if( rc==0 ){
|
||||
p->nBusy = -1;
|
||||
}else{
|
||||
@@ -1551,6 +1581,7 @@ int sqlite3_busy_handler(
|
||||
db->busyHandler.xBusyHandler = xBusy;
|
||||
db->busyHandler.pBusyArg = pArg;
|
||||
db->busyHandler.nBusy = 0;
|
||||
db->busyHandler.bExtraFileArg = 0;
|
||||
db->busyTimeout = 0;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return SQLITE_OK;
|
||||
@@ -1598,8 +1629,10 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
if( ms>0 ){
|
||||
sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
|
||||
sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
|
||||
(void*)db);
|
||||
db->busyTimeout = ms;
|
||||
db->busyHandler.bExtraFileArg = 1;
|
||||
}else{
|
||||
sqlite3_busy_handler(db, 0, 0);
|
||||
}
|
||||
|
Reference in New Issue
Block a user