Cloud Backed SQLite

Check-in [7712ba2611]
Login

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

Overview
Comment:Add "nclient" and "nprefetch" columns to the bcv_database table.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 7712ba261154aa2d65cb8ac68e9b9c5d08de4306d2e54f2269bd4960ed5aebe5
User & Date: dan 2023-08-18 19:24:01.634
Context
2023-08-18
20:10
Update documentation to match bcv_database changes. check-in: 683101f90f user: dan tags: trunk
19:24
Add "nclient" and "nprefetch" columns to the bcv_database table. check-in: 7712ba2611 user: dan tags: trunk
2023-08-02
15:32
Upgrade to SQLite 3.42.0. check-in: fbbff0c1fb user: dan tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/bcv_int.h.
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
  const char *zName;
  const char *zStorage;           /* Storage module */
  const char *zAccount;           /* Account name (if any) */
  const char *zContainer;         /* Name of container in cloud */
  const char *zLocalDir;          /* Local directory used by container */

  Manifest *pMan;                 /* Current container manifest */
  int nClient;                    /* Current number of clients */
  Container *pNext;               /* Next container on same VFS */

  int nBcv;
  BcvWrapper *aBcv;
  int eState;                     /* CONTAINER_STATE_* constant */

  u8 aKey[BCV_LOCAL_KEYSIZE];     /* Encryption key to use */







|







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
  const char *zName;
  const char *zStorage;           /* Storage module */
  const char *zAccount;           /* Account name (if any) */
  const char *zContainer;         /* Name of container in cloud */
  const char *zLocalDir;          /* Local directory used by container */

  Manifest *pMan;                 /* Current container manifest */
  int nClient;                    /* Number of clients (incl. prefetch) */
  Container *pNext;               /* Next container on same VFS */

  int nBcv;
  BcvWrapper *aBcv;
  int eState;                     /* CONTAINER_STATE_* constant */

  u8 aKey[BCV_LOCAL_KEYSIZE];     /* Encryption key to use */
392
393
394
395
396
397
398
399


400
401
402
403
404
405
406
void bcvfsHashRemove(BcvCommon *p, CacheEntry *pEntry);
void bcvfsLruRemoveIf(BcvCommon *p, CacheEntry *pEntry);
void bcvfsEntryUnref(BcvCommon *p, CacheEntry *pEntry);
void bcvfsBlockidToText(const u8 *pBlk, int nBlk, char *aBuf);
ManifestDb *bcvManifestDbidToDb(Manifest *p, i64 iDbId);
void bcvfsLruAdd(BcvCommon *p, CacheEntry *pEntry);
u8 *bcvDatabaseVtabData(
    int*, BcvCommon*, const char*, const char*, const char*, u32, int*


);
int bcvManifestUpdate(BcvCommon*, Container*, Manifest*, char**);
void bcvExecPrintf(int *pRc, sqlite3 *db, const char *zFmt, ...);
void bcvfsUnusedAdd(BcvCommon *p, CacheEntry *pEntry);
void bcvfsLruAddIf(BcvCommon *p, CacheEntry *pEntry);
int bcvfsNameToBlockid(Manifest *p, const char *zName, u8 *aBlk);
u8 *bcvEmptyKV(int *pRc, int *pnData);







|
>
>







392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
void bcvfsHashRemove(BcvCommon *p, CacheEntry *pEntry);
void bcvfsLruRemoveIf(BcvCommon *p, CacheEntry *pEntry);
void bcvfsEntryUnref(BcvCommon *p, CacheEntry *pEntry);
void bcvfsBlockidToText(const u8 *pBlk, int nBlk, char *aBuf);
ManifestDb *bcvManifestDbidToDb(Manifest *p, i64 iDbId);
void bcvfsLruAdd(BcvCommon *p, CacheEntry *pEntry);
u8 *bcvDatabaseVtabData(
    int*, BcvCommon*, const char*, const char*, const char*, 
    void(*xClientCount)(BcvCommon*,Container*,int,int*,int*),
    u32, int*, int*
);
int bcvManifestUpdate(BcvCommon*, Container*, Manifest*, char**);
void bcvExecPrintf(int *pRc, sqlite3 *db, const char *zFmt, ...);
void bcvfsUnusedAdd(BcvCommon *p, CacheEntry *pEntry);
void bcvfsLruAddIf(BcvCommon *p, CacheEntry *pEntry);
int bcvfsNameToBlockid(Manifest *p, const char *zName, u8 *aBlk);
u8 *bcvEmptyKV(int *pRc, int *pnData);
528
529
530
531
532
533
534

535
536
537
538
539
540
541
typedef struct BcvVtabReply BcvVtabReply;
typedef struct BcvPrefetchMsg BcvPrefetchMsg;
typedef struct BcvPrefetchReply BcvPrefetchReply;

struct BcvHelloMsg {
  const char *zContainer;
  const char *zDatabase;

};

struct BcvHelloReply {
  u32 errCode;                    /* Error code */
  const char *zErrMsg;            /* Error message */

  const char *zStorage;           /* Storage system in use for db */







>







530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
typedef struct BcvVtabReply BcvVtabReply;
typedef struct BcvPrefetchMsg BcvPrefetchMsg;
typedef struct BcvPrefetchReply BcvPrefetchReply;

struct BcvHelloMsg {
  const char *zContainer;
  const char *zDatabase;
  int bPrefetch;
};

struct BcvHelloReply {
  u32 errCode;                    /* Error code */
  const char *zErrMsg;            /* Error message */

  const char *zStorage;           /* Storage system in use for db */
572
573
574
575
576
577
578

579
580
581
582
583

584
585
586
587
588
589
590
};

struct BcvVtabMsg {
  const char *zVtab;
  const char *zContainer;
  const char *zDatabase;
  u32 colUsed;

};

struct BcvVtabReply {
  int nData;
  const u8 *aData;

};

struct BcvDetachMsg {
  const char *zName;
};

struct BcvReadMsg {







>





>







575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
};

struct BcvVtabMsg {
  const char *zVtab;
  const char *zContainer;
  const char *zDatabase;
  u32 colUsed;
  int iVersion;                   /* Vtab schema version requested */
};

struct BcvVtabReply {
  int nData;
  const u8 *aData;
  int iVersion;                   /* Vtab schema version supplied */
};

struct BcvDetachMsg {
  const char *zName;
};

struct BcvReadMsg {
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
** Valid values for BcvMessage.
*/
#define BCV_MESSAGE_HELLO          0x01      /* c->d   BcvHelloMsg */
#define BCV_MESSAGE_HELLO_REPLY    0x02      /* d->c   BcvHelloReply */
#define BCV_MESSAGE_REPLY          0x03      /* d->c   BcvReply */
#define BCV_MESSAGE_ATTACH         0x04      /* d->c   BcvAttachMsg */
#define BCV_MESSAGE_VTAB           0x05      /* c->d   BcvVtabMsg */
#define BCV_MESSAGE_VTAB_REPLY     0x06      /* d->c   BcvVtabMsg */
#define BCV_MESSAGE_DETACH         0x07      /* c->d   BcvDetachMsg */
#define BCV_MESSAGE_READ           0x08      /* c->d   BcvReadMsg */
#define BCV_MESSAGE_READ_REPLY     0x09      /* d->c   BcvReadReply */
#define BCV_MESSAGE_END            0x0A      /* c->d   BcvEndMsg */
#define BCV_MESSAGE_CMD            0x0B      /* c->d   BcvCmdMsg */
#define BCV_MESSAGE_PASS           0x0C      /* c->d   BcvPassMsg */
#define BCV_MESSAGE_PASS_REPLY     0x0D      /* d->c   BcvPassReply */







|







663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
** Valid values for BcvMessage.
*/
#define BCV_MESSAGE_HELLO          0x01      /* c->d   BcvHelloMsg */
#define BCV_MESSAGE_HELLO_REPLY    0x02      /* d->c   BcvHelloReply */
#define BCV_MESSAGE_REPLY          0x03      /* d->c   BcvReply */
#define BCV_MESSAGE_ATTACH         0x04      /* d->c   BcvAttachMsg */
#define BCV_MESSAGE_VTAB           0x05      /* c->d   BcvVtabMsg */
#define BCV_MESSAGE_VTAB_REPLY     0x06      /* d->c   BcvVtabReply */
#define BCV_MESSAGE_DETACH         0x07      /* c->d   BcvDetachMsg */
#define BCV_MESSAGE_READ           0x08      /* c->d   BcvReadMsg */
#define BCV_MESSAGE_READ_REPLY     0x09      /* d->c   BcvReadReply */
#define BCV_MESSAGE_END            0x0A      /* c->d   BcvEndMsg */
#define BCV_MESSAGE_CMD            0x0B      /* c->d   BcvCmdMsg */
#define BCV_MESSAGE_PASS           0x0C      /* c->d   BcvPassMsg */
#define BCV_MESSAGE_PASS_REPLY     0x0D      /* d->c   BcvPassReply */
Changes to src/bcvutil.c.
3614
3615
3616
3617
3618
3619
3620

3621
3622
3623

3624
3625
3626
3627
3628
3629
3630

3631
3632
3633
3634
3635
3636
3637
      bcvBufferMsgString(&rc, &buf, pMsg->u.error_r.zErrMsg);
      break;
    case BCV_MESSAGE_VTAB:
      bcvBufferMsgString(&rc, &buf, pMsg->u.vtab.zVtab);
      bcvBufferMsgString(&rc, &buf, pMsg->u.vtab.zContainer);
      bcvBufferMsgString(&rc, &buf, pMsg->u.vtab.zDatabase);
      bcvBufferAppendU32(&rc, &buf, pMsg->u.vtab.colUsed);

      break;
    case BCV_MESSAGE_VTAB_REPLY:
      bcvBufferMsgBlob(&rc, &buf, pMsg->u.vtab_r.aData, pMsg->u.vtab_r.nData);

      break;
    case BCV_MESSAGE_DETACH:
      bcvBufferMsgString(&rc, &buf, pMsg->u.detach.zName);
      break;
    case BCV_MESSAGE_HELLO:
      bcvBufferMsgString(&rc, &buf, pMsg->u.hello.zContainer);
      bcvBufferMsgString(&rc, &buf, pMsg->u.hello.zDatabase);

      break;
    case BCV_MESSAGE_HELLO_REPLY:
      bcvBufferAppendU32(&rc, &buf, pMsg->u.hello_r.errCode);
      bcvBufferMsgString(&rc, &buf, pMsg->u.hello_r.zErrMsg);
      bcvBufferMsgString(&rc, &buf, pMsg->u.hello_r.zStorage);
      bcvBufferMsgString(&rc, &buf, pMsg->u.hello_r.zAccount);
      bcvBufferMsgString(&rc, &buf, pMsg->u.hello_r.zContainer);







>



>







>







3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
      bcvBufferMsgString(&rc, &buf, pMsg->u.error_r.zErrMsg);
      break;
    case BCV_MESSAGE_VTAB:
      bcvBufferMsgString(&rc, &buf, pMsg->u.vtab.zVtab);
      bcvBufferMsgString(&rc, &buf, pMsg->u.vtab.zContainer);
      bcvBufferMsgString(&rc, &buf, pMsg->u.vtab.zDatabase);
      bcvBufferAppendU32(&rc, &buf, pMsg->u.vtab.colUsed);
      bcvBufferAppendU32(&rc, &buf, pMsg->u.vtab.iVersion);
      break;
    case BCV_MESSAGE_VTAB_REPLY:
      bcvBufferMsgBlob(&rc, &buf, pMsg->u.vtab_r.aData, pMsg->u.vtab_r.nData);
      bcvBufferAppendU32(&rc, &buf, pMsg->u.vtab_r.iVersion);
      break;
    case BCV_MESSAGE_DETACH:
      bcvBufferMsgString(&rc, &buf, pMsg->u.detach.zName);
      break;
    case BCV_MESSAGE_HELLO:
      bcvBufferMsgString(&rc, &buf, pMsg->u.hello.zContainer);
      bcvBufferMsgString(&rc, &buf, pMsg->u.hello.zDatabase);
      bcvBufferAppendU32(&rc, &buf, pMsg->u.hello.bPrefetch);
      break;
    case BCV_MESSAGE_HELLO_REPLY:
      bcvBufferAppendU32(&rc, &buf, pMsg->u.hello_r.errCode);
      bcvBufferMsgString(&rc, &buf, pMsg->u.hello_r.zErrMsg);
      bcvBufferMsgString(&rc, &buf, pMsg->u.hello_r.zStorage);
      bcvBufferMsgString(&rc, &buf, pMsg->u.hello_r.zAccount);
      bcvBufferMsgString(&rc, &buf, pMsg->u.hello_r.zContainer);
3762
3763
3764
3765
3766
3767
3768



3769
3770
3771
3772



3773
3774
3775
3776
3777
3778
3779
3780
3781



3782
3783
3784
3785
3786
3787
3788
            break;
          }
          case BCV_MESSAGE_VTAB: {
            pMsg->u.vtab.zVtab = bcvMsgGetString(&aBody);
            pMsg->u.vtab.zContainer = bcvMsgGetString(&aBody);
            pMsg->u.vtab.zDatabase = bcvMsgGetString(&aBody);
            pMsg->u.vtab.colUsed = bcvMsgGetU32(&aBody);



            break;
          }
          case BCV_MESSAGE_VTAB_REPLY: {
            pMsg->u.vtab_r.aData = bcvMsgGetBlob(&aBody, &pMsg->u.vtab_r.nData);



            break;
          }
          case BCV_MESSAGE_DETACH: {
            pMsg->u.detach.zName = bcvMsgGetString(&aBody);
            break;
          }
          case BCV_MESSAGE_HELLO: {
            pMsg->u.hello.zContainer = bcvMsgGetString(&aBody);
            pMsg->u.hello.zDatabase = bcvMsgGetString(&aBody);



            break;
          }

          case BCV_MESSAGE_HELLO_REPLY: {
            pMsg->u.hello_r.errCode = bcvMsgGetU32(&aBody);
            pMsg->u.hello_r.zErrMsg = bcvMsgGetString(&aBody);
            pMsg->u.hello_r.zStorage = bcvMsgGetString(&aBody);







>
>
>




>
>
>









>
>
>







3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
            break;
          }
          case BCV_MESSAGE_VTAB: {
            pMsg->u.vtab.zVtab = bcvMsgGetString(&aBody);
            pMsg->u.vtab.zContainer = bcvMsgGetString(&aBody);
            pMsg->u.vtab.zDatabase = bcvMsgGetString(&aBody);
            pMsg->u.vtab.colUsed = bcvMsgGetU32(&aBody);
            if( (aBody - (u8*)&pMsg[1])<nByte ){
              pMsg->u.vtab.iVersion = bcvMsgGetU32(&aBody);
            }
            break;
          }
          case BCV_MESSAGE_VTAB_REPLY: {
            pMsg->u.vtab_r.aData = bcvMsgGetBlob(&aBody, &pMsg->u.vtab_r.nData);
            if( (aBody - (u8*)&pMsg[1])<nByte ){
              pMsg->u.vtab_r.iVersion = bcvMsgGetU32(&aBody);
            }
            break;
          }
          case BCV_MESSAGE_DETACH: {
            pMsg->u.detach.zName = bcvMsgGetString(&aBody);
            break;
          }
          case BCV_MESSAGE_HELLO: {
            pMsg->u.hello.zContainer = bcvMsgGetString(&aBody);
            pMsg->u.hello.zDatabase = bcvMsgGetString(&aBody);
            if( (aBody - (u8*)&pMsg[1])<nByte ){
              pMsg->u.hello.bPrefetch = bcvMsgGetU32(&aBody);
            }
            break;
          }

          case BCV_MESSAGE_HELLO_REPLY: {
            pMsg->u.hello_r.errCode = bcvMsgGetU32(&aBody);
            pMsg->u.hello_r.zErrMsg = bcvMsgGetString(&aBody);
            pMsg->u.hello_r.zStorage = bcvMsgGetString(&aBody);
Changes to src/blockcachevfs.c.
236
237
238
239
240
241
242



243
244
245
246
247
248
249
  void(*xLog)(void*, int, const char*);
  int bCurlVerbose;

  /* Authentication callback */
  void *pAuthCtx;
  int(*xAuth)(void*, const char*, const char*, const char*, char**);




  BcvCommon c;                    /* Hash tables etc. */
  Mutex mutex;                    /* Mutex/condition variable object */
};

struct BcvDbPath {
  char *zContainer;
  char *zDatabase;







>
>
>







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
  void(*xLog)(void*, int, const char*);
  int bCurlVerbose;

  /* Authentication callback */
  void *pAuthCtx;
  int(*xAuth)(void*, const char*, const char*, const char*, char**);

  /* Active prefetches */
  sqlite3_prefetch *pPrefetch;

  BcvCommon c;                    /* Hash tables etc. */
  Mutex mutex;                    /* Mutex/condition variable object */
};

struct BcvDbPath {
  char *zContainer;
  char *zDatabase;
3133
3134
3135
3136
3137
3138
3139

3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153

3154
3155
3156
3157
3158
3159
3160
** connect to the daemon to access container zCont, and optionally database
** zDb.
*/
static int bcvfsProxyConnect(
  sqlite3_bcvfs *pFs,             /* Proxy VFS */
  const char *zCont,              /* Container to open */
  const char *zDb,                /* Name of db to open, or NULL */

  BCV_SOCKET_TYPE *pS,            /* OUT: Open socket */
  BcvMessage **ppReply            /* OUT: HELLO_REPLY message */
){
  BCV_SOCKET_TYPE s = INVALID_SOCKET;
  int rc = SQLITE_OK;
  BcvMessage *pReply = 0;

  s = bcvConnectSocket(&rc, pFs->zPortnumber, 0);
  if( rc==SQLITE_OK && zCont ){
    BcvMessage hello;
    memset(&hello, 0, sizeof(BcvMessage));
    hello.eType = BCV_MESSAGE_HELLO;
    hello.u.hello.zContainer = zCont;
    hello.u.hello.zDatabase = zDb;

    pReply = bcvExchangeMessage(&rc, s, &hello);
  }
  if( rc!=SQLITE_OK ){
    assert( pReply==0 );
    bcv_close_socket(s);
    s = INVALID_SOCKET;
  }







>














>







3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
** connect to the daemon to access container zCont, and optionally database
** zDb.
*/
static int bcvfsProxyConnect(
  sqlite3_bcvfs *pFs,             /* Proxy VFS */
  const char *zCont,              /* Container to open */
  const char *zDb,                /* Name of db to open, or NULL */
  int bPrefetch,                  /* True for prefetch connection */
  BCV_SOCKET_TYPE *pS,            /* OUT: Open socket */
  BcvMessage **ppReply            /* OUT: HELLO_REPLY message */
){
  BCV_SOCKET_TYPE s = INVALID_SOCKET;
  int rc = SQLITE_OK;
  BcvMessage *pReply = 0;

  s = bcvConnectSocket(&rc, pFs->zPortnumber, 0);
  if( rc==SQLITE_OK && zCont ){
    BcvMessage hello;
    memset(&hello, 0, sizeof(BcvMessage));
    hello.eType = BCV_MESSAGE_HELLO;
    hello.u.hello.zContainer = zCont;
    hello.u.hello.zDatabase = zDb;
    hello.u.hello.bPrefetch = bPrefetch;
    pReply = bcvExchangeMessage(&rc, s, &hello);
  }
  if( rc!=SQLITE_OK ){
    assert( pReply==0 );
    bcv_close_socket(s);
    s = INVALID_SOCKET;
  }
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
  sqlite3_bcvfs *pFs, 
  BcvDbPath *pPath, 
  BcvfsFile *pFile
){
  int rc = SQLITE_OK;
  BcvMessage *pReply = 0;
  rc = bcvfsProxyConnect(
      pFs, pPath->zContainer, pPath->zDatabase, &pFile->p.fdProxy, &pReply
  );
  if( pReply ){
    if( rc==SQLITE_OK ){
      rc = pReply->u.hello_r.errCode;
    }
    if( rc==SQLITE_OK ){
      pFile->p.zStorage = bcvStrdupRc(&rc, pReply->u.hello_r.zStorage);







|







3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
  sqlite3_bcvfs *pFs, 
  BcvDbPath *pPath, 
  BcvfsFile *pFile
){
  int rc = SQLITE_OK;
  BcvMessage *pReply = 0;
  rc = bcvfsProxyConnect(
      pFs, pPath->zContainer, pPath->zDatabase, 0, &pFile->p.fdProxy, &pReply
  );
  if( pReply ){
    if( rc==SQLITE_OK ){
      rc = pReply->u.hello_r.errCode;
    }
    if( rc==SQLITE_OK ){
      pFile->p.zStorage = bcvStrdupRc(&rc, pReply->u.hello_r.zStorage);
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
  char **pzErr                    /* OUT: error message */
){
  int rc = SQLITE_OK;                       /* Error code */
  BCV_SOCKET_TYPE s = INVALID_SOCKET;       /* Socket connected to daemon */
  BcvMessage *pReply = 0;                   /* HELLO_REPLY message */

  assert( pzErr );
  rc = bcvfsProxyConnect(pFs, zCont, zDb, &s, &pReply);
  if( pReply ){
    rc = pReply->u.hello_r.errCode;
    if( rc && pzErr ){
      *pzErr = sqlite3_mprintf("%s", pReply->u.hello_r.zErrMsg);
    }
  }
  if( rc==SQLITE_OK ){







|







4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
  char **pzErr                    /* OUT: error message */
){
  int rc = SQLITE_OK;                       /* Error code */
  BCV_SOCKET_TYPE s = INVALID_SOCKET;       /* Socket connected to daemon */
  BcvMessage *pReply = 0;                   /* HELLO_REPLY message */

  assert( pzErr );
  rc = bcvfsProxyConnect(pFs, zCont, zDb, 0, &s, &pReply);
  if( pReply ){
    rc = pReply->u.hello_r.errCode;
    if( rc && pzErr ){
      *pzErr = sqlite3_mprintf("%s", pReply->u.hello_r.zErrMsg);
    }
  }
  if( rc==SQLITE_OK ){
5368
5369
5370
5371
5372
5373
5374

5375
5376
5377
5378
5379
5380
5381
      bcvfsContainerReleaseBcv(pFs, pFile->pCont, pDisp, pBcv, bError);
    } LEAVE_VFS_MUTEX;
  }
}

struct sqlite3_prefetch {
  sqlite3_bcvfs *pFs;


  Container *pCont;
  Manifest *pMan;
  ManifestDb *pManDb;
  BcvContainer *pBcv;
  BcvDispatch *pDisp;
  sqlite3_file *pCacheFile;







>







5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
      bcvfsContainerReleaseBcv(pFs, pFile->pCont, pDisp, pBcv, bError);
    } LEAVE_VFS_MUTEX;
  }
}

struct sqlite3_prefetch {
  sqlite3_bcvfs *pFs;
  sqlite3_prefetch *pNext;

  Container *pCont;
  Manifest *pMan;
  ManifestDb *pManDb;
  BcvContainer *pBcv;
  BcvDispatch *pDisp;
  sqlite3_file *pCacheFile;
5413
5414
5415
5416
5417
5418
5419


5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432

  pNew = bcvMallocRc(&rc, sizeof(sqlite3_prefetch));
  if( pNew ){
    pNew->fdProxy = INVALID_SOCKET;
    pNew->pFs = pFs;
    ENTER_VFS_MUTEX; {
      pFs->nRef++;


    }; LEAVE_VFS_MUTEX;

    if( pFs->zPortnumber ){
      BcvMessage *pReply = 0;     /* HELLO_REPLY message */
      pNew->rc = bcvfsProxyConnect(
          pFs, zCont, zDb, &pNew->fdProxy, &pReply
      );
      if( pReply ){
        assert( pNew->rc==SQLITE_OK );
        pNew->rc = pReply->u.hello_r.errCode;
        if( pNew->rc ){
          pNew->zErr = sqlite3_mprintf("%s", pReply->u.hello_r.zErrMsg);
        }







>
>





|







5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440

  pNew = bcvMallocRc(&rc, sizeof(sqlite3_prefetch));
  if( pNew ){
    pNew->fdProxy = INVALID_SOCKET;
    pNew->pFs = pFs;
    ENTER_VFS_MUTEX; {
      pFs->nRef++;
      pNew->pNext = pFs->pPrefetch;
      pFs->pPrefetch = pNew;
    }; LEAVE_VFS_MUTEX;

    if( pFs->zPortnumber ){
      BcvMessage *pReply = 0;     /* HELLO_REPLY message */
      pNew->rc = bcvfsProxyConnect(
          pFs, zCont, zDb, 1, &pNew->fdProxy, &pReply
      );
      if( pReply ){
        assert( pNew->rc==SQLITE_OK );
        pNew->rc = pReply->u.hello_r.errCode;
        if( pNew->rc ){
          pNew->zErr = sqlite3_mprintf("%s", pReply->u.hello_r.zErrMsg);
        }
5699
5700
5701
5702
5703
5704
5705

5706






5707
5708
5709
5710
5711
5712
5713
  return rc;
}

void sqlite3_bcvfs_prefetch_destroy(sqlite3_prefetch *p){
  if( p ){
    sqlite3_bcvfs *pFs = p->pFs;
    ENTER_VFS_MUTEX; {

      pFs->nRef--;






    }; LEAVE_VFS_MUTEX;
    bcvManifestDeref(p->pMan);
    if( p->pCont ){
      int bError = p->rc || (p->nOutstanding>0);
      p->pCont->nClient--;
      bcvfsContainerReleaseBcv(p->pFs, p->pCont, p->pDisp, p->pBcv, bError);
    }







>

>
>
>
>
>
>







5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
  return rc;
}

void sqlite3_bcvfs_prefetch_destroy(sqlite3_prefetch *p){
  if( p ){
    sqlite3_bcvfs *pFs = p->pFs;
    ENTER_VFS_MUTEX; {
      sqlite3_prefetch **pp;
      pFs->nRef--;
      for(pp=&pFs->pPrefetch; *pp; pp=&(*pp)->pNext){
        if( *pp==p ){
          *pp = p->pNext;
          break;
        }
      }
    }; LEAVE_VFS_MUTEX;
    bcvManifestDeref(p->pMan);
    if( p->pCont ){
      int bError = p->rc || (p->nOutstanding>0);
      p->pCont->nClient--;
      bcvfsContainerReleaseBcv(p->pFs, p->pCont, p->pDisp, p->pBcv, bError);
    }
5895
5896
5897
5898
5899
5900
5901

5902

5903
5904
5905
5906
5907
5908
5909
"CREATE TABLE bcv_database("      \
"  container TEXT,"               \
"  database  TEXT,"               \
"  nblock INTEGER,"               \
"  ncache INTEGER,"               \
"  ndirty INTEGER,"               \
"  walfile BOOLEAN,"              \

"  state TEXT "                   \

")"

#define BCV_CONTAINER_VTAB_SCHEMA \
"CREATE TABLE bcv_container("     \
"  name      TEXT,"               \
"  storage   TEXT,"               \
"  user      TEXT,"               \







>
|
>







5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
"CREATE TABLE bcv_database("      \
"  container TEXT,"               \
"  database  TEXT,"               \
"  nblock INTEGER,"               \
"  ncache INTEGER,"               \
"  ndirty INTEGER,"               \
"  walfile BOOLEAN,"              \
"  state TEXT, "                  \
"  nclient INTEGER, "             \
"  nprefetch INTEGER"             \
")"

#define BCV_CONTAINER_VTAB_SCHEMA \
"CREATE TABLE bcv_container("     \
"  name      TEXT,"               \
"  storage   TEXT,"               \
"  user      TEXT,"               \
5929
5930
5931
5932
5933
5934
5935






5936
5937
5938
5939
5940
5941
5942

#define BCV_FILEMETA_VTAB_SCHEMA  \
"CREATE TABLE bcv_kv("            \
"  name      TEXT,"               \
"  value     TEXT "               \
")"







/*
** Bits used in the idxNum value
*/
#define BCV_COLUSED_MASK   0x0000FFFF
#define BCV_CONTAINER_MASK 0x00010000
#define BCV_DATABASE_MASK  0x00020000








>
>
>
>
>
>







5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965

#define BCV_FILEMETA_VTAB_SCHEMA  \
"CREATE TABLE bcv_kv("            \
"  name      TEXT,"               \
"  value     TEXT "               \
")"

/* Current version is 1.
**
** 1: Add the "nclient" and "nprefetch" fields to the bcv_database table.
*/
#define BCV_VTAB_VERSION 1

/*
** Bits used in the idxNum value
*/
#define BCV_COLUSED_MASK   0x0000FFFF
#define BCV_CONTAINER_MASK 0x00010000
#define BCV_DATABASE_MASK  0x00020000

5992
5993
5994
5995
5996
5997
5998

5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009


6010
6011
6012
6013
6014
6015
6016
**   Offset of next row in pData blob.
*/
struct bcv_database_cursor {
  sqlite3_vtab_cursor base;       /* Base class */

  VtabBlob data;
  void *pFreeData;


  /* Values for current row */
  i64 iRow;                       /* Rowid */
  char *zContainer;
  char *zDatabase;
  int nBlock;
  int nCache;
  int nDirty;
  int bWalfile;
  int nPin;
  char *zState;


};

/*
** pData:
**   If the underlying VFS is a proxy VFS, then the data to return
**   is contained in the pData message object obtained from the daemon
**   process within the xFilter call. The message object contains a







>











>
>







6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
**   Offset of next row in pData blob.
*/
struct bcv_database_cursor {
  sqlite3_vtab_cursor base;       /* Base class */

  VtabBlob data;
  void *pFreeData;
  int iVersion;                   /* Version from VtabReply message */

  /* Values for current row */
  i64 iRow;                       /* Rowid */
  char *zContainer;
  char *zDatabase;
  int nBlock;
  int nCache;
  int nDirty;
  int bWalfile;
  int nPin;
  char *zState;
  int nClient;
  int nPrefetch;
};

/*
** pData:
**   If the underlying VFS is a proxy VFS, then the data to return
**   is contained in the pData message object obtained from the daemon
**   process within the xFilter call. The message object contains a
6179
6180
6181
6182
6183
6184
6185

6186
6187

6188
6189
6190

6191
6192
6193
6194
6195
6196
6197
*/
u8 *bcvDatabaseVtabData(
  int *pRc,                       /* IN/OUT: error code */
  BcvCommon *pCommon,             /* State to base returned data on */
  const char *zName,              /* "bcv_database" or "bcv_container" */
  const char *zContFilter,        /* Container to query, or NULL */
  const char *zDbFilter,          /* Database to query, or NULL */

  u32 colUsed,                    /* Columns used mask */
  int *pnData                     /* OUT: Size of returned buffer */

){
  int rc = SQLITE_OK;
  BcvBuffer buf = {0,0,0};


  if( bcvStrcmp(zName, "bcv_database")==0 ){
    Container *pCont;
    for(pCont=pCommon->pCList; pCont; pCont=pCont->pNext){
      int ii;
      Manifest *pMan = pCont->pMan;
      if( zContFilter && bcvStrcmp(zContFilter, pCont->zName) ) continue;







>

|
>



>







6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
*/
u8 *bcvDatabaseVtabData(
  int *pRc,                       /* IN/OUT: error code */
  BcvCommon *pCommon,             /* State to base returned data on */
  const char *zName,              /* "bcv_database" or "bcv_container" */
  const char *zContFilter,        /* Container to query, or NULL */
  const char *zDbFilter,          /* Database to query, or NULL */
  void(*xClientCount)(BcvCommon*,Container*,int,int*,int*),
  u32 colUsed,                    /* Columns used mask */
  int *pnData,                    /* OUT: Size of returned buffer */
  int *piVersion                  /* IN/OUT: Vtab schema version used */
){
  int rc = SQLITE_OK;
  BcvBuffer buf = {0,0,0};
  int iVersion = MAX(*piVersion, BCV_VTAB_VERSION);

  if( bcvStrcmp(zName, "bcv_database")==0 ){
    Container *pCont;
    for(pCont=pCommon->pCList; pCont; pCont=pCont->pNext){
      int ii;
      Manifest *pMan = pCont->pMan;
      if( zContFilter && bcvStrcmp(zContFilter, pCont->zName) ) continue;
6218
6219
6220
6221
6222
6223
6224








6225
6226
6227
6228
6229
6230
6231
        bcvBufferAppendU32(&rc, &buf, (u32)bWalfile);
        if( pDb->nBlkLocal==0 ){
          zState = "deleted";
        }else if( pDb->iDbId>=BCVFS_FIRST_LOCAL_ID ){
          zState = "copied";
        }
        bcvBufferMsgString(&rc, &buf, zState);








      }
    }
  }else if( bcvStrcmp(zName, "bcv_container")==0 ){
    Container *pCont;
    for(pCont=pCommon->pCList; pCont; pCont=pCont->pNext){
      if( zContFilter && bcvStrcmp(zContFilter, pCont->zName) ) continue;
      bcvBufferMsgString(&rc, &buf, pCont->zName);







>
>
>
>
>
>
>
>







6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
        bcvBufferAppendU32(&rc, &buf, (u32)bWalfile);
        if( pDb->nBlkLocal==0 ){
          zState = "deleted";
        }else if( pDb->iDbId>=BCVFS_FIRST_LOCAL_ID ){
          zState = "copied";
        }
        bcvBufferMsgString(&rc, &buf, zState);
        if( iVersion>=1 ){
          /* TODO: Real values! */
          int nClient = 0;
          int nPrefetch = 0;
          xClientCount(pCommon, pCont, pDb->iDbId, &nClient, &nPrefetch);
          bcvBufferAppendU32(&rc, &buf, nClient);
          bcvBufferAppendU32(&rc, &buf, nPrefetch);
        }
      }
    }
  }else if( bcvStrcmp(zName, "bcv_container")==0 ){
    Container *pCont;
    for(pCont=pCommon->pCList; pCont; pCont=pCont->pNext){
      if( zContFilter && bcvStrcmp(zContFilter, pCont->zName) ) continue;
      bcvBufferMsgString(&rc, &buf, pCont->zName);
6327
6328
6329
6330
6331
6332
6333




6334
6335
6336
6337
6338
6339
6340
  pCur->zContainer = (char*)bcvVtabExtractString(&pCur->data);
  pCur->zDatabase = (char*)bcvVtabExtractString(&pCur->data);
  pCur->nBlock = (int)bcvVtabExtractU32(&pCur->data);
  pCur->nCache = (int)bcvVtabExtractU32(&pCur->data);
  pCur->nDirty = (int)bcvVtabExtractU32(&pCur->data);
  pCur->bWalfile = (int)bcvVtabExtractU32(&pCur->data);
  pCur->zState = (char*)bcvVtabExtractString(&pCur->data);





  pCur->iRow++;
  return SQLITE_OK;
}

static int bcvContainerVtabNext(sqlite3_vtab_cursor *cur){
  bcv_container_cursor *pCur = (bcv_container_cursor*)cur;







>
>
>
>







6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
  pCur->zContainer = (char*)bcvVtabExtractString(&pCur->data);
  pCur->zDatabase = (char*)bcvVtabExtractString(&pCur->data);
  pCur->nBlock = (int)bcvVtabExtractU32(&pCur->data);
  pCur->nCache = (int)bcvVtabExtractU32(&pCur->data);
  pCur->nDirty = (int)bcvVtabExtractU32(&pCur->data);
  pCur->bWalfile = (int)bcvVtabExtractU32(&pCur->data);
  pCur->zState = (char*)bcvVtabExtractString(&pCur->data);
  if( pCur->iVersion>=1 ){
    pCur->nClient = (int)bcvVtabExtractU32(&pCur->data);
    pCur->nPrefetch = (int)bcvVtabExtractU32(&pCur->data);
  }

  pCur->iRow++;
  return SQLITE_OK;
}

static int bcvContainerVtabNext(sqlite3_vtab_cursor *cur){
  bcv_container_cursor *pCur = (bcv_container_cursor*)cur;
6391
6392
6393
6394
6395
6396
6397






6398
6399
6400
6401
6402
6403
6404
      break;
    case 5: /* dirty */
      sqlite3_result_int(ctx, pCur->bWalfile);
      break;
    case 6: /* state */
      sqlite3_result_text(ctx, pCur->zState, -1, SQLITE_TRANSIENT);
      break;






  }
  return SQLITE_OK;
}

static int bcvContainerVtabColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */







>
>
>
>
>
>







6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
      break;
    case 5: /* dirty */
      sqlite3_result_int(ctx, pCur->bWalfile);
      break;
    case 6: /* state */
      sqlite3_result_text(ctx, pCur->zState, -1, SQLITE_TRANSIENT);
      break;
    case 7: /* nclient */
      if( pCur->iVersion>=1 ) sqlite3_result_int(ctx, pCur->nClient);
      break;
    case 8: /* nprefetch */
      if( pCur->iVersion>=1 ) sqlite3_result_int(ctx, pCur->nPrefetch);
      break;
  }
  return SQLITE_OK;
}

static int bcvContainerVtabColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
6517
6518
6519
6520
6521
6522
6523

6524
6525
6526
6527
6528
6529
6530










































6531
6532
6533
6534
6535
6536
6537

  memset(&msg, 0, sizeof(msg));
  msg.eType = BCV_MESSAGE_VTAB;
  msg.u.vtab.zVtab = zVtab;
  msg.u.vtab.zContainer = zCont;
  msg.u.vtab.zDatabase = zDb;
  msg.u.vtab.colUsed = colUsed;


  pReply = bcvExchangeMessage(pRc, pFile->p.fdProxy, &msg);
  assert( (pReply==0)==(*pRc!=SQLITE_OK) );

  return pReply;
}












































/*
** xFilter implentations for bcv_database and bcv_block.
*/
static int bcvReadonlyVtabFilter(
  sqlite3_vtab_cursor *cur, 
  int idxNum, const char *idxStr,







>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627

  memset(&msg, 0, sizeof(msg));
  msg.eType = BCV_MESSAGE_VTAB;
  msg.u.vtab.zVtab = zVtab;
  msg.u.vtab.zContainer = zCont;
  msg.u.vtab.zDatabase = zDb;
  msg.u.vtab.colUsed = colUsed;
  msg.u.vtab.iVersion = BCV_VTAB_VERSION;

  pReply = bcvExchangeMessage(pRc, pFile->p.fdProxy, &msg);
  assert( (pReply==0)==(*pRc!=SQLITE_OK) );

  return pReply;
}

/*
** GCC does not define the offsetof() macro so we'll have to do it
** ourselves.
*/
#ifndef offsetof
#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
#endif

/*
** Version of xClientCount for local VFS
*/
static void bcvLocalClientCount(
  BcvCommon *pCommon, 
  Container *pCont, 
  int iDbId, 
  int *pnClient,
  int *pnPrefetch
){
  BcvfsFile *pFile = 0;
  sqlite3_prefetch *pPrefetch = 0;
  sqlite3_bcvfs *pFs = 0;
  int nClient = 0;
  int nPrefetch = 0;
  pFs = (sqlite3_bcvfs*)&((u8*)pCommon)[-offsetof(sqlite3_bcvfs, c)];

  assert( pCommon->bDaemon==0 );

  for(pFile=pFs->pFileList; pFile; pFile=pFile->pNextFile){
    if( pFile->pCont==pCont && pFile->iFileDbId==iDbId ){
      nClient++;
    }
  }

  for(pPrefetch=pFs->pPrefetch; pPrefetch; pPrefetch=pPrefetch->pNext){
    if( pPrefetch->pCont==pCont && pPrefetch->pManDb->iDbId==iDbId ){
      nPrefetch++;
    }
  }

  *pnClient = nClient;
  *pnPrefetch = nPrefetch;
}

/*
** xFilter implentations for bcv_database and bcv_block.
*/
static int bcvReadonlyVtabFilter(
  sqlite3_vtab_cursor *cur, 
  int idxNum, const char *idxStr,
6558
6559
6560
6561
6562
6563
6564
6565

6566
6567
6568
6569
6570
6571

6572
6573

6574
6575


6576
6577
6578
6579
6580
6581
6582
  sqlite3_free(pCur->pFreeData);
  pCur->pFreeData = 0;
  memset(&pCur->data, 0, sizeof(VtabBlob));

  sqlite3_file_control(pTab->db, "main", BCV_FCNTL_FD, (void*)&pFile);
  if( pFile ){
    if( pFile->pFs->zPortnumber ){
      BcvMessage *pMsg = bcvVtabFetchData(

          &rc, pFile, pTab->zMod, zCont, zDb, colUsed
      );
      if( pMsg ){
        pCur->data.aData = pMsg->u.vtab_r.aData;
        pCur->data.nData = pMsg->u.vtab_r.nData;
        pCur->pFreeData = (void*)pMsg;

      }
    }else{

      pCur->data.aData = bcvDatabaseVtabData(&rc, &pFile->pFs->c, 
          pTab->zMod, zCont, zDb, colUsed, &pCur->data.nData


      );
      pCur->pFreeData = (void*)pCur->data.aData;
    }
    if( rc==SQLITE_OK ){
      return pTab->base.pModule->xNext(cur);
    }
  }







|
>






>


>

|
>
>







6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
  sqlite3_free(pCur->pFreeData);
  pCur->pFreeData = 0;
  memset(&pCur->data, 0, sizeof(VtabBlob));

  sqlite3_file_control(pTab->db, "main", BCV_FCNTL_FD, (void*)&pFile);
  if( pFile ){
    if( pFile->pFs->zPortnumber ){
      BcvMessage *pMsg = 0;
      pMsg = bcvVtabFetchData(
          &rc, pFile, pTab->zMod, zCont, zDb, colUsed
      );
      if( pMsg ){
        pCur->data.aData = pMsg->u.vtab_r.aData;
        pCur->data.nData = pMsg->u.vtab_r.nData;
        pCur->pFreeData = (void*)pMsg;
        pCur->iVersion = pMsg->u.vtab_r.iVersion;
      }
    }else{
      pCur->iVersion = BCV_VTAB_VERSION;
      pCur->data.aData = bcvDatabaseVtabData(&rc, &pFile->pFs->c, 
          pTab->zMod, zCont, zDb, 
          bcvLocalClientCount,
          colUsed, &pCur->data.nData, &pCur->iVersion
      );
      pCur->pFreeData = (void*)pCur->data.aData;
    }
    if( rc==SQLITE_OK ){
      return pTab->base.pModule->xNext(cur);
    }
  }
6613
6614
6615
6616
6617
6618
6619

6620
6621
6622
6623
6624
6625
6626
6627
6628
      );
      if( pMsg ){
        pCur->data.aData = pMsg->u.vtab_r.aData;
        pCur->data.nData = pMsg->u.vtab_r.nData;
        pCur->pFreeData = (void*)pMsg;
      }
    }else{

      pCur->data.aData = bcvDatabaseVtabData(&rc, &pFile->pFs->c, 
          "bcv_container", zCont, 0, colUsed, &pCur->data.nData
      );
      pCur->pFreeData = (void*)pCur->data.aData;
    }
    if( rc==SQLITE_OK ){
      return bcvContainerVtabNext(cur);
    }
  }







>

|







6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
      );
      if( pMsg ){
        pCur->data.aData = pMsg->u.vtab_r.aData;
        pCur->data.nData = pMsg->u.vtab_r.nData;
        pCur->pFreeData = (void*)pMsg;
      }
    }else{
      int iVersion = BCV_VTAB_VERSION;
      pCur->data.aData = bcvDatabaseVtabData(&rc, &pFile->pFs->c, 
          "bcv_container", zCont, 0, 0, colUsed, &pCur->data.nData, &iVersion
      );
      pCur->pFreeData = (void*)pCur->data.aData;
    }
    if( rc==SQLITE_OK ){
      return bcvContainerVtabNext(cur);
    }
  }
Changes to src/blockcachevfsd.c.
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068
1069
1070

typedef struct DaemonCtx DaemonCtx;
typedef struct DClient DClient;
typedef struct FetchCtx FetchCtx;
typedef struct DPrefetch DPrefetch;

struct DPrefetch {

  int nOutstanding;
  int iNext;
  int bReply;
  int errCode;
  char *zErrMsg;
};








>







1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071

typedef struct DaemonCtx DaemonCtx;
typedef struct DClient DClient;
typedef struct FetchCtx FetchCtx;
typedef struct DPrefetch DPrefetch;

struct DPrefetch {
  int bPrefetch;                  /* True if this is a prefetch connection */
  int nOutstanding;
  int iNext;
  int bReply;
  int errCode;
  char *zErrMsg;
};

1755
1756
1757
1758
1759
1760
1761







































1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779

1780
1781
1782
1783
1784


1785
1786

1787
1788
1789
1790
1791
1792
1793
  reply.eType = BCV_MESSAGE_REPLY;
  reply.u.error_r.errCode = rc;
  reply.u.error_r.zErrMsg = zErr;
  bdSendMsg(p, pClient, &reply);
  sqlite3_free(zErr);
  sqlite3_free(pMsg);
}








































/*
** Handle a message of type BCV_MESSAGE_VTAB from client pClient.
*/
static void bdHandleVtab(
  DaemonCtx *p, 
  DClient *pClient, 
  BcvMessage *pMsg
){
  const char *zTab = pMsg->u.vtab.zVtab;
  const char *zCont = pMsg->u.vtab.zContainer;
  const char *zDb = pMsg->u.vtab.zDatabase;
  const u32 colUsed = pMsg->u.vtab.colUsed;

  int rc = SQLITE_OK;
  BcvMessage reply;
  u8 *aData = 0;
  int nData = 0;


  memset(&reply, 0, sizeof(reply));
  reply.eType = BCV_MESSAGE_VTAB_REPLY;

  aData = bcvDatabaseVtabData(&rc, &p->c, zTab, zCont, zDb, colUsed, &nData);


  reply.u.vtab_r.aData = aData;
  reply.u.vtab_r.nData = nData;

  bdSendMsg(p, pClient, &reply);

  sqlite3_free(aData);
  sqlite3_free(pMsg);
}

/*







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


















>




|
>
>


>







1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
  reply.eType = BCV_MESSAGE_REPLY;
  reply.u.error_r.errCode = rc;
  reply.u.error_r.zErrMsg = zErr;
  bdSendMsg(p, pClient, &reply);
  sqlite3_free(zErr);
  sqlite3_free(pMsg);
}

/*
** GCC does not define the offsetof() macro so we'll have to do it
** ourselves.
*/
#ifndef offsetof
#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
#endif


/*
** Version of xClientCount for proxy VFS
*/
static void bcvProxyClientCount(
  BcvCommon *pCommon, 
  Container *pCont, 
  int iDbId, 
  int *pnClient,
  int *pnPrefetch
){
  DClient *pClient = 0;
  DaemonCtx *p = 0;
  int nClient = 0;
  int nPrefetch = 0;

  p = (DaemonCtx*)&((u8*)pCommon)[-offsetof(DaemonCtx, c)];
  for(pClient=p->pClientList; pClient; pClient=pClient->pNext){
    if( pClient->pCont==pCont && pClient->iDbId==iDbId ){
      if( pClient->prefetch.bPrefetch ){
        nPrefetch++;
      }else{
        nClient++;
      }
    }
  }

  *pnClient = nClient;
  *pnPrefetch = nPrefetch;
}

/*
** Handle a message of type BCV_MESSAGE_VTAB from client pClient.
*/
static void bdHandleVtab(
  DaemonCtx *p, 
  DClient *pClient, 
  BcvMessage *pMsg
){
  const char *zTab = pMsg->u.vtab.zVtab;
  const char *zCont = pMsg->u.vtab.zContainer;
  const char *zDb = pMsg->u.vtab.zDatabase;
  const u32 colUsed = pMsg->u.vtab.colUsed;

  int rc = SQLITE_OK;
  BcvMessage reply;
  u8 *aData = 0;
  int nData = 0;
  int iVersion = pMsg->u.vtab.iVersion;

  memset(&reply, 0, sizeof(reply));
  reply.eType = BCV_MESSAGE_VTAB_REPLY;

  aData = bcvDatabaseVtabData(&rc, &p->c, 
      zTab, zCont, zDb, bcvProxyClientCount, colUsed, &nData, &iVersion
  );
  reply.u.vtab_r.aData = aData;
  reply.u.vtab_r.nData = nData;
  reply.u.vtab_r.iVersion = iVersion;
  bdSendMsg(p, pClient, &reply);

  sqlite3_free(aData);
  sqlite3_free(pMsg);
}

/*
1801
1802
1803
1804
1805
1806
1807

1808
1809
1810
1811
1812
1813
1814
  const char *zCont = pMsg->u.hello.zContainer;
  const char *zDb = pMsg->u.hello.zDatabase;
  Container *pCont = 0;
  ManifestDb *pDb = 0;
  BcvMessage reply;
  char *zErr = 0;


  pCont = bcvfsFindContAlias(&p->c, zCont, &zErr);
  if( pCont && zDb ){
    pDb = bcvfsFindDatabase(pCont->pMan, zDb, -1);
    if( pDb==0 ){
      zErr = bcvMprintf("no such database: /%s/%s", zCont, zDb);
      pCont = 0;
    }







>







1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
  const char *zCont = pMsg->u.hello.zContainer;
  const char *zDb = pMsg->u.hello.zDatabase;
  Container *pCont = 0;
  ManifestDb *pDb = 0;
  BcvMessage reply;
  char *zErr = 0;

  pClient->prefetch.bPrefetch = pMsg->u.hello.bPrefetch;
  pCont = bcvfsFindContAlias(&p->c, zCont, &zErr);
  if( pCont && zDb ){
    pDb = bcvfsFindDatabase(pCont->pMan, zDb, -1);
    if( pDb==0 ){
      zErr = bcvMprintf("no such database: /%s/%s", zCont, zDb);
      pCont = 0;
    }
2428
2429
2430
2431
2432
2433
2434

2435
2436
2437
2438
2439
2440
2441
  DClient *pClient, 
  BcvMessage *pMsg
){
  BcvContainer *pBcv = 0;
  int rc = SQLITE_OK;

  pClient->prefetch.bReply = 1;


  pBcv = bdUpdateBCV(pClient, pMsg->u.pass.zAuth);
  if( pClient->pManDb==0 ){
    Manifest *pMan = pClient->pCont->pMan;
    ManifestDb *pDb = bcvManifestDbidToDb(pMan, pClient->iDbId);
    if( pDb ){
      bcvManifestRef(pMan);







>







2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
  DClient *pClient, 
  BcvMessage *pMsg
){
  BcvContainer *pBcv = 0;
  int rc = SQLITE_OK;

  pClient->prefetch.bReply = 1;
  pClient->prefetch.bPrefetch = 1;

  pBcv = bdUpdateBCV(pClient, pMsg->u.pass.zAuth);
  if( pClient->pManDb==0 ){
    Manifest *pMan = pClient->pCont->pMan;
    ManifestDb *pDb = bcvManifestDbidToDb(pMan, pClient->iDbId);
    if( pDb ){
      bcvManifestRef(pMan);
Changes to test/bcvfs_auth3.test.
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
do_test 1.1 {
  pf run 1 1000
} {0}

do_execsql_test 1.2 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 7 1 0 0 {}
}

do_test 1.3 {
  while {[pf run 2 1000]==0} {}
  pf destroy
} {}

do_execsql_test 1.4 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 7 7 0 0 {}
}

db close
$cmd destroy

#-------------------------------------------------------------------------








|










|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
do_test 1.1 {
  pf run 1 1000
} {0}

do_execsql_test 1.2 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 7 1 0 0 {} 1 1
}

do_test 1.3 {
  while {[pf run 2 1000]==0} {}
  pf destroy
} {}

do_execsql_test 1.4 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 7 7 0 0 {} 1 0
}

db close
$cmd destroy

#-------------------------------------------------------------------------

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
do_test 2.1 {
  pf run 1 1000
} {0}

do_execsql_test 2.2 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 7 1 0 0 {}
}

do_test 2.3 {
  while {[pf run 2 1000]==0} {}
  pf errcode
} {403}
pf destroy

do_execsql_test 2.4 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 7 1 0 0 {}
}

db close
$cmd destroy

finish_test









|











|








105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
do_test 2.1 {
  pf run 1 1000
} {0}

do_execsql_test 2.2 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 7 1 0 0 {} 1 1
}

do_test 2.3 {
  while {[pf run 2 1000]==0} {}
  pf errcode
} {403}
pf destroy

do_execsql_test 2.4 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 7 1 0 0 {} 1 0
}

db close
$cmd destroy

finish_test


Changes to test/bcvfs_copy2.test.
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
bcvfs_attach $cmd cont1
sqlite3 db /cont1/t1.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 1.0 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {}
}

$cmd copy cont1 t1.db t2.db

do_execsql_test 1.1 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {}
  cont1 t2.db 1 1 0 0 copied
}

sqlite3 db2 /cont1/t2.db -vfs bcvfs
do_execsql2_test 1.2 {
  SELECT * FROM x1
} {
  hello world one two







|







|
|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
bcvfs_attach $cmd cont1
sqlite3 db /cont1/t1.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 1.0 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {} 1 0
}

$cmd copy cont1 t1.db t2.db

do_execsql_test 1.1 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {} 1 0
  cont1 t2.db 1 1 0 0 copied 0 0
}

sqlite3 db2 /cont1/t2.db -vfs bcvfs
do_execsql2_test 1.2 {
  SELECT * FROM x1
} {
  hello world one two
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
  hello world one two A B
}

$cmd copy cont1 t2.db t3.db
do_execsql_test 1.5 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 0 0 0 {}
  cont1 t2.db 1 1 0 0 {}
  cont1 t3.db 1 1 0 0 copied
}

db2 close
db close
$cmd destroy

set cmd [bcvfs_create testdir bcvfs]
sqlite3 db /cont1/t1.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 1.6 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {}
  cont1 t2.db 1 1 0 0 {}
  cont1 t3.db 1 1 0 0 copied
}

do_execsql_test 1.7 {
  INSERT INTO x1 VALUES('yes', 'no');
}

$cmd upload cont1

do_execsql_test 1.8 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {}
  cont1 t2.db 1 1 0 0 {}
  cont1 t3.db 1 1 0 0 {}
}

do_test 1.9 {
  $cmd copy cont1 t1.db t4.db
  set bcv [bcv_open cont1]
  $bcv copy t1.db t5.db
  $bcv close







|
|
|













|
|
|











|
|
|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
  hello world one two A B
}

$cmd copy cont1 t2.db t3.db
do_execsql_test 1.5 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 0 0 0 {} 1 0
  cont1 t2.db 1 1 0 0 {} 1 0
  cont1 t3.db 1 1 0 0 copied 0 0
}

db2 close
db close
$cmd destroy

set cmd [bcvfs_create testdir bcvfs]
sqlite3 db /cont1/t1.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 1.6 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {} 1 0
  cont1 t2.db 1 1 0 0 {} 0 0
  cont1 t3.db 1 1 0 0 copied 0 0
}

do_execsql_test 1.7 {
  INSERT INTO x1 VALUES('yes', 'no');
}

$cmd upload cont1

do_execsql_test 1.8 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {} 1 0
  cont1 t2.db 1 1 0 0 {} 0 0
  cont1 t3.db 1 1 0 0 {} 0 0
}

do_test 1.9 {
  $cmd copy cont1 t1.db t4.db
  set bcv [bcv_open cont1]
  $bcv copy t1.db t5.db
  $bcv close
Changes to test/bcvfs_delete2.test.
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
bcvfs_attach $bcvfs cont5
sqlite3 db /cont5/a.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 3.0 {
  SELECT * FROM bcv_database
} {
  cont5 a.db 7 1 0 0 {}
  cont5 b.db 1 0 0 0 {}
}

do_execsql_test 3.1 {
  UPDATE t1 SET y=1 WHERE rowid IN (100, 500, 900);
  PRAGMA wal_checkpoint = truncate;
} {0 0 0}

do_execsql_test 3.2 {
  SELECT * FROM bcv_database
} {
  cont5 a.db 7 3 3 0 {}
  cont5 b.db 1 0 0 0 {}
}

db close
$bcvfs delete cont5 a.db
$bcvfs upload cont5
sqlite3 db /cont5/b.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 3.3 {
  SELECT * FROM t1
} {
  hello world
}

do_execsql_test 3.2 {
  SELECT * FROM bcv_database
} {
  cont5 b.db 1 1 0 0 {}
}


db close
$bcvfs destroy

finish_test








|
|










|
|

















|








232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
bcvfs_attach $bcvfs cont5
sqlite3 db /cont5/a.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 3.0 {
  SELECT * FROM bcv_database
} {
  cont5 a.db 7 1 0 0 {} 1 0
  cont5 b.db 1 0 0 0 {} 0 0
}

do_execsql_test 3.1 {
  UPDATE t1 SET y=1 WHERE rowid IN (100, 500, 900);
  PRAGMA wal_checkpoint = truncate;
} {0 0 0}

do_execsql_test 3.2 {
  SELECT * FROM bcv_database
} {
  cont5 a.db 7 3 3 0 {} 1 0
  cont5 b.db 1 0 0 0 {} 0 0
}

db close
$bcvfs delete cont5 a.db
$bcvfs upload cont5
sqlite3 db /cont5/b.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 3.3 {
  SELECT * FROM t1
} {
  hello world
}

do_execsql_test 3.2 {
  SELECT * FROM bcv_database
} {
  cont5 b.db 1 1 0 0 {} 1 0
}


db close
$bcvfs destroy

finish_test

Changes to test/bcvfs_file1.test.
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
do_execsql_test 4.1 {
  SELECT name, container FROM bcv_container
} {xyz23 xyz23}

do_execsql_test 4.2 {
  SELECT * FROM bcv_database
} {
  xyz23 a.db 1 0 0 0 {}
  xyz23 b.db 1 0 0 0 {}
}

db close
do_test 4.3 {
  list [catch { sqlite3 db /xyz24 -vfs bcvfs } msg] $msg
} {1 {unable to open database file}}








|
|







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
do_execsql_test 4.1 {
  SELECT name, container FROM bcv_container
} {xyz23 xyz23}

do_execsql_test 4.2 {
  SELECT * FROM bcv_database
} {
  xyz23 a.db 1 0 0 0 {} 0 0
  xyz23 b.db 1 0 0 0 {} 0 0
}

db close
do_test 4.3 {
  list [catch { sqlite3 db /xyz24 -vfs bcvfs } msg] $msg
} {1 {unable to open database file}}

Changes to test/bcvfs_poll1.test.
276
277
278
279
280
281
282
283
284
285


286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
} {{hello world}}
db3 close

sqlite3_bcvfs_register_vtab db2
do_execsql2_test 3.8 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {} 
  cont1 t2.db 1 1 1 0 {}
}


do_test 3.9 {
  $cmd2 delete cont1 t2.db
} {}
do_execsql2_test 3.10 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {} 
  cont1 t2.db 0 0 0 0 deleted
}
do_test 3.11 {
  db eval {
    INSERT INTO t1 VALUES(5), (6);
    PRAGMA wal_checkpoint;
  }
  $cmd upload cont1
} {}

do_test 3.12 {
  $cmd2 poll cont1
} {}

do_execsql2_test 3.13 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {} 
  cont1 t2.db 0 0 0 0 deleted
}

db2 close
db close
$cmd destroy
$cmd2 destroy








|
|

>
>






|
|
















|
|







276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
} {{hello world}}
db3 close

sqlite3_bcvfs_register_vtab db2
do_execsql2_test 3.8 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {} 1 0
  cont1 t2.db 1 1 1 0 {} 0 0
}


do_test 3.9 {
  $cmd2 delete cont1 t2.db
} {}
do_execsql2_test 3.10 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {} 1 0
  cont1 t2.db 0 0 0 0 deleted 0 0
}
do_test 3.11 {
  db eval {
    INSERT INTO t1 VALUES(5), (6);
    PRAGMA wal_checkpoint;
  }
  $cmd upload cont1
} {}

do_test 3.12 {
  $cmd2 poll cont1
} {}

do_execsql2_test 3.13 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {} 1 0
  cont1 t2.db 0 0 0 0 deleted 0 0
}

db2 close
db close
$cmd destroy
$cmd2 destroy

Changes to test/bcvfs_revert1.test.
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  $cmd copy mycont x2.db copy.db
  $cmd delete mycont x4.db
} {}

do_execsql_test 1.3 {
  SELECT * FROM bcv_database
} {
  mycont x1.db 1 1 1 1 {} 
  mycont x2.db 1 0 0 0 {} 
  mycont x3.db 1 1 0 1 {} 
  mycont x4.db 0 0 0 0 deleted 
  mycont copy.db 1 0 0 0 copied
}

do_test 1.4 {
  $cmd revert mycont
} {}

sqlite3 db  /mycont/x1.db -vfs bcvfs
sqlite3 db2 /mycont/x3.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 1.5 {
  SELECT * FROM t1;
} {1 4 7}
do_execsql2_test 1.6 {
  SELECT * FROM t1;
} {3 6 9}
do_execsql_test 1.7 {
  SELECT * FROM bcv_database
} {
  mycont x1.db 1 1 0 0 {} 
  mycont x2.db 1 0 0 0 {} 
  mycont x3.db 1 1 0 0 {} 
  mycont x4.db 1 0 0 0 {} 
}

db close
db2 close
$cmd destroy

#-------------------------------------------------------------------------







|
|
|
|
|



















|
|
|
|







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  $cmd copy mycont x2.db copy.db
  $cmd delete mycont x4.db
} {}

do_execsql_test 1.3 {
  SELECT * FROM bcv_database
} {
  mycont x1.db 1 1 1 1 {} 1 0
  mycont x2.db 1 0 0 0 {} 0 0
  mycont x3.db 1 1 0 1 {} 1 0
  mycont x4.db 0 0 0 0 deleted 0 0
  mycont copy.db 1 0 0 0 copied 0 0
}

do_test 1.4 {
  $cmd revert mycont
} {}

sqlite3 db  /mycont/x1.db -vfs bcvfs
sqlite3 db2 /mycont/x3.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 1.5 {
  SELECT * FROM t1;
} {1 4 7}
do_execsql2_test 1.6 {
  SELECT * FROM t1;
} {3 6 9}
do_execsql_test 1.7 {
  SELECT * FROM bcv_database
} {
  mycont x1.db 1 1 0 0 {} 1 0
  mycont x2.db 1 0 0 0 {} 0 0
  mycont x3.db 1 1 0 0 {} 1 0
  mycont x4.db 1 0 0 0 {} 0 0
}

db close
db2 close
$cmd destroy

#-------------------------------------------------------------------------
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  list [catch { $cmd revert mycont} msg] $msg
} {0 {}}

sqlite3_bcvfs_register_vtab db
do_execsql_test 2.8 {
  SELECT * FROM bcv_database
} {
  mycont x1.db 1 1 0 0 {} 
  mycont x2.db 1 0 0 0 {} 
  mycont x3.db 1 0 0 0 {} 
}

do_test 2.9 {
  $cmd copy mycont x2.db x4.db
  $cmd copy mycont x2.db x5.db
  $cmd delete mycont x4.db
} {}

do_execsql_test 2.10 {
  SELECT * FROM bcv_database
} {
  mycont x1.db 1 1 0 0 {} 
  mycont x2.db 1 0 0 0 {} 
  mycont x3.db 1 0 0 0 {} 
  mycont x4.db 0 0 0 0 deleted 
  mycont x5.db 1 0 0 0 copied 
}

do_test 2.11 {
  list [catch { $cmd revert mycont} msg] $msg
} {0 {}}

do_execsql_test 2.12 {
  SELECT * FROM bcv_database
} {
  mycont x1.db 1 1 0 0 {} 
  mycont x2.db 1 0 0 0 {} 
  mycont x3.db 1 0 0 0 {} 
}

db close
sqlite3 db  / -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_test 2.13 {
   $cmd delete mycont x3.db
   $cmd delete mycont x2.db
   $cmd delete mycont x1.db
} {}

do_execsql_test 2.14 {
  SELECT * FROM bcv_database
} {
  mycont x1.db 0 0 0 0 deleted
  mycont x2.db 0 0 0 0 deleted
  mycont x3.db 0 0 0 0 deleted
}

db close
$cmd destroy

finish_test








|
|
|











|
|
|
|
|









|
|
|















|
|
|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  list [catch { $cmd revert mycont} msg] $msg
} {0 {}}

sqlite3_bcvfs_register_vtab db
do_execsql_test 2.8 {
  SELECT * FROM bcv_database
} {
  mycont x1.db 1 1 0 0 {} 1 0
  mycont x2.db 1 0 0 0 {} 0 0
  mycont x3.db 1 0 0 0 {} 0 0
}

do_test 2.9 {
  $cmd copy mycont x2.db x4.db
  $cmd copy mycont x2.db x5.db
  $cmd delete mycont x4.db
} {}

do_execsql_test 2.10 {
  SELECT * FROM bcv_database
} {
  mycont x1.db 1 1 0 0 {} 1 0
  mycont x2.db 1 0 0 0 {} 0 0
  mycont x3.db 1 0 0 0 {} 0 0 
  mycont x4.db 0 0 0 0 deleted 0 0
  mycont x5.db 1 0 0 0 copied 0 0
}

do_test 2.11 {
  list [catch { $cmd revert mycont} msg] $msg
} {0 {}}

do_execsql_test 2.12 {
  SELECT * FROM bcv_database
} {
  mycont x1.db 1 1 0 0 {} 1 0
  mycont x2.db 1 0 0 0 {} 0 0
  mycont x3.db 1 0 0 0 {} 0 0
}

db close
sqlite3 db  / -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_test 2.13 {
   $cmd delete mycont x3.db
   $cmd delete mycont x2.db
   $cmd delete mycont x1.db
} {}

do_execsql_test 2.14 {
  SELECT * FROM bcv_database
} {
  mycont x1.db 0 0 0 0 deleted 0 0
  mycont x2.db 0 0 0 0 deleted 0 0
  mycont x3.db 0 0 0 0 deleted 0 0
}

db close
$cmd destroy

finish_test

Changes to test/bcvfs_upload2.test.
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#  nblock INTEGER
#  ncache INTEGER
#  ndirty INTEGER
#  walfile BOOLEAN
do_execsql_test 1.1 {
  SELECT * FROM bcv_database
} {
  cont1 x1.db 1 0 0 0 {}
  cont1 x2.db 1 1 0 1 {}
  cont1 x3.db 1 0 0 0 {}
}

do_test 1.2 {
  $cmd upload cont1
} {}

do_execsql_test 1.3 {
  SELECT * FROM bcv_database
} {
  cont1 x1.db 1 0 0 0 {}
  cont1 x2.db 1 1 0 0 {}
  cont1 x3.db 1 0 0 0 {}
}

do_execsql_test 1.4 {
  INSERT INTO t1 VALUES(5, 6);
  INSERT INTO t1 VALUES(7, 8);
  PRAGMA wal_checkpoint;
} {
  0 2 2
}

do_execsql_test 1.4 {
  SELECT * FROM bcv_database
} {
  cont1 x1.db 1 0 0 0 {}
  cont1 x2.db 1 1 1 1 {}
  cont1 x3.db 1 0 0 0 {}
}

do_test 1.5 {
  set fd [open testdir/cont1/x3.db-wal w]
  puts $fd hello_world
  close $fd
} {}

do_execsql_test 1.6 {
  SELECT * FROM bcv_database
} {
  cont1 x1.db 1 0 0 0 {}
  cont1 x2.db 1 1 1 1 {}
  cont1 x3.db 1 0 0 1 {}
}

do_test 1.7 {
  $cmd upload cont1
} {}

do_execsql_test 1.8 {
  SELECT * FROM bcv_database
} {
  cont1 x1.db 1 0 0 0 {}
  cont1 x2.db 1 1 0 0 {}
  cont1 x3.db 1 1 0 0 {}
}

do_execsql_test 1.9 {
  INSERT INTO t1 VALUES(9, 10);
} {
}








|
|
|









|
|
|













|
|
|











|
|
|









|
|
|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#  nblock INTEGER
#  ncache INTEGER
#  ndirty INTEGER
#  walfile BOOLEAN
do_execsql_test 1.1 {
  SELECT * FROM bcv_database
} {
  cont1 x1.db 1 0 0 0 {} 0 0
  cont1 x2.db 1 1 0 1 {} 1 0
  cont1 x3.db 1 0 0 0 {} 0 0
}

do_test 1.2 {
  $cmd upload cont1
} {}

do_execsql_test 1.3 {
  SELECT * FROM bcv_database
} {
  cont1 x1.db 1 0 0 0 {} 0 0
  cont1 x2.db 1 1 0 0 {} 1 0
  cont1 x3.db 1 0 0 0 {} 0 0
}

do_execsql_test 1.4 {
  INSERT INTO t1 VALUES(5, 6);
  INSERT INTO t1 VALUES(7, 8);
  PRAGMA wal_checkpoint;
} {
  0 2 2
}

do_execsql_test 1.4 {
  SELECT * FROM bcv_database
} {
  cont1 x1.db 1 0 0 0 {} 0 0
  cont1 x2.db 1 1 1 1 {} 1 0
  cont1 x3.db 1 0 0 0 {} 0 0
}

do_test 1.5 {
  set fd [open testdir/cont1/x3.db-wal w]
  puts $fd hello_world
  close $fd
} {}

do_execsql_test 1.6 {
  SELECT * FROM bcv_database
} {
  cont1 x1.db 1 0 0 0 {} 0 0
  cont1 x2.db 1 1 1 1 {} 1 0
  cont1 x3.db 1 0 0 1 {} 0 0
}

do_test 1.7 {
  $cmd upload cont1
} {}

do_execsql_test 1.8 {
  SELECT * FROM bcv_database
} {
  cont1 x1.db 1 0 0 0 {} 0 0
  cont1 x2.db 1 1 0 0 {} 1 0
  cont1 x3.db 1 1 0 0 {} 0 0
}

do_execsql_test 1.9 {
  INSERT INTO t1 VALUES(9, 10);
} {
}

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  BEGIN;
    SELECT * FROM t1;
} {1 2 3 4 5 6 7 8 9 10}

do_execsql_test 1.13 {
  SELECT * FROM bcv_database
} {
  cont1 x1.db 1 0 0 0 {}
  cont1 x2.db 1 1 1 1 {}
  cont1 x3.db 1 1 0 0 {}
}

do_test 1.14 {
  list [catch { $cmd upload cont1 } msg] $msg
} {0 {}}

db2 close
db close
$cmd destroy

finish_test








|
|
|












121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  BEGIN;
    SELECT * FROM t1;
} {1 2 3 4 5 6 7 8 9 10}

do_execsql_test 1.13 {
  SELECT * FROM bcv_database
} {
  cont1 x1.db 1 0 0 0 {} 0 0
  cont1 x2.db 1 1 1 1 {} 2 0
  cont1 x3.db 1 1 0 0 {} 0 0
}

do_test 1.14 {
  list [catch { $cmd upload cont1 } msg] $msg
} {0 {}}

db2 close
db close
$cmd destroy

finish_test

Added test/bcvfs_vtab3.test.


































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#
# 18-August-2023
#
#-------------------------------------------------------------------------
#

source [file join [file dirname [info script]] test_common.tcl]
set testprefix bcvfs_vtab3

bcv_mkdir testdir
bcv_create_container cont1
bcv_upload_new_db cont1 test.db {
  CREATE TABLE t1(x, y);
}

set cmd [bcvfs_create testdir "bcvfs"]
bcvfs_attach $cmd cont1

sqlite3 db /cont1/test.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 1.0 {
  SELECT container, database, nclient, nprefetch FROM bcv_database
} {cont1 test.db 1 0}

sqlite3 db2 /cont1/test.db -vfs bcvfs

do_execsql_test 1.1 {
  SELECT container, database, nclient, nprefetch FROM bcv_database
} {cont1 test.db 2 0}

foreach {tn script nclient nprefetch} {
  1 {
    sqlite3 db2 /cont1/test.db -vfs bcvfs
    $cmd prefetch_new pf1 cont1 test.db
  } 2 1
  2 {
    pf1 destroy
    sqlite3 db3 /cont1/test.db -vfs bcvfs
  } 3 0
  3 {
    $cmd prefetch_new pf1 cont1 test.db
    $cmd prefetch_new pf2 cont1 test.db
    $cmd prefetch_new pf3 cont1 test.db
    db2 close
  } 2 3
  4 {
    pf1 destroy
    pf3 destroy
    db close
    sqlite3 db /cont1/test.db -vfs bcvfs
    sqlite3_bcvfs_register_vtab db
  } 2 1
  5 {
    pf2 destroy
    db3 close
  } 1 0
  6 {
    db close
    sqlite3 db2 /cont1/test.db -vfs bcvfs
    sqlite3 db /cont1/test.db -vfs bcvfs
    sqlite3_bcvfs_register_vtab db
  } 2 0
  7 {
    db2 close
  } 1 0
} {
  eval $script
  do_execsql_test 1.3.$tn {
    SELECT container, database, nclient, nprefetch FROM bcv_database
  } [list cont1 test.db $nclient $nprefetch]
}

bcv_upload_new_db cont1 test.db2 { CREATE TABLE t1(x, y); }
bcv_upload_new_db cont1 test.db3 { CREATE TABLE t1(x, y); }
bcv_upload_new_db cont1 test.db4 { CREATE TABLE t1(x, y); }

$cmd poll cont1

sqlite3 db2.1 /cont1/test.db2 -vfs bcvfs
sqlite3 db2.2 /cont1/test.db2 -vfs bcvfs
sqlite3 db3.1 /cont1/test.db3 -vfs bcvfs
sqlite3 db3.2 /cont1/test.db3 -vfs bcvfs
sqlite3 db3.3 /cont1/test.db3 -vfs bcvfs
sqlite3 db4.1 /cont1/test.db4 -vfs bcvfs
sqlite3 db4.2 /cont1/test.db4 -vfs bcvfs
sqlite3 db4.3 /cont1/test.db4 -vfs bcvfs
sqlite3 db4.4 /cont1/test.db4 -vfs bcvfs

do_execsql_test 1.4 {
  SELECT container, database, nclient, nprefetch FROM bcv_database
} {
  cont1 test.db  1 0
  cont1 test.db2 2 0
  cont1 test.db3 3 0
  cont1 test.db4 4 0
}

db2.1 close
db2.2 close
db3.1 close
db3.2 close
db3.3 close
db4.1 close
db4.2 close
db4.3 close
db4.4 close

db close
$cmd destroy
finish_test


Changes to test/dmn1.test.
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  cont2 cont2 0
  cont1 cont1 0
}

do_execsql_test 1.2.4 {
  SELECT * FROM bcv_database
} {
  c3    t3.db 1 0 0 0 {}
  cont2 t2.db 1 0 0 0 {}
  cont1 t1.db 1 0 0 0 {}
}

db close
$cmd destroy
wait_daemon 0

#-------------------------------------------------------------------------







|
|
|







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  cont2 cont2 0
  cont1 cont1 0
}

do_execsql_test 1.2.4 {
  SELECT * FROM bcv_database
} {
  c3    t3.db 1 0 0 0 {} 0 0
  cont2 t2.db 1 0 0 0 {} 0 0
  cont1 t1.db 1 0 0 0 {} 0 0
}

db close
$cmd destroy
wait_daemon 0

#-------------------------------------------------------------------------
Changes to test/dmn2.test.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
do_execsql_test 1.1 {
  SELECT * FROM t1
} {fox guard}

do_execsql_test 1.2 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {}
}

bcv_upload_new_db cont1 t2.db {
  CREATE TABLE t2(a, b);
  INSERT INTO t2 VALUES('a', 'b');
}

do_execsql_test 1.3 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {}
}

$::cmd poll cont1
do_execsql_test 1.4 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {}
  cont1 t2.db 1 0 0 0 {}
}

bcv_mkdir testdir
set cmd2 [bcvfs_create testdir bcvfs2]
bcvfs_attach $cmd2 cont1
sqlite3 db2 /cont1/t1.db -vfs bcvfs2








|










|






|
|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
do_execsql_test 1.1 {
  SELECT * FROM t1
} {fox guard}

do_execsql_test 1.2 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {} 1 0
}

bcv_upload_new_db cont1 t2.db {
  CREATE TABLE t2(a, b);
  INSERT INTO t2 VALUES('a', 'b');
}

do_execsql_test 1.3 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {} 1 0
}

$::cmd poll cont1
do_execsql_test 1.4 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 1 1 0 0 {} 1 0
  cont1 t2.db 1 0 0 0 {} 0 0
}

bcv_mkdir testdir
set cmd2 [bcvfs_create testdir bcvfs2]
bcvfs_attach $cmd2 cont1
sqlite3 db2 /cont1/t1.db -vfs bcvfs2

Changes to test/dmn_auth1.test.
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

sqlite3 db /cont1/t1.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 1.0 {
  PRAGMA cache_size = 10;
  SELECT * FROM bcv_database
} {cont1 t1.db 10 1 0 0 {}}

for {set i 0} {$i < 10} {incr i} {
  do_execsql_test 1.1.$i {
    SELECT count(x || y) FROM x1
  } {1500}
  wait_ms 1000
}







|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

sqlite3 db /cont1/t1.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 1.0 {
  PRAGMA cache_size = 10;
  SELECT * FROM bcv_database
} {cont1 t1.db 10 1 0 0 {} 1 0}

for {set i 0} {$i < 10} {incr i} {
  do_execsql_test 1.1.$i {
    SELECT count(x || y) FROM x1
  } {1500}
  wait_ms 1000
}
Changes to test/dmn_auth2.test.
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
do_test 1.1 {
  pf run 1 1000
} {0}

do_execsql_test 1.2 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 7 2 0 0 {}
}

do_test 1.3 {
  while {[pf run 2 1000]==0} {}
  pf destroy
} {}

do_execsql_test 1.4 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 7 7 0 0 {}
}

db close
$cmd destroy
wait_daemon 0









|










|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
do_test 1.1 {
  pf run 1 1000
} {0}

do_execsql_test 1.2 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 7 2 0 0 {} 1 1
}

do_test 1.3 {
  while {[pf run 2 1000]==0} {}
  pf destroy
} {}

do_execsql_test 1.4 {
  SELECT * FROM bcv_database
} {
  cont1 t1.db 7 7 0 0 {} 1 0
}

db close
$cmd destroy
wait_daemon 0


Added test/dmn_vtab3.test.






































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#
# 18-August-2023
#
#-------------------------------------------------------------------------
#

source [file join [file dirname [info script]] test_common.tcl]
set testprefix dmn_vtab3.test

bcv_create_container cont1
bcv_upload_new_db cont1 test.db {
  CREATE TABLE t1(x, y);
}

start_new_daemon 0 
set cmd [bcvfs_create testdir.0 "bcvfs"]
bcvfs_attach $cmd cont1

sqlite3 db /cont1/test.db -vfs bcvfs
sqlite3_bcvfs_register_vtab db

do_execsql_test 1.0 {
  SELECT container, database, nclient, nprefetch FROM bcv_database
} {cont1 test.db 1 0}

sqlite3 db2 /cont1/test.db -vfs bcvfs

do_execsql_test 1.1 {
  SELECT container, database, nclient, nprefetch FROM bcv_database
} {cont1 test.db 2 0}

foreach {tn script nclient nprefetch} {
  1 {
    sqlite3 db2 /cont1/test.db -vfs bcvfs
    $cmd prefetch_new pf1 cont1 test.db
  } 2 1
  2 {
    pf1 destroy
    sqlite3 db3 /cont1/test.db -vfs bcvfs
  } 3 0
  3 {
    $cmd prefetch_new pf1 cont1 test.db
    $cmd prefetch_new pf2 cont1 test.db
    $cmd prefetch_new pf3 cont1 test.db
    db2 close
  } 2 3
  4 {
    pf1 destroy
    pf3 destroy
    db close
    sqlite3 db /cont1/test.db -vfs bcvfs
    sqlite3_bcvfs_register_vtab db
  } 2 1
  5 {
    pf2 destroy
    db3 close
  } 1 0
  6 {
    sqlite3 db2 /cont1/test.db -vfs bcvfs
    db close
    sqlite3 db /cont1/test.db -vfs bcvfs
    sqlite3_bcvfs_register_vtab db
  } 2 0
  7 {
    db2 close
  } 1 0
} {
  eval $script
  do_execsql_test 1.3.$tn {
    SELECT container, database, nclient, nprefetch FROM bcv_database
  } [list cont1 test.db $nclient $nprefetch]
}

bcv_upload_new_db cont1 test.db2 { CREATE TABLE t1(x, y); }
bcv_upload_new_db cont1 test.db3 { CREATE TABLE t1(x, y); }
bcv_upload_new_db cont1 test.db4 { CREATE TABLE t1(x, y); }

$cmd poll cont1

sqlite3 db2.1 /cont1/test.db2 -vfs bcvfs
sqlite3 db2.2 /cont1/test.db2 -vfs bcvfs
sqlite3 db3.1 /cont1/test.db3 -vfs bcvfs
sqlite3 db3.2 /cont1/test.db3 -vfs bcvfs
sqlite3 db3.3 /cont1/test.db3 -vfs bcvfs
sqlite3 db4.1 /cont1/test.db4 -vfs bcvfs
sqlite3 db4.2 /cont1/test.db4 -vfs bcvfs
sqlite3 db4.3 /cont1/test.db4 -vfs bcvfs
sqlite3 db4.4 /cont1/test.db4 -vfs bcvfs

do_execsql_test 1.4 {
  SELECT container, database, nclient, nprefetch FROM bcv_database
} {
  cont1 test.db  1 0
  cont1 test.db2 2 0
  cont1 test.db3 3 0
  cont1 test.db4 4 0
}

db2.1 close
db2.2 close
db3.1 close
db3.2 close
db3.3 close
db4.1 close
db4.2 close
db4.3 close
db4.4 close

db close
$cmd destroy

wait_daemon 0
finish_test