// Path: c5-replicator-util/src/main/java/c5db/log/EntryEncodingUtil.java
// public static <T> T decodeAndCheckCrc(InputStream inputStream, Schema<T> schema)
//     throws IOException, CrcError {
//   // TODO this should check the length first and compare it with a passed-in maximum length
//   final T message = schema.newMessage();
//   final CrcInputStream crcStream = new CrcInputStream(inputStream, new Adler32());
//   ProtobufIOUtil.mergeDelimitedFrom(crcStream, message, schema);
// 
//   final long computedCrc = crcStream.getValue();
//   final long diskCrc = readCrc(inputStream);
//   if (diskCrc != computedCrc) {
//     throw new CrcError("CRC mismatch on deserialized message " + message.toString());
//   }
// 
//   return message;
// }
// 
// Path: c5-replicator-log/src/main/java/c5db/log/LogPersistenceService.java
// interface BytePersistence extends AutoCloseable {
//   /**
//    * Determine if the store is empty.
//    *
//    * @return True if empty, otherwise false.
//    * @throws IOException
//    */
//   boolean isEmpty() throws IOException;
// 
//   /**
//    * Get the size in bytes of the data, equal to the position/address of
//    * next byte to be appended.
//    *
//    * @return Size in bytes.
//    * @throws IOException
//    */
//   long size() throws IOException;
// 
//   /**
//    * Append data.
//    *
//    * @param buffers Data to append.
//    *                IOException if the persistence is closed, or if the underlying object is inaccessible.
//    */
//   void append(ByteBuffer[] buffers) throws IOException;
// 
//   /**
//    * Get a new reader of the data. Each reader is independent of any other,
//    * and the caller takes responsibility for releasing associated resources.
//    *
//    * @return A new reader instance.
//    * @throws IOException
//    */
//   PersistenceReader getReader() throws IOException;
// 
//   /**
//    * Truncate data from the end, to a certain size.
//    *
//    * @param size New size of the data, equal to the position/address of the next
//    *             byte to be appended after the truncation. After calling this method,
//    *             the size() method will return this value of size.
//    * @throws IOException if the persistence is closed, or if the underlying object is inaccessible.
//    */
//   void truncate(long size) throws IOException;
// 
//   /**
//    * Sync previous operations to the underlying medium.
//    *
//    * @throws IOException if the persistence is closed, or if the underlying object is inaccessible.
//    */
//   void sync() throws IOException;
// 
//   /**
//    * Release held resources.
//    *
//    * @throws IOException
//    */
//   void close() throws IOException;
// }
// 
// Path: c5-replicator-log/src/main/java/c5db/log/LogPersistenceService.java
// interface PersistenceReader extends ReadableByteChannel, AutoCloseable {
//   long position() throws IOException;
// 
//   void position(long newPos) throws IOException;
// }


import java.util.Locale;
import static c5db.log.EntryEncodingUtil.decodeAndCheckCrc;
import static c5db.log.LogPersistenceService.BytePersistence;
import static c5db.log.LogPersistenceService.PersistenceReader;
import c5db.interfaces.log.SequentialEntryCodec;
import c5db.log.generated.OLogHeader;
import c5db.replication.generated.QuorumConfigurationMessage;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.channels.Channels;
import java.util.Formatter;
import java.util.List;

  private static void formatContent(Formatter formatter, OLogEntryDescription entry) {
    switch (entry.getType()) {
      case QUORUM_CONFIGURATION:
        formatter.format(" [quorum configuration: ");
        formatConfiguration(formatter, entry.getQuorumConfiguration().toProtostuff());
        formatter.format("]");
        break;
      case DATA:
        formatter.format(" [content length: %" + INT_DIGITS + "d]", entry.getContentLength());
        break;
      default:
        throw new AssertionError("Unhandled enum value in CatOLog#formatContent");
    }
  }

  private static void formatConfiguration(Formatter formatter, QuorumConfigurationMessage message) {
    formatter.format("(");
    if (message.getTransitional()) {
      formatPeerIdList(formatter, message.getPrevPeersList());
      formatter.format(" -> ");
      formatPeerIdList(formatter, message.getNextPeersList());
    } else {
      formatPeerIdList(formatter, message.getAllPeersList());
    }
    formatter.format(")");
  }

  private static void formatPeerIdList(Formatter formatter, List<Long> peerIdList) {
    Joiner joiner = Joiner.on(", ");
// Path: c5-replicator-util/src/main/java/c5db/log/EntryEncodingUtil.java
// public static <T> T decodeAndCheckCrc(InputStream inputStream, Schema<T> schema)
//     throws IOException, CrcError {
//   // TODO this should check the length first and compare it with a passed-in maximum length
//   final T message = schema.newMessage();
//   final CrcInputStream crcStream = new CrcInputStream(inputStream, new Adler32());
//   ProtobufIOUtil.mergeDelimitedFrom(crcStream, message, schema);
// 
//   final long computedCrc = crcStream.getValue();
//   final long diskCrc = readCrc(inputStream);
//   if (diskCrc != computedCrc) {
//     throw new CrcError("CRC mismatch on deserialized message " + message.toString());
//   }
// 
//   return message;
// }
// 
// Path: c5-replicator-log/src/main/java/c5db/log/LogPersistenceService.java
// interface BytePersistence extends AutoCloseable {
//   /**
//    * Determine if the store is empty.
//    *
//    * @return True if empty, otherwise false.
//    * @throws IOException
//    */
//   boolean isEmpty() throws IOException;
// 
//   /**
//    * Get the size in bytes of the data, equal to the position/address of
//    * next byte to be appended.
//    *
//    * @return Size in bytes.
//    * @throws IOException
//    */
//   long size() throws IOException;
// 
//   /**
//    * Append data.
//    *
//    * @param buffers Data to append.
//    *                IOException if the persistence is closed, or if the underlying object is inaccessible.
//    */
//   void append(ByteBuffer[] buffers) throws IOException;
// 
//   /**
//    * Get a new reader of the data. Each reader is independent of any other,
//    * and the caller takes responsibility for releasing associated resources.
//    *
//    * @return A new reader instance.
//    * @throws IOException
//    */
//   PersistenceReader getReader() throws IOException;
// 
//   /**
//    * Truncate data from the end, to a certain size.
//    *
//    * @param size New size of the data, equal to the position/address of the next
//    *             byte to be appended after the truncation. After calling this method,
//    *             the size() method will return this value of size.
//    * @throws IOException if the persistence is closed, or if the underlying object is inaccessible.
//    */
//   void truncate(long size) throws IOException;
// 
//   /**
//    * Sync previous operations to the underlying medium.
//    *
//    * @throws IOException if the persistence is closed, or if the underlying object is inaccessible.
//    */
//   void sync() throws IOException;
// 
//   /**
//    * Release held resources.
//    *
//    * @throws IOException
//    */
//   void close() throws IOException;
// }
// 
// Path: c5-replicator-log/src/main/java/c5db/log/LogPersistenceService.java
// interface PersistenceReader extends ReadableByteChannel, AutoCloseable {
//   long position() throws IOException;
// 
//   void position(long newPos) throws IOException;
// }


// Path: cat-olog/src/main/java/c5db/log/CatOLog.java
import java.util.Locale;
import static c5db.log.EntryEncodingUtil.decodeAndCheckCrc;
import static c5db.log.LogPersistenceService.BytePersistence;
import static c5db.log.LogPersistenceService.PersistenceReader;
import c5db.interfaces.log.SequentialEntryCodec;
import c5db.log.generated.OLogHeader;
import c5db.replication.generated.QuorumConfigurationMessage;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.channels.Channels;
import java.util.Formatter;
import java.util.List;


  private static void formatContent(Formatter formatter, OLogEntryDescription entry) {
    switch (entry.getType()) {
      case QUORUM_CONFIGURATION:
        formatter.format(" [quorum configuration: ");
        formatConfiguration(formatter, entry.getQuorumConfiguration().toProtostuff());
        formatter.format("]");
        break;
      case DATA:
        formatter.format(" [content length: %" + INT_DIGITS + "d]", entry.getContentLength());
        break;
      default:
        throw new AssertionError("Unhandled enum value in CatOLog#formatContent");
    }
  }

  private static void formatConfiguration(Formatter formatter, QuorumConfigurationMessage message) {
    formatter.format("(");
    if (message.getTransitional()) {
      formatPeerIdList(formatter, message.getPrevPeersList());
      formatter.format(" -> ");
      formatPeerIdList(formatter, message.getNextPeersList());
    } else {
      formatPeerIdList(formatter, message.getAllPeersList());
    }
    formatter.format(")");
  }

  private static void formatPeerIdList(Formatter formatter, List<Long> peerIdList) {
    Joiner joiner = Joiner.on(", ");
    formatter.format(joiner.join(peerIdList));