wasCSharpSQLite – Blame information for rev 1

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