/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package com.github.geophile.erdo; import com.github.geophile.erdo.apiimpl.DeletedRecord; import com.github.geophile.erdo.map.Factory; import com.github.geophile.erdo.map.LazyRecord; import com.github.geophile.erdo.map.diskmap.DiskPage; import com.github.geophile.erdo.transaction.Transaction; import com.github.geophile.erdo.util.Transferrable; import java.io.IOException; import java.nio.ByteBuffer; /** * AbstractRecord is the base class for Erdo records. Applications need to provide subclasses that contain record state, * serialize and deserialize, copy a record, provide an estimate of serialized size. * * This class contains several undocumented methods. These need to be public for implementation reasons, but are not * intended to be used by applications or by AbstractKey subclasses. */ public abstract class AbstractRecord<KEY extends AbstractKey> extends LazyRecord<KEY> implements Transferrable { // Object interface @Override public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append('('); buffer.append(key().toString()); Transaction transaction = key.transaction(); if (transaction != null) { buffer.append("/"); buffer.append(transaction.toString()); } buffer.append(')'); return buffer.toString(); } // Transferrable interface /** * Read the state of this record from the given buffer. * @param buffer contains the serialized state of the record. * @throws java.nio.BufferUnderflowException */ public void readFrom(ByteBuffer buffer) {} /** * Write the state of this record to the given buffer. * @param buffer container of the serialized record. * @throws java.nio.BufferOverflowException */ public void writeTo(ByteBuffer buffer) {} public int recordCount() { return 1; } // LazyRecord interface @Override public final KEY key() { return key; } @Override public ByteBuffer keyBuffer() throws IOException, InterruptedException { throw new UnsupportedOperationException(); } @Override public AbstractRecord<KEY> materializeRecord() throws IOException, InterruptedException { return this; } @Override public ByteBuffer recordBuffer() throws IOException, InterruptedException { throw new UnsupportedOperationException(); } @Override public long estimatedSizeBytes() { return key.estimatedSizeBytes(); } @Override public boolean prefersSerialized() { return false; } @Override public void destroyRecordReference() { } // AbstractRecord interface public boolean deleted() { return key.deleted(); } /** * Returns a copy of this record. The original and the copy should not share mutable state, so that if one is changed * in any way, the other is not affected. * @return A copy of this record. */ public abstract AbstractRecord<KEY> copy(); public static AbstractRecord deserialize(Factory factory, DiskPage.AccessBuffers pageAccessBuffers, int erdoId, long timestamp) { ByteBuffer keyBuffer = pageAccessBuffers.keyBuffer(); ByteBuffer recordBuffer = pageAccessBuffers.recordBuffer(); keyBuffer.mark(); recordBuffer.mark(); try { // key AbstractKey key = factory.recordFactory(erdoId).newKey(); key.erdoId(erdoId); key.readFrom(keyBuffer); key.transactionTimestamp(timestamp); // record AbstractRecord record; if (key.deleted()) { record = new DeletedRecord(key); } else { record = factory.recordFactory(erdoId).newRecord(); record.key = key; record.readFrom(recordBuffer); } return record; } finally { keyBuffer.reset(); recordBuffer.reset(); } } // For use by subclasses protected AbstractRecord() {} protected AbstractRecord(boolean deleted) { key.deleted(deleted); } protected AbstractRecord(KEY key) { this.key = key; } protected AbstractRecord(AbstractRecord record) { key = (KEY) record.key.copy(); } // Object state private KEY key; }