// File: /workspace/github_c_makefile_star2_O0/genometools[P]genometools/src/external/sqlite-3.33.0/sqlite3.c
// Function: walIndexRecover
static int walIndexRecover(Wal *pWal){
  int rc;                         /* Return Code */
  i64 nSize;                      /* Size of log file */
  u32 aFrameCksum[2] = {0, 0};
  int iLock;                      /* Lock offset to lock for checkpoint */

  /* Obtain an exclusive lock on all byte in the locking range not already
  ** locked by the caller. The caller is guaranteed to have locked the
  ** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
  ** If successful, the same bytes that are locked here are unlocked before
  ** this function returns.
  */
  assert( pWal->ckptLock==1 || pWal->ckptLock==0 );
  assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 );
  assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
  assert( pWal->writeLock );
  iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
  rc = walLockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
  if( rc ){
    return rc;
  }

  WALTRACE(("WAL%p: recovery begin...\n", pWal));

  memset(&pWal->hdr, 0, sizeof(WalIndexHdr));

  rc = sqlite3OsFileSize(pWal->pWalFd, &nSize);
  if( rc!=SQLITE_OK ){
    goto recovery_error;
  }

  if( nSize>WAL_HDRSIZE ){
    u8 aBuf[WAL_HDRSIZE];         /* Buffer to load WAL header into */
    u32 *aPrivate = 0;            /* Heap copy of *-shm hash being populated */
    u8 *aFrame = 0;               /* Malloc'd buffer to load entire frame */
    int szFrame;                  /* Number of bytes in buffer aFrame[] */
    u8 *aData;                    /* Pointer to data part of aFrame buffer */
    int szPage;                   /* Page size according to the log */
    u32 magic;                    /* Magic value read from WAL header */
    u32 version;                  /* Magic value read from WAL header */
    int isValid;                  /* True if this frame is valid */
    u32 iPg;                      /* Current 32KB wal-index page */
    u32 iLastFrame;               /* Last frame in wal, based on nSize alone */

    /* Read in the WAL header. */
    rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
    if( rc!=SQLITE_OK ){
      goto recovery_error;
    }

    /* If the database page size is not a power of two, or is greater than
    ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid
    ** data. Similarly, if the 'magic' value is invalid, ignore the whole
    ** WAL file.
    */
    magic = sqlite3Get4byte(&aBuf[0]);
    szPage = sqlite3Get4byte(&aBuf[8]);
    if( (magic&0xFFFFFFFE)!=WAL_MAGIC
     || szPage&(szPage-1)
     || szPage>SQLITE_MAX_PAGE_SIZE
     || szPage<512
    ){
      goto finished;
    }
    pWal->hdr.bigEndCksum = (u8)(magic&0x00000001);
    pWal->szPage = szPage;
    pWal->nCkpt = sqlite3Get4byte(&aBuf[12]);
    memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);

    /* Verify that the WAL header checksum is correct */
    walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN,
        aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum
    );
    if( pWal->hdr.aFrameCksum[0]!=sqlite3Get4byte(&aBuf[24])
     || pWal->hdr.aFrameCksum[1]!=sqlite3Get4byte(&aBuf[28])
    ){
      goto finished;
    }

    /* Verify that the version number on the WAL format is one that
    ** are able to understand */
    version = sqlite3Get4byte(&aBuf[4]);
    if( version!=WAL_MAX_VERSION ){
      rc = SQLITE_CANTOPEN_BKPT;
      goto finished;
    }

    /* Malloc a buffer to read frames into. */
    szFrame = szPage + WAL_FRAME_HDRSIZE;
    aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ);
    if( !aFrame ){
      rc = SQLITE_NOMEM_BKPT;
      goto recovery_error;
    }
    aData = &aFrame[WAL_FRAME_HDRSIZE];
    aPrivate = (u32*)&aData[szPage];

    /* Read all frames from the log file. */
    iLastFrame = (nSize - WAL_HDRSIZE) / szFrame;
    for(iPg=0; iPg<=(u32)walFramePage(iLastFrame); iPg++){
      u32 *aShare;
      u32 iFrame;                 /* Index of last frame read */
      u32 iLast = MIN(iLastFrame, HASHTABLE_NPAGE_ONE+iPg*HASHTABLE_NPAGE);
      u32 iFirst = 1 + (iPg==0?0:HASHTABLE_NPAGE_ONE+(iPg-1)*HASHTABLE_NPAGE);
      u32 nHdr, nHdr32;
      rc = walIndexPage(pWal, iPg, (volatile u32**)&aShare);
      if( rc ) break;
      pWal->apWiData[iPg] = aPrivate;

      for(iFrame=iFirst; iFrame<=iLast; iFrame++){
        i64 iOffset = walFrameOffset(iFrame, szPage);
        u32 pgno;                 /* Database page number for frame */
        u32 nTruncate;            /* dbsize field from frame header */

        /* Read and decode the next log frame. */
        rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset);
        if( rc!=SQLITE_OK ) break;
        isValid = walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame);
        if( !isValid ) break;
        rc = walIndexAppend(pWal, iFrame, pgno);
        if( NEVER(rc!=SQLITE_OK) ) break;

        /* If nTruncate is non-zero, this is a commit record. */
        if( nTruncate ){
          pWal->hdr.mxFrame = iFrame;
          pWal->hdr.nPage = nTruncate;
          pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
          testcase( szPage<=32768 );
          testcase( szPage>=65536 );
          aFrameCksum[0] = pWal->hdr.aFrameCksum[0];
          aFrameCksum[1] = pWal->hdr.aFrameCksum[1];
        }
      }
      pWal->apWiData[iPg] = aShare;
      nHdr = (iPg==0 ? WALINDEX_HDR_SIZE : 0);
      nHdr32 = nHdr / sizeof(u32);
#ifndef SQLITE_SAFER_WALINDEX_RECOVERY
      /* Memcpy() should work fine here, on all reasonable implementations.
      ** Technically, memcpy() might change the destination to some
      ** intermediate value before setting to the final value, and that might
      ** cause a concurrent reader to malfunction.  Memcpy() is allowed to
      ** do that, according to the spec, but no memcpy() implementation that
      ** we know of actually does that, which is why we say that memcpy()
      ** is safe for this.  Memcpy() is certainly a lot faster.
      */
      memcpy(&aShare[nHdr32], &aPrivate[nHdr32], WALINDEX_PGSZ-nHdr);
#else
      /* In the event that some platform is found for which memcpy()
      ** changes the destination to some intermediate value before
      ** setting the final value, this alternative copy routine is
      ** provided.
      */
      {
        int i;
        for(i=nHdr32; i<WALINDEX_PGSZ/sizeof(u32); i++){
          if( aShare[i]!=aPrivate[i] ){
            /* Atomic memory operations are not required here because if
            ** the value needs to be changed, that means it is not being
            ** accessed concurrently. */
            aShare[i] = aPrivate[i];
          }
        }
      }
#endif
      if( iFrame<=iLast ) break;
    }

    sqlite3_free(aFrame);
  }

finished:
  if( rc==SQLITE_OK ){
    volatile WalCkptInfo *pInfo;
    int i;
    pWal->hdr.aFrameCksum[0] = aFrameCksum[0];
    pWal->hdr.aFrameCksum[1] = aFrameCksum[1];
    walIndexWriteHdr(pWal);

    /* Reset the checkpoint-header. This is safe because this thread is
    ** currently holding locks that exclude all other writers and
    ** checkpointers. Then set the values of read-mark slots 1 through N.
    */
    pInfo = walCkptInfo(pWal);
    pInfo->nBackfill = 0;
    pInfo->nBackfillAttempted = pWal->hdr.mxFrame;
    pInfo->aReadMark[0] = 0;
    for(i=1; i<WAL_NREADER; i++){
      rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
      if( rc==SQLITE_OK ){
        if( i==1 && pWal->hdr.mxFrame ){
          pInfo->aReadMark[i] = pWal->hdr.mxFrame;
        }else{
          pInfo->aReadMark[i] = READMARK_NOT_USED;
        }
        walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
      }else if( rc!=SQLITE_BUSY ){
        goto recovery_error;
      }
    }

    /* If more than one frame was recovered from the log file, report an
    ** event via sqlite3_log(). This is to help with identifying performance
    ** problems caused by applications routinely shutting down without
    ** checkpointing the log file.
    */
    if( pWal->hdr.nPage ){
      sqlite3_log(SQLITE_NOTICE_RECOVER_WAL,
          "recovered %d frames from WAL file %s",
          pWal->hdr.mxFrame, pWal->zWalName
      );
    }
  }

recovery_error:
  WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
  walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
  return rc;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rdi, -0x10(%rbp)
leaq -0x28(%rbp), %rdi
xorl %esi, %esi
movl $0x8, %edx
callq 0x19360
movq -0x10(%rbp), %rax
movzbl 0x41(%rax), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rdi
movl -0x2c(%rbp), %esi
movl $0x3, %edx
subl -0x2c(%rbp), %edx
callq 0x3de5e0
movl %eax, -0x14(%rbp)
cmpl $0x0, -0x14(%rbp)
je 0x3df2f5
movl -0x14(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x3df933
movq -0x10(%rbp), %rdi
addq $0x48, %rdi
xorl %esi, %esi
movl $0x30, %edx
callq 0x19360
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
leaq -0x20(%rbp), %rsi
callq 0x3dfbd0
movl %eax, -0x14(%rbp)
cmpl $0x0, -0x14(%rbp)
je 0x3df328
jmp 0x3df919
cmpq $0x20, -0x20(%rbp)
jle 0x3df7cd
movq $0x0, -0x58(%rbp)
movq $0x0, -0x60(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
leaq -0x50(%rbp), %rsi
movl $0x20, %edx
xorl %eax, %eax
movl %eax, %ecx
callq 0x3dfc00
movl %eax, -0x14(%rbp)
cmpl $0x0, -0x14(%rbp)
je 0x3df36b
jmp 0x3df919
leaq -0x50(%rbp), %rdi
callq 0x3db720
movl %eax, -0x78(%rbp)
leaq -0x50(%rbp), %rdi
addq $0x8, %rdi
callq 0x3db720
movl %eax, -0x74(%rbp)
movl -0x78(%rbp), %eax
andl $-0x2, %eax
cmpl $0x377f0682, %eax       # imm = 0x377F0682
jne 0x3df3b6
movl -0x74(%rbp), %eax
movl -0x74(%rbp), %ecx
subl $0x1, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
jne 0x3df3b6
cmpl $0x10000, -0x74(%rbp)   # imm = 0x10000
jg 0x3df3b6
cmpl $0x200, -0x74(%rbp)     # imm = 0x200
jge 0x3df3bb
jmp 0x3df7cf
movl -0x78(%rbp), %eax
andl $0x1, %eax
movb %al, %cl
movq -0x10(%rbp), %rax
movb %cl, 0x55(%rax)
movl -0x74(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x38(%rax)
leaq -0x50(%rbp), %rdi
addq $0xc, %rdi
callq 0x3db720
movl %eax, %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x88(%rax)
movq -0x10(%rbp), %rax
movq -0x40(%rbp), %rcx
movq %rcx, 0x68(%rax)
movq -0x10(%rbp), %rax
movzbl 0x55(%rax), %eax
cmpl $0x0, %eax
sete %al
andb $0x1, %al
movzbl %al, %edi
leaq -0x50(%rbp), %rsi
movq -0x10(%rbp), %r8
addq $0x48, %r8
addq $0x18, %r8
movl $0x18, %edx
xorl %eax, %eax
movl %eax, %ecx
callq 0x3dde00
movq -0x10(%rbp), %rax
movl 0x60(%rax), %eax
movl %eax, -0xc8(%rbp)
leaq -0x50(%rbp), %rdi
addq $0x18, %rdi
callq 0x3db720
movl %eax, %ecx
movl -0xc8(%rbp), %eax
cmpl %ecx, %eax
jne 0x3df476
movq -0x10(%rbp), %rax
movl 0x64(%rax), %eax
movl %eax, -0xcc(%rbp)
leaq -0x50(%rbp), %rdi
addq $0x1c, %rdi
callq 0x3db720
movl %eax, %ecx
movl -0xcc(%rbp), %eax
cmpl %ecx, %eax
je 0x3df47b
jmp 0x3df7cf
leaq -0x50(%rbp), %rdi
addq $0x4, %rdi
callq 0x3db720
movl %eax, -0x7c(%rbp)
cmpl $0x2de218, -0x7c(%rbp)  # imm = 0x2DE218
je 0x3df4a6
movl $0xecdb, %edi           # imm = 0xECDB
callq 0x3d80e0
movl %eax, -0x14(%rbp)
jmp 0x3df7cf
movl -0x74(%rbp), %eax
addl $0x18, %eax
movl %eax, -0x64(%rbp)
movslq -0x64(%rbp), %rdi
addq $0x8000, %rdi           # imm = 0x8000
callq 0x3c07c0
movq %rax, -0x60(%rbp)
cmpq $0x0, -0x60(%rbp)
jne 0x3df4d6
movl $0x7, -0x14(%rbp)
jmp 0x3df919
movq -0x60(%rbp), %rax
addq $0x18, %rax
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
movslq -0x74(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x20(%rbp), %rax
subq $0x20, %rax
movslq -0x64(%rbp), %rcx
cqto
idivq %rcx
movl %eax, -0x88(%rbp)
movl $0x0, -0x84(%rbp)
movl -0x84(%rbp), %eax
movl %eax, -0xd0(%rbp)
movl -0x88(%rbp), %edi
callq 0x3dfc40
movl %eax, %ecx
movl -0xd0(%rbp), %eax
cmpl %ecx, %eax
ja 0x3df7c4
movl -0x88(%rbp), %eax
movl -0x84(%rbp), %ecx
shll $0xc, %ecx
movl %ecx, %ecx
addq $0xfde, %rcx            # imm = 0xFDE
cmpq %rcx, %rax
jae 0x3df565
movl -0x88(%rbp), %eax
movq %rax, -0xd8(%rbp)
jmp 0x3df57d
movl -0x84(%rbp), %eax
shll $0xc, %eax
movl %eax, %eax
addq $0xfde, %rax            # imm = 0xFDE
movq %rax, -0xd8(%rbp)
movq -0xd8(%rbp), %rax
movl %eax, -0x98(%rbp)
cmpl $0x0, -0x84(%rbp)
jne 0x3df59e
xorl %eax, %eax
movq %rax, -0xe0(%rbp)
jmp 0x3df5b9
movl -0x84(%rbp), %eax
subl $0x1, %eax
shll $0xc, %eax
movl %eax, %eax
addq $0xfde, %rax            # imm = 0xFDE
movq %rax, -0xe0(%rbp)
movq -0xe0(%rbp), %rax
addq $0x1, %rax
movl %eax, -0x9c(%rbp)
movq -0x10(%rbp), %rdi
movl -0x84(%rbp), %esi
leaq -0x90(%rbp), %rdx
callq 0x3df0f0
movl %eax, -0x14(%rbp)
cmpl $0x0, -0x14(%rbp)
je 0x3df5ee
jmp 0x3df7c4
movq -0x58(%rbp), %rdx
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movl -0x84(%rbp), %ecx
movq %rdx, (%rax,%rcx,8)
movl -0x9c(%rbp), %eax
movl %eax, -0x94(%rbp)
movl -0x94(%rbp), %eax
cmpl -0x98(%rbp), %eax
ja 0x3df723
movl -0x94(%rbp), %eax
subl $0x1, %eax
movl %eax, %eax
movl -0x74(%rbp), %ecx
addl $0x18, %ecx
movslq %ecx, %rcx
imulq %rcx, %rax
addq $0x20, %rax
movq %rax, -0xb0(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
movq -0x60(%rbp), %rsi
movl -0x64(%rbp), %edx
movq -0xb0(%rbp), %rcx
callq 0x3dfc00
movl %eax, -0x14(%rbp)
cmpl $0x0, -0x14(%rbp)
je 0x3df66e
jmp 0x3df723
movq -0x10(%rbp), %rdi
movq -0x70(%rbp), %rcx
movq -0x60(%rbp), %r8
leaq -0xb4(%rbp), %rsi
leaq -0xb8(%rbp), %rdx
callq 0x3dfc70
movl %eax, -0x80(%rbp)
cmpl $0x0, -0x80(%rbp)
jne 0x3df69b
jmp 0x3df723
movq -0x10(%rbp), %rdi
movl -0x94(%rbp), %esi
movl -0xb4(%rbp), %edx
callq 0x3de400
movl %eax, -0x14(%rbp)
cmpl $0x0, -0x14(%rbp)
je 0x3df6bb
jmp 0x3df723
cmpl $0x0, -0xb8(%rbp)
je 0x3df70d
movl -0x94(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x58(%rax)
movl -0xb8(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x5c(%rax)
movl -0x74(%rbp), %eax
andl $0xff00, %eax           # imm = 0xFF00
movl -0x74(%rbp), %ecx
sarl $0x10, %ecx
orl %ecx, %eax
movw %ax, %cx
movq -0x10(%rbp), %rax
movw %cx, 0x56(%rax)
movq -0x10(%rbp), %rax
movl 0x60(%rax), %eax
movl %eax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movl 0x64(%rax), %eax
movl %eax, -0x24(%rbp)
jmp 0x3df70f
movl -0x94(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x94(%rbp)
jmp 0x3df610
movq -0x90(%rbp), %rdx
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movl -0x84(%rbp), %ecx
movq %rdx, (%rax,%rcx,8)
movl -0x84(%rbp), %edx
xorl %eax, %eax
movl $0x88, %ecx
cmpl $0x0, %edx
cmoveq %rcx, %rax
movl %eax, -0xa0(%rbp)
movl -0xa0(%rbp), %eax
shrq $0x2, %rax
movl %eax, -0xa4(%rbp)
movq -0x90(%rbp), %rdi
movl -0xa4(%rbp), %eax
shlq $0x2, %rax
addq %rax, %rdi
movq -0x58(%rbp), %rsi
movl -0xa4(%rbp), %eax
shlq $0x2, %rax
addq %rax, %rsi
movl -0xa0(%rbp), %eax
movl $0x8000, %edx           # imm = 0x8000
subq %rax, %rdx
callq 0x19610
movl -0x94(%rbp), %eax
cmpl -0x98(%rbp), %eax
ja 0x3df7ae
jmp 0x3df7c4
jmp 0x3df7b0
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
jmp 0x3df512
movq -0x60(%rbp), %rdi
callq 0x3c0800
jmp 0x3df7cf
cmpl $0x0, -0x14(%rbp)
jne 0x3df917
movl -0x28(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x60(%rax)
movl -0x24(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x64(%rax)
movq -0x10(%rbp), %rdi
callq 0x3de520
movq -0x10(%rbp), %rdi
callq 0x3de5c0
movq %rax, -0xc0(%rbp)
movq -0xc0(%rbp), %rax
movl $0x0, (%rax)
movq -0x10(%rbp), %rax
movl 0x58(%rax), %ecx
movq -0xc0(%rbp), %rax
movl %ecx, 0x20(%rax)
movq -0xc0(%rbp), %rax
movl $0x0, 0x4(%rax)
movl $0x1, -0xc4(%rbp)
cmpl $0x5, -0xc4(%rbp)
jge 0x3df8e6
movq -0x10(%rbp), %rdi
movl -0xc4(%rbp), %esi
addl $0x3, %esi
movl $0x1, %edx
callq 0x3de5e0
movl %eax, -0x14(%rbp)
cmpl $0x0, -0x14(%rbp)
jne 0x3df8c6
cmpl $0x1, -0xc4(%rbp)
jne 0x3df897
movq -0x10(%rbp), %rax
cmpl $0x0, 0x58(%rax)
je 0x3df897
movq -0x10(%rbp), %rax
movl 0x58(%rax), %edx
movq -0xc0(%rbp), %rax
movslq -0xc4(%rbp), %rcx
movl %edx, 0x4(%rax,%rcx,4)
jmp 0x3df8ad
movq -0xc0(%rbp), %rax
movslq -0xc4(%rbp), %rcx
movl $0xffffffff, 0x4(%rax,%rcx,4) # imm = 0xFFFFFFFF
movq -0x10(%rbp), %rdi
movl -0xc4(%rbp), %esi
addl $0x3, %esi
movl $0x1, %edx
callq 0x3de700
jmp 0x3df8d0
cmpl $0x5, -0x14(%rbp)
je 0x3df8ce
jmp 0x3df919
jmp 0x3df8d0
jmp 0x3df8d2
movl -0xc4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc4(%rbp)
jmp 0x3df83c
movq -0x10(%rbp), %rax
cmpl $0x0, 0x5c(%rax)
je 0x3df915
movq -0x10(%rbp), %rax
movl 0x58(%rax), %edx
movq -0x10(%rbp), %rax
movq 0x80(%rax), %rcx
movl $0x11b, %edi            # imm = 0x11B
leaq 0x1cb836(%rip), %rsi    # 0x5ab144
movb $0x0, %al
callq 0x3c3970
jmp 0x3df917
jmp 0x3df919
movq -0x10(%rbp), %rdi
movl -0x2c(%rbp), %esi
movl $0x3, %edx
subl -0x2c(%rbp), %edx
callq 0x3de700
movl -0x14(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xe0, %rsp
popq %rbp
retq
nop