Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
Journal Header: written as the first record of each journal file.
* Identifies the version, creation timestamp of the journal, created timestamp
* of the journal file and path to which journal file was originally written.
*
*
*
+16
*
Version (long)
*
*
*
+24
*
Journal file size (long)
*
*
*
+32
*
Current journal address (long)
*
*
*
+40
*
Base journal address (long)
*
*
*
+48
*
Journal created timestamp (long)
*
*
*
+56
*
Journal file created timestamp (long)
*
*
*
+64
*
Last valid checkpoint timestamp (long)
*
*
*
+72
*
Reserved (8 bytes)
*
*
*
+80
*
Journal File Path (variable - length determined by record length)
*
*
*
*
*
*
*
JE
*
Journal End: written as the last record of each journal file. Indicates
* that the next valid record is in the next journal file, and confirms that the
* journal file is complete. Lack of a JE record at the end of a journal file
* indicates the system did not shut down normally.
*
*
*
+16
*
Current journal address (long)
*
*
*
+24
*
Base journal address (long)
*
*
*
+32
*
Journal created timestamp (long)
*
*
*
*
*
*
*
IV
*
Identify Volume: associates an integer handle to a Volume. This handle is
* referenced by subsequent log records to identify this Volume. The handle has
* no meaning beyond the scope of one log file; every new log generation gets
* new IV records.
*
*
*
+16
*
Volume handle (int)
*
*
*
+20
*
Volume Id (long)
*
*
*
+28
*
Volume Path (variable - length determined by record length)
*
*
*
*
*
*
*
IT
*
Identify Tree: associates an integer handle to a Tree. This handle is
* referenced by subsequent log records to identify this Tree. The handle has no
* meaning beyond the scope of one log file; every new log generation gets new
* IT records.
*
*
*
+16
*
Tree handle (int)
*
*
*
+20
*
Volume handle (int)
*
*
*
+24
*
Tree Name (variable - length determined by record length)
*
*
*
*
*
*
*
PA
*
Page Image
*
*
*
+16
*
Volume handle (int) - refers to a volume defined in a preceding IV record
*
*
*
*
+20
*
page address (long)
*
*
*
+28
*
leftSize (int)
*
*
*
+32
*
bytes: the first leftSize bytes will go into the page at offset 0 the
* remaining bytes will go to the end of the page; the middle of the page will
* be cleared
*
*
*
*
*
*
*
PM
*
Page Map: written once near the top of each journal file. Represents the
* state of the page map at the time the journal rolled over.
*
*
*
+16
*
*
Instances of the following fixed-length structure (28 bytes), number
* determined by overall record size
*
*
*
+0
*
Transaction timestamp (long)
*
*
*
+8
*
Journal address (long)
*
*
*
+16
*
Volume handle (int) - refers to a volume defined in a preceding IV record
*
*
*
*
+20
*
Page address (long)
*
*
*
*
*
*
*
*
*
*
TM
*
Transaction Map: written once near the top of each journal file.
* Represents map of transactions still open (started, but neither rolled back
* nor committed) at the time the journal rolled over.
*
*
*
+16
*
*
Instances of the following fixed-length structure (24 bytes) number
* determined by overall record size
*
*
*
+0
*
Transaction timestamp (long)
*
*
*
+8
*
Journal address (long)
*
*
*
+16
*
isCommitted (byte) - indicates whether this transaction committed
*
*
*
*
*
*
*
*
*
*
CP
*
Checkpoint. Specifies a timestamp and a system time in millis at which
* all pages modified prior to that timestamp are present in the log.
*
*
*
+16
*
System time in milliseconds (long)
*
*
*
+24
*
Base journal address (long)
*
*
*
*
*
*
*
TX
*
Transaction update record - encapsulates a set of updates applied to the
* database. This record type encapsulates SR, DR, DT, DV, and CU records
* defined below.
*
*
*
+16
*
Commit timestamp, or -1 if the transaction has not committed.
*
*
*
+24
*
Previous record journal address (long).
*
*
*
+32
*
serialized updates as a series of contiguous SR, DR, DT, DV, and CU
* records
*
*
*
*
*
*
* The following sub-record types are encapsulated inside of a TX record. Their
* format differs from the main record types by not including timestamp or
* backpointer fields.
*
*
*
*
*
SR
*
Store Record - specifies a Tree into which a key/value pair should be
* inserted
*
*
*
+8
*
Tree handle (int) - matches a tree identified in a preceding IT record
*
*
*
+12
*
Key size (short)
*
*
*
+14
*
Key bytes immediately followed by Value bytes (variable).
*
*
*
*
*
DR
*
Delete Record - specifies a Tree and two Keys: all key/value pairs
* between these two keys (inclusive) are deleted. The Key bytes field defines
* two keys, key1 and key2. These delimit the range to be deleted. The first
* Key1_size bytes of this field contain the encoded key1 value. The remaining
* bytes define key2. The first Elision_count bytes of Key2 are the same as
* Key1; only the remaining unique bytes are stored in the record.
*
*
*
+8
*
Tree handle (int) - matches a tree identified in a preceding IT record
*
*
*
+12
*
Key1_size (short)
*
*
*
+14
*
Key2 Elision_count (short)
*
*
*
+16
*
Key bytes
*
*
*
*
*
*
DT
*
Delete Tree - specifies a Tree to be deleted.
*
*
*
+8
*
Tree handle (int) - matches a tree identified in a preceding IT record
*
*
*
*
*
*
*
DV
*
Delete Volume - specifies a Volume to be deleted.
*
*
*
+8
*
Volume handle (int) - matches a volume identified in a preceding IV
* record
*
*
*
*
*
*
D1
*
Delta with 1 long-valued argument - encapsulates an update with argument
* to a Delta (see @link Accumulator}
*
*
*
+8
*
Tree handle (int) - matches a tree identified in a preceding IT record
* instance
*
*
*
+12
*
index (char) - an Accumulator index
*
*
*
+14
*
type (char) - type of Accumulator (0=SUM, 1=MAX, 2=MIN, 3=SEQ)
*
*
*
+16
*
argument (long) - value by which the Delta is to be adjusted
*
*
*
*
*
*
D0
*
Delta with no argument - encapsulates an update with a argument value of
* 1 to a Delta (see @link Accumulator}
*
*
*
+8
*
Tree handle (int) - matches a tree identified in a preceding IT record
* instance
*
*
*
+12
*
index (char) - an Accumulator index
*
*
*
+14
*
type (char) - type of Accumulator (0=SUM, 1=MAX, 2=MIN, 3=SEQ)
*
*
*
*
*
* @author peter
*
*/
public class JournalRecord {
/**
* Minimum length of first-level record
*/
final static int OVERHEAD = 16;
/**
* Minimum length of a sub-record inside of a TX
*/
final static int SUB_RECORD_OVERHEAD = 12;
private final static Charset UTF8 = Charset.forName("UTF-8");
public final static int[] TYPES = new int[] { JE.TYPE, JH.TYPE, PA.TYPE, PM.TYPE, SR.TYPE, DR.TYPE, DT.TYPE,
TM.TYPE, CP.TYPE, IV.TYPE, IT.TYPE, D1.TYPE, D0.TYPE, TX.TYPE };
public static boolean isValidType(final int t) {
for (final int type : TYPES) {
if (t == type) {
return true;
}
}
return false;
}
public static String str(final int t) {
if (isValidType(t)) {
return new String(new char[] { (char) ((t >>> 8) & 0xFF), (char) (t & 0xFF) });
} else {
return "??";
}
}
private static void putByte(final ByteBuffer bb, final int offset, final int value) {
Util.putByte(bb.array(), bb.position() + offset, value);
}
static int getByte(final ByteBuffer bb, final int offset) {
return Util.getByte(bb.array(), bb.position() + offset);
}
static void putChar(final ByteBuffer bb, final int offset, final int value) {
Util.putChar(bb.array(), bb.position() + offset, value);
}
static int getChar(final ByteBuffer bb, final int offset) {
return Util.getChar(bb.array(), bb.position() + offset);
}
static void putInt(final ByteBuffer bb, final int offset, final int value) {
Util.putInt(bb.array(), bb.position() + offset, value);
}
static int getInt(final ByteBuffer bb, final int offset) {
return Util.getInt(bb.array(), bb.position() + offset);
}
static void putLong(final ByteBuffer bb, final int offset, final long value) {
Util.putLong(bb.array(), bb.position() + offset, value);
}
static long getLong(final ByteBuffer bb, final int offset) {
return Util.getLong(bb.array(), bb.position() + offset);
}
static int getLength(final ByteBuffer bb) {
return getInt(bb, 0);
}
static void putLength(final ByteBuffer bb, final int length) {
putInt(bb, 0, length);
}
public static int getType(final ByteBuffer bb) {
return getChar(bb, 4);
}
static void putType(final ByteBuffer bb, final int type) {
putChar(bb, 4, type);
}
public static long getTimestamp(final ByteBuffer bb) {
return getLong(bb, 8);
}
public static void putTimestamp(final ByteBuffer bb, final long timestamp) {
putLong(bb, 8, timestamp);
}
/**
* Journal End
*/
static class JE extends JournalRecord {
public final static int TYPE = ('J' << 8) | 'E';
public final static int OVERHEAD = 40;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static long getCurrentJournalAddress(final ByteBuffer bb) {
return getLong(bb, 16);
}
public static void putCurrentJournalAddress(final ByteBuffer bb, final long address) {
putLong(bb, 16, address);
}
public static long getBaseAddress(final ByteBuffer bb) {
return getLong(bb, 24);
}
public static void putBaseAddress(final ByteBuffer bb, final long address) {
putLong(bb, 24, address);
}
public static long getJournalCreatedTime(final ByteBuffer bb) {
return getLong(bb, 32);
}
public static void putJournalCreatedTime(final ByteBuffer bb, final long time) {
putLong(bb, 32, time);
}
}
/**
* Journal header
*/
static class JH extends JournalRecord {
public final static int TYPE = ('J' << 8) | 'H';
public final static int OVERHEAD = 64;
public final static int MAX_LENGTH = OVERHEAD + 2048;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static long getVersion(final ByteBuffer bb) {
return getLong(bb, 16);
}
public static void putVersion(final ByteBuffer bb, final long version) {
putLong(bb, 16, version);
}
public static long getBaseJournalAddress(final ByteBuffer bb) {
return getLong(bb, 24);
}
public static void putBaseJournalAddress(final ByteBuffer bb, final long address) {
putLong(bb, 24, address);
}
public static long getCurrentJournalAddress(final ByteBuffer bb) {
return getLong(bb, 32);
}
public static void putCurrentJournalAddress(final ByteBuffer bb, final long address) {
putLong(bb, 32, address);
}
public static long getJournalCreatedTime(final ByteBuffer bb) {
return getLong(bb, 40);
}
public static void putJournalCreatedTime(final ByteBuffer bb, final long time) {
putLong(bb, 40, time);
}
public static long getFileCreatedTime(final ByteBuffer bb) {
return getLong(bb, 48);
}
public static void putFileCreatedTime(final ByteBuffer bb, final long time) {
putLong(bb, 48, time);
}
public static long getBlockSize(final ByteBuffer bb) {
return getLong(bb, 56);
}
public static void putBlockSize(final ByteBuffer bb, final long size) {
putLong(bb, 56, size);
}
public static String getPath(final ByteBuffer bb) {
final int length = getLength(bb) - OVERHEAD;
return new String(bb.array(), bb.position() + OVERHEAD, length, UTF8);
}
public static void putPath(final ByteBuffer bb, final String path) {
final byte[] stringBytes = path.getBytes(UTF8);
System.arraycopy(stringBytes, 0, bb.array(), bb.position() + OVERHEAD, stringBytes.length);
putLength(bb, OVERHEAD + stringBytes.length);
}
}
/**
* Page Map
*/
static class PM extends JournalRecord {
public final static int TYPE = ('P' << 8) | 'M';
public final static int OVERHEAD = 16;
public final static int ENTRY_SIZE = 28;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static int getEntryCount(final ByteBuffer bb) {
final int length = getLength(bb) - OVERHEAD;
return length / ENTRY_SIZE;
}
public static long getEntryTimestamp(final ByteBuffer bb, final int index) {
return getLong(bb, (index * ENTRY_SIZE));
}
public static long getEntryJournalAddress(final ByteBuffer bb, final int index) {
return getLong(bb, 8 + (index * ENTRY_SIZE));
}
public static int getEntryVolumeHandle(final ByteBuffer bb, final int index) {
return getInt(bb, 16 + (index * ENTRY_SIZE));
}
public static long getEntryPageAddress(final ByteBuffer bb, final int index) {
return getLong(bb, 20 + (index * ENTRY_SIZE));
}
public static void putEntry(final ByteBuffer bb, final int index, final long timestamp,
final long journalAddress, final int volumeHandle, final long pageAddress) {
putLong(bb, 0 + (index * ENTRY_SIZE), timestamp);
putLong(bb, 8 + (index * ENTRY_SIZE), journalAddress);
putInt(bb, 16 + (index * ENTRY_SIZE), volumeHandle);
putLong(bb, 20 + (index * ENTRY_SIZE), pageAddress);
}
}
/**
* Transaction Map
*/
static class TM extends JournalRecord {
public final static int TYPE = ('T' << 8) | 'M';
public final static int OVERHEAD = 16;
public final static int ENTRY_SIZE = 32;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static int getEntryCount(final ByteBuffer bb) {
final int length = getLength(bb) - OVERHEAD;
return length / ENTRY_SIZE;
}
public static long getEntryStartTimestamp(final ByteBuffer bb, final int index) {
return getLong(bb, (index * ENTRY_SIZE));
}
public static long getEntryCommitTimestamp(final ByteBuffer bb, final int index) {
return getLong(bb, 8 + (index * ENTRY_SIZE));
}
public static long getEntryJournalAddress(final ByteBuffer bb, final int index) {
return getLong(bb, 16 + (index * ENTRY_SIZE));
}
public static long getLastRecordAddress(final ByteBuffer bb, final int index) {
return getLong(bb, 24 + (index * ENTRY_SIZE));
}
public static void putEntry(final ByteBuffer bb, final int index, final long startTimestamp,
final long commitTimestamp, final long journalAddress, final long lastRecordAddress) {
putLong(bb, 0 + (index * ENTRY_SIZE), startTimestamp);
putLong(bb, 8 + (index * ENTRY_SIZE), commitTimestamp);
putLong(bb, 16 + (index * ENTRY_SIZE), journalAddress);
putLong(bb, 24 + (index * ENTRY_SIZE), lastRecordAddress);
}
}
/**
* Identify Volume
*/
static class IV extends JournalRecord {
public final static int TYPE = ('I' << 8) | 'V';
public final static int OVERHEAD = 28;
public final static int MAX_LENGTH = OVERHEAD + 2048;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static int getHandle(final ByteBuffer bb) {
return getInt(bb, 16);
}
public static void putHandle(final ByteBuffer bb, final int handle) {
putInt(bb, 16, handle);
}
public static long getVolumeId(final ByteBuffer bb) {
return getLong(bb, 20);
}
public static void putVolumeId(final ByteBuffer bb, final long volumeId) {
putLong(bb, 20, volumeId);
}
public static String getVolumeSpecification(final ByteBuffer bb) {
final int length = getLength(bb) - OVERHEAD;
return new String(bb.array(), bb.position() + OVERHEAD, length, UTF8);
}
public static void putVolumeSpecification(final ByteBuffer bb, final String volumeSpec) {
final byte[] stringBytes = volumeSpec.getBytes(UTF8);
System.arraycopy(stringBytes, 0, bb.array(), bb.position() + OVERHEAD, stringBytes.length);
putLength(bb, OVERHEAD + stringBytes.length);
}
}
/**
* Identify Tree
*/
static class IT extends JournalRecord {
public final static int TYPE = ('I' << 8) | 'T';
public final static int OVERHEAD = 24;
public final static int MAX_LENGTH = OVERHEAD + 1024;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static int getHandle(final ByteBuffer bb) {
return getInt(bb, 16);
}
public static void putHandle(final ByteBuffer bb, final int handle) {
putInt(bb, 16, handle);
}
public static int getVolumeHandle(final ByteBuffer bb) {
return getInt(bb, 20);
}
public static void putVolumeHandle(final ByteBuffer bb, final int volumeHandle) {
putInt(bb, 20, volumeHandle);
}
public static String getTreeName(final ByteBuffer bb) {
final int length = getLength(bb) - OVERHEAD;
return new String(bb.array(), bb.position() + OVERHEAD, length, UTF8);
}
public static void putTreeName(final ByteBuffer bb, final String treeName) {
final byte[] stringBytes = treeName.getBytes(UTF8);
System.arraycopy(stringBytes, 0, bb.array(), bb.position() + OVERHEAD, stringBytes.length);
putLength(bb, OVERHEAD + stringBytes.length);
}
}
/**
* Page
*/
static class PA extends JournalRecord {
public final static int TYPE = ('P' << 8) | 'A';
public final static int OVERHEAD = 36;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static int getVolumeHandle(final ByteBuffer bb) {
return getInt(bb, 16);
}
public static void putVolumeHandle(final ByteBuffer bb, final int volumeHandle) {
putInt(bb, 16, volumeHandle);
}
public static long getPageAddress(final ByteBuffer bb) {
return getLong(bb, 20);
}
public static void putPageAddress(final ByteBuffer bb, final long pageAddress) {
putLong(bb, 20, pageAddress);
}
public static int getLeftSize(final ByteBuffer bb) {
return getInt(bb, 28);
}
public static void putLeftSize(final ByteBuffer bb, final int leftSize) {
putInt(bb, 28, leftSize);
}
public static int getBufferSize(final ByteBuffer bb) {
return getInt(bb, 32);
}
public static void putBufferSize(final ByteBuffer bb, final int bufferSize) {
putInt(bb, 32, (char) bufferSize);
}
}
/**
* Checkpoint
*/
static class CP extends JournalRecord {
public final static int TYPE = ('C' << 8) | 'P';
public final static int OVERHEAD = 32;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static long getSystemTimeMillis(final ByteBuffer bb) {
return getLong(bb, 16);
}
public static void putSystemTimeMillis(final ByteBuffer bb, final long systemTimeMillis) {
putLong(bb, 16, systemTimeMillis);
}
public static long getBaseAddress(final ByteBuffer bb) {
return getLong(bb, 24);
}
public static void putBaseAddress(final ByteBuffer bb, final long base) {
putLong(bb, 24, base);
}
}
/**
* Transaction update envelope
*/
static class TX extends JournalRecord {
public final static int TYPE = ('T' << 8) | 'X';
public final static int OVERHEAD = 32;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static long getCommitTimestamp(final ByteBuffer bb) {
return getLong(bb, 16);
}
public static void putCommitTimestamp(final ByteBuffer bb, final long address) {
putLong(bb, 16, address);
}
public static long getBackchainAddress(final ByteBuffer bb) {
return getLong(bb, 24);
}
public static void putBackchainAddress(final ByteBuffer bb, final long address) {
putLong(bb, 24, address);
}
}
/*
* -------------------------------------------------------------
*
* The following record types occur only within the scope of a TX record.
*
* -------------------------------------------------------------
*/
/**
* Store Record
*/
static class SR extends JournalRecord {
public final static int TYPE = ('S' << 8) | 'R';
public final static int OVERHEAD = 14;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static void putTreeHandle(final ByteBuffer bb, final int handle) {
putInt(bb, 8, handle);
}
public static int getTreeHandle(final ByteBuffer bb) {
return getInt(bb, 8);
}
public static void putKeySize(final ByteBuffer bb, final int size) {
putChar(bb, 12, size);
}
public static int getKeySize(final ByteBuffer bb) {
return getChar(bb, 12);
}
}
/**
* Delete Record
*/
static class DR extends JournalRecord {
public final static int TYPE = ('D' << 8) | 'R';
public final static int OVERHEAD = 16;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static void putTreeHandle(final ByteBuffer bb, final int handle) {
putInt(bb, 8, handle);
}
public static int getTreeHandle(final ByteBuffer bb) {
return getInt(bb, 8);
}
public static void putKey1Size(final ByteBuffer bb, final int size) {
putChar(bb, 12, size);
}
public static int getKey1Size(final ByteBuffer bb) {
return getChar(bb, 12);
}
public static void putKey2Elision(final ByteBuffer bb, final int elisionCount) {
putChar(bb, 14, elisionCount);
}
public static int getKey2Elision(final ByteBuffer bb) {
return getChar(bb, 14);
}
}
/**
* Delete Tree
*/
static class DT extends JournalRecord {
public final static int TYPE = ('D' << 8) | 'T';
public final static int OVERHEAD = 12;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static void putTreeHandle(final ByteBuffer bb, final int handle) {
putInt(bb, 8, handle);
}
public static int getTreeHandle(final ByteBuffer bb) {
return getInt(bb, 8);
}
}
static class D1 extends JournalRecord {
public final static int TYPE = ('D' << 8) | '1';
public final static int OVERHEAD = 24;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static void putTreeHandle(final ByteBuffer bb, final int handle) {
putInt(bb, 8, handle);
}
public static int getTreeHandle(final ByteBuffer bb) {
return getInt(bb, 8);
}
public static void putIndex(final ByteBuffer bb, final int index) {
putChar(bb, 12, index);
}
public static int getIndex(final ByteBuffer bb) {
return getChar(bb, 12);
}
public static void putAccumulatorTypeOrdinal(final ByteBuffer bb, final int type) {
putChar(bb, 14, type);
}
public static int getAccumulatorTypeOrdinal(final ByteBuffer bb) {
return getChar(bb, 14);
}
public static long getValue(final ByteBuffer bb) {
return getLong(bb, 16);
}
public static void putValue(final ByteBuffer bb, final long value) {
putLong(bb, 16, value);
}
}
static class D0 extends JournalRecord {
public final static int TYPE = ('D' << 8) | '0';
public final static int OVERHEAD = 16;
public static void putType(final ByteBuffer bb) {
putType(bb, TYPE);
}
public static void putTreeHandle(final ByteBuffer bb, final int handle) {
putInt(bb, 8, handle);
}
public static int getTreeHandle(final ByteBuffer bb) {
return getInt(bb, 8);
}
public static void putIndex(final ByteBuffer bb, final int index) {
putChar(bb, 12, index);
}
public static int getIndex(final ByteBuffer bb) {
return getChar(bb, 12);
}
public static void putAccumulatorTypeOrdinal(final ByteBuffer bb, final int type) {
putChar(bb, 14, type);
}
public static int getAccumulatorTypeOrdinal(final ByteBuffer bb) {
return getChar(bb, 14);
}
}
}