// File: /workspace/github_c_makefile_star2_O0/barabo[P]advanced-shell-history/src/sqlite3.c
// Function: pager_playback_one_page
static int pager_playback_one_page(
  Pager *pPager,                /* The pager being played back */
  i64 *pOffset,                 /* Offset of record to playback */
  Bitvec *pDone,                /* Bitvec of pages already played back */
  int isMainJrnl,               /* 1 -> main journal. 0 -> sub-journal. */
  int isSavepnt                 /* True for a savepoint rollback */
){
  int rc;
  PgHdr *pPg;                   /* An existing page in the cache */
  Pgno pgno;                    /* The page number of a page in journal */
  u32 cksum;                    /* Checksum used for sanity checking */
  char *aData;                  /* Temporary storage for the page */
  sqlite3_file *jfd;            /* The file descriptor for the journal file */
  int isSynced;                 /* True if journal page is synced */

  assert( (isMainJrnl&~1)==0 );      /* isMainJrnl is 0 or 1 */
  assert( (isSavepnt&~1)==0 );       /* isSavepnt is 0 or 1 */
  assert( isMainJrnl || pDone );     /* pDone always used on sub-journals */
  assert( isSavepnt || pDone==0 );   /* pDone never used on non-savepoint */

  aData = pPager->pTmpSpace;
  assert( aData );         /* Temp storage must have already been allocated */
  assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) );

  /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction 
  ** or savepoint rollback done at the request of the caller) or this is
  ** a hot-journal rollback. If it is a hot-journal rollback, the pager
  ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback
  ** only reads from the main journal, not the sub-journal.
  */
  assert( pPager->eState>=PAGER_WRITER_CACHEMOD
       || (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK)
  );
  assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl );

  /* Read the page number and page data from the journal or sub-journal
  ** file. Return an error code to the caller if an IO error occurs.
  */
  jfd = isMainJrnl ? pPager->jfd : pPager->sjfd;
  rc = read32bits(jfd, *pOffset, &pgno);
  if( rc!=SQLITE_OK ) return rc;
  rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4);
  if( rc!=SQLITE_OK ) return rc;
  *pOffset += pPager->pageSize + 4 + isMainJrnl*4;

  /* Sanity checking on the page.  This is more important that I originally
  ** thought.  If a power failure occurs while the journal is being written,
  ** it could cause invalid data to be written into the journal.  We need to
  ** detect this invalid data (with high probability) and ignore it.
  */
  if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
    assert( !isSavepnt );
    return SQLITE_DONE;
  }
  if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){
    return SQLITE_OK;
  }
  if( isMainJrnl ){
    rc = read32bits(jfd, (*pOffset)-4, &cksum);
    if( rc ) return rc;
    if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){
      return SQLITE_DONE;
    }
  }

  /* If this page has already been played by before during the current
  ** rollback, then don't bother to play it back again.
  */
  if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){
    return rc;
  }

  /* When playing back page 1, restore the nReserve setting
  */
  if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
    pPager->nReserve = ((u8*)aData)[20];
    pagerReportSize(pPager);
  }

  /* If the pager is in CACHEMOD state, then there must be a copy of this
  ** page in the pager cache. In this case just update the pager cache,
  ** not the database file. The page is left marked dirty in this case.
  **
  ** An exception to the above rule: If the database is in no-sync mode
  ** and a page is moved during an incremental vacuum then the page may
  ** not be in the pager cache. Later: if a malloc() or IO error occurs
  ** during a Movepage() call, then the page may not be in the cache
  ** either. So the condition described in the above paragraph is not
  ** assert()able.
  **
  ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the
  ** pager cache if it exists and the main file. The page is then marked 
  ** not dirty. Since this code is only executed in PAGER_OPEN state for
  ** a hot-journal rollback, it is guaranteed that the page-cache is empty
  ** if the pager is in OPEN state.
  **
  ** Ticket #1171:  The statement journal might contain page content that is
  ** different from the page content at the start of the transaction.
  ** This occurs when a page is changed prior to the start of a statement
  ** then changed again within the statement.  When rolling back such a
  ** statement we must not write to the original database unless we know
  ** for certain that original page contents are synced into the main rollback
  ** journal.  Otherwise, a power loss might leave modified data in the
  ** database file without an entry in the rollback journal that can
  ** restore the database to its original form.  Two conditions must be
  ** met before writing to the database files. (1) the database must be
  ** locked.  (2) we know that the original page content is fully synced
  ** in the main journal either because the page is not in cache or else
  ** the page is marked as needSync==0.
  **
  ** 2008-04-14:  When attempting to vacuum a corrupt database file, it
  ** is possible to fail a statement on a database that does not yet exist.
  ** Do not attempt to write if database file has never been opened.
  */
  if( pagerUseWal(pPager) ){
    pPg = 0;
  }else{
    pPg = pager_lookup(pPager, pgno);
  }
  assert( pPg || !MEMDB );
  assert( pPager->eState!=PAGER_OPEN || pPg==0 );
  PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
           PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
           (isMainJrnl?"main-journal":"sub-journal")
  ));
  if( isMainJrnl ){
    isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr);
  }else{
    isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC));
  }
  if( isOpen(pPager->fd)
   && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
   && isSynced
  ){
    i64 ofst = (pgno-1)*(i64)pPager->pageSize;
    testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
    assert( !pagerUseWal(pPager) );
    rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
    if( pgno>pPager->dbFileSize ){
      pPager->dbFileSize = pgno;
    }
    if( pPager->pBackup ){
      CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM);
      sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
      CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData);
    }
  }else if( !isMainJrnl && pPg==0 ){
    /* If this is a rollback of a savepoint and data was not written to
    ** the database and the page is not in-memory, there is a potential
    ** problem. When the page is next fetched by the b-tree layer, it 
    ** will be read from the database file, which may or may not be 
    ** current. 
    **
    ** There are a couple of different ways this can happen. All are quite
    ** obscure. When running in synchronous mode, this can only happen 
    ** if the page is on the free-list at the start of the transaction, then
    ** populated, then moved using sqlite3PagerMovepage().
    **
    ** The solution is to add an in-memory page to the cache containing
    ** the data just read from the sub-journal. Mark the page as dirty 
    ** and if the pager requires a journal-sync, then mark the page as 
    ** requiring a journal-sync before it is written.
    */
    assert( isSavepnt );
    assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 );
    pPager->doNotSpill |= SPILLFLAG_ROLLBACK;
    rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
    assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 );
    pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK;
    if( rc!=SQLITE_OK ) return rc;
    pPg->flags &= ~PGHDR_NEED_READ;
    sqlite3PcacheMakeDirty(pPg);
  }
  if( pPg ){
    /* No page should ever be explicitly rolled back that is in use, except
    ** for page 1 which is held in use in order to keep the lock on the
    ** database active. However such a page may be rolled back as a result
    ** of an internal error resulting in an automatic call to
    ** sqlite3PagerRollback().
    */
    void *pData;
    pData = pPg->pData;
    memcpy(pData, (u8*)aData, pPager->pageSize);
    pPager->xReiniter(pPg);
    if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){
      /* If the contents of this page were just restored from the main 
      ** journal file, then its content must be as they were when the 
      ** transaction was first opened. In this case we can mark the page
      ** as clean, since there will be no need to write it out to the
      ** database.
      **
      ** There is one exception to this rule. If the page is being rolled
      ** back as part of a savepoint (or statement) rollback from an 
      ** unsynced portion of the main journal file, then it is not safe
      ** to mark the page as clean. This is because marking the page as
      ** clean will clear the PGHDR_NEED_SYNC flag. Since the page is
      ** already in the journal file (recorded in Pager.pInJournal) and
      ** the PGHDR_NEED_SYNC flag is cleared, if the page is written to
      ** again within this transaction, it will be marked as dirty but
      ** the PGHDR_NEED_SYNC flag will not be set. It could then potentially
      ** be written out into the database file before its journal file
      ** segment is synced. If a crash occurs during or following this,
      ** database corruption may ensue.
      */
      assert( !pagerUseWal(pPager) );
      sqlite3PcacheMakeClean(pPg);
    }
    pager_set_pagehash(pPg);

    /* If this was page 1, then restore the value of Pager.dbFileVers.
    ** Do this before any decoding. */
    if( pgno==1 ){
      memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
    }

    /* Decode the page just read from disk */
    CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM);
    sqlite3PcacheRelease(pPg);
  }
  return rc;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movl %ecx, -0x24(%rbp)
movl %r8d, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq 0x108(%rax), %rax
movq %rax, -0x48(%rbp)
cmpl $0x0, -0x24(%rbp)
je 0x274d1
movq -0x10(%rbp), %rax
movq 0x50(%rax), %rax
movq %rax, -0x70(%rbp)
jmp 0x274dd
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
leaq -0x3c(%rbp), %rdx
callq 0x287c0
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
je 0x2750d
movl -0x2c(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x278b9
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
movq -0x10(%rbp), %rax
movl 0xbc(%rax), %edx
movq -0x18(%rbp), %rax
movq (%rax), %rcx
addq $0x4, %rcx
callq 0x23e30
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
je 0x27543
movl -0x2c(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x278b9
movq -0x10(%rbp), %rax
movl 0xbc(%rax), %eax
addl $0x4, %eax
movl -0x24(%rbp), %ecx
shll $0x2, %ecx
addl %ecx, %eax
movslq %eax, %rcx
movq -0x18(%rbp), %rax
addq (%rax), %rcx
movq %rcx, (%rax)
cmpl $0x0, -0x3c(%rbp)
je 0x2758e
movl -0x3c(%rbp), %eax
movl %eax, -0x74(%rbp)
movl 0xa9359(%rip), %eax     # 0xd08d0
movq -0x10(%rbp), %rcx
cltd
idivl 0xbc(%rcx)
movl %eax, %ecx
movl -0x74(%rbp), %eax
addl $0x1, %ecx
cmpl %ecx, %eax
jne 0x2759a
movl $0x65, -0x4(%rbp)
jmp 0x278b9
movl -0x3c(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0x1c(%rcx), %eax
ja 0x275b7
movq -0x20(%rbp), %rdi
movl -0x3c(%rbp), %esi
callq 0x219a0
cmpl $0x0, %eax
je 0x275c3
movl $0x0, -0x4(%rbp)
jmp 0x278b9
cmpl $0x0, -0x24(%rbp)
je 0x2761b
movq -0x50(%rbp), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
subq $0x4, %rsi
leaq -0x40(%rbp), %rdx
callq 0x287c0
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
je 0x275f5
movl -0x2c(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x278b9
cmpl $0x0, -0x28(%rbp)
jne 0x27619
movq -0x10(%rbp), %rdi
movq -0x48(%rbp), %rsi
callq 0x28810
cmpl -0x40(%rbp), %eax
je 0x27619
movl $0x65, -0x4(%rbp)
jmp 0x278b9
jmp 0x2761b
cmpq $0x0, -0x20(%rbp)
je 0x27641
movq -0x20(%rbp), %rdi
movl -0x3c(%rbp), %esi
callq 0x220b0
movl %eax, -0x2c(%rbp)
cmpl $0x0, %eax
je 0x27641
movl -0x2c(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x278b9
cmpl $0x1, -0x3c(%rbp)
jne 0x27674
movq -0x10(%rbp), %rax
movswl 0xb2(%rax), %eax
movq -0x48(%rbp), %rcx
movzbl 0x14(%rcx), %ecx
cmpl %ecx, %eax
je 0x27674
movq -0x48(%rbp), %rax
movzbl 0x14(%rax), %eax
movw %ax, %cx
movq -0x10(%rbp), %rax
movw %cx, 0xb2(%rax)
movq -0x10(%rbp), %rdi
callq 0x211a0
cmpl $0x0, %eax
je 0x2768c
movq $0x0, -0x38(%rbp)
jmp 0x2769c
movq -0x10(%rbp), %rdi
movl -0x3c(%rbp), %esi
callq 0x28870
movq %rax, -0x38(%rbp)
cmpl $0x0, -0x24(%rbp)
je 0x276d6
movq -0x10(%rbp), %rax
movzbl 0xb(%rax), %ecx
movb $0x1, %al
cmpl $0x0, %ecx
movb %al, -0x75(%rbp)
jne 0x276c9
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq -0x10(%rbp), %rcx
cmpq 0x68(%rcx), %rax
setle %al
movb %al, -0x75(%rbp)
movb -0x75(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x54(%rbp)
jmp 0x27702
movb $0x1, %al
cmpq $0x0, -0x38(%rbp)
movb %al, -0x76(%rbp)
je 0x276f7
movq -0x38(%rbp), %rax
movzwl 0x2c(%rax), %ecx
andl $0x4, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
sete %al
movb %al, -0x76(%rbp)
movb -0x76(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x54(%rbp)
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
cmpq $0x0, (%rax)
je 0x277b4
movq -0x10(%rbp), %rax
movzbl 0x13(%rax), %eax
cmpl $0x4, %eax
jge 0x27732
movq -0x10(%rbp), %rax
movzbl 0x13(%rax), %eax
cmpl $0x0, %eax
jne 0x277b4
cmpl $0x0, -0x54(%rbp)
je 0x277b4
movl -0x3c(%rbp), %eax
subl $0x1, %eax
movl %eax, %eax
movq -0x10(%rbp), %rcx
movslq 0xbc(%rcx), %rcx
imulq %rcx, %rax
movq %rax, -0x60(%rbp)
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rdi
movq -0x48(%rbp), %rsi
movq -0x10(%rbp), %rax
movl 0xbc(%rax), %edx
movq -0x60(%rbp), %rcx
callq 0xf430
movl %eax, -0x2c(%rbp)
movl -0x3c(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0x24(%rcx), %eax
jbe 0x2778b
movl -0x3c(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x24(%rax)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x70(%rax)
je 0x277b2
movq -0x10(%rbp), %rax
movq 0x70(%rax), %rdi
movl -0x3c(%rbp), %esi
movq -0x48(%rbp), %rdx
callq 0x22970
movq -0x48(%rbp), %rax
movq %rax, -0x48(%rbp)
jmp 0x27820
cmpl $0x0, -0x24(%rbp)
jne 0x2781e
cmpq $0x0, -0x38(%rbp)
jne 0x2781e
movq -0x10(%rbp), %rax
movzbl 0x17(%rax), %ecx
orl $0x2, %ecx
movb %cl, 0x17(%rax)
movq -0x10(%rbp), %rdi
movl -0x3c(%rbp), %esi
leaq -0x38(%rbp), %rdx
movl $0x1, %ecx
callq 0xe5f0
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rax
movzbl 0x17(%rax), %ecx
andl $-0x3, %ecx
movb %cl, 0x17(%rax)
cmpl $0x0, -0x2c(%rbp)
je 0x27806
movl -0x2c(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x278b9
movq -0x38(%rbp), %rax
movzwl 0x2c(%rax), %ecx
andl $-0x9, %ecx
movw %cx, 0x2c(%rax)
movq -0x38(%rbp), %rdi
callq 0x288b0
jmp 0x27820
cmpq $0x0, -0x38(%rbp)
je 0x278b3
movq -0x38(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rdi
movq -0x48(%rbp), %rsi
movq -0x10(%rbp), %rax
movslq 0xbc(%rax), %rdx
callq 0x82f0
movq -0x10(%rbp), %rax
movq 0x100(%rax), %rax
movq -0x38(%rbp), %rdi
callq *%rax
cmpl $0x0, -0x24(%rbp)
je 0x27886
cmpl $0x0, -0x28(%rbp)
je 0x2787d
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq -0x10(%rbp), %rcx
cmpq 0x68(%rcx), %rax
jg 0x27886
movq -0x38(%rbp), %rdi
callq 0x21900
cmpl $0x1, -0x3c(%rbp)
jne 0x278aa
movq -0x10(%rbp), %rax
movq -0x68(%rbp), %rcx
movq 0x18(%rcx), %rdx
movq %rdx, 0x84(%rax)
movq 0x20(%rcx), %rcx
movq %rcx, 0x8c(%rax)
movq -0x38(%rbp), %rdi
callq 0x28900
movl -0x2c(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x80, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)