Exemple #1
0
      public void Clear()
      {
        sqlite3_free(ref this.pData);
        this.pData = null;
        this.pExtra = null;
        this.pDirty = null;
        this.pgno = 0;
        this.pPager = null;
#if SQLITE_CHECK_PAGES
this.pageHash=0;
#endif
        this.flags = 0;
        this.nRef = 0;
        this.pCache = null;
        this.pDirtyNext = null;
        this.pDirtyPrev = null;
        this.pPgHdr1 = null;
      }
Exemple #2
0
    /*
    ** Check that there are at least nSavepoint savepoints open. If there are
    ** currently less than nSavepoints open, then open one or more savepoints
    ** to make up the difference. If the number of savepoints is already
    ** equal to nSavepoint, then this function is a no-op.
    **
    ** If a memory allocation fails, SQLITE_NOMEM is returned. If an error
    ** occurs while opening the sub-journal file, then an IO error code is
    ** returned. Otherwise, SQLITE_OK.
    */
    static int sqlite3PagerOpenSavepoint( Pager pPager, int nSavepoint )
    {
      int rc = SQLITE_OK;                      /* Return code */
      int nCurrent = pPager.nSavepoint;        /* Current number of savepoints */

      if ( nSavepoint > nCurrent && pPager.useJournal != 0 )
      {
        int ii;                 /* Iterator variable */
        PagerSavepoint[] aNew;  /* New Pager.aSavepoint array */

        /* Either there is no active journal or the sub-journal is open or
        ** the journal is always stored in memory */
        Debug.Assert( pPager.nSavepoint == 0 || isOpen( pPager.sjfd ) ||
        pPager.journalMode == PAGER_JOURNALMODE_MEMORY );

        /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM
        ** if the allocation fails. Otherwise, zero the new portion in case a
        ** malloc failure occurs while populating it in the for(...) loop below.
        */
        //aNew = (PagerSavepoint *)sqlite3Realloc(
        //    pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint
        //);
        Array.Resize( ref pPager.aSavepoint, nSavepoint );
        aNew = pPager.aSavepoint;
        //if( null==aNew ){
        //  return SQLITE_NOMEM;
        //}
        // memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint));
        // pPager.aSavepoint = aNew;
        pPager.nSavepoint = nSavepoint;

        /* Populate the PagerSavepoint structures just allocated. */
        for ( ii = nCurrent; ii < nSavepoint; ii++ )
        {
          Debug.Assert( pPager.dbSizeValid );
          aNew[ii] = new PagerSavepoint();
          aNew[ii].nOrig = pPager.dbSize;
          if ( isOpen( pPager.jfd ) && ALWAYS( pPager.journalOff > 0 ) )
          {
            aNew[ii].iOffset = pPager.journalOff;
          }
          else
          {
            aNew[ii].iOffset = (int)JOURNAL_HDR_SZ( pPager );
          }
          aNew[ii].iSubRec = pPager.nSubRec;
          aNew[ii].pInSavepoint = sqlite3BitvecCreate( pPager.dbSize );
          if ( null == aNew[ii].pInSavepoint )
          {
            return SQLITE_NOMEM;
          }
        }

        /* Open the sub-journal, if it is not already opened. */
        rc = openSubJournal( pPager );
        assertTruncateConstraint( pPager );
      }

      return rc;
    }
Exemple #3
0
//# define CODEC2(P,D,N,X,E,O) O=(char*)D
static bool CODEC2( Pager P, byte[] D, uint N, int X, ref byte[] O ) { O = D; return false; }
Exemple #4
0
    // The E parameter is what executes when there is an error, 
    // cannot implement here, since this is not really a macro
    // calling code must be modified to call E when truen

    //# define CODEC2(P,D,N,X,E,O) \
    //if( P.xCodec==0 ){ O=(char*)D; }else \
    //if( (O=(char*)(P.xCodec(P.pCodec,D,N,X)))==0 ){ E; }
    static bool CODEC2( Pager P, byte[] D, uint N, int X, ref byte[] O )
    {
      if ( P.xCodec == null )
      {
        O = D; // do nothing
        return false;
      }
      else
      {
        return ( ( O = P.xCodec( P.pCodec, D, N, X ) ) == null );
      }
    }
Exemple #5
0
    /*
** The following two macros are used within the PAGERTRACE() macros above
** to print out file-descriptors.
**
** PAGERID() takes a pointer to a Pager struct as its argument. The
** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
** struct as its argument.
*/
    //#define PAGERID(p) ((int)(p.fd))
    static int PAGERID( Pager p )
    {
      return p.GetHashCode();
    }
Exemple #6
0
 static sqlite3_file sqlite3Pager_get_fd( Pager pPager )
 {
   return ( isOpen( pPager.fd ) ) ? pPager.fd : null;
 }
Exemple #7
0
 /* BEGIN CRYPTO */
 static void sqlite3pager_get_codec( Pager pPager, ref codec_ctx ctx )
 {
   ctx = pPager.pCodec;
 }
Exemple #8
0
    /*
    ** The journal file must be open when this function is called.
    **
    ** This function is a no-op if the journal file has not been written to
    ** within the current transaction (i.e. if Pager.journalOff==0).
    **
    ** If doTruncate is non-zero or the Pager.journalSizeLimit variable is
    ** set to 0, then truncate the journal file to zero bytes in size. Otherwise,
    ** zero the 28-byte header at the start of the journal file. In either case,
    ** if the pager is not in no-sync mode, sync the journal file immediately
    ** after writing or truncating it.
    **
    ** If Pager.journalSizeLimit is set to a positive, non-zero value, and
    ** following the truncation or zeroing described above the size of the
    ** journal file in bytes is larger than this value, then truncate the
    ** journal file to Pager.journalSizeLimit bytes. The journal file does
    ** not need to be synced following this operation.
    **
    ** If an IO error occurs, abandon processing and return the IO error code.
    ** Otherwise, return SQLITE_OK.
    */
    static int zeroJournalHdr( Pager pPager, int doTruncate )
    {
      int rc = SQLITE_OK;                               /* Return code */
      Debug.Assert( isOpen( pPager.jfd ) );

      if ( pPager.journalOff != 0 )
      {
        i64 iLimit = pPager.journalSizeLimit;           /* Local cache of jsl */
        IOTRACE( "JZEROHDR %p\n", pPager );
        if ( doTruncate != 0 || iLimit == 0 )
        {
          rc = sqlite3OsTruncate( pPager.jfd, 0 );
        }
        else
        {
          byte[] zeroHdr = new byte[28];// = {0};
          rc = sqlite3OsWrite( pPager.jfd, zeroHdr, zeroHdr.Length, 0 );
        }
        if ( rc == SQLITE_OK && !pPager.noSync )
        {
          rc = sqlite3OsSync( pPager.jfd, SQLITE_SYNC_DATAONLY | pPager.sync_flags );
        }

        /* At this point the transaction is committed but the write lock
        ** is still held on the file. If there is a size limit configured for
        ** the persistent journal and the journal file currently consumes more
        ** space than that limit allows for, truncate it now. There is no need
        ** to sync the file following this operation.
        */
        if ( rc == SQLITE_OK && iLimit > 0 )
        {
          i64  sz = 0;
          rc = sqlite3OsFileSize( pPager.jfd, ref sz );
          if ( rc == SQLITE_OK && sz > iLimit )
          {
            rc = sqlite3OsTruncate( pPager.jfd, iLimit );
          }
        }
      }
      return rc;
    }
Exemple #9
0
/*
** Set or retrieve the codec for this pager
*/
    static void sqlite3PagerSetCodec(
    Pager pPager,
    dxCodec xCodec,                 //void *(*xCodec)(void*,void*,Pgno,int),
    dxCodecSizeChng xCodecSizeChng, //void (*xCodecSizeChng)(void*,int,int),
    dxCodecFree xCodecFree,         //void (*xCodecFree)(void*),
    codec_ctx pCodec
    )
    {
      if ( pPager.xCodecFree != null ) pPager.xCodecFree( ref pPager.pCodec );
      pPager.xCodec = (pPager.memDb!=0) ? null : xCodec;
      pPager.xCodecSizeChng = xCodecSizeChng;
      pPager.xCodecFree = xCodecFree;
      pPager.pCodec = pCodec;
      pagerReportSize( pPager );
    }
Exemple #10
0
 /*
 ** Return true if fsync() calls are disabled for this pager.  Return FALSE
 ** if fsync()s are executed normally.
 */
 static bool sqlite3PagerNosync( Pager pPager )
 {
   return pPager.noSync;
 }
Exemple #11
0
 /*
 ** Return the full pathname of the journal file.
 */
 static string sqlite3PagerJournalname( Pager pPager )
 {
   return pPager.zJournal;
 }
Exemple #12
0
 /*
 ** Return the file handle for the database file associated
 ** with the pager.  This might return NULL if the file has
 ** not yet been opened.
 */
 static sqlite3_file sqlite3PagerFile( Pager pPager )
 {
   return pPager.fd;
 }
Exemple #13
0
 /*
 ** Return the VFS structure for the pager.
 */
 static sqlite3_vfs sqlite3PagerVfs( Pager pPager )
 {
   return pPager.pVfs;
 }
Exemple #14
0
 /*
 ** Return the full pathname of the database file.
 */
 static string sqlite3PagerFilename( Pager pPager )
 {
   return pPager.zFilename;
 }
Exemple #15
0
    /*
    ** This function is called to rollback or release (commit) a savepoint.
    ** The savepoint to release or rollback need not be the most recently
    ** created savepoint.
    **
    ** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE.
    ** If it is SAVEPOINT_RELEASE, then release and destroy the savepoint with
    ** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes
    ** that have occurred since the specified savepoint was created.
    **
    ** The savepoint to rollback or release is identified by parameter
    ** iSavepoint. A value of 0 means to operate on the outermost savepoint
    ** (the first created). A value of (Pager.nSavepoint-1) means operate
    ** on the most recently created savepoint. If iSavepoint is greater than
    ** (Pager.nSavepoint-1), then this function is a no-op.
    **
    ** If a negative value is passed to this function, then the current
    ** transaction is rolled back. This is different to calling
    ** sqlite3PagerRollback() because this function does not terminate
    ** the transaction or unlock the database, it just restores the
    ** contents of the database to its original state.
    **
    ** In any case, all savepoints with an index greater than iSavepoint
    ** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE),
    ** then savepoint iSavepoint is also destroyed.
    **
    ** This function may return SQLITE_NOMEM if a memory allocation fails,
    ** or an IO error code if an IO error occurs while rolling back a
    ** savepoint. If no errors occur, SQLITE_OK is returned.
    */
    static int sqlite3PagerSavepoint( Pager pPager, int op, int iSavepoint )
    {
      int rc = SQLITE_OK;

      Debug.Assert( op == SAVEPOINT_RELEASE || op == SAVEPOINT_ROLLBACK );
      Debug.Assert( iSavepoint >= 0 || op == SAVEPOINT_ROLLBACK );

      if ( iSavepoint < pPager.nSavepoint )
      {
        int ii;        /* Iterator variable */
        int nNew;      /* Number of remaining savepoints after this op. */

        /* Figure out how many savepoints will still be active after this
        ** operation. Store this value in nNew. Then free resources associated
        ** with any savepoints that are destroyed by this operation.
        */
        nNew = iSavepoint + ((op == SAVEPOINT_RELEASE) ? 0 : 1);
        for (ii = nNew; ii < pPager.nSavepoint; ii++)
        {
          sqlite3BitvecDestroy( ref pPager.aSavepoint[ii].pInSavepoint );
        }
        pPager.nSavepoint = nNew;

        /* If this is a release of the outermost savepoint, truncate 
        ** the sub-journal to zero bytes in size. */
        if (op == SAVEPOINT_RELEASE)
        {
          if (nNew == 0 && isOpen(pPager.sjfd))
          {
            /* Only truncate if it is an in-memory sub-journal. */
            if (sqlite3IsMemJournal(pPager.sjfd))
            {
              rc = sqlite3OsTruncate(pPager.sjfd, 0);
              Debug.Assert(rc == SQLITE_OK);
            }
            pPager.nSubRec = 0;
          }
        }
        /* Else this is a rollback operation, playback the specified savepoint.
        ** If this is a temp-file, it is possible that the journal file has
        ** not yet been opened. In this case there have been no changes to
        ** the database file, so the playback operation can be skipped.
        */
        else if ( isOpen( pPager.jfd ) )
        {
          PagerSavepoint pSavepoint = ( nNew == 0 ) ? null : pPager.aSavepoint[nNew - 1];
          rc = pagerPlaybackSavepoint( pPager, pSavepoint );
          Debug.Assert( rc != SQLITE_DONE );
        }
      }
      return rc;
    }
Exemple #16
0
 /*
 ** Return the offset of the sector boundary at or immediately
 ** following the value in pPager.journalOff, assuming a sector
 ** size of pPager.sectorSize bytes.
 **
 ** i.e for a sector size of 512:
 **
 **   Pager.journalOff          Return value
 **   ---------------------------------------
 **   0                         0
 **   512                       512
 **   100                       512
 **   2000                      2048
 **
 */
 static i64 journalHdrOffset( Pager pPager )
 {
   i64 offset = 0;
   i64 c = pPager.journalOff;
   if ( c != 0 )
   {
     offset = (int)( ( ( c - 1 ) / pPager.sectorSize + 1 ) * pPager.sectorSize );//offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager);
   }
   Debug.Assert( offset % pPager.sectorSize == 0 ); //Debug.Assert(offset % JOURNAL_HDR_SZ(pPager) == 0);
   Debug.Assert( offset >= c );
   Debug.Assert( ( offset - c ) < pPager.sectorSize );//Debug.Assert( (offset-c)<JOURNAL_HDR_SZ(pPager) );
   return offset;
 }
Exemple #17
0
 static void seekJournalHdr( Pager pPager )
 {
   pPager.journalOff = journalHdrOffset( pPager );
 }
Exemple #18
0
 static object sqlite3PagerGetCodec( Pager pPager )
 {
   return pPager.pCodec;
 }
Exemple #19
0
    /*
    ** The journal file must be open when this routine is called. A journal
    ** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the
    ** current location.
    **
    ** The format for the journal header is as follows:
    ** - 8 bytes: Magic identifying journal format.
    ** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.
    ** - 4 bytes: Random number used for page hash.
    ** - 4 bytes: Initial database page count.
    ** - 4 bytes: Sector size used by the process that wrote this journal.
    ** - 4 bytes: Database page size.
    **
    ** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
    */
    static int writeJournalHdr( Pager pPager )
    {

      int rc = SQLITE_OK;                 /* Return code */
      byte[] zHeader = pPager.pTmpSpace;  /* Temporary space used to build header */
      u32 nHeader = (u32)pPager.pageSize; /* Size of buffer pointed to by zHeader */
      u32 nWrite;                         /* Bytes of header sector written */
      int ii;                             /* Loop counter */

      Debug.Assert( isOpen( pPager.jfd ) );      /* Journal file must be open. */

      if ( nHeader > JOURNAL_HDR_SZ( pPager ) )
      {
        nHeader = JOURNAL_HDR_SZ( pPager );
      }
      /* If there are active savepoints and any of them were created
      ** since the most recent journal header was written, update the
      ** PagerSavepoint.iHdrOffset fields now.
      */
      for ( ii = 0; ii < pPager.nSavepoint; ii++ )
      {
        if ( pPager.aSavepoint[ii].iHdrOffset == 0 )
        {
          pPager.aSavepoint[ii].iHdrOffset = pPager.journalOff;
        }
      }
      pPager.journalHdr = pPager.journalOff = journalHdrOffset( pPager );

      /*
      ** Write the nRec Field - the number of page records that follow this
      ** journal header. Normally, zero is written to this value at this time.
      ** After the records are added to the journal (and the journal synced,
      ** if in full-sync mode), the zero is overwritten with the true number
      ** of records (see syncJournal()).
      **
      ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When
      ** reading the journal this value tells SQLite to assume that the
      ** rest of the journal file contains valid page records. This assumption
      ** is dangerous, as if a failure occurred whilst writing to the journal
      ** file it may contain some garbage data. There are two scenarios
      ** where this risk can be ignored:
      **
      **   * When the pager is in no-sync mode. Corruption can follow a
      **     power failure in this case anyway.
      **
      **   * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees
      **     that garbage data is never appended to the journal file.
      */
      Debug.Assert( isOpen( pPager.fd ) || pPager.noSync );
      if ( ( pPager.noSync ) || ( pPager.journalMode == PAGER_JOURNALMODE_MEMORY )
      || ( sqlite3OsDeviceCharacteristics( pPager.fd ) & SQLITE_IOCAP_SAFE_APPEND ) != 0
      )
      {
        aJournalMagic.CopyTo( zHeader, 0 );// memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
        put32bits( zHeader, aJournalMagic.Length, 0xffffffff );
      }
      else
      {
        Array.Clear( zHeader, 0, aJournalMagic.Length + 4 );//memset(zHeader, 0, sizeof(aJournalMagic)+4);
      }

      /* The random check-hash initialiser */
      i64 i64Temp = 0;
      sqlite3_randomness( sizeof( i64 ), ref i64Temp );
      pPager.cksumInit = (u32)i64Temp;
      put32bits( zHeader, aJournalMagic.Length + 4, pPager.cksumInit );
      /* The initial database size */
      put32bits( zHeader, aJournalMagic.Length + 8, pPager.dbOrigSize );
      /* The assumed sector size for this process */
      put32bits( zHeader, aJournalMagic.Length + 12, pPager.sectorSize );
      /* The page size */
      put32bits( zHeader, aJournalMagic.Length + 16, (u32)pPager.pageSize );

      /* Initializing the tail of the buffer is not necessary.  Everything
      ** works find if the following memset() is omitted.  But initializing
      ** the memory prevents valgrind from complaining, so we are willing to
      ** take the performance hit.
      */
      //  memset(&zHeader[sizeof(aJournalMagic)+20], 0,
      //  nHeader-(sizeof(aJournalMagic)+20));
      Array.Clear( zHeader, aJournalMagic.Length + 20, (int)nHeader - ( aJournalMagic.Length + 20 ) );

      /* In theory, it is only necessary to write the 28 bytes that the
      ** journal header consumes to the journal file here. Then increment the
      ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next
      ** record is written to the following sector (leaving a gap in the file
      ** that will be implicitly filled in by the OS).
      **
      ** However it has been discovered that on some systems this pattern can
      ** be significantly slower than contiguously writing data to the file,
      ** even if that means explicitly writing data to the block of
      ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what
      ** is done.
      **
      ** The loop is required here in case the sector-size is larger than the
      ** database page size. Since the zHeader buffer is only Pager.pageSize
      ** bytes in size, more than one call to sqlite3OsWrite() may be required
      ** to populate the entire journal header sector.
      */
      for ( nWrite = 0; rc == SQLITE_OK && nWrite < JOURNAL_HDR_SZ( pPager ); nWrite += nHeader )
      {
        IOTRACE( "JHDR %p %lld %d\n", pPager, pPager.journalHdr, nHeader );
        rc = sqlite3OsWrite( pPager.jfd, zHeader, (int)nHeader, pPager.journalOff );
        pPager.journalOff += (int)nHeader;
      }
      return rc;
    }
Exemple #20
0
    /*
** Move the page pPg to location pgno in the file.
**
** There must be no references to the page previously located at
** pgno (which we call pPgOld) though that page is allowed to be
** in cache.  If the page previously located at pgno is not already
** in the rollback journal, it is not put there by by this routine.
**
** References to the page pPg remain valid. Updating any
** meta-data associated with pPg (i.e. data stored in the nExtra bytes
** allocated along with the page) is the responsibility of the caller.
**
** A transaction must be active when this routine is called. It used to be
** required that a statement transaction was not active, but this restriction
** has been removed (CREATE INDEX needs to move a page when a statement
** transaction is active).
**
** If the fourth argument, isCommit, is non-zero, then this page is being
** moved as part of a database reorganization just before the transaction
** is being committed. In this case, it is guaranteed that the database page
** pPg refers to will not be written to again within this transaction.
**
** This function may return SQLITE_NOMEM or an IO error code if an error
** occurs. Otherwise, it returns SQLITE_OK.
*/
    static int sqlite3PagerMovepage( Pager pPager, DbPage pPg, u32 pgno, int isCommit )
    {
      PgHdr pPgOld;                /* The page being overwritten. */
      u32 needSyncPgno = 0;        /* Old value of pPg.pgno, if sync is required */
      int rc;                      /* Return code */
      Pgno origPgno;               /* The original page number */

      Debug.Assert( pPg.nRef > 0 );

      /* In order to be able to rollback, an in-memory database must journal
      ** the page we are moving from.
      */
      if (
#if SQLITE_OMIT_MEMORYDB
1==MEMDB
#else
 pPager.memDb != 0
#endif
 )
      {
        rc = sqlite3PagerWrite( pPg );
        if ( rc != 0 ) return rc;
      }

      /* If the page being moved is dirty and has not been saved by the latest
      ** savepoint, then save the current contents of the page into the
      ** sub-journal now. This is required to handle the following scenario:
      **
      **   BEGIN;
      **     <journal page X, then modify it in memory>
      **     SAVEPOINT one;
      **       <Move page X to location Y>
      **     ROLLBACK TO one;
      **
      ** If page X were not written to the sub-journal here, it would not
      ** be possible to restore its contents when the "ROLLBACK TO one"
      ** statement were is processed.
      **
      ** subjournalPage() may need to allocate space to store pPg.pgno into
      ** one or more savepoint bitvecs. This is the reason this function
      ** may return SQLITE_NOMEM.
      */
      if ( ( pPg.flags & PGHDR_DIRTY ) != 0
      && subjRequiresPage( pPg )
      && SQLITE_OK != ( rc = subjournalPage( pPg ) )
      )
      {
        return rc;
      }

      PAGERTRACE( "MOVE %d page %d (needSync=%d) moves to %d\n",
      PAGERID( pPager ), pPg.pgno, ( pPg.flags & PGHDR_NEED_SYNC ) != 0 ? 1 : 0, pgno );
      IOTRACE( "MOVE %p %d %d\n", pPager, pPg.pgno, pgno );

      /* If the journal needs to be sync()ed before page pPg.pgno can
      ** be written to, store pPg.pgno in local variable needSyncPgno.
      **
      ** If the isCommit flag is set, there is no need to remember that
      ** the journal needs to be sync()ed before database page pPg.pgno
      ** can be written to. The caller has already promised not to write to it.
      */
      if ( ( ( pPg.flags & PGHDR_NEED_SYNC ) != 0 ) && 0 == isCommit )
      {
        needSyncPgno = pPg.pgno;
        Debug.Assert( pageInJournal( pPg ) || pPg.pgno > pPager.dbOrigSize );
        Debug.Assert( ( pPg.flags & PGHDR_DIRTY ) != 0 );
        Debug.Assert( pPager.needSync );
      }

      /* If the cache contains a page with page-number pgno, remove it
      ** from its hash chain. Also, if the PgHdr.needSync was set for
      ** page pgno before the 'move' operation, it needs to be retained
      ** for the page moved there.
      */
      pPg.flags &= ~PGHDR_NEED_SYNC;
      pPgOld = pager_lookup( pPager, pgno );
      Debug.Assert( null == pPgOld || pPgOld.nRef == 1 );
      if ( pPgOld != null )
      {
        pPg.flags |= ( pPgOld.flags & PGHDR_NEED_SYNC );
        if (
#if SQLITE_OMIT_MEMORYDB
1==MEMDB
#else
 pPager.memDb != 0
#endif
 )
        {
          /* Do not discard pages from an in-memory database since we might
          ** need to rollback later.  Just move the page out of the way. */
          Debug.Assert( pPager.dbSizeValid );
          sqlite3PcacheMove( pPgOld, pPager.dbSize + 1 );
        }
        else
        {
          sqlite3PcacheDrop( pPgOld );
        }
      }
      origPgno = pPg.pgno;
      sqlite3PcacheMove( pPg, pgno );
      sqlite3PcacheMakeDirty( pPg );
      pPager.dbModified = true;

      if ( needSyncPgno != 0 )
      {
        /* If needSyncPgno is non-zero, then the journal file needs to be
        ** sync()ed before any data is written to database file page needSyncPgno.
        ** Currently, no such page exists in the page-cache and the
        ** "is journaled" bitvec flag has been set. This needs to be remedied by
        ** loading the page into the pager-cache and setting the PgHdr.needSync
        ** flag.
        **
        ** If the attempt to load the page into the page-cache fails, (due
        ** to a malloc() or IO failure), clear the bit in the pInJournal[]
        ** array. Otherwise, if the page is loaded and written again in
        ** this transaction, it may be written to the database file before
        ** it is synced into the journal file. This way, it may end up in
        ** the journal file twice, but that is not a problem.
        **
        ** The sqlite3PagerGet() call may cause the journal to sync. So make
        ** sure the Pager.needSync flag is set too.
        */
        PgHdr pPgHdr = null;
        Debug.Assert( pPager.needSync );
        rc = sqlite3PagerGet( pPager, needSyncPgno, ref pPgHdr );
        if ( rc != SQLITE_OK )
        {
          if ( needSyncPgno <= pPager.dbOrigSize )
          {
            Debug.Assert( pPager.pTmpSpace != null );
            u32[] pTemp = new u32[pPager.pTmpSpace.Length];
            sqlite3BitvecClear( pPager.pInJournal, needSyncPgno, pTemp );//pPager.pTmpSpace );
          }
          return rc;
        }
        pPager.needSync = true;
        Debug.Assert( pPager.noSync == false &&
#if SQLITE_OMIT_MEMORYDB
0==MEMDB
#else
 0 == pPager.memDb
#endif
 );
        pPgHdr.flags |= PGHDR_NEED_SYNC;
        sqlite3PcacheMakeDirty( pPgHdr );
        sqlite3PagerUnref( pPgHdr );
      }

      /*
      ** For an in-memory database, make sure the original page continues
      ** to exist, in case the transaction needs to roll back.  Use pPgOld
      ** as the original page since it has already been allocated.
      */
      if (
#if SQLITE_OMIT_MEMORYDB
MEMDB != 0
#else
 pPager.memDb != 0
#endif
 )
      {
        sqlite3PcacheMove( pPgOld, origPgno );
        sqlite3PagerUnref( pPgOld );
      }
      return SQLITE_OK;
    }
Exemple #21
0
 static int sqlite3pager_is_mj_pgno( Pager pPager, Pgno pgno )
 {
   return ( PAGER_MJ_PGNO( pPager ) == pgno ) ? 1 : 0;
 }
Exemple #22
0
 /*
 ** Get/set the locking-mode for this pager. Parameter eMode must be one
 ** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or
 ** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then
 ** the locking-mode is set to the value specified.
 **
 ** The returned value is either PAGER_LOCKINGMODE_NORMAL or
 ** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated)
 ** locking-mode.
 */
 static bool sqlite3PagerLockingMode( Pager pPager, int eMode )
 {
   Debug.Assert( eMode == PAGER_LOCKINGMODE_QUERY
   || eMode == PAGER_LOCKINGMODE_NORMAL
   || eMode == PAGER_LOCKINGMODE_EXCLUSIVE );
   Debug.Assert( PAGER_LOCKINGMODE_QUERY < 0 );
   Debug.Assert( PAGER_LOCKINGMODE_NORMAL >= 0 && PAGER_LOCKINGMODE_EXCLUSIVE >= 0 );
   if ( eMode >= 0 && !pPager.tempFile )
   {
     pPager.exclusiveMode = eMode != 0;
   }
   return pPager.exclusiveMode;
 }
Exemple #23
0
 static void sqlite3pager_sqlite3PagerSetCodec(
 Pager pPager,
 dxCodec xCodec,
 dxCodecSizeChng xCodecSizeChng,
 dxCodecFree xCodecFree,
 codec_ctx pCodec
 )
 {
   sqlite3PagerSetCodec( pPager, xCodec, xCodecSizeChng, xCodecFree, pCodec );
 }
Exemple #24
0
    /*
    ** Get/set the journal-mode for this pager. Parameter eMode must be one of:
    **
    **    PAGER_JOURNALMODE_QUERY
    **    PAGER_JOURNALMODE_DELETE
    **    PAGER_JOURNALMODE_TRUNCATE
    **    PAGER_JOURNALMODE_PERSIST
    **    PAGER_JOURNALMODE_OFF
    **    PAGER_JOURNALMODE_MEMORY
    **
    ** If the parameter is not _QUERY, then the journal_mode is set to the
    ** value specified if the change is allowed.  The change is disallowed
    ** for the following reasons:
    **
    **   *  An in-memory database can only have its journal_mode set to _OFF
    **      or _MEMORY.
    **
    **   *  The journal mode may not be changed while a transaction is active.
    **
    ** The returned indicate the current (possibly updated) journal-mode.
    */
    static int sqlite3PagerJournalMode( Pager pPager, int eMode )
    {
      Debug.Assert( eMode == PAGER_JOURNALMODE_QUERY
      || eMode == PAGER_JOURNALMODE_DELETE
      || eMode == PAGER_JOURNALMODE_TRUNCATE
      || eMode == PAGER_JOURNALMODE_PERSIST
      || eMode == PAGER_JOURNALMODE_OFF
      || eMode == PAGER_JOURNALMODE_MEMORY );
      Debug.Assert( PAGER_JOURNALMODE_QUERY < 0 );
      if ( eMode >= 0
      && (
#if SQLITE_OMIT_MEMORYDB
0==MEMDB
#else
 0 == pPager.memDb
#endif
 || eMode == PAGER_JOURNALMODE_MEMORY
      || eMode == PAGER_JOURNALMODE_OFF )
      && !pPager.dbModified
      && ( !isOpen( pPager.jfd ) || 0 == pPager.journalOff )
      )
      {
        if ( isOpen( pPager.jfd ) )
        {
          sqlite3OsClose( pPager.jfd );
        }
        pPager.journalMode = (u8)eMode;
      }
      return (int)pPager.journalMode;
    }
Exemple #25
0
    /*
    ** A macro used for invoking the codec if there is one
    */

    // The E parameter is what executes when there is an error, 
    // cannot implement here, since this is not really a macro
    // calling code must be modified to call E when truen

#if SQLITE_HAS_CODEC
    //# define CODEC1(P,D,N,X,E) \
    //if( P.xCodec && P.xCodec(P.pCodec,D,N,X)==0 ){ E; }
    static bool CODEC1( Pager P, byte[] D, uint N /* page number */, int X /* E (moved to caller */)
    {
      return ( ( P.xCodec != null ) && ( P.xCodec( P.pCodec, D, N, X ) == null ) );
    }
Exemple #26
0
 /*
 ** Get/set the size-limit used for persistent journal files.
 **
 ** Setting the size limit to -1 means no limit is enforced.
 ** An attempt to set a limit smaller than -1 is a no-op.
 */
 static i64 sqlite3PagerJournalSizeLimit( Pager pPager, i64 iLimit )
 {
   if ( iLimit >= -1 )
   {
     pPager.journalSizeLimit = iLimit;
   }
   return pPager.journalSizeLimit;
 }
Exemple #27
0
//# define CODEC1(P,D,N,X,E)   /* NO-OP */
static bool CODEC1 (Pager P, byte[] D, uint N /* page number */, int X /* E (moved to caller */)  { return false; }
Exemple #28
0
 /*
 ** Return a pointer to the pPager.pBackup variable. The backup module
 ** in backup.c maintains the content of this variable. This module
 ** uses it opaquely as an argument to sqlite3BackupRestart() and
 ** sqlite3BackupUpdate() only.
 */
 static sqlite3_backup sqlite3PagerBackupPtr( Pager pPager )
 {
   return pPager.pBackup;
 }
Exemple #29
0
    const int SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT = -1;//#define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1
#endif

    /*
** The type used to represent a page number.  The first page in a file
** is called page 1.  0 is used to represent "not a page".
*/
    //typedef u32 Pgno;

    /*
    ** Each open file is managed by a separate instance of the "Pager" structure.
    */
    //typedef struct Pager Pager;

    /*
    ** Handle type for pages.
    */
    //typedef struct PgHdr DbPage;

    /*
    ** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
    ** reserved for working around a windows/posix incompatibility). It is
    ** used in the journal to signify that the remainder of the journal file
    ** is devoted to storing a master journal name - there are no more pages to
    ** roll back. See comments for function writeMasterJournal() in pager.c
    ** for details.
    */
    //#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
    static Pgno PAGER_MJ_PGNO( Pager x )
    {
      return ( (Pgno)( ( PENDING_BYTE / ( ( x ).pageSize ) ) + 1 ) );
    }
Exemple #30
0
    /*
    ** This function determines whether or not the atomic-write optimization
    ** can be used with this pager. The optimization can be used if:
    **
    **  (a) the value returned by OsDeviceCharacteristics() indicates that
    **      a database page may be written atomically, and
    **  (b) the value returned by OsSectorSize() is less than or equal
    **      to the page size.
    **
    ** The optimization is also always enabled for temporary files. It is
    ** an error to call this function if pPager is opened on an in-memory
    ** database.
    **
    ** If the optimization cannot be used, 0 is returned. If it can be used,
    ** then the value returned is the size of the journal file when it
    ** contains rollback data for exactly one page.
    */
#if SQLITE_ENABLE_ATOMIC_WRITE
static int jrnlBufferSize(Pager *pPager){
assert( 0==MEMDB );
if( !pPager.tempFile ){
int dc;                           /* Device characteristics */
int nSector;                      /* Sector size */
int szPage;                       /* Page size */

assert( isOpen(pPager.fd) );
dc = sqlite3OsDeviceCharacteristics(pPager.fd);
nSector = pPager.sectorSize;
szPage = pPager.pageSize;

assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){
return 0;
}
}

return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
}