/ Changes On Branch shared-mapping-hack
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch shared-mapping-hack Excluding Merge-Ins

This is equivalent to a diff from 42f0777555 to 2e57335081

2017-09-18
16:28
Add extension "mmapwarm.c". Provides function sqlite3_mmap_warm(), used to "warm up" the memory mapping used by SQLite in mmap mode to access db file content. (check-in: d4a30b91f9 user: dan tags: mmap-warm)
09:40
The out-of-bounds read on recovery fix of check-in [378afa16381a222a] caused problems for some corner-case error conditions. This alternative fix appears to work better. (check-in: 74f399d81f user: drh tags: trunk)
08:51
Merge latest trunk changes with this branch. (Leaf check-in: 2e57335081 user: dan tags: shared-mapping-hack)
00:18
Fix the CSV virtual table extension so that it works when the default character is unsigned. (check-in: 42f0777555 user: drh tags: trunk)
2017-09-17
19:45
Do not make the assumption (as check-in [4da49a95c0f07] incorrectly did) that the ExprList returned by sqlite3ExprListDup() would never be passed into sqlite3ExprListAppend(). Include a new test case that shows this sometimes does happen. (check-in: 29227d00a9 user: drh tags: trunk)
2017-09-12
18:11
Merge the mutex-free PRNG change into this branch. (check-in: 8b1fc4b9f3 user: dan tags: shared-mapping-hack)

Changes to src/func.c.

   477    477   */
   478    478   static void randomFunc(
   479    479     sqlite3_context *context,
   480    480     int NotUsed,
   481    481     sqlite3_value **NotUsed2
   482    482   ){
   483    483     sqlite_int64 r;
          484  +  sqlite3 *db = sqlite3_context_db_handle(context);
   484    485     UNUSED_PARAMETER2(NotUsed, NotUsed2);
   485         -  sqlite3_randomness(sizeof(r), &r);
          486  +  sqlite3FastRandomness(&db->sPrng, sizeof(r), &r);
   486    487     if( r<0 ){
   487    488       /* We need to prevent a random number of 0x8000000000000000 
   488    489       ** (or -9223372036854775808) since when you do abs() of that
   489    490       ** number of you get the same value back again.  To do this
   490    491       ** in a way that is testable, mask the sign bit off of negative
   491    492       ** values, resulting in a positive value.  Then take the 
   492    493       ** 2s complement of that positive value.  The end result can
................................................................................
   504    505   static void randomBlob(
   505    506     sqlite3_context *context,
   506    507     int argc,
   507    508     sqlite3_value **argv
   508    509   ){
   509    510     int n;
   510    511     unsigned char *p;
          512  +  sqlite3 *db = sqlite3_context_db_handle(context);
   511    513     assert( argc==1 );
   512    514     UNUSED_PARAMETER(argc);
   513    515     n = sqlite3_value_int(argv[0]);
   514    516     if( n<1 ){
   515    517       n = 1;
   516    518     }
   517    519     p = contextMalloc(context, n);
   518    520     if( p ){
   519         -    sqlite3_randomness(n, p);
          521  +    sqlite3FastRandomness(&db->sPrng, n, p);
   520    522       sqlite3_result_blob(context, (char*)p, n, sqlite3_free);
   521    523     }
   522    524   }
   523    525   
   524    526   /*
   525    527   ** Implementation of the last_insert_rowid() SQL function.  The return
   526    528   ** value is the same as the sqlite3_last_insert_rowid() API function.

Changes to src/main.c.

  2861   2861       }
  2862   2862     }
  2863   2863     sqlite3_mutex_enter(db->mutex);
  2864   2864     db->errMask = 0xff;
  2865   2865     db->nDb = 2;
  2866   2866     db->magic = SQLITE_MAGIC_BUSY;
  2867   2867     db->aDb = db->aDbStatic;
         2868  +  sqlite3FastPrngInit(&db->sPrng);
  2868   2869   
  2869   2870     assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
  2870   2871     memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
  2871   2872     db->aLimit[SQLITE_LIMIT_WORKER_THREADS] = SQLITE_DEFAULT_WORKER_THREADS;
  2872   2873     db->autoCommit = 1;
  2873   2874     db->nextAutovac = -1;
  2874   2875     db->szMmap = sqlite3GlobalConfig.szMmap;

Changes to src/os_unix.c.

    42     42   **   *  Locking primitives for the proxy uber-locking-method. (MacOSX only)
    43     43   **   *  Definitions of sqlite3_vfs objects for all locking methods
    44     44   **      plus implementations of sqlite3_os_init() and sqlite3_os_end().
    45     45   */
    46     46   #include "sqliteInt.h"
    47     47   #if SQLITE_OS_UNIX              /* This file is used on unix only */
    48     48   
           49  +/* #define SQLITE_SHARED_MAPPING 1 */
           50  +
    49     51   /*
    50     52   ** There are various methods for file locking used for concurrency
    51     53   ** control:
    52     54   **
    53     55   **   1. POSIX locking (the default),
    54     56   **   2. No locking,
    55     57   **   3. Dot-file locking,
................................................................................
  1111   1113   #if SQLITE_ENABLE_LOCKING_STYLE
  1112   1114     unsigned long long sharedByte;  /* for AFP simulated shared lock */
  1113   1115   #endif
  1114   1116   #if OS_VXWORKS
  1115   1117     sem_t *pSem;                    /* Named POSIX semaphore */
  1116   1118     char aSemName[MAX_PATHNAME+2];  /* Name of that semaphore */
  1117   1119   #endif
         1120  +#ifdef SQLITE_SHARED_MAPPING
         1121  +  sqlite3_int64 nSharedMapping;   /* Size of mapped region in bytes */
         1122  +  void *pSharedMapping;           /* Memory mapped region */
         1123  +#endif
  1118   1124   };
  1119   1125   
  1120   1126   /*
  1121   1127   ** A lists of all unixInodeInfo objects.
  1122   1128   */
  1123   1129   static unixInodeInfo *inodeList = 0;  /* All unixInodeInfo objects */
  1124   1130   static unsigned int nUnusedFd = 0;    /* Total unused file descriptors */
................................................................................
  1245   1251   static void releaseInodeInfo(unixFile *pFile){
  1246   1252     unixInodeInfo *pInode = pFile->pInode;
  1247   1253     assert( unixMutexHeld() );
  1248   1254     if( ALWAYS(pInode) ){
  1249   1255       pInode->nRef--;
  1250   1256       if( pInode->nRef==0 ){
  1251   1257         assert( pInode->pShmNode==0 );
         1258  +#ifdef SQLITE_SHARED_MAPPING
         1259  +      if( pInode->pSharedMapping ){
         1260  +        osMunmap(pInode->pSharedMapping, pInode->nSharedMapping);
         1261  +        pInode->pSharedMapping = 0;
         1262  +        pInode->nSharedMapping = 0;
         1263  +      }
         1264  +#endif
  1252   1265         closePendingFds(pFile);
  1253   1266         if( pInode->pPrev ){
  1254   1267           assert( pInode->pPrev->pNext==pInode );
  1255   1268           pInode->pPrev->pNext = pInode->pNext;
  1256   1269         }else{
  1257   1270           assert( inodeList==pInode );
  1258   1271           inodeList = pInode->pNext;
................................................................................
  2051   2064     return SQLITE_OK;
  2052   2065   }
  2053   2066   
  2054   2067   /*
  2055   2068   ** Close the file.
  2056   2069   */
  2057   2070   static int nolockClose(sqlite3_file *id) {
         2071  +#ifdef SQLITE_SHARED_MAPPING
         2072  +  unixFile *pFd = (unixFile*)id;
         2073  +  if( pFd->pInode ){
         2074  +    unixEnterMutex();
         2075  +    releaseInodeInfo(pFd);
         2076  +    unixLeaveMutex();
         2077  +  }
         2078  +#endif
  2058   2079     return closeUnixFile(id);
  2059   2080   }
  2060   2081   
  2061   2082   /******************* End of the no-op lock implementation *********************
  2062   2083   ******************************************************************************/
  2063   2084   
  2064   2085   /******************************************************************************
................................................................................
  3870   3891         if( newLimit>0 && sizeof(size_t)<8 ){
  3871   3892           newLimit = (newLimit & 0x7FFFFFFF);
  3872   3893         }
  3873   3894   
  3874   3895         *(i64*)pArg = pFile->mmapSizeMax;
  3875   3896         if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
  3876   3897           pFile->mmapSizeMax = newLimit;
         3898  +#ifdef SQLITE_SHARED_MAPPING
         3899  +        if( pFile->pInode==0 )
         3900  +#endif
  3877   3901           if( pFile->mmapSize>0 ){
  3878   3902             unixUnmapfile(pFile);
  3879   3903             rc = unixMapfile(pFile, -1);
  3880   3904           }
  3881   3905         }
  3882   3906         return rc;
  3883   3907       }
................................................................................
  4770   4794   
  4771   4795   #if SQLITE_MAX_MMAP_SIZE>0
  4772   4796   /*
  4773   4797   ** If it is currently memory mapped, unmap file pFd.
  4774   4798   */
  4775   4799   static void unixUnmapfile(unixFile *pFd){
  4776   4800     assert( pFd->nFetchOut==0 );
         4801  +#ifdef SQLITE_SHARED_MAPPING
         4802  +  if( pFd->pInode ) return;
         4803  +#endif
  4777   4804     if( pFd->pMapRegion ){
  4778   4805       osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
  4779   4806       pFd->pMapRegion = 0;
  4780   4807       pFd->mmapSize = 0;
  4781   4808       pFd->mmapSizeActual = 0;
  4782   4809     }
  4783   4810   }
................................................................................
  4900   4927         return SQLITE_IOERR_FSTAT;
  4901   4928       }
  4902   4929       nMap = statbuf.st_size;
  4903   4930     }
  4904   4931     if( nMap>pFd->mmapSizeMax ){
  4905   4932       nMap = pFd->mmapSizeMax;
  4906   4933     }
         4934  +
         4935  +#ifdef SQLITE_SHARED_MAPPING
         4936  +  if( pFd->pInode ){
         4937  +    unixInodeInfo *pInode = pFd->pInode;
         4938  +    if( pFd->pMapRegion ) return SQLITE_OK;
         4939  +    unixEnterMutex();
         4940  +    if( pInode->pSharedMapping==0 ){
         4941  +      u8 *pNew = osMmap(0, nMap, PROT_READ, MAP_SHARED, pFd->h, 0);
         4942  +      if( pNew==MAP_FAILED ){
         4943  +        unixLogError(SQLITE_OK, "mmap", pFd->zPath);
         4944  +        pFd->mmapSizeMax = 0;
         4945  +      }else{
         4946  +        pInode->pSharedMapping = pNew;
         4947  +        pInode->nSharedMapping = nMap;
         4948  +      }
         4949  +    }
         4950  +    pFd->pMapRegion = pInode->pSharedMapping;
         4951  +    pFd->mmapSizeActual = pFd->mmapSize = pInode->nSharedMapping;
         4952  +    unixLeaveMutex();
         4953  +    return SQLITE_OK;
         4954  +  }
         4955  +#endif
  4907   4956   
  4908   4957     assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) );
  4909   4958     if( nMap!=pFd->mmapSize ){
  4910   4959       unixRemapfile(pFd, nMap);
  4911   4960     }
  4912   4961   
  4913   4962     return SQLITE_OK;
................................................................................
  5339   5388   #endif
  5340   5389     }
  5341   5390   
  5342   5391     if( pLockingStyle == &posixIoMethods
  5343   5392   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  5344   5393       || pLockingStyle == &nfsIoMethods
  5345   5394   #endif
         5395  +#ifdef SQLITE_SHARED_MAPPING
         5396  +    || pLockingStyle == &nolockIoMethods
         5397  +#endif
  5346   5398     ){
  5347   5399       unixEnterMutex();
  5348   5400       rc = findInodeInfo(pNew, &pNew->pInode);
  5349   5401       if( rc!=SQLITE_OK ){
  5350   5402         /* If an error occurred in findInodeInfo(), close the file descriptor
  5351   5403         ** immediately, before releasing the mutex. findInodeInfo() may fail
  5352   5404         ** in two scenarios:

Changes to src/random.c.

   101    101       wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
   102    102       wsdPrng.s[wsdPrng.j] = t;
   103    103       t += wsdPrng.s[wsdPrng.i];
   104    104       *(zBuf++) = wsdPrng.s[t];
   105    105     }while( --N );
   106    106     sqlite3_mutex_leave(mutex);
   107    107   }
          108  +
          109  +/*
          110  +** Initialize a fast PRNG.  A Fast PRNG is called "fast" because it does
          111  +** not need a mutex to operate, though it does use a mutex to initialize.
          112  +** The quality of the randomness is not as good as the global PRNG.
          113  +*/
          114  +void sqlite3FastPrngInit(FastPrng *pPrng){
          115  +  sqlite3_randomness(sizeof(*pPrng), pPrng);
          116  +  pPrng->x |= 1;
          117  +}
          118  +
          119  +/*
          120  +** Generate N bytes of pseudo-randomness using a FastPrng
          121  +*/
          122  +void sqlite3FastRandomness(FastPrng *pPrng, int N, void *P){
          123  +  unsigned char *pOut = (unsigned char*)P;
          124  +  while( N-->0 ){
          125  +    pPrng->x = ((pPrng->x)>>1) ^ ((1+~((pPrng->x)&1)) & 0xd0000001);
          126  +    pPrng->y = (pPrng->y)*1103515245 + 12345;
          127  +    *(pOut++) = (pPrng->x ^ pPrng->y) & 0xff;
          128  +  }
          129  +}
   108    130   
   109    131   #ifndef SQLITE_UNTESTABLE
   110    132   /*
   111    133   ** For testing purposes, we sometimes want to preserve the state of
   112    134   ** PRNG and restore the PRNG to its saved state at a later time, or
   113    135   ** to reset the PRNG to its initial state.  These routines accomplish
   114    136   ** those tasks.

Changes to src/select.c.

  1740   1740       while( zName && sqlite3HashFind(&ht, zName)!=0 ){
  1741   1741         nName = sqlite3Strlen30(zName);
  1742   1742         if( nName>0 ){
  1743   1743           for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){}
  1744   1744           if( zName[j]==':' ) nName = j;
  1745   1745         }
  1746   1746         zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt);
  1747         -      if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt);
         1747  +      if( cnt>3 ) sqlite3FastRandomness(&db->sPrng, sizeof(cnt), &cnt);
  1748   1748       }
  1749   1749       pCol->zName = zName;
  1750   1750       sqlite3ColumnPropertiesFromName(0, pCol);
  1751   1751       if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){
  1752   1752         sqlite3OomFault(db);
  1753   1753       }
  1754   1754     }

Changes to src/sqliteInt.h.

  1061   1061   typedef struct Lookaside Lookaside;
  1062   1062   typedef struct LookasideSlot LookasideSlot;
  1063   1063   typedef struct Module Module;
  1064   1064   typedef struct NameContext NameContext;
  1065   1065   typedef struct Parse Parse;
  1066   1066   typedef struct PreUpdate PreUpdate;
  1067   1067   typedef struct PrintfArguments PrintfArguments;
         1068  +typedef struct FastPrng FastPrng;
  1068   1069   typedef struct RowSet RowSet;
  1069   1070   typedef struct Savepoint Savepoint;
  1070   1071   typedef struct Select Select;
  1071   1072   typedef struct SQLiteThread SQLiteThread;
  1072   1073   typedef struct SelectDest SelectDest;
  1073   1074   typedef struct SrcList SrcList;
  1074   1075   typedef struct StrAccum StrAccum;
................................................................................
  1132   1133   */
  1133   1134   #ifndef SQLITE_DEFAULT_SYNCHRONOUS
  1134   1135   # define SQLITE_DEFAULT_SYNCHRONOUS 2
  1135   1136   #endif
  1136   1137   #ifndef SQLITE_DEFAULT_WAL_SYNCHRONOUS
  1137   1138   # define SQLITE_DEFAULT_WAL_SYNCHRONOUS SQLITE_DEFAULT_SYNCHRONOUS
  1138   1139   #endif
         1140  +
         1141  +/*
         1142  +** State of a simple PRNG used for the per-connection and per-pager
         1143  +** pseudo-random number generators.
         1144  +*/
         1145  +struct FastPrng {
         1146  +  unsigned int x, y;
         1147  +};
  1139   1148   
  1140   1149   /*
  1141   1150   ** Each database file to be accessed by the system is an instance
  1142   1151   ** of the following structure.  There are normally two of these structures
  1143   1152   ** in the sqlite.aDb[] array.  aDb[0] is the main database file and
  1144   1153   ** aDb[1] is the database file used to hold temporary tables.  Additional
  1145   1154   ** databases may be attached.
................................................................................
  1339   1348     u8 vtabOnConflict;            /* Value to return for s3_vtab_on_conflict() */
  1340   1349     u8 isTransactionSavepoint;    /* True if the outermost savepoint is a TS */
  1341   1350     u8 mTrace;                    /* zero or more SQLITE_TRACE flags */
  1342   1351     u8 skipBtreeMutex;            /* True if no shared-cache backends */
  1343   1352     u8 nSqlExec;                  /* Number of pending OP_SqlExec opcodes */
  1344   1353     int nextPagesize;             /* Pagesize after VACUUM if >0 */
  1345   1354     u32 magic;                    /* Magic number for detect library misuse */
         1355  +  FastPrng sPrng;               /* State of the per-connection PRNG */
  1346   1356     int nChange;                  /* Value returned by sqlite3_changes() */
  1347   1357     int nTotalChange;             /* Value returned by sqlite3_total_changes() */
  1348   1358     int aLimit[SQLITE_N_LIMIT];   /* Limits */
  1349   1359     int nMaxSorterMmap;           /* Maximum size of regions mapped by sorter */
  1350   1360     struct sqlite3InitInfo {      /* Information used during initialization */
  1351   1361       int newTnum;                /* Rootpage of table being initialized */
  1352   1362       u8 iDb;                     /* Which db file is being initialized */
................................................................................
  3808   3818   int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
  3809   3819   int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
  3810   3820   Vdbe *sqlite3GetVdbe(Parse*);
  3811   3821   #ifndef SQLITE_UNTESTABLE
  3812   3822   void sqlite3PrngSaveState(void);
  3813   3823   void sqlite3PrngRestoreState(void);
  3814   3824   #endif
         3825  +void sqlite3FastPrngInit(FastPrng*);
         3826  +void sqlite3FastRandomness(FastPrng*, int N, void *P);
  3815   3827   void sqlite3RollbackAll(sqlite3*,int);
  3816   3828   void sqlite3CodeVerifySchema(Parse*, int);
  3817   3829   void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
  3818   3830   void sqlite3BeginTransaction(Parse*, int);
  3819   3831   void sqlite3EndTransaction(Parse*,int);
  3820   3832   void sqlite3Savepoint(Parse*, int, Token*);
  3821   3833   void sqlite3CloseSavepoints(sqlite3 *);

Changes to src/wal.c.

   444    444     u8 syncHeader;             /* Fsync the WAL header if true */
   445    445     u8 padToSectorBoundary;    /* Pad transactions out to the next sector */
   446    446     WalIndexHdr hdr;           /* Wal-index header for current transaction */
   447    447     u32 minFrame;              /* Ignore wal frames before this one */
   448    448     u32 iReCksum;              /* On commit, recalculate checksums from here */
   449    449     const char *zWalName;      /* Name of WAL file */
   450    450     u32 nCkpt;                 /* Checkpoint sequence counter in the wal-header */
          451  +  FastPrng sPrng;            /* Random number generator */
   451    452   #ifdef SQLITE_DEBUG
   452    453     u8 lockError;              /* True if a locking error has occurred */
   453    454   #endif
   454    455   #ifdef SQLITE_ENABLE_SNAPSHOT
   455    456     WalIndexHdr *pSnapshot;    /* Start transaction here if not NULL */
   456    457   #endif
   457    458   };
................................................................................
  1319   1320     pRet->pDbFd = pDbFd;
  1320   1321     pRet->readLock = -1;
  1321   1322     pRet->mxWalSize = mxWalSize;
  1322   1323     pRet->zWalName = zWalName;
  1323   1324     pRet->syncHeader = 1;
  1324   1325     pRet->padToSectorBoundary = 1;
  1325   1326     pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
         1327  +  sqlite3FastPrngInit(&pRet->sPrng);
  1326   1328   
  1327   1329     /* Open file handle on the write-ahead log file. */
  1328   1330     flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
  1329   1331     rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
  1330   1332     if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){
  1331   1333       pRet->readOnly = WAL_RDONLY;
  1332   1334     }
................................................................................
  1866   1868     */
  1867   1869     if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){
  1868   1870       assert( pWal->writeLock );
  1869   1871       if( pInfo->nBackfill<pWal->hdr.mxFrame ){
  1870   1872         rc = SQLITE_BUSY;
  1871   1873       }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){
  1872   1874         u32 salt1;
  1873         -      sqlite3_randomness(4, &salt1);
         1875  +      sqlite3FastRandomness(&pWal->sPrng, 4, &salt1);
  1874   1876         assert( pInfo->nBackfill==pWal->hdr.mxFrame );
  1875   1877         rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1);
  1876   1878         if( rc==SQLITE_OK ){
  1877   1879           if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){
  1878   1880             /* IMPLEMENTATION-OF: R-44699-57140 This mode works the same way as
  1879   1881             ** SQLITE_CHECKPOINT_RESTART with the addition that it also
  1880   1882             ** truncates the log file to zero bytes just prior to a
................................................................................
  2874   2876     int cnt;
  2875   2877   
  2876   2878     if( pWal->readLock==0 ){
  2877   2879       volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
  2878   2880       assert( pInfo->nBackfill==pWal->hdr.mxFrame );
  2879   2881       if( pInfo->nBackfill>0 ){
  2880   2882         u32 salt1;
  2881         -      sqlite3_randomness(4, &salt1);
         2883  +      sqlite3FastRandomness(&pWal->sPrng, 4, &salt1);
  2882   2884         rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
  2883   2885         if( rc==SQLITE_OK ){
  2884   2886           /* If all readers are using WAL_READ_LOCK(0) (in other words if no
  2885   2887           ** readers are currently using the WAL), then the transactions
  2886   2888           ** frames will overwrite the start of the existing log. Update the
  2887   2889           ** wal-index header to reflect this.
  2888   2890           **
................................................................................
  3090   3092       u8 aWalHdr[WAL_HDRSIZE];      /* Buffer to assemble wal-header in */
  3091   3093       u32 aCksum[2];                /* Checksum for wal-header */
  3092   3094   
  3093   3095       sqlite3Put4byte(&aWalHdr[0], (WAL_MAGIC | SQLITE_BIGENDIAN));
  3094   3096       sqlite3Put4byte(&aWalHdr[4], WAL_MAX_VERSION);
  3095   3097       sqlite3Put4byte(&aWalHdr[8], szPage);
  3096   3098       sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt);
  3097         -    if( pWal->nCkpt==0 ) sqlite3_randomness(8, pWal->hdr.aSalt);
         3099  +    if( pWal->nCkpt==0 ) sqlite3FastRandomness(&pWal->sPrng, 8, pWal->hdr.aSalt);
  3098   3100       memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8);
  3099   3101       walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum);
  3100   3102       sqlite3Put4byte(&aWalHdr[24], aCksum[0]);
  3101   3103       sqlite3Put4byte(&aWalHdr[28], aCksum[1]);
  3102   3104       
  3103   3105       pWal->szPage = szPage;
  3104   3106       pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN;