📄 test_onefile.c
字号:
/*** 2007 September 14**** The author disclaims copyright to this source code. In place of** a legal notice, here is a blessing:**** May you do good and not evil.** May you find forgiveness for yourself and forgive others.** May you share freely, never taking more than you give.******************************************************************************* $Id: test_onefile.c,v 1.9 2008/06/26 10:54:12 danielk1977 Exp $**** OVERVIEW:**** This file contains some example code demonstrating how the SQLite ** vfs feature can be used to have SQLite operate directly on an ** embedded media, without using an intermediate file system.**** Because this is only a demo designed to run on a workstation, the** underlying media is simulated using a regular file-system file. The** size of the file is fixed when it is first created (default size 10 MB).** From SQLite's point of view, this space is used to store a single** database file and the journal file. **** Any statement journal created is stored in volatile memory obtained ** from sqlite3_malloc(). Any attempt to create a temporary database file ** will fail (SQLITE_IOERR). To prevent SQLite from attempting this,** it should be configured to store all temporary database files in ** main memory (see pragma "temp_store" or the SQLITE_TEMP_STORE compile ** time option).**** ASSUMPTIONS:**** After it has been created, the blob file is accessed using the** following three functions only:**** mediaRead(); - Read a 512 byte block from the file.** mediaWrite(); - Write a 512 byte block to the file.** mediaSync(); - Tell the media hardware to sync.**** It is assumed that these can be easily implemented by any "real"** media vfs driver adapting this code.**** FILE FORMAT:**** The basic principle is that the "database file" is stored at the** beginning of the 10 MB blob and grows in a forward direction. The ** "journal file" is stored at the end of the 10MB blob and grows** in the reverse direction. If, during a transaction, insufficient** space is available to expand either the journal or database file,** an SQLITE_FULL error is returned. The database file is never allowed** to consume more than 90% of the blob space. If SQLite tries to** create a file larger than this, SQLITE_FULL is returned.**** No allowance is made for "wear-leveling", as is required by.** embedded devices in the absence of equivalent hardware features.**** The first 512 block byte of the file is reserved for storing the** size of the "database file". It is updated as part of the sync()** operation. On startup, it can only be trusted if no journal file** exists. If a journal-file does exist, then it stores the real size** of the database region. The second and subsequent blocks store the ** actual database content.**** The size of the "journal file" is not stored persistently in the ** file. When the system is running, the size of the journal file is** stored in volatile memory. When recovering from a crash, this vfs** reports a very large size for the journal file. The normal journal** header and checksum mechanisms serve to prevent SQLite from ** processing any data that lies past the logical end of the journal.**** When SQLite calls OsDelete() to delete the journal file, the final** 512 bytes of the blob (the area containing the first journal header)** are zeroed.**** LOCKING:**** File locking is a no-op. Only one connection may be open at any one** time using this demo vfs.*/#include "sqlite3.h"#include <assert.h>#include <string.h>/*** Maximum pathname length supported by the fs backend.*/#define BLOCKSIZE 512#define BLOBSIZE 10485760/*** Name used to identify this VFS.*/#define FS_VFS_NAME "fs"typedef struct fs_real_file fs_real_file;struct fs_real_file { sqlite3_file *pFile; const char *zName; int nDatabase; /* Current size of database region */ int nJournal; /* Current size of journal region */ int nBlob; /* Total size of allocated blob */ int nRef; /* Number of pointers to this structure */ fs_real_file *pNext; fs_real_file **ppThis;};typedef struct fs_file fs_file;struct fs_file { sqlite3_file base; int eType; fs_real_file *pReal;};typedef struct tmp_file tmp_file;struct tmp_file { sqlite3_file base; int nSize; int nAlloc; char *zAlloc;};/* Values for fs_file.eType. */#define DATABASE_FILE 1#define JOURNAL_FILE 2/*** Method declarations for fs_file.*/static int fsClose(sqlite3_file*);static int fsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);static int fsWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);static int fsTruncate(sqlite3_file*, sqlite3_int64 size);static int fsSync(sqlite3_file*, int flags);static int fsFileSize(sqlite3_file*, sqlite3_int64 *pSize);static int fsLock(sqlite3_file*, int);static int fsUnlock(sqlite3_file*, int);static int fsCheckReservedLock(sqlite3_file*, int *pResOut);static int fsFileControl(sqlite3_file*, int op, void *pArg);static int fsSectorSize(sqlite3_file*);static int fsDeviceCharacteristics(sqlite3_file*);/*** Method declarations for tmp_file.*/static int tmpClose(sqlite3_file*);static int tmpRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);static int tmpWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);static int tmpTruncate(sqlite3_file*, sqlite3_int64 size);static int tmpSync(sqlite3_file*, int flags);static int tmpFileSize(sqlite3_file*, sqlite3_int64 *pSize);static int tmpLock(sqlite3_file*, int);static int tmpUnlock(sqlite3_file*, int);static int tmpCheckReservedLock(sqlite3_file*, int *pResOut);static int tmpFileControl(sqlite3_file*, int op, void *pArg);static int tmpSectorSize(sqlite3_file*);static int tmpDeviceCharacteristics(sqlite3_file*);/*** Method declarations for fs_vfs.*/static int fsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);static int fsDelete(sqlite3_vfs*, const char *zName, int syncDir);static int fsAccess(sqlite3_vfs*, const char *zName, int flags, int *);static int fsFullPathname(sqlite3_vfs*, const char *zName, int nOut,char *zOut);static void *fsDlOpen(sqlite3_vfs*, const char *zFilename);static void fsDlError(sqlite3_vfs*, int nByte, char *zErrMsg);static void *fsDlSym(sqlite3_vfs*,void*, const char *zSymbol);static void fsDlClose(sqlite3_vfs*, void*);static int fsRandomness(sqlite3_vfs*, int nByte, char *zOut);static int fsSleep(sqlite3_vfs*, int microseconds);static int fsCurrentTime(sqlite3_vfs*, double*);typedef struct fs_vfs_t fs_vfs_t;struct fs_vfs_t { sqlite3_vfs base; fs_real_file *pFileList; sqlite3_vfs *pParent;};static fs_vfs_t fs_vfs = { { 1, /* iVersion */ 0, /* szOsFile */ 0, /* mxPathname */ 0, /* pNext */ FS_VFS_NAME, /* zName */ 0, /* pAppData */ fsOpen, /* xOpen */ fsDelete, /* xDelete */ fsAccess, /* xAccess */ fsFullPathname, /* xFullPathname */ fsDlOpen, /* xDlOpen */ fsDlError, /* xDlError */ fsDlSym, /* xDlSym */ fsDlClose, /* xDlClose */ fsRandomness, /* xRandomness */ fsSleep, /* xSleep */ fsCurrentTime /* xCurrentTime */ }, 0, /* pFileList */ 0 /* pParent */};static sqlite3_io_methods fs_io_methods = { 1, /* iVersion */ fsClose, /* xClose */ fsRead, /* xRead */ fsWrite, /* xWrite */ fsTruncate, /* xTruncate */ fsSync, /* xSync */ fsFileSize, /* xFileSize */ fsLock, /* xLock */ fsUnlock, /* xUnlock */ fsCheckReservedLock, /* xCheckReservedLock */ fsFileControl, /* xFileControl */ fsSectorSize, /* xSectorSize */ fsDeviceCharacteristics /* xDeviceCharacteristics */};static sqlite3_io_methods tmp_io_methods = { 1, /* iVersion */ tmpClose, /* xClose */ tmpRead, /* xRead */ tmpWrite, /* xWrite */ tmpTruncate, /* xTruncate */ tmpSync, /* xSync */ tmpFileSize, /* xFileSize */ tmpLock, /* xLock */ tmpUnlock, /* xUnlock */ tmpCheckReservedLock, /* xCheckReservedLock */ tmpFileControl, /* xFileControl */ tmpSectorSize, /* xSectorSize */ tmpDeviceCharacteristics /* xDeviceCharacteristics */};/* Useful macros used in several places */#define MIN(x,y) ((x)<(y)?(x):(y))#define MAX(x,y) ((x)>(y)?(x):(y))/*** Close a tmp-file.*/static int tmpClose(sqlite3_file *pFile){ tmp_file *pTmp = (tmp_file *)pFile; sqlite3_free(pTmp->zAlloc); return SQLITE_OK;}/*** Read data from a tmp-file.*/static int tmpRead( sqlite3_file *pFile, void *zBuf, int iAmt, sqlite_int64 iOfst){ tmp_file *pTmp = (tmp_file *)pFile; if( (iAmt+iOfst)>pTmp->nSize ){ return SQLITE_IOERR_SHORT_READ; } memcpy(zBuf, &pTmp->zAlloc[iOfst], iAmt); return SQLITE_OK;}/*** Write data to a tmp-file.*/static int tmpWrite( sqlite3_file *pFile, const void *zBuf, int iAmt, sqlite_int64 iOfst){ tmp_file *pTmp = (tmp_file *)pFile; if( (iAmt+iOfst)>pTmp->nAlloc ){ int nNew = 2*(iAmt+iOfst+pTmp->nAlloc); char *zNew = sqlite3_realloc(pTmp->zAlloc, nNew); if( !zNew ){ return SQLITE_NOMEM; } pTmp->zAlloc = zNew; pTmp->nAlloc = nNew; } memcpy(&pTmp->zAlloc[iOfst], zBuf, iAmt); pTmp->nSize = MAX(pTmp->nSize, iOfst+iAmt); return SQLITE_OK;}/*** Truncate a tmp-file.*/static int tmpTruncate(sqlite3_file *pFile, sqlite_int64 size){ tmp_file *pTmp = (tmp_file *)pFile; pTmp->nSize = MIN(pTmp->nSize, size); return SQLITE_OK;}/*** Sync a tmp-file.*/static int tmpSync(sqlite3_file *pFile, int flags){ return SQLITE_OK;}/*** Return the current file-size of a tmp-file.*/static int tmpFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ tmp_file *pTmp = (tmp_file *)pFile; *pSize = pTmp->nSize; return SQLITE_OK;}/*** Lock a tmp-file.*/static int tmpLock(sqlite3_file *pFile, int eLock){ return SQLITE_OK;}/*** Unlock a tmp-file.*/static int tmpUnlock(sqlite3_file *pFile, int eLock){ return SQLITE_OK;}/*** Check if another file-handle holds a RESERVED lock on a tmp-file.*/static int tmpCheckReservedLock(sqlite3_file *pFile, int *pResOut){ *pResOut = 0; return SQLITE_OK;}/*** File control method. For custom operations on a tmp-file.*/static int tmpFileControl(sqlite3_file *pFile, int op, void *pArg){ return SQLITE_OK;}/*** Return the sector-size in bytes for a tmp-file.*/static int tmpSectorSize(sqlite3_file *pFile){ return 0;}/*** Return the device characteristic flags supported by a tmp-file.*/static int tmpDeviceCharacteristics(sqlite3_file *pFile){ return 0;}/*** Close an fs-file.*/static int fsClose(sqlite3_file *pFile){ int rc = SQLITE_OK; fs_file *p = (fs_file *)pFile; fs_real_file *pReal = p->pReal; /* Decrement the real_file ref-count. */ pReal->nRef--; assert(pReal->nRef>=0); /* When the ref-count reaches 0, destroy the structure */ if( pReal->nRef==0 ){ *pReal->ppThis = pReal->pNext; if( pReal->pNext ){ pReal->pNext->ppThis = pReal->ppThis; } rc = pReal->pFile->pMethods->xClose(pReal->pFile); sqlite3_free(pReal); } return rc;}/*** Read data from an fs-file.*/static int fsRead( sqlite3_file *pFile, void *zBuf, int iAmt, sqlite_int64 iOfst){ int rc = SQLITE_OK; fs_file *p = (fs_file *)pFile; fs_real_file *pReal = p->pReal; sqlite3_file *pF = pReal->pFile; if( (p->eType==DATABASE_FILE && (iAmt+iOfst)>pReal->nDatabase) || (p->eType==JOURNAL_FILE && (iAmt+iOfst)>pReal->nJournal) ){ rc = SQLITE_IOERR_SHORT_READ; }else if( p->eType==DATABASE_FILE ){ rc = pF->pMethods->xRead(pF, zBuf, iAmt, iOfst+BLOCKSIZE); }else{ /* Journal file. */ int iRem = iAmt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -