Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Further tweaks to work with zipvfs. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | ota-update-no-pager_ota_mode |
Files: | files | file ages | folders |
SHA1: |
0f152416be792457c52417aeb531ac86 |
User & Date: | dan 2015-02-10 20:00:38.125 |
Context
2015-02-11
| ||
16:25 | Ensure that an error is reported if an attempt is made to update a wal mode database via ota. (check-in: 6fc5d4d26a user: dan tags: ota-update-no-pager_ota_mode) | |
2015-02-10
| ||
20:00 | Further tweaks to work with zipvfs. (check-in: 0f152416be user: dan tags: ota-update-no-pager_ota_mode) | |
17:08 | Add documentation and test cases for sqlite3ota_create_vfs(). Also code to detect errors in zipvfs/ota setup. (check-in: e729668168 user: dan tags: ota-update-no-pager_ota_mode) | |
Changes
Changes to ext/ota/sqlite3ota.c.
︙ | ︙ | |||
71 72 73 74 75 76 77 | #define OTA_STATE_IDX 3 #define OTA_STATE_ROW 4 #define OTA_STATE_PROGRESS 5 #define OTA_STATE_CKPT 6 #define OTA_STATE_COOKIE 7 #define OTA_STAGE_OAL 1 | < | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #define OTA_STATE_IDX 3 #define OTA_STATE_ROW 4 #define OTA_STATE_PROGRESS 5 #define OTA_STATE_CKPT 6 #define OTA_STATE_COOKIE 7 #define OTA_STAGE_OAL 1 #define OTA_STAGE_CKPT 3 #define OTA_STAGE_DONE 4 #define OTA_CREATE_STATE "CREATE TABLE IF NOT EXISTS ota.ota_state" \ "(k INTEGER PRIMARY KEY, v)" |
︙ | ︙ | |||
171 172 173 174 175 176 177 | char *zErrmsg; /* Error message if rc!=SQLITE_OK */ int nStep; /* Rows processed for current object */ int nProgress; /* Rows processed for all objects */ OtaObjIter objiter; /* Iterator for skipping through tbl/idx */ sqlite3_ckpt *pCkpt; /* Incr-checkpoint handle */ ota_file *pTargetFd; /* File handle open on target db */ const char *zVfsName; /* Name of automatically created ota vfs */ | < > > | 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 | char *zErrmsg; /* Error message if rc!=SQLITE_OK */ int nStep; /* Rows processed for current object */ int nProgress; /* Rows processed for all objects */ OtaObjIter objiter; /* Iterator for skipping through tbl/idx */ sqlite3_ckpt *pCkpt; /* Incr-checkpoint handle */ ota_file *pTargetFd; /* File handle open on target db */ const char *zVfsName; /* Name of automatically created ota vfs */ }; struct ota_vfs { sqlite3_vfs base; /* ota VFS shim methods */ sqlite3_vfs *pRealVfs; /* Underlying VFS */ sqlite3_mutex *mutex; const char *zOtaWal; }; struct ota_file { sqlite3_file base; /* sqlite3_file methods */ sqlite3_file *pReal; /* Underlying file handle */ ota_vfs *pOtaVfs; /* Pointer to the ota_vfs object */ sqlite3ota *pOta; /* Pointer to ota object (ota target only) */ int openFlags; /* Flags this file was opened with */ unsigned int iCookie; /* Cookie value for main db files */ int nShm; /* Number of entries in apShm[] array */ char **apShm; /* Array of mmap'd *-shm regions */ const char *zWal; /* Wal filename for this db file */ char *zDel; /* Delete this when closing file */ }; |
︙ | ︙ | |||
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 | memcpy(pIter->zMask, zMask, pIter->nTblCol); } 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){ int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; assert( p->rc==SQLITE_OK ); assert( p->db==0 ); p->rc = sqlite3_open_v2(p->zTarget, &p->db, flags, p->zVfsName); if( p->rc ){ p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db)); }else{ /* Mark the database file just opened as an OTA target database. If ** this call returns SQLITE_NOTFOUND, then the OTA vfs is not in use. ** This is an error. */ | > > > > > > > > | | | | < < > | 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 | memcpy(pIter->zMask, zMask, pIter->nTblCol); } sqlite3_free(zWhere); sqlite3_free(zSet); } return p->rc; } static void otaSqlTrace(void *pCtx, const char *zSql){ /* printf("SQL: %s\n", zSql); */ } /* ** 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){ int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; assert( p->rc==SQLITE_OK ); assert( p->db==0 ); p->rc = sqlite3_open_v2(p->zTarget, &p->db, flags, p->zVfsName); if( p->rc ){ p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db)); }else{ otaMPrintfExec(p, "ATTACH %Q AS ota", p->zOta); /* sqlite3_trace(p->db, otaSqlTrace, 0); */ /* Mark the database file just opened as an OTA target database. If ** this call returns SQLITE_NOTFOUND, then the OTA vfs is not in use. ** This is an error. */ if( p->rc==SQLITE_OK ){ p->rc = sqlite3_file_control(p->db, "main", SQLITE_FCNTL_OTA, (void*)p); if( p->rc==SQLITE_NOTFOUND ){ p->rc = SQLITE_ERROR; p->zErrmsg = sqlite3_mprintf("ota vfs not found"); } } } } /* ** This routine is a copy of the sqlite3FileSuffix3() routine from the core. ** It is a no-op unless SQLITE_ENABLE_8_3_NAMES is defined. |
︙ | ︙ | |||
1851 1852 1853 1854 1855 1856 1857 | "(%d, %lld) ", OTA_STATE_STAGE, p->eStage, OTA_STATE_TBL, p->objiter.zTbl, OTA_STATE_IDX, p->objiter.zIdx, OTA_STATE_ROW, p->nStep, OTA_STATE_PROGRESS, p->nProgress, OTA_STATE_CKPT, | | | 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 | "(%d, %lld) ", OTA_STATE_STAGE, p->eStage, OTA_STATE_TBL, p->objiter.zTbl, OTA_STATE_IDX, p->objiter.zIdx, OTA_STATE_ROW, p->nStep, OTA_STATE_PROGRESS, p->nProgress, OTA_STATE_CKPT, OTA_STATE_COOKIE, (sqlite3_int64)p->pTargetFd->iCookie ) ); assert( pInsert==0 || rc==SQLITE_OK ); if( rc==SQLITE_OK ){ if( p->pCkpt ){ unsigned char *pCkptState = 0; int nCkptState = 0; |
︙ | ︙ | |||
1898 1899 1900 1901 1902 1903 1904 | ** ** If an error occurs, leave an error code and message in the ota handle ** and return NULL. */ static OtaState *otaLoadState(sqlite3ota *p){ const char *zSelect = "SELECT k, v FROM ota.ota_state"; OtaState *pRet = 0; | | < | 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 | ** ** If an error occurs, leave an error code and message in the ota handle ** and return NULL. */ static OtaState *otaLoadState(sqlite3ota *p){ const char *zSelect = "SELECT k, v FROM ota.ota_state"; OtaState *pRet = 0; sqlite3_stmt *pStmt = 0; int rc; int rc2; assert( p->rc==SQLITE_OK ); pRet = (OtaState*)sqlite3_malloc(sizeof(OtaState)); if( pRet==0 ){ rc = SQLITE_NOMEM; }else{ memset(pRet, 0, sizeof(OtaState)); rc = prepareAndCollectError(p->db, &pStmt, &p->zErrmsg, zSelect); } while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ switch( sqlite3_column_int(pStmt, 0) ){ case OTA_STATE_STAGE: pRet->eStage = sqlite3_column_int(pStmt, 1); if( pRet->eStage!=OTA_STAGE_OAL && pRet->eStage!=OTA_STAGE_CKPT ){ p->rc = SQLITE_CORRUPT; } break; case OTA_STATE_TBL: |
︙ | ︙ | |||
1952 1953 1954 1955 1956 1957 1958 | case OTA_STATE_COOKIE: /* At this point (p->iCookie) contains the value of the change-counter ** cookie (the thing that gets incremented when a transaction is ** committed in rollback mode) currently stored on page 1 of the ** database file. */ if( pRet->eStage==OTA_STAGE_OAL | | | 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 | case OTA_STATE_COOKIE: /* At this point (p->iCookie) contains the value of the change-counter ** cookie (the thing that gets incremented when a transaction is ** committed in rollback mode) currently stored on page 1 of the ** database file. */ if( pRet->eStage==OTA_STAGE_OAL && p->pTargetFd->iCookie!=(unsigned int)sqlite3_column_int64(pStmt, 1) ){ rc = SQLITE_BUSY; p->zErrmsg = sqlite3_mprintf("database modified during ota update"); } break; default: |
︙ | ︙ | |||
2253 2254 2255 2256 2257 2258 2259 | sqlite3_file *pFile, void *zBuf, int iAmt, sqlite_int64 iOfst ){ ota_file *p = (ota_file*)pFile; int rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); | | < < | | < < | | 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 | sqlite3_file *pFile, void *zBuf, int iAmt, sqlite_int64 iOfst ){ ota_file *p = (ota_file*)pFile; int rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){ p->iCookie = otaGetU32((unsigned char*)&zBuf[24]); } return rc; } /* ** Write data to an otaVfs-file. */ static int otaVfsWrite( sqlite3_file *pFile, const void *zBuf, int iAmt, sqlite_int64 iOfst ){ ota_file *p = (ota_file*)pFile; int rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst); if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){ p->iCookie = otaGetU32((unsigned char*)&zBuf[24]); } return rc; } /* ** Truncate an otaVfs-file. */ |
︙ | ︙ | |||
2400 2401 2402 2403 2404 2405 2406 | ** Shared-memory methods are all pass-thrus. */ static int otaVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ ota_file *p = (ota_file*)pFile; int rc = SQLITE_OK; #ifdef SQLITE_AMALGAMATION | | | | 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 | ** Shared-memory methods are all pass-thrus. */ static int otaVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ ota_file *p = (ota_file*)pFile; int rc = SQLITE_OK; #ifdef SQLITE_AMALGAMATION assert( WAL_CKPT_LOCK==1 ); #endif if( p->pOta && p->pOta->eStage==OTA_STAGE_OAL ){ /* Magic number 1 is the WAL_CKPT_LOCK lock. Preventing SQLite from ** taking this lock also prevents any checkpoints from occurring. ** todo: really, it's not clear why this might occur, as ** wal_autocheckpoint ought to be turned off. */ if( ofst==1 && n==1 ) rc = SQLITE_BUSY; }else{ assert( p->nShm==0 ); rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags); |
︙ | ︙ | |||
2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 | } if( rc==SQLITE_OK && p->apShm[iRegion]==0 ){ char *pNew = (char*)sqlite3_malloc(szRegion); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ p->apShm[iRegion] = pNew; } } if( rc==SQLITE_OK ){ *pp = p->apShm[iRegion]; }else{ | > | 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 | } if( rc==SQLITE_OK && p->apShm[iRegion]==0 ){ char *pNew = (char*)sqlite3_malloc(szRegion); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ memset(pNew, 0, szRegion); p->apShm[iRegion] = pNew; } } if( rc==SQLITE_OK ){ *pp = p->apShm[iRegion]; }else{ |
︙ | ︙ | |||
2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 | ota_file *pFd = (ota_file *)pFile; int rc = SQLITE_OK; const char *zOpen = zName; memset(pFd, 0, sizeof(ota_file)); pFd->pReal = (sqlite3_file*)&pFd[1]; pFd->pOtaVfs = pOtaVfs; if( zName ){ if( flags & SQLITE_OPEN_MAIN_DB ){ /* A main database has just been opened. The following block sets ** (pFd->zWal) to point to a buffer owned by SQLite that contains ** the name of the *-wal file this db connection will use. SQLite ** happens to pass a pointer to this buffer when using xAccess() ** or xOpen() to operate on the *-wal file. */ | > | 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 | ota_file *pFd = (ota_file *)pFile; int rc = SQLITE_OK; const char *zOpen = zName; memset(pFd, 0, sizeof(ota_file)); pFd->pReal = (sqlite3_file*)&pFd[1]; pFd->pOtaVfs = pOtaVfs; pFd->openFlags = flags; if( zName ){ if( flags & SQLITE_OPEN_MAIN_DB ){ /* A main database has just been opened. The following block sets ** (pFd->zWal) to point to a buffer owned by SQLite that contains ** the name of the *-wal file this db connection will use. SQLite ** happens to pass a pointer to this buffer when using xAccess() ** or xOpen() to operate on the *-wal file. */ |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
215 216 217 218 219 220 221 222 223 224 225 226 227 228 | SRC += \ $(TOP)/ext/rtree/sqlite3rtree.h \ $(TOP)/ext/rtree/rtree.h \ $(TOP)/ext/rtree/rtree.c SRC += \ $(TOP)/ext/userauth/userauth.c \ $(TOP)/ext/userauth/sqlite3userauth.h # Generated source code files # SRC += \ keywordhash.h \ opcodes.c \ opcodes.h \ | > > > | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | SRC += \ $(TOP)/ext/rtree/sqlite3rtree.h \ $(TOP)/ext/rtree/rtree.h \ $(TOP)/ext/rtree/rtree.c SRC += \ $(TOP)/ext/userauth/userauth.c \ $(TOP)/ext/userauth/sqlite3userauth.h SRC += \ $(TOP)/ext/ota/sqlite3ota.c \ $(TOP)/ext/ota/sqlite3ota.h # Generated source code files # SRC += \ keywordhash.h \ opcodes.c \ opcodes.h \ |
︙ | ︙ |
Changes to tool/mksqlite3c.tcl.
︙ | ︙ | |||
108 109 110 111 112 113 114 115 | os_win.h os.h pager.h parse.h pcache.h pragma.h rtree.h sqlite3ext.h | > | | 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | os_win.h os.h pager.h parse.h pcache.h pragma.h rtree.h sqlite3.h sqlite3ext.h sqlite3ota.h sqliteicu.h sqliteInt.h sqliteLimit.h vdbe.h vdbeInt.h wal.h whereInt.h |
︙ | ︙ | |||
330 331 332 333 334 335 336 337 338 339 340 341 | fts3_snippet.c fts3_unicode.c fts3_unicode2.c rtree.c icu.c fts3_icu.c } { copy_file tsrc/$file } close $out | > | 331 332 333 334 335 336 337 338 339 340 341 342 343 | fts3_snippet.c fts3_unicode.c fts3_unicode2.c rtree.c icu.c fts3_icu.c sqlite3ota.c } { copy_file tsrc/$file } close $out |