@Override
    public void run() {
      try {
        long index = readIndex(socket);
        Excerpt excerpt = chronicle.createExcerpt();
        ByteBuffer bb = TcpUtil.createBuffer(1, chronicle); // minimum size
        long sendInSync = 0;
        boolean first = true;
        OUTER:
        while (!closed) {
          while (!excerpt.index(index)) {
            //                        System.out.println("Waiting for " + index);
            long now = System.currentTimeMillis();
            if (sendInSync <= now && !first) {
              bb.clear();
              bb.putInt(IN_SYNC_LEN);
              bb.flip();
              while (bb.remaining() > 0 && socket.write(bb) > 0) {
                doNothing();
              }
              sendInSync = now + HEARTBEAT_INTERVAL_MS;
            }
            pause();
            if (closed) break OUTER;
          }
          //                    System.out.println("Writing " + index);
          final int size = excerpt.capacity();
          int remaining;

          bb.clear();
          if (first) {
            //                        System.out.println("wi " + index);
            bb.putLong(index);
            first = false;
            remaining = size + TcpUtil.HEADER_SIZE;
          } else {
            remaining = size + 4;
          }
          bb.putInt(size);
          // for large objects send one at a time.
          if (size > bb.capacity() / 2) {
            while (remaining > 0) {
              int size2 = Math.min(remaining, bb.capacity());
              bb.limit(size2);
              excerpt.read(bb);
              bb.flip();
              //                        System.out.println("w " + ChronicleTools.asString(bb));
              remaining -= bb.remaining();
              while (bb.remaining() > 0 && socket.write(bb) > 0) {
                doNothing();
              }
            }
          } else {
            bb.limit(remaining);
            excerpt.read(bb);
            int count = 1;
            while (excerpt.index(index + 1) && count++ < MAX_MESSAGE) {
              if (excerpt.remaining() + 4 >= bb.capacity() - bb.position()) break;
              // if there is free space, copy another one.
              int size2 = excerpt.capacity();
              //                            System.out.println("W+ "+size);
              bb.limit(bb.position() + size2 + 4);
              bb.putInt(size2);
              excerpt.read(bb);

              index++;
            }

            bb.flip();
            //                        System.out.println("W " + size + " wb " + bb);
            while (bb.remaining() > 0 && socket.write(bb) > 0) {
              doNothing();
            }
          }
          if (bb.remaining() > 0) throw new EOFException("Failed to send index=" + index);
          index++;
          sendInSync = 0;
          //                    if (index % 20000 == 0)
          //                        System.out.println(System.currentTimeMillis() + ": wrote " +
          // index);
        }
      } catch (IOException e) {
        if (!closed) {
          String msg = e.getMessage();
          if (msg != null
              && (msg.contains("reset by peer")
                  || msg.contains("Broken pipe")
                  || msg.contains("was aborted by")))
            logger.log(Level.INFO, "Connect " + socket + " closed from the other end " + e);
          else logger.log(Level.INFO, "Connect " + socket + " died", e);
        }
      }
    }