diff options
-rw-r--r-- | manifest | 32 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/os_unix.c | 64 | ||||
-rw-r--r-- | src/sqlite.h.in | 1 | ||||
-rw-r--r-- | src/test1.c | 39 | ||||
-rw-r--r-- | test/fallocate.test | 56 |
6 files changed, 169 insertions, 25 deletions
@@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Increase\sthe\sversion\snumber\sto\s3.7.1\sdue\sto\sthe\sAPI\senhancement\sof\sthe\sprevious\ncheck-in. -D 2010-07-26T16:40:04 +C Add\sexperimental\sunix-only\sfile-control\sto\sgrow\sand\struncate\sthe\sdatabase\sfile\sby\sa\sconfigurable\schunk\ssize. +D 2010-07-27T18:34:16 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -157,7 +154,7 @@ F src/os.c 60178f518c4d6c0dcb59f7292232281d7bea2dcf F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9 F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e -F src/os_unix.c 3109e0e5a0d5551bab2e8c7322b20a3b8b171248 +F src/os_unix.c 77e963fbbed6a2ca9b7c9115ae06f05181729490 F src/os_win.c 1f8b0a1a5bcf6289e7754d0d3c16cec16d4c93ab F src/pager.c 78ca1e1f3315c8227431c403c04d791dccf242fb F src/pager.h 879fdde5a102d2f21a3135d6f647530b21c2796c @@ -173,14 +170,14 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/select.c 74fef1334bec27e606ef0b19e5c41cd0a639e69c F src/shell.c fd4ccdb37c3b68de0623eb938a649e0990710714 -F src/sqlite.h.in e789728101d821fd4307208aa11e332e51eedbf9 +F src/sqlite.h.in 3b201a7aced2227339c2bba8dfbee47a823d43ad F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89 F src/sqliteInt.h a9be6badc6cd6a3c1ae54475a98661cf351ecad5 F src/sqliteLimit.h 196e2f83c3b444c4548fc1874f52f84fdbda40f3 F src/status.c 51f65ba9768846c071fa621624d55d6866fce28b F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/tclsqlite.c ae1e4fb653c91ddad7e2534d209711a12604ccc4 -F src/test1.c ff3b4533fc4d78d1bff2ef831a5791db55096ed3 +F src/test1.c 0bfcda72f9f8ab5c0e90fac05cc22c1c21131ddf F src/test2.c e3f564ab1e9fd0b47b0c9e23e7054e38bf0836cf F src/test3.c 4c21700c73a890a47fc685c1097bfb661346ac94 F src/test4.c 0528360b5025688002a5feb6be906ddce52eaaee @@ -354,6 +351,7 @@ F test/exclusive.test 5fe18e10a159342dd52ca14b1554e33f98734267 F test/exclusive2.test fcbb1c9ca9739292a0a22a3763243ad6d868086b F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7 F test/expr.test 9f521ae22f00e074959f72ce2e55d46b9ed23f68 +F test/fallocate.test 2aa524a237893aca5b2a7ad5d450ee4801b4abdd F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e F test/filefmt.test 5d271bf467e6557fe7499dcc8203069c9dc5825e F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da @@ -841,14 +839,10 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 008368b2bd1513e2df21c2070548c6fc94abebb1 -R e0e547721eadb5865947ac95d9a5637b -U drh -Z b2f076ca75f409c11b1173e904fc1e43 ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFMTbpnoxKgR168RlERAgRsAKCEDv9PrVdoUqb+GgrX9p308vOjrgCgi4/A -Wv1UV7AZmSjiGasHOtjRZXM= -=082N ------END PGP SIGNATURE----- +P 1d7571e4be6d96aec13cd8b3b7b10b8dc44d19a5 +R 06d24f984109c26ad9ccb04075848e30 +T *branch * experimental +T *sym-experimental * +T -sym-trunk * +U dan +Z 84d3b6ef35de3d3ded4f7f20ba0de5c7 diff --git a/manifest.uuid b/manifest.uuid index 2e3613187..e26c476d9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1d7571e4be6d96aec13cd8b3b7b10b8dc44d19a5
\ No newline at end of file +7cf0e851d4c5e826ea22ed08291b7c91d7b1abc7
\ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 9457516ca..467409b19 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -210,6 +210,7 @@ struct unixFile { int fileFlags; /* Miscellanous flags */ const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ + int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ #if SQLITE_ENABLE_LOCKING_STYLE int openFlags; /* The flags specified at open() */ #endif @@ -2763,6 +2764,43 @@ static int unixWrite( } SimulateIOError(( wrote=(-1), amt=1 )); SimulateDiskfullError(( wrote=0, amt=1 )); + + /* If the user has configured a chunk-size for this file, it could be + ** that the file needs to be extended at this point. + */ + if( pFile->szChunk && amt==0 ){ + i64 nSize; /* Required file size */ + struct stat buf; /* Used to hold return values of fstat() */ + int rc = fstat(pFile->h, &buf); + if( rc!=0 ) return SQLITE_IOERR_FSTAT; + nSize = ((offset+amt+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk; + if( nSize>(i64)buf.st_size ){ +#ifdef HAVE_POSIX_FALLOCATE + if( posix_fallocate(pFile->h, buf.st_size, nSize-buf.st_size) ){ + return SQLITE_IOERR_WRITE; + } +#else + /* If the OS does not have posix_fallocate(), fake it. First use + ** ftruncate() to set the file size, then write a single byte to + ** the last byte in each block within the extended region. + */ + int nBlk = buf.st_blksize; /* File-system block size */ + i64 iWrite; /* Next offset to write to */ + + if( ftruncate(pFile->h, nSize) ){ + pFile->lastErrno = errno; + return SQLITE_IOERR_TRUNCATE; + } + iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1; + do { + wrote = seekAndWrite(pFile, iWrite, "", 1); + iWrite += nBlk; + } while( wrote==1 && iWrite<nSize ); + if( wrote!=1 ) amt = 1; +#endif + } + } + if( amt>0 ){ if( wrote<0 ){ /* lastErrno set by seekAndWrite */ @@ -2772,6 +2810,7 @@ static int unixWrite( return SQLITE_FULL; } } + return SQLITE_OK; } @@ -2973,12 +3012,23 @@ static int unixSync(sqlite3_file *id, int flags){ ** Truncate an open file to a specified size */ static int unixTruncate(sqlite3_file *id, i64 nByte){ + unixFile *pFile = (unixFile *)id; int rc; - assert( id ); + assert( pFile ); SimulateIOError( return SQLITE_IOERR_TRUNCATE ); - rc = ftruncate(((unixFile*)id)->h, (off_t)nByte); + + /* If the user has configured a chunk-size for this file, truncate the + ** file so that it consists of an integer number of chunks (i.e. the + ** actual file size after the operation may be larger than the requested + ** size). + */ + if( pFile->szChunk ){ + nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; + } + + rc = ftruncate(pFile->h, (off_t)nByte); if( rc ){ - ((unixFile*)id)->lastErrno = errno; + pFile->lastErrno = errno; return SQLITE_IOERR_TRUNCATE; }else{ #ifndef NDEBUG @@ -2989,8 +3039,8 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){ ** when restoring a database using the backup API from a zero-length ** source. */ - if( ((unixFile*)id)->inNormalWrite && nByte==0 ){ - ((unixFile*)id)->transCntrChng = 1; + if( pFile->inNormalWrite && nByte==0 ){ + pFile->transCntrChng = 1; } #endif @@ -3047,6 +3097,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ *(int*)pArg = ((unixFile*)id)->lastErrno; return SQLITE_OK; } + case SQLITE_FCNTL_CHUNK_SIZE: { + ((unixFile*)id)->szChunk = *(int *)pArg; + return SQLITE_OK; + } case SQLITE_FCNTL_SIZE_HINT: { #if 0 /* No performance advantage seen on Linux */ sqlite3_int64 szFile = *(sqlite3_int64*)pArg; diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 89bcf1c40..ca0ea5dd4 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -696,6 +696,7 @@ struct sqlite3_io_methods { #define SQLITE_SET_LOCKPROXYFILE 3 #define SQLITE_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 +#define SQLITE_FCNTL_CHUNK_SIZE 6 /* ** CAPI3REF: Mutex Handle diff --git a/src/test1.c b/src/test1.c index 33ac7a1bd..acb812b37 100644 --- a/src/test1.c +++ b/src/test1.c @@ -4614,6 +4614,44 @@ static int file_control_lasterrno_test( } /* +** tclcmd: file_control_chunksize_test DB DBNAME SIZE +** +** This TCL command runs the sqlite3_file_control interface and +** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and +** SQLITE_SET_LOCKPROXYFILE verbs. +*/ +static int file_control_chunksize_test( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + int nSize; /* New chunk size */ + char *zDb; /* Db name ("main", "temp" etc.) */ + sqlite3 *db; /* Database handle */ + int rc; /* file_control() return code */ + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) + || Tcl_GetIntFromObj(interp, objv[3], &nSize) + ){ + return TCL_ERROR; + } + zDb = Tcl_GetString(objv[2]); + if( zDb[0]=='\0' ) zDb = NULL; + + rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize); + if( rc ){ + Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC); + return TCL_ERROR; + } + return TCL_OK; +} + +/* ** tclcmd: file_control_lockproxy_test DB PWD ** ** This TCL command runs the sqlite3_file_control interface and @@ -5106,6 +5144,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "file_control_test", file_control_test, 0 }, { "file_control_lasterrno_test", file_control_lasterrno_test, 0 }, { "file_control_lockproxy_test", file_control_lockproxy_test, 0 }, + { "file_control_chunksize_test", file_control_chunksize_test, 0 }, { "sqlite3_vfs_list", vfs_list, 0 }, /* Functions from os.h */ diff --git a/test/fallocate.test b/test/fallocate.test new file mode 100644 index 000000000..b9c4f460d --- /dev/null +++ b/test/fallocate.test @@ -0,0 +1,56 @@ +# 2010 July 28 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +if {$::tcl_platform(platform)!="unix"} { + finish_test + return +} + +file_control_chunksize_test db main [expr 1024*1024] + +do_test fallocate-1.1 { + execsql { + PRAGMA page_size = 1024; + PRAGMA auto_vacuum = 1; + CREATE TABLE t1(a, b); + } + file size test.db +} [expr 1*1024*1024] + +do_test fallocate-1.2 { + execsql { INSERT INTO t1 VALUES(1, zeroblob(1024*900)) } + file size test.db +} [expr 1*1024*1024] + +do_test fallocate-1.3 { + execsql { INSERT INTO t1 VALUES(2, zeroblob(1024*900)) } + file size test.db +} [expr 2*1024*1024] + +do_test fallocate-1.4 { + execsql { DELETE FROM t1 WHERE a = 1 } + file size test.db +} [expr 1*1024*1024] + +do_test fallocate-1.5 { + execsql { DELETE FROM t1 WHERE a = 2 } + file size test.db +} [expr 1*1024*1024] + +do_test fallocate-1.6 { + execsql { PRAGMA freelist_count } +} {0} + +finish_test |