diff options
author | drh <drh@noemail.net> | 2007-08-31 16:11:35 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2007-08-31 16:11:35 +0000 |
commit | cc6bb3eaebcff254e9ddb4d0f204656cf78d107b (patch) | |
tree | a5f588f960c518cc14dbd2e5d55242ee2a499ed9 /src | |
parent | 3570ad93d8325611dc61a6f01d1c7ce0d7277c03 (diff) | |
download | sqlite-cc6bb3eaebcff254e9ddb4d0f204656cf78d107b.tar.gz sqlite-cc6bb3eaebcff254e9ddb4d0f204656cf78d107b.zip |
Initial implementation of the sqlite3_file_control() interface.
Compiles and passes all historical tests but the new method is itself
untested. (CVS 4353)
FossilOrigin-Name: d3ab3e3911f10b17d0859a34f4f007c790a0cd82
Diffstat (limited to 'src')
-rw-r--r-- | src/loadext.c | 1 | ||||
-rw-r--r-- | src/main.c | 35 | ||||
-rw-r--r-- | src/os.c | 6 | ||||
-rw-r--r-- | src/os.h | 2 | ||||
-rw-r--r-- | src/os_unix.c | 17 | ||||
-rw-r--r-- | src/os_win.c | 6 | ||||
-rw-r--r-- | src/pager.c | 11 | ||||
-rw-r--r-- | src/pager.h | 3 | ||||
-rw-r--r-- | src/sqlite.h.in | 44 | ||||
-rw-r--r-- | src/sqlite3ext.h | 4 | ||||
-rw-r--r-- | src/test6.c | 6 |
11 files changed, 107 insertions, 28 deletions
diff --git a/src/loadext.c b/src/loadext.c index 2f0e81f77..2ae3aabe8 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -256,6 +256,7 @@ const sqlite3_api_routines sqlite3_apis = { sqlite3_blob_read, sqlite3_blob_write, sqlite3_create_collation_v2, + sqlite3_file_control, sqlite3_memory_highwater, sqlite3_memory_used, #ifdef SQLITE_MUTEX_NOOP diff --git a/src/main.c b/src/main.c index eda460fd8..a6db28352 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.400 2007/08/30 20:09:48 drh Exp $ +** $Id: main.c,v 1.401 2007/08/31 16:11:36 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -1432,3 +1432,36 @@ int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } + +/* +** Invoke the xFileControl method on a particular database. +*/ +int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ + int rc = SQLITE_ERROR; + int iDb; + sqlite3_mutex_enter(db->mutex); + if( zDbName==0 ){ + iDb = 0; + }else{ + for(iDb=0; iDb<db->nDb; iDb++){ + if( strcmp(db->aDb[iDb].zName, zDbName)==0 ) break; + } + } + if( iDb<db->nDb ){ + Btree *pBtree = db->aDb[iDb].pBt; + if( pBtree ){ + Pager *pPager; + sqlite3BtreeEnter(pBtree); + pPager = sqlite3BtreePager(pBtree); + if( pPager ){ + sqlite3_file *fd = sqlite3PagerFile(pPager); + if( fd ){ + rc = sqlite3OsFileControl(fd, op, pArg); + } + } + sqlite3BtreeLeave(pBtree); + } + } + sqlite3_mutex_leave(db->mutex); + return rc; +} @@ -52,12 +52,12 @@ int sqlite3OsLock(sqlite3_file *id, int lockType){ int sqlite3OsUnlock(sqlite3_file *id, int lockType){ return id->pMethods->xUnlock(id, lockType); } -int sqlite3OsBreakLock(sqlite3_file *id){ - return id->pMethods->xBreakLock(id); -} int sqlite3OsCheckReservedLock(sqlite3_file *id){ return id->pMethods->xCheckReservedLock(id); } +int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ + return id->pMethods->xFileControl(id,op,pArg); +} #ifdef SQLITE_TEST /* The following two variables are used to override the values returned @@ -239,9 +239,9 @@ int sqlite3OsSync(sqlite3_file*, int); int sqlite3OsFileSize(sqlite3_file*, i64 *pSize); int sqlite3OsLock(sqlite3_file*, int); int sqlite3OsUnlock(sqlite3_file*, int); -int sqlite3OsBreakLock(sqlite3_file*); int sqlite3OsCheckReservedLock(sqlite3_file *id); int sqlite3OsLockState(sqlite3_file *id); +int sqlite3OsFileControl(sqlite3_file*,int,void*); int sqlite3OsSectorSize(sqlite3_file *id); int sqlite3OsDeviceCharacteristics(sqlite3_file *id); diff --git a/src/os_unix.c b/src/os_unix.c index c46d82407..54674f7c7 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -2016,11 +2016,10 @@ static int nolockUnixClose(sqlite3_file *id) { /* -** TODO: xBreakLock() for this vfs. +** No xFileControl opcodes are implemented by this VFS. */ -static int unixBreakLock(sqlite3_file *id){ - assert(!"TODO: unixBreakLock()"); - return 0; +static int unixFileControl(sqlite3_file *id, int op, void *pArg){ + return SQLITE_ERROR; } /* @@ -2067,8 +2066,8 @@ static const sqlite3_io_methods sqlite3UnixIoMethod = { unixLock, unixUnlock, unixCheckReservedLock, - unixBreakLock, unixLockState, + unixFileControl, unixSectorSize, unixDeviceCharacteristics }; @@ -2089,8 +2088,8 @@ static const sqlite3_io_methods sqlite3AFPLockingUnixIoMethod = { afpUnixLock, afpUnixUnlock, afpUnixCheckReservedLock, - unixBreakLock, unixLockState, + unixFileControl, unixSectorSize, unixDeviceCharacteristics }; @@ -2110,8 +2109,8 @@ static const sqlite3_io_methods sqlite3FlockLockingUnixIoMethod = { flockUnixLock, flockUnixUnlock, flockUnixCheckReservedLock, - unixBreakLock, unixLockState, + unixFileControl, unixSectorSize, unixDeviceCharacteristics }; @@ -2131,8 +2130,8 @@ static const sqlite3_io_methods sqlite3DotlockLockingUnixIoMethod = { dotlockUnixLock, dotlockUnixUnlock, dotlockUnixCheckReservedLock, - unixBreakLock, unixLockState, + unixFileControl, unixSectorSize, unixDeviceCharacteristics }; @@ -2152,8 +2151,8 @@ static const sqlite3_io_methods sqlite3NolockLockingUnixIoMethod = { nolockUnixLock, nolockUnixUnlock, nolockUnixCheckReservedLock, - unixBreakLock, unixLockState, + unixFileControl, unixSectorSize, unixDeviceCharacteristics }; diff --git a/src/os_win.c b/src/os_win.c index 0cd6a24f6..233195f0f 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -977,9 +977,9 @@ static int winUnlock(sqlite3_file *id, int locktype){ } /* -** Currently unimplemented +** No xFileControl operations are currently implemented. */ -static int winBreakLock(sqlite3_file *id){ +static int winFileControl(sqlite3_file *id){ return SQLITE_ERROR; } @@ -1028,8 +1028,8 @@ static const sqlite3_io_methods winIoMethod = { winLock, winUnlock, winCheckReservedLock, - winBreakLock, winLockState, + winFileControl, winSectorSize, winDeviceCharacteristics }; diff --git a/src/pager.c b/src/pager.c index fd364ae51..59ef3e804 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.381 2007/08/30 08:08:17 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.382 2007/08/31 16:11:36 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -4823,6 +4823,15 @@ const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){ } /* +** Return the file handle for the database file associated +** with the pager. This might return NULL if the file has +** not yet been opened. +*/ +sqlite3_file *sqlite3PagerFile(Pager *pPager){ + return pPager->fd; +} + +/* ** Return the directory of the database file. */ const char *sqlite3PagerDirname(Pager *pPager){ diff --git a/src/pager.h b/src/pager.h index 7402dd74e..4933d0069 100644 --- a/src/pager.h +++ b/src/pager.h @@ -13,7 +13,7 @@ ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.64 2007/08/29 12:31:27 danielk1977 Exp $ +** @(#) $Id: pager.h,v 1.65 2007/08/31 16:11:36 drh Exp $ */ #ifndef _PAGER_H_ @@ -86,6 +86,7 @@ int sqlite3PagerRefcount(Pager*); void sqlite3PagerSetSafetyLevel(Pager*,int,int); const char *sqlite3PagerFilename(Pager*); const sqlite3_vfs *sqlite3PagerVfs(Pager*); +sqlite3_file *sqlite3PagerFile(Pager*); const char *sqlite3PagerDirname(Pager*); const char *sqlite3PagerJournalname(Pager*); int sqlite3PagerNosync(Pager*); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 780fb87bc..4ec7226da 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -30,7 +30,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.251 2007/08/30 20:09:48 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.252 2007/08/31 16:11:36 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -472,9 +472,20 @@ struct sqlite3_file { ** PENDING, or EXCLUSIVE lock on the file. It returns true ** if such a lock exists and false if not. ** -** xBreakLock() attempts to break a lock held by another process. -** This can be used to remove a stale dot-file lock, for example. -** It returns 0 on success and non-zero for a failure. +** The xFileControl() method is a generic interface that allows custom +** VFS implementations to directly control an open file using the +** [sqlite3_file_control()] interface. The second argument (the +** "op" argument) is intended to be an integer opcode. The third +** argument is a generic pointer which is intended to be a pointer +** to a structure that may contain arguments or space in which to +** write return values. Potential uses for xFileControl() might be +** functions to enable blocking locks with timeouts, to change the +** locking strategy (for example to use dot-file locks), to inquire +** about the status of a lock, or to break stale locks. No standard +** xFileControl opcodes are currently defined, but this may change in +** future releases. Applications that define a custom xFileControl +** method should use opcodes greater than 100 to avoid conflicts +** with future official opcodes which will be less than that value. ** ** The xSectorSize() method returns the sector size of the ** device that underlies the file. The sector size is the @@ -520,8 +531,8 @@ struct sqlite3_io_methods { int (*xLock)(sqlite3_file*, int); int (*xUnlock)(sqlite3_file*, int); int (*xCheckReservedLock)(sqlite3_file*); - int (*xBreakLock)(sqlite3_file*); int (*xLockState)(sqlite3_file *); + int (*xFileControl)(sqlite3_file*, int op, void *pArg); int (*xSectorSize)(sqlite3_file*); int (*xDeviceCharacteristics)(sqlite3_file*); /* Additional methods may be added in future releases */ @@ -3438,6 +3449,29 @@ int sqlite3_mutex_notheld(sqlite3_mutex*); #define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ #define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ +/* +** CAPI3REF: Low-Level Control Of Database Files +** +** The [sqlite3_file_control()] interface makes a direct call to the +** xFileControl method for the [sqlite3_io_methods] object associated +** with a particular database identified by the second argument. The +** name of the database is the name assigned to the database by the +** <a href="lang_attach.html">ATTACH</a> SQL command that opened the +** database. To control the main database file, use the name "main" +** or a NULL pointer. The third and fourth parameters to this routine +** are passed directly through to the second and third parameters of +** the xFileControl method. The return value of the xFileControl +** method becomes the return value of this routine. +** +** If the second parameter (zDbName) does not match the name of any +** open database file, then SQLITE_ERROR is returned. This error +** code is not remembered and will not be recalled by [sqlite3_errcode()] +** or [sqlite3_errmsg()]. The underlying xFileControl method might +** also return SQLITE_ERROR. There is no way to distinguish between +** an incorrect zDbName and an SQLITE_ERROR return from the underlying +** xFileControl method. +*/ +int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); /* ** Undo the hack that converts floating point types to integer for diff --git a/src/sqlite3ext.h b/src/sqlite3ext.h index 667650aca..5d4c2dec9 100644 --- a/src/sqlite3ext.h +++ b/src/sqlite3ext.h @@ -15,7 +15,7 @@ ** as extensions by SQLite should #include this file instead of ** sqlite3.h. ** -** @(#) $Id: sqlite3ext.h,v 1.16 2007/08/30 17:15:38 drh Exp $ +** @(#) $Id: sqlite3ext.h,v 1.17 2007/08/31 16:11:36 drh Exp $ */ #ifndef _SQLITE3EXT_H_ #define _SQLITE3EXT_H_ @@ -165,6 +165,7 @@ struct sqlite3_api_routines { int (*blob_read)(sqlite3_blob*,void*,int,int); int (*blob_write)(sqlite3_blob*,const void*,int,int); int (*create_collation_v2)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*),void(*)(void*)); + int (*file_control)(sqlite3*,const char*,int,void*); sqlite3_int64 (*memory_highwater)(int); sqlite3_int64 (*memory_used)(void); sqlite3_mutex *(*mutex_alloc)(int); @@ -324,6 +325,7 @@ struct sqlite3_api_routines { #define sqlite3_blob_read sqlite3_api->blob_read #define sqlite3_blob_write sqlite3_api->blob_write #define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2 +#define sqlite3_file_control sqlite3_api->file_control #define sqlite3_memory_highwater sqlite3_api->memory_highwater #define sqlite3_memory_used sqlite3_api->memory_used #define sqlite3_mutex_alloc sqlite3_api->mutex_alloc diff --git a/src/test6.c b/src/test6.c index 6747fb613..5d47cc79c 100644 --- a/src/test6.c +++ b/src/test6.c @@ -476,8 +476,8 @@ static int cfCheckReservedLock(sqlite3_file *pFile){ static int cfLockState(sqlite3_file *pFile){ return sqlite3OsLockState(((CrashFile *)pFile)->pRealFile); } -static int cfBreakLock(sqlite3_file *pFile){ - return sqlite3OsBreakLock(((CrashFile *)pFile)->pRealFile); +static int cfFileControl(sqlite3_file *pFile, int op, void *pArg){ + return sqlite3OsFileControl(((CrashFile *)pFile)->pRealFile, op, pArg); } /* @@ -503,8 +503,8 @@ static const sqlite3_io_methods CrashFileVtab = { cfLock, /* xLock */ cfUnlock, /* xUnlock */ cfCheckReservedLock, /* xCheckReservedLock */ - cfBreakLock, /* xBreakLock */ cfLockState, /* xLockState */ + cfFileControl, /* xFileControl */ cfSectorSize, /* xSectorSize */ cfDeviceCharacteristics /* xDeviceCharacteristics */ }; |