Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/sqlite/src/src/backup.c |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /* | - | ||||||||||||||||||||||||
2 | ** 2009 January 28 | - | ||||||||||||||||||||||||
3 | ** | - | ||||||||||||||||||||||||
4 | ** The author disclaims copyright to this source code. In place of | - | ||||||||||||||||||||||||
5 | ** a legal notice, here is a blessing: | - | ||||||||||||||||||||||||
6 | ** | - | ||||||||||||||||||||||||
7 | ** May you do good and not evil. | - | ||||||||||||||||||||||||
8 | ** May you find forgiveness for yourself and forgive others. | - | ||||||||||||||||||||||||
9 | ** May you share freely, never taking more than you give. | - | ||||||||||||||||||||||||
10 | ** | - | ||||||||||||||||||||||||
11 | ************************************************************************* | - | ||||||||||||||||||||||||
12 | ** This file contains the implementation of the sqlite3_backup_XXX() | - | ||||||||||||||||||||||||
13 | ** API functions and the related features. | - | ||||||||||||||||||||||||
14 | */ | - | ||||||||||||||||||||||||
15 | #include "sqliteInt.h" | - | ||||||||||||||||||||||||
16 | #include "btreeInt.h" | - | ||||||||||||||||||||||||
17 | - | |||||||||||||||||||||||||
18 | /* | - | ||||||||||||||||||||||||
19 | ** Structure allocated for each backup operation. | - | ||||||||||||||||||||||||
20 | */ | - | ||||||||||||||||||||||||
21 | struct sqlite3_backup { | - | ||||||||||||||||||||||||
22 | sqlite3* pDestDb; /* Destination database handle */ | - | ||||||||||||||||||||||||
23 | Btree *pDest; /* Destination b-tree file */ | - | ||||||||||||||||||||||||
24 | u32 iDestSchema; /* Original schema cookie in destination */ | - | ||||||||||||||||||||||||
25 | int bDestLocked; /* True once a write-transaction is open on pDest */ | - | ||||||||||||||||||||||||
26 | - | |||||||||||||||||||||||||
27 | Pgno iNext; /* Page number of the next source page to copy */ | - | ||||||||||||||||||||||||
28 | sqlite3* pSrcDb; /* Source database handle */ | - | ||||||||||||||||||||||||
29 | Btree *pSrc; /* Source b-tree file */ | - | ||||||||||||||||||||||||
30 | - | |||||||||||||||||||||||||
31 | int rc; /* Backup process error code */ | - | ||||||||||||||||||||||||
32 | - | |||||||||||||||||||||||||
33 | /* These two variables are set by every call to backup_step(). They are | - | ||||||||||||||||||||||||
34 | ** read by calls to backup_remaining() and backup_pagecount(). | - | ||||||||||||||||||||||||
35 | */ | - | ||||||||||||||||||||||||
36 | Pgno nRemaining; /* Number of pages left to copy */ | - | ||||||||||||||||||||||||
37 | Pgno nPagecount; /* Total number of pages to copy */ | - | ||||||||||||||||||||||||
38 | - | |||||||||||||||||||||||||
39 | int isAttached; /* True once backup has been registered with pager */ | - | ||||||||||||||||||||||||
40 | sqlite3_backup *pNext; /* Next backup associated with source pager */ | - | ||||||||||||||||||||||||
41 | }; | - | ||||||||||||||||||||||||
42 | - | |||||||||||||||||||||||||
43 | /* | - | ||||||||||||||||||||||||
44 | ** THREAD SAFETY NOTES: | - | ||||||||||||||||||||||||
45 | ** | - | ||||||||||||||||||||||||
46 | ** Once it has been created using backup_init(), a single sqlite3_backup | - | ||||||||||||||||||||||||
47 | ** structure may be accessed via two groups of thread-safe entry points: | - | ||||||||||||||||||||||||
48 | ** | - | ||||||||||||||||||||||||
49 | ** * Via the sqlite3_backup_XXX() API function backup_step() and | - | ||||||||||||||||||||||||
50 | ** backup_finish(). Both these functions obtain the source database | - | ||||||||||||||||||||||||
51 | ** handle mutex and the mutex associated with the source BtShared | - | ||||||||||||||||||||||||
52 | ** structure, in that order. | - | ||||||||||||||||||||||||
53 | ** | - | ||||||||||||||||||||||||
54 | ** * Via the BackupUpdate() and BackupRestart() functions, which are | - | ||||||||||||||||||||||||
55 | ** invoked by the pager layer to report various state changes in | - | ||||||||||||||||||||||||
56 | ** the page cache associated with the source database. The mutex | - | ||||||||||||||||||||||||
57 | ** associated with the source database BtShared structure will always | - | ||||||||||||||||||||||||
58 | ** be held when either of these functions are invoked. | - | ||||||||||||||||||||||||
59 | ** | - | ||||||||||||||||||||||||
60 | ** The other sqlite3_backup_XXX() API functions, backup_remaining() and | - | ||||||||||||||||||||||||
61 | ** backup_pagecount() are not thread-safe functions. If they are called | - | ||||||||||||||||||||||||
62 | ** while some other thread is calling backup_step() or backup_finish(), | - | ||||||||||||||||||||||||
63 | ** the values returned may be invalid. There is no way for a call to | - | ||||||||||||||||||||||||
64 | ** BackupUpdate() or BackupRestart() to interfere with backup_remaining() | - | ||||||||||||||||||||||||
65 | ** or backup_pagecount(). | - | ||||||||||||||||||||||||
66 | ** | - | ||||||||||||||||||||||||
67 | ** Depending on the SQLite configuration, the database handles and/or | - | ||||||||||||||||||||||||
68 | ** the Btree objects may have their own mutexes that require locking. | - | ||||||||||||||||||||||||
69 | ** Non-sharable Btrees (in-memory databases for example), do not have | - | ||||||||||||||||||||||||
70 | ** associated mutexes. | - | ||||||||||||||||||||||||
71 | */ | - | ||||||||||||||||||||||||
72 | - | |||||||||||||||||||||||||
73 | /* | - | ||||||||||||||||||||||||
74 | ** Return a pointer corresponding to database zDb (i.e. "main", "temp") | - | ||||||||||||||||||||||||
75 | ** in connection handle pDb. If such a database cannot be found, return | - | ||||||||||||||||||||||||
76 | ** a NULL pointer and write an error message to pErrorDb. | - | ||||||||||||||||||||||||
77 | ** | - | ||||||||||||||||||||||||
78 | ** If the "temp" database is requested, it may need to be opened by this | - | ||||||||||||||||||||||||
79 | ** function. If an error occurs while doing so, return 0 and write an | - | ||||||||||||||||||||||||
80 | ** error message to pErrorDb. | - | ||||||||||||||||||||||||
81 | */ | - | ||||||||||||||||||||||||
82 | static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ | - | ||||||||||||||||||||||||
83 | int i = sqlite3FindDbName(pDb, zDb); | - | ||||||||||||||||||||||||
84 | - | |||||||||||||||||||||||||
85 | if( i==1 ){
| 5-79 | ||||||||||||||||||||||||
86 | Parse sParse; | - | ||||||||||||||||||||||||
87 | int rc = 0; | - | ||||||||||||||||||||||||
88 | memset(&sParse, 0, sizeof(sParse)); | - | ||||||||||||||||||||||||
89 | sParse.db = pDb; | - | ||||||||||||||||||||||||
90 | if( sqlite3OpenTempDatabase(&sParse) ){
| 0-5 | ||||||||||||||||||||||||
91 | sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg); | - | ||||||||||||||||||||||||
92 | rc = SQLITE_ERROR; | - | ||||||||||||||||||||||||
93 | } never executed: end of block | 0 | ||||||||||||||||||||||||
94 | sqlite3DbFree(pErrorDb, sParse.zErrMsg); | - | ||||||||||||||||||||||||
95 | sqlite3ParserReset(&sParse); | - | ||||||||||||||||||||||||
96 | if( rc ){
| 0-5 | ||||||||||||||||||||||||
97 | return 0; never executed: return 0; | 0 | ||||||||||||||||||||||||
98 | } | - | ||||||||||||||||||||||||
99 | } executed 5 times by 1 test: end of block Executed by:
| 5 | ||||||||||||||||||||||||
100 | - | |||||||||||||||||||||||||
101 | if( i<0 ){
| 2-82 | ||||||||||||||||||||||||
102 | sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); | - | ||||||||||||||||||||||||
103 | return 0; executed 2 times by 1 test: return 0; Executed by:
| 2 | ||||||||||||||||||||||||
104 | } | - | ||||||||||||||||||||||||
105 | - | |||||||||||||||||||||||||
106 | return pDb->aDb[i].pBt; executed 82 times by 1 test: return pDb->aDb[i].pBt; Executed by:
| 82 | ||||||||||||||||||||||||
107 | } | - | ||||||||||||||||||||||||
108 | - | |||||||||||||||||||||||||
109 | /* | - | ||||||||||||||||||||||||
110 | ** Attempt to set the page size of the destination to match the page size | - | ||||||||||||||||||||||||
111 | ** of the source. | - | ||||||||||||||||||||||||
112 | */ | - | ||||||||||||||||||||||||
113 | static int setDestPgsz(sqlite3_backup *p){ | - | ||||||||||||||||||||||||
114 | int rc; | - | ||||||||||||||||||||||||
115 | rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0); | - | ||||||||||||||||||||||||
116 | return rc; executed 535 times by 2 tests: return rc; Executed by:
| 535 | ||||||||||||||||||||||||
117 | } | - | ||||||||||||||||||||||||
118 | - | |||||||||||||||||||||||||
119 | /* | - | ||||||||||||||||||||||||
120 | ** Check that there is no open read-transaction on the b-tree passed as the | - | ||||||||||||||||||||||||
121 | ** second argument. If there is not, return SQLITE_OK. Otherwise, if there | - | ||||||||||||||||||||||||
122 | ** is an open read-transaction, return SQLITE_ERROR and leave an error | - | ||||||||||||||||||||||||
123 | ** message in database handle db. | - | ||||||||||||||||||||||||
124 | */ | - | ||||||||||||||||||||||||
125 | static int checkReadTransaction(sqlite3 *db, Btree *p){ | - | ||||||||||||||||||||||||
126 | if( sqlite3BtreeIsInReadTrans(p) ){
| 1-39 | ||||||||||||||||||||||||
127 | sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use"); | - | ||||||||||||||||||||||||
128 | return SQLITE_ERROR; executed 1 time by 1 test: return 1; Executed by:
| 1 | ||||||||||||||||||||||||
129 | } | - | ||||||||||||||||||||||||
130 | return SQLITE_OK; executed 39 times by 1 test: return 0; Executed by:
| 39 | ||||||||||||||||||||||||
131 | } | - | ||||||||||||||||||||||||
132 | - | |||||||||||||||||||||||||
133 | /* | - | ||||||||||||||||||||||||
134 | ** Create an sqlite3_backup process to copy the contents of zSrcDb from | - | ||||||||||||||||||||||||
135 | ** connection handle pSrcDb to zDestDb in pDestDb. If successful, return | - | ||||||||||||||||||||||||
136 | ** a pointer to the new sqlite3_backup object. | - | ||||||||||||||||||||||||
137 | ** | - | ||||||||||||||||||||||||
138 | ** If an error occurs, NULL is returned and an error code and error message | - | ||||||||||||||||||||||||
139 | ** stored in database handle pDestDb. | - | ||||||||||||||||||||||||
140 | */ | - | ||||||||||||||||||||||||
141 | sqlite3_backup *sqlite3_backup_init( | - | ||||||||||||||||||||||||
142 | sqlite3* pDestDb, /* Database to write to */ | - | ||||||||||||||||||||||||
143 | const char *zDestDb, /* Name of database within pDestDb */ | - | ||||||||||||||||||||||||
144 | sqlite3* pSrcDb, /* Database connection to read from */ | - | ||||||||||||||||||||||||
145 | const char *zSrcDb /* Name of database within pSrcDb */ | - | ||||||||||||||||||||||||
146 | ){ | - | ||||||||||||||||||||||||
147 | sqlite3_backup *p; /* Value to return */ | - | ||||||||||||||||||||||||
148 | - | |||||||||||||||||||||||||
149 | #ifdef SQLITE_ENABLE_API_ARMOR | - | ||||||||||||||||||||||||
150 | if( !sqlite3SafetyCheckOk(pSrcDb)||!sqlite3SafetyCheckOk(pDestDb) ){ | - | ||||||||||||||||||||||||
151 | (void)SQLITE_MISUSE_BKPT; | - | ||||||||||||||||||||||||
152 | return 0; | - | ||||||||||||||||||||||||
153 | } | - | ||||||||||||||||||||||||
154 | #endif | - | ||||||||||||||||||||||||
155 | - | |||||||||||||||||||||||||
156 | /* Lock the source database handle. The destination database | - | ||||||||||||||||||||||||
157 | ** handle is not locked in this routine, but it is locked in | - | ||||||||||||||||||||||||
158 | ** sqlite3_backup_step(). The user is required to ensure that no | - | ||||||||||||||||||||||||
159 | ** other thread accesses the destination handle for the duration | - | ||||||||||||||||||||||||
160 | ** of the backup operation. Any attempt to use the destination | - | ||||||||||||||||||||||||
161 | ** database connection while a backup is in progress may cause | - | ||||||||||||||||||||||||
162 | ** a malfunction or a deadlock. | - | ||||||||||||||||||||||||
163 | */ | - | ||||||||||||||||||||||||
164 | sqlite3_mutex_enter(pSrcDb->mutex); | - | ||||||||||||||||||||||||
165 | sqlite3_mutex_enter(pDestDb->mutex); | - | ||||||||||||||||||||||||
166 | - | |||||||||||||||||||||||||
167 | if( pSrcDb==pDestDb ){
| 0-42 | ||||||||||||||||||||||||
168 | sqlite3ErrorWithMsg( | - | ||||||||||||||||||||||||
169 | pDestDb, SQLITE_ERROR, "source and destination must be distinct" | - | ||||||||||||||||||||||||
170 | ); | - | ||||||||||||||||||||||||
171 | p = 0; | - | ||||||||||||||||||||||||
172 | }else { never executed: end of block | 0 | ||||||||||||||||||||||||
173 | /* Allocate space for a new sqlite3_backup object... | - | ||||||||||||||||||||||||
174 | ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a | - | ||||||||||||||||||||||||
175 | ** call to sqlite3_backup_init() and is destroyed by a call to | - | ||||||||||||||||||||||||
176 | ** sqlite3_backup_finish(). */ | - | ||||||||||||||||||||||||
177 | p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup)); | - | ||||||||||||||||||||||||
178 | if( !p ){
| 0-42 | ||||||||||||||||||||||||
179 | sqlite3Error(pDestDb, SQLITE_NOMEM_BKPT); | - | ||||||||||||||||||||||||
180 | } never executed: end of block | 0 | ||||||||||||||||||||||||
181 | } executed 42 times by 1 test: end of block Executed by:
| 42 | ||||||||||||||||||||||||
182 | - | |||||||||||||||||||||||||
183 | /* If the allocation succeeded, populate the new object. */ | - | ||||||||||||||||||||||||
184 | if( p ){
| 0-42 | ||||||||||||||||||||||||
185 | p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); | - | ||||||||||||||||||||||||
186 | p->pDest = findBtree(pDestDb, pDestDb, zDestDb); | - | ||||||||||||||||||||||||
187 | p->pDestDb = pDestDb; | - | ||||||||||||||||||||||||
188 | p->pSrcDb = pSrcDb; | - | ||||||||||||||||||||||||
189 | p->iNext = 1; | - | ||||||||||||||||||||||||
190 | p->isAttached = 0; | - | ||||||||||||||||||||||||
191 | - | |||||||||||||||||||||||||
192 | if( 0==p->pSrc || 0==p->pDest
| 1-41 | ||||||||||||||||||||||||
193 | || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
| 1-39 | ||||||||||||||||||||||||
194 | ){ | - | ||||||||||||||||||||||||
195 | /* One (or both) of the named databases did not exist or an OOM | - | ||||||||||||||||||||||||
196 | ** error was hit. Or there is a transaction open on the destination | - | ||||||||||||||||||||||||
197 | ** database. The error has already been written into the pDestDb | - | ||||||||||||||||||||||||
198 | ** handle. All that is left to do here is free the sqlite3_backup | - | ||||||||||||||||||||||||
199 | ** structure. */ | - | ||||||||||||||||||||||||
200 | sqlite3_free(p); | - | ||||||||||||||||||||||||
201 | p = 0; | - | ||||||||||||||||||||||||
202 | } executed 3 times by 1 test: end of block Executed by:
| 3 | ||||||||||||||||||||||||
203 | } executed 42 times by 1 test: end of block Executed by:
| 42 | ||||||||||||||||||||||||
204 | if( p ){
| 3-39 | ||||||||||||||||||||||||
205 | p->pSrc->nBackup++; | - | ||||||||||||||||||||||||
206 | } executed 39 times by 1 test: end of block Executed by:
| 39 | ||||||||||||||||||||||||
207 | - | |||||||||||||||||||||||||
208 | sqlite3_mutex_leave(pDestDb->mutex); | - | ||||||||||||||||||||||||
209 | sqlite3_mutex_leave(pSrcDb->mutex); | - | ||||||||||||||||||||||||
210 | return p; executed 42 times by 1 test: return p; Executed by:
| 42 | ||||||||||||||||||||||||
211 | } | - | ||||||||||||||||||||||||
212 | - | |||||||||||||||||||||||||
213 | /* | - | ||||||||||||||||||||||||
214 | ** Argument rc is an SQLite error code. Return true if this error is | - | ||||||||||||||||||||||||
215 | ** considered fatal if encountered during a backup operation. All errors | - | ||||||||||||||||||||||||
216 | ** are considered fatal except for SQLITE_BUSY and SQLITE_LOCKED. | - | ||||||||||||||||||||||||
217 | */ | - | ||||||||||||||||||||||||
218 | static int isFatalError(int rc){ | - | ||||||||||||||||||||||||
219 | return (rc!=SQLITE_OK && rc!=SQLITE_BUSY && ALWAYS(rc!=SQLITE_LOCKED)); executed 3091 times by 2 tests: return (rc!=0 && rc!=5 && (rc!=6)); Executed by:
| 0-3091 | ||||||||||||||||||||||||
220 | } | - | ||||||||||||||||||||||||
221 | - | |||||||||||||||||||||||||
222 | /* | - | ||||||||||||||||||||||||
223 | ** Parameter zSrcData points to a buffer containing the data for | - | ||||||||||||||||||||||||
224 | ** page iSrcPg from the source database. Copy this data into the | - | ||||||||||||||||||||||||
225 | ** destination database. | - | ||||||||||||||||||||||||
226 | */ | - | ||||||||||||||||||||||||
227 | static int backupOnePage( | - | ||||||||||||||||||||||||
228 | sqlite3_backup *p, /* Backup handle */ | - | ||||||||||||||||||||||||
229 | Pgno iSrcPg, /* Source database page to backup */ | - | ||||||||||||||||||||||||
230 | const u8 *zSrcData, /* Source database page data */ | - | ||||||||||||||||||||||||
231 | int bUpdate /* True for an update, false otherwise */ | - | ||||||||||||||||||||||||
232 | ){ | - | ||||||||||||||||||||||||
233 | Pager * const pDestPager = sqlite3BtreePager(p->pDest); | - | ||||||||||||||||||||||||
234 | const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); | - | ||||||||||||||||||||||||
235 | int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); | - | ||||||||||||||||||||||||
236 | const int nCopy = MIN(nSrcPgsz, nDestPgsz);
| 17-98732 | ||||||||||||||||||||||||
237 | const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; | - | ||||||||||||||||||||||||
238 | #ifdef SQLITE_HAS_CODEC | - | ||||||||||||||||||||||||
239 | /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is | - | ||||||||||||||||||||||||
240 | ** guaranteed that the shared-mutex is held by this thread, handle | - | ||||||||||||||||||||||||
241 | ** p->pSrc may not actually be the owner. */ | - | ||||||||||||||||||||||||
242 | int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc); | - | ||||||||||||||||||||||||
243 | int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest); | - | ||||||||||||||||||||||||
244 | #endif | - | ||||||||||||||||||||||||
245 | int rc = SQLITE_OK; | - | ||||||||||||||||||||||||
246 | i64 iOff; | - | ||||||||||||||||||||||||
247 | - | |||||||||||||||||||||||||
248 | assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 ); | - | ||||||||||||||||||||||||
249 | assert( p->bDestLocked ); | - | ||||||||||||||||||||||||
250 | assert( !isFatalError(p->rc) ); | - | ||||||||||||||||||||||||
251 | assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ); | - | ||||||||||||||||||||||||
252 | assert( zSrcData ); | - | ||||||||||||||||||||||||
253 | - | |||||||||||||||||||||||||
254 | /* Catch the case where the destination is an in-memory database and the | - | ||||||||||||||||||||||||
255 | ** page sizes of the source and destination differ. | - | ||||||||||||||||||||||||
256 | */ | - | ||||||||||||||||||||||||
257 | if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){
| 2-98584 | ||||||||||||||||||||||||
258 | rc = SQLITE_READONLY; | - | ||||||||||||||||||||||||
259 | } executed 2 times by 1 test: end of block Executed by:
| 2 | ||||||||||||||||||||||||
260 | - | |||||||||||||||||||||||||
261 | #ifdef SQLITE_HAS_CODEC | - | ||||||||||||||||||||||||
262 | /* Backup is not possible if the page size of the destination is changing | - | ||||||||||||||||||||||||
263 | ** and a codec is in use. | - | ||||||||||||||||||||||||
264 | */ | - | ||||||||||||||||||||||||
265 | if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){ | - | ||||||||||||||||||||||||
266 | rc = SQLITE_READONLY; | - | ||||||||||||||||||||||||
267 | } | - | ||||||||||||||||||||||||
268 | - | |||||||||||||||||||||||||
269 | /* Backup is not possible if the number of bytes of reserve space differ | - | ||||||||||||||||||||||||
270 | ** between source and destination. If there is a difference, try to | - | ||||||||||||||||||||||||
271 | ** fix the destination to agree with the source. If that is not possible, | - | ||||||||||||||||||||||||
272 | ** then the backup cannot proceed. | - | ||||||||||||||||||||||||
273 | */ | - | ||||||||||||||||||||||||
274 | if( nSrcReserve!=nDestReserve ){ | - | ||||||||||||||||||||||||
275 | u32 newPgsz = nSrcPgsz; | - | ||||||||||||||||||||||||
276 | rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve); | - | ||||||||||||||||||||||||
277 | if( rc==SQLITE_OK && newPgsz!=nSrcPgsz ) rc = SQLITE_READONLY; | - | ||||||||||||||||||||||||
278 | } | - | ||||||||||||||||||||||||
279 | #endif | - | ||||||||||||||||||||||||
280 | - | |||||||||||||||||||||||||
281 | /* This loop runs once for each destination page spanned by the source | - | ||||||||||||||||||||||||
282 | ** page. For each iteration, variable iOff is set to the byte offset | - | ||||||||||||||||||||||||
283 | ** of the destination page. | - | ||||||||||||||||||||||||
284 | */ | - | ||||||||||||||||||||||||
285 | for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){
| 275-197387 | ||||||||||||||||||||||||
286 | DbPage *pDestPg = 0; | - | ||||||||||||||||||||||||
287 | Pgno iDest = (Pgno)(iOff/nDestPgsz)+1; | - | ||||||||||||||||||||||||
288 | if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue; never executed: continue;
| 0-98913 | ||||||||||||||||||||||||
289 | if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0))
| 0-98913 | ||||||||||||||||||||||||
290 | && SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg))
| 273-98640 | ||||||||||||||||||||||||
291 | ){ | - | ||||||||||||||||||||||||
292 | const u8 *zIn = &zSrcData[iOff%nSrcPgsz]; | - | ||||||||||||||||||||||||
293 | u8 *zDestData = sqlite3PagerGetData(pDestPg); | - | ||||||||||||||||||||||||
294 | u8 *zOut = &zDestData[iOff%nDestPgsz]; | - | ||||||||||||||||||||||||
295 | - | |||||||||||||||||||||||||
296 | /* Copy the data from the source page into the destination page. | - | ||||||||||||||||||||||||
297 | ** Then clear the Btree layer MemPage.isInit flag. Both this module | - | ||||||||||||||||||||||||
298 | ** and the pager code use this trick (clearing the first byte | - | ||||||||||||||||||||||||
299 | ** of the page 'extra' space to invalidate the Btree layers | - | ||||||||||||||||||||||||
300 | ** cached parse of the page). MemPage.isInit is marked | - | ||||||||||||||||||||||||
301 | ** "MUST BE FIRST" for this purpose. | - | ||||||||||||||||||||||||
302 | */ | - | ||||||||||||||||||||||||
303 | memcpy(zOut, zIn, nCopy); | - | ||||||||||||||||||||||||
304 | ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; | - | ||||||||||||||||||||||||
305 | if( iOff==0 && bUpdate==0 ){
| 4-98111 | ||||||||||||||||||||||||
306 | sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc)); | - | ||||||||||||||||||||||||
307 | } executed 525 times by 2 tests: end of block Executed by:
| 525 | ||||||||||||||||||||||||
308 | } executed 98640 times by 2 tests: end of block Executed by:
| 98640 | ||||||||||||||||||||||||
309 | sqlite3PagerUnref(pDestPg); | - | ||||||||||||||||||||||||
310 | } executed 98913 times by 2 tests: end of block Executed by:
| 98913 | ||||||||||||||||||||||||
311 | - | |||||||||||||||||||||||||
312 | return rc; executed 98749 times by 2 tests: return rc; Executed by:
| 98749 | ||||||||||||||||||||||||
313 | } | - | ||||||||||||||||||||||||
314 | - | |||||||||||||||||||||||||
315 | /* | - | ||||||||||||||||||||||||
316 | ** If pFile is currently larger than iSize bytes, then truncate it to | - | ||||||||||||||||||||||||
317 | ** exactly iSize bytes. If pFile is not larger than iSize bytes, then | - | ||||||||||||||||||||||||
318 | ** this function is a no-op. | - | ||||||||||||||||||||||||
319 | ** | - | ||||||||||||||||||||||||
320 | ** Return SQLITE_OK if everything is successful, or an SQLite error | - | ||||||||||||||||||||||||
321 | ** code if an error occurs. | - | ||||||||||||||||||||||||
322 | */ | - | ||||||||||||||||||||||||
323 | static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){ | - | ||||||||||||||||||||||||
324 | i64 iCurrent; | - | ||||||||||||||||||||||||
325 | int rc = sqlite3OsFileSize(pFile, &iCurrent); | - | ||||||||||||||||||||||||
326 | if( rc==SQLITE_OK && iCurrent>iSize ){
| 0-8 | ||||||||||||||||||||||||
327 | rc = sqlite3OsTruncate(pFile, iSize); | - | ||||||||||||||||||||||||
328 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||||||||||||||
329 | return rc; executed 8 times by 1 test: return rc; Executed by:
| 8 | ||||||||||||||||||||||||
330 | } | - | ||||||||||||||||||||||||
331 | - | |||||||||||||||||||||||||
332 | /* | - | ||||||||||||||||||||||||
333 | ** Register this backup object with the associated source pager for | - | ||||||||||||||||||||||||
334 | ** callbacks when pages are changed or the cache invalidated. | - | ||||||||||||||||||||||||
335 | */ | - | ||||||||||||||||||||||||
336 | static void attachBackupObject(sqlite3_backup *p){ | - | ||||||||||||||||||||||||
337 | sqlite3_backup **pp; | - | ||||||||||||||||||||||||
338 | assert( sqlite3BtreeHoldsMutex(p->pSrc) ); | - | ||||||||||||||||||||||||
339 | pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); | - | ||||||||||||||||||||||||
340 | p->pNext = *pp; | - | ||||||||||||||||||||||||
341 | *pp = p; | - | ||||||||||||||||||||||||
342 | p->isAttached = 1; | - | ||||||||||||||||||||||||
343 | } executed 7 times by 1 test: end of block Executed by:
| 7 | ||||||||||||||||||||||||
344 | - | |||||||||||||||||||||||||
345 | /* | - | ||||||||||||||||||||||||
346 | ** Copy nPage pages from the source b-tree to the destination. | - | ||||||||||||||||||||||||
347 | */ | - | ||||||||||||||||||||||||
348 | int sqlite3_backup_step(sqlite3_backup *p, int nPage){ | - | ||||||||||||||||||||||||
349 | int rc; | - | ||||||||||||||||||||||||
350 | int destMode; /* Destination journal mode */ | - | ||||||||||||||||||||||||
351 | int pgszSrc = 0; /* Source page size */ | - | ||||||||||||||||||||||||
352 | int pgszDest = 0; /* Destination page size */ | - | ||||||||||||||||||||||||
353 | - | |||||||||||||||||||||||||
354 | #ifdef SQLITE_ENABLE_API_ARMOR | - | ||||||||||||||||||||||||
355 | if( p==0 ) return SQLITE_MISUSE_BKPT; | - | ||||||||||||||||||||||||
356 | #endif | - | ||||||||||||||||||||||||
357 | sqlite3_mutex_enter(p->pSrcDb->mutex); | - | ||||||||||||||||||||||||
358 | sqlite3BtreeEnter(p->pSrc); | - | ||||||||||||||||||||||||
359 | if( p->pDestDb ){
| 52-498 | ||||||||||||||||||||||||
360 | sqlite3_mutex_enter(p->pDestDb->mutex); | - | ||||||||||||||||||||||||
361 | } executed 52 times by 1 test: end of block Executed by:
| 52 | ||||||||||||||||||||||||
362 | - | |||||||||||||||||||||||||
363 | rc = p->rc; | - | ||||||||||||||||||||||||
364 | if( !isFatalError(rc) ){
| 1-549 | ||||||||||||||||||||||||
365 | Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */ | - | ||||||||||||||||||||||||
366 | Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */ | - | ||||||||||||||||||||||||
367 | int ii; /* Iterator variable */ | - | ||||||||||||||||||||||||
368 | int nSrcPage = -1; /* Size of source db in pages */ | - | ||||||||||||||||||||||||
369 | int bCloseTrans = 0; /* True if src db requires unlocking */ | - | ||||||||||||||||||||||||
370 | - | |||||||||||||||||||||||||
371 | /* If the source pager is currently in a write-transaction, return | - | ||||||||||||||||||||||||
372 | ** SQLITE_BUSY immediately. | - | ||||||||||||||||||||||||
373 | */ | - | ||||||||||||||||||||||||
374 | if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){
| 2-498 | ||||||||||||||||||||||||
375 | rc = SQLITE_BUSY; | - | ||||||||||||||||||||||||
376 | }else{ executed 2 times by 1 test: end of block Executed by:
| 2 | ||||||||||||||||||||||||
377 | rc = SQLITE_OK; | - | ||||||||||||||||||||||||
378 | } executed 547 times by 2 tests: end of block Executed by:
| 547 | ||||||||||||||||||||||||
379 | - | |||||||||||||||||||||||||
380 | /* If there is no open read-transaction on the source database, open | - | ||||||||||||||||||||||||
381 | ** one now. If a transaction is opened here, then it will be closed | - | ||||||||||||||||||||||||
382 | ** before this function exits. | - | ||||||||||||||||||||||||
383 | */ | - | ||||||||||||||||||||||||
384 | if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
| 2-547 | ||||||||||||||||||||||||
385 | rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0); | - | ||||||||||||||||||||||||
386 | bCloseTrans = 1; | - | ||||||||||||||||||||||||
387 | } executed 49 times by 1 test: end of block Executed by:
| 49 | ||||||||||||||||||||||||
388 | - | |||||||||||||||||||||||||
389 | /* If the destination database has not yet been locked (i.e. if this | - | ||||||||||||||||||||||||
390 | ** is the first call to backup_step() for the current backup operation), | - | ||||||||||||||||||||||||
391 | ** try to set its page size to the same as the source database. This | - | ||||||||||||||||||||||||
392 | ** is especially important on ZipVFS systems, as in that case it is | - | ||||||||||||||||||||||||
393 | ** not possible to create a database file that uses one page size by | - | ||||||||||||||||||||||||
394 | ** writing to it with another. */ | - | ||||||||||||||||||||||||
395 | if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){
| 0-540 | ||||||||||||||||||||||||
396 | rc = SQLITE_NOMEM; | - | ||||||||||||||||||||||||
397 | } never executed: end of block | 0 | ||||||||||||||||||||||||
398 | - | |||||||||||||||||||||||||
399 | /* Lock the destination database, if it is not locked already. */ | - | ||||||||||||||||||||||||
400 | if( SQLITE_OK==rc && p->bDestLocked==0
| 7-542 | ||||||||||||||||||||||||
401 | && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2,
| 2-533 | ||||||||||||||||||||||||
402 | (int*)&p->iDestSchema))
| 2-533 | ||||||||||||||||||||||||
403 | ){ | - | ||||||||||||||||||||||||
404 | p->bDestLocked = 1; | - | ||||||||||||||||||||||||
405 | } executed 533 times by 2 tests: end of block Executed by:
| 533 | ||||||||||||||||||||||||
406 | - | |||||||||||||||||||||||||
407 | /* Do not allow backup if the destination database is in WAL mode | - | ||||||||||||||||||||||||
408 | ** and the page sizes are different between source and destination */ | - | ||||||||||||||||||||||||
409 | pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); | - | ||||||||||||||||||||||||
410 | pgszDest = sqlite3BtreeGetPageSize(p->pDest); | - | ||||||||||||||||||||||||
411 | destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest)); | - | ||||||||||||||||||||||||
412 | if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){
| 0-540 | ||||||||||||||||||||||||
413 | rc = SQLITE_READONLY; | - | ||||||||||||||||||||||||
414 | } never executed: end of block | 0 | ||||||||||||||||||||||||
415 | - | |||||||||||||||||||||||||
416 | /* Now that there is a read-lock on the source database, query the | - | ||||||||||||||||||||||||
417 | ** source pager for the number of pages in the database. | - | ||||||||||||||||||||||||
418 | */ | - | ||||||||||||||||||||||||
419 | nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc); | - | ||||||||||||||||||||||||
420 | assert( nSrcPage>=0 ); | - | ||||||||||||||||||||||||
421 | for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
| 0-98035 | ||||||||||||||||||||||||
422 | const Pgno iSrcPg = p->iNext; /* Source page number */ | - | ||||||||||||||||||||||||
423 | if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
| 202-97284 | ||||||||||||||||||||||||
424 | DbPage *pSrcPg; /* Source page object */ | - | ||||||||||||||||||||||||
425 | rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY); | - | ||||||||||||||||||||||||
426 | if( rc==SQLITE_OK ){
| 0-97284 | ||||||||||||||||||||||||
427 | rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); | - | ||||||||||||||||||||||||
428 | sqlite3PagerUnref(pSrcPg); | - | ||||||||||||||||||||||||
429 | } executed 97284 times by 2 tests: end of block Executed by:
| 97284 | ||||||||||||||||||||||||
430 | } executed 97284 times by 2 tests: end of block Executed by:
| 97284 | ||||||||||||||||||||||||
431 | p->iNext++; | - | ||||||||||||||||||||||||
432 | } executed 97486 times by 2 tests: end of block Executed by:
| 97486 | ||||||||||||||||||||||||
433 | if( rc==SQLITE_OK ){
| 265-284 | ||||||||||||||||||||||||
434 | p->nPagecount = nSrcPage; | - | ||||||||||||||||||||||||
435 | p->nRemaining = nSrcPage+1-p->iNext; | - | ||||||||||||||||||||||||
436 | if( p->iNext>(Pgno)nSrcPage ){
| 7-258 | ||||||||||||||||||||||||
437 | rc = SQLITE_DONE; | - | ||||||||||||||||||||||||
438 | }else if( !p->isAttached ){ executed 258 times by 2 tests: end of block Executed by:
| 0-258 | ||||||||||||||||||||||||
439 | attachBackupObject(p); | - | ||||||||||||||||||||||||
440 | } executed 7 times by 1 test: end of block Executed by:
| 7 | ||||||||||||||||||||||||
441 | } executed 265 times by 2 tests: end of block Executed by:
| 265 | ||||||||||||||||||||||||
442 | - | |||||||||||||||||||||||||
443 | /* Update the schema version field in the destination database. This | - | ||||||||||||||||||||||||
444 | ** is to make sure that the schema-version really does change in | - | ||||||||||||||||||||||||
445 | ** the case where the source and destination databases have the | - | ||||||||||||||||||||||||
446 | ** same schema version. | - | ||||||||||||||||||||||||
447 | */ | - | ||||||||||||||||||||||||
448 | if( rc==SQLITE_DONE ){
| 258-291 | ||||||||||||||||||||||||
449 | if( nSrcPage==0 ){
| 4-254 | ||||||||||||||||||||||||
450 | rc = sqlite3BtreeNewDb(p->pDest); | - | ||||||||||||||||||||||||
451 | nSrcPage = 1; | - | ||||||||||||||||||||||||
452 | } executed 4 times by 1 test: end of block Executed by:
| 4 | ||||||||||||||||||||||||
453 | if( rc==SQLITE_OK || rc==SQLITE_DONE ){
| 0-254 | ||||||||||||||||||||||||
454 | rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1); | - | ||||||||||||||||||||||||
455 | } executed 258 times by 2 tests: end of block Executed by:
| 258 | ||||||||||||||||||||||||
456 | if( rc==SQLITE_OK ){
| 0-258 | ||||||||||||||||||||||||
457 | if( p->pDestDb ){
| 33-225 | ||||||||||||||||||||||||
458 | sqlite3ResetAllSchemasOfConnection(p->pDestDb); | - | ||||||||||||||||||||||||
459 | } executed 33 times by 1 test: end of block Executed by:
| 33 | ||||||||||||||||||||||||
460 | if( destMode==PAGER_JOURNALMODE_WAL ){
| 23-235 | ||||||||||||||||||||||||
461 | rc = sqlite3BtreeSetVersion(p->pDest, 2); | - | ||||||||||||||||||||||||
462 | } executed 23 times by 1 test: end of block Executed by:
| 23 | ||||||||||||||||||||||||
463 | } executed 258 times by 2 tests: end of block Executed by:
| 258 | ||||||||||||||||||||||||
464 | if( rc==SQLITE_OK ){
| 0-258 | ||||||||||||||||||||||||
465 | int nDestTruncate; | - | ||||||||||||||||||||||||
466 | /* Set nDestTruncate to the final number of pages in the destination | - | ||||||||||||||||||||||||
467 | ** database. The complication here is that the destination page | - | ||||||||||||||||||||||||
468 | ** size may be different to the source page size. | - | ||||||||||||||||||||||||
469 | ** | - | ||||||||||||||||||||||||
470 | ** If the source page size is smaller than the destination page size, | - | ||||||||||||||||||||||||
471 | ** round up. In this case the call to sqlite3OsTruncate() below will | - | ||||||||||||||||||||||||
472 | ** fix the size of the file. However it is important to call | - | ||||||||||||||||||||||||
473 | ** sqlite3PagerTruncateImage() here so that any pages in the | - | ||||||||||||||||||||||||
474 | ** destination file that lie beyond the nDestTruncate page mark are | - | ||||||||||||||||||||||||
475 | ** journalled by PagerCommitPhaseOne() before they are destroyed | - | ||||||||||||||||||||||||
476 | ** by the file truncation. | - | ||||||||||||||||||||||||
477 | */ | - | ||||||||||||||||||||||||
478 | assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) ); | - | ||||||||||||||||||||||||
479 | assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) ); | - | ||||||||||||||||||||||||
480 | if( pgszSrc<pgszDest ){
| 8-250 | ||||||||||||||||||||||||
481 | int ratio = pgszDest/pgszSrc; | - | ||||||||||||||||||||||||
482 | nDestTruncate = (nSrcPage+ratio-1)/ratio; | - | ||||||||||||||||||||||||
483 | if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
| 0-8 | ||||||||||||||||||||||||
484 | nDestTruncate--; | - | ||||||||||||||||||||||||
485 | } never executed: end of block | 0 | ||||||||||||||||||||||||
486 | }else{ executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||||||||||||||
487 | nDestTruncate = nSrcPage * (pgszSrc/pgszDest); | - | ||||||||||||||||||||||||
488 | } executed 250 times by 2 tests: end of block Executed by:
| 250 | ||||||||||||||||||||||||
489 | assert( nDestTruncate>0 ); | - | ||||||||||||||||||||||||
490 | - | |||||||||||||||||||||||||
491 | if( pgszSrc<pgszDest ){
| 8-250 | ||||||||||||||||||||||||
492 | /* If the source page-size is smaller than the destination page-size, | - | ||||||||||||||||||||||||
493 | ** two extra things may need to happen: | - | ||||||||||||||||||||||||
494 | ** | - | ||||||||||||||||||||||||
495 | ** * The destination may need to be truncated, and | - | ||||||||||||||||||||||||
496 | ** | - | ||||||||||||||||||||||||
497 | ** * Data stored on the pages immediately following the | - | ||||||||||||||||||||||||
498 | ** pending-byte page in the source database may need to be | - | ||||||||||||||||||||||||
499 | ** copied into the destination database. | - | ||||||||||||||||||||||||
500 | */ | - | ||||||||||||||||||||||||
501 | const i64 iSize = (i64)pgszSrc * (i64)nSrcPage; | - | ||||||||||||||||||||||||
502 | sqlite3_file * const pFile = sqlite3PagerFile(pDestPager); | - | ||||||||||||||||||||||||
503 | Pgno iPg; | - | ||||||||||||||||||||||||
504 | int nDstPage; | - | ||||||||||||||||||||||||
505 | i64 iOff; | - | ||||||||||||||||||||||||
506 | i64 iEnd; | - | ||||||||||||||||||||||||
507 | - | |||||||||||||||||||||||||
508 | assert( pFile ); | - | ||||||||||||||||||||||||
509 | assert( nDestTruncate==0 | - | ||||||||||||||||||||||||
510 | || (i64)nDestTruncate*(i64)pgszDest >= iSize || ( | - | ||||||||||||||||||||||||
511 | nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1) | - | ||||||||||||||||||||||||
512 | && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest | - | ||||||||||||||||||||||||
513 | )); | - | ||||||||||||||||||||||||
514 | - | |||||||||||||||||||||||||
515 | /* This block ensures that all data required to recreate the original | - | ||||||||||||||||||||||||
516 | ** database has been stored in the journal for pDestPager and the | - | ||||||||||||||||||||||||
517 | ** journal synced to disk. So at this point we may safely modify | - | ||||||||||||||||||||||||
518 | ** the database file in any way, knowing that if a power failure | - | ||||||||||||||||||||||||
519 | ** occurs, the original database will be reconstructed from the | - | ||||||||||||||||||||||||
520 | ** journal file. */ | - | ||||||||||||||||||||||||
521 | sqlite3PagerPagecount(pDestPager, &nDstPage); | - | ||||||||||||||||||||||||
522 | for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
| 0-26 | ||||||||||||||||||||||||
523 | if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
| 0-18 | ||||||||||||||||||||||||
524 | DbPage *pPg; | - | ||||||||||||||||||||||||
525 | rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0); | - | ||||||||||||||||||||||||
526 | if( rc==SQLITE_OK ){
| 0-18 | ||||||||||||||||||||||||
527 | rc = sqlite3PagerWrite(pPg); | - | ||||||||||||||||||||||||
528 | sqlite3PagerUnref(pPg); | - | ||||||||||||||||||||||||
529 | } executed 18 times by 1 test: end of block Executed by:
| 18 | ||||||||||||||||||||||||
530 | } executed 18 times by 1 test: end of block Executed by:
| 18 | ||||||||||||||||||||||||
531 | } executed 18 times by 1 test: end of block Executed by:
| 18 | ||||||||||||||||||||||||
532 | if( rc==SQLITE_OK ){
| 0-8 | ||||||||||||||||||||||||
533 | rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1); | - | ||||||||||||||||||||||||
534 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||||||||||||||
535 | - | |||||||||||||||||||||||||
536 | /* Write the extra pages and truncate the database file as required */ | - | ||||||||||||||||||||||||
537 | iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
| 0-8 | ||||||||||||||||||||||||
538 | for( | - | ||||||||||||||||||||||||
539 | iOff=PENDING_BYTE+pgszSrc; | - | ||||||||||||||||||||||||
540 | rc==SQLITE_OK && iOff<iEnd;
| 0-8 | ||||||||||||||||||||||||
541 | iOff+=pgszSrc | - | ||||||||||||||||||||||||
542 | ){ | - | ||||||||||||||||||||||||
543 | PgHdr *pSrcPg = 0; | - | ||||||||||||||||||||||||
544 | const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1); | - | ||||||||||||||||||||||||
545 | rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg, 0); | - | ||||||||||||||||||||||||
546 | if( rc==SQLITE_OK ){
| 0 | ||||||||||||||||||||||||
547 | u8 *zData = sqlite3PagerGetData(pSrcPg); | - | ||||||||||||||||||||||||
548 | rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff); | - | ||||||||||||||||||||||||
549 | } never executed: end of block | 0 | ||||||||||||||||||||||||
550 | sqlite3PagerUnref(pSrcPg); | - | ||||||||||||||||||||||||
551 | } never executed: end of block | 0 | ||||||||||||||||||||||||
552 | if( rc==SQLITE_OK ){
| 0-8 | ||||||||||||||||||||||||
553 | rc = backupTruncateFile(pFile, iSize); | - | ||||||||||||||||||||||||
554 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||||||||||||||
555 | - | |||||||||||||||||||||||||
556 | /* Sync the database file to disk. */ | - | ||||||||||||||||||||||||
557 | if( rc==SQLITE_OK ){
| 0-8 | ||||||||||||||||||||||||
558 | rc = sqlite3PagerSync(pDestPager, 0); | - | ||||||||||||||||||||||||
559 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||||||||||||||
560 | }else{ executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||||||||||||||
561 | sqlite3PagerTruncateImage(pDestPager, nDestTruncate); | - | ||||||||||||||||||||||||
562 | rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0); | - | ||||||||||||||||||||||||
563 | } executed 250 times by 2 tests: end of block Executed by:
| 250 | ||||||||||||||||||||||||
564 | - | |||||||||||||||||||||||||
565 | /* Finish committing the transaction to the destination database. */ | - | ||||||||||||||||||||||||
566 | if( SQLITE_OK==rc
| 95-163 | ||||||||||||||||||||||||
567 | && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
| 0-163 | ||||||||||||||||||||||||
568 | ){ | - | ||||||||||||||||||||||||
569 | rc = SQLITE_DONE; | - | ||||||||||||||||||||||||
570 | } executed 163 times by 2 tests: end of block Executed by:
| 163 | ||||||||||||||||||||||||
571 | } executed 258 times by 2 tests: end of block Executed by:
| 258 | ||||||||||||||||||||||||
572 | } executed 258 times by 2 tests: end of block Executed by:
| 258 | ||||||||||||||||||||||||
573 | - | |||||||||||||||||||||||||
574 | /* If bCloseTrans is true, then this function opened a read transaction | - | ||||||||||||||||||||||||
575 | ** on the source database. Close the read transaction here. There is | - | ||||||||||||||||||||||||
576 | ** no need to check the return values of the btree methods here, as | - | ||||||||||||||||||||||||
577 | ** "committing" a read-only transaction cannot fail. | - | ||||||||||||||||||||||||
578 | */ | - | ||||||||||||||||||||||||
579 | if( bCloseTrans ){
| 49-500 | ||||||||||||||||||||||||
580 | TESTONLY( int rc2 ); | - | ||||||||||||||||||||||||
581 | TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0); | - | ||||||||||||||||||||||||
582 | TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0); | - | ||||||||||||||||||||||||
583 | assert( rc2==SQLITE_OK ); | - | ||||||||||||||||||||||||
584 | } executed 49 times by 1 test: end of block Executed by:
| 49 | ||||||||||||||||||||||||
585 | - | |||||||||||||||||||||||||
586 | if( rc==SQLITE_IOERR_NOMEM ){
| 0-549 | ||||||||||||||||||||||||
587 | rc = SQLITE_NOMEM_BKPT; | - | ||||||||||||||||||||||||
588 | } never executed: end of block | 0 | ||||||||||||||||||||||||
589 | p->rc = rc; | - | ||||||||||||||||||||||||
590 | } executed 549 times by 2 tests: end of block Executed by:
| 549 | ||||||||||||||||||||||||
591 | if( p->pDestDb ){
| 52-498 | ||||||||||||||||||||||||
592 | sqlite3_mutex_leave(p->pDestDb->mutex); | - | ||||||||||||||||||||||||
593 | } executed 52 times by 1 test: end of block Executed by:
| 52 | ||||||||||||||||||||||||
594 | sqlite3BtreeLeave(p->pSrc); | - | ||||||||||||||||||||||||
595 | sqlite3_mutex_leave(p->pSrcDb->mutex); | - | ||||||||||||||||||||||||
596 | return rc; executed 550 times by 2 tests: return rc; Executed by:
| 550 | ||||||||||||||||||||||||
597 | } | - | ||||||||||||||||||||||||
598 | - | |||||||||||||||||||||||||
599 | /* | - | ||||||||||||||||||||||||
600 | ** Release all resources associated with an sqlite3_backup* handle. | - | ||||||||||||||||||||||||
601 | */ | - | ||||||||||||||||||||||||
602 | int sqlite3_backup_finish(sqlite3_backup *p){ | - | ||||||||||||||||||||||||
603 | sqlite3_backup **pp; /* Ptr to head of pagers backup list */ | - | ||||||||||||||||||||||||
604 | sqlite3 *pSrcDb; /* Source database connection */ | - | ||||||||||||||||||||||||
605 | int rc; /* Value to return */ | - | ||||||||||||||||||||||||
606 | - | |||||||||||||||||||||||||
607 | /* Enter the mutexes */ | - | ||||||||||||||||||||||||
608 | if( p==0 ) return SQLITE_OK; never executed: return 0;
| 0-537 | ||||||||||||||||||||||||
609 | pSrcDb = p->pSrcDb; | - | ||||||||||||||||||||||||
610 | sqlite3_mutex_enter(pSrcDb->mutex); | - | ||||||||||||||||||||||||
611 | sqlite3BtreeEnter(p->pSrc); | - | ||||||||||||||||||||||||
612 | if( p->pDestDb ){
| 39-498 | ||||||||||||||||||||||||
613 | sqlite3_mutex_enter(p->pDestDb->mutex); | - | ||||||||||||||||||||||||
614 | } executed 39 times by 1 test: end of block Executed by:
| 39 | ||||||||||||||||||||||||
615 | - | |||||||||||||||||||||||||
616 | /* Detach this backup from the source pager. */ | - | ||||||||||||||||||||||||
617 | if( p->pDestDb ){
| 39-498 | ||||||||||||||||||||||||
618 | p->pSrc->nBackup--; | - | ||||||||||||||||||||||||
619 | } executed 39 times by 1 test: end of block Executed by:
| 39 | ||||||||||||||||||||||||
620 | if( p->isAttached ){
| 7-530 | ||||||||||||||||||||||||
621 | pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); | - | ||||||||||||||||||||||||
622 | while( *pp!=p ){
| 0-7 | ||||||||||||||||||||||||
623 | pp = &(*pp)->pNext; | - | ||||||||||||||||||||||||
624 | } never executed: end of block | 0 | ||||||||||||||||||||||||
625 | *pp = p->pNext; | - | ||||||||||||||||||||||||
626 | } executed 7 times by 1 test: end of block Executed by:
| 7 | ||||||||||||||||||||||||
627 | - | |||||||||||||||||||||||||
628 | /* If a transaction is still open on the Btree, roll it back. */ | - | ||||||||||||||||||||||||
629 | sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0); | - | ||||||||||||||||||||||||
630 | - | |||||||||||||||||||||||||
631 | /* Set the error code of the destination database handle. */ | - | ||||||||||||||||||||||||
632 | rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
| 163-374 | ||||||||||||||||||||||||
633 | if( p->pDestDb ){
| 39-498 | ||||||||||||||||||||||||
634 | sqlite3Error(p->pDestDb, rc); | - | ||||||||||||||||||||||||
635 | - | |||||||||||||||||||||||||
636 | /* Exit the mutexes and free the backup context structure. */ | - | ||||||||||||||||||||||||
637 | sqlite3LeaveMutexAndCloseZombie(p->pDestDb); | - | ||||||||||||||||||||||||
638 | } executed 39 times by 1 test: end of block Executed by:
| 39 | ||||||||||||||||||||||||
639 | sqlite3BtreeLeave(p->pSrc); | - | ||||||||||||||||||||||||
640 | if( p->pDestDb ){
| 39-498 | ||||||||||||||||||||||||
641 | /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a | - | ||||||||||||||||||||||||
642 | ** call to sqlite3_backup_init() and is destroyed by a call to | - | ||||||||||||||||||||||||
643 | ** sqlite3_backup_finish(). */ | - | ||||||||||||||||||||||||
644 | sqlite3_free(p); | - | ||||||||||||||||||||||||
645 | } executed 39 times by 1 test: end of block Executed by:
| 39 | ||||||||||||||||||||||||
646 | sqlite3LeaveMutexAndCloseZombie(pSrcDb); | - | ||||||||||||||||||||||||
647 | return rc; executed 537 times by 2 tests: return rc; Executed by:
| 537 | ||||||||||||||||||||||||
648 | } | - | ||||||||||||||||||||||||
649 | - | |||||||||||||||||||||||||
650 | /* | - | ||||||||||||||||||||||||
651 | ** Return the number of pages still to be backed up as of the most recent | - | ||||||||||||||||||||||||
652 | ** call to sqlite3_backup_step(). | - | ||||||||||||||||||||||||
653 | */ | - | ||||||||||||||||||||||||
654 | int sqlite3_backup_remaining(sqlite3_backup *p){ | - | ||||||||||||||||||||||||
655 | #ifdef SQLITE_ENABLE_API_ARMOR | - | ||||||||||||||||||||||||
656 | if( p==0 ){ | - | ||||||||||||||||||||||||
657 | (void)SQLITE_MISUSE_BKPT; | - | ||||||||||||||||||||||||
658 | return 0; | - | ||||||||||||||||||||||||
659 | } | - | ||||||||||||||||||||||||
660 | #endif | - | ||||||||||||||||||||||||
661 | return p->nRemaining; never executed: return p->nRemaining; | 0 | ||||||||||||||||||||||||
662 | } | - | ||||||||||||||||||||||||
663 | - | |||||||||||||||||||||||||
664 | /* | - | ||||||||||||||||||||||||
665 | ** Return the total number of pages in the source database as of the most | - | ||||||||||||||||||||||||
666 | ** recent call to sqlite3_backup_step(). | - | ||||||||||||||||||||||||
667 | */ | - | ||||||||||||||||||||||||
668 | int sqlite3_backup_pagecount(sqlite3_backup *p){ | - | ||||||||||||||||||||||||
669 | #ifdef SQLITE_ENABLE_API_ARMOR | - | ||||||||||||||||||||||||
670 | if( p==0 ){ | - | ||||||||||||||||||||||||
671 | (void)SQLITE_MISUSE_BKPT; | - | ||||||||||||||||||||||||
672 | return 0; | - | ||||||||||||||||||||||||
673 | } | - | ||||||||||||||||||||||||
674 | #endif | - | ||||||||||||||||||||||||
675 | return p->nPagecount; never executed: return p->nPagecount; | 0 | ||||||||||||||||||||||||
676 | } | - | ||||||||||||||||||||||||
677 | - | |||||||||||||||||||||||||
678 | /* | - | ||||||||||||||||||||||||
679 | ** This function is called after the contents of page iPage of the | - | ||||||||||||||||||||||||
680 | ** source database have been modified. If page iPage has already been | - | ||||||||||||||||||||||||
681 | ** copied into the destination database, then the data written to the | - | ||||||||||||||||||||||||
682 | ** destination is now invalidated. The destination copy of iPage needs | - | ||||||||||||||||||||||||
683 | ** to be updated with the new data before the backup operation is | - | ||||||||||||||||||||||||
684 | ** complete. | - | ||||||||||||||||||||||||
685 | ** | - | ||||||||||||||||||||||||
686 | ** It is assumed that the mutex associated with the BtShared object | - | ||||||||||||||||||||||||
687 | ** corresponding to the source database is held when this function is | - | ||||||||||||||||||||||||
688 | ** called. | - | ||||||||||||||||||||||||
689 | */ | - | ||||||||||||||||||||||||
690 | static SQLITE_NOINLINE void backupUpdate( | - | ||||||||||||||||||||||||
691 | sqlite3_backup *p, | - | ||||||||||||||||||||||||
692 | Pgno iPage, | - | ||||||||||||||||||||||||
693 | const u8 *aData | - | ||||||||||||||||||||||||
694 | ){ | - | ||||||||||||||||||||||||
695 | assert( p!=0 ); | - | ||||||||||||||||||||||||
696 | do{ | - | ||||||||||||||||||||||||
697 | assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); | - | ||||||||||||||||||||||||
698 | if( !isFatalError(p->rc) && iPage<p->iNext ){
| 0-2541 | ||||||||||||||||||||||||
699 | /* The backup process p has already copied page iPage. But now it | - | ||||||||||||||||||||||||
700 | ** has been modified by a transaction on the source pager. Copy | - | ||||||||||||||||||||||||
701 | ** the new data into the backup. | - | ||||||||||||||||||||||||
702 | */ | - | ||||||||||||||||||||||||
703 | int rc; | - | ||||||||||||||||||||||||
704 | assert( p->pDestDb ); | - | ||||||||||||||||||||||||
705 | sqlite3_mutex_enter(p->pDestDb->mutex); | - | ||||||||||||||||||||||||
706 | rc = backupOnePage(p, iPage, aData, 1); | - | ||||||||||||||||||||||||
707 | sqlite3_mutex_leave(p->pDestDb->mutex); | - | ||||||||||||||||||||||||
708 | assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); | - | ||||||||||||||||||||||||
709 | if( rc!=SQLITE_OK ){
| 0-1465 | ||||||||||||||||||||||||
710 | p->rc = rc; | - | ||||||||||||||||||||||||
711 | } never executed: end of block | 0 | ||||||||||||||||||||||||
712 | } executed 1465 times by 1 test: end of block Executed by:
| 1465 | ||||||||||||||||||||||||
713 | }while( (p = p->pNext)!=0 ); executed 2541 times by 1 test: end of block Executed by:
| 0-2541 | ||||||||||||||||||||||||
714 | } executed 2541 times by 1 test: end of block Executed by:
| 2541 | ||||||||||||||||||||||||
715 | void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){ | - | ||||||||||||||||||||||||
716 | if( pBackup ) backupUpdate(pBackup, iPage, aData); executed 2541 times by 1 test: backupUpdate(pBackup, iPage, aData); Executed by:
| 2541-1492489 | ||||||||||||||||||||||||
717 | } executed 1495030 times by 131 tests: end of block Executed by:
| 1495030 | ||||||||||||||||||||||||
718 | - | |||||||||||||||||||||||||
719 | /* | - | ||||||||||||||||||||||||
720 | ** Restart the backup process. This is called when the pager layer | - | ||||||||||||||||||||||||
721 | ** detects that the database has been modified by an external database | - | ||||||||||||||||||||||||
722 | ** connection. In this case there is no way of knowing which of the | - | ||||||||||||||||||||||||
723 | ** pages that have been copied into the destination database are still | - | ||||||||||||||||||||||||
724 | ** valid and which are not, so the entire process needs to be restarted. | - | ||||||||||||||||||||||||
725 | ** | - | ||||||||||||||||||||||||
726 | ** It is assumed that the mutex associated with the BtShared object | - | ||||||||||||||||||||||||
727 | ** corresponding to the source database is held when this function is | - | ||||||||||||||||||||||||
728 | ** called. | - | ||||||||||||||||||||||||
729 | */ | - | ||||||||||||||||||||||||
730 | void sqlite3BackupRestart(sqlite3_backup *pBackup){ | - | ||||||||||||||||||||||||
731 | sqlite3_backup *p; /* Iterator variable */ | - | ||||||||||||||||||||||||
732 | for(p=pBackup; p; p=p->pNext){
| 64-205694 | ||||||||||||||||||||||||
733 | assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); | - | ||||||||||||||||||||||||
734 | p->iNext = 1; | - | ||||||||||||||||||||||||
735 | } executed 64 times by 1 test: end of block Executed by:
| 64 | ||||||||||||||||||||||||
736 | } executed 205694 times by 438 tests: end of block Executed by:
| 205694 | ||||||||||||||||||||||||
737 | - | |||||||||||||||||||||||||
738 | #ifndef SQLITE_OMIT_VACUUM | - | ||||||||||||||||||||||||
739 | /* | - | ||||||||||||||||||||||||
740 | ** Copy the complete content of pBtFrom into pBtTo. A transaction | - | ||||||||||||||||||||||||
741 | ** must be active for both files. | - | ||||||||||||||||||||||||
742 | ** | - | ||||||||||||||||||||||||
743 | ** The size of file pTo may be reduced by this operation. If anything | - | ||||||||||||||||||||||||
744 | ** goes wrong, the transaction on pTo is rolled back. If successful, the | - | ||||||||||||||||||||||||
745 | ** transaction is committed before returning. | - | ||||||||||||||||||||||||
746 | */ | - | ||||||||||||||||||||||||
747 | int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ | - | ||||||||||||||||||||||||
748 | int rc; | - | ||||||||||||||||||||||||
749 | sqlite3_file *pFd; /* File descriptor for database pTo */ | - | ||||||||||||||||||||||||
750 | sqlite3_backup b; | - | ||||||||||||||||||||||||
751 | sqlite3BtreeEnter(pTo); | - | ||||||||||||||||||||||||
752 | sqlite3BtreeEnter(pFrom); | - | ||||||||||||||||||||||||
753 | - | |||||||||||||||||||||||||
754 | assert( sqlite3BtreeIsInTrans(pTo) ); | - | ||||||||||||||||||||||||
755 | pFd = sqlite3PagerFile(sqlite3BtreePager(pTo)); | - | ||||||||||||||||||||||||
756 | if( pFd->pMethods ){
| 6-492 | ||||||||||||||||||||||||
757 | i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom); | - | ||||||||||||||||||||||||
758 | rc = sqlite3OsFileControl(pFd, SQLITE_FCNTL_OVERWRITE, &nByte); | - | ||||||||||||||||||||||||
759 | if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; executed 492 times by 2 tests: rc = 0; Executed by:
| 0-492 | ||||||||||||||||||||||||
760 | if( rc ) goto copy_finished; never executed: goto copy_finished;
| 0-492 | ||||||||||||||||||||||||
761 | } executed 492 times by 2 tests: end of block Executed by:
| 492 | ||||||||||||||||||||||||
762 | - | |||||||||||||||||||||||||
763 | /* Set up an sqlite3_backup object. sqlite3_backup.pDestDb must be set | - | ||||||||||||||||||||||||
764 | ** to 0. This is used by the implementations of sqlite3_backup_step() | - | ||||||||||||||||||||||||
765 | ** and sqlite3_backup_finish() to detect that they are being called | - | ||||||||||||||||||||||||
766 | ** from this function, not directly by the user. | - | ||||||||||||||||||||||||
767 | */ | - | ||||||||||||||||||||||||
768 | memset(&b, 0, sizeof(b)); | - | ||||||||||||||||||||||||
769 | b.pSrcDb = pFrom->db; | - | ||||||||||||||||||||||||
770 | b.pSrc = pFrom; | - | ||||||||||||||||||||||||
771 | b.pDest = pTo; | - | ||||||||||||||||||||||||
772 | b.iNext = 1; | - | ||||||||||||||||||||||||
773 | - | |||||||||||||||||||||||||
774 | #ifdef SQLITE_HAS_CODEC | - | ||||||||||||||||||||||||
775 | sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom)); | - | ||||||||||||||||||||||||
776 | #endif | - | ||||||||||||||||||||||||
777 | - | |||||||||||||||||||||||||
778 | /* 0x7FFFFFFF is the hard limit for the number of pages in a database | - | ||||||||||||||||||||||||
779 | ** file. By passing this as the number of pages to copy to | - | ||||||||||||||||||||||||
780 | ** sqlite3_backup_step(), we can guarantee that the copy finishes | - | ||||||||||||||||||||||||
781 | ** within a single call (unless an error occurs). The assert() statement | - | ||||||||||||||||||||||||
782 | ** checks this assumption - (p->rc) should be set to either SQLITE_DONE | - | ||||||||||||||||||||||||
783 | ** or an error code. */ | - | ||||||||||||||||||||||||
784 | sqlite3_backup_step(&b, 0x7FFFFFFF); | - | ||||||||||||||||||||||||
785 | assert( b.rc!=SQLITE_OK ); | - | ||||||||||||||||||||||||
786 | - | |||||||||||||||||||||||||
787 | rc = sqlite3_backup_finish(&b); | - | ||||||||||||||||||||||||
788 | if( rc==SQLITE_OK ){
| 130-368 | ||||||||||||||||||||||||
789 | pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; | - | ||||||||||||||||||||||||
790 | }else{ executed 130 times by 2 tests: end of block Executed by:
| 130 | ||||||||||||||||||||||||
791 | sqlite3PagerClearCache(sqlite3BtreePager(b.pDest)); | - | ||||||||||||||||||||||||
792 | } executed 368 times by 1 test: end of block Executed by:
| 368 | ||||||||||||||||||||||||
793 | - | |||||||||||||||||||||||||
794 | assert( sqlite3BtreeIsInTrans(pTo)==0 ); | - | ||||||||||||||||||||||||
795 | copy_finished: code before this statement executed 498 times by 2 tests: copy_finished: Executed by:
| 498 | ||||||||||||||||||||||||
796 | sqlite3BtreeLeave(pFrom); | - | ||||||||||||||||||||||||
797 | sqlite3BtreeLeave(pTo); | - | ||||||||||||||||||||||||
798 | return rc; executed 498 times by 2 tests: return rc; Executed by:
| 498 | ||||||||||||||||||||||||
799 | } | - | ||||||||||||||||||||||||
800 | #endif /* SQLITE_OMIT_VACUUM */ | - | ||||||||||||||||||||||||
Source code | Switch to Preprocessed file |