Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add experimental unix-only file-control to grow and truncate the database file by a configurable chunk size. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | experimental |
Files: | files | file ages | folders |
SHA1: |
7cf0e851d4c5e826ea22ed08291b7c91 |
User & Date: | dan 2010-07-27 18:34:16.000 |
Context
2010-07-27
| ||
18:36 | Merge trunk changes into experimental branch. (check-in: 621824092d user: dan tags: experimental) | |
18:34 | Add experimental unix-only file-control to grow and truncate the database file by a configurable chunk size. (check-in: 7cf0e851d4 user: dan tags: experimental) | |
2010-07-26
| ||
16:40 | Increase the version number to 3.7.1 due to the API enhancement of the previous check-in. (check-in: 1d7571e4be user: drh tags: trunk) | |
Changes
Changes to src/os_unix.c.
︙ | ︙ | |||
206 207 208 209 210 211 212 213 214 215 216 217 218 219 | unsigned char eFileLock; /* The type of lock held on this fd */ int lastErrno; /* The unix errno from last I/O error */ void *lockingContext; /* Locking style specific state */ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ int fileFlags; /* Miscellanous flags */ const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ #if SQLITE_ENABLE_LOCKING_STYLE int openFlags; /* The flags specified at open() */ #endif #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif #if OS_VXWORKS | > | 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | unsigned char eFileLock; /* The type of lock held on this fd */ int lastErrno; /* The unix errno from last I/O error */ void *lockingContext; /* Locking style specific state */ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ 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 #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif #if OS_VXWORKS |
︙ | ︙ | |||
2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 | while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){ amt -= wrote; offset += wrote; pBuf = &((char*)pBuf)[wrote]; } SimulateIOError(( wrote=(-1), amt=1 )); SimulateDiskfullError(( wrote=0, amt=1 )); if( amt>0 ){ if( wrote<0 ){ /* lastErrno set by seekAndWrite */ return SQLITE_IOERR_WRITE; }else{ pFile->lastErrno = 0; /* not a system error */ return SQLITE_FULL; } } return SQLITE_OK; } #ifdef SQLITE_TEST /* ** Count the number of fullsyncs and normal syncs. This is used to test ** that syncs and fullsyncs are occurring at the right times. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 | while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){ amt -= wrote; offset += wrote; pBuf = &((char*)pBuf)[wrote]; } 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 */ return SQLITE_IOERR_WRITE; }else{ pFile->lastErrno = 0; /* not a system error */ return SQLITE_FULL; } } return SQLITE_OK; } #ifdef SQLITE_TEST /* ** Count the number of fullsyncs and normal syncs. This is used to test ** that syncs and fullsyncs are occurring at the right times. |
︙ | ︙ | |||
2969 2970 2971 2972 2973 2974 2975 2976 | return rc; } /* ** Truncate an open file to a specified size */ static int unixTruncate(sqlite3_file *id, i64 nByte){ int rc; | > | > > > > > > > > > > | | | | | 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 | return rc; } /* ** Truncate an open file to a specified size */ static int unixTruncate(sqlite3_file *id, i64 nByte){ unixFile *pFile = (unixFile *)id; int rc; assert( pFile ); SimulateIOError( return SQLITE_IOERR_TRUNCATE ); /* 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 ){ pFile->lastErrno = errno; return SQLITE_IOERR_TRUNCATE; }else{ #ifndef NDEBUG /* If we are doing a normal write to a database file (as opposed to ** doing a hot-journal rollback or a write to some file other than a ** normal database file) and we truncate the file to zero length, ** that effectively updates the change counter. This might happen ** when restoring a database using the backup API from a zero-length ** source. */ if( pFile->inNormalWrite && nByte==0 ){ pFile->transCntrChng = 1; } #endif return SQLITE_OK; } } |
︙ | ︙ | |||
3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 | case SQLITE_FCNTL_LOCKSTATE: { *(int*)pArg = ((unixFile*)id)->eFileLock; return SQLITE_OK; } case SQLITE_LAST_ERRNO: { *(int*)pArg = ((unixFile*)id)->lastErrno; return SQLITE_OK; } case SQLITE_FCNTL_SIZE_HINT: { #if 0 /* No performance advantage seen on Linux */ sqlite3_int64 szFile = *(sqlite3_int64*)pArg; unixFile *pFile = (unixFile*)id; ftruncate(pFile->h, szFile); #endif | > > > > | 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 | case SQLITE_FCNTL_LOCKSTATE: { *(int*)pArg = ((unixFile*)id)->eFileLock; return SQLITE_OK; } case SQLITE_LAST_ERRNO: { *(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; unixFile *pFile = (unixFile*)id; ftruncate(pFile->h, szFile); #endif |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
692 693 694 695 696 697 698 699 700 701 702 703 704 705 | ** file run faster. */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_GET_LOCKPROXYFILE 2 #define SQLITE_SET_LOCKPROXYFILE 3 #define SQLITE_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 /* ** CAPI3REF: Mutex Handle ** ** The mutex module within SQLite defines [sqlite3_mutex] to be an ** abstract type for a mutex object. The SQLite core never looks ** at the internal representation of an [sqlite3_mutex]. It only | > | 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 | ** file run faster. */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_GET_LOCKPROXYFILE 2 #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 ** ** The mutex module within SQLite defines [sqlite3_mutex] to be an ** abstract type for a mutex object. The SQLite core never looks ** at the internal representation of an [sqlite3_mutex]. It only |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 | if( iArg!=0 ) { Tcl_AppendResult(interp, "Unexpected non-zero errno: ", Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0); return TCL_ERROR; } return TCL_OK; } /* ** tclcmd: file_control_lockproxy_test DB PWD ** ** This TCL command runs the sqlite3_file_control interface and ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and ** SQLITE_SET_LOCKPROXYFILE verbs. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 | if( iArg!=0 ) { Tcl_AppendResult(interp, "Unexpected non-zero errno: ", Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0); return TCL_ERROR; } 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 ** ** This TCL command runs the sqlite3_file_control interface and ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and ** SQLITE_SET_LOCKPROXYFILE verbs. |
︙ | ︙ | |||
5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 | { "vfs_unlink_test", vfs_unlink_test, 0 }, { "vfs_initfail_test", vfs_initfail_test, 0 }, { "vfs_unregister_all", vfs_unregister_all, 0 }, { "vfs_reregister_all", vfs_reregister_all, 0 }, { "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 }, { "sqlite3_vfs_list", vfs_list, 0 }, /* Functions from os.h */ #ifndef SQLITE_OMIT_UTF16 { "add_test_collate", test_collate, 0 }, { "add_test_collate_needed", test_collate_needed, 0 }, { "add_test_function", test_function, 0 }, | > | 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 | { "vfs_unlink_test", vfs_unlink_test, 0 }, { "vfs_initfail_test", vfs_initfail_test, 0 }, { "vfs_unregister_all", vfs_unregister_all, 0 }, { "vfs_reregister_all", vfs_reregister_all, 0 }, { "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 */ #ifndef SQLITE_OMIT_UTF16 { "add_test_collate", test_collate, 0 }, { "add_test_collate_needed", test_collate_needed, 0 }, { "add_test_function", test_function, 0 }, |
︙ | ︙ |
Added test/fallocate.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 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 |