You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ratis.apache.org by el...@apache.org on 2018/09/20 17:42:59 UTC

incubator-ratis git commit: RATIS-317. Log service state machine

Repository: incubator-ratis
Updated Branches:
  refs/heads/master ed8e60dad -> 523fb6383


RATIS-317. Log service state machine

Signed-off-by: Josh Elser <el...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-ratis/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ratis/commit/523fb638
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ratis/tree/523fb638
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ratis/diff/523fb638

Branch: refs/heads/master
Commit: 523fb63832e574fac0a3b8cc65f548e91940dba5
Parents: ed8e60d
Author: Vladimir Rodionov <vr...@hortonworks.com>
Authored: Wed Sep 19 12:45:01 2018 -0700
Committer: Josh Elser <el...@apache.org>
Committed: Thu Sep 20 13:42:44 2018 -0400

----------------------------------------------------------------------
 .../apache/ratis/logservice/api/LogMessage.java | 175 ++++++++++++++++
 .../apache/ratis/logservice/api/LogName.java    |   8 +
 .../ratis/logservice/api/LogStateMachine.java   | 197 +++++++++++++++++++
 .../org/apache/ratis/logservice/util/Utils.java |  48 +++++
 .../ratis/logservice/api/TestLogMessage.java    |  55 ++++++
 .../apache/ratis/logservice/util/TestUtils.java |  95 +++++++++
 .../src/main/proto/Logservice.proto             |  35 ++++
 7 files changed, 613 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/523fb638/ratis-logservice/src/main/java/org/apache/ratis/logservice/api/LogMessage.java
----------------------------------------------------------------------
diff --git a/ratis-logservice/src/main/java/org/apache/ratis/logservice/api/LogMessage.java b/ratis-logservice/src/main/java/org/apache/ratis/logservice/api/LogMessage.java
new file mode 100644
index 0000000..bf2024f
--- /dev/null
+++ b/ratis-logservice/src/main/java/org/apache/ratis/logservice/api/LogMessage.java
@@ -0,0 +1,175 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ratis.logservice.api;
+
+import java.nio.charset.Charset;
+
+import org.apache.ratis.protocol.Message;
+import org.apache.ratis.shaded.proto.logservice.LogServiceProtos;
+
+import org.apache.ratis.shaded.com.google.protobuf.ByteString;
+import org.apache.ratis.shaded.com.google.protobuf.InvalidProtocolBufferException;
+
+public class LogMessage implements Message {
+  public static final Charset UTF8 = Charset.forName("UTF-8");
+  /*
+   * Type of message
+   */
+  public static enum Type {
+    READ_REQUEST, READ_REPLY, WRITE
+  }
+
+  /*
+   * For all READ and WRITE requests
+   */
+  private final LogName name;
+
+  /*
+   * Set only for READ_REPLY response
+   */
+  private long  length;
+
+  /*
+   * Pay load for WRITE request
+   */
+  private byte[] data;
+
+  /*
+   * Type of message
+   */
+
+  private Type type;
+
+  /**
+   * Constructor for WRITE request
+   * @param logName name of a log
+   * @param data  pay load data
+   */
+  public LogMessage(LogName logName, byte[] data) {
+    this.name = logName;
+    this.data = data;
+    this.type = Type.WRITE;
+  }
+
+  /**
+   * Constructor for READ reply
+   * @param logName name of a log
+   * @param length length of a log
+   */
+  public LogMessage(LogName logName, long length) {
+    this.name = logName;
+    this.length = length;
+    this.type = Type.READ_REPLY;
+  }
+
+  /**
+   * Constructor for READ request
+   * @param logName name of a log
+   */
+  public LogMessage(LogName logName) {
+    this.name = logName;
+    this.type = Type.READ_REQUEST;
+  }
+
+  public static LogMessage parseFrom(ByteString data)
+      throws InvalidProtocolBufferException {
+    LogServiceProtos.LogMessage msg = LogServiceProtos.LogMessage.parseFrom(data);
+    LogServiceProtos.MessageType type = msg.getType();
+    long length = 0;
+    LogName name = null;
+    byte[] bdata = null;
+    name = LogName.of(msg.getLogName());
+    switch (type) {
+      case READ_REPLY:
+        length = msg.getLength();
+        return new LogMessage(name, length);
+      case READ_REQUEST:
+        return new LogMessage(name);
+      case WRITE:
+        bdata = msg.getData().toByteArray();
+        return new LogMessage(name, bdata);
+      default:
+        //TODO replace exception
+        throw new RuntimeException("Wrong message type: "+ type);
+    }
+  }
+
+
+  /**
+   * Get log name
+   * @return log name
+   */
+  public LogName getLogName() {
+    return name;
+  }
+
+  /**
+   * Get log length
+   * @return log length
+   */
+  public long getLength() {
+    return length;
+  }
+
+  /**
+   * Get log message data
+   * @return data
+   */
+  public byte[] getData() {
+    return data;
+  }
+
+  /**
+   * Get message type
+   * @return message type
+   */
+  public Type getType() {
+    return type;
+  }
+
+
+  @SuppressWarnings("deprecation")
+  @Override
+  public ByteString getContent() {
+    LogServiceProtos.LogMessage.Builder builder = LogServiceProtos.LogMessage.newBuilder();
+    builder.setType(LogServiceProtos.MessageType.valueOf(type.ordinal()));
+    builder.setLogName(name.getName());
+    switch (type) {
+      case READ_REPLY:
+        builder.setLength(length);
+        break;
+      case WRITE:
+        builder.setData(ByteString.copyFrom(data));
+        break;
+      default:
+    }
+
+    return builder.build().toByteString();
+  }
+
+  @Override
+  public String toString() {
+    String s = type.name() + " : log=" + name.getName();
+    if (type == Type.READ_REPLY) {
+      s += " len=" + length;
+    } else if (type == Type.WRITE) {
+      s += " data len=" + data.length;
+    }
+    return s;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/523fb638/ratis-logservice/src/main/java/org/apache/ratis/logservice/api/LogName.java
----------------------------------------------------------------------
diff --git a/ratis-logservice/src/main/java/org/apache/ratis/logservice/api/LogName.java b/ratis-logservice/src/main/java/org/apache/ratis/logservice/api/LogName.java
index 3227845..bbeb0a5 100644
--- a/ratis-logservice/src/main/java/org/apache/ratis/logservice/api/LogName.java
+++ b/ratis-logservice/src/main/java/org/apache/ratis/logservice/api/LogName.java
@@ -62,6 +62,14 @@ public class LogName {
   }
 
   /**
+   * Length of a log's name
+   * @return length
+   */
+  public int getLength() {
+    return name.length();
+  }
+
+  /**
    * Creates a {@link LogName} given the provided string.
    */
   public static LogName of(String name) {

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/523fb638/ratis-logservice/src/main/java/org/apache/ratis/logservice/api/LogStateMachine.java
----------------------------------------------------------------------
diff --git a/ratis-logservice/src/main/java/org/apache/ratis/logservice/api/LogStateMachine.java b/ratis-logservice/src/main/java/org/apache/ratis/logservice/api/LogStateMachine.java
new file mode 100644
index 0000000..3444dd5
--- /dev/null
+++ b/ratis-logservice/src/main/java/org/apache/ratis/logservice/api/LogStateMachine.java
@@ -0,0 +1,197 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ratis.logservice.api;
+
+import org.apache.ratis.protocol.Message;
+import org.apache.ratis.protocol.RaftGroupId;
+import org.apache.ratis.server.RaftServer;
+import org.apache.ratis.server.impl.RaftServerConstants;
+import org.apache.ratis.server.protocol.TermIndex;
+import org.apache.ratis.server.storage.RaftStorage;
+import org.apache.ratis.shaded.proto.RaftProtos;
+import org.apache.ratis.shaded.proto.RaftProtos.LogEntryProto;
+import org.apache.ratis.statemachine.StateMachineStorage;
+import org.apache.ratis.statemachine.TransactionContext;
+import org.apache.ratis.statemachine.impl.BaseStateMachine;
+import org.apache.ratis.statemachine.impl.SimpleStateMachineStorage;
+import org.apache.ratis.statemachine.impl.SingleFileSnapshotInfo;
+import org.apache.ratis.util.AutoCloseableLock;
+
+import org.apache.ratis.shaded.com.google.protobuf.InvalidProtocolBufferException;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+public class LogStateMachine extends BaseStateMachine {
+  private final Map<LogName, Long> state = new ConcurrentHashMap<>();
+
+  private final SimpleStateMachineStorage storage = new SimpleStateMachineStorage();
+
+  private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+
+  private AutoCloseableLock readLock() {
+    return AutoCloseableLock.acquire(lock.readLock());
+  }
+
+  private AutoCloseableLock writeLock() {
+    return AutoCloseableLock.acquire(lock.writeLock());
+  }
+
+  void reset() {
+    state.clear();
+    setLastAppliedTermIndex(null);
+  }
+
+  @Override
+  public void initialize(RaftServer server, RaftGroupId groupId,
+      RaftStorage raftStorage) throws IOException {
+    super.initialize(server, groupId, raftStorage);
+    this.storage.init(raftStorage);
+    loadSnapshot(storage.getLatestSnapshot());
+  }
+
+  @Override
+  public void reinitialize() throws IOException {
+    close();
+    loadSnapshot(storage.getLatestSnapshot());
+  }
+
+  @Override
+  public long takeSnapshot() {
+    final Map<LogName, Long> copy;
+    final TermIndex last;
+    try(final AutoCloseableLock readLock = readLock()) {
+      copy = new HashMap<>(state);
+      last = getLastAppliedTermIndex();
+    }
+
+    final File snapshotFile =  storage.getSnapshotFile(last.getTerm(), last.getIndex());
+    LOG.info("Taking a snapshot to file {}", snapshotFile);
+
+    try(final ObjectOutputStream out = new ObjectOutputStream(
+        new BufferedOutputStream(new FileOutputStream(snapshotFile)))) {
+      out.writeObject(copy);
+    } catch(IOException ioe) {
+      LOG.warn("Failed to write snapshot file \"" + snapshotFile
+          + "\", last applied index=" + last);
+    }
+
+    return last.getIndex();
+  }
+
+  private long loadSnapshot(SingleFileSnapshotInfo snapshot) throws IOException {
+    return load(snapshot, false);
+  }
+
+  @SuppressWarnings("unchecked")
+  private long load(SingleFileSnapshotInfo snapshot, boolean reload) throws IOException {
+    if (snapshot == null) {
+      LOG.warn("The snapshot info is null.");
+      return RaftServerConstants.INVALID_LOG_INDEX;
+    }
+    final File snapshotFile = snapshot.getFile().getPath().toFile();
+    if (!snapshotFile.exists()) {
+      LOG.warn("The snapshot file {} does not exist for snapshot {}", snapshotFile, snapshot);
+      return RaftServerConstants.INVALID_LOG_INDEX;
+    }
+
+    final TermIndex last = SimpleStateMachineStorage.getTermIndexFromSnapshotFile(snapshotFile);
+    try(final AutoCloseableLock writeLock = writeLock();
+        final ObjectInputStream in = new ObjectInputStream(
+            new BufferedInputStream(new FileInputStream(snapshotFile)))) {
+      if (reload) {
+        reset();
+      }
+      setLastAppliedTermIndex(last);
+      state.putAll((Map<LogName, Long>) in.readObject());
+    } catch (ClassNotFoundException e) {
+      throw new IllegalStateException(e);
+    }
+    return last.getIndex();
+  }
+
+  @Override
+  public StateMachineStorage getStateMachineStorage() {
+    return storage;
+  }
+
+  @Override
+  public CompletableFuture<Message> query(Message request) {
+    LogMessage msg = null;
+    try {
+      msg = LogMessage.parseFrom(request.getContent());
+      LogName logName = msg.getLogName();
+      Long len = null;
+      try(final AutoCloseableLock readLock = readLock()) {
+        len = state.get(logName);
+        if (len == null) {
+          len = new Long(-1);
+        }
+      }
+      LOG.debug("QUERY: {}, RESULT: {}", msg, len);
+      return CompletableFuture.completedFuture(new LogMessage (logName, len));
+    } catch (InvalidProtocolBufferException e) {
+      //TODO exception handling
+      throw new RuntimeException(e);
+    }
+
+  }
+
+
+  @Override
+  public void close() {
+    reset();
+  }
+
+  @Override
+  public CompletableFuture<Message> applyTransaction(TransactionContext trx) {
+    try {
+      final LogEntryProto entry = trx.getLogEntry();
+      final LogMessage logMessage = LogMessage.parseFrom((entry.getSmLogEntry().getData()));
+
+      final long index = entry.getIndex();
+      Long val = null;
+      LogName name = null;
+      try (final AutoCloseableLock writeLock = writeLock()) {
+        name = logMessage.getLogName();
+        long dataLength = logMessage.getData().length;
+        val = state.get(name);
+        if (val == null) {
+          val = new Long(0);
+        }
+        state.put(name, val + dataLength);
+        updateLastAppliedTermIndex(entry.getTerm(), index);
+      }
+      final CompletableFuture<Message> f =
+          CompletableFuture.completedFuture(new LogMessage(name, val));
+      final RaftProtos.RaftPeerRole role = trx.getServerRole();
+      LOG.debug("{}:{}-{}: {} new length {}", role, getId(), index, logMessage, val);
+      if (LOG.isTraceEnabled()) {
+        LOG.trace("{}-{}: variables={}", getId(), index, state);
+      }
+      return f;
+    } catch (InvalidProtocolBufferException e) {
+      // TODO exception handling
+      throw new RuntimeException(e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/523fb638/ratis-logservice/src/main/java/org/apache/ratis/logservice/util/Utils.java
----------------------------------------------------------------------
diff --git a/ratis-logservice/src/main/java/org/apache/ratis/logservice/util/Utils.java b/ratis-logservice/src/main/java/org/apache/ratis/logservice/util/Utils.java
new file mode 100644
index 0000000..3709b6f
--- /dev/null
+++ b/ratis-logservice/src/main/java/org/apache/ratis/logservice/util/Utils.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ratis.logservice.util;
+
+public class Utils {
+
+
+  public static int long2bytes(long v, byte[] buf, int offset) {
+    int2bytes((int)(v >>> 32), buf, offset);
+    int2bytes((int) v        , buf, offset + 4);
+    return 8;
+  }
+
+  public static int bytes2int(byte[] buf, int offset) {
+    return (buf[offset] << 24)
+        + ((0xFF & buf[offset + 1]) << 16)
+        + ((0xFF & buf[offset + 2]) <<  8)
+        +  (0xFF & buf[offset + 3]);
+  }
+
+  public static long bytes2long(byte[] buf, int offset) {
+    return ((long)bytes2int(buf, offset) << 32)
+        + (0xFFFFFFFFL & bytes2int(buf, offset + 4));
+  }
+
+  public static int int2bytes(int v, byte[] buf, int offset) {
+    buf[offset    ] = (byte) (v >>> 24);
+    buf[offset + 1] = (byte) (v >>> 16);
+    buf[offset + 2] = (byte) (v >>> 8);
+    buf[offset + 3] = (byte) (v);
+    return 4;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/523fb638/ratis-logservice/src/test/java/org/apache/ratis/logservice/api/TestLogMessage.java
----------------------------------------------------------------------
diff --git a/ratis-logservice/src/test/java/org/apache/ratis/logservice/api/TestLogMessage.java b/ratis-logservice/src/test/java/org/apache/ratis/logservice/api/TestLogMessage.java
new file mode 100644
index 0000000..fb74d64
--- /dev/null
+++ b/ratis-logservice/src/test/java/org/apache/ratis/logservice/api/TestLogMessage.java
@@ -0,0 +1,55 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ratis.logservice.api;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.ratis.logservice.api.LogMessage.Type;
+import org.junit.Test;
+
+import org.apache.ratis.shaded.com.google.protobuf.ByteString;
+import org.apache.ratis.shaded.com.google.protobuf.InvalidProtocolBufferException;
+
+public class TestLogMessage {
+
+  @Test
+  public void testLogMessages() throws InvalidProtocolBufferException {
+
+    LogMessage msg = new LogMessage(LogName.of("testLog"));
+    assertEquals(Type.READ_REQUEST, msg.getType());
+    ByteString content = msg.getContent();
+    LogMessage other = LogMessage.parseFrom(content);
+    assertEquals(msg.toString(), other.toString());
+
+    msg = new LogMessage(LogName.of("testLog"), 100);
+    assertEquals(Type.READ_REPLY, msg.getType());
+    content = msg.getContent();
+    other = LogMessage.parseFrom(content);
+    assertEquals(msg.toString(), other.toString());
+
+    msg = new LogMessage(LogName.of("testLog"), new byte[] { 0, 0, 0 });
+    assertEquals(Type.WRITE, msg.getType());
+    content = msg.getContent();
+    other = LogMessage.parseFrom(content);
+    assertEquals(msg.toString(), other.toString());
+    assertEquals(msg.getData().length, other.getData().length);
+
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/523fb638/ratis-logservice/src/test/java/org/apache/ratis/logservice/util/TestUtils.java
----------------------------------------------------------------------
diff --git a/ratis-logservice/src/test/java/org/apache/ratis/logservice/util/TestUtils.java b/ratis-logservice/src/test/java/org/apache/ratis/logservice/util/TestUtils.java
new file mode 100644
index 0000000..752889a
--- /dev/null
+++ b/ratis-logservice/src/test/java/org/apache/ratis/logservice/util/TestUtils.java
@@ -0,0 +1,95 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ratis.logservice.util;
+
+import static org.apache.ratis.logservice.util.Utils.bytes2int;
+import static org.apache.ratis.logservice.util.Utils.int2bytes;
+import static org.apache.ratis.logservice.util.Utils.bytes2long;
+import static org.apache.ratis.logservice.util.Utils.long2bytes;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class TestUtils {
+
+  @Test
+  public void testInt2Bytes() {
+
+    byte[] buf = new byte[4];
+    int v1 = 0;
+    int2bytes(v1, buf, 0);
+    int vv1 = bytes2int(buf, 0);
+    assertEquals(v1, vv1);
+    int v2 = 1;
+    int2bytes(v2, buf, 0);
+    int vv2 = bytes2int(buf, 0);
+    assertEquals(v2, vv2);
+    int v3 = -1;
+    int2bytes(v3, buf, 0);
+    int vv3 = bytes2int(buf, 0);
+    assertEquals(v3, vv3);
+    int v4 = Integer.MIN_VALUE;
+    int2bytes(v4, buf, 0);
+    int vv4 = bytes2int(buf, 0);
+    assertEquals(v4, vv4);
+    int v5 = Integer.MAX_VALUE;
+    int2bytes(v5, buf, 0);
+    int vv5 = bytes2int(buf, 0);
+    assertEquals(v5, vv5);
+
+  }
+
+
+  @Test
+  public void testLong2Bytes() {
+    byte[] buf = new byte[8];
+    long v1 = 0;
+    long2bytes(v1, buf, 0);
+    long vv1 = bytes2long(buf, 0);
+    assertEquals(v1, vv1);
+
+    long v2 = 1;
+    long2bytes(v2, buf, 0);
+    long vv2 = bytes2long(buf, 0);
+    assertEquals(v2, vv2);
+
+    long v3 = -1;
+    long2bytes(v3, buf, 0);
+    long vv3 = bytes2long(buf, 0);
+    assertEquals(v3, vv3);
+
+    long v4 = Long.MIN_VALUE;
+    long2bytes(v4, buf, 0);
+    long vv4 = bytes2long(buf, 0);
+    assertEquals(v4, vv4);
+
+    long v5 = Integer.MAX_VALUE;
+    long2bytes(v5, buf, 0);
+    long vv5 = bytes2long(buf, 0);
+    assertEquals(v5, vv5);
+
+    long v6 = 100;
+    buf = new byte[20];
+    long2bytes(v6, buf, 12);
+    long vv6 = bytes2long(buf, 12);
+    assertEquals(v6, vv6);
+
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/523fb638/ratis-proto-shaded/src/main/proto/Logservice.proto
----------------------------------------------------------------------
diff --git a/ratis-proto-shaded/src/main/proto/Logservice.proto b/ratis-proto-shaded/src/main/proto/Logservice.proto
new file mode 100644
index 0000000..fd586bf
--- /dev/null
+++ b/ratis-proto-shaded/src/main/proto/Logservice.proto
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+syntax = "proto3";
+option java_package = "org.apache.ratis.shaded.proto.logservice";
+option java_outer_classname = "LogServiceProtos";
+option java_generate_equals_and_hash = true;
+package ratis.logservice;
+
+enum MessageType {
+	READ_REQUEST = 0;
+	READ_REPLY = 1;
+	WRITE = 2;
+}
+
+message LogMessage {
+	MessageType type = 1;
+	string log_name = 2;
+	uint64 length = 3;
+	bytes  data = 4;
+}
\ No newline at end of file