Annotation of embedaddon/sqlite3/src/test_demovfs.c, revision 1.1.1.1

1.1       misho       1: /*
                      2: ** 2010 April 7
                      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: ** This file implements an example of a simple VFS implementation that 
                     14: ** omits complex features often not required or not possible on embedded
                     15: ** platforms.  Code is included to buffer writes to the journal file, 
                     16: ** which can be a significant performance improvement on some embedded
                     17: ** platforms.
                     18: **
                     19: ** OVERVIEW
                     20: **
                     21: **   The code in this file implements a minimal SQLite VFS that can be 
                     22: **   used on Linux and other posix-like operating systems. The following 
                     23: **   system calls are used:
                     24: **
                     25: **    File-system: access(), unlink(), getcwd()
                     26: **    File IO:     open(), read(), write(), fsync(), close(), fstat()
                     27: **    Other:       sleep(), usleep(), time()
                     28: **
                     29: **   The following VFS features are omitted:
                     30: **
                     31: **     1. File locking. The user must ensure that there is at most one
                     32: **        connection to each database when using this VFS. Multiple
                     33: **        connections to a single shared-cache count as a single connection
                     34: **        for the purposes of the previous statement.
                     35: **
                     36: **     2. The loading of dynamic extensions (shared libraries).
                     37: **
                     38: **     3. Temporary files. The user must configure SQLite to use in-memory
                     39: **        temp files when using this VFS. The easiest way to do this is to
                     40: **        compile with:
                     41: **
                     42: **          -DSQLITE_TEMP_STORE=3
                     43: **
                     44: **     4. File truncation. As of version 3.6.24, SQLite may run without
                     45: **        a working xTruncate() call, providing the user does not configure
                     46: **        SQLite to use "journal_mode=truncate", or use both
                     47: **        "journal_mode=persist" and ATTACHed databases.
                     48: **
                     49: **   It is assumed that the system uses UNIX-like path-names. Specifically,
                     50: **   that '/' characters are used to separate path components and that
                     51: **   a path-name is a relative path unless it begins with a '/'. And that
                     52: **   no UTF-8 encoded paths are greater than 512 bytes in length.
                     53: **
                     54: ** JOURNAL WRITE-BUFFERING
                     55: **
                     56: **   To commit a transaction to the database, SQLite first writes rollback
                     57: **   information into the journal file. This usually consists of 4 steps:
                     58: **
                     59: **     1. The rollback information is sequentially written into the journal
                     60: **        file, starting at the start of the file.
                     61: **     2. The journal file is synced to disk.
                     62: **     3. A modification is made to the first few bytes of the journal file.
                     63: **     4. The journal file is synced to disk again.
                     64: **
                     65: **   Most of the data is written in step 1 using a series of calls to the
                     66: **   VFS xWrite() method. The buffers passed to the xWrite() calls are of
                     67: **   various sizes. For example, as of version 3.6.24, when committing a 
                     68: **   transaction that modifies 3 pages of a database file that uses 4096 
                     69: **   byte pages residing on a media with 512 byte sectors, SQLite makes 
                     70: **   eleven calls to the xWrite() method to create the rollback journal, 
                     71: **   as follows:
                     72: **
                     73: **             Write offset | Bytes written
                     74: **             ----------------------------
                     75: **                        0            512
                     76: **                      512              4
                     77: **                      516           4096
                     78: **                     4612              4
                     79: **                     4616              4
                     80: **                     4620           4096
                     81: **                     8716              4
                     82: **                     8720              4
                     83: **                     8724           4096
                     84: **                    12820              4
                     85: **             ++++++++++++SYNC+++++++++++
                     86: **                        0             12
                     87: **             ++++++++++++SYNC+++++++++++
                     88: **
                     89: **   On many operating systems, this is an efficient way to write to a file.
                     90: **   However, on some embedded systems that do not cache writes in OS 
                     91: **   buffers it is much more efficient to write data in blocks that are
                     92: **   an integer multiple of the sector-size in size and aligned at the
                     93: **   start of a sector.
                     94: **
                     95: **   To work around this, the code in this file allocates a fixed size
                     96: **   buffer of SQLITE_DEMOVFS_BUFFERSZ using sqlite3_malloc() whenever a 
                     97: **   journal file is opened. It uses the buffer to coalesce sequential
                     98: **   writes into aligned SQLITE_DEMOVFS_BUFFERSZ blocks. When SQLite
                     99: **   invokes the xSync() method to sync the contents of the file to disk,
                    100: **   all accumulated data is written out, even if it does not constitute
                    101: **   a complete block. This means the actual IO to create the rollback 
                    102: **   journal for the example transaction above is this:
                    103: **
                    104: **             Write offset | Bytes written
                    105: **             ----------------------------
                    106: **                        0           8192
                    107: **                     8192           4632
                    108: **             ++++++++++++SYNC+++++++++++
                    109: **                        0             12
                    110: **             ++++++++++++SYNC+++++++++++
                    111: **
                    112: **   Much more efficient if the underlying OS is not caching write 
                    113: **   operations.
                    114: */
                    115: 
                    116: #if !defined(SQLITE_TEST) || SQLITE_OS_UNIX
                    117: 
                    118: #include <sqlite3.h>
                    119: 
                    120: #include <assert.h>
                    121: #include <string.h>
                    122: #include <sys/types.h>
                    123: #include <sys/stat.h>
                    124: #include <sys/file.h>
                    125: #include <sys/param.h>
                    126: #include <unistd.h>
                    127: #include <time.h>
                    128: #include <errno.h>
                    129: #include <fcntl.h>
                    130: 
                    131: /*
                    132: ** Size of the write buffer used by journal files in bytes.
                    133: */
                    134: #ifndef SQLITE_DEMOVFS_BUFFERSZ
                    135: # define SQLITE_DEMOVFS_BUFFERSZ 8192
                    136: #endif
                    137: 
                    138: /*
                    139: ** The maximum pathname length supported by this VFS.
                    140: */
                    141: #define MAXPATHNAME 512
                    142: 
                    143: /*
                    144: ** When using this VFS, the sqlite3_file* handles that SQLite uses are
                    145: ** actually pointers to instances of type DemoFile.
                    146: */
                    147: typedef struct DemoFile DemoFile;
                    148: struct DemoFile {
                    149:   sqlite3_file base;              /* Base class. Must be first. */
                    150:   int fd;                         /* File descriptor */
                    151: 
                    152:   char *aBuffer;                  /* Pointer to malloc'd buffer */
                    153:   int nBuffer;                    /* Valid bytes of data in zBuffer */
                    154:   sqlite3_int64 iBufferOfst;      /* Offset in file of zBuffer[0] */
                    155: };
                    156: 
                    157: /*
                    158: ** Write directly to the file passed as the first argument. Even if the
                    159: ** file has a write-buffer (DemoFile.aBuffer), ignore it.
                    160: */
                    161: static int demoDirectWrite(
                    162:   DemoFile *p,                    /* File handle */
                    163:   const void *zBuf,               /* Buffer containing data to write */
                    164:   int iAmt,                       /* Size of data to write in bytes */
                    165:   sqlite_int64 iOfst              /* File offset to write to */
                    166: ){
                    167:   off_t ofst;                     /* Return value from lseek() */
                    168:   size_t nWrite;                  /* Return value from write() */
                    169: 
                    170:   ofst = lseek(p->fd, iOfst, SEEK_SET);
                    171:   if( ofst!=iOfst ){
                    172:     return SQLITE_IOERR_WRITE;
                    173:   }
                    174: 
                    175:   nWrite = write(p->fd, zBuf, iAmt);
                    176:   if( nWrite!=iAmt ){
                    177:     return SQLITE_IOERR_WRITE;
                    178:   }
                    179: 
                    180:   return SQLITE_OK;
                    181: }
                    182: 
                    183: /*
                    184: ** Flush the contents of the DemoFile.aBuffer buffer to disk. This is a
                    185: ** no-op if this particular file does not have a buffer (i.e. it is not
                    186: ** a journal file) or if the buffer is currently empty.
                    187: */
                    188: static int demoFlushBuffer(DemoFile *p){
                    189:   int rc = SQLITE_OK;
                    190:   if( p->nBuffer ){
                    191:     rc = demoDirectWrite(p, p->aBuffer, p->nBuffer, p->iBufferOfst);
                    192:     p->nBuffer = 0;
                    193:   }
                    194:   return rc;
                    195: }
                    196: 
                    197: /*
                    198: ** Close a file.
                    199: */
                    200: static int demoClose(sqlite3_file *pFile){
                    201:   int rc;
                    202:   DemoFile *p = (DemoFile*)pFile;
                    203:   rc = demoFlushBuffer(p);
                    204:   sqlite3_free(p->aBuffer);
                    205:   close(p->fd);
                    206:   return rc;
                    207: }
                    208: 
                    209: /*
                    210: ** Read data from a file.
                    211: */
                    212: static int demoRead(
                    213:   sqlite3_file *pFile, 
                    214:   void *zBuf, 
                    215:   int iAmt, 
                    216:   sqlite_int64 iOfst
                    217: ){
                    218:   DemoFile *p = (DemoFile*)pFile;
                    219:   off_t ofst;                     /* Return value from lseek() */
                    220:   int nRead;                      /* Return value from read() */
                    221:   int rc;                         /* Return code from demoFlushBuffer() */
                    222: 
                    223:   /* Flush any data in the write buffer to disk in case this operation
                    224:   ** is trying to read data the file-region currently cached in the buffer.
                    225:   ** It would be possible to detect this case and possibly save an 
                    226:   ** unnecessary write here, but in practice SQLite will rarely read from
                    227:   ** a journal file when there is data cached in the write-buffer.
                    228:   */
                    229:   rc = demoFlushBuffer(p);
                    230:   if( rc!=SQLITE_OK ){
                    231:     return rc;
                    232:   }
                    233: 
                    234:   ofst = lseek(p->fd, iOfst, SEEK_SET);
                    235:   if( ofst!=iOfst ){
                    236:     return SQLITE_IOERR_READ;
                    237:   }
                    238:   nRead = read(p->fd, zBuf, iAmt);
                    239: 
                    240:   if( nRead==iAmt ){
                    241:     return SQLITE_OK;
                    242:   }else if( nRead>=0 ){
                    243:     return SQLITE_IOERR_SHORT_READ;
                    244:   }
                    245: 
                    246:   return SQLITE_IOERR_READ;
                    247: }
                    248: 
                    249: /*
                    250: ** Write data to a crash-file.
                    251: */
                    252: static int demoWrite(
                    253:   sqlite3_file *pFile, 
                    254:   const void *zBuf, 
                    255:   int iAmt, 
                    256:   sqlite_int64 iOfst
                    257: ){
                    258:   DemoFile *p = (DemoFile*)pFile;
                    259:   
                    260:   if( p->aBuffer ){
                    261:     char *z = (char *)zBuf;       /* Pointer to remaining data to write */
                    262:     int n = iAmt;                 /* Number of bytes at z */
                    263:     sqlite3_int64 i = iOfst;      /* File offset to write to */
                    264: 
                    265:     while( n>0 ){
                    266:       int nCopy;                  /* Number of bytes to copy into buffer */
                    267: 
                    268:       /* If the buffer is full, or if this data is not being written directly
                    269:       ** following the data already buffered, flush the buffer. Flushing
                    270:       ** the buffer is a no-op if it is empty.  
                    271:       */
                    272:       if( p->nBuffer==SQLITE_DEMOVFS_BUFFERSZ || p->iBufferOfst+p->nBuffer!=i ){
                    273:         int rc = demoFlushBuffer(p);
                    274:         if( rc!=SQLITE_OK ){
                    275:           return rc;
                    276:         }
                    277:       }
                    278:       assert( p->nBuffer==0 || p->iBufferOfst+p->nBuffer==i );
                    279:       p->iBufferOfst = i - p->nBuffer;
                    280: 
                    281:       /* Copy as much data as possible into the buffer. */
                    282:       nCopy = SQLITE_DEMOVFS_BUFFERSZ - p->nBuffer;
                    283:       if( nCopy>n ){
                    284:         nCopy = n;
                    285:       }
                    286:       memcpy(&p->aBuffer[p->nBuffer], z, nCopy);
                    287:       p->nBuffer += nCopy;
                    288: 
                    289:       n -= nCopy;
                    290:       i += nCopy;
                    291:       z += nCopy;
                    292:     }
                    293:   }else{
                    294:     return demoDirectWrite(p, zBuf, iAmt, iOfst);
                    295:   }
                    296: 
                    297:   return SQLITE_OK;
                    298: }
                    299: 
                    300: /*
                    301: ** Truncate a file. This is a no-op for this VFS (see header comments at
                    302: ** the top of the file).
                    303: */
                    304: static int demoTruncate(sqlite3_file *pFile, sqlite_int64 size){
                    305: #if 0
                    306:   if( ftruncate(((DemoFile *)pFile)->fd, size) ) return SQLITE_IOERR_TRUNCATE;
                    307: #endif
                    308:   return SQLITE_OK;
                    309: }
                    310: 
                    311: /*
                    312: ** Sync the contents of the file to the persistent media.
                    313: */
                    314: static int demoSync(sqlite3_file *pFile, int flags){
                    315:   DemoFile *p = (DemoFile*)pFile;
                    316:   int rc;
                    317: 
                    318:   rc = demoFlushBuffer(p);
                    319:   if( rc!=SQLITE_OK ){
                    320:     return rc;
                    321:   }
                    322: 
                    323:   rc = fsync(p->fd);
                    324:   return (rc==0 ? SQLITE_OK : SQLITE_IOERR_FSYNC);
                    325: }
                    326: 
                    327: /*
                    328: ** Write the size of the file in bytes to *pSize.
                    329: */
                    330: static int demoFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
                    331:   DemoFile *p = (DemoFile*)pFile;
                    332:   int rc;                         /* Return code from fstat() call */
                    333:   struct stat sStat;              /* Output of fstat() call */
                    334: 
                    335:   /* Flush the contents of the buffer to disk. As with the flush in the
                    336:   ** demoRead() method, it would be possible to avoid this and save a write
                    337:   ** here and there. But in practice this comes up so infrequently it is
                    338:   ** not worth the trouble.
                    339:   */
                    340:   rc = demoFlushBuffer(p);
                    341:   if( rc!=SQLITE_OK ){
                    342:     return rc;
                    343:   }
                    344: 
                    345:   rc = fstat(p->fd, &sStat);
                    346:   if( rc!=0 ) return SQLITE_IOERR_FSTAT;
                    347:   *pSize = sStat.st_size;
                    348:   return SQLITE_OK;
                    349: }
                    350: 
                    351: /*
                    352: ** Locking functions. The xLock() and xUnlock() methods are both no-ops.
                    353: ** The xCheckReservedLock() always indicates that no other process holds
                    354: ** a reserved lock on the database file. This ensures that if a hot-journal
                    355: ** file is found in the file-system it is rolled back.
                    356: */
                    357: static int demoLock(sqlite3_file *pFile, int eLock){
                    358:   return SQLITE_OK;
                    359: }
                    360: static int demoUnlock(sqlite3_file *pFile, int eLock){
                    361:   return SQLITE_OK;
                    362: }
                    363: static int demoCheckReservedLock(sqlite3_file *pFile, int *pResOut){
                    364:   *pResOut = 0;
                    365:   return SQLITE_OK;
                    366: }
                    367: 
                    368: /*
                    369: ** No xFileControl() verbs are implemented by this VFS.
                    370: */
                    371: static int demoFileControl(sqlite3_file *pFile, int op, void *pArg){
                    372:   return SQLITE_OK;
                    373: }
                    374: 
                    375: /*
                    376: ** The xSectorSize() and xDeviceCharacteristics() methods. These two
                    377: ** may return special values allowing SQLite to optimize file-system 
                    378: ** access to some extent. But it is also safe to simply return 0.
                    379: */
                    380: static int demoSectorSize(sqlite3_file *pFile){
                    381:   return 0;
                    382: }
                    383: static int demoDeviceCharacteristics(sqlite3_file *pFile){
                    384:   return 0;
                    385: }
                    386: 
                    387: /*
                    388: ** Open a file handle.
                    389: */
                    390: static int demoOpen(
                    391:   sqlite3_vfs *pVfs,              /* VFS */
                    392:   const char *zName,              /* File to open, or 0 for a temp file */
                    393:   sqlite3_file *pFile,            /* Pointer to DemoFile struct to populate */
                    394:   int flags,                      /* Input SQLITE_OPEN_XXX flags */
                    395:   int *pOutFlags                  /* Output SQLITE_OPEN_XXX flags (or NULL) */
                    396: ){
                    397:   static const sqlite3_io_methods demoio = {
                    398:     1,                            /* iVersion */
                    399:     demoClose,                    /* xClose */
                    400:     demoRead,                     /* xRead */
                    401:     demoWrite,                    /* xWrite */
                    402:     demoTruncate,                 /* xTruncate */
                    403:     demoSync,                     /* xSync */
                    404:     demoFileSize,                 /* xFileSize */
                    405:     demoLock,                     /* xLock */
                    406:     demoUnlock,                   /* xUnlock */
                    407:     demoCheckReservedLock,        /* xCheckReservedLock */
                    408:     demoFileControl,              /* xFileControl */
                    409:     demoSectorSize,               /* xSectorSize */
                    410:     demoDeviceCharacteristics     /* xDeviceCharacteristics */
                    411:   };
                    412: 
                    413:   DemoFile *p = (DemoFile*)pFile; /* Populate this structure */
                    414:   int oflags = 0;                 /* flags to pass to open() call */
                    415:   char *aBuf = 0;
                    416: 
                    417:   if( zName==0 ){
                    418:     return SQLITE_IOERR;
                    419:   }
                    420: 
                    421:   if( flags&SQLITE_OPEN_MAIN_JOURNAL ){
                    422:     aBuf = (char *)sqlite3_malloc(SQLITE_DEMOVFS_BUFFERSZ);
                    423:     if( !aBuf ){
                    424:       return SQLITE_NOMEM;
                    425:     }
                    426:   }
                    427: 
                    428:   if( flags&SQLITE_OPEN_EXCLUSIVE ) oflags |= O_EXCL;
                    429:   if( flags&SQLITE_OPEN_CREATE )    oflags |= O_CREAT;
                    430:   if( flags&SQLITE_OPEN_READONLY )  oflags |= O_RDONLY;
                    431:   if( flags&SQLITE_OPEN_READWRITE ) oflags |= O_RDWR;
                    432: 
                    433:   memset(p, 0, sizeof(DemoFile));
                    434:   p->fd = open(zName, oflags, 0600);
                    435:   if( p->fd<0 ){
                    436:     sqlite3_free(aBuf);
                    437:     return SQLITE_CANTOPEN;
                    438:   }
                    439:   p->aBuffer = aBuf;
                    440: 
                    441:   if( pOutFlags ){
                    442:     *pOutFlags = flags;
                    443:   }
                    444:   p->base.pMethods = &demoio;
                    445:   return SQLITE_OK;
                    446: }
                    447: 
                    448: /*
                    449: ** Delete the file identified by argument zPath. If the dirSync parameter
                    450: ** is non-zero, then ensure the file-system modification to delete the
                    451: ** file has been synced to disk before returning.
                    452: */
                    453: static int demoDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
                    454:   int rc;                         /* Return code */
                    455: 
                    456:   rc = unlink(zPath);
                    457:   if( rc!=0 && errno==ENOENT ) return SQLITE_OK;
                    458: 
                    459:   if( rc==0 && dirSync ){
                    460:     int dfd;                      /* File descriptor open on directory */
                    461:     int i;                        /* Iterator variable */
                    462:     char zDir[MAXPATHNAME+1];     /* Name of directory containing file zPath */
                    463: 
                    464:     /* Figure out the directory name from the path of the file deleted. */
                    465:     sqlite3_snprintf(MAXPATHNAME, zDir, "%s", zPath);
                    466:     zDir[MAXPATHNAME] = '\0';
                    467:     for(i=strlen(zDir); i>1 && zDir[i]!='/'; i++);
                    468:     zDir[i] = '\0';
                    469: 
                    470:     /* Open a file-descriptor on the directory. Sync. Close. */
                    471:     dfd = open(zDir, O_RDONLY, 0);
                    472:     if( dfd<0 ){
                    473:       rc = -1;
                    474:     }else{
                    475:       rc = fsync(dfd);
                    476:       close(dfd);
                    477:     }
                    478:   }
                    479:   return (rc==0 ? SQLITE_OK : SQLITE_IOERR_DELETE);
                    480: }
                    481: 
                    482: #ifndef F_OK
                    483: # define F_OK 0
                    484: #endif
                    485: #ifndef R_OK
                    486: # define R_OK 4
                    487: #endif
                    488: #ifndef W_OK
                    489: # define W_OK 2
                    490: #endif
                    491: 
                    492: /*
                    493: ** Query the file-system to see if the named file exists, is readable or
                    494: ** is both readable and writable.
                    495: */
                    496: static int demoAccess(
                    497:   sqlite3_vfs *pVfs, 
                    498:   const char *zPath, 
                    499:   int flags, 
                    500:   int *pResOut
                    501: ){
                    502:   int rc;                         /* access() return code */
                    503:   int eAccess = F_OK;             /* Second argument to access() */
                    504: 
                    505:   assert( flags==SQLITE_ACCESS_EXISTS       /* access(zPath, F_OK) */
                    506:        || flags==SQLITE_ACCESS_READ         /* access(zPath, R_OK) */
                    507:        || flags==SQLITE_ACCESS_READWRITE    /* access(zPath, R_OK|W_OK) */
                    508:   );
                    509: 
                    510:   if( flags==SQLITE_ACCESS_READWRITE ) eAccess = R_OK|W_OK;
                    511:   if( flags==SQLITE_ACCESS_READ )      eAccess = R_OK;
                    512: 
                    513:   rc = access(zPath, eAccess);
                    514:   *pResOut = (rc==0);
                    515:   return SQLITE_OK;
                    516: }
                    517: 
                    518: /*
                    519: ** Argument zPath points to a nul-terminated string containing a file path.
                    520: ** If zPath is an absolute path, then it is copied as is into the output 
                    521: ** buffer. Otherwise, if it is a relative path, then the equivalent full
                    522: ** path is written to the output buffer.
                    523: **
                    524: ** This function assumes that paths are UNIX style. Specifically, that:
                    525: **
                    526: **   1. Path components are separated by a '/'. and 
                    527: **   2. Full paths begin with a '/' character.
                    528: */
                    529: static int demoFullPathname(
                    530:   sqlite3_vfs *pVfs,              /* VFS */
                    531:   const char *zPath,              /* Input path (possibly a relative path) */
                    532:   int nPathOut,                   /* Size of output buffer in bytes */
                    533:   char *zPathOut                  /* Pointer to output buffer */
                    534: ){
                    535:   char zDir[MAXPATHNAME+1];
                    536:   if( zPath[0]=='/' ){
                    537:     zDir[0] = '\0';
                    538:   }else{
                    539:     getcwd(zDir, sizeof(zDir));
                    540:   }
                    541:   zDir[MAXPATHNAME] = '\0';
                    542: 
                    543:   sqlite3_snprintf(nPathOut, zPathOut, "%s/%s", zDir, zPath);
                    544:   zPathOut[nPathOut-1] = '\0';
                    545: 
                    546:   return SQLITE_OK;
                    547: }
                    548: 
                    549: /*
                    550: ** The following four VFS methods:
                    551: **
                    552: **   xDlOpen
                    553: **   xDlError
                    554: **   xDlSym
                    555: **   xDlClose
                    556: **
                    557: ** are supposed to implement the functionality needed by SQLite to load
                    558: ** extensions compiled as shared objects. This simple VFS does not support
                    559: ** this functionality, so the following functions are no-ops.
                    560: */
                    561: static void *demoDlOpen(sqlite3_vfs *pVfs, const char *zPath){
                    562:   return 0;
                    563: }
                    564: static void demoDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
                    565:   sqlite3_snprintf(nByte, zErrMsg, "Loadable extensions are not supported");
                    566:   zErrMsg[nByte-1] = '\0';
                    567: }
                    568: static void (*demoDlSym(sqlite3_vfs *pVfs, void *pH, const char *z))(void){
                    569:   return 0;
                    570: }
                    571: static void demoDlClose(sqlite3_vfs *pVfs, void *pHandle){
                    572:   return;
                    573: }
                    574: 
                    575: /*
                    576: ** Parameter zByte points to a buffer nByte bytes in size. Populate this
                    577: ** buffer with pseudo-random data.
                    578: */
                    579: static int demoRandomness(sqlite3_vfs *pVfs, int nByte, char *zByte){
                    580:   return SQLITE_OK;
                    581: }
                    582: 
                    583: /*
                    584: ** Sleep for at least nMicro microseconds. Return the (approximate) number 
                    585: ** of microseconds slept for.
                    586: */
                    587: static int demoSleep(sqlite3_vfs *pVfs, int nMicro){
                    588:   sleep(nMicro / 1000000);
                    589:   usleep(nMicro % 1000000);
                    590:   return nMicro;
                    591: }
                    592: 
                    593: /*
                    594: ** Set *pTime to the current UTC time expressed as a Julian day. Return
                    595: ** SQLITE_OK if successful, or an error code otherwise.
                    596: **
                    597: **   http://en.wikipedia.org/wiki/Julian_day
                    598: **
                    599: ** This implementation is not very good. The current time is rounded to
                    600: ** an integer number of seconds. Also, assuming time_t is a signed 32-bit 
                    601: ** value, it will stop working some time in the year 2038 AD (the so-called
                    602: ** "year 2038" problem that afflicts systems that store time this way). 
                    603: */
                    604: static int demoCurrentTime(sqlite3_vfs *pVfs, double *pTime){
                    605:   time_t t = time(0);
                    606:   *pTime = t/86400.0 + 2440587.5; 
                    607:   return SQLITE_OK;
                    608: }
                    609: 
                    610: /*
                    611: ** This function returns a pointer to the VFS implemented in this file.
                    612: ** To make the VFS available to SQLite:
                    613: **
                    614: **   sqlite3_vfs_register(sqlite3_demovfs(), 0);
                    615: */
                    616: sqlite3_vfs *sqlite3_demovfs(void){
                    617:   static sqlite3_vfs demovfs = {
                    618:     1,                            /* iVersion */
                    619:     sizeof(DemoFile),             /* szOsFile */
                    620:     MAXPATHNAME,                  /* mxPathname */
                    621:     0,                            /* pNext */
                    622:     "demo",                       /* zName */
                    623:     0,                            /* pAppData */
                    624:     demoOpen,                     /* xOpen */
                    625:     demoDelete,                   /* xDelete */
                    626:     demoAccess,                   /* xAccess */
                    627:     demoFullPathname,             /* xFullPathname */
                    628:     demoDlOpen,                   /* xDlOpen */
                    629:     demoDlError,                  /* xDlError */
                    630:     demoDlSym,                    /* xDlSym */
                    631:     demoDlClose,                  /* xDlClose */
                    632:     demoRandomness,               /* xRandomness */
                    633:     demoSleep,                    /* xSleep */
                    634:     demoCurrentTime,              /* xCurrentTime */
                    635:   };
                    636:   return &demovfs;
                    637: }
                    638: 
                    639: #endif /* !defined(SQLITE_TEST) || SQLITE_OS_UNIX */
                    640: 
                    641: 
                    642: #ifdef SQLITE_TEST
                    643: 
                    644: #include <tcl.h>
                    645: 
                    646: #if SQLITE_OS_UNIX
                    647: static int register_demovfs(
                    648:   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
                    649:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
                    650:   int objc,              /* Number of arguments */
                    651:   Tcl_Obj *CONST objv[]  /* Command arguments */
                    652: ){
                    653:   sqlite3_vfs_register(sqlite3_demovfs(), 1);
                    654:   return TCL_OK;
                    655: }
                    656: static int unregister_demovfs(
                    657:   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
                    658:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
                    659:   int objc,              /* Number of arguments */
                    660:   Tcl_Obj *CONST objv[]  /* Command arguments */
                    661: ){
                    662:   sqlite3_vfs_unregister(sqlite3_demovfs());
                    663:   return TCL_OK;
                    664: }
                    665: 
                    666: /*
                    667: ** Register commands with the TCL interpreter.
                    668: */
                    669: int Sqlitetest_demovfs_Init(Tcl_Interp *interp){
                    670:   Tcl_CreateObjCommand(interp, "register_demovfs", register_demovfs, 0, 0);
                    671:   Tcl_CreateObjCommand(interp, "unregister_demovfs", unregister_demovfs, 0, 0);
                    672:   return TCL_OK;
                    673: }
                    674: 
                    675: #else
                    676: int Sqlitetest_demovfs_Init(Tcl_Interp *interp){ return TCL_OK; }
                    677: #endif
                    678: 
                    679: #endif /* SQLITE_TEST */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>