final SqlJetMemPage pPage = this;
int pnSize = 0;
int nPayload;
ISqlJetMemoryPointer pSrc;
int nSrc, n;
int spaceLeft;
SqlJetMemPage pOvfl = null;
SqlJetMemPage pToRelease = null;
ISqlJetMemoryPointer pPrior;
ISqlJetMemoryPointer pPayload;
SqlJetBtreeShared pBt = pPage.pBt;
int[] pgnoOvfl = { 0 };
int nHeader;
SqlJetBtreeCellInfo info;
assert (pPage.pBt.mutex.held());
/*
* pPage is not necessarily writeable since pCell might be auxiliary*
* buffer space that is separate from the pPage buffer area
*/
assert (pCell.getBuffer() != pPage.aData.getBuffer() || pPage.pDbPage.isWriteable());
/* Fill in the header. */
nHeader = 0;
if (!pPage.leaf) {
nHeader += 4;
}
if (pPage.hasData) {
nHeader += putVarint(pointer(pCell, nHeader), nData + nZero);
} else {
nData = nZero = 0;
}
nHeader += putVarint(pointer(pCell, nHeader), nKey);
info = pPage.parseCellPtr(pCell);
assert (info.nHeader == nHeader);
assert (info.nKey == nKey);
assert (info.nData == nData + nZero);
/* Fill in the payload */
nPayload = nData + nZero;
if (pPage.intKey) {
pSrc = pData;
nSrc = nData;
nData = 0;
} else {
/* TBD: Perhaps raise SQLITE_CORRUPT if nKey is larger than 31 bits? */
nPayload += (int) nKey;
pSrc = pKey;
nSrc = (int) nKey;
}
pnSize = info.nSize;
spaceLeft = info.nLocal;
pPayload = pointer(pCell, nHeader);
pPrior = pointer(pCell, info.iOverflow);
while (nPayload > 0) {
if (spaceLeft == 0) {
int pgnoPtrmap = pgnoOvfl[0]; /*
* Overflow page pointer-map entry
* page
*/
if (pBt.autoVacuum) {
do {
pgnoOvfl[0]++;
} while (pBt.PTRMAP_ISPAGE(pgnoOvfl[0]) || pgnoOvfl[0] == pBt.PENDING_BYTE_PAGE());
}
try {
pOvfl = pBt.allocatePage(pgnoOvfl, pgnoOvfl[0], false);
/*
* 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) {
byte eType = (pgnoPtrmap != 0 ? SqlJetBtreeShared.PTRMAP_OVERFLOW2
: SqlJetBtreeShared.PTRMAP_OVERFLOW1);
try {
pBt.ptrmapPut(pgnoOvfl[0], eType, pgnoPtrmap);
} catch (SqlJetException e) {
releasePage(pOvfl);
}
}
} catch (SqlJetException e) {
releasePage(pToRelease);
throw e;
}
/*
* If pToRelease is not zero than pPrior points into the data
* area* of pToRelease. Make sure pToRelease is still writeable.
*/
assert (pToRelease == null || pToRelease.pDbPage.isWriteable());
/*
* If pPrior is part of the data area of pPage, then make sure
* pPage* is still writeable
*/
assert (pPrior.getBuffer() != pPage.aData.getBuffer() || pPage.pDbPage.isWriteable());
put4byte(pPrior, pgnoOvfl[0]);
releasePage(pToRelease);
pToRelease = pOvfl;
pPrior = pOvfl.aData;
put4byte(pPrior, 0);
pPayload = pointer(pOvfl.aData, 4);
spaceLeft = pBt.usableSize - 4;
}
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.
*/
assert (pToRelease == null || pToRelease.pDbPage.isWriteable());
/*
* If pPayload is part of the data area of pPage, then make sure
* pPage* is still writeable
*/
assert (pPayload.getBuffer() != pPage.aData.getBuffer() || pPage.pDbPage.isWriteable());
if (nSrc > 0) {
if (n > nSrc)
n = nSrc;
assert (pSrc != null);