/**
* Copyright 2011-2012 Akiban Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.persistit;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import com.persistit.util.Util;
/**
* This class encapsulates the formats of Persistit journal records. There is
* one inner class per record type. The following describes the byte layout
* implemented by these classes.
*
* All multi-byte integers are stored in big-endian form. General record format:
*
* <table border="1">
* <tr valign="top">
* <td>+0</td>
* <td>length</td>
* </tr>
* <tr valign="top">
* <td>+4</td>
* <td>type</td>
* </tr>
* <tr valign="top">
* <td>+8</td>
* <td>timestamp</td>
* </tr>
* <tr valign="top">
* <td>+16</td>
* <td>payload</td>
* </tr>
* </table>
* <p />
* Type: two ASCII bytes:
* <p />
* <table border="1">
*
* <tr valign="top">
* <td>JH</td>
* <td>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.
* <table>
* <tr valign="top">
* <td>+16</td>
* <td>Version (long)</td>
* </tr>
* <tr valign="top">
* <td>+24</td>
* <td>Journal file size (long)</td>
* </tr>
* <tr valign="top">
* <td>+32</td>
* <td>Current journal address (long)</td>
* </tr>
* <tr valign="top">
* <td>+40</td>
* <td>Base journal address (long)</td>
* </tr>
* <tr valign="top">
* <td>+48</td>
* <td>Journal created timestamp (long)</td>
* </tr>
* <tr valign="top">
* <td>+56</td>
* <td>Journal file created timestamp (long)</td>
* </tr>
* <tr valign="top">
* <td>+64</td>
* <td>Last valid checkpoint timestamp (long)</td>
* </tr>
* <tr valign="top">
* <td>+72</td>
* <td>Reserved (8 bytes)</td>
* </tr>
* <tr valign="top">
* <td>+80</td>
* <td>Journal File Path (variable - length determined by record length)</td>
* </tr>
* </table>
* </td>
* </tr>
*
* <tr valign="top">
* <td>JE</td>
* <td>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.
* <table>
* <tr valign="top">
* <td>+16</td>
* <td>Current journal address (long)</td>
* </tr>
* <tr valign="top">
* <td>+24</td>
* <td>Base journal address (long)</td>
* </tr>
* <tr valign="top">
* <td>+32</td>
* <td>Journal created timestamp (long)</td>
* </tr>
* </table>
* </td>
* </tr>
*
* <tr valign="top">
* <td>IV</td>
* <td>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.
* <table>
* <tr valign="top">
* <td>+16</td>
* <td>Volume handle (int)</td>
* </tr>
* <tr valign="top">
* <td>+20</td>
* <td>Volume Id (long)</td>
* </tr>
* <tr valign="top">
* <td>+28</td>
* <td>Volume Path (variable - length determined by record length)</td>
* </tr>
* </table>
* </td>
* </tr>
*
* <tr valign="top">
* <td>IT</td>
* <td>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.
* <table>
* <tr valign="top">
* <td>+16</td>
* <td>Tree handle (int)</td>
* </tr>
* <tr valign="top">
* <td>+20</td>
* <td>Volume handle (int)</td>
* </tr>
* <tr valign="top">
* <td>+24</td>
* <td>Tree Name (variable - length determined by record length)</td>
* </tr>
* </table>
* </td>
* </tr>
*
* <tr valign="top">
* <td>PA</td>
* <td>Page Image
* <table>
* <tr valign="top">
* <td>+16</td>
* <td>Volume handle (int) - refers to a volume defined in a preceding IV record
* </td>
* </tr>
* <tr valign="top">
* <td>+20</td>
* <td>page address (long)</td>
* </tr>
* <tr valign="top">
* <td>+28</td>
* <td>leftSize (int)</td>
* </tr>
* <tr valign="top">
* <td>+32</td>
* <td>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</td>
* </tr>
* </table>
* </td>
* </tr>
*
* <tr valign="top">
* <td>PM</td>
* <td>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.
* <table>
* <tr valign="top">
* <td>+16</td>
* <td></td>
* <td>Instances of the following fixed-length structure (28 bytes), number
* determined by overall record size
* <table>
* <tr valign="top">
* <td>+0</td>
* <td>Transaction timestamp (long)</td>
* </tr>
* <tr valign="top">
* <td>+8</td>
* <td>Journal address (long)</td>
* </tr>
* <tr valign="top">
* <td>+16</td>
* <td>Volume handle (int) - refers to a volume defined in a preceding IV record
* </td>
* </tr>
* <tr valign="top">
* <td>+20</td>
* <td>Page address (long)</td>
* </tr>
* </table>
* </td>
* </tr>
* </table>
* </td>
* </tr>
*
* <tr valign="top">
* <td>TM</td>
* <td>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.
* <table>
* <tr valign="top">
* <td>+16</td>
* <td></td>
* <td>Instances of the following fixed-length structure (24 bytes) number
* determined by overall record size
* <table>
* <tr valign="top">
* <td>+0</td>
* <td>Transaction timestamp (long)</td>
* </tr>
* <tr valign="top">
* <td>+8</td>
* <td>Journal address (long)</td>
* </tr>
* <tr valign="top">
* <td>+16</td>
* <td>isCommitted (byte) - indicates whether this transaction committed</td>
* </tr>
* </table>
* </td>
* </tr>
* </table>
* </td>
* </tr>
*
* <tr valign="top">
* <td>CP</td>
* <td>Checkpoint. Specifies a timestamp and a system time in millis at which
* all pages modified prior to that timestamp are present in the log.
* <table>
* <tr valign="top">
* <td>+16</td>
* <td>System time in milliseconds (long)</td>
* </tr>
* <tr valign="top">
* <td>+24</td>
* <td>Base journal address (long)</td>
* </tr>
* </table>
* </td>
* </tr>
*
* <tr valign="top">
* <td>TX</td>
* <td>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.
* <table>
* <tr valign="top">
* <td>+16</td>
* <td>Commit timestamp, or -1 if the transaction has not committed.</td>
* </tr>
* <tr valign="top">
* <td>+24</td>
* <td>Previous record journal address (long).</td>
* </tr>
* <tr valign="top">
* <td>+32</td>
* <td>serialized updates as a series of contiguous SR, DR, DT, DV, and CU
* records</td>
* </tr>
* </table>
* </tr>
*
* </table>
* <p>
* 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.
*
*
* <table border="1">
* <tr valign="top">
* <td>SR</td>
* <td>Store Record - specifies a Tree into which a key/value pair should be
* inserted
* <table>
* <tr valign="top">
* <td>+8</td>
* <td>Tree handle (int) - matches a tree identified in a preceding IT record</td>
* </tr>
* <tr valign="top">
* <td>+12</td>
* <td>Key size (short)</td>
* </tr>
* <tr valign="top">
* <td>+14</td>
* <td>Key bytes immediately followed by Value bytes (variable).</td>
* </tr>
* </table>
*
* <tr valign="top">
* <td>DR</td>
* <td>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.
* <table>
* <tr valign="top">
* <td>+8</td>
* <td>Tree handle (int) - matches a tree identified in a preceding IT record</td>
* </tr>
* <tr valign="top">
* <td>+12</td>
* <td>Key1_size (short)</td>
* </tr>
* <tr valign="top">
* <td>+14</td>
* <td>Key2 Elision_count (short)</td>
* </tr>
* <tr valign="top">
* <td>+16</td>
* <td>Key bytes</td>
* </tr>
* </table>
* </tr>
*
* <tr valign="top">
* <td>DT</td>
* <td>Delete Tree - specifies a Tree to be deleted.
* <table>
* <tr valign="top">
* <td>+8</td>
* <td>Tree handle (int) - matches a tree identified in a preceding IT record</td>
* </tr>
* </table>
* </tr>
*
* </tr>
* <tr valign="top">
* <td>DV</td>
* <td>Delete Volume - specifies a Volume to be deleted.
* <table>
* <tr valign="top">
* <td>+8</td>
* <td>Volume handle (int) - matches a volume identified in a preceding IV
* record</td>
* </tr>
* </table>
* </tr>
*
* <tr valign="top">
* <td>D1</td>
* <td>Delta with 1 long-valued argument - encapsulates an update with argument
* to a <code>Delta</code> (see @link Accumulator}
* <table>
* <tr valign="top">
* <td>+8</td>
* <td>Tree handle (int) - matches a tree identified in a preceding IT record</td>
* instance</td>
* </tr>
* <tr valign="top">
* <td>+12</td>
* <td>index (char) - an Accumulator index</td>
* </tr>
* <tr valign="top">
* <td>+14</td>
* <td>type (char) - type of Accumulator (0=SUM, 1=MAX, 2=MIN, 3=SEQ)</td>
* </tr>
* <tr valign="top">
* <td>+16</td>
* <td>argument (long) - value by which the Delta is to be adjusted</td>
* </tr>
* </table>
* </tr>
*
* <tr valign="top">
* <td>D0</td>
* <td>Delta with no argument - encapsulates an update with a argument value of
* 1 to a <code>Delta</code> (see @link Accumulator}
* <table>
* <tr valign="top">
* <td>+8</td>
* <td>Tree handle (int) - matches a tree identified in a preceding IT record</td>
* instance</td>
* </tr>
* <tr valign="top">
* <td>+12</td>
* <td>index (char) - an Accumulator index</td>
* </tr>
* <tr valign="top">
* <td>+14</td>
* <td>type (char) - type of Accumulator (0=SUM, 1=MAX, 2=MIN, 3=SEQ)</td>
* </tr>
* </table> </tr>
*
* </table>
*
* @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);
}
}
}