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-07-07 | 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("urlclassifier3.sqlite", URLCLASSIFIER),
          71                 :   SQLITE_TELEMETRY("cookies.sqlite", COOKIES),
          72                 :   SQLITE_TELEMETRY("webappsstore.sqlite", WEBAPPS),
          73                 :   SQLITE_TELEMETRY(NULL, OTHER)
          74                 : };
          75                 : #undef SQLITE_TELEMETRY
          76                 :
          77                 : /** RAII class for measuring how long io takes on/off main thread
          78                 :  */
          79                 : class IOThreadAutoTimer {
          80                 : public:
          81                 :   /**
          82                 :    * IOThreadAutoTimer measures time spent in IO. Additionally it
          83                 :    * automatically determines whether IO is happening on the main
          84                 :    * thread and picks an appropriate histogram.
          85                 :    *
          86                 :    * @param id takes a telemetry histogram id. The id+1 must be an
          87                 :    * equivalent histogram for the main thread. Eg, MOZ_SQLITE_OPEN_MS
          88                 :    * is followed by MOZ_SQLITE_OPEN_MAIN_THREAD_MS.
          89                 :    */
          90          508710 :   IOThreadAutoTimer(Telemetry::ID id)
          91                 :     : start(TimeStamp::Now()),
          92          508710 :       id(id)
          93                 :   {
          94          508710 :   }
          95                 :
          96          508710 :   ~IOThreadAutoTimer() {
          97          508710 :     PRUint32 mainThread = NS_IsMainThread() ? 1 : 0;
          98                 :     Telemetry::AccumulateTimeDelta(static_cast<Telemetry::ID>(id + mainThread),
          99          508710 :                                    start);
         100          508710 :   }
         101                 :
         102                 : private:
         103                 :   const TimeStamp start;
         104                 :   const Telemetry::ID id;
         105                 : };
         106                 :
         107                 : struct telemetry_file {
         108                 :   sqlite3_file base;        // Base class.  Must be first
         109                 :   Histograms *histograms;   // histograms pertaining to this file
         110                 :   sqlite3_file pReal[1];    // This contains the vfs that actually does work
         111                 : };
         112                 :
         113                 : /*
         114                 : ** Close a telemetry_file.
         115                 : */
         116                 : int
         117           11078 : xClose(sqlite3_file *pFile)
         118                 : {
         119           11078 :   telemetry_file *p = (telemetry_file *)pFile;
         120                 :   int rc;
         121           11078 :   rc = p->pReal->pMethods->xClose(p->pReal);
         122           11078 :   if( rc==SQLITE_OK ){
         123           11078 :     delete p->base.pMethods;
         124           11078 :     p->base.pMethods = NULL;
         125                 :   }
         126           11078 :   return rc;
         127                 : }
         128                 :
         129                 : /*
         130                 : ** Read data from a telemetry_file.
         131                 : */
         132                 : int
         133           78626 : xRead(sqlite3_file *pFile, void *zBuf, int iAmt, sqlite_int64 iOfst)
         134                 : {
         135           78626 :   telemetry_file *p = (telemetry_file *)pFile;
         136          157252 :   IOThreadAutoTimer ioTimer(p->histograms->readMS);
         137                 :   int rc;
         138           78626 :   rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
         139                 :   // sqlite likes to read from empty files, this is normal, ignore it.
         140           78626 :   if (rc != SQLITE_IOERR_SHORT_READ)
         141           71986 :     Telemetry::Accumulate(p->histograms->readB, rc == SQLITE_OK ? iAmt : 0);
         142           78626 :   return rc;
         143                 : }
         144                 :
         145                 : /*
         146                 : ** Write data to a telemetry_file.
         147                 : */
         148                 : int
         149          383609 : xWrite(sqlite3_file *pFile, const void *zBuf, int iAmt, sqlite_int64 iOfst)
         150                 : {
         151          383609 :   telemetry_file *p = (telemetry_file *)pFile;
         152          767218 :   IOThreadAutoTimer ioTimer(p->histograms->writeMS);
         153                 :   int rc;
         154          383609 :   rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
         155          383609 :   Telemetry::Accumulate(p->histograms->writeB, rc == SQLITE_OK ? iAmt : 0);
         156          383609 :   return rc;
         157                 : }
         158                 :
         159                 : /*
         160                 : ** Truncate a telemetry_file.
         161                 : */
         162                 : int
         163            7672 : xTruncate(sqlite3_file *pFile, sqlite_int64 size)
         164                 : {
         165           15344 :   IOThreadAutoTimer ioTimer(Telemetry::MOZ_SQLITE_TRUNCATE_MS);
         166            7672 :   telemetry_file *p = (telemetry_file *)pFile;
         167                 :   int rc;
         168           15344 :   Telemetry::AutoTimer<Telemetry::MOZ_SQLITE_TRUNCATE_MS> timer;
         169            7672 :   rc = p->pReal->pMethods->xTruncate(p->pReal, size);
         170            7672 :   return rc;
         171                 : }
         172                 :
         173                 : /*
         174                 : ** Sync a telemetry_file.
         175                 : */
         176                 : int
         177           27721 : xSync(sqlite3_file *pFile, int flags)
         178                 : {
         179           27721 :   telemetry_file *p = (telemetry_file *)pFile;
         180           55442 :   IOThreadAutoTimer ioTimer(p->histograms->syncMS);
         181           27721 :   return p->pReal->pMethods->xSync(p->pReal, flags);
         182                 : }
         183                 :
         184                 : /*
         185                 : ** Return the current file-size of a telemetry_file.
         186                 : */
         187                 : int
         188           55829 : xFileSize(sqlite3_file *pFile, sqlite_int64 *pSize)
         189                 : {
         190           55829 :   telemetry_file *p = (telemetry_file *)pFile;
         191                 :   int rc;
         192           55829 :   rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
         193           55829 :   return rc;
         194                 : }
         195                 :
         196                 : /*
         197                 : ** Lock a telemetry_file.
         198                 : */
         199                 : int
         200           31614 : xLock(sqlite3_file *pFile, int eLock)
         201                 : {
         202           31614 :   telemetry_file *p = (telemetry_file *)pFile;
         203                 :   int rc;
         204           31614 :   rc = p->pReal->pMethods->xLock(p->pReal, eLock);
         205           31614 :   return rc;
         206                 : }
         207                 :
         208                 : /*
         209                 : ** Unlock a telemetry_file.
         210                 : */
         211                 : int
         212           25361 : xUnlock(sqlite3_file *pFile, int eLock)
         213                 : {
         214           25361 :   telemetry_file *p = (telemetry_file *)pFile;
         215                 :   int rc;
         216           25361 :   rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
         217           25361 :   return rc;
         218                 : }
         219                 :
         220                 : /*
         221                 : ** Check if another file-handle holds a RESERVED lock on a telemetry_file.
         222                 : */
         223                 : int
         224               0 : xCheckReservedLock(sqlite3_file *pFile, int *pResOut)
         225                 : {
         226               0 :   telemetry_file *p = (telemetry_file *)pFile;
         227               0 :   int rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
         228               0 :   return rc;
         229                 : }
         230                 :
         231                 : /*
         232                 : ** File control method. For custom operations on a telemetry_file.
         233                 : */
         234                 : int
         235            6080 : xFileControl(sqlite3_file *pFile, int op, void *pArg)
         236                 : {
         237            6080 :   telemetry_file *p = (telemetry_file *)pFile;
         238            6080 :   int rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
         239            6080 :   return rc;
         240                 : }
         241                 :
         242                 : /*
         243                 : ** Return the sector-size in bytes for a telemetry_file.
         244                 : */
         245                 : int
         246               0 : xSectorSize(sqlite3_file *pFile)
         247                 : {
         248               0 :   telemetry_file *p = (telemetry_file *)pFile;
         249                 :   int rc;
         250               0 :   rc = p->pReal->pMethods->xSectorSize(p->pReal);
         251               0 :   return rc;
         252                 : }
         253                 :
         254                 : /*
         255                 : ** Return the device characteristic flags supported by a telemetry_file.
         256                 : */
         257                 : int
         258           37325 : xDeviceCharacteristics(sqlite3_file *pFile)
         259                 : {
         260           37325 :   telemetry_file *p = (telemetry_file *)pFile;
         261                 :   int rc;
         262           37325 :   rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
         263           37325 :   return rc;
         264                 : }
         265                 :
         266                 : /*
         267                 : ** Shared-memory operations.
         268                 : */
         269                 : int
         270          238155 : xShmLock(sqlite3_file *pFile, int ofst, int n, int flags)
         271                 : {
         272          238155 :   telemetry_file *p = (telemetry_file *)pFile;
         273          238155 :   return p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
         274                 : }
         275                 :
         276                 : int
         277             779 : xShmMap(sqlite3_file *pFile, int iRegion, int szRegion, int isWrite, void volatile **pp)
         278                 : {
         279             779 :   telemetry_file *p = (telemetry_file *)pFile;
         280                 :   int rc;
         281             779 :   rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
         282             779 :   return rc;
         283                 : }
         284                 :
         285                 : void
         286          122667 : xShmBarrier(sqlite3_file *pFile){
         287          122667 :   telemetry_file *p = (telemetry_file *)pFile;
         288          122667 :   p->pReal->pMethods->xShmBarrier(p->pReal);
         289          122667 : }
         290                 :
         291                 : int
         292             426 : xShmUnmap(sqlite3_file *pFile, int delFlag){
         293             426 :   telemetry_file *p = (telemetry_file *)pFile;
         294                 :   int rc;
         295             426 :   rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
         296             426 :   return rc;
         297                 : }
         298                 :
         299                 : int
         300           11082 : xOpen(sqlite3_vfs* vfs, const char *zName, sqlite3_file* pFile,
         301                 :           int flags, int *pOutFlags)
         302                 : {
         303           22164 :   IOThreadAutoTimer ioTimer(Telemetry::MOZ_SQLITE_OPEN_MS);
         304           22164 :   Telemetry::AutoTimer<Telemetry::MOZ_SQLITE_OPEN_MS> timer;
         305           11082 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         306                 :   int rc;
         307           11082 :   telemetry_file *p = (telemetry_file *)pFile;
         308           11082 :   Histograms *h = NULL;
         309                 :   // check if the filename is one we are probing for
         310           46892 :   for(size_t i = 0;i < sizeof(gHistograms)/sizeof(gHistograms[0]);i++) {
         311           46892 :     h = &gHistograms[i];
         312                 :     // last probe is the fallback probe
         313           46892 :     if (!h->name)
         314            8008 :       break;
         315           38884 :     if (!zName)
         316            1644 :       continue;
         317           37240 :     const char *match = strstr(zName, h->name);
         318           37240 :     if (!match)
         319           34162 :       continue;
         320            3078 :     char c = match[strlen(h->name)];
         321                 :     // include -wal/-journal too
         322            3078 :     if (!c || c == '-')
         323            3074 :       break;
         324                 :   }
         325           11082 :   p->histograms = h;
         326           11082 :   rc = orig_vfs->xOpen(orig_vfs, zName, p->pReal, flags, pOutFlags);
         327           11082 :   if( rc != SQLITE_OK )
         328               4 :     return rc;
         329           11078 :   if( p->pReal->pMethods ){
         330           11078 :     sqlite3_io_methods *pNew = new sqlite3_io_methods;
         331           11078 :     const sqlite3_io_methods *pSub = p->pReal->pMethods;
         332           11078 :     memset(pNew, 0, sizeof(*pNew));
         333           11078 :     pNew->iVersion = pSub->iVersion;
         334           11078 :     pNew->xClose = xClose;
         335           11078 :     pNew->xRead = xRead;
         336           11078 :     pNew->xWrite = xWrite;
         337           11078 :     pNew->xTruncate = xTruncate;
         338           11078 :     pNew->xSync = xSync;
         339           11078 :     pNew->xFileSize = xFileSize;
         340           11078 :     pNew->xLock = xLock;
         341           11078 :     pNew->xUnlock = xUnlock;
         342           11078 :     pNew->xCheckReservedLock = xCheckReservedLock;
         343           11078 :     pNew->xFileControl = xFileControl;
         344           11078 :     pNew->xSectorSize = xSectorSize;
         345           11078 :     pNew->xDeviceCharacteristics = xDeviceCharacteristics;
         346           11078 :     if( pNew->iVersion>=2 ){
         347            3090 :       pNew->xShmMap = pSub->xShmMap ? xShmMap : 0;
         348            3090 :       pNew->xShmLock = pSub->xShmLock ? xShmLock : 0;
         349            3090 :       pNew->xShmBarrier = pSub->xShmBarrier ? xShmBarrier : 0;
         350            3090 :       pNew->xShmUnmap = pSub->xShmUnmap ? xShmUnmap : 0;
         351                 :     }
         352           11078 :     pFile->pMethods = pNew;
         353                 :   }
         354           11078 :   return rc;
         355                 : }
         356                 :
         357                 : int
         358           10941 : xDelete(sqlite3_vfs* vfs, const char *zName, int syncDir)
         359                 : {
         360           10941 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         361           10941 :   return orig_vfs->xDelete(orig_vfs, zName, syncDir);
         362                 : }
         363                 :
         364                 : int
         365           29025 : xAccess(sqlite3_vfs *vfs, const char *zName, int flags, int *pResOut)
         366                 : {
         367           29025 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         368           29025 :   return orig_vfs->xAccess(orig_vfs, zName, flags, pResOut);
         369                 : }
         370                 :
         371                 : int
         372            4549 : xFullPathname(sqlite3_vfs *vfs, const char *zName, int nOut, char *zOut)
         373                 : {
         374            4549 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         375            4549 :   return orig_vfs->xFullPathname(orig_vfs, zName, nOut, zOut);
         376                 : }
         377                 :
         378                 : void*
         379               0 : xDlOpen(sqlite3_vfs *vfs, const char *zFilename)
         380                 : {
         381               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         382               0 :   return orig_vfs->xDlOpen(orig_vfs, zFilename);
         383                 : }
         384                 :
         385                 : void
         386               0 : xDlError(sqlite3_vfs *vfs, int nByte, char *zErrMsg)
         387                 : {
         388               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         389               0 :   orig_vfs->xDlError(orig_vfs, nByte, zErrMsg);
         390               0 : }
         391                 :
         392                 : void
         393               0 : (*xDlSym(sqlite3_vfs *vfs, void *pHdle, const char *zSym))(void){
         394               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         395               0 :   return orig_vfs->xDlSym(orig_vfs, pHdle, zSym);
         396                 : }
         397                 :
         398                 : void
         399               0 : xDlClose(sqlite3_vfs *vfs, void *pHandle)
         400                 : {
         401               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         402               0 :   orig_vfs->xDlClose(orig_vfs, pHandle);
         403               0 : }
         404                 :
         405                 : int
         406             689 : xRandomness(sqlite3_vfs *vfs, int nByte, char *zOut)
         407                 : {
         408             689 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         409             689 :   return orig_vfs->xRandomness(orig_vfs, nByte, zOut);
         410                 : }
         411                 :
         412                 : int
         413               0 : xSleep(sqlite3_vfs *vfs, int microseconds)
         414                 : {
         415               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         416               0 :   return orig_vfs->xSleep(orig_vfs, microseconds);
         417                 : }
         418                 :
         419                 : int
         420               0 : xCurrentTime(sqlite3_vfs *vfs, double *prNow)
         421                 : {
         422               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         423               0 :   return orig_vfs->xCurrentTime(orig_vfs, prNow);
         424                 : }
         425                 :
         426                 : int
         427               0 : xGetLastError(sqlite3_vfs *vfs, int nBuf, char *zBuf)
         428                 : {
         429               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         430               0 :   return orig_vfs->xGetLastError(orig_vfs, nBuf, zBuf);
         431                 : }
         432                 :
         433                 : int
         434           10623 : xCurrentTimeInt64(sqlite3_vfs *vfs, sqlite3_int64 *piNow)
         435                 : {
         436           10623 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         437           10623 :   return orig_vfs->xCurrentTimeInt64(orig_vfs, piNow);
         438                 : }
         439                 :
         440                 : static
         441                 : int
         442               0 : xSetSystemCall(sqlite3_vfs *vfs, const char *zName, sqlite3_syscall_ptr pFunc)
         443                 : {
         444               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         445               0 :   return orig_vfs->xSetSystemCall(orig_vfs, zName, pFunc);
         446                 : }
         447                 :
         448                 : static
         449                 : sqlite3_syscall_ptr
         450               0 : xGetSystemCall(sqlite3_vfs *vfs, const char *zName)
         451                 : {
         452               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         453               0 :   return orig_vfs->xGetSystemCall(orig_vfs, zName);
         454                 : }
         455                 :
         456                 : static
         457                 : const char *
         458               0 : xNextSystemCall(sqlite3_vfs *vfs, const char *zName)
         459                 : {
         460               0 :   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
         461               0 :   return orig_vfs->xNextSystemCall(orig_vfs, zName);
         462                 : }
         463                 :
         464                 : }
         465                 :
         466                 : namespace mozilla {
         467                 : namespace storage {
         468                 :
         469             803 : sqlite3_vfs* ConstructTelemetryVFS()
         470                 : {
         471                 : #if defined(XP_WIN)
         472                 : #define EXPECTED_VFS "win32"
         473                 : #else
         474                 : #define EXPECTED_VFS "unix"
         475                 : #endif
         476                 :
         477             803 :   sqlite3_vfs *vfs = sqlite3_vfs_find(NULL);
         478             803 :   const bool expected_vfs = vfs->zName && !strcmp(vfs->zName, EXPECTED_VFS);
         479             803 :   if (!expected_vfs) {
         480               0 :     return NULL;
         481                 :   }
         482                 :
         483             803 :   sqlite3_vfs *tvfs = new ::sqlite3_vfs;
         484             803 :   memset(tvfs, 0, sizeof(::sqlite3_vfs));
         485             803 :   tvfs->iVersion = 3;
         486                 :   // If the SQLite VFS version is updated, this shim must be updated as well.
         487             803 :   MOZ_ASSERT(vfs->iVersion == tvfs->iVersion);
         488             803 :   tvfs->szOsFile = sizeof(telemetry_file) - sizeof(sqlite3_file) + vfs->szOsFile;
         489             803 :   tvfs->mxPathname = vfs->mxPathname;
         490             803 :   tvfs->zName = "telemetry-vfs";
         491             803 :   tvfs->pAppData = vfs;
         492             803 :   tvfs->xOpen = xOpen;
         493             803 :   tvfs->xDelete = xDelete;
         494             803 :   tvfs->xAccess = xAccess;
         495             803 :   tvfs->xFullPathname = xFullPathname;
         496             803 :   tvfs->xDlOpen = xDlOpen;
         497             803 :   tvfs->xDlError = xDlError;
         498             803 :   tvfs->xDlSym = xDlSym;
         499             803 :   tvfs->xDlClose = xDlClose;
         500             803 :   tvfs->xRandomness = xRandomness;
         501             803 :   tvfs->xSleep = xSleep;
         502             803 :   tvfs->xCurrentTime = xCurrentTime;
         503             803 :   tvfs->xGetLastError = xGetLastError;
         504                 :   // Added in version 2.
         505             803 :   tvfs->xCurrentTimeInt64 = xCurrentTimeInt64;
         506                 :   // Added in version 3.
         507             803 :   tvfs->xSetSystemCall = xSetSystemCall;
         508             803 :   tvfs->xGetSystemCall = xGetSystemCall;
         509             803 :   tvfs->xNextSystemCall = xNextSystemCall;
         510                 :
         511             803 :   return tvfs;
         512                 : }
         513                 :
         514                 : }
         515                 : }

Generated by: LCOV version 1.7