fd881ac637
One more step in the renaming arc. Depends on D925182 Differential Revision: D927227
276 linhas
8.7 KiB
C++
276 linhas
8.7 KiB
C++
/*
|
|
+----------------------------------------------------------------------+
|
|
| HipHop for PHP |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 3.01 of the PHP license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.php.net/license/3_01.txt |
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
#include "hphp/util/embedded-vfs.h"
|
|
|
|
/*
|
|
* based on test_demovfs.c and test_multiplex.c in sqlite3
|
|
*/
|
|
#include <sqlite3.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
|
|
#ifndef SQLITE_CORE
|
|
#define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */
|
|
#endif
|
|
#include <sqlite3ext.h>
|
|
|
|
namespace HPHP {
|
|
|
|
/*
|
|
** For a build without mutexes, no-op the mutex calls.
|
|
*/
|
|
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
|
|
#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
|
|
#define sqlite3_mutex_free(X)
|
|
#define sqlite3_mutex_enter(X)
|
|
#define sqlite3_mutex_try(X) SQLITE_OK
|
|
#define sqlite3_mutex_leave(X)
|
|
#define sqlite3_mutex_held(X) ((void)(X),1)
|
|
#define sqlite3_mutex_notheld(X) ((void)(X),1)
|
|
#endif /* SQLITE_THREADSAFE==0 */
|
|
|
|
struct embeddedConn {
|
|
sqlite3_file base;
|
|
int fd;
|
|
size_t offset;
|
|
size_t len;
|
|
};
|
|
|
|
static struct {
|
|
sqlite3_vfs* pOrigVfs;
|
|
sqlite3_vfs sThisVfs;
|
|
sqlite3_io_methods sIoMethodsV1;
|
|
sqlite3_mutex* pMutex;
|
|
int isInitialized;
|
|
} gEmbedded;
|
|
|
|
static void embeddedEnter() { sqlite3_mutex_enter(gEmbedded.pMutex); }
|
|
static void embeddedLeave() { sqlite3_mutex_leave(gEmbedded.pMutex); }
|
|
|
|
static int embeddedOpen(sqlite3_vfs *pVfs, const char *zName,
|
|
sqlite3_file *pConn, int flags,
|
|
int *pOutFlags) {
|
|
memset(pConn, 0, pVfs->szOsFile);
|
|
assert(zName || (flags & SQLITE_OPEN_DELETEONCLOSE));
|
|
|
|
if (zName) {
|
|
const char *p = strchr(zName, ':');
|
|
unsigned long off, len;
|
|
char c;
|
|
if (p && sscanf(p + 1, "%lu:%lu%c", &off, &len, &c) == 2) {
|
|
embeddedConn *eConn = (embeddedConn*)pConn;
|
|
eConn->base.pMethods = &gEmbedded.sIoMethodsV1;
|
|
char *tmp = strdup(zName);
|
|
tmp[p - zName] = 0;
|
|
eConn->fd = open(tmp, O_RDONLY, 0);
|
|
free(tmp);
|
|
if (eConn->fd < 0) return SQLITE_CANTOPEN;
|
|
eConn->offset = off;
|
|
eConn->len = len;
|
|
*pOutFlags = SQLITE_OPEN_READONLY;
|
|
return SQLITE_OK;
|
|
}
|
|
}
|
|
|
|
sqlite3_vfs *pOrigVfs = gEmbedded.pOrigVfs; /* Real VFS */
|
|
return pOrigVfs->xOpen(pOrigVfs, zName, pConn, flags, pOutFlags);
|
|
}
|
|
|
|
static int embeddedDelete(sqlite3_vfs* pVfs, const char* zName, int syncDir) {
|
|
return gEmbedded.pOrigVfs->xDelete(gEmbedded.pOrigVfs, zName, syncDir);
|
|
}
|
|
|
|
static int embeddedAccess(sqlite3_vfs* a, const char* b, int c, int* d) {
|
|
return gEmbedded.pOrigVfs->xAccess(gEmbedded.pOrigVfs, b, c, d);
|
|
}
|
|
|
|
static int embeddedFullPathname(sqlite3_vfs* a, const char* b, int c, char* d) {
|
|
return gEmbedded.pOrigVfs->xFullPathname(gEmbedded.pOrigVfs, b, c, d);
|
|
}
|
|
|
|
static void* embeddedDlOpen(sqlite3_vfs* a, const char* b) {
|
|
return gEmbedded.pOrigVfs->xDlOpen(gEmbedded.pOrigVfs, b);
|
|
}
|
|
|
|
static void embeddedDlError(sqlite3_vfs* a, int b, char* c) {
|
|
gEmbedded.pOrigVfs->xDlError(gEmbedded.pOrigVfs, b, c);
|
|
}
|
|
|
|
static void (*embeddedDlSym(sqlite3_vfs* a, void* b, const char* c))() {
|
|
return gEmbedded.pOrigVfs->xDlSym(gEmbedded.pOrigVfs, b, c);
|
|
}
|
|
|
|
static void embeddedDlClose(sqlite3_vfs* a, void* b) {
|
|
gEmbedded.pOrigVfs->xDlClose(gEmbedded.pOrigVfs, b);
|
|
}
|
|
|
|
static int embeddedRandomness(sqlite3_vfs* a, int b, char* c) {
|
|
return gEmbedded.pOrigVfs->xRandomness(gEmbedded.pOrigVfs, b, c);
|
|
}
|
|
|
|
static int embeddedSleep(sqlite3_vfs* a, int b) {
|
|
return gEmbedded.pOrigVfs->xSleep(gEmbedded.pOrigVfs, b);
|
|
}
|
|
|
|
static int embeddedCurrentTime(sqlite3_vfs* a, double* b) {
|
|
return gEmbedded.pOrigVfs->xCurrentTime(gEmbedded.pOrigVfs, b);
|
|
}
|
|
|
|
static int embeddedGetLastError(sqlite3_vfs* a, int b, char* c) {
|
|
return gEmbedded.pOrigVfs->xGetLastError(gEmbedded.pOrigVfs, b, c);
|
|
}
|
|
|
|
static int embeddedCurrentTimeInt64(sqlite3_vfs* a, sqlite3_int64* b) {
|
|
return gEmbedded.pOrigVfs->xCurrentTimeInt64(gEmbedded.pOrigVfs, b);
|
|
}
|
|
|
|
static int embeddedClose(sqlite3_file* pConn) {
|
|
embeddedConn* p = (embeddedConn*)pConn;
|
|
return close(p->fd) ? SQLITE_OK : SQLITE_ERROR;
|
|
}
|
|
|
|
static int embeddedRead(sqlite3_file* pConn, void* pBuf,
|
|
int iAmt, sqlite3_int64 iOfst) {
|
|
embeddedConn* p = (embeddedConn*)pConn;
|
|
if (iOfst > p->len) return SQLITE_IOERR_READ;
|
|
int rc = SQLITE_OK;
|
|
if (iAmt + iOfst > p->len) {
|
|
rc = SQLITE_IOERR_SHORT_READ;
|
|
iAmt = p->len - iOfst;
|
|
}
|
|
iOfst += p->offset;
|
|
embeddedEnter();
|
|
if (lseek(p->fd, iOfst, SEEK_SET) != iOfst) {
|
|
rc = SQLITE_IOERR_READ;
|
|
} else if (read(p->fd, pBuf, iAmt) != iAmt) {
|
|
rc = SQLITE_IOERR_READ;
|
|
}
|
|
embeddedLeave();
|
|
return rc;
|
|
}
|
|
|
|
static int embeddedWrite(sqlite3_file* pConn, const void* pBuf,
|
|
int iAmt, sqlite3_int64 iOfst) {
|
|
return SQLITE_IOERR_WRITE;
|
|
}
|
|
|
|
static int embeddedTruncate(sqlite3_file* pConn, sqlite3_int64 size) {
|
|
return SQLITE_IOERR_TRUNCATE;
|
|
}
|
|
|
|
static int embeddedSync(sqlite3_file* pConn, int flags) {
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
static int embeddedFileSize(sqlite3_file* pConn, sqlite3_int64* pSize) {
|
|
embeddedConn* p = (embeddedConn*)pConn;
|
|
*pSize = p->len;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
static int embeddedLock(sqlite3_file* pConn, int lock) {
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
static int embeddedUnlock(sqlite3_file* pConn, int lock) {
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
static int embeddedCheckReservedLock(sqlite3_file* pConn, int* pResOut) {
|
|
return SQLITE_IOERR_CHECKRESERVEDLOCK;
|
|
}
|
|
|
|
static int embeddedFileControl(sqlite3_file* pConn, int op, void* pArg) {
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
static int embeddedSectorSize(sqlite3_file* pConn) {
|
|
return 0;
|
|
}
|
|
|
|
static int embeddedDeviceCharacteristics(sqlite3_file* pConn) {
|
|
return 0;
|
|
}
|
|
|
|
int sqlite3_embedded_initialize(const char* zOrigVfsName, int makeDefault) {
|
|
sqlite3_vfs* pOrigVfs;
|
|
if (gEmbedded.isInitialized) return SQLITE_MISUSE;
|
|
pOrigVfs = sqlite3_vfs_find(zOrigVfsName);
|
|
if (pOrigVfs==0) return SQLITE_ERROR;
|
|
assert(pOrigVfs!=&gEmbedded.sThisVfs);
|
|
gEmbedded.pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
|
if (!gEmbedded.pMutex) {
|
|
return SQLITE_NOMEM;
|
|
}
|
|
|
|
gEmbedded.isInitialized = 1;
|
|
gEmbedded.pOrigVfs = pOrigVfs;
|
|
gEmbedded.sThisVfs = *pOrigVfs;
|
|
gEmbedded.sThisVfs.szOsFile += sizeof(embeddedConn);
|
|
gEmbedded.sThisVfs.zName = "embedded";
|
|
gEmbedded.sThisVfs.xOpen = embeddedOpen;
|
|
gEmbedded.sThisVfs.xDelete = embeddedDelete;
|
|
gEmbedded.sThisVfs.xAccess = embeddedAccess;
|
|
gEmbedded.sThisVfs.xFullPathname = embeddedFullPathname;
|
|
gEmbedded.sThisVfs.xDlOpen = embeddedDlOpen;
|
|
gEmbedded.sThisVfs.xDlError = embeddedDlError;
|
|
gEmbedded.sThisVfs.xDlSym = embeddedDlSym;
|
|
gEmbedded.sThisVfs.xDlClose = embeddedDlClose;
|
|
gEmbedded.sThisVfs.xRandomness = embeddedRandomness;
|
|
gEmbedded.sThisVfs.xSleep = embeddedSleep;
|
|
gEmbedded.sThisVfs.xCurrentTime = embeddedCurrentTime;
|
|
gEmbedded.sThisVfs.xGetLastError = embeddedGetLastError;
|
|
gEmbedded.sThisVfs.xCurrentTimeInt64 = embeddedCurrentTimeInt64;
|
|
|
|
gEmbedded.sIoMethodsV1.iVersion = 1;
|
|
gEmbedded.sIoMethodsV1.xClose = embeddedClose;
|
|
gEmbedded.sIoMethodsV1.xRead = embeddedRead;
|
|
gEmbedded.sIoMethodsV1.xWrite = embeddedWrite;
|
|
gEmbedded.sIoMethodsV1.xTruncate = embeddedTruncate;
|
|
gEmbedded.sIoMethodsV1.xSync = embeddedSync;
|
|
gEmbedded.sIoMethodsV1.xFileSize = embeddedFileSize;
|
|
gEmbedded.sIoMethodsV1.xLock = embeddedLock;
|
|
gEmbedded.sIoMethodsV1.xUnlock = embeddedUnlock;
|
|
gEmbedded.sIoMethodsV1.xCheckReservedLock = embeddedCheckReservedLock;
|
|
gEmbedded.sIoMethodsV1.xFileControl = embeddedFileControl;
|
|
gEmbedded.sIoMethodsV1.xSectorSize = embeddedSectorSize;
|
|
gEmbedded.sIoMethodsV1.xDeviceCharacteristics =
|
|
embeddedDeviceCharacteristics;
|
|
|
|
sqlite3_vfs_register(&gEmbedded.sThisVfs, makeDefault);
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
int sqlite3_embedded_shutdown() {
|
|
if( gEmbedded.isInitialized==0 ) return SQLITE_MISUSE;
|
|
gEmbedded.isInitialized = 0;
|
|
sqlite3_mutex_free(gEmbedded.pMutex);
|
|
sqlite3_vfs_unregister(&gEmbedded.sThisVfs);
|
|
memset(&gEmbedded, 0, sizeof(gEmbedded));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
}
|