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