LCOV - app.info - storage/src/TelemetryVFS.cpp

LCOV - code coverage report
| Current view: | directory - storage/src - TelemetryVFS.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 203 | 162 | 79.8 %
| Date: | 2012-04-21 | Functions: | 35 | 23 | 65.7 %

           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                 :  * ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is Oracle Corporation code.
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is
          19                 :  *  Oracle Corporation
          20                 :  * Portions created by the Initial Developer are Copyright (C) 2011
          21                 :  * the Initial Developer. All Rights Reserved.
          22                 :  *
          23                 :  * Contributor(s):
          24                 :  *   Taras Glek <tglek@mozilla.com>
          25                 :  *
          26                 :  * Alternatively, the contents of this file may be used under the terms of
          27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          30                 :  * of those above. If you wish to allow use of your version of this file only
          31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          32                 :  * use your version of this file under the terms of the MPL, indicate your
          33                 :  * decision by deleting the provisions above and replace them with the notice
          34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          35                 :  * the provisions above, a recipient may use your version of this file under
          36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          37                 :  *
          38                 :  * ***** END LICENSE BLOCK ***** */
          39                 :
          40                 : #include <string.h>
          41                 : #include "mozilla/Telemetry.h"
          42                 : #include "sqlite3.h"
          43                 : #include "nsThreadUtils.h"
          44                 : #include "mozilla/Util.h"
          45                 :
          46                 : namespace {
          47                 :
          48                 : using namespace mozilla;
          49                 :
          50                 : struct Histograms {
          51                 :   const char *name;
          52                 :   const Telemetry::ID readB;
          53                 :   const Telemetry::ID writeB;
          54                 :   const Telemetry::ID readMS;
          55                 :   const Telemetry::ID writeMS;
          56                 :   const Telemetry::ID syncMS;
          57                 : };
          58                 :
          59                 : #define SQLITE_TELEMETRY(FILENAME, HGRAM) \
          60                 :   { FILENAME, \
          61                 :     Telemetry::MOZ_SQLITE_ ## HGRAM ## _READ_B, \
          62                 :     Telemetry::MOZ_SQLITE_ ## HGRAM ## _WRITE_B, \
          63                 :     Telemetry::MOZ_SQLITE_ ## HGRAM ## _READ_MS, \
          64                 :     Telemetry::MOZ_SQLITE_ ## HGRAM ## _WRITE_MS, \
          65                 :     Telemetry::MOZ_SQLITE_ ## HGRAM ## _SYNC_MS \
          66                 :   }
          67                 :
          68                 : Histograms gHistograms[] = {
          69                 :   SQLITE_TELEMETRY("places.sqlite", PLACES),
          70                 :   SQLITE_TELEMETRY("cookies.sqlite", COOKIES),
          71                 :   SQLITE_TELEMETRY("webappsstore.sqlite", WEBAPPS),
          72                 :   SQLITE_TELEMETRY(NULL, OTHER)
          73                 : };
          74                 : #undef SQLITE_TELEMETRY
          75                 :
          76                 : /** RAII class for measuring how long io takes on/off main thread
          77                 :  */
          78                 : class IOThreadAutoTimer {
          79                 : public:
          80                 :   /**
          81                 :    * IOThreadAutoTimer measures time spent in IO. Additionally it
          82                 :    * automatically determines whether IO is happening on the main
          83                 :    * thread and picks an appropriate histogram.
          84                 :    *
          85                 :    * @param id takes a telemetry histogram id. The id+1 must be an
          86                 :    * equivalent histogram for the main thread. Eg, MOZ_SQLITE_OPEN_MS
          87                 :    * is followed by MOZ_SQLITE_OPEN_MAIN_THREAD_MS.
          88                 :    */
          89          473125 :   IOThreadAutoTimer(Telemetry::ID id)
          90                 :     : start(TimeStamp::Now()),
          91          473125 :       id(id)
          92                 :   {
          93          473125 :   }
          94                 :
          95          473125 :   ~IOThreadAutoTimer() {
          96          473125 :     PRUint32 mainThread = NS_IsMainThread() ? 1 : 0;
          97                 :     Telemetry::AccumulateTimeDelta(static_cast<Telemetry::ID>(id + mainThread),
          98          473125 :                                    start);
          99          473125 :   }
         100                 :
         101                 : private:
         102                 :   const TimeStamp start;
         103                 :   const Telemetry::ID id;
         104                 : };
         105                 :
         106                 : struct telemetry_file {
         107                 :   sqlite3_file base;        // Base class.  Must be first
         108                 :   Histograms *histograms;   // histograms pertaining to this file
         109                 :   sqlite3_file pReal[1];    // This contains the vfs that actually does work
         110                 : };
         111                 :
         112                 : /*
         113                 : ** Close a telemetry_file.
         114                 : */
         115                 : int
         116           10290 : xClose(sqlite3_file *pFile)
         117                 : {
         118           10290 :   telemetry_file *p = (telemetry_file *)pFile;
         119                 :   int rc;
         120           10290 :   rc = p->pReal->pMethods->xClose(p->pReal);
         121           10290 :   if( rc==SQLITE_OK ){
         122           10290 :     delete p->base.pMethods;
         123           10290 :     p->base.pMethods = NULL;
         124                 :   }
         125           10290 :   return rc;
         126                 : }
         127                 :
         128                 : /*
         129                 : ** Read data from a telemetry_file.
         130                 : */
         131                 : int
         132           71895 : xRead(sqlite3_file *pFile, void *zBuf, int iAmt, sqlite_int64 iOfst)
         133                 : {
         134           71895 :   telemetry_file *p = (telemetry_file *)pFile;
         135          143790 :   IOThreadAutoTimer ioTimer(p->histograms->readMS);
         136                 :   int rc;
         137           71895 :   rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
         138                 :   // sqlite likes to read from empty files, this is normal, ignore it.
         139           71895 :   if (rc != SQLITE_IOERR_SHORT_READ)
         140           65329 :     Telemetry::Accumulate(p->histograms->readB, rc == SQLITE_OK ? iAmt : 0);
         141           71895 :   return rc;
         142                 : }
         143                 :
         144                 : /*
         145                 : ** Write data to a telemetry_file.
         146                 : */
         147                 : int
         148          357429 : xWrite(sqlite3_file *pFile, const void *zBuf, int iAmt, sqlite_int64 iOfst)
         149                 : {
         150          357429 :   telemetry_file *p = (telemetry_file *)pFile;
         151          714858 :   IOThreadAutoTimer ioTimer(p->histograms->writeMS);
         152                 :   int rc;
         153          357429 :   rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
         154          357429 :   Telemetry::Accumulate(p->histograms->writeB, rc == SQLITE_OK ? iAmt : 0);
         155          357429 :   return rc;
         156                 : }
         157                 :
         158                 : /*
         159                 : ** Truncate a telemetry_file.
         160                 : */
         161                 : int
         162            6934 : xTruncate(sqlite3_file *pFile, sqlite_int64 size)
         163                 : {
         164           13868 :   IOThreadAutoTimer ioTimer(Telemetry::MOZ_SQLITE_TRUNCATE_MS);
         165            6934 :   telemetry_file *p = (telemetry_file *)pFile;
         166                 :   int rc;
         167           13868 :   Telemetry::AutoTimer<Telemetry::MOZ_SQLITE_TRUNCATE_MS> timer;
         168            6934 :   rc = p->pReal->pMethods->xTruncate(p->pReal, size);
         169            6934 :   return rc;
         170                 : }
         171                 :
         172                 : /*
         173                 : ** Sync a telemetry_file.
         174                 : */
         175                 : int
         176           26573 : xSync(sqlite3_file *pFile, int flags)
         177                 : {
         178           26573 :   telemetry_file *p = (telemetry_file *)pFile;
         179           53146 :   IOThreadAutoTimer ioTimer(p->histograms->syncMS);
         180           26573 :   return p->pReal->pMethods->xSync(p->pReal, flags);
         181                 : }
         182                 :
         183                 : /*
         184                 : ** Return the current file-size of a telemetry_file.
         185                 : */
         186                 : int
         187           49190 : xFileSize(sqlite3_file *pFile, sqlite_int64 *pSize)
         188                 : {
         189           49190 :   telemetry_file *p = (telemetry_file *)pFile;
         190                 :   int rc;
         191           49190 :   rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
         192           49190 :   return rc;
         193                 : }
         194                 :
         195                 : /*
         196                 : ** Lock a telemetry_file.
         197                 : */
         198                 : int
         199           28398 : xLock(sqlite3_file *pFile, int eLock)
         200                 : {
         201           28398 :   telemetry_file *p = (telemetry_file *)pFile;
         202                 :   int rc;
         203           28398 :   rc = p->pReal->pMethods->xLock(p->pReal, eLock);
         204           28398 :   return rc;
         205                 : }
         206                 :
         207                 : /*
         208                 : ** Unlock a telemetry_file.
         209                 : */
         210                 : int
         211           22553 : xUnlock(sqlite3_file *pFile, int eLock)
         212                 : {
         213           22553 :   telemetry_file *p = (telemetry_file *)pFile;
         214                 :   int rc;
         215           22553 :   rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
         216           22553 :   return rc;
         217                 : }
         218                 :
         219                 : /*
         220                 : ** Check if another file-handle holds a RESERVED lock on a telemetry_file.
         221                 : */
         222                 : int
         223               0 : xCheckReservedLock(sqlite3_file *pFile, int *pResOut)
         224                 : {
         225               0 :   telemetry_file *p = (telemetry_file *)pFile;
         226               0 :   int rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
         227               0 :   return rc;
         228                 : }
         229                 :
         230                 : /*
         231                 : ** File control method. For custom operations on a telemetry_file.
         232                 : */
         233                 : int
         234            5284 : xFileControl(sqlite3_file *pFile, int op, void *pArg)
         235                 : {
         236            5284 :   telemetry_file *p = (telemetry_file *)pFile;
         237            5284 :   int rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
         238            5284 :   return rc;
         239                 : }
         240                 :
         241                 : /*
         242                 : ** Return the sector-size in bytes for a telemetry_file.
         243                 : */
         244                 : int
         245               0 : xSectorSize(sqlite3_file *pFile)
         246                 : {
         247               0 :   telemetry_file *p = (telemetry_file *)pFile;
         248                 :   int rc;
         249               0 :   rc = p->pReal->pMethods->xSectorSize(p->pReal);
         250               0 :   return rc;
         251                 : }
         252                 :
         253                 : /*
         254                 : ** Return the device characteristic flags supported by a telemetry_file.
         255                 : */
         256                 : int
         257           34701 : xDeviceCharacteristics(sqlite3_file *pFile)
         258                 : {
         259           34701 :   telemetry_file *p = (telemetry_file *)pFile;
         260                 :   int rc;
         261           34701 :   rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
         262           34701 :   return rc;
         263                 : }
         264                 :
         265                 : /*
         266                 : ** Shared-memory operations.
         267                 : */
         268                 : int
         269          261107 : xShmLock(sqlite3_file *pFile, int ofst, int n, int flags)
         270                 : {
         271          261107 :   telemetry_file *p = (telemetry_file *)pFile;
         272          261107 :   return p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
         273                 : }
         274                 :
         275                 : int
         276             776 : xShmMap(sqlite3_file *pFile, int iRegion, int szRegion, int isWrite, void volatile **pp)
         277                 : {
         278             776 :   telemetry_file *p = (telemetry_file *)pFile;
         279                 :   int rc;
         280             776 :   rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
         281             776 :   return rc;
         282                 : }
         283                 :
         284                 : void
         285          155185 : xShmBarrier(sqlite3_file *pFile){
         286          155185 :   telemetry_file *p = (telemetry_file *)pFile;
         287          155185 :   p->pReal->pMethods->xShmBarrier(p->pReal);
         288          155185 : }
         289                 :
         290                 : int
         291             424 : xShmUnmap(sqlite3_file *pFile, int delFlag){
         292             424 :   telemetry_file *p = (telemetry_file *)pFile;
         293                 :   int rc;
         294             424 :   rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
         295             424 :   return rc;
         296                 : }
         297                 :
         298                 : int
         299           10294 : xOpen(sqlite3_vfs* vfs, const char *zName, sqlite3_file* pFile,
         300                 :           int flags, int *pOutFlags)
         301                 : {
         302           20588 :   IOThreadAutoTimer ioTimer(Telemetry::MOZ_SQLITE_OPEN_MS);
         303           20588 :   Telemetry::AutoTimer<Telemetry::MOZ_SQLITE_OPEN_MS> timer;
         304           10294 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         305                 :   int rc;
         306           10294 :   telemetry_file *p = (telemetry_file *)pFile;
         307           10294 :   Histograms *h = NULL;
         308                 :   // check if the filename is one we are probing for
         309           35610 :   for(size_t i = 0;i < sizeof(gHistograms)/sizeof(gHistograms[0]);i++) {
         310           35610 :     h = &gHistograms[i];
         311                 :     // last probe is the fallback probe
         312           35610 :     if (!h->name)
         313            7910 :       break;
         314           27700 :     if (!zName)
         315            1233 :       continue;
         316           26467 :     const char *match = strstr(zName, h->name);
         317           26467 :     if (!match)
         318           24079 :       continue;
         319            2388 :     char c = match[strlen(h->name)];
         320                 :     // include -wal/-journal too
         321            2388 :     if (!c || c == '-')
         322            2384 :       break;
         323                 :   }
         324           10294 :   p->histograms = h;
         325           10294 :   rc = orig_vfs->xOpen(orig_vfs, zName, p->pReal, flags, pOutFlags);
         326           10294 :   if( rc != SQLITE_OK )
         327               4 :     return rc;
         328           10290 :   if( p->pReal->pMethods ){
         329           10290 :     sqlite3_io_methods *pNew = new sqlite3_io_methods;
         330           10290 :     const sqlite3_io_methods *pSub = p->pReal->pMethods;
         331           10290 :     memset(pNew, 0, sizeof(*pNew));
         332           10290 :     pNew->iVersion = pSub->iVersion;
         333           10290 :     pNew->xClose = xClose;
         334           10290 :     pNew->xRead = xRead;
         335           10290 :     pNew->xWrite = xWrite;
         336           10290 :     pNew->xTruncate = xTruncate;
         337           10290 :     pNew->xSync = xSync;
         338           10290 :     pNew->xFileSize = xFileSize;
         339           10290 :     pNew->xLock = xLock;
         340           10290 :     pNew->xUnlock = xUnlock;
         341           10290 :     pNew->xCheckReservedLock = xCheckReservedLock;
         342           10290 :     pNew->xFileControl = xFileControl;
         343           10290 :     pNew->xSectorSize = xSectorSize;
         344           10290 :     pNew->xDeviceCharacteristics = xDeviceCharacteristics;
         345           10290 :     if( pNew->iVersion>=2 ){
         346            2898 :       pNew->xShmMap = pSub->xShmMap ? xShmMap : 0;
         347            2898 :       pNew->xShmLock = pSub->xShmLock ? xShmLock : 0;
         348            2898 :       pNew->xShmBarrier = pSub->xShmBarrier ? xShmBarrier : 0;
         349            2898 :       pNew->xShmUnmap = pSub->xShmUnmap ? xShmUnmap : 0;
         350                 :     }
         351           10290 :     pFile->pMethods = pNew;
         352                 :   }
         353           10290 :   return rc;
         354                 : }
         355                 :
         356                 : int
         357           10215 : xDelete(sqlite3_vfs* vfs, const char *zName, int syncDir)
         358                 : {
         359           10215 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         360           10215 :   return orig_vfs->xDelete(orig_vfs, zName, syncDir);
         361                 : }
         362                 :
         363                 : int
         364           25110 : xAccess(sqlite3_vfs *vfs, const char *zName, int flags, int *pResOut)
         365                 : {
         366           25110 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         367           25110 :   return orig_vfs->xAccess(orig_vfs, zName, flags, pResOut);
         368                 : }
         369                 :
         370                 : int
         371            4389 : xFullPathname(sqlite3_vfs *vfs, const char *zName, int nOut, char *zOut)
         372                 : {
         373            4389 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         374            4389 :   return orig_vfs->xFullPathname(orig_vfs, zName, nOut, zOut);
         375                 : }
         376                 :
         377                 : void*
         378               0 : xDlOpen(sqlite3_vfs *vfs, const char *zFilename)
         379                 : {
         380               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         381               0 :   return orig_vfs->xDlOpen(orig_vfs, zFilename);
         382                 : }
         383                 :
         384                 : void
         385               0 : xDlError(sqlite3_vfs *vfs, int nByte, char *zErrMsg)
         386                 : {
         387               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         388               0 :   orig_vfs->xDlError(orig_vfs, nByte, zErrMsg);
         389               0 : }
         390                 :
         391                 : void
         392               0 : (*xDlSym(sqlite3_vfs *vfs, void *pHdle, const char *zSym))(void){
         393               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         394               0 :   return orig_vfs->xDlSym(orig_vfs, pHdle, zSym);
         395                 : }
         396                 :
         397                 : void
         398               0 : xDlClose(sqlite3_vfs *vfs, void *pHandle)
         399                 : {
         400               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         401               0 :   orig_vfs->xDlClose(orig_vfs, pHandle);
         402               0 : }
         403                 :
         404                 : int
         405             676 : xRandomness(sqlite3_vfs *vfs, int nByte, char *zOut)
         406                 : {
         407             676 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         408             676 :   return orig_vfs->xRandomness(orig_vfs, nByte, zOut);
         409                 : }
         410                 :
         411                 : int
         412               0 : xSleep(sqlite3_vfs *vfs, int microseconds)
         413                 : {
         414               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         415               0 :   return orig_vfs->xSleep(orig_vfs, microseconds);
         416                 : }
         417                 :
         418                 : int
         419               0 : xCurrentTime(sqlite3_vfs *vfs, double *prNow)
         420                 : {
         421               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         422               0 :   return orig_vfs->xCurrentTime(orig_vfs, prNow);
         423                 : }
         424                 :
         425                 : int
         426               0 : xGetLastError(sqlite3_vfs *vfs, int nBuf, char *zBuf)
         427                 : {
         428               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         429               0 :   return orig_vfs->xGetLastError(orig_vfs, nBuf, zBuf);
         430                 : }
         431                 :
         432                 : int
         433           11152 : xCurrentTimeInt64(sqlite3_vfs *vfs, sqlite3_int64 *piNow)
         434                 : {
         435           11152 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         436           11152 :   return orig_vfs->xCurrentTimeInt64(orig_vfs, piNow);
         437                 : }
         438                 :
         439                 : static
         440                 : int
         441               0 : xSetSystemCall(sqlite3_vfs *vfs, const char *zName, sqlite3_syscall_ptr pFunc)
         442                 : {
         443               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         444               0 :   return orig_vfs->xSetSystemCall(orig_vfs, zName, pFunc);
         445                 : }
         446                 :
         447                 : static
         448                 : sqlite3_syscall_ptr
         449               0 : xGetSystemCall(sqlite3_vfs *vfs, const char *zName)
         450                 : {
         451               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         452               0 :   return orig_vfs->xGetSystemCall(orig_vfs, zName);
         453                 : }
         454                 :
         455                 : static
         456                 : const char *
         457               0 : xNextSystemCall(sqlite3_vfs *vfs, const char *zName)
         458                 : {
         459               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         460               0 :   return orig_vfs->xNextSystemCall(orig_vfs, zName);
         461                 : }
         462                 :
         463                 : }
         464                 :
         465                 : namespace mozilla {
         466                 : namespace storage {
         467                 :
         468             783 : sqlite3_vfs* ConstructTelemetryVFS()
         469                 : {
         470                 : #if defined(XP_WIN)
         471                 : #define EXPECTED_VFS "win32"
         472                 : #else
         473                 : #define EXPECTED_VFS "unix"
         474                 : #endif
         475                 :
         476             783 :   sqlite3_vfs *vfs = sqlite3_vfs_find(NULL);
         477             783 :   const bool expected_vfs = vfs->zName && !strcmp(vfs->zName, EXPECTED_VFS);
         478             783 :   if (!expected_vfs) {
         479               0 :     return NULL;
         480                 :   }
         481                 :
         482             783 :   sqlite3_vfs *tvfs = new ::sqlite3_vfs;
         483             783 :   memset(tvfs, 0, sizeof(::sqlite3_vfs));
         484             783 :   tvfs->iVersion = 3;
         485                 :   // If the SQLite VFS version is updated, this shim must be updated as well.
         486             783 :   MOZ_ASSERT(vfs->iVersion == tvfs->iVersion);
         487             783 :   tvfs->szOsFile = sizeof(telemetry_file) - sizeof(sqlite3_file) + vfs->szOsFile;
         488             783 :   tvfs->mxPathname = vfs->mxPathname;
         489             783 :   tvfs->zName = "telemetry-vfs";
         490             783 :   tvfs->pAppData = vfs;
         491             783 :   tvfs->xOpen = xOpen;
         492             783 :   tvfs->xDelete = xDelete;
         493             783 :   tvfs->xAccess = xAccess;
         494             783 :   tvfs->xFullPathname = xFullPathname;
         495             783 :   tvfs->xDlOpen = xDlOpen;
         496             783 :   tvfs->xDlError = xDlError;
         497             783 :   tvfs->xDlSym = xDlSym;
         498             783 :   tvfs->xDlClose = xDlClose;
         499             783 :   tvfs->xRandomness = xRandomness;
         500             783 :   tvfs->xSleep = xSleep;
         501             783 :   tvfs->xCurrentTime = xCurrentTime;
         502             783 :   tvfs->xGetLastError = xGetLastError;
         503                 :   // Added in version 2.
         504             783 :   tvfs->xCurrentTimeInt64 = xCurrentTimeInt64;
         505                 :   // Added in version 3.
         506             783 :   tvfs->xSetSystemCall = xSetSystemCall;
         507             783 :   tvfs->xGetSystemCall = xGetSystemCall;
         508             783 :   tvfs->xNextSystemCall = xNextSystemCall;
         509                 :
         510             783 :   return tvfs;
         511                 : }
         512                 :
         513                 : }
         514                 : }

Generated by: LCOV version 1.7