Class ReadTransaction

java.lang.Object
com.iizix.ReadTransaction
All Implemented Interfaces:
ITransaction

public class ReadTransaction extends Object implements ITransaction
This transaction class is used for all communication between the Server, Client and Remote Administration programs. It is used to stream out transaction specific data that is streamed in on the other end.

Note: All "synchronization" calls are now removed for performance reasons, so threaded access to a transaction instance should be synchronized by the calling threads.

Author:
Christopher Mindus
  • Method Details

    • getLongData

      public static byte[] getLongData(int val)
      Static helper method to get the 4-byte representation of a 32 bit signed value.
      Parameters:
      val - The 32-bit value.
      Returns:
      A byte array of 4 in length of the 32-bit value.
    • from

      public static ReadTransaction from(byte[] data, HashMap<Integer,String> readCache)
      Creates a transaction with a read cache.
      Parameters:
      data - The data array to initialize this read-type transaction with.
      readCache - The read cache to use, null for none.
    • getByte

      public int getByte()
      Get an unsigned byte from the incoming data without moving the read position.
      Returns:
      A byte value 0x00 to 0xFF.
      Throws:
      RuntimeException - If the position exceeds the read buffer.
    • readTransaction

      public ReadTransaction readTransaction()
      Retrieves a sub-transaction from an incoming transaction.
      Returns:
      null if no more sub-transactions exist.
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer.
    • getRemainingReadSize

      public int getRemainingReadSize()
      Gets the remaining size in bytes for read methods in the transaction. This is useful to see if a transaction has read all its data.
      Returns:
      Byte count value.
    • getTotalReadSize

      public int getTotalReadSize()
      Gets the size of the read transaction.
      Returns:
      Byte count value.
    • skipBytes

      public void skipBytes(int count)
      Skips a number of bytes for reading.
      Parameters:
      count - Count of bytes to skip in the read data.
      Throws:
      IllegalArgumentException - If count is negative or if count is too large and is past the buffer.
    • smartSkip

      public void smartSkip(int size)
      Skips a number of bytes for reading by WALKING them: every element in the region is read with the ordinary type-driven read method and its value is discarded. Use this, never skipBytes(int), to skip data that was written with the append methods of SendTransaction.

      The reason is the string cache. A cached string travels ONCE with its definition, i.e. its index and its text, and as the index alone from then on, and the sender keeps no record of whether the receiver parsed the definition. Bytes skipped unparsed can hold such a definition. The index then resolves to nothing here or, once the sender has reused the index of an evicted string, to the PREVIOUS string, and a field displays another property's text. Walking the region registers every definition exactly as a real parse would, and that is the only side effect of this method.

      The walk is possible because the stream describes itself when data types are included: every element starts with its type byte. There is ONE exception, the byte array: ITransaction.TYPE_BYTES carries no length on the wire, its reader is expected to know it. By the convention of ByteArrayProp, the only property value holding one, the count is the unsigned integer appended IMMEDIATELY before the array, and that is what the walk uses. A byte array preceded by anything else cannot be walked and is refused. A sub-transaction is walked recursively.

      The walk must not begin at the first read position of a transaction whose first element is a sub-transaction: that one alone carries no type byte, see readTransaction(), and it is refused as an unknown data type.

      The JavaScript Transaction.smartSkip in transaction.js is the same walk, case for case. A data type added to one must be added to the other.

      Parameters:
      size - Count of bytes to walk in the read data.
      Throws:
      IllegalStateException - If data types are not included in transactions: nothing can then be walked. It asserts that the build is sane and is never a runtime path.
      IllegalArgumentException - If size is negative or is past the buffer.
      InternalError - If the walk does not land EXACTLY on the end of the region, for an unknown data type, or for a byte array that is not preceded by its unsigned count. Each means that the sender and this receiver disagree about the encoding: the read cache can no longer be trusted, and the caller must not carry on with the session.
      RuntimeException - As the read methods throw it, for a wrong data type or a read outside the buffer.
      See Also:
    • getSmartSkipElements

      public int getSmartSkipElements()
      Gets the count of elements the last call to smartSkip(int) walked, for the log line of the caller. An element is one typed value, and a sub-transaction counts as one element plus the elements inside it.

      The byte count needs no accessor: the walk lands exactly on the end of the region or throws, so it is the size the caller passed.

      Returns:
      The element count, zero when nothing has been smart-skipped.
    • readByte

      public int readByte()
      Reads an unsigned byte from the incoming data.
      Returns:
      A byte value 0-255 from the data.
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer.
    • readBytes

      public byte[] readBytes(int count)
      Reads a byte array from the incoming data.
      Parameters:
      count - Count of bytes to read.
      Returns:
      The newly allocated bytes read.
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the count exceeds what remains of this transaction's read buffer.
    • readChar

      public char readChar()
      Reads an encoded character in a byte from the incoming data. If the transactions use Unicode only, two bytes are read, otherwise just one using the codepage conversion or the default ISO 8859-1 character set. A unicode character is preceded with the '\xFF' character, meaning that 3 bytes are used for the Unicode character.

      The character has, due to Java itself, a code point between U+0000 and U+FFFF, i.e. 16 bits. The additional so called "surrogate pair characters" (two "char" in an array) having the code points U+000000 to U+10FFFF cannot be used here.

      The range of legal code points is now U+0000 to U+10FFFF, known as Unicode scalar value. The set of characters from U+0000 to U+FFFF is sometimes referred to as the Basic Multilingual Plane (BMP). Characters whose code points are greater than U+FFFF are called supplementary characters, and not supported here.

      Encoding: if the character ASCII (code point) value is up to 254 inclusive (i.e. smaller than 0xFF), a single byte is added, otherwise 3 character.

      Returns:
      the character read.
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer.
    • readBoolean

      public boolean readBoolean()
      Reads a boolean from incoming data.
      Returns:
      true if read byte is non-zero, false otherwise.
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer.
    • readUnsigned

      public int readUnsigned()
      Reads an unsigned integer of the range 0x00000000 to 0x3FFFFFFF. The space occupied in the transaction is 1 to 4 bytes.
      Returns:
      The unsigned integer.
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer.
    • readSigned

      public int readSigned()
      Reads a signed integer of the range -0x1FFFFFFF to 0x1FFFFFFF. The space occupied in the transaction is 1 to 4 bytes.
      Returns:
      The signed integer.
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer.
    • readShort

      public int readShort()
      Reads a 16 bit signed value from the incoming data.
      Returns:
      A value -0x8000 to 0x7FFF.
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer.
    • readUShort

      public int readUShort()
      Reads a 16 bit unsigned value from the incoming data.
      Returns:
      A value 0x0000 to 0xFFFF.
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer.
    • readLong

      public int readLong()
      Reads a 32 bit signed value from the incoming data.
      Returns:
      A value Integer.MIN_VALUE to Integer.MAX_VALUE.
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer.
    • readLong64

      public long readLong64()
      Reads a 64 bit signed value from the incoming data.
      Returns:
      A value Long.MIN_VALUE to Long.MAX_VALUE.
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer.
    • readFloat

      public float readFloat()
      Reads a float value from the incoming data.
      Returns:
      A float value (32 bits).
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer.
    • readDouble

      public double readDouble()
      Reads a 64 bit double value from the incoming data.
      Returns:
      A double value (64 bits).
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer.
    • readNumber

      public double readNumber()
      Reads a JavaScript Number from transaction.
      Returns:
      A double Number value (64 bits).
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer.
    • readString

      public String readString()
      Reads a string from the incoming data. The string may be encoded in Ansi or Unicode formats.
      Returns:
      the string read, possibly using a read cache.
      Throws:
      IllegalStateException - For wrong data type.
      RuntimeException - If the position exceeds the read buffer, or the String does not exist in read cache.