Java ReadableByteChannel Read readFromAnerisChannel(ReadableByteChannel chan, ByteBuffer buffer)

Here you can find the source of readFromAnerisChannel(ReadableByteChannel chan, ByteBuffer buffer)

Description

Reads the next Aneris message from this channel and returns it in String form.

License

Open Source License

Exception

Parameter Description
Exception if a problem occurred while reading the message.

Declaration

public static String readFromAnerisChannel(ReadableByteChannel chan, ByteBuffer buffer) throws Exception 

Method Source Code

//package com.java2s;
/* Copyright 2012 Cornell University
 * Copyright 2013 Cornell University/*from ww w.  j a va2 s . co  m*/
 *
 *
 * This file is part of ShadowDB - a replicated database based on
 * an formally-verified implementation of an atomic broadcast service.
 * The normal case processing is written in Java, while failure-handling is taken
 * care of by an atomic broadcast service called Aneris. Aneris contains
 * two formally-verified implementations of atomic broadcast, one is
 * based on Paxos, the other one is based on two-third consensus.
 * 
 * The three code contributors of this project are:
 * Vincent Rahli (Aneris)
 * Nicolas Schiper (ShadowDB)
 * Mark Bickford (Aneris)
 * 
 * ShadowDB was implemented at Cornell University, Ithaca, NY.
 *
 * ShadowDB is a free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ShadowDB is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ShadowDB.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  o Authors:     Nicolas Schiper
 *  o Affiliation: Cornell University
 *  o Date:        13 May 2013
 *  o File name:   NIOUtils.java
 *  o Description: A utility class to interact with non-blocking channels.
 */

import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;

public class Main {
    public static final int ERROR_HEADER_INT = -2;
    /**
     * When reading from an Aneris channel, we will retry a couple
     * of times before giving up and considering the other end crashed.
     * More specifically, we will retry {@code RETRIAL_COUNT} times and
     * sleep {@code SLEEP_TIME_BETWEEN_TRIALS} number of times.
     */
    private static final int RETRIAL_COUNT = 1000;
    private static final int SLEEP_TIME_BETWEEN_TRIALS = 1;

    /**
     * <p> Reads the next Aneris message from this channel and returns it in String form.
     * 
     * <p> This method uses an "ad-hoc" way to detect that the end host crashed: if after reading data
     * {@value #RETRIAL_COUNT} times from the channel (and sleeping {@value #SLEEP_TIME_BETWEEN_TRIALS} ms between
     * trials) no bytes could be read, we consider the end host dead and return null.
     * 
     * <p> This method also returns null if the other end closes the connection before we read
     * the string in its entirety.
     * 
     * @throws Exception if a problem occurred while reading the message.
     */
    public static String readFromAnerisChannel(ReadableByteChannel chan, ByteBuffer buffer) throws Exception {

        int nbBytes = readAnerisHeader(chan, buffer);

        if (nbBytes != ERROR_HEADER_INT) {
            buffer.position(0);
            buffer.limit(nbBytes);

            int trialNo = 1;

            while (buffer.hasRemaining()) {
                int bytesRead = chan.read(buffer);
                if (bytesRead == 0) {
                    if (trialNo < RETRIAL_COUNT) {
                        trialNo++;
                        Thread.sleep(SLEEP_TIME_BETWEEN_TRIALS);
                    } else {
                        return null;
                    }
                } else if (chan.read(buffer) < 0) {
                    return null;
                }
            }
            buffer.flip();
            byte[] msgInBytes = new byte[nbBytes];
            buffer.get(msgInBytes);
            String msg = new String(msgInBytes);

            return msg;
        } else {
            return null;
        }
    }

    /**
     * <p> Reads a header from the given channel connected to the Aneris service using the provided buffer.
     * The header is returned as an integer. If the header could not be read,
     * {@code ERROR_HEADER_INT} is returned.
     * 
     * <p> This method uses an "ad-hoc" way to detect that the end host crashed: if after reading data
     * {@value #RETRIAL_COUNT} times from the channel (and sleeping {@value #SLEEP_TIME_BETWEEN_TRIALS} ms between
     * trials) no bytes could be read, we consider the end host dead and return {@code ERROR_HEADER_INT}.
     */
    public static int readAnerisHeader(ReadableByteChannel from, ByteBuffer buffer) throws Exception {

        int headerLength = 0;
        int trialNo = 1;

        do {
            buffer.position(headerLength);
            headerLength++;
            buffer.limit(headerLength);

            while (buffer.hasRemaining()) {
                int bytesRead = from.read(buffer);

                if (bytesRead == 0) {
                    Thread.sleep(SLEEP_TIME_BETWEEN_TRIALS);
                    trialNo++;
                    if (trialNo == RETRIAL_COUNT) {
                        return ERROR_HEADER_INT;
                    }
                } else if (bytesRead < 0) {
                    return ERROR_HEADER_INT;
                }
            }
        } while (buffer.get(headerLength - 1) != '!');

        // The returned header does not include the '!'.
        byte[] headerBytes = new byte[headerLength - 1];
        buffer.flip();
        buffer.get(headerBytes);
        String headerStr = new String(headerBytes);
        return Integer.parseInt(headerStr);
    }
}

Related

  1. readAll(ReadableByteChannel ch, ByteBuffer dst)
  2. readAllBytesOrNone(ReadableByteChannel channel, ByteBuffer buffer, int numBytes)
  3. readAnerisHeader(ReadableByteChannel from, ByteBuffer buffer)
  4. readBuffer(ReadableByteChannel chan, ByteBuffer buf)
  5. readCharArray(ReadableByteChannel channel, ByteBuffer buffer, char[] charArray)
  6. readFromChannel(ReadableByteChannel channel, ByteBuffer buffer)
  7. readFull(ReadableByteChannel ch, ByteBuffer dst)
  8. readFully(final ReadableByteChannel channel, final ByteBuffer buf)
  9. readFully(final ReadableByteChannel channel, final ByteBuffer buf)