* Append the data into the head of the array
*/
public long append(byte[] data) throws IOException {
try {
arrayReadLock.lock();
IMappedPage toAppendDataPage = null;
IMappedPage toAppendIndexPage = null;
long toAppendIndexPageIndex = -1L;
long toAppendDataPageIndex = -1L;
long toAppendArrayIndex = -1L;
try {
appendLock.lock(); // only one thread can append
if (this.isFull()) { // end of the world check:)
throw new IOException("ring space of java long type used up, the end of the world!!!");
}
// prepare the data pointer
if (this.headDataItemOffset + data.length > DATA_PAGE_SIZE) { // not enough space
if (this.headDataPageIndex == Long.MAX_VALUE) {
this.headDataPageIndex = 0L; // wrap
} else {
this.headDataPageIndex++;
}
this.headDataItemOffset = 0;
}
toAppendDataPageIndex = this.headDataPageIndex;
int toAppendDataItemOffset = this.headDataItemOffset;
toAppendArrayIndex = this.arrayHeadIndex.get();
// append data
toAppendDataPage = this.dataPageFactory.acquirePage(toAppendDataPageIndex);
ByteBuffer toAppendDataPageBuffer = toAppendDataPage.getLocal(toAppendDataItemOffset);
toAppendDataPageBuffer.put(data);
toAppendDataPage.setDirty(true);
// update to next
this.headDataItemOffset += data.length;
toAppendIndexPageIndex = Calculator.div(toAppendArrayIndex, INDEX_ITEMS_PER_PAGE_BITS); // shift optimization
toAppendIndexPage = this.indexPageFactory.acquirePage(toAppendIndexPageIndex);
int toAppendIndexItemOffset = (int) (Calculator.mul(Calculator.mod(toAppendArrayIndex, INDEX_ITEMS_PER_PAGE_BITS), INDEX_ITEM_LENGTH_BITS));
// update index
ByteBuffer toAppendIndexPageBuffer = toAppendIndexPage.getLocal(toAppendIndexItemOffset);
toAppendIndexPageBuffer.putLong(toAppendDataPageIndex);
toAppendIndexPageBuffer.putInt(toAppendDataItemOffset);
toAppendIndexPageBuffer.putInt(data.length);
long currentTime = System.currentTimeMillis();
toAppendIndexPageBuffer.putLong(currentTime);
toAppendIndexPage.setDirty(true);
// advance the head
this.arrayHeadIndex.incrementAndGet();
// update meta data
IMappedPage metaDataPage = this.metaPageFactory.acquirePage(META_DATA_PAGE_INDEX);
ByteBuffer metaDataBuf = metaDataPage.getLocal(0);
metaDataBuf.putLong(this.arrayHeadIndex.get());
metaDataBuf.putLong(this.arrayTailIndex.get());
metaDataPage.setDirty(true);
} finally {
appendLock.unlock();