⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 backup.c

📁 sqlite最新源码
💻 C
📖 第 1 页 / 共 2 页
字号:
      p->bDestLocked = 1;      rc = sqlite3BtreeGetMeta(p->pDest, 1, &p->iDestSchema);    }    /* If there is no open read-transaction on the source database, open    ** one now. If a transaction is opened here, then it will be closed    ** before this function exits.    */    if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){      rc = sqlite3BtreeBeginTrans(p->pSrc, 0);      bCloseTrans = 1;    }      /* Now that there is a read-lock on the source database, query the    ** source pager for the number of pages in the database.    */    if( rc==SQLITE_OK ){      rc = sqlite3PagerPagecount(pSrcPager, &nSrcPage);    }    for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){      const Pgno iSrcPg = p->iNext;                 /* Source page number */      if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){        DbPage *pSrcPg;                             /* Source page object */        rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);        if( rc==SQLITE_OK ){          rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg));          sqlite3PagerUnref(pSrcPg);        }      }      p->iNext++;    }    if( rc==SQLITE_OK ){      p->nPagecount = nSrcPage;      p->nRemaining = nSrcPage+1-p->iNext;      if( p->iNext>(Pgno)nSrcPage ){        rc = SQLITE_DONE;      }    }      if( rc==SQLITE_DONE ){      const int nSrcPagesize = sqlite3BtreeGetPageSize(p->pSrc);      const int nDestPagesize = sqlite3BtreeGetPageSize(p->pDest);      int nDestTruncate;        /* Update the schema version field in the destination database. This      ** is to make sure that the schema-version really does change in      ** the case where the source and destination databases have the      ** same schema version.      */      sqlite3BtreeUpdateMeta(p->pDest, 1, p->iDestSchema+1);      if( p->pDestDb ){        sqlite3ResetInternalSchema(p->pDestDb, 0);      }      /* Set nDestTruncate to the final number of pages in the destination      ** database. The complication here is that the destination page      ** size may be different to the source page size.       **      ** If the source page size is smaller than the destination page size,       ** round up. In this case the call to sqlite3OsTruncate() below will      ** fix the size of the file. However it is important to call      ** sqlite3PagerTruncateImage() here so that any pages in the       ** destination file that lie beyond the nDestTruncate page mark are      ** journalled by PagerCommitPhaseOne() before they are destroyed      ** by the file truncation.      */      if( nSrcPagesize<nDestPagesize ){        int ratio = nDestPagesize/nSrcPagesize;        nDestTruncate = (nSrcPage+ratio-1)/ratio;        if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){          nDestTruncate--;        }      }else{        nDestTruncate = nSrcPage * (nSrcPagesize/nDestPagesize);      }      sqlite3PagerTruncateImage(pDestPager, nDestTruncate);      if( nSrcPagesize<nDestPagesize ){        /* If the source page-size is smaller than the destination page-size,        ** two extra things may need to happen:        **        **   * The destination may need to be truncated, and        **        **   * Data stored on the pages immediately following the         **     pending-byte page in the source database may need to be        **     copied into the destination database.        */        const i64 iSize = (i64)nSrcPagesize * (i64)nSrcPage;        sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);        assert( pFile );        assert( (i64)nDestTruncate*(i64)nDestPagesize >= iSize || (              nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)           && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+nDestPagesize        ));        if( SQLITE_OK==(rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1))         && SQLITE_OK==(rc = backupTruncateFile(pFile, iSize))         && SQLITE_OK==(rc = sqlite3PagerSync(pDestPager))        ){          i64 iOff;          i64 iEnd = MIN(PENDING_BYTE + nDestPagesize, iSize);          for(            iOff=PENDING_BYTE+nSrcPagesize;             rc==SQLITE_OK && iOff<iEnd;             iOff+=nSrcPagesize          ){            PgHdr *pSrcPg = 0;            const Pgno iSrcPg = (Pgno)((iOff/nSrcPagesize)+1);            rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);            if( rc==SQLITE_OK ){              u8 *zData = sqlite3PagerGetData(pSrcPg);              rc = sqlite3OsWrite(pFile, zData, nSrcPagesize, iOff);            }            sqlite3PagerUnref(pSrcPg);          }        }      }else{        rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);      }        /* Finish committing the transaction to the destination database. */      if( SQLITE_OK==rc       && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest))      ){        rc = SQLITE_DONE;      }    }      /* If bCloseTrans is true, then this function opened a read transaction    ** on the source database. Close the read transaction here. There is    ** no need to check the return values of the btree methods here, as    ** "committing" a read-only transaction cannot fail.    */    if( bCloseTrans ){      TESTONLY( int rc2 );      TESTONLY( rc2  = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0);      TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc);      assert( rc2==SQLITE_OK );    }      p->rc = rc;  }  if( p->pDestDb ){    sqlite3_mutex_leave(p->pDestDb->mutex);  }  sqlite3BtreeLeave(p->pSrc);  sqlite3_mutex_leave(p->pSrcDb->mutex);  return rc;}/*** Release all resources associated with an sqlite3_backup* handle.*/int sqlite3_backup_finish(sqlite3_backup *p){  sqlite3_backup **pp;                 /* Ptr to head of pagers backup list */  sqlite3_mutex *mutex;                /* Mutex to protect source database */  int rc;                              /* Value to return */  /* Enter the mutexes */  sqlite3_mutex_enter(p->pSrcDb->mutex);  sqlite3BtreeEnter(p->pSrc);  mutex = p->pSrcDb->mutex;  if( p->pDestDb ){    sqlite3_mutex_enter(p->pDestDb->mutex);  }  /* Detach this backup from the source pager. */  if( p->pDestDb ){    pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));    while( *pp!=p ){      pp = &(*pp)->pNext;    }    *pp = p->pNext;    p->pSrc->nBackup--;  }  /* If a transaction is still open on the Btree, roll it back. */  sqlite3BtreeRollback(p->pDest);  /* Set the error code of the destination database handle. */  rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;  sqlite3Error(p->pDestDb, rc, 0);  /* Exit the mutexes and free the backup context structure. */  if( p->pDestDb ){    sqlite3_mutex_leave(p->pDestDb->mutex);  }  sqlite3BtreeLeave(p->pSrc);  if( p->pDestDb ){    sqlite3_free(p);  }  sqlite3_mutex_leave(mutex);  return rc;}/*** Return the number of pages still to be backed up as of the most recent** call to sqlite3_backup_step().*/int sqlite3_backup_remaining(sqlite3_backup *p){  return p->nRemaining;}/*** Return the total number of pages in the source database as of the most ** recent call to sqlite3_backup_step().*/int sqlite3_backup_pagecount(sqlite3_backup *p){  return p->nPagecount;}/*** This function is called after the contents of page iPage of the** source database have been modified. If page iPage has already been ** copied into the destination database, then the data written to the** destination is now invalidated. The destination copy of iPage needs** to be updated with the new data before the backup operation is** complete.**** It is assumed that the mutex associated with the BtShared object** corresponding to the source database is held when this function is** called.*/void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){  sqlite3_backup *p;                   /* Iterator variable */  for(p=pBackup; p; p=p->pNext){    assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );    if( !isFatalError(p->rc) && iPage<p->iNext ){      /* The backup process p has already copied page iPage. But now it      ** has been modified by a transaction on the source pager. Copy      ** the new data into the backup.      */      int rc = backupOnePage(p, iPage, aData);      assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );      if( rc!=SQLITE_OK ){        p->rc = rc;      }    }  }}/*** Restart the backup process. This is called when the pager layer** detects that the database has been modified by an external database** connection. In this case there is no way of knowing which of the** pages that have been copied into the destination database are still ** valid and which are not, so the entire process needs to be restarted.**** It is assumed that the mutex associated with the BtShared object** corresponding to the source database is held when this function is** called.*/void sqlite3BackupRestart(sqlite3_backup *pBackup){  sqlite3_backup *p;                   /* Iterator variable */  for(p=pBackup; p; p=p->pNext){    assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );    p->iNext = 1;  }}#ifndef SQLITE_OMIT_VACUUM/*** Copy the complete content of pBtFrom into pBtTo.  A transaction** must be active for both files.**** The size of file pTo may be reduced by this operation. If anything ** goes wrong, the transaction on pTo is rolled back. If successful, the ** transaction is committed before returning.*/int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){  int rc;  sqlite3_backup b;  sqlite3BtreeEnter(pTo);  sqlite3BtreeEnter(pFrom);  /* Set up an sqlite3_backup object. sqlite3_backup.pDestDb must be set  ** to 0. This is used by the implementations of sqlite3_backup_step()  ** and sqlite3_backup_finish() to detect that they are being called  ** from this function, not directly by the user.  */  memset(&b, 0, sizeof(b));  b.pSrcDb = pFrom->db;  b.pSrc = pFrom;  b.pDest = pTo;  b.iNext = 1;  /* 0x7FFFFFFF is the hard limit for the number of pages in a database  ** file. By passing this as the number of pages to copy to  ** sqlite3_backup_step(), we can guarantee that the copy finishes   ** within a single call (unless an error occurs). The assert() statement  ** checks this assumption - (p->rc) should be set to either SQLITE_DONE   ** or an error code.  */  sqlite3_backup_step(&b, 0x7FFFFFFF);  assert( b.rc!=SQLITE_OK );  rc = sqlite3_backup_finish(&b);  if( rc==SQLITE_OK ){    pTo->pBt->pageSizeFixed = 0;  }  sqlite3BtreeLeave(pFrom);  sqlite3BtreeLeave(pTo);  return rc;}#endif /* SQLITE_OMIT_VACUUM */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -