internal RC fillInCell(byte[] pCell, byte[] pKey, long nKey, byte[] pData, int nData, int nZero, ref int pnSize) { Debug.Assert(MutexEx.Held(this.Shared.Mutex)); // pPage is not necessarily writeable since pCell might be auxiliary buffer space that is separate from the pPage buffer area // TODO -- Determine if the following Assert is needed under c# //Debug.Assert( pCell < pPage.aData || pCell >= &pPage.aData[pBt.pageSize] || sqlite3PagerIswriteable(pPage.pDbPage) ); // Fill in the header. var nHeader = 0; if (this.Leaf == 0) { nHeader += 4; } if (this.HasData != 0) { nHeader += (int)ConvertEx.PutVarint9(pCell, (uint)nHeader, (int)(nData + nZero)); } else { nData = nZero = 0; } nHeader += ConvertEx.PutVarint9L(pCell, (uint)nHeader, (ulong)nKey); var info = new CellInfo(); btreeParseCellPtr(pCell, ref info); Debug.Assert(info.nHeader == nHeader); Debug.Assert(info.nKey == nKey); Debug.Assert(info.nData == (uint)(nData + nZero)); // Fill in the payload var nPayload = nData + nZero; byte[] pSrc; int nSrc; if (this.HasIntKey) { pSrc = pData; nSrc = nData; nData = 0; } else { if (Check.NEVER(nKey > 0x7fffffff || pKey == null)) { return(SysEx.SQLITE_CORRUPT_BKPT()); } nPayload += (int)nKey; pSrc = pKey; nSrc = (int)nKey; } pnSize = info.nSize; var spaceLeft = (int)info.nLocal; var pPayload = pCell; var pPayloadIndex = nHeader; var pPrior = pCell; var pPriorIndex = (int)info.iOverflow; var pBt = this.Shared; Pgno pgnoOvfl = 0; MemPage pToRelease = null; while (nPayload > 0) { if (spaceLeft == 0) { #if !SQLITE_OMIT_AUTOVACUUM var pgnoPtrmap = pgnoOvfl; // Overflow page pointer-map entry page if (pBt.AutoVacuum) { do { pgnoOvfl++; }while (PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl == PENDING_BYTE_PAGE(pBt)); } #endif MemPage pOvfl = null; var rc = pBt.allocateBtreePage(ref pOvfl, ref pgnoOvfl, pgnoOvfl, 0); #if !SQLITE_OMIT_AUTOVACUUM // If the database supports auto-vacuum, and the second or subsequent overflow page is being allocated, add an entry to the pointer-map for that page now. // If this is the first overflow page, then write a partial entry to the pointer-map. If we write nothing to this pointer-map slot, // then the optimistic overflow chain processing in clearCell() may misinterpret the uninitialised values and delete the // wrong pages from the database. if (pBt.AutoVacuum && rc == RC.OK) { var eType = (pgnoPtrmap != 0 ? PTRMAP.OVERFLOW2 : PTRMAP.OVERFLOW1); pBt.ptrmapPut(pgnoOvfl, eType, pgnoPtrmap, ref rc); if (rc != RC.OK) { pOvfl.releasePage(); } } #endif if (rc != RC.OK) { pToRelease.releasePage(); return(rc); } // If pToRelease is not zero than pPrior points into the data area of pToRelease. Make sure pToRelease is still writeable. Debug.Assert(pToRelease == null || Pager.IsPageWriteable(pToRelease.DbPage)); // If pPrior is part of the data area of pPage, then make sure pPage is still writeable // TODO -- Determine if the following Assert is needed under c# //Debug.Assert( pPrior < pPage.aData || pPrior >= &pPage.aData[pBt.pageSize] || sqlite3PagerIswriteable(pPage.pDbPage) ); ConvertEx.Put4L(pPrior, pPriorIndex, pgnoOvfl); pToRelease.releasePage(); pToRelease = pOvfl; pPrior = pOvfl.Data; pPriorIndex = 0; ConvertEx.Put4(pPrior, 0); pPayload = pOvfl.Data; pPayloadIndex = 4; spaceLeft = (int)pBt.UsableSize - 4; } var n = nPayload; if (n > spaceLeft) { n = spaceLeft; } // If pToRelease is not zero than pPayload points into the data area of pToRelease. Make sure pToRelease is still writeable. Debug.Assert(pToRelease == null || Pager.IsPageWriteable(pToRelease.DbPage)); // If pPayload is part of the data area of pPage, then make sure pPage is still writeable // TODO -- Determine if the following Assert is needed under c# //Debug.Assert( pPayload < pPage.aData || pPayload >= &pPage.aData[pBt.pageSize] || sqlite3PagerIswriteable(pPage.pDbPage) ); var pSrcIndex = 0; if (nSrc > 0) { if (n > nSrc) { n = nSrc; } Debug.Assert(pSrc != null); Buffer.BlockCopy(pSrc, pSrcIndex, pPayload, pPayloadIndex, n); } else { var pZeroBlob = MallocEx.sqlite3Malloc(n); Buffer.BlockCopy(pZeroBlob, 0, pPayload, pPayloadIndex, n); } nPayload -= n; pPayloadIndex += n; pSrcIndex += n; nSrc -= n; spaceLeft -= n; if (nSrc == 0) { nSrc = nData; pSrc = pData; } } pToRelease.releasePage(); return(RC.OK); }