1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

Add experimental unix-only file-control to grow and truncate the database file by a configurable chunk size.

FossilOrigin-Name: 7cf0e851d4c5e826ea22ed08291b7c91d7b1abc7
This commit is contained in:
dan
2010-07-27 18:34:15 +00:00
parent d2de9f4e68
commit 6e09d69c92
6 changed files with 169 additions and 25 deletions

View 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;