]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add experimental unix-only file-control to grow and truncate the database file by...
authordan <dan@noemail.net>
Tue, 27 Jul 2010 18:34:15 +0000 (18:34 +0000)
committerdan <dan@noemail.net>
Tue, 27 Jul 2010 18:34:15 +0000 (18:34 +0000)
FossilOrigin-Name: 7cf0e851d4c5e826ea22ed08291b7c91d7b1abc7

manifest
manifest.uuid
src/os_unix.c
src/sqlite.h.in
src/test1.c
test/fallocate.test [new file with mode: 0644]

index a21c43a05808ff82967a336c48ca457438723071..167b5239a5378c45cb8bd09fcf2f44e5190ba56c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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
index 2e3613187400eaa18f47d9618c7dadaf77a83d2d..e26c476d95912752ee78d62c2bf0faf0df8962f4 100644 (file)
@@ -1 +1 @@
-1d7571e4be6d96aec13cd8b3b7b10b8dc44d19a5
\ No newline at end of file
+7cf0e851d4c5e826ea22ed08291b7c91d7b1abc7
\ No newline at end of file
index 9457516cac0b8225a175a43d54eabc11a82fbd66..467409b198ec51416294dc5a58e6c6e686a40fb8 100644 (file)
@@ -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;
index 89bcf1c4003f5228d3f67c356743eed51c11101a..ca0ea5dd4b1bb78a68296d28032e4d96f969ced1 100644 (file)
@@ -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
index 33ac7a1bd45e4ab5a1f054e8533d71673f6dca6f..acb812b372e33ac90702c2b8865d8828980b3080 100644 (file)
@@ -4613,6 +4613,44 @@ static int file_control_lasterrno_test(
   return TCL_OK;  
 }
 
+/*
+** 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
 **
@@ -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 (file)
index 0000000..b9c4f46
--- /dev/null
@@ -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