private void WriteObjectPart(long id, long objOffset, byte[] buffer, int off, int length)
{
// ASSERT: Read and Write position must be 64K aligned.
if (objOffset%(PageSize*1024) != 0)
throw new Exception("Assert failed: offset is not 64k aligned.");
// ASSERT: Length is less than or equal to 64K
if (length > (PageSize * 1024)) {
throw new Exception("Assert failed: length is greater than 64K.");
}
int refCount;
long objPos;
long maxSize;
long currentSize;
lock (fixedList) {
if (id < 0 || id >= fixedList.NodeCount)
throw new IOException("Object id is out of range.");
IArea block = fixedList.GetRecord(id);
var status = block.ReadInt4();
if ((status & DeletedFlag) != 0)
throw new InvalidOperationException("Assertion failed: record is deleted!");
block.ReadInt4(); // Ref count
maxSize = block.ReadInt8(); // Total Size / Max Size
currentSize = block.ReadInt8(); // Current Size
objPos = block.ReadInt8(); // Last Page Position
}
// Open an IArea into the blob
IArea area = store.GetArea(objPos);
area.ReadInt4();
var type = area.ReadInt4();
var size = area.ReadInt8();
// Assert that the area being Read is within the bounds of the blob
if (objOffset < 0 || objOffset + length > size) {
throw new IOException("Object invalid write. offset = " + objOffset + ", length = " + length + ", size = " + size);
}
// Convert to the page number
long pageNumber = (objOffset / (PageSize * 1024));
area.Position = (int)((pageNumber * 8) + 32);
long pagePos = area.ReadInt8();
if (pagePos != -1) {
// This means we are trying to rewrite a page we've already written
// before.
throw new Exception("Assert failed: page position is not -1");
}
// Is the compression bit set?
byte[] toWrite;
int writeLength;
if ((type & CompressedFlag) != 0) {
// Yes, compression
#if !PCL
using (var input = new MemoryStream(buffer, off, length)) {
using (var output = new MemoryStream(PageSize * 1024)) {
using (var deflateStream = new DeflateStream(output, CompressionMode.Compress, false)) {
input.CopyTo(deflateStream);
deflateStream.Flush();
deflateStream.Close();
toWrite = output.ToArray();
writeLength = toWrite.Length;
}
}
}
#else
throw new NotSupportedException("Compression not supported in PCL.");
#endif
} else {
// No compression
toWrite = buffer;
writeLength = length;
}
try {
store.Lock();
// Allocate and Write the page.
IArea pageArea = store.CreateArea(writeLength + 8);
pagePos = pageArea.Id;
pageArea.WriteInt4(1);
pageArea.WriteInt4(writeLength);
pageArea.Write(toWrite, 0, writeLength);
// Finish this page
pageArea.Flush();
// Update the page in the header.
area.Position = (int)((pageNumber * 8) + 24);
area.WriteInt8(currentSize + writeLength);
area.WriteInt8(pagePos);
// Check out this change.
area.Flush();
} finally {
store.Unlock();
}
}