Directory: | cvmfs/ |
---|---|
File: | cvmfs/sqlitevfs.cc |
Date: | 2025-06-29 02:35:41 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 123 | 215 | 57.2% |
Branches: | 71 | 180 | 39.4% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /** | ||
2 | * This file is part of the CernVM File System. | ||
3 | * | ||
4 | * An optimized virtual file system layer for the client only. It expects to | ||
5 | * operate on immutable, valid SQlite files. Hence it can do a few | ||
6 | * optimizations. Most notably it doesn't need to know about the path of | ||
7 | * the SQlite file once opened. It works purely on the file descriptor. | ||
8 | */ | ||
9 | |||
10 | #ifndef __STDC_FORMAT_MACROS | ||
11 | #define __STDC_FORMAT_MACROS | ||
12 | #endif | ||
13 | |||
14 | |||
15 | #include "sqlitevfs.h" | ||
16 | |||
17 | #include <dlfcn.h> | ||
18 | #include <errno.h> | ||
19 | #include <fcntl.h> | ||
20 | #include <inttypes.h> | ||
21 | #include <stdint.h> | ||
22 | #include <sys/select.h> | ||
23 | #include <sys/time.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <sys/uio.h> | ||
26 | #include <unistd.h> | ||
27 | |||
28 | #include <cassert> | ||
29 | #include <climits> | ||
30 | #include <cstring> | ||
31 | #include <ctime> | ||
32 | #include <vector> | ||
33 | |||
34 | #include "cache.h" | ||
35 | #include "duplex_sqlite3.h" | ||
36 | #include "statistics.h" | ||
37 | #include "util/logging.h" | ||
38 | #include "util/platform.h" | ||
39 | #include "util/smalloc.h" | ||
40 | #include "util/string.h" | ||
41 | |||
42 | using namespace std; // NOLINT | ||
43 | |||
44 | namespace sqlite { | ||
45 | |||
46 | namespace { | ||
47 | |||
48 | const char *kVfsName = "cvmfs-readonly"; | ||
49 | |||
50 | /** | ||
51 | * The private user data attached to the sqlite_vfs object. | ||
52 | */ | ||
53 | struct VfsRdOnly { | ||
54 | 1659 | VfsRdOnly() | |
55 | 1659 | : cache_mgr(NULL) | |
56 | 1659 | , n_access(NULL) | |
57 | 1659 | , no_open(NULL) | |
58 | 1659 | , n_rand(NULL) | |
59 | 1659 | , sz_rand(NULL) | |
60 | 1659 | , n_read(NULL) | |
61 | 1659 | , sz_read(NULL) | |
62 | 1659 | , n_sleep(NULL) | |
63 | 1659 | , sz_sleep(NULL) | |
64 | 1659 | , n_time(NULL) { } | |
65 | CacheManager *cache_mgr; | ||
66 | perf::Counter *n_access; | ||
67 | perf::Counter *no_open; | ||
68 | perf::Counter *n_rand; | ||
69 | perf::Counter *sz_rand; | ||
70 | perf::Counter *n_read; | ||
71 | perf::Counter *sz_read; | ||
72 | perf::Counter *n_sleep; | ||
73 | perf::Counter *sz_sleep; | ||
74 | perf::Counter *n_time; | ||
75 | }; | ||
76 | |||
77 | /** | ||
78 | * This is passed to all operations once a file is opened. | ||
79 | */ | ||
80 | struct VfsRdOnlyFile { | ||
81 | sqlite3_file base; // Base class. Must be first. | ||
82 | VfsRdOnly *vfs_rdonly; | ||
83 | int fd; | ||
84 | uint64_t size; | ||
85 | }; | ||
86 | |||
87 | /** | ||
88 | * File descriptor mappings | ||
89 | */ | ||
90 | std::vector<int> *fd_from_ = NULL; | ||
91 | std::vector<int> *fd_to_ = NULL; | ||
92 | |||
93 | } // anonymous namespace | ||
94 | |||
95 | 8990 | static void ApplyFdMap(VfsRdOnlyFile *pFile) { | |
96 | 8990 | const unsigned N = fd_from_->size(); | |
97 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8990 times.
|
8990 | for (unsigned i = 0; i < N; ++i) { |
98 | ✗ | if (pFile->fd == (*fd_from_)[i]) { | |
99 | ✗ | LogCvmfs(kLogSql, kLogDebug, "map fd %d --> %d", (*fd_from_)[i], | |
100 | ✗ | (*fd_to_)[i]); | |
101 | ✗ | pFile->fd = (*fd_to_)[i]; | |
102 | ✗ | fd_from_->erase(fd_from_->begin() + i); | |
103 | ✗ | fd_to_->erase(fd_to_->begin() + i); | |
104 | ✗ | return; | |
105 | } | ||
106 | } | ||
107 | } | ||
108 | |||
109 | |||
110 | 785 | static int VfsRdOnlyClose(sqlite3_file *pFile) { | |
111 | 785 | VfsRdOnlyFile *p = reinterpret_cast<VfsRdOnlyFile *>(pFile); | |
112 | 785 | ApplyFdMap(p); | |
113 | 785 | const int retval = p->vfs_rdonly->cache_mgr->Close(p->fd); | |
114 |
1/2✓ Branch 0 taken 785 times.
✗ Branch 1 not taken.
|
785 | if (retval == 0) { |
115 | 785 | perf::Dec(p->vfs_rdonly->no_open); | |
116 | 785 | return SQLITE_OK; | |
117 | } | ||
118 | ✗ | return SQLITE_IOERR_CLOSE; | |
119 | } | ||
120 | |||
121 | |||
122 | /** | ||
123 | * On a short read, the remaining bytes must be zero'ed. | ||
124 | * TODO(jblomer): the reads seem to be rather small. Investigate buffered read. | ||
125 | */ | ||
126 | 8205 | static int VfsRdOnlyRead(sqlite3_file *pFile, | |
127 | void *zBuf, | ||
128 | int iAmt, | ||
129 | sqlite_int64 iOfst) { | ||
130 | 8205 | VfsRdOnlyFile *p = reinterpret_cast<VfsRdOnlyFile *>(pFile); | |
131 | 8205 | ApplyFdMap(p); | |
132 | 8205 | const ssize_t got = p->vfs_rdonly->cache_mgr->Pread(p->fd, zBuf, iAmt, iOfst); | |
133 | 8205 | perf::Inc(p->vfs_rdonly->n_read); | |
134 |
1/2✓ Branch 0 taken 8205 times.
✗ Branch 1 not taken.
|
8205 | if (got == iAmt) { |
135 | 8205 | perf::Xadd(p->vfs_rdonly->sz_read, iAmt); | |
136 | 8205 | return SQLITE_OK; | |
137 | ✗ | } else if (got < 0) { | |
138 | ✗ | return SQLITE_IOERR_READ; | |
139 | } else { | ||
140 | ✗ | perf::Xadd(p->vfs_rdonly->sz_read, got); | |
141 | ✗ | memset(reinterpret_cast<char *>(zBuf) + got, 0, iAmt - got); | |
142 | ✗ | return SQLITE_IOERR_SHORT_READ; | |
143 | } | ||
144 | } | ||
145 | |||
146 | |||
147 | ✗ | static int VfsRdOnlyWrite(sqlite3_file *pFile __attribute__((unused)), | |
148 | const void *zBuf __attribute__((unused)), | ||
149 | int iAmt __attribute__((unused)), | ||
150 | sqlite_int64 iOfst __attribute__((unused))) { | ||
151 | ✗ | return SQLITE_READONLY; | |
152 | } | ||
153 | |||
154 | |||
155 | ✗ | static int VfsRdOnlyTruncate(sqlite3_file *pFile __attribute__((unused)), | |
156 | sqlite_int64 size __attribute__((unused))) { | ||
157 | ✗ | return SQLITE_READONLY; | |
158 | } | ||
159 | |||
160 | |||
161 | ✗ | static int VfsRdOnlySync(sqlite3_file *pFile __attribute__((unused)), | |
162 | int flags __attribute__((unused))) { | ||
163 | ✗ | return SQLITE_OK; | |
164 | } | ||
165 | |||
166 | |||
167 | 785 | static int VfsRdOnlyFileSize(sqlite3_file *pFile, sqlite_int64 *pSize) { | |
168 | 785 | VfsRdOnlyFile *p = reinterpret_cast<VfsRdOnlyFile *>(pFile); | |
169 | 785 | *pSize = p->size; | |
170 | 785 | return SQLITE_OK; | |
171 | } | ||
172 | |||
173 | |||
174 | 785 | static int VfsRdOnlyLock(sqlite3_file *p __attribute__((unused)), | |
175 | int level __attribute__((unused))) { | ||
176 | 785 | return SQLITE_OK; | |
177 | } | ||
178 | |||
179 | |||
180 | 785 | static int VfsRdOnlyUnlock(sqlite3_file *p __attribute__((unused)), | |
181 | int level __attribute__((unused))) { | ||
182 | 785 | return SQLITE_OK; | |
183 | } | ||
184 | |||
185 | |||
186 | ✗ | static int VfsRdOnlyCheckReservedLock(sqlite3_file *p __attribute__((unused)), | |
187 | int *pResOut) { | ||
188 | ✗ | *pResOut = 0; | |
189 | ✗ | return SQLITE_OK; | |
190 | } | ||
191 | |||
192 | |||
193 | /** | ||
194 | * No xFileControl() verbs are implemented by this VFS. | ||
195 | */ | ||
196 | 3925 | static int VfsRdOnlyFileControl(sqlite3_file *p __attribute__((unused)), | |
197 | int op __attribute__((unused)), | ||
198 | void *pArg __attribute__((unused))) { | ||
199 | 3925 | return SQLITE_NOTFOUND; | |
200 | } | ||
201 | |||
202 | |||
203 | /** | ||
204 | * A good unit of bytes to read at once. But probably only used for writes. | ||
205 | */ | ||
206 | 785 | static int VfsRdOnlySectorSize(sqlite3_file *p __attribute__((unused))) { | |
207 | 785 | return 4096; | |
208 | } | ||
209 | |||
210 | |||
211 | /** | ||
212 | * Only relevant for writing. | ||
213 | */ | ||
214 | 2355 | static int VfsRdOnlyDeviceCharacteristics(sqlite3_file *p | |
215 | __attribute__((unused))) { | ||
216 | 2355 | return 0; | |
217 | } | ||
218 | |||
219 | |||
220 | /** | ||
221 | * Supports only read-only opens. The "file name" has to be in the form of | ||
222 | * '@<file descriptor>', where file descriptor is usable by the cache manager. | ||
223 | */ | ||
224 | 785 | static int VfsRdOnlyOpen(sqlite3_vfs *vfs, | |
225 | const char *zName, | ||
226 | sqlite3_file *pFile, | ||
227 | int flags, | ||
228 | int *pOutFlags) { | ||
229 | static const sqlite3_io_methods io_methods = {1, // iVersion | ||
230 | VfsRdOnlyClose, | ||
231 | VfsRdOnlyRead, | ||
232 | VfsRdOnlyWrite, | ||
233 | VfsRdOnlyTruncate, | ||
234 | VfsRdOnlySync, | ||
235 | VfsRdOnlyFileSize, | ||
236 | VfsRdOnlyLock, | ||
237 | VfsRdOnlyUnlock, | ||
238 | VfsRdOnlyCheckReservedLock, | ||
239 | VfsRdOnlyFileControl, | ||
240 | VfsRdOnlySectorSize, | ||
241 | VfsRdOnlyDeviceCharacteristics}; | ||
242 | |||
243 | 785 | VfsRdOnlyFile *p = reinterpret_cast<VfsRdOnlyFile *>(pFile); | |
244 | 785 | CacheManager *cache_mgr = reinterpret_cast<VfsRdOnly *>(vfs->pAppData) | |
245 | ->cache_mgr; | ||
246 | // Prevent xClose from being called in case of errors | ||
247 | 785 | p->base.pMethods = NULL; | |
248 | |||
249 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 785 times.
|
785 | if (flags & SQLITE_OPEN_READWRITE) |
250 | ✗ | return SQLITE_IOERR; | |
251 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 785 times.
|
785 | if (flags & SQLITE_OPEN_DELETEONCLOSE) |
252 | ✗ | return SQLITE_IOERR; | |
253 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 785 times.
|
785 | if (flags & SQLITE_OPEN_EXCLUSIVE) |
254 | ✗ | return SQLITE_IOERR; | |
255 | |||
256 |
2/4✓ Branch 0 taken 785 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 785 times.
✗ Branch 3 not taken.
|
785 | assert(zName && (zName[0] == '@')); |
257 |
2/4✓ Branch 2 taken 785 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 785 times.
✗ Branch 6 not taken.
|
785 | p->fd = String2Int64(string(&zName[1])); |
258 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 785 times.
|
785 | if (p->fd < 0) |
259 | ✗ | return SQLITE_IOERR; | |
260 | 785 | const int64_t size = cache_mgr->GetSize(p->fd); | |
261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 785 times.
|
785 | if (size < 0) { |
262 | ✗ | cache_mgr->Close(p->fd); | |
263 | ✗ | p->fd = -1; | |
264 | ✗ | return SQLITE_IOERR_FSTAT; | |
265 | } | ||
266 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 785 times.
|
785 | if (cache_mgr->Readahead(p->fd) != 0) { |
267 | ✗ | cache_mgr->Close(p->fd); | |
268 | ✗ | p->fd = -1; | |
269 | ✗ | return SQLITE_IOERR; | |
270 | } | ||
271 | 785 | p->size = static_cast<uint64_t>(size); | |
272 |
1/2✓ Branch 0 taken 785 times.
✗ Branch 1 not taken.
|
785 | if (pOutFlags) |
273 | 785 | *pOutFlags = flags; | |
274 | 785 | p->vfs_rdonly = reinterpret_cast<VfsRdOnly *>(vfs->pAppData); | |
275 | 785 | p->base.pMethods = &io_methods; | |
276 | 785 | perf::Inc(p->vfs_rdonly->no_open); | |
277 | 785 | LogCvmfs(kLogSql, kLogDebug, "open sqlite3 catalog on fd %d, size %" PRIu64, | |
278 | p->fd, p->size); | ||
279 | 785 | return SQLITE_OK; | |
280 | } | ||
281 | |||
282 | |||
283 | ✗ | static int VfsRdOnlyDelete(sqlite3_vfs * __attribute__((unused)), | |
284 | const char *zName __attribute__((unused)), | ||
285 | int syncDir __attribute__((unused))) { | ||
286 | ✗ | return SQLITE_IOERR_DELETE; | |
287 | } | ||
288 | |||
289 | |||
290 | /** | ||
291 | * Cvmfs r/o file catalogs cannot have a write-ahead log or a journal. | ||
292 | */ | ||
293 | 1570 | static int VfsRdOnlyAccess(sqlite3_vfs *vfs, | |
294 | const char *zPath, | ||
295 | int flags, | ||
296 | int *pResOut) { | ||
297 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1570 times.
|
1570 | if (flags == SQLITE_ACCESS_READWRITE) { |
298 | ✗ | *pResOut = 0; | |
299 | ✗ | return SQLITE_OK; | |
300 | } | ||
301 |
22/50✓ Branch 2 taken 1570 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1570 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1570 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 785 times.
✓ Branch 12 taken 785 times.
✓ Branch 15 taken 785 times.
✗ Branch 16 not taken.
✓ Branch 19 taken 785 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 785 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 785 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 785 times.
✓ Branch 27 taken 785 times.
✓ Branch 29 taken 785 times.
✓ Branch 30 taken 785 times.
✓ Branch 32 taken 785 times.
✓ Branch 33 taken 785 times.
✓ Branch 35 taken 785 times.
✓ Branch 36 taken 785 times.
✓ Branch 38 taken 1570 times.
✗ Branch 39 not taken.
✓ Branch 41 taken 1570 times.
✗ Branch 42 not taken.
✓ Branch 44 taken 1570 times.
✗ Branch 45 not taken.
✓ Branch 47 taken 1570 times.
✗ Branch 48 not taken.
✓ Branch 50 taken 1570 times.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
|
1570 | if (HasSuffix(zPath, "-wal", false) || HasSuffix(zPath, "-journal", false)) { |
302 | 1570 | *pResOut = 0; | |
303 | 1570 | return SQLITE_OK; | |
304 | } | ||
305 | |||
306 | // This VFS deals with file descriptors, we know the files are there | ||
307 | ✗ | *pResOut = 0; | |
308 | ✗ | perf::Inc(reinterpret_cast<VfsRdOnly *>(vfs->pAppData)->n_access); | |
309 | ✗ | return SQLITE_OK; | |
310 | } | ||
311 | |||
312 | |||
313 | /** | ||
314 | * Since the path is never stored, there is no need to produce a full path. | ||
315 | */ | ||
316 | 785 | int VfsRdOnlyFullPathname(sqlite3_vfs *vfs __attribute__((unused)), | |
317 | const char *zPath, | ||
318 | int nOut, | ||
319 | char *zOut) { | ||
320 | 785 | zOut[nOut - 1] = '\0'; | |
321 | 785 | sqlite3_snprintf(nOut, zOut, "%s", zPath); | |
322 | 785 | return SQLITE_OK; | |
323 | } | ||
324 | |||
325 | |||
326 | /** | ||
327 | * Taken from unixRandomness | ||
328 | */ | ||
329 | ✗ | static int VfsRdOnlyRandomness(sqlite3_vfs *vfs, int nBuf, char *zBuf) { | |
330 | ✗ | assert(static_cast<size_t>(nBuf) >= (sizeof(time_t) + sizeof(int))); | |
331 | ✗ | perf::Inc(reinterpret_cast<VfsRdOnly *>(vfs->pAppData)->n_rand); | |
332 | ✗ | memset(zBuf, 0, nBuf); | |
333 | ✗ | pid_t randomnessPid = getpid(); | |
334 | int fd, got; | ||
335 | ✗ | fd = open("/dev/urandom", O_RDONLY, 0); | |
336 | ✗ | if (fd < 0) { | |
337 | time_t t; | ||
338 | ✗ | time(&t); | |
339 | ✗ | memcpy(zBuf, &t, sizeof(t)); | |
340 | ✗ | memcpy(&zBuf[sizeof(t)], &randomnessPid, sizeof(randomnessPid)); | |
341 | ✗ | assert(sizeof(t) + sizeof(randomnessPid) <= static_cast<size_t>(nBuf)); | |
342 | ✗ | nBuf = sizeof(t) + sizeof(randomnessPid); | |
343 | } else { | ||
344 | do { | ||
345 | ✗ | got = read(fd, zBuf, nBuf); | |
346 | ✗ | } while (got < 0 && errno == EINTR); | |
347 | ✗ | close(fd); | |
348 | } | ||
349 | ✗ | perf::Xadd(reinterpret_cast<VfsRdOnly *>(vfs->pAppData)->sz_rand, nBuf); | |
350 | ✗ | return nBuf; | |
351 | } | ||
352 | |||
353 | |||
354 | /** | ||
355 | * Like SafeSleepMs, avoid conflict with the ALARM signal. | ||
356 | */ | ||
357 | ✗ | static int VfsRdOnlySleep(sqlite3_vfs *vfs, int microseconds) { | |
358 | struct timeval wait_for; | ||
359 | ✗ | wait_for.tv_sec = microseconds / (1000 * 1000); | |
360 | ✗ | wait_for.tv_usec = microseconds % (1000 * 1000); | |
361 | ✗ | select(0, NULL, NULL, NULL, &wait_for); | |
362 | ✗ | perf::Inc(reinterpret_cast<VfsRdOnly *>(vfs->pAppData)->n_sleep); | |
363 | ✗ | perf::Xadd(reinterpret_cast<VfsRdOnly *>(vfs->pAppData)->sz_sleep, | |
364 | microseconds); | ||
365 | ✗ | return microseconds; | |
366 | } | ||
367 | |||
368 | |||
369 | /** | ||
370 | * Taken from unixCurrentTimeInt64() | ||
371 | */ | ||
372 | ✗ | static int VfsRdOnlyCurrentTimeInt64(sqlite3_vfs *vfs, sqlite3_int64 *piNow) { | |
373 | static const sqlite3_int64 unixEpoch = 24405875 * (sqlite3_int64)8640000; | ||
374 | ✗ | int rc = SQLITE_OK; | |
375 | struct timeval sNow; | ||
376 | ✗ | if (gettimeofday(&sNow, 0) == 0) { | |
377 | ✗ | *piNow = unixEpoch + 1000 * (sqlite3_int64)sNow.tv_sec | |
378 | ✗ | + sNow.tv_usec / 1000; | |
379 | ✗ | perf::Inc(reinterpret_cast<VfsRdOnly *>(vfs->pAppData)->n_time); | |
380 | } else { | ||
381 | ✗ | rc = SQLITE_ERROR; | |
382 | } | ||
383 | ✗ | return rc; | |
384 | } | ||
385 | |||
386 | |||
387 | /** | ||
388 | * Taken from unixCurrentTime | ||
389 | */ | ||
390 | ✗ | static int VfsRdOnlyCurrentTime(sqlite3_vfs *vfs, double *prNow) { | |
391 | ✗ | sqlite3_int64 i = 0; | |
392 | ✗ | const int rc = VfsRdOnlyCurrentTimeInt64(vfs, &i); | |
393 | ✗ | *prNow = i / 86400000.0; | |
394 | ✗ | return rc; | |
395 | } | ||
396 | |||
397 | |||
398 | /** | ||
399 | * So far unused by sqlite. | ||
400 | */ | ||
401 | ✗ | static int VfsRdOnlyGetLastError(sqlite3_vfs *vfs __attribute__((unused)), | |
402 | int not_used1 __attribute__((unused)), | ||
403 | char *not_used2 __attribute__((unused))) { | ||
404 | ✗ | return 0; | |
405 | } | ||
406 | |||
407 | |||
408 | /** | ||
409 | * Can only be registered once. | ||
410 | */ | ||
411 | 1659 | bool RegisterVfsRdOnly(CacheManager *cache_mgr, | |
412 | perf::Statistics *statistics, | ||
413 | const VfsOptions options) { | ||
414 | 1659 | fd_from_ = new std::vector<int>(); | |
415 | 1659 | fd_to_ = new std::vector<int>(); | |
416 | |||
417 | sqlite3_vfs *vfs = reinterpret_cast<sqlite3_vfs *>( | ||
418 | 1659 | smalloc(sizeof(sqlite3_vfs))); | |
419 | 1659 | memset(vfs, 0, sizeof(sqlite3_vfs)); | |
420 | 1659 | VfsRdOnly *vfs_rdonly = new VfsRdOnly(); | |
421 | |||
422 | 1659 | vfs->iVersion = 2; | |
423 | 1659 | vfs->szOsFile = sizeof(VfsRdOnlyFile); | |
424 | 1659 | vfs->mxPathname = PATH_MAX; | |
425 | 1659 | vfs->zName = kVfsName; | |
426 | 1659 | vfs->pAppData = vfs_rdonly; | |
427 | 1659 | vfs->xOpen = VfsRdOnlyOpen; | |
428 | 1659 | vfs->xDelete = VfsRdOnlyDelete; | |
429 | 1659 | vfs->xAccess = VfsRdOnlyAccess; | |
430 | 1659 | vfs->xFullPathname = VfsRdOnlyFullPathname; | |
431 | 1659 | vfs->xDlOpen = NULL; | |
432 | 1659 | vfs->xDlError = NULL; | |
433 | 1659 | vfs->xDlSym = NULL; | |
434 | 1659 | vfs->xDlClose = NULL; | |
435 | 1659 | vfs->xRandomness = VfsRdOnlyRandomness; | |
436 | 1659 | vfs->xSleep = VfsRdOnlySleep; | |
437 | 1659 | vfs->xCurrentTime = VfsRdOnlyCurrentTime; | |
438 | 1659 | vfs->xGetLastError = VfsRdOnlyGetLastError; | |
439 | 1659 | vfs->xCurrentTimeInt64 = VfsRdOnlyCurrentTimeInt64; | |
440 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1659 times.
|
1659 | assert(vfs->zName); |
441 | |||
442 | 1659 | const int retval = sqlite3_vfs_register(vfs, options == kVfsOptDefault); | |
443 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1659 times.
|
1659 | if (retval != SQLITE_OK) { |
444 | ✗ | free(const_cast<char *>(vfs->zName)); | |
445 | ✗ | delete vfs_rdonly; | |
446 | ✗ | free(vfs); | |
447 | ✗ | return false; | |
448 | } | ||
449 | |||
450 | 1659 | vfs_rdonly->cache_mgr = cache_mgr; | |
451 |
3/6✓ Branch 2 taken 1659 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1659 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1659 times.
✗ Branch 10 not taken.
|
1659 | vfs_rdonly->n_access = statistics->Register( |
452 | "sqlite.n_access", "overall number of access() calls"); | ||
453 |
3/6✓ Branch 2 taken 1659 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1659 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1659 times.
✗ Branch 10 not taken.
|
1659 | vfs_rdonly->no_open = statistics->Register("sqlite.no_open", |
454 | "currently open sqlite files"); | ||
455 |
3/6✓ Branch 2 taken 1659 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1659 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1659 times.
✗ Branch 10 not taken.
|
1659 | vfs_rdonly->n_rand = statistics->Register("sqlite.n_rand", |
456 | "overall number of random() calls"); | ||
457 |
3/6✓ Branch 2 taken 1659 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1659 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1659 times.
✗ Branch 10 not taken.
|
1659 | vfs_rdonly->sz_rand = statistics->Register("sqlite.sz_rand", |
458 | "overall number of random bytes"); | ||
459 |
3/6✓ Branch 2 taken 1659 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1659 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1659 times.
✗ Branch 10 not taken.
|
1659 | vfs_rdonly->n_read = statistics->Register("sqlite.n_read", |
460 | "overall number of read() calls"); | ||
461 |
3/6✓ Branch 2 taken 1659 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1659 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1659 times.
✗ Branch 10 not taken.
|
1659 | vfs_rdonly->sz_read = statistics->Register("sqlite.sz_read", |
462 | "overall bytes read()"); | ||
463 |
3/6✓ Branch 2 taken 1659 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1659 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1659 times.
✗ Branch 10 not taken.
|
1659 | vfs_rdonly->n_sleep = statistics->Register("sqlite.n_sleep", |
464 | "overall number of sleep() calls"); | ||
465 |
3/6✓ Branch 2 taken 1659 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1659 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1659 times.
✗ Branch 10 not taken.
|
1659 | vfs_rdonly->sz_sleep = statistics->Register("sqlite.sz_sleep", |
466 | "overall microseconds slept"); | ||
467 |
3/6✓ Branch 2 taken 1659 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1659 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1659 times.
✗ Branch 10 not taken.
|
1659 | vfs_rdonly->n_time = statistics->Register("sqlite.n_time", |
468 | "overall number of time() calls"); | ||
469 | |||
470 | 1659 | return true; | |
471 | } | ||
472 | |||
473 | |||
474 | /** | ||
475 | * If the file system was the default VFS, another default VFS is selected by | ||
476 | * SQlite randomly. | ||
477 | */ | ||
478 | 1656 | bool UnregisterVfsRdOnly() { | |
479 | 1656 | sqlite3_vfs *vfs = sqlite3_vfs_find(kVfsName); | |
480 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1656 times.
|
1656 | if (vfs == NULL) |
481 | ✗ | return false; | |
482 | 1656 | const int retval = sqlite3_vfs_unregister(vfs); | |
483 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1656 times.
|
1656 | if (retval != SQLITE_OK) |
484 | ✗ | return false; | |
485 | |||
486 |
1/2✓ Branch 0 taken 1656 times.
✗ Branch 1 not taken.
|
1656 | delete reinterpret_cast<VfsRdOnly *>(vfs->pAppData); |
487 | 1656 | free(vfs); | |
488 | |||
489 |
1/2✓ Branch 0 taken 1656 times.
✗ Branch 1 not taken.
|
1656 | delete fd_from_; |
490 |
1/2✓ Branch 0 taken 1656 times.
✗ Branch 1 not taken.
|
1656 | delete fd_to_; |
491 | 1656 | fd_from_ = NULL; | |
492 | 1656 | fd_to_ = NULL; | |
493 | |||
494 | 1656 | return true; | |
495 | } | ||
496 | |||
497 | ✗ | void RegisterFdMapping(int from, int to) { | |
498 | ✗ | fd_from_->push_back(from); | |
499 | ✗ | fd_to_->push_back(to); | |
500 | } | ||
501 | |||
502 | ✗ | void ReplaceCacheManager(CacheManager *new_cache_mgr) { | |
503 | ✗ | sqlite3_vfs *vfs = sqlite3_vfs_find(kVfsName); | |
504 | ✗ | if (vfs == NULL) | |
505 | ✗ | return; | |
506 | ✗ | static_cast<VfsRdOnly *>(vfs->pAppData)->cache_mgr = new_cache_mgr; | |
507 | } | ||
508 | |||
509 | } // namespace sqlite | ||
510 |