Merge autoland to mozilla central a=merge
[gecko.git] / storage / BaseVFS.cpp
blob7793c9f24104ccf1088d63dff9b1036ea96c7e55
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "BaseVFS.h"
9 #include <string.h>
10 #include "sqlite3.h"
12 namespace {
14 // The last VFS version for which this file has been updated.
15 constexpr int kLastKnowVfsVersion = 3;
17 // The last io_methods version for which this file has been updated.
18 constexpr int kLastKnownIOMethodsVersion = 3;
20 using namespace mozilla;
22 struct BaseFile {
23 // Base class. Must be first
24 sqlite3_file base;
25 // This points to the underlying sqlite3_file
26 sqlite3_file pReal[1];
29 int BaseClose(sqlite3_file* pFile) {
30 BaseFile* p = (BaseFile*)pFile;
31 return p->pReal->pMethods->xClose(p->pReal);
34 int BaseRead(sqlite3_file* pFile, void* zBuf, int iAmt, sqlite_int64 iOfst) {
35 BaseFile* p = (BaseFile*)pFile;
36 return p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
39 int BaseWrite(sqlite3_file* pFile, const void* zBuf, int iAmt,
40 sqlite_int64 iOfst) {
41 BaseFile* p = (BaseFile*)pFile;
42 return p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
45 int BaseTruncate(sqlite3_file* pFile, sqlite_int64 size) {
46 BaseFile* p = (BaseFile*)pFile;
47 return p->pReal->pMethods->xTruncate(p->pReal, size);
50 int BaseSync(sqlite3_file* pFile, int flags) {
51 BaseFile* p = (BaseFile*)pFile;
52 return p->pReal->pMethods->xSync(p->pReal, flags);
55 int BaseFileSize(sqlite3_file* pFile, sqlite_int64* pSize) {
56 BaseFile* p = (BaseFile*)pFile;
57 return p->pReal->pMethods->xFileSize(p->pReal, pSize);
60 int BaseLock(sqlite3_file* pFile, int eLock) {
61 BaseFile* p = (BaseFile*)pFile;
62 return p->pReal->pMethods->xLock(p->pReal, eLock);
65 int BaseUnlock(sqlite3_file* pFile, int eLock) {
66 BaseFile* p = (BaseFile*)pFile;
67 return p->pReal->pMethods->xUnlock(p->pReal, eLock);
70 int BaseCheckReservedLock(sqlite3_file* pFile, int* pResOut) {
71 BaseFile* p = (BaseFile*)pFile;
72 return p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
75 int BaseFileControl(sqlite3_file* pFile, int op, void* pArg) {
76 #if defined(MOZ_SQLITE_PERSIST_AUXILIARY_FILES)
77 // Persist auxiliary files (-shm and -wal) on disk, because creating and
78 // deleting them may be expensive on slow storage.
79 // Only do this when there is a journal size limit, so the journal is
80 // truncated instead of deleted on shutdown, that feels safer if the user
81 // moves a database file around without its auxiliary files.
82 MOZ_ASSERT(
83 ::sqlite3_compileoption_used("DEFAULT_JOURNAL_SIZE_LIMIT"),
84 "A journal size limit ensures the journal is truncated on shutdown");
85 if (op == SQLITE_FCNTL_PERSIST_WAL) {
86 *static_cast<int*>(pArg) = 1;
87 return SQLITE_OK;
89 #endif
90 BaseFile* p = (BaseFile*)pFile;
91 return p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
94 int BaseSectorSize(sqlite3_file* pFile) {
95 BaseFile* p = (BaseFile*)pFile;
96 return p->pReal->pMethods->xSectorSize(p->pReal);
99 int BaseDeviceCharacteristics(sqlite3_file* pFile) {
100 BaseFile* p = (BaseFile*)pFile;
101 return p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
104 int BaseShmMap(sqlite3_file* pFile, int iPg, int pgsz, int bExtend,
105 void volatile** pp) {
106 BaseFile* p = (BaseFile*)pFile;
107 return p->pReal->pMethods->xShmMap(p->pReal, iPg, pgsz, bExtend, pp);
110 int BaseShmLock(sqlite3_file* pFile, int offset, int n, int flags) {
111 BaseFile* p = (BaseFile*)pFile;
112 return p->pReal->pMethods->xShmLock(p->pReal, offset, n, flags);
115 void BaseShmBarrier(sqlite3_file* pFile) {
116 BaseFile* p = (BaseFile*)pFile;
117 return p->pReal->pMethods->xShmBarrier(p->pReal);
120 int BaseShmUnmap(sqlite3_file* pFile, int deleteFlag) {
121 BaseFile* p = (BaseFile*)pFile;
122 return p->pReal->pMethods->xShmUnmap(p->pReal, deleteFlag);
125 int BaseFetch(sqlite3_file* pFile, sqlite3_int64 iOfst, int iAmt, void** pp) {
126 BaseFile* p = (BaseFile*)pFile;
127 return p->pReal->pMethods->xFetch(p->pReal, iOfst, iAmt, pp);
130 int BaseUnfetch(sqlite3_file* pFile, sqlite3_int64 iOfst, void* pPage) {
131 BaseFile* p = (BaseFile*)pFile;
132 return p->pReal->pMethods->xUnfetch(p->pReal, iOfst, pPage);
135 int BaseOpen(sqlite3_vfs* vfs, const char* zName, sqlite3_file* pFile,
136 int flags, int* pOutFlags) {
137 BaseFile* p = (BaseFile*)pFile;
138 sqlite3_vfs* origVfs = (sqlite3_vfs*)(vfs->pAppData);
139 int rc = origVfs->xOpen(origVfs, zName, p->pReal, flags, pOutFlags);
140 if (rc) {
141 return rc;
143 if (p->pReal->pMethods) {
144 // If the io_methods version is higher than the last known one, you should
145 // update this VFS adding appropriate IO methods for any methods added in
146 // the version change.
147 MOZ_ASSERT(p->pReal->pMethods->iVersion == kLastKnownIOMethodsVersion);
148 static const sqlite3_io_methods IOmethods = {
149 kLastKnownIOMethodsVersion, /* iVersion */
150 BaseClose, /* xClose */
151 BaseRead, /* xRead */
152 BaseWrite, /* xWrite */
153 BaseTruncate, /* xTruncate */
154 BaseSync, /* xSync */
155 BaseFileSize, /* xFileSize */
156 BaseLock, /* xLock */
157 BaseUnlock, /* xUnlock */
158 BaseCheckReservedLock, /* xCheckReservedLock */
159 BaseFileControl, /* xFileControl */
160 BaseSectorSize, /* xSectorSize */
161 BaseDeviceCharacteristics, /* xDeviceCharacteristics */
162 BaseShmMap, /* xShmMap */
163 BaseShmLock, /* xShmLock */
164 BaseShmBarrier, /* xShmBarrier */
165 BaseShmUnmap, /* xShmUnmap */
166 BaseFetch, /* xFetch */
167 BaseUnfetch /* xUnfetch */
169 pFile->pMethods = &IOmethods;
172 return SQLITE_OK;
175 } // namespace
177 namespace mozilla::storage::basevfs {
179 const char* GetVFSName(bool exclusive) {
180 return exclusive ? "base-vfs-excl" : "base-vfs";
183 UniquePtr<sqlite3_vfs> ConstructVFS(bool exclusive) {
184 #if defined(XP_WIN)
185 # define EXPECTED_VFS "win32"
186 # define EXPECTED_VFS_EXCL "win32"
187 #else
188 # define EXPECTED_VFS "unix"
189 # define EXPECTED_VFS_EXCL "unix-excl"
190 #endif
192 if (sqlite3_vfs_find(GetVFSName(exclusive))) {
193 return nullptr;
196 bool found;
197 sqlite3_vfs* origVfs;
198 if (!exclusive) {
199 // Use the non-exclusive VFS.
200 origVfs = sqlite3_vfs_find(nullptr);
201 found = origVfs && origVfs->zName && !strcmp(origVfs->zName, EXPECTED_VFS);
202 } else {
203 origVfs = sqlite3_vfs_find(EXPECTED_VFS_EXCL);
204 found = (origVfs != nullptr);
206 if (!found) {
207 return nullptr;
210 // If the VFS version is higher than the last known one, you should update
211 // this VFS adding appropriate methods for any methods added in the version
212 // change.
213 MOZ_ASSERT(origVfs->iVersion == kLastKnowVfsVersion);
215 sqlite3_vfs vfs = {
216 kLastKnowVfsVersion, /* iVersion */
217 origVfs->szOsFile + static_cast<int>(sizeof(BaseFile)), /* szOsFile */
218 origVfs->mxPathname, /* mxPathname */
219 nullptr, /* pNext */
220 GetVFSName(exclusive), /* zName */
221 origVfs, /* pAppData */
222 BaseOpen, /* xOpen */
223 origVfs->xDelete, /* xDelete */
224 origVfs->xAccess, /* xAccess */
225 origVfs->xFullPathname, /* xFullPathname */
226 origVfs->xDlOpen, /* xDlOpen */
227 origVfs->xDlError, /* xDlError */
228 origVfs->xDlSym, /* xDlSym */
229 origVfs->xDlClose, /* xDlClose */
230 origVfs->xRandomness, /* xRandomness */
231 origVfs->xSleep, /* xSleep */
232 origVfs->xCurrentTime, /* xCurrentTime */
233 origVfs->xGetLastError, /* xGetLastError */
234 origVfs->xCurrentTimeInt64, /* xCurrentTimeInt64 */
235 origVfs->xSetSystemCall, /* xSetSystemCall */
236 origVfs->xGetSystemCall, /* xGetSystemCall */
237 origVfs->xNextSystemCall /* xNextSystemCall */
240 return MakeUnique<sqlite3_vfs>(vfs);
243 } // namespace mozilla::storage::basevfs