Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add an API to query an ota handle for the total number of key/value operations performed so far. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | ota-update |
Files: | files | file ages | folders |
SHA1: |
e3943fa7bbbfc5e16f73a494d8fa54d1 |
User & Date: | dan 2014-09-18 14:48:38.579 |
Context
2014-09-18
| ||
15:22 | Add new file ext/ota/README.txt, containing notes regarding the implementation of the ota extension. (check-in: 3c6e1cbb4b user: dan tags: ota-update) | |
14:48 | Add an API to query an ota handle for the total number of key/value operations performed so far. (check-in: e3943fa7bb user: dan tags: ota-update) | |
11:31 | Merge latest trunk changes with this branch. (check-in: 67ea2979d5 user: dan tags: ota-update) | |
Changes
Changes to ext/ota/ota.c.
︙ | ︙ | |||
51 52 53 54 55 56 57 58 59 60 61 62 63 64 | int i; const char *zTarget; /* Target database to apply OTA to */ const char *zOta; /* Database containing OTA */ char *zErrmsg; /* Error message, if any */ sqlite3ota *pOta; /* OTA handle */ int nStep = 0; /* Maximum number of step() calls */ int rc; /* Process command line arguments. Following this block local variables ** zTarget, zOta and nStep are all set. */ if( argc==5 ){ int nArg1 = strlen(argv[1]); if( nArg1>5 || nArg1<2 || memcmp("-step", argv[1], nArg1) ) usage(argv[0]); nStep = atoi(argv[2]); | > | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | int i; const char *zTarget; /* Target database to apply OTA to */ const char *zOta; /* Database containing OTA */ char *zErrmsg; /* Error message, if any */ sqlite3ota *pOta; /* OTA handle */ int nStep = 0; /* Maximum number of step() calls */ int rc; sqlite3_int64 nProgress = 0; /* Process command line arguments. Following this block local variables ** zTarget, zOta and nStep are all set. */ if( argc==5 ){ int nArg1 = strlen(argv[1]); if( nArg1>5 || nArg1<2 || memcmp("-step", argv[1], nArg1) ) usage(argv[0]); nStep = atoi(argv[2]); |
︙ | ︙ | |||
72 73 74 75 76 77 78 79 80 81 82 83 | /* Open an OTA handle. If nStep is less than or equal to zero, call ** sqlite3ota_step() until either the OTA has been completely applied ** or an error occurs. Or, if nStep is greater than zero, call ** sqlite3ota_step() a maximum of nStep times. */ pOta = sqlite3ota_open(zTarget, zOta); for(i=0; (nStep<=0 || i<nStep) && sqlite3ota_step(pOta)==SQLITE_OK; i++); rc = sqlite3ota_close(pOta, &zErrmsg); /* Let the user know what happened. */ switch( rc ){ case SQLITE_OK: | > | > > > | > > > | 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 | /* Open an OTA handle. If nStep is less than or equal to zero, call ** sqlite3ota_step() until either the OTA has been completely applied ** or an error occurs. Or, if nStep is greater than zero, call ** sqlite3ota_step() a maximum of nStep times. */ pOta = sqlite3ota_open(zTarget, zOta); for(i=0; (nStep<=0 || i<nStep) && sqlite3ota_step(pOta)==SQLITE_OK; i++); nProgress = sqlite3ota_progress(pOta); rc = sqlite3ota_close(pOta, &zErrmsg); /* Let the user know what happened. */ switch( rc ){ case SQLITE_OK: fprintf(stdout, "SQLITE_OK: ota update incomplete (%lld operations so far)\n", nProgress ); break; case SQLITE_DONE: fprintf(stdout, "SQLITE_DONE: ota update completed (%lld operations)\n", nProgress ); break; default: fprintf(stderr, "error=%d: %s\n", rc, zErrmsg); break; } sqlite3_free(zErrmsg); return (rc==SQLITE_OK || rc==SQLITE_DONE) ? 0 : 1; } |
Changes to ext/ota/sqlite3ota.c.
︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 | /* ** A structure to store values read from the ota_state table in memory. */ struct OtaState { char *zTbl; char *zIdx; int nRow; }; /* ** An iterator of this type is used to iterate through all objects in ** the target database that require updating. For each such table, the ** iterator visits, in order: ** | > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | /* ** A structure to store values read from the ota_state table in memory. */ struct OtaState { char *zTbl; char *zIdx; int nRow; sqlite3_int64 nProgress; }; /* ** An iterator of this type is used to iterate through all objects in ** the target database that require updating. For each such table, the ** iterator visits, in order: ** |
︙ | ︙ | |||
89 90 91 92 93 94 95 96 97 98 99 100 101 102 | */ struct sqlite3ota { sqlite3 *db; /* "main" -> target db, "ota" -> ota db */ char *zTarget; /* Path to target db */ int rc; /* Value returned by last ota_step() call */ char *zErrmsg; /* Error message if rc!=SQLITE_OK */ int nStep; /* Rows processed for current object */ OtaObjIter objiter; }; /* ** Prepare the SQL statement in buffer zSql against database handle db. ** If successful, set *ppStmt to point to the new statement and return ** SQLITE_OK. | > | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | */ struct sqlite3ota { sqlite3 *db; /* "main" -> target db, "ota" -> ota db */ char *zTarget; /* Path to target db */ int rc; /* Value returned by last ota_step() call */ char *zErrmsg; /* Error message if rc!=SQLITE_OK */ int nStep; /* Rows processed for current object */ int nProgress; /* Rows processed for all objects */ OtaObjIter objiter; }; /* ** Prepare the SQL statement in buffer zSql against database handle db. ** If successful, set *ppStmt to point to the new statement and return ** SQLITE_OK. |
︙ | ︙ | |||
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 | otaObjIterPrepareAll(p, pIter, 0); /* Advance to the next row to process. */ if( p->rc==SQLITE_OK ){ int rc = sqlite3_step(pIter->pSelect); if( rc==SQLITE_ROW ){ p->nStep++; return otaStep(p); } p->rc = sqlite3_reset(pIter->pSelect); p->nStep = 0; } } otaObjIterNext(p, pIter); } if( p->rc==SQLITE_OK && pIter->zTbl==0 ){ p->rc = SQLITE_DONE; } } return p->rc; } static void otaSaveTransactionState(sqlite3ota *p){ otaMPrintfExec(p, "INSERT OR REPLACE INTO ota.ota_state(rowid, tbl, idx, row, progress)" | > | | | 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 | otaObjIterPrepareAll(p, pIter, 0); /* Advance to the next row to process. */ if( p->rc==SQLITE_OK ){ int rc = sqlite3_step(pIter->pSelect); if( rc==SQLITE_ROW ){ p->nStep++; p->nProgress++; return otaStep(p); } p->rc = sqlite3_reset(pIter->pSelect); p->nStep = 0; } } otaObjIterNext(p, pIter); } if( p->rc==SQLITE_OK && pIter->zTbl==0 ){ p->rc = SQLITE_DONE; } } return p->rc; } static void otaSaveTransactionState(sqlite3ota *p){ otaMPrintfExec(p, "INSERT OR REPLACE INTO ota.ota_state(rowid, tbl, idx, row, progress)" "VALUES(1, %Q, %Q, %d, %lld)", p->objiter.zTbl, p->objiter.zIdx, p->nStep, p->nProgress ); } /* ** Allocate an OtaState object and load the contents of the ota_state ** table into it. Return a pointer to the new object. It is the ** responsibility of the caller to eventually free the object using |
︙ | ︙ | |||
938 939 940 941 942 943 944 945 946 947 948 949 950 951 | if( zIdx ){ pRet->zIdx = &pRet->zTbl[nTbl]; memcpy(pRet->zIdx, zIdx, nIdx); }else{ pRet->zIdx = 0; } pRet->nRow = sqlite3_column_int(pStmt, 2); } }else{ pRet = (OtaState*)sqlite3_malloc(sizeof(OtaState)); if( pRet ){ memset(pRet, 0, sizeof(*pRet)); } } | > | 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 | if( zIdx ){ pRet->zIdx = &pRet->zTbl[nTbl]; memcpy(pRet->zIdx, zIdx, nIdx); }else{ pRet->zIdx = 0; } pRet->nRow = sqlite3_column_int(pStmt, 2); pRet->nProgress = sqlite3_column_int64(pStmt, 3); } }else{ pRet = (OtaState*)sqlite3_malloc(sizeof(OtaState)); if( pRet ){ memset(pRet, 0, sizeof(*pRet)); } } |
︙ | ︙ | |||
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 | /* Point the object iterator at the first object */ if( p->rc==SQLITE_OK ){ p->rc = otaObjIterFirst(p, &p->objiter); } if( p->rc==SQLITE_OK ){ otaLoadTransactionState(p, pState); } sqlite3_free(pState); } return p; | > | 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 | /* Point the object iterator at the first object */ if( p->rc==SQLITE_OK ){ p->rc = otaObjIterFirst(p, &p->objiter); } if( p->rc==SQLITE_OK ){ p->nProgress = pState->nProgress; otaLoadTransactionState(p, pState); } sqlite3_free(pState); } return p; |
︙ | ︙ | |||
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 | sqlite3_free(p); }else{ rc = SQLITE_NOMEM; *pzErrmsg = 0; } return rc; } /**************************************************************************/ #ifdef SQLITE_TEST #include <tcl.h> | > > > > > > > > > | 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 | sqlite3_free(p); }else{ rc = SQLITE_NOMEM; *pzErrmsg = 0; } return rc; } /* ** Return the total number of key-value operations (inserts, deletes or ** updates) that have been performed on the target database since the ** current OTA update was started. */ sqlite3_int64 sqlite3ota_progress(sqlite3ota *pOta){ return pOta->nProgress; } /**************************************************************************/ #ifdef SQLITE_TEST #include <tcl.h> |
︙ | ︙ |
Changes to ext/ota/sqlite3ota.h.
︙ | ︙ | |||
211 212 213 214 215 216 217 218 219 | ** ** Otherwise, if no error occurs, this function returns SQLITE_OK if the ** update has been partially applied, or SQLITE_DONE if it has been ** completely applied. */ int sqlite3ota_close(sqlite3ota *pOta, char **pzErrmsg); #endif /* _SQLITE3OTA_H */ | > > > > > > > | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | ** ** Otherwise, if no error occurs, this function returns SQLITE_OK if the ** update has been partially applied, or SQLITE_DONE if it has been ** completely applied. */ int sqlite3ota_close(sqlite3ota *pOta, char **pzErrmsg); /* ** Return the total number of key-value operations (inserts, deletes or ** updates) that have been performed on the target database since the ** current OTA update was started. */ sqlite3_int64 sqlite3ota_progress(sqlite3ota *pOta); #endif /* _SQLITE3OTA_H */ |