/ Check-in [6fd09854]
Login

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

Overview
Comment:Test that sqlite3ota_open() works with URI paths. Fix some other issues.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | ota-update
Files: files | file ages | folders
SHA1: 6fd09854feb46739f42b7e7a5e76680d5f9b8c5a
User & Date: dan 2014-10-21 19:35:03
Context
2014-10-22
11:30
Sync the database file in sqlite3_ckpt_close(), even if the checkpoint has not finished. check-in: e2729d62 user: dan tags: ota-update
2014-10-21
19:35
Test that sqlite3ota_open() works with URI paths. Fix some other issues. check-in: 6fd09854 user: dan tags: ota-update
18:09
Add tests for another application writing the database while an ota update is ongoing. check-in: 2402baa0 user: dan tags: ota-update
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/ota/ota1.test.

12
13
14
15
16
17
18



19
20
21
22
23
24
25
..
87
88
89
90
91
92
93












94
95
96
97
98
99
100
101

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix ota1





# Create a simple OTA database. That expects to write to a table:
#
#   CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
#
proc create_ota1 {filename} {
  forcedelete $filename
................................................................................
    set rc [ota step]
    ota close
    if {$rc != "SQLITE_OK"} break
  }
  set rc
}













foreach {tn2 cmd} {1 run_ota 2 step_ota} {
  foreach {tn schema} {
    1 {
      CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
    }
    2 { 
      CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
      CREATE INDEX i1 ON t1(b);







>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
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
116

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix ota1

db close
sqlite3_shutdown
sqlite3_config_uri 1

# Create a simple OTA database. That expects to write to a table:
#
#   CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
#
proc create_ota1 {filename} {
  forcedelete $filename
................................................................................
    set rc [ota step]
    ota close
    if {$rc != "SQLITE_OK"} break
  }
  set rc
}

# Same as [step_ota], except using a URI to open the target db.
#
proc step_ota_uri {target ota} {
  while 1 {
    sqlite3ota ota file:$target?xyz=123 $ota
    set rc [ota step]
    ota close
    if {$rc != "SQLITE_OK"} break
  }
  set rc
}

foreach {tn2 cmd} {1 run_ota 2 step_ota 3 step_ota_uri} {
  foreach {tn schema} {
    1 {
      CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
    }
    2 { 
      CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
      CREATE INDEX i1 ON t1(b);

Changes to ext/ota/sqlite3ota.c.

777
778
779
780
781
782
783




784
785
786
787
788
789
790
...
824
825
826
827
828
829
830
831


832
833
834
835
836
837
838
839
840

841
842
843
844
845
846
847
    }
    sqlite3_free(zWhere);
    sqlite3_free(zSet);
  }
  return p->rc;
}





static void otaOpenDatabase(sqlite3ota *p){
  assert( p->rc==SQLITE_OK );
  sqlite3_close(p->db);
  p->db = 0;

  p->rc = sqlite3_open(p->zTarget, &p->db);
  if( p->rc ){
................................................................................
    for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
    if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
  }
#endif
}

/*
** Move the "*-oal" file corresponding to the target database to the


** "*-wal" location. If an error occurs, leave an error code and error 
** message in the ota handle.
*/
static void otaMoveOalFile(sqlite3ota *p){
  const char *zBase = sqlite3_db_filename(p->db, "main");

  char *zWal = sqlite3_mprintf("%s-wal", zBase);
  char *zOal = sqlite3_mprintf("%s-oal", zBase);


  assert( p->rc==SQLITE_OK && p->zErrmsg==0 );
  if( zWal==0 || zOal==0 ){
    p->rc = SQLITE_NOMEM;
  }else{
    /* Move the *-oal file to *-wal. At this point connection p->db is
    ** holding a SHARED lock on the target database file (because it is
    ** in WAL mode). So no other connection may be writing the db.  */







>
>
>
>







 







|
>
>
|
|







>







777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
...
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
    }
    sqlite3_free(zWhere);
    sqlite3_free(zSet);
  }
  return p->rc;
}

/*
** Open the database handle and attach the OTA database as "ota". If an
** error occurs, leave an error code and message in the OTA handle.
*/
static void otaOpenDatabase(sqlite3ota *p){
  assert( p->rc==SQLITE_OK );
  sqlite3_close(p->db);
  p->db = 0;

  p->rc = sqlite3_open(p->zTarget, &p->db);
  if( p->rc ){
................................................................................
    for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
    if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
  }
#endif
}

/*
** The OTA handle is currently in OTA_STAGE_OAL state, with a SHARED lock
** on the database file. This proc moves the *-oal file to the *-wal path,
** then reopens the database file (this time in vanilla, non-oal, WAL mode).
** If an error occurs, leave an error code and error message in the ota 
** handle.
*/
static void otaMoveOalFile(sqlite3ota *p){
  const char *zBase = sqlite3_db_filename(p->db, "main");

  char *zWal = sqlite3_mprintf("%s-wal", zBase);
  char *zOal = sqlite3_mprintf("%s-oal", zBase);

  assert( p->eStage==OTA_STAGE_OAL );
  assert( p->rc==SQLITE_OK && p->zErrmsg==0 );
  if( zWal==0 || zOal==0 ){
    p->rc = SQLITE_NOMEM;
  }else{
    /* Move the *-oal file to *-wal. At this point connection p->db is
    ** holding a SHARED lock on the target database file (because it is
    ** in WAL mode). So no other connection may be writing the db.  */

Changes to src/main.c.

1769
1770
1771
1772
1773
1774
1775



1776
1777
1778
1779
1780
1781
1782
  }
  rc = sqlite3ApiExit(db, rc);
  sqlite3_mutex_leave(db->mutex);
  return rc;
#endif
}




int sqlite3_ckpt_open(
  sqlite3 *db, 
  unsigned char *a, int n, 
  sqlite3_ckpt **ppCkpt
){
  Pager *pPager;
  Btree *pBt;







>
>
>







1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
  }
  rc = sqlite3ApiExit(db, rc);
  sqlite3_mutex_leave(db->mutex);
  return rc;
#endif
}

/*
** Open an incremental checkpoint handle.
*/
int sqlite3_ckpt_open(
  sqlite3 *db, 
  unsigned char *a, int n, 
  sqlite3_ckpt **ppCkpt
){
  Pager *pPager;
  Btree *pBt;

Changes to src/pager.c.

619
620
621
622
623
624
625
626
627
628

629
630
631
632
633
634
635
....
7289
7290
7291
7292
7293
7294
7295

7296
7297



7298
7299
7300
7301
7302



7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
** otaMode
**   This variable is normally 0. It is set to 1 by the PagerSetOtaMode()
**   function - as a result of a "PRAGMA pager_ota_mode=1" command. Once 
**   the *-oal file has been opened and it has been determined that the 
**   database file has not been modified since it was created, this variable 
**   is set to 2.
**
** noCkptOnClose
**
**

*/
struct Pager {
  sqlite3_vfs *pVfs;          /* OS functions to use for IO */
  u8 exclusiveMode;           /* Boolean. True if locking_mode==EXCLUSIVE */
  u8 journalMode;             /* One of the PAGER_JOURNALMODE_* values */
  u8 useJournal;              /* Use a rollback journal on this file */
  u8 noSync;                  /* Do not sync the journal if true */
................................................................................
}
#endif

/*
** Set or clear the "OTA mode" flag.
*/
int sqlite3PagerSetOtaMode(Pager *pPager, int iOta){

  if( iOta==1 && (pPager->pWal || pPager->eState!=PAGER_OPEN) ){
    return SQLITE_ERROR;



  }
  pPager->otaMode = iOta;
  return SQLITE_OK;
}




int sqlite3PagerWalCheckpointStart(
  sqlite3 *db, 
  Pager *pPager,
  u8 *a, int n, 
  sqlite3_ckpt **ppCkpt
){
  return sqlite3WalCheckpointStart(db, pPager->pWal, a, n,
      pPager->xBusyHandler, pPager->pBusyHandlerArg,
      pPager->ckptSyncFlags, ppCkpt
  );
}

#endif /* SQLITE_OMIT_DISKIO */







|
|
|
>







 







>


>
>
>





>
>
>













619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
....
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
** otaMode
**   This variable is normally 0. It is set to 1 by the PagerSetOtaMode()
**   function - as a result of a "PRAGMA pager_ota_mode=1" command. Once 
**   the *-oal file has been opened and it has been determined that the 
**   database file has not been modified since it was created, this variable 
**   is set to 2.
**
**   It is also possible to use PagerSetOtaMode() to 2 if the database is
**   already in WAL mode. In this case the only effect is to prevent the
**   connection from checkpointing the db as part of an sqlite3PagerClose()
**   call.
*/
struct Pager {
  sqlite3_vfs *pVfs;          /* OS functions to use for IO */
  u8 exclusiveMode;           /* Boolean. True if locking_mode==EXCLUSIVE */
  u8 journalMode;             /* One of the PAGER_JOURNALMODE_* values */
  u8 useJournal;              /* Use a rollback journal on this file */
  u8 noSync;                  /* Do not sync the journal if true */
................................................................................
}
#endif

/*
** Set or clear the "OTA mode" flag.
*/
int sqlite3PagerSetOtaMode(Pager *pPager, int iOta){
  assert( iOta==1 || iOta==2 );
  if( iOta==1 && (pPager->pWal || pPager->eState!=PAGER_OPEN) ){
    return SQLITE_ERROR;
  }
  if( iOta==2 && 0==pPager->pWal ){
    return SQLITE_ERROR;
  }
  pPager->otaMode = iOta;
  return SQLITE_OK;
}

/*
** Open an incremental checkpoint handle.
*/
int sqlite3PagerWalCheckpointStart(
  sqlite3 *db, 
  Pager *pPager,
  u8 *a, int n, 
  sqlite3_ckpt **ppCkpt
){
  return sqlite3WalCheckpointStart(db, pPager->pWal, a, n,
      pPager->xBusyHandler, pPager->pBusyHandlerArg,
      pPager->ckptSyncFlags, ppCkpt
  );
}

#endif /* SQLITE_OMIT_DISKIO */

Changes to src/wal.c.

3104
3105
3106
3107
3108
3109
3110



3111
3112
3113
3114
3115
3116
3117
  pWal->ckptLock = 0;
  sqlite3_free(p);
  memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
  sqlite3_mutex_leave(db->mutex);
  return rc;
}




int sqlite3WalCheckpointStart(
  sqlite3 *db,                    /* Database connection */
  Wal *pWal,                      /* Wal connection */
  u8 *aState, int nState,         /* Checkpoint state to restore */
  int (*xBusy)(void*),            /* Function to call when busy */
  void *pBusyArg,                 /* Context argument for xBusyHandler */
  int sync_flags,                 /* Flags to sync db file with (or 0) */







>
>
>







3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
  pWal->ckptLock = 0;
  sqlite3_free(p);
  memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
  sqlite3_mutex_leave(db->mutex);
  return rc;
}

/*
** Open an incremental checkpoint handle.
*/
int sqlite3WalCheckpointStart(
  sqlite3 *db,                    /* Database connection */
  Wal *pWal,                      /* Wal connection */
  u8 *aState, int nState,         /* Checkpoint state to restore */
  int (*xBusy)(void*),            /* Function to call when busy */
  void *pBusyArg,                 /* Context argument for xBusyHandler */
  int sync_flags,                 /* Flags to sync db file with (or 0) */

Changes to test/wal.test.

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
  list [file size test.db] [file size test.db-wal]
} [list 2048 [wal_file_size 3 1024]]

# Execute some transactions in auto-vacuum mode to test database file
# truncation.
#
do_test wal-8.1 {
breakpoint
  reopen_db
  catch { db close }
  forcedelete test.db test.db-wal

  sqlite3 db test.db
  db function blob blob
  execsql {







<







371
372
373
374
375
376
377

378
379
380
381
382
383
384
  list [file size test.db] [file size test.db-wal]
} [list 2048 [wal_file_size 3 1024]]

# Execute some transactions in auto-vacuum mode to test database file
# truncation.
#
do_test wal-8.1 {

  reopen_db
  catch { db close }
  forcedelete test.db test.db-wal

  sqlite3 db test.db
  db function blob blob
  execsql {