package water;
import java.io.IOException;
import java.nio.channels.ByteChannel;
import java.nio.channels.SocketChannel;
/**
* <p>This class is used to coordinate the requests for accessing/obtaining H2O frames from non-H2O environments
* ( ie. Spark Executors).</p>
*
* <p>The user should use {@code getConnection} method to open a connection to an H2O node. This method creates the socket channel
* in a way h2o internals expect it.</p>
*
* <p>The data can be written to h2o frame and read data from h2o frame.
* When writing, it is expected that empty H2O frame is already in DKV before using the writing API. The caller
* is responsible for finishing the frame once all data has been written to the frame. To read more about the writing
* API, please read documentation of {@link ExternalFrameWriterClient}</p>
*
* <p>When reading the data, it is expected that h2o frame is in DKV. To read more about the reading API, please read
* documentation of {@link ExternalFrameReaderClient}</p>
*
*
*/
final class ExternalFrameHandler {
/**
* This is used to inform us that another byte is coming.
* That byte can be either {@code MARKER_ORIGINAL_VALUE} or {@code MARKER_NA}. If it's
* {@code MARKER_ORIGINAL_VALUE}, that means
* the value sent is in the previous data sent, otherwise the value is NA.
*/
static final byte NUM_MARKER_NEXT_BYTE_FOLLOWS = 127;
/**
* Same as above, but for Strings. We are using unicode code for CONTROL, which should be very very rare
* String to send as usual String data.
*/
static final String STR_MARKER_NEXT_BYTE_FOLLOWS = "\u0080";
/**
* Marker informing us that the data are not NA and are stored in the previous byte
*/
static final byte MARKER_ORIGINAL_VALUE = 0;
/**
* Marker informing us that the data being sent is NA
*/
static final byte MARKER_NA = 1;
/** Byte signaling that new communication has been started on a existing/newly created socket channel
* Since connections can reused at the caller site ( for example spark executor ) we have to identify whether the
* the connection has been reused for sending more data or not
* */
static final byte INIT_BYTE = 42;
/**
* Bytes used for signaling that either reading from h2o frame or writing to h2o frame has finished.
* It is important for these 2 bytes to be different, otherwise we could confirm writing by reading byte, which
* would lead to unwanted states.
*/
static final byte CONFIRM_READING_DONE = 1;
static final byte CONFIRM_WRITING_DONE = 2;
/**
* Main task codes
*/
static final byte CREATE_FRAME = 0;
static final byte DOWNLOAD_FRAME = 1;
/**
* Method which receives the {@link ByteChannel} and {@link AutoBuffer} and dispatches the request for further processing
*/
void process(ByteChannel sock, AutoBuffer ab) throws IOException {
int requestType = ab.get1();
switch (requestType) {
case CREATE_FRAME:
ExternalFrameWriterBackend.handleWriteToChunk(sock, ab);
break;
case DOWNLOAD_FRAME:
ExternalFrameReaderBackend.handleReadingFromChunk(sock, ab);
break;
}
}
}