- OIntegerSerializer.INT_SIZE;
crc32.update(fullEntryContent, 0, crcPosition);
final int crc = OIntegerSerializer.INSTANCE.deserializeNative(fullEntryContent, crcPosition);
if (crc != (int) crc32.getValue())
throw new OStorageException("Content of record for cluster with id " + id + " and position " + clusterPosition
+ " is broken.");
}
int updatedContentLength = content.length + 2 * OByteSerializer.BYTE_SIZE + OIntegerSerializer.INT_SIZE
+ OLongSerializer.LONG_SIZE;
if (useCRC32)
updatedContentLength += OIntegerSerializer.INT_SIZE;
byte[] recordEntry;
if (updatedContentLength <= fullEntryContent.length)
recordEntry = new byte[fullEntryContent.length - OLongSerializer.LONG_SIZE - OByteSerializer.BYTE_SIZE];
else {
final int grownContent = (int) (content.length * config.recordOverflowGrowFactor);
if (!useCRC32)
recordEntry = new byte[grownContent + OByteSerializer.BYTE_SIZE + OIntegerSerializer.INT_SIZE];
else
recordEntry = new byte[grownContent + OByteSerializer.BYTE_SIZE + 2 * OIntegerSerializer.INT_SIZE];
}
final OClusterPage.TrackMode trackMode = getTrackMode();
startAtomicOperation();
try {
lockTillAtomicOperationCompletes();
int entryPosition = 0;
recordEntry[entryPosition] = recordType;
entryPosition++;
OIntegerSerializer.INSTANCE.serializeNative(content.length, recordEntry, entryPosition);
entryPosition += OIntegerSerializer.INT_SIZE;
System.arraycopy(content, 0, recordEntry, entryPosition, content.length);
if (useCRC32) {
CRC32 crc32 = new CRC32();
final int crcPosition = recordEntry.length - OIntegerSerializer.INT_SIZE;
crc32.update(recordEntry, 0, crcPosition);
OIntegerSerializer.INSTANCE.serializeNative((int) crc32.getValue(), recordEntry, crcPosition);
}
int recordsSizeDiff = 0;
long prevPageRecordPointer = -1;
int currentPos = 0;
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;
from = to;
to = to + (OClusterPage.MAX_RECORD_SIZE - OLongSerializer.LONG_SIZE - OByteSerializer.BYTE_SIZE);
if (to > recordEntry.length)
to = recordEntry.length;
}
updateClusterState(trackMode, 0, recordsSizeDiff);
endAtomicOperation(false);
} catch (Throwable e) {
endAtomicOperation(true);
throw new OStorageException(null, e);
}
} finally {
releaseExclusiveLock();
}
} finally {