| OLD | NEW | 
 | (Empty) | 
|    1 /* |  | 
|    2 ** 2007 August 22 |  | 
|    3 ** |  | 
|    4 ** The author disclaims copyright to this source code.  In place of |  | 
|    5 ** a legal notice, here is a blessing: |  | 
|    6 ** |  | 
|    7 **    May you do good and not evil. |  | 
|    8 **    May you find forgiveness for yourself and forgive others. |  | 
|    9 **    May you share freely, never taking more than you give. |  | 
|   10 ** |  | 
|   11 ************************************************************************* |  | 
|   12 ** |  | 
|   13 ** @(#) $Id: journal.c,v 1.9 2009/01/20 17:06:27 danielk1977 Exp $ |  | 
|   14 */ |  | 
|   15  |  | 
|   16 #ifdef SQLITE_ENABLE_ATOMIC_WRITE |  | 
|   17  |  | 
|   18 /* |  | 
|   19 ** This file implements a special kind of sqlite3_file object used |  | 
|   20 ** by SQLite to create journal files if the atomic-write optimization |  | 
|   21 ** is enabled. |  | 
|   22 ** |  | 
|   23 ** The distinctive characteristic of this sqlite3_file is that the |  | 
|   24 ** actual on disk file is created lazily. When the file is created, |  | 
|   25 ** the caller specifies a buffer size for an in-memory buffer to |  | 
|   26 ** be used to service read() and write() requests. The actual file |  | 
|   27 ** on disk is not created or populated until either: |  | 
|   28 ** |  | 
|   29 **   1) The in-memory representation grows too large for the allocated  |  | 
|   30 **      buffer, or |  | 
|   31 **   2) The sqlite3JournalCreate() function is called. |  | 
|   32 */ |  | 
|   33  |  | 
|   34 #include "sqliteInt.h" |  | 
|   35  |  | 
|   36  |  | 
|   37 /* |  | 
|   38 ** A JournalFile object is a subclass of sqlite3_file used by |  | 
|   39 ** as an open file handle for journal files. |  | 
|   40 */ |  | 
|   41 struct JournalFile { |  | 
|   42   sqlite3_io_methods *pMethod;    /* I/O methods on journal files */ |  | 
|   43   int nBuf;                       /* Size of zBuf[] in bytes */ |  | 
|   44   char *zBuf;                     /* Space to buffer journal writes */ |  | 
|   45   int iSize;                      /* Amount of zBuf[] currently used */ |  | 
|   46   int flags;                      /* xOpen flags */ |  | 
|   47   sqlite3_vfs *pVfs;              /* The "real" underlying VFS */ |  | 
|   48   sqlite3_file *pReal;            /* The "real" underlying file descriptor */ |  | 
|   49   const char *zJournal;           /* Name of the journal file */ |  | 
|   50 }; |  | 
|   51 typedef struct JournalFile JournalFile; |  | 
|   52  |  | 
|   53 /* |  | 
|   54 ** If it does not already exists, create and populate the on-disk file  |  | 
|   55 ** for JournalFile p. |  | 
|   56 */ |  | 
|   57 static int createFile(JournalFile *p){ |  | 
|   58   int rc = SQLITE_OK; |  | 
|   59   if( !p->pReal ){ |  | 
|   60     sqlite3_file *pReal = (sqlite3_file *)&p[1]; |  | 
|   61     rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0); |  | 
|   62     if( rc==SQLITE_OK ){ |  | 
|   63       p->pReal = pReal; |  | 
|   64       if( p->iSize>0 ){ |  | 
|   65         assert(p->iSize<=p->nBuf); |  | 
|   66         rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); |  | 
|   67       } |  | 
|   68     } |  | 
|   69   } |  | 
|   70   return rc; |  | 
|   71 } |  | 
|   72  |  | 
|   73 /* |  | 
|   74 ** Close the file. |  | 
|   75 */ |  | 
|   76 static int jrnlClose(sqlite3_file *pJfd){ |  | 
|   77   JournalFile *p = (JournalFile *)pJfd; |  | 
|   78   if( p->pReal ){ |  | 
|   79     sqlite3OsClose(p->pReal); |  | 
|   80   } |  | 
|   81   sqlite3_free(p->zBuf); |  | 
|   82   return SQLITE_OK; |  | 
|   83 } |  | 
|   84  |  | 
|   85 /* |  | 
|   86 ** Read data from the file. |  | 
|   87 */ |  | 
|   88 static int jrnlRead( |  | 
|   89   sqlite3_file *pJfd,    /* The journal file from which to read */ |  | 
|   90   void *zBuf,            /* Put the results here */ |  | 
|   91   int iAmt,              /* Number of bytes to read */ |  | 
|   92   sqlite_int64 iOfst     /* Begin reading at this offset */ |  | 
|   93 ){ |  | 
|   94   int rc = SQLITE_OK; |  | 
|   95   JournalFile *p = (JournalFile *)pJfd; |  | 
|   96   if( p->pReal ){ |  | 
|   97     rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); |  | 
|   98   }else if( (iAmt+iOfst)>p->iSize ){ |  | 
|   99     rc = SQLITE_IOERR_SHORT_READ; |  | 
|  100   }else{ |  | 
|  101     memcpy(zBuf, &p->zBuf[iOfst], iAmt); |  | 
|  102   } |  | 
|  103   return rc; |  | 
|  104 } |  | 
|  105  |  | 
|  106 /* |  | 
|  107 ** Write data to the file. |  | 
|  108 */ |  | 
|  109 static int jrnlWrite( |  | 
|  110   sqlite3_file *pJfd,    /* The journal file into which to write */ |  | 
|  111   const void *zBuf,      /* Take data to be written from here */ |  | 
|  112   int iAmt,              /* Number of bytes to write */ |  | 
|  113   sqlite_int64 iOfst     /* Begin writing at this offset into the file */ |  | 
|  114 ){ |  | 
|  115   int rc = SQLITE_OK; |  | 
|  116   JournalFile *p = (JournalFile *)pJfd; |  | 
|  117   if( !p->pReal && (iOfst+iAmt)>p->nBuf ){ |  | 
|  118     rc = createFile(p); |  | 
|  119   } |  | 
|  120   if( rc==SQLITE_OK ){ |  | 
|  121     if( p->pReal ){ |  | 
|  122       rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); |  | 
|  123     }else{ |  | 
|  124       memcpy(&p->zBuf[iOfst], zBuf, iAmt); |  | 
|  125       if( p->iSize<(iOfst+iAmt) ){ |  | 
|  126         p->iSize = (iOfst+iAmt); |  | 
|  127       } |  | 
|  128     } |  | 
|  129   } |  | 
|  130   return rc; |  | 
|  131 } |  | 
|  132  |  | 
|  133 /* |  | 
|  134 ** Truncate the file. |  | 
|  135 */ |  | 
|  136 static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ |  | 
|  137   int rc = SQLITE_OK; |  | 
|  138   JournalFile *p = (JournalFile *)pJfd; |  | 
|  139   if( p->pReal ){ |  | 
|  140     rc = sqlite3OsTruncate(p->pReal, size); |  | 
|  141   }else if( size<p->iSize ){ |  | 
|  142     p->iSize = size; |  | 
|  143   } |  | 
|  144   return rc; |  | 
|  145 } |  | 
|  146  |  | 
|  147 /* |  | 
|  148 ** Sync the file. |  | 
|  149 */ |  | 
|  150 static int jrnlSync(sqlite3_file *pJfd, int flags){ |  | 
|  151   int rc; |  | 
|  152   JournalFile *p = (JournalFile *)pJfd; |  | 
|  153   if( p->pReal ){ |  | 
|  154     rc = sqlite3OsSync(p->pReal, flags); |  | 
|  155   }else{ |  | 
|  156     rc = SQLITE_OK; |  | 
|  157   } |  | 
|  158   return rc; |  | 
|  159 } |  | 
|  160  |  | 
|  161 /* |  | 
|  162 ** Query the size of the file in bytes. |  | 
|  163 */ |  | 
|  164 static int jrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){ |  | 
|  165   int rc = SQLITE_OK; |  | 
|  166   JournalFile *p = (JournalFile *)pJfd; |  | 
|  167   if( p->pReal ){ |  | 
|  168     rc = sqlite3OsFileSize(p->pReal, pSize); |  | 
|  169   }else{ |  | 
|  170     *pSize = (sqlite_int64) p->iSize; |  | 
|  171   } |  | 
|  172   return rc; |  | 
|  173 } |  | 
|  174  |  | 
|  175 /* |  | 
|  176 ** Table of methods for JournalFile sqlite3_file object. |  | 
|  177 */ |  | 
|  178 static struct sqlite3_io_methods JournalFileMethods = { |  | 
|  179   1,             /* iVersion */ |  | 
|  180   jrnlClose,     /* xClose */ |  | 
|  181   jrnlRead,      /* xRead */ |  | 
|  182   jrnlWrite,     /* xWrite */ |  | 
|  183   jrnlTruncate,  /* xTruncate */ |  | 
|  184   jrnlSync,      /* xSync */ |  | 
|  185   jrnlFileSize,  /* xFileSize */ |  | 
|  186   0,             /* xLock */ |  | 
|  187   0,             /* xUnlock */ |  | 
|  188   0,             /* xCheckReservedLock */ |  | 
|  189   0,             /* xFileControl */ |  | 
|  190   0,             /* xSectorSize */ |  | 
|  191   0              /* xDeviceCharacteristics */ |  | 
|  192 }; |  | 
|  193  |  | 
|  194 /*  |  | 
|  195 ** Open a journal file. |  | 
|  196 */ |  | 
|  197 int sqlite3JournalOpen( |  | 
|  198   sqlite3_vfs *pVfs,         /* The VFS to use for actual file I/O */ |  | 
|  199   const char *zName,         /* Name of the journal file */ |  | 
|  200   sqlite3_file *pJfd,        /* Preallocated, blank file handle */ |  | 
|  201   int flags,                 /* Opening flags */ |  | 
|  202   int nBuf                   /* Bytes buffered before opening the file */ |  | 
|  203 ){ |  | 
|  204   JournalFile *p = (JournalFile *)pJfd; |  | 
|  205   memset(p, 0, sqlite3JournalSize(pVfs)); |  | 
|  206   if( nBuf>0 ){ |  | 
|  207     p->zBuf = sqlite3MallocZero(nBuf); |  | 
|  208     if( !p->zBuf ){ |  | 
|  209       return SQLITE_NOMEM; |  | 
|  210     } |  | 
|  211   }else{ |  | 
|  212     return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); |  | 
|  213   } |  | 
|  214   p->pMethod = &JournalFileMethods; |  | 
|  215   p->nBuf = nBuf; |  | 
|  216   p->flags = flags; |  | 
|  217   p->zJournal = zName; |  | 
|  218   p->pVfs = pVfs; |  | 
|  219   return SQLITE_OK; |  | 
|  220 } |  | 
|  221  |  | 
|  222 /* |  | 
|  223 ** If the argument p points to a JournalFile structure, and the underlying |  | 
|  224 ** file has not yet been created, create it now. |  | 
|  225 */ |  | 
|  226 int sqlite3JournalCreate(sqlite3_file *p){ |  | 
|  227   if( p->pMethods!=&JournalFileMethods ){ |  | 
|  228     return SQLITE_OK; |  | 
|  229   } |  | 
|  230   return createFile((JournalFile *)p); |  | 
|  231 } |  | 
|  232  |  | 
|  233 /*  |  | 
|  234 ** Return the number of bytes required to store a JournalFile that uses vfs |  | 
|  235 ** pVfs to create the underlying on-disk files. |  | 
|  236 */ |  | 
|  237 int sqlite3JournalSize(sqlite3_vfs *pVfs){ |  | 
|  238   return (pVfs->szOsFile+sizeof(JournalFile)); |  | 
|  239 } |  | 
|  240 #endif |  | 
| OLD | NEW |