while (pagePointer >= 0 && currentPos < recordEntry.length) {
recordPosition = (int) (pagePointer & RECORD_POSITION_MASK);
pageIndex = pagePointer >>> PAGE_INDEX_OFFSET;
int freePageIndex;
final OCacheEntry cacheEntry = diskCache.load(fileId, pageIndex, false);
cacheEntry.acquireExclusiveLock();
try {
final OClusterPage localPage = new OClusterPage(cacheEntry, false, trackMode);
int freeSpace = localPage.getFreeSpace();
freePageIndex = calculateFreePageIndex(localPage);
final int chunkSize = localPage.getRecordSize(recordPosition);
final long nextPagePointer = localPage.getRecordLongValue(recordPosition, -OLongSerializer.LONG_SIZE);
int newChunkLen = Math.min(recordEntry.length - currentPos + OLongSerializer.LONG_SIZE + OByteSerializer.BYTE_SIZE,
chunkSize);
int dataLen = newChunkLen - OLongSerializer.LONG_SIZE - OByteSerializer.BYTE_SIZE;
byte[] newRecordChunk = new byte[newChunkLen];
System.arraycopy(recordEntry, currentPos, newRecordChunk, 0, dataLen);
if (currentPos > 0)
newRecordChunk[newRecordChunk.length - OLongSerializer.LONG_SIZE - OByteSerializer.BYTE_SIZE] = 0;
else
newRecordChunk[newRecordChunk.length - OLongSerializer.LONG_SIZE - OByteSerializer.BYTE_SIZE] = 1;
OLongSerializer.INSTANCE.serializeNative(-1L, newRecordChunk, newRecordChunk.length - OLongSerializer.LONG_SIZE);
if (prevPageRecordPointer >= 0) {
long prevPageIndex = prevPageRecordPointer >>> PAGE_INDEX_OFFSET;
int prevPageRecordPosition = (int) (prevPageRecordPointer & RECORD_POSITION_MASK);
final OCacheEntry prevPageCacheEntry = diskCache.load(fileId, prevPageIndex, false);
prevPageCacheEntry.acquireExclusiveLock();
try {
final OClusterPage prevPage = new OClusterPage(prevPageCacheEntry, false, trackMode);
prevPage.setRecordLongValue(prevPageRecordPosition, -OLongSerializer.LONG_SIZE, pagePointer);
logPageChanges(prevPage, fileId, prevPageIndex, false);
prevPageCacheEntry.markDirty();
} finally {
prevPageCacheEntry.releaseExclusiveLock();
diskCache.release(prevPageCacheEntry);
}
}
localPage.replaceRecord(recordPosition, newRecordChunk, recordVersion.getCounter() != -2 ? recordVersion : null);
currentPos += dataLen;
recordsSizeDiff += freeSpace - localPage.getFreeSpace();
prevPageRecordPointer = pagePointer;
pagePointer = nextPagePointer;
logPageChanges(localPage, fileId, pageIndex, false);
} finally {
cacheEntry.releaseExclusiveLock();
diskCache.release(cacheEntry);
}
updateFreePagesIndex(freePageIndex, pageIndex, trackMode);
}
int from = currentPos;
int to = from + (OClusterPage.MAX_RECORD_SIZE - OByteSerializer.BYTE_SIZE - OLongSerializer.LONG_SIZE);
if (to > recordEntry.length)
to = recordEntry.length;
while (from < to) {
byte[] entryContent = new byte[to - from + OByteSerializer.BYTE_SIZE + OLongSerializer.LONG_SIZE];
System.arraycopy(recordEntry, from, entryContent, 0, to - from);
if (from > 0)
entryContent[entryContent.length - OLongSerializer.LONG_SIZE - OByteSerializer.BYTE_SIZE] = 0;
else
entryContent[entryContent.length - OLongSerializer.LONG_SIZE - OByteSerializer.BYTE_SIZE] = 1;
OLongSerializer.INSTANCE.serializeNative(-1L, entryContent, entryContent.length - OLongSerializer.LONG_SIZE);
final AddEntryResult addEntryResult = addEntry(recordVersion, entryContent, trackMode);
recordsSizeDiff += addEntryResult.recordsSizeDiff;
long addedPagePointer = createPagePointer(addEntryResult.pageIndex, addEntryResult.pagePosition);
if (prevPageRecordPointer >= 0) {
long prevPageIndex = prevPageRecordPointer >>> PAGE_INDEX_OFFSET;
int prevPageRecordPosition = (int) (prevPageRecordPointer & RECORD_POSITION_MASK);
final OCacheEntry prevPageCacheEntry = diskCache.load(fileId, prevPageIndex, false);
prevPageCacheEntry.acquireExclusiveLock();
try {
final OClusterPage prevPage = new OClusterPage(prevPageCacheEntry, false, trackMode);
prevPage.setRecordLongValue(prevPageRecordPosition, -OLongSerializer.LONG_SIZE, addedPagePointer);
logPageChanges(prevPage, fileId, prevPageIndex, false);
prevPageCacheEntry.markDirty();
} finally {
prevPageCacheEntry.releaseExclusiveLock();
diskCache.release(prevPageCacheEntry);
}
}
prevPageRecordPointer = addedPagePointer;