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