public boolean readOne() {
    if (!excerpt.nextIndex()) {
      //            System.out.println("r- " + excerpt.index());
      return false;
    }

    long pos = excerpt.position();
    //        System.out.println("r " + excerpt.index() + " " + excerpt.capacity());
    MessageType mt = excerpt.readEnum(MessageType.class);
    if (mt == null) {
      // rewind and read again.
      excerpt.position(pos);
      System.err.println("Unknown message type " + excerpt.readUTFΔ());
      return true;
    }
    switch (mt) {
      case small:
        {
          metaData.sourceId = sourceId;
          metaData.readFromGateway(excerpt);
          smallCommand.readMarshallable(excerpt);
          peEvents.small(metaData, smallCommand);
          break;
        }
      default:
        System.err.println("Unknown message type " + mt);
        break;
    }
    return true;
  }
  public static void main(@NotNull String... args) throws IOException, InterruptedException {
    if (args.length < 1) {
      System.err.println(
          "Usage: java " + ChronicleReader.class.getName() + " {chronicle-base-path} [from-index]");
      System.exit(-1);
    }

    String basePath = args[0];
    long index = args.length > 1 ? Long.parseLong(args[1]) : 0L;
    IndexedChronicle ic = new IndexedChronicle(basePath);
    ExcerptTailer excerpt = ic.createTailer();
    //noinspection InfiniteLoopStatement
    while (true) {
      while (!excerpt.nextIndex())
        //noinspection BusyWait
        Thread.sleep(50);
      System.out.print(index + ": ");
      int nullCount = 0;
      while (excerpt.remaining() > 0) {
        char ch = (char) excerpt.readUnsignedByte();
        if (ch == 0) {
          nullCount++;
          continue;
        }
        if (nullCount > 0) System.out.print(" " + nullCount + "*\\0");
        nullCount = 0;
        if (ch < ' ') System.out.print("^" + (char) (ch + '@'));
        else if (ch > 126) System.out.print("\\x" + Integer.toHexString(ch));
        else System.out.print(ch);
      }
      if (nullCount > 0) System.out.print(" " + nullCount + "*\\0");
      System.out.println();
      index++;
    }
  }
  @SuppressWarnings("unchecked")
  public static void main(String... args) throws ParseException, JoranException, IOException {
    Parser parser = new BasicParser();
    CommandLine cl = null;
    try {
      cl = parser.parse(OPTS, args);
    } catch (ParseException e) {
      HelpFormatter help = new HelpFormatter();
      help.printHelp("dlog", OPTS, true);
      System.exit(-1);
    }

    LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
    loggerContext.reset();

    if (cl.hasOption("config")) {
      // Read Logback configuration
      JoranConfigurator configurator = new JoranConfigurator();
      configurator.setContext(loggerContext);

      configurator.doConfigure(cl.getOptionValue("file", "logback.xml"));

      StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext);
    } else {
      BasicConfigurator.configure(loggerContext);
    }

    Appender appender = null;
    if (cl.hasOption("output")) {
      String outputAppender = cl.getOptionValue("output", "console");
      appender = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME).getAppender(outputAppender);
    }

    ChronicleTools.warmup();
    Chronicle chronicle = new IndexedChronicle(cl.getOptionValue("path"), ChronicleConfig.DEFAULT);
    ExcerptTailer ex = chronicle.createTailer();

    Level level = Level.valueOf(cl.getOptionValue("level", "TRACE"));

    if (cl.hasOption("head")) {
      int lines = Integer.parseInt(cl.getOptionValue("head", "10"));
      for (int i = 0; i < lines; i++) {
        LoggingEvent evt = readLoggingEvent(ex, loggerContext);
        if (evt.getLevel().isGreaterOrEqual(level)) {
          writeEvent(evt, appender);
        }
      }
    } else if (cl.hasOption("tail")) {
      int lines = Integer.parseInt(cl.getOptionValue("tail", "10"));
      Queue<LoggingEvent> tail = new LinkedBlockingQueue<LoggingEvent>(lines);
      while (ex.nextIndex()) {
        LoggingEvent evt = readLoggingEvent(ex, loggerContext);
        if (!tail.offer(evt)) {
          tail.poll();
          tail.add(evt);
        }
      }
      LoggingEvent evt;
      while (null != (evt = tail.poll())) {
        if (evt.getLevel().isGreaterOrEqual(level)) {
          writeEvent(evt, appender);
        }
      }
    } else if (cl.hasOption("search")) {
      String regex = cl.getOptionValue("search");
      Pattern regexPatt = Pattern.compile(regex);
      while (ex.nextIndex()) {
        LoggingEvent evt = readLoggingEvent(ex, loggerContext);
        if (null != evt && evt.getLevel().isGreaterOrEqual(level)) {
          if (regexPatt.matcher(evt.getFormattedMessage()).matches()) {
            writeEvent(evt, appender);
          }
        }
      }
    }

    loggerContext.stop();
    chronicle.close();
  }