diff options
Diffstat (limited to 'libraries/sqlite/win32/journal.c')
-rwxr-xr-x | libraries/sqlite/win32/journal.c | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/libraries/sqlite/win32/journal.c b/libraries/sqlite/win32/journal.c new file mode 100755 index 0000000..7cbe5bc --- /dev/null +++ b/libraries/sqlite/win32/journal.c | |||
@@ -0,0 +1,238 @@ | |||
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.7 2007/09/06 13:49:37 drh 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 xSync() method 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{ | ||
99 | assert( iAmt+iOfst<=p->iSize ); | ||
100 | memcpy(zBuf, &p->zBuf[iOfst], iAmt); | ||
101 | } | ||
102 | return rc; | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | ** Write data to the file. | ||
107 | */ | ||
108 | static int jrnlWrite( | ||
109 | sqlite3_file *pJfd, /* The journal file into which to write */ | ||
110 | const void *zBuf, /* Take data to be written from here */ | ||
111 | int iAmt, /* Number of bytes to write */ | ||
112 | sqlite_int64 iOfst /* Begin writing at this offset into the file */ | ||
113 | ){ | ||
114 | int rc = SQLITE_OK; | ||
115 | JournalFile *p = (JournalFile *)pJfd; | ||
116 | if( !p->pReal && (iOfst+iAmt)>p->nBuf ){ | ||
117 | rc = createFile(p); | ||
118 | } | ||
119 | if( rc==SQLITE_OK ){ | ||
120 | if( p->pReal ){ | ||
121 | rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); | ||
122 | }else{ | ||
123 | memcpy(&p->zBuf[iOfst], zBuf, iAmt); | ||
124 | if( p->iSize<(iOfst+iAmt) ){ | ||
125 | p->iSize = (iOfst+iAmt); | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | return rc; | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | ** Truncate the file. | ||
134 | */ | ||
135 | static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ | ||
136 | int rc = SQLITE_OK; | ||
137 | JournalFile *p = (JournalFile *)pJfd; | ||
138 | if( p->pReal ){ | ||
139 | rc = sqlite3OsTruncate(p->pReal, size); | ||
140 | }else if( size<p->iSize ){ | ||
141 | p->iSize = size; | ||
142 | } | ||
143 | return rc; | ||
144 | } | ||
145 | |||
146 | /* | ||
147 | ** Sync the file. | ||
148 | */ | ||
149 | static int jrnlSync(sqlite3_file *pJfd, int flags){ | ||
150 | int rc; | ||
151 | JournalFile *p = (JournalFile *)pJfd; | ||
152 | rc = createFile(p); | ||
153 | if( rc==SQLITE_OK ){ | ||
154 | rc = sqlite3OsSync(p->pReal, flags); | ||
155 | } | ||
156 | return rc; | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | ** Query the size of the file in bytes. | ||
161 | */ | ||
162 | static int jrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){ | ||
163 | int rc = SQLITE_OK; | ||
164 | JournalFile *p = (JournalFile *)pJfd; | ||
165 | if( p->pReal ){ | ||
166 | rc = sqlite3OsFileSize(p->pReal, pSize); | ||
167 | }else{ | ||
168 | *pSize = (sqlite_int64) p->iSize; | ||
169 | } | ||
170 | return rc; | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | ** Table of methods for JournalFile sqlite3_file object. | ||
175 | */ | ||
176 | static struct sqlite3_io_methods JournalFileMethods = { | ||
177 | 1, /* iVersion */ | ||
178 | jrnlClose, /* xClose */ | ||
179 | jrnlRead, /* xRead */ | ||
180 | jrnlWrite, /* xWrite */ | ||
181 | jrnlTruncate, /* xTruncate */ | ||
182 | jrnlSync, /* xSync */ | ||
183 | jrnlFileSize, /* xFileSize */ | ||
184 | 0, /* xLock */ | ||
185 | 0, /* xUnlock */ | ||
186 | 0, /* xCheckReservedLock */ | ||
187 | 0, /* xFileControl */ | ||
188 | 0, /* xSectorSize */ | ||
189 | 0 /* xDeviceCharacteristics */ | ||
190 | }; | ||
191 | |||
192 | /* | ||
193 | ** Open a journal file. | ||
194 | */ | ||
195 | int sqlite3JournalOpen( | ||
196 | sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */ | ||
197 | const char *zName, /* Name of the journal file */ | ||
198 | sqlite3_file *pJfd, /* Preallocated, blank file handle */ | ||
199 | int flags, /* Opening flags */ | ||
200 | int nBuf /* Bytes buffered before opening the file */ | ||
201 | ){ | ||
202 | JournalFile *p = (JournalFile *)pJfd; | ||
203 | memset(p, 0, sqlite3JournalSize(pVfs)); | ||
204 | if( nBuf>0 ){ | ||
205 | p->zBuf = sqlite3MallocZero(nBuf); | ||
206 | if( !p->zBuf ){ | ||
207 | return SQLITE_NOMEM; | ||
208 | } | ||
209 | }else{ | ||
210 | return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); | ||
211 | } | ||
212 | p->pMethod = &JournalFileMethods; | ||
213 | p->nBuf = nBuf; | ||
214 | p->flags = flags; | ||
215 | p->zJournal = zName; | ||
216 | p->pVfs = pVfs; | ||
217 | return SQLITE_OK; | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | ** If the argument p points to a JournalFile structure, and the underlying | ||
222 | ** file has not yet been created, create it now. | ||
223 | */ | ||
224 | int sqlite3JournalCreate(sqlite3_file *p){ | ||
225 | if( p->pMethods!=&JournalFileMethods ){ | ||
226 | return SQLITE_OK; | ||
227 | } | ||
228 | return createFile((JournalFile *)p); | ||
229 | } | ||
230 | |||
231 | /* | ||
232 | ** Return the number of bytes required to store a JournalFile that uses vfs | ||
233 | ** pVfs to create the underlying on-disk files. | ||
234 | */ | ||
235 | int sqlite3JournalSize(sqlite3_vfs *pVfs){ | ||
236 | return (pVfs->szOsFile+sizeof(JournalFile)); | ||
237 | } | ||
238 | #endif | ||