Here you can find the source of readFromAnerisChannel(ReadableByteChannel chan, ByteBuffer buffer)
Reads the next Aneris message from this channel and returns it in String form.
Parameter | Description |
---|---|
Exception | if a problem occurred while reading the message. |
public static String readFromAnerisChannel(ReadableByteChannel chan, ByteBuffer buffer) throws Exception
//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); } }