Repository: libsql/libsql
File: libsql-sqlite3/src/wal.c (C)

Code before:
      p->aSegment[i].nEntry = nEntry;
      p->aSegment[i].aIndex = aIndex;
      p->aSegment[i].aPgno = (u32 *)sLoc.aPgno;
    }
  }
  if( rc!=SQLITE_OK ){
    SEH_FREE_ON_ERROR(p, 0);
    walIteratorFree(p);
    p = 0;
  }
  *pp = p;
  return rc;
}

static int walIteratorRevInit(Wal *pWal, u32 nBackfill, struct WalIteratorRev *p, u32 mxSafeFrame, int getMissingFrame){
    WalIterator *pIter;
    u32 *frames;
    u32 iFrame, iPageno;
    int rc;

    frames = (u32*)sqlite3MallocZero((pWal->hdr.mxFrame + 1) * sizeof(u32));
    if (!frames) return SQLITE_NOMEM_BKPT;
    rc = walIteratorInit(pWal, nBackfill, &pIter);
    if (rc || !pIter) {
        sqlite3_free(frames);
        return rc;
    }

    while (walIteratorNext(pIter, &iPageno, &iFrame) == 0) {
        /*
         * If we get a page with a frame_no greater than mxSafeFrame, and getMissingFrame is true,
         * then we replace it with the latest page with frame_no <= mxSafeFrame.
         */
        if (iFrame > mxSafeFrame && getMissingFrame) {
           rc = walFindFrame(pWal, iPageno, mxSafeFrame, &iFrame);
           if( rc!=SQLITE_OK ) break;
           if (iFrame == 0) {
               continue;
           }
        }
        frames[iFrame] = iPageno;
    }
    walIteratorFree(pIter);
    if (rc != 0) {
        sqlite3_free(frames);
        return rc;
    }

    p->current = pWal->hdr.mxFrame;
    p->frames = frames;


Review comment (performance):
do we always have access to `sqlite3` db instance via `Wal *`? If we do, we should consider allocating and deallocating with `sqlite3DbMallocZero` and `sqlite3DbFree` instead, which possibly use more efficient lookaside memory: https://www.sqlite.org/malloc.html#_lookaside_memory_allocator

Code after:
      for(j=0; j<nEntry; j++){
        aIndex[j] = (ht_slot)j;
      }
      walMergesort((u32 *)sLoc.aPgno, aTmp, aIndex, &nEntry);
      p->aSegment[i].iZero = sLoc.iZero;
      p->aSegment[i].nEntry = nEntry;
      p->aSegment[i].aIndex = aIndex;
      p->aSegment[i].aPgno = (u32 *)sLoc.aPgno;
    }
  }
  if( rc!=SQLITE_OK ){
    SEH_FREE_ON_ERROR(p, 0);
    walIteratorFree(p);
    p = 0;
  }
  *pp = p;
  return rc;
}

static int walIteratorRevInit(Wal *pWal, u32 nBackfill, struct WalIteratorRev *p, u32 mxSafeFrame, int ignoreFrameIfNewerExist){
    WalIterator *pIter;
    u32 *frames;
    u32 iFrame, iPageno;
    int rc;

    frames = (u32*)sqlite3MallocZero((pWal->hdr.mxFrame + 1) * sizeof(u32));
    if (!frames) return SQLITE_NOMEM_BKPT;
    rc = walIteratorInit(pWal, nBackfill, &pIter);
    if (rc || !pIter) {
        sqlite3_free(frames);
        return rc;
    }

    while (walIteratorNext(pIter, &iPageno, &iFrame) == 0) {
        /*
         * If we get a page with a frame_no greater than mxSafeFrame, and ignoreFrameIfNewerExist is false,
         * then we replace it with the latest page with frame_no <= mxSafeFrame.
         */
        if (iFrame > mxSafeFrame && !ignoreFrameIfNewerExist) {
           rc = walFindFrame(pWal, iPageno, mxSafeFrame, &iFrame);
           if( rc!=SQLITE_OK ) break;
           if (iFrame == 0) {
               continue;
           }
        }
        frames[iFrame] = iPageno;
    }
    walIteratorFree(pIter);
    if (rc != 0) {
        sqlite3_free(frames);
        return rc;