journal.c

Go to the documentation of this file.
00001 /*
00002 ** 2007 August 22
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 *************************************************************************
00012 **
00013 ** @(#) $Id: journal.c,v 1.8 2008/05/01 18:01:47 drh Exp $
00014 */
00015 
00016 #ifdef SQLITE_ENABLE_ATOMIC_WRITE
00017 
00018 /*
00019 ** This file implements a special kind of sqlite3_file object used
00020 ** by SQLite to create journal files if the atomic-write optimization
00021 ** is enabled.
00022 **
00023 ** The distinctive characteristic of this sqlite3_file is that the
00024 ** actual on disk file is created lazily. When the file is created,
00025 ** the caller specifies a buffer size for an in-memory buffer to
00026 ** be used to service read() and write() requests. The actual file
00027 ** on disk is not created or populated until either:
00028 **
00029 **   1) The in-memory representation grows too large for the allocated 
00030 **      buffer, or
00031 **   2) The xSync() method is called.
00032 */
00033 
00034 #include "sqliteInt.h"
00035 
00036 
00037 /*
00038 ** A JournalFile object is a subclass of sqlite3_file used by
00039 ** as an open file handle for journal files.
00040 */
00041 struct JournalFile {
00042   sqlite3_io_methods *pMethod;    /* I/O methods on journal files */
00043   int nBuf;                       /* Size of zBuf[] in bytes */
00044   char *zBuf;                     /* Space to buffer journal writes */
00045   int iSize;                      /* Amount of zBuf[] currently used */
00046   int flags;                      /* xOpen flags */
00047   sqlite3_vfs *pVfs;              /* The "real" underlying VFS */
00048   sqlite3_file *pReal;            /* The "real" underlying file descriptor */
00049   const char *zJournal;           /* Name of the journal file */
00050 };
00051 typedef struct JournalFile JournalFile;
00052 
00053 /*
00054 ** If it does not already exists, create and populate the on-disk file 
00055 ** for JournalFile p.
00056 */
00057 static int createFile(JournalFile *p){
00058   int rc = SQLITE_OK;
00059   if( !p->pReal ){
00060     sqlite3_file *pReal = (sqlite3_file *)&p[1];
00061     rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0);
00062     if( rc==SQLITE_OK ){
00063       p->pReal = pReal;
00064       if( p->iSize>0 ){
00065         assert(p->iSize<=p->nBuf);
00066         rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
00067       }
00068     }
00069   }
00070   return rc;
00071 }
00072 
00073 /*
00074 ** Close the file.
00075 */
00076 static int jrnlClose(sqlite3_file *pJfd){
00077   JournalFile *p = (JournalFile *)pJfd;
00078   if( p->pReal ){
00079     sqlite3OsClose(p->pReal);
00080   }
00081   sqlite3_free(p->zBuf);
00082   return SQLITE_OK;
00083 }
00084 
00085 /*
00086 ** Read data from the file.
00087 */
00088 static int jrnlRead(
00089   sqlite3_file *pJfd,    /* The journal file from which to read */
00090   void *zBuf,            /* Put the results here */
00091   int iAmt,              /* Number of bytes to read */
00092   sqlite_int64 iOfst     /* Begin reading at this offset */
00093 ){
00094   int rc = SQLITE_OK;
00095   JournalFile *p = (JournalFile *)pJfd;
00096   if( p->pReal ){
00097     rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
00098   }else{
00099     assert( iAmt+iOfst<=p->iSize );
00100     memcpy(zBuf, &p->zBuf[iOfst], iAmt);
00101   }
00102   return rc;
00103 }
00104 
00105 /*
00106 ** Write data to the file.
00107 */
00108 static int jrnlWrite(
00109   sqlite3_file *pJfd,    /* The journal file into which to write */
00110   const void *zBuf,      /* Take data to be written from here */
00111   int iAmt,              /* Number of bytes to write */
00112   sqlite_int64 iOfst     /* Begin writing at this offset into the file */
00113 ){
00114   int rc = SQLITE_OK;
00115   JournalFile *p = (JournalFile *)pJfd;
00116   if( !p->pReal && (iOfst+iAmt)>p->nBuf ){
00117     rc = createFile(p);
00118   }
00119   if( rc==SQLITE_OK ){
00120     if( p->pReal ){
00121       rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
00122     }else{
00123       memcpy(&p->zBuf[iOfst], zBuf, iAmt);
00124       if( p->iSize<(iOfst+iAmt) ){
00125         p->iSize = (iOfst+iAmt);
00126       }
00127     }
00128   }
00129   return rc;
00130 }
00131 
00132 /*
00133 ** Truncate the file.
00134 */
00135 static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
00136   int rc = SQLITE_OK;
00137   JournalFile *p = (JournalFile *)pJfd;
00138   if( p->pReal ){
00139     rc = sqlite3OsTruncate(p->pReal, size);
00140   }else if( size<p->iSize ){
00141     p->iSize = size;
00142   }
00143   return rc;
00144 }
00145 
00146 /*
00147 ** Sync the file.
00148 */
00149 static int jrnlSync(sqlite3_file *pJfd, int flags){
00150   int rc;
00151   JournalFile *p = (JournalFile *)pJfd;
00152   if( p->pReal ){
00153     rc = sqlite3OsSync(p->pReal, flags);
00154   }else{
00155     rc = SQLITE_OK;
00156   }
00157   return rc;
00158 }
00159 
00160 /*
00161 ** Query the size of the file in bytes.
00162 */
00163 static int jrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){
00164   int rc = SQLITE_OK;
00165   JournalFile *p = (JournalFile *)pJfd;
00166   if( p->pReal ){
00167     rc = sqlite3OsFileSize(p->pReal, pSize);
00168   }else{
00169     *pSize = (sqlite_int64) p->iSize;
00170   }
00171   return rc;
00172 }
00173 
00174 /*
00175 ** Table of methods for JournalFile sqlite3_file object.
00176 */
00177 static struct sqlite3_io_methods JournalFileMethods = {
00178   1,             /* iVersion */
00179   jrnlClose,     /* xClose */
00180   jrnlRead,      /* xRead */
00181   jrnlWrite,     /* xWrite */
00182   jrnlTruncate,  /* xTruncate */
00183   jrnlSync,      /* xSync */
00184   jrnlFileSize,  /* xFileSize */
00185   0,             /* xLock */
00186   0,             /* xUnlock */
00187   0,             /* xCheckReservedLock */
00188   0,             /* xFileControl */
00189   0,             /* xSectorSize */
00190   0              /* xDeviceCharacteristics */
00191 };
00192 
00193 /* 
00194 ** Open a journal file.
00195 */
00196 int sqlite3JournalOpen(
00197   sqlite3_vfs *pVfs,         /* The VFS to use for actual file I/O */
00198   const char *zName,         /* Name of the journal file */
00199   sqlite3_file *pJfd,        /* Preallocated, blank file handle */
00200   int flags,                 /* Opening flags */
00201   int nBuf                   /* Bytes buffered before opening the file */
00202 ){
00203   JournalFile *p = (JournalFile *)pJfd;
00204   memset(p, 0, sqlite3JournalSize(pVfs));
00205   if( nBuf>0 ){
00206     p->zBuf = sqlite3MallocZero(nBuf);
00207     if( !p->zBuf ){
00208       return SQLITE_NOMEM;
00209     }
00210   }else{
00211     return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0);
00212   }
00213   p->pMethod = &JournalFileMethods;
00214   p->nBuf = nBuf;
00215   p->flags = flags;
00216   p->zJournal = zName;
00217   p->pVfs = pVfs;
00218   return SQLITE_OK;
00219 }
00220 
00221 /*
00222 ** If the argument p points to a JournalFile structure, and the underlying
00223 ** file has not yet been created, create it now.
00224 */
00225 int sqlite3JournalCreate(sqlite3_file *p){
00226   if( p->pMethods!=&JournalFileMethods ){
00227     return SQLITE_OK;
00228   }
00229   return createFile((JournalFile *)p);
00230 }
00231 
00232 /* 
00233 ** Return the number of bytes required to store a JournalFile that uses vfs
00234 ** pVfs to create the underlying on-disk files.
00235 */
00236 int sqlite3JournalSize(sqlite3_vfs *pVfs){
00237   return (pVfs->szOsFile+sizeof(JournalFile));
00238 }
00239 #endif

ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:54 2011 by Doxygen 1.6.1