Fossil SCM
Improvements to clone performance. Skip cross-linking during the clone the automatically rebuild after the clone. Fixes to rebuild to make sure all artifacts are crosslinked.
Commit
791a513c289ded077964c0c1332e089a0e65587d
Parent
243e02bfbdf5629…
2 files changed
+28
-30
+27
-4
M
src/db.c
+28
-30
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -50,10 +50,11 @@ | ||
| 50 | 50 | ** structure. |
| 51 | 51 | */ |
| 52 | 52 | struct Stmt { |
| 53 | 53 | Blob sql; /* The SQL for this statement */ |
| 54 | 54 | sqlite3_stmt *pStmt; /* The results of sqlite3_prepare() */ |
| 55 | + Stmt *pNext, *pPrev; /* List of all unfinalized statements */ | |
| 55 | 56 | }; |
| 56 | 57 | #endif /* INTERFACE */ |
| 57 | 58 | |
| 58 | 59 | /* |
| 59 | 60 | ** Call this routine when a database error occurs. |
| @@ -82,10 +83,11 @@ | ||
| 82 | 83 | static int nCommitHook = 0; /* Number of commit hooks */ |
| 83 | 84 | static struct sCommitHook { |
| 84 | 85 | int (*xHook)(void); /* Functions to call at db_end_transaction() */ |
| 85 | 86 | int sequence; /* Call functions in sequence order */ |
| 86 | 87 | } aHook[5]; |
| 88 | +static Stmt *pAllStmt = 0; /* List of all unfinalized statements */ | |
| 87 | 89 | |
| 88 | 90 | /* |
| 89 | 91 | ** This routine is called by the SQLite commit-hook mechanism |
| 90 | 92 | ** just prior to each omit. All this routine does is verify |
| 91 | 93 | ** that nBegin really is zero. That insures that transactions |
| @@ -163,36 +165,25 @@ | ||
| 163 | 165 | aHook[nCommitHook].sequence = sequence; |
| 164 | 166 | aHook[nCommitHook].xHook = x; |
| 165 | 167 | nCommitHook++; |
| 166 | 168 | } |
| 167 | 169 | |
| 168 | -/* | |
| 169 | -** Prepare or reprepare the sqlite3 statement from the raw SQL text. | |
| 170 | -*/ | |
| 171 | -static void reprepare(Stmt *pStmt){ | |
| 172 | - sqlite3_stmt *pNew; | |
| 173 | - if( sqlite3_prepare(g.db, blob_buffer(&pStmt->sql), -1, &pNew, 0)!=0 ){ | |
| 174 | - db_err("%s\n%s", blob_str(&pStmt->sql), sqlite3_errmsg(g.db)); | |
| 175 | - } | |
| 176 | - if( pStmt->pStmt ){ | |
| 177 | - sqlite3_transfer_bindings(pStmt->pStmt, pNew); | |
| 178 | - sqlite3_finalize(pStmt->pStmt); | |
| 179 | - } | |
| 180 | - pStmt->pStmt = pNew; | |
| 181 | -} | |
| 182 | - | |
| 183 | 170 | /* |
| 184 | 171 | ** Prepare a Stmt. Assume that the Stmt is previously uninitialized. |
| 185 | 172 | ** If the input string contains multiple SQL statements, only the first |
| 186 | 173 | ** one is processed. All statements beyond the first are silently ignored. |
| 187 | 174 | */ |
| 188 | 175 | int db_vprepare(Stmt *pStmt, const char *zFormat, va_list ap){ |
| 176 | + char *zSql; | |
| 189 | 177 | blob_zero(&pStmt->sql); |
| 190 | 178 | blob_vappendf(&pStmt->sql, zFormat, ap); |
| 191 | 179 | va_end(ap); |
| 192 | - pStmt->pStmt = 0; | |
| 193 | - reprepare(pStmt); | |
| 180 | + zSql = blob_str(&pStmt->sql); | |
| 181 | + if( sqlite3_prepare_v2(g.db, zSql, -1, &pStmt->pStmt, 0)!=0 ){ | |
| 182 | + db_err("%s\n%s", zSql, sqlite3_errmsg(g.db)); | |
| 183 | + } | |
| 184 | + pStmt->pNext = pStmt->pPrev = 0; | |
| 194 | 185 | return 0; |
| 195 | 186 | } |
| 196 | 187 | int db_prepare(Stmt *pStmt, const char *zFormat, ...){ |
| 197 | 188 | int rc; |
| 198 | 189 | va_list ap; |
| @@ -205,10 +196,14 @@ | ||
| 205 | 196 | int rc = SQLITE_OK; |
| 206 | 197 | if( blob_size(&pStmt->sql)==0 ){ |
| 207 | 198 | va_list ap; |
| 208 | 199 | va_start(ap, zFormat); |
| 209 | 200 | rc = db_vprepare(pStmt, zFormat, ap); |
| 201 | + pStmt->pNext = pAllStmt; | |
| 202 | + pStmt->pPrev = 0; | |
| 203 | + if( pAllStmt ) pAllStmt->pPrev = pStmt; | |
| 204 | + pAllStmt = pStmt; | |
| 210 | 205 | va_end(ap); |
| 211 | 206 | } |
| 212 | 207 | return rc; |
| 213 | 208 | } |
| 214 | 209 | |
| @@ -258,23 +253,12 @@ | ||
| 258 | 253 | /* |
| 259 | 254 | ** Step the SQL statement. Return either SQLITE_ROW or an error code |
| 260 | 255 | ** or SQLITE_OK if the statement finishes successfully. |
| 261 | 256 | */ |
| 262 | 257 | int db_step(Stmt *pStmt){ |
| 263 | - int rc = SQLITE_OK; | |
| 264 | - int limit = 3; | |
| 265 | - while( limit-- ){ | |
| 266 | - rc = sqlite3_step(pStmt->pStmt); | |
| 267 | - if( rc==SQLITE_ERROR ){ | |
| 268 | - rc = sqlite3_reset(pStmt->pStmt); | |
| 269 | - } | |
| 270 | - if( rc==SQLITE_SCHEMA ){ | |
| 271 | - reprepare(pStmt); | |
| 272 | - }else{ | |
| 273 | - break; | |
| 274 | - } | |
| 275 | - } | |
| 258 | + int rc; | |
| 259 | + rc = sqlite3_step(pStmt->pStmt); | |
| 276 | 260 | return rc; |
| 277 | 261 | } |
| 278 | 262 | |
| 279 | 263 | /* |
| 280 | 264 | ** Reset or finalize a statement. |
| @@ -287,10 +271,21 @@ | ||
| 287 | 271 | int db_finalize(Stmt *pStmt){ |
| 288 | 272 | int rc; |
| 289 | 273 | blob_reset(&pStmt->sql); |
| 290 | 274 | rc = sqlite3_finalize(pStmt->pStmt); |
| 291 | 275 | db_check_result(rc); |
| 276 | + pStmt->pStmt = 0; | |
| 277 | + if( pStmt->pNext ){ | |
| 278 | + pStmt->pNext->pPrev = pStmt->pPrev; | |
| 279 | + } | |
| 280 | + if( pStmt->pPrev ){ | |
| 281 | + pStmt->pPrev->pNext = pStmt->pNext; | |
| 282 | + }else if( pAllStmt==pStmt ){ | |
| 283 | + pAllStmt = pStmt->pNext; | |
| 284 | + } | |
| 285 | + pStmt->pNext = 0; | |
| 286 | + pStmt->pPrev = 0; | |
| 292 | 287 | return rc; |
| 293 | 288 | } |
| 294 | 289 | |
| 295 | 290 | /* |
| 296 | 291 | ** Return the rowid of the most recent insert |
| @@ -714,10 +709,13 @@ | ||
| 714 | 709 | /* |
| 715 | 710 | ** Close the database connection. |
| 716 | 711 | */ |
| 717 | 712 | void db_close(void){ |
| 718 | 713 | if( g.db==0 ) return; |
| 714 | + while( pAllStmt ){ | |
| 715 | + db_finalize(pAllStmt); | |
| 716 | + } | |
| 719 | 717 | g.repositoryOpen = 0; |
| 720 | 718 | g.localOpen = 0; |
| 721 | 719 | g.configOpen = 0; |
| 722 | 720 | sqlite3_close(g.db); |
| 723 | 721 | g.db = 0; |
| 724 | 722 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -50,10 +50,11 @@ | |
| 50 | ** structure. |
| 51 | */ |
| 52 | struct Stmt { |
| 53 | Blob sql; /* The SQL for this statement */ |
| 54 | sqlite3_stmt *pStmt; /* The results of sqlite3_prepare() */ |
| 55 | }; |
| 56 | #endif /* INTERFACE */ |
| 57 | |
| 58 | /* |
| 59 | ** Call this routine when a database error occurs. |
| @@ -82,10 +83,11 @@ | |
| 82 | static int nCommitHook = 0; /* Number of commit hooks */ |
| 83 | static struct sCommitHook { |
| 84 | int (*xHook)(void); /* Functions to call at db_end_transaction() */ |
| 85 | int sequence; /* Call functions in sequence order */ |
| 86 | } aHook[5]; |
| 87 | |
| 88 | /* |
| 89 | ** This routine is called by the SQLite commit-hook mechanism |
| 90 | ** just prior to each omit. All this routine does is verify |
| 91 | ** that nBegin really is zero. That insures that transactions |
| @@ -163,36 +165,25 @@ | |
| 163 | aHook[nCommitHook].sequence = sequence; |
| 164 | aHook[nCommitHook].xHook = x; |
| 165 | nCommitHook++; |
| 166 | } |
| 167 | |
| 168 | /* |
| 169 | ** Prepare or reprepare the sqlite3 statement from the raw SQL text. |
| 170 | */ |
| 171 | static void reprepare(Stmt *pStmt){ |
| 172 | sqlite3_stmt *pNew; |
| 173 | if( sqlite3_prepare(g.db, blob_buffer(&pStmt->sql), -1, &pNew, 0)!=0 ){ |
| 174 | db_err("%s\n%s", blob_str(&pStmt->sql), sqlite3_errmsg(g.db)); |
| 175 | } |
| 176 | if( pStmt->pStmt ){ |
| 177 | sqlite3_transfer_bindings(pStmt->pStmt, pNew); |
| 178 | sqlite3_finalize(pStmt->pStmt); |
| 179 | } |
| 180 | pStmt->pStmt = pNew; |
| 181 | } |
| 182 | |
| 183 | /* |
| 184 | ** Prepare a Stmt. Assume that the Stmt is previously uninitialized. |
| 185 | ** If the input string contains multiple SQL statements, only the first |
| 186 | ** one is processed. All statements beyond the first are silently ignored. |
| 187 | */ |
| 188 | int db_vprepare(Stmt *pStmt, const char *zFormat, va_list ap){ |
| 189 | blob_zero(&pStmt->sql); |
| 190 | blob_vappendf(&pStmt->sql, zFormat, ap); |
| 191 | va_end(ap); |
| 192 | pStmt->pStmt = 0; |
| 193 | reprepare(pStmt); |
| 194 | return 0; |
| 195 | } |
| 196 | int db_prepare(Stmt *pStmt, const char *zFormat, ...){ |
| 197 | int rc; |
| 198 | va_list ap; |
| @@ -205,10 +196,14 @@ | |
| 205 | int rc = SQLITE_OK; |
| 206 | if( blob_size(&pStmt->sql)==0 ){ |
| 207 | va_list ap; |
| 208 | va_start(ap, zFormat); |
| 209 | rc = db_vprepare(pStmt, zFormat, ap); |
| 210 | va_end(ap); |
| 211 | } |
| 212 | return rc; |
| 213 | } |
| 214 | |
| @@ -258,23 +253,12 @@ | |
| 258 | /* |
| 259 | ** Step the SQL statement. Return either SQLITE_ROW or an error code |
| 260 | ** or SQLITE_OK if the statement finishes successfully. |
| 261 | */ |
| 262 | int db_step(Stmt *pStmt){ |
| 263 | int rc = SQLITE_OK; |
| 264 | int limit = 3; |
| 265 | while( limit-- ){ |
| 266 | rc = sqlite3_step(pStmt->pStmt); |
| 267 | if( rc==SQLITE_ERROR ){ |
| 268 | rc = sqlite3_reset(pStmt->pStmt); |
| 269 | } |
| 270 | if( rc==SQLITE_SCHEMA ){ |
| 271 | reprepare(pStmt); |
| 272 | }else{ |
| 273 | break; |
| 274 | } |
| 275 | } |
| 276 | return rc; |
| 277 | } |
| 278 | |
| 279 | /* |
| 280 | ** Reset or finalize a statement. |
| @@ -287,10 +271,21 @@ | |
| 287 | int db_finalize(Stmt *pStmt){ |
| 288 | int rc; |
| 289 | blob_reset(&pStmt->sql); |
| 290 | rc = sqlite3_finalize(pStmt->pStmt); |
| 291 | db_check_result(rc); |
| 292 | return rc; |
| 293 | } |
| 294 | |
| 295 | /* |
| 296 | ** Return the rowid of the most recent insert |
| @@ -714,10 +709,13 @@ | |
| 714 | /* |
| 715 | ** Close the database connection. |
| 716 | */ |
| 717 | void db_close(void){ |
| 718 | if( g.db==0 ) return; |
| 719 | g.repositoryOpen = 0; |
| 720 | g.localOpen = 0; |
| 721 | g.configOpen = 0; |
| 722 | sqlite3_close(g.db); |
| 723 | g.db = 0; |
| 724 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -50,10 +50,11 @@ | |
| 50 | ** structure. |
| 51 | */ |
| 52 | struct Stmt { |
| 53 | Blob sql; /* The SQL for this statement */ |
| 54 | sqlite3_stmt *pStmt; /* The results of sqlite3_prepare() */ |
| 55 | Stmt *pNext, *pPrev; /* List of all unfinalized statements */ |
| 56 | }; |
| 57 | #endif /* INTERFACE */ |
| 58 | |
| 59 | /* |
| 60 | ** Call this routine when a database error occurs. |
| @@ -82,10 +83,11 @@ | |
| 83 | static int nCommitHook = 0; /* Number of commit hooks */ |
| 84 | static struct sCommitHook { |
| 85 | int (*xHook)(void); /* Functions to call at db_end_transaction() */ |
| 86 | int sequence; /* Call functions in sequence order */ |
| 87 | } aHook[5]; |
| 88 | static Stmt *pAllStmt = 0; /* List of all unfinalized statements */ |
| 89 | |
| 90 | /* |
| 91 | ** This routine is called by the SQLite commit-hook mechanism |
| 92 | ** just prior to each omit. All this routine does is verify |
| 93 | ** that nBegin really is zero. That insures that transactions |
| @@ -163,36 +165,25 @@ | |
| 165 | aHook[nCommitHook].sequence = sequence; |
| 166 | aHook[nCommitHook].xHook = x; |
| 167 | nCommitHook++; |
| 168 | } |
| 169 | |
| 170 | /* |
| 171 | ** Prepare a Stmt. Assume that the Stmt is previously uninitialized. |
| 172 | ** If the input string contains multiple SQL statements, only the first |
| 173 | ** one is processed. All statements beyond the first are silently ignored. |
| 174 | */ |
| 175 | int db_vprepare(Stmt *pStmt, const char *zFormat, va_list ap){ |
| 176 | char *zSql; |
| 177 | blob_zero(&pStmt->sql); |
| 178 | blob_vappendf(&pStmt->sql, zFormat, ap); |
| 179 | va_end(ap); |
| 180 | zSql = blob_str(&pStmt->sql); |
| 181 | if( sqlite3_prepare_v2(g.db, zSql, -1, &pStmt->pStmt, 0)!=0 ){ |
| 182 | db_err("%s\n%s", zSql, sqlite3_errmsg(g.db)); |
| 183 | } |
| 184 | pStmt->pNext = pStmt->pPrev = 0; |
| 185 | return 0; |
| 186 | } |
| 187 | int db_prepare(Stmt *pStmt, const char *zFormat, ...){ |
| 188 | int rc; |
| 189 | va_list ap; |
| @@ -205,10 +196,14 @@ | |
| 196 | int rc = SQLITE_OK; |
| 197 | if( blob_size(&pStmt->sql)==0 ){ |
| 198 | va_list ap; |
| 199 | va_start(ap, zFormat); |
| 200 | rc = db_vprepare(pStmt, zFormat, ap); |
| 201 | pStmt->pNext = pAllStmt; |
| 202 | pStmt->pPrev = 0; |
| 203 | if( pAllStmt ) pAllStmt->pPrev = pStmt; |
| 204 | pAllStmt = pStmt; |
| 205 | va_end(ap); |
| 206 | } |
| 207 | return rc; |
| 208 | } |
| 209 | |
| @@ -258,23 +253,12 @@ | |
| 253 | /* |
| 254 | ** Step the SQL statement. Return either SQLITE_ROW or an error code |
| 255 | ** or SQLITE_OK if the statement finishes successfully. |
| 256 | */ |
| 257 | int db_step(Stmt *pStmt){ |
| 258 | int rc; |
| 259 | rc = sqlite3_step(pStmt->pStmt); |
| 260 | return rc; |
| 261 | } |
| 262 | |
| 263 | /* |
| 264 | ** Reset or finalize a statement. |
| @@ -287,10 +271,21 @@ | |
| 271 | int db_finalize(Stmt *pStmt){ |
| 272 | int rc; |
| 273 | blob_reset(&pStmt->sql); |
| 274 | rc = sqlite3_finalize(pStmt->pStmt); |
| 275 | db_check_result(rc); |
| 276 | pStmt->pStmt = 0; |
| 277 | if( pStmt->pNext ){ |
| 278 | pStmt->pNext->pPrev = pStmt->pPrev; |
| 279 | } |
| 280 | if( pStmt->pPrev ){ |
| 281 | pStmt->pPrev->pNext = pStmt->pNext; |
| 282 | }else if( pAllStmt==pStmt ){ |
| 283 | pAllStmt = pStmt->pNext; |
| 284 | } |
| 285 | pStmt->pNext = 0; |
| 286 | pStmt->pPrev = 0; |
| 287 | return rc; |
| 288 | } |
| 289 | |
| 290 | /* |
| 291 | ** Return the rowid of the most recent insert |
| @@ -714,10 +709,13 @@ | |
| 709 | /* |
| 710 | ** Close the database connection. |
| 711 | */ |
| 712 | void db_close(void){ |
| 713 | if( g.db==0 ) return; |
| 714 | while( pAllStmt ){ |
| 715 | db_finalize(pAllStmt); |
| 716 | } |
| 717 | g.repositoryOpen = 0; |
| 718 | g.localOpen = 0; |
| 719 | g.configOpen = 0; |
| 720 | sqlite3_close(g.db); |
| 721 | g.db = 0; |
| 722 |
+27
-4
| --- src/rebuild.c | ||
| +++ src/rebuild.c | ||
| @@ -68,15 +68,18 @@ | ||
| 68 | 68 | ** Variables used for progress information |
| 69 | 69 | */ |
| 70 | 70 | static int totalSize; /* Total number of artifacts to process */ |
| 71 | 71 | static int processCnt; /* Number processed so far */ |
| 72 | 72 | static int ttyOutput; /* Do progress output */ |
| 73 | +static Bag bagDone; /* Bag of records rebuilt */ | |
| 73 | 74 | |
| 74 | 75 | /* |
| 75 | 76 | ** Called after each artifact is processed |
| 76 | 77 | */ |
| 77 | -static void rebuild_step_done(void){ | |
| 78 | +static void rebuild_step_done(rid){ | |
| 79 | + assert( bag_find(&bagDone, rid)==0 ); | |
| 80 | + bag_insert(&bagDone, rid); | |
| 78 | 81 | if( ttyOutput ){ |
| 79 | 82 | processCnt++; |
| 80 | 83 | printf("%d (%d%%)...\r", processCnt, (processCnt*100/totalSize)); |
| 81 | 84 | fflush(stdout); |
| 82 | 85 | } |
| @@ -103,11 +106,14 @@ | ||
| 103 | 106 | |
| 104 | 107 | /* Find all children of artifact rid */ |
| 105 | 108 | db_prepare(&q1, "SELECT rid FROM delta WHERE srcid=%d", rid); |
| 106 | 109 | bag_init(&children); |
| 107 | 110 | while( db_step(&q1)==SQLITE_ROW ){ |
| 108 | - bag_insert(&children, db_column_int(&q1, 0)); | |
| 111 | + int cid = db_column_int(&q1, 0); | |
| 112 | + if( !bag_find(&bagDone, cid) ){ | |
| 113 | + bag_insert(&children, cid); | |
| 114 | + } | |
| 109 | 115 | } |
| 110 | 116 | nChild = bag_count(&children); |
| 111 | 117 | db_finalize(&q1); |
| 112 | 118 | |
| 113 | 119 | /* Crosslink the artifact */ |
| @@ -143,11 +149,11 @@ | ||
| 143 | 149 | db_finalize(&q2); |
| 144 | 150 | blob_reset(pUse); |
| 145 | 151 | } |
| 146 | 152 | } |
| 147 | 153 | bag_clear(&children); |
| 148 | - rebuild_step_done(); | |
| 154 | + rebuild_step_done(rid); | |
| 149 | 155 | } |
| 150 | 156 | |
| 151 | 157 | /* |
| 152 | 158 | ** Core function to rebuild the infomration in the derived tables of a |
| 153 | 159 | ** fossil repository from the blobs. This function is shared between |
| @@ -163,10 +169,11 @@ | ||
| 163 | 169 | int rebuild_db(int randomize, int doOut){ |
| 164 | 170 | Stmt s; |
| 165 | 171 | int errCnt = 0; |
| 166 | 172 | char *zTable; |
| 167 | 173 | |
| 174 | + bag_init(&bagDone); | |
| 168 | 175 | ttyOutput = doOut; |
| 169 | 176 | processCnt = 0; |
| 170 | 177 | db_multi_exec(zSchemaUpdates); |
| 171 | 178 | for(;;){ |
| 172 | 179 | zTable = db_text(0, |
| @@ -204,13 +211,29 @@ | ||
| 204 | 211 | int size = db_column_int(&s, 1); |
| 205 | 212 | if( size>=0 ){ |
| 206 | 213 | Blob content; |
| 207 | 214 | content_get(rid, &content); |
| 208 | 215 | rebuild_step(rid, size, &content); |
| 216 | + } | |
| 217 | + } | |
| 218 | + db_finalize(&s); | |
| 219 | + db_prepare(&s, | |
| 220 | + "SELECT rid, size FROM blob" | |
| 221 | + " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)" | |
| 222 | + ); | |
| 223 | + while( db_step(&s)==SQLITE_ROW ){ | |
| 224 | + int rid = db_column_int(&s, 0); | |
| 225 | + int size = db_column_int(&s, 1); | |
| 226 | + if( size>=0 ){ | |
| 227 | + if( !bag_find(&bagDone, rid) ){ | |
| 228 | + Blob content; | |
| 229 | + content_get(rid, &content); | |
| 230 | + rebuild_step(rid, size, &content); | |
| 231 | + } | |
| 209 | 232 | }else{ |
| 210 | 233 | db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid); |
| 211 | - rebuild_step_done(); | |
| 234 | + rebuild_step_done(rid); | |
| 212 | 235 | } |
| 213 | 236 | } |
| 214 | 237 | db_finalize(&s); |
| 215 | 238 | if( ttyOutput ){ |
| 216 | 239 | printf("\n"); |
| 217 | 240 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -68,15 +68,18 @@ | |
| 68 | ** Variables used for progress information |
| 69 | */ |
| 70 | static int totalSize; /* Total number of artifacts to process */ |
| 71 | static int processCnt; /* Number processed so far */ |
| 72 | static int ttyOutput; /* Do progress output */ |
| 73 | |
| 74 | /* |
| 75 | ** Called after each artifact is processed |
| 76 | */ |
| 77 | static void rebuild_step_done(void){ |
| 78 | if( ttyOutput ){ |
| 79 | processCnt++; |
| 80 | printf("%d (%d%%)...\r", processCnt, (processCnt*100/totalSize)); |
| 81 | fflush(stdout); |
| 82 | } |
| @@ -103,11 +106,14 @@ | |
| 103 | |
| 104 | /* Find all children of artifact rid */ |
| 105 | db_prepare(&q1, "SELECT rid FROM delta WHERE srcid=%d", rid); |
| 106 | bag_init(&children); |
| 107 | while( db_step(&q1)==SQLITE_ROW ){ |
| 108 | bag_insert(&children, db_column_int(&q1, 0)); |
| 109 | } |
| 110 | nChild = bag_count(&children); |
| 111 | db_finalize(&q1); |
| 112 | |
| 113 | /* Crosslink the artifact */ |
| @@ -143,11 +149,11 @@ | |
| 143 | db_finalize(&q2); |
| 144 | blob_reset(pUse); |
| 145 | } |
| 146 | } |
| 147 | bag_clear(&children); |
| 148 | rebuild_step_done(); |
| 149 | } |
| 150 | |
| 151 | /* |
| 152 | ** Core function to rebuild the infomration in the derived tables of a |
| 153 | ** fossil repository from the blobs. This function is shared between |
| @@ -163,10 +169,11 @@ | |
| 163 | int rebuild_db(int randomize, int doOut){ |
| 164 | Stmt s; |
| 165 | int errCnt = 0; |
| 166 | char *zTable; |
| 167 | |
| 168 | ttyOutput = doOut; |
| 169 | processCnt = 0; |
| 170 | db_multi_exec(zSchemaUpdates); |
| 171 | for(;;){ |
| 172 | zTable = db_text(0, |
| @@ -204,13 +211,29 @@ | |
| 204 | int size = db_column_int(&s, 1); |
| 205 | if( size>=0 ){ |
| 206 | Blob content; |
| 207 | content_get(rid, &content); |
| 208 | rebuild_step(rid, size, &content); |
| 209 | }else{ |
| 210 | db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid); |
| 211 | rebuild_step_done(); |
| 212 | } |
| 213 | } |
| 214 | db_finalize(&s); |
| 215 | if( ttyOutput ){ |
| 216 | printf("\n"); |
| 217 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -68,15 +68,18 @@ | |
| 68 | ** Variables used for progress information |
| 69 | */ |
| 70 | static int totalSize; /* Total number of artifacts to process */ |
| 71 | static int processCnt; /* Number processed so far */ |
| 72 | static int ttyOutput; /* Do progress output */ |
| 73 | static Bag bagDone; /* Bag of records rebuilt */ |
| 74 | |
| 75 | /* |
| 76 | ** Called after each artifact is processed |
| 77 | */ |
| 78 | static void rebuild_step_done(rid){ |
| 79 | assert( bag_find(&bagDone, rid)==0 ); |
| 80 | bag_insert(&bagDone, rid); |
| 81 | if( ttyOutput ){ |
| 82 | processCnt++; |
| 83 | printf("%d (%d%%)...\r", processCnt, (processCnt*100/totalSize)); |
| 84 | fflush(stdout); |
| 85 | } |
| @@ -103,11 +106,14 @@ | |
| 106 | |
| 107 | /* Find all children of artifact rid */ |
| 108 | db_prepare(&q1, "SELECT rid FROM delta WHERE srcid=%d", rid); |
| 109 | bag_init(&children); |
| 110 | while( db_step(&q1)==SQLITE_ROW ){ |
| 111 | int cid = db_column_int(&q1, 0); |
| 112 | if( !bag_find(&bagDone, cid) ){ |
| 113 | bag_insert(&children, cid); |
| 114 | } |
| 115 | } |
| 116 | nChild = bag_count(&children); |
| 117 | db_finalize(&q1); |
| 118 | |
| 119 | /* Crosslink the artifact */ |
| @@ -143,11 +149,11 @@ | |
| 149 | db_finalize(&q2); |
| 150 | blob_reset(pUse); |
| 151 | } |
| 152 | } |
| 153 | bag_clear(&children); |
| 154 | rebuild_step_done(rid); |
| 155 | } |
| 156 | |
| 157 | /* |
| 158 | ** Core function to rebuild the infomration in the derived tables of a |
| 159 | ** fossil repository from the blobs. This function is shared between |
| @@ -163,10 +169,11 @@ | |
| 169 | int rebuild_db(int randomize, int doOut){ |
| 170 | Stmt s; |
| 171 | int errCnt = 0; |
| 172 | char *zTable; |
| 173 | |
| 174 | bag_init(&bagDone); |
| 175 | ttyOutput = doOut; |
| 176 | processCnt = 0; |
| 177 | db_multi_exec(zSchemaUpdates); |
| 178 | for(;;){ |
| 179 | zTable = db_text(0, |
| @@ -204,13 +211,29 @@ | |
| 211 | int size = db_column_int(&s, 1); |
| 212 | if( size>=0 ){ |
| 213 | Blob content; |
| 214 | content_get(rid, &content); |
| 215 | rebuild_step(rid, size, &content); |
| 216 | } |
| 217 | } |
| 218 | db_finalize(&s); |
| 219 | db_prepare(&s, |
| 220 | "SELECT rid, size FROM blob" |
| 221 | " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)" |
| 222 | ); |
| 223 | while( db_step(&s)==SQLITE_ROW ){ |
| 224 | int rid = db_column_int(&s, 0); |
| 225 | int size = db_column_int(&s, 1); |
| 226 | if( size>=0 ){ |
| 227 | if( !bag_find(&bagDone, rid) ){ |
| 228 | Blob content; |
| 229 | content_get(rid, &content); |
| 230 | rebuild_step(rid, size, &content); |
| 231 | } |
| 232 | }else{ |
| 233 | db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid); |
| 234 | rebuild_step_done(rid); |
| 235 | } |
| 236 | } |
| 237 | db_finalize(&s); |
| 238 | if( ttyOutput ){ |
| 239 | printf("\n"); |
| 240 |