You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ratis.apache.org by ji...@apache.org on 2017/01/31 21:17:17 UTC

[32/54] [abbrv] incubator-ratis git commit: Renamed the packages from raft to ratis in preperation for Apache Incubation - Moved all java packages from org.apache.raft to org.apache.ratis. - Moved native package to org_apache_ratis, and native lib to l

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/7e71a2e0/ratis-client/src/main/java/org/apache/ratis/client/RaftClientRequestSender.java
----------------------------------------------------------------------
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/RaftClientRequestSender.java b/ratis-client/src/main/java/org/apache/ratis/client/RaftClientRequestSender.java
new file mode 100644
index 0000000..b2541e1
--- /dev/null
+++ b/ratis-client/src/main/java/org/apache/ratis/client/RaftClientRequestSender.java
@@ -0,0 +1,34 @@
+/**
+ * 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.client;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.apache.ratis.protocol.RaftClientReply;
+import org.apache.ratis.protocol.RaftClientRequest;
+import org.apache.ratis.protocol.RaftPeer;
+
+/** Send requests to a raft service. */
+public interface RaftClientRequestSender extends Closeable {
+  /** Send a request. */
+  RaftClientReply sendRequest(RaftClientRequest request) throws IOException;
+
+  /** Add the information of the given raft servers */
+  void addServers(Iterable<RaftPeer> servers);
+}

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/7e71a2e0/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientProtoUtils.java
----------------------------------------------------------------------
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientProtoUtils.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientProtoUtils.java
new file mode 100644
index 0000000..24bb4ec
--- /dev/null
+++ b/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientProtoUtils.java
@@ -0,0 +1,131 @@
+/**
+ * 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.client.impl;
+
+import org.apache.ratis.shaded.com.google.protobuf.ByteString;
+import org.apache.ratis.shaded.proto.RaftProtos.*;
+import org.apache.ratis.protocol.*;
+import org.apache.ratis.util.ProtoUtils;
+
+import java.util.Arrays;
+
+public class ClientProtoUtils {
+  public static RaftRpcReplyProto.Builder toRaftRpcReplyProtoBuilder(
+      String requestorId, String replyId, long seqNum, boolean success) {
+    return RaftRpcReplyProto.newBuilder()
+        .setRequestorId(requestorId).setReplyId(replyId).setSeqNum(seqNum)
+        .setSuccess(success);
+  }
+
+  public static RaftRpcRequestProto.Builder toRaftRpcRequestProtoBuilder(
+      String requesterId, String replyId, long seqNum) {
+    return RaftRpcRequestProto.newBuilder()
+        .setRequestorId(requesterId).setReplyId(replyId).setSeqNum(seqNum);
+  }
+
+  public static RaftClientRequest toRaftClientRequest(RaftClientRequestProto p) {
+    return new RaftClientRequest(p.getRpcRequest().getRequestorId(),
+        p.getRpcRequest().getReplyId(), p.getRpcRequest().getSeqNum(),
+        toMessage(p.getMessage()), p.getReadOnly());
+  }
+
+  public static RaftClientRequestProto toRaftClientRequestProto(
+      RaftClientRequest request) {
+    return RaftClientRequestProto.newBuilder()
+        .setRpcRequest(toRaftRpcRequestProtoBuilder(request.getRequestorId(),
+            request.getReplierId(), request.getSeqNum()))
+        .setMessage(toClientMessageEntryProto(request.getMessage()))
+        .setReadOnly(request.isReadOnly())
+        .build();
+  }
+
+  public static RaftClientRequestProto genRaftClientRequestProto(
+      String requestorId, String replierId, long seqNum, ByteString content,
+      boolean readOnly) {
+    return RaftClientRequestProto.newBuilder()
+        .setRpcRequest(toRaftRpcRequestProtoBuilder(requestorId, replierId, seqNum))
+        .setMessage(ClientMessageEntryProto.newBuilder().setContent(content))
+        .setReadOnly(readOnly)
+        .build();
+  }
+
+  public static RaftClientReplyProto toRaftClientReplyProto(
+      RaftClientReply reply) {
+    final RaftClientReplyProto.Builder b = RaftClientReplyProto.newBuilder();
+    if (reply != null) {
+      b.setRpcReply(toRaftRpcReplyProtoBuilder(reply.getRequestorId(),
+          reply.getReplierId(), reply.getSeqNum(), reply.isSuccess()));
+      if (reply.getMessage() != null) {
+        b.setMessage(toClientMessageEntryProto(reply.getMessage()));
+      }
+      if (reply.isNotLeader()) {
+        b.setIsNotLeader(true);
+        final RaftPeer suggestedLeader = reply.getNotLeaderException()
+            .getSuggestedLeader();
+        if (suggestedLeader != null) {
+          b.setSuggestedLeader(ProtoUtils.toRaftPeerProto(suggestedLeader));
+        }
+        b.addAllPeersInConf(ProtoUtils.toRaftPeerProtos(
+            Arrays.asList(reply.getNotLeaderException().getPeers())));
+      }
+    }
+    return b.build();
+  }
+
+  public static RaftClientReply toRaftClientReply(
+      RaftClientReplyProto replyProto) {
+    final RaftRpcReplyProto rp = replyProto.getRpcReply();
+    NotLeaderException e = null;
+    if (replyProto.getIsNotLeader()) {
+      final RaftPeer suggestedLeader = replyProto.hasSuggestedLeader() ?
+          ProtoUtils.toRaftPeer(replyProto.getSuggestedLeader()) : null;
+      final RaftPeer[] peers = ProtoUtils.toRaftPeerArray(
+          replyProto.getPeersInConfList());
+      e = new NotLeaderException(rp.getReplyId(), suggestedLeader, peers);
+    }
+    return new RaftClientReply(rp.getRequestorId(), rp.getReplyId(),
+        rp.getSeqNum(), rp.getSuccess(), toMessage(replyProto.getMessage()), e);
+  }
+
+  public static Message toMessage(final ClientMessageEntryProto p) {
+    return p::getContent;
+  }
+
+  public static ClientMessageEntryProto toClientMessageEntryProto(Message message) {
+    return ClientMessageEntryProto.newBuilder()
+        .setContent(message.getContent()).build();
+  }
+
+  public static SetConfigurationRequest toSetConfigurationRequest(
+      SetConfigurationRequestProto p) {
+    final RaftRpcRequestProto m = p.getRpcRequest();
+    final RaftPeer[] peers = ProtoUtils.toRaftPeerArray(p.getPeersList());
+    return new SetConfigurationRequest(m.getRequestorId(), m.getReplyId(),
+        p.getRpcRequest().getSeqNum(), peers);
+  }
+
+  public static SetConfigurationRequestProto toSetConfigurationRequestProto(
+      SetConfigurationRequest request) {
+    return SetConfigurationRequestProto.newBuilder()
+        .setRpcRequest(toRaftRpcRequestProtoBuilder(request.getRequestorId(),
+            request.getReplierId(), request.getSeqNum()))
+        .addAllPeers(ProtoUtils.toRaftPeerProtos(
+            Arrays.asList(request.getPeersInNewConf())))
+        .build();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/7e71a2e0/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftClientImpl.java
----------------------------------------------------------------------
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftClientImpl.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftClientImpl.java
new file mode 100644
index 0000000..e101554
--- /dev/null
+++ b/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftClientImpl.java
@@ -0,0 +1,172 @@
+/**
+ * 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.client.impl;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import org.apache.ratis.client.RaftClient;
+import org.apache.ratis.client.RaftClientConfigKeys;
+import org.apache.ratis.client.RaftClientRequestSender;
+import org.apache.ratis.conf.RaftProperties;
+import org.apache.ratis.protocol.*;
+import org.apache.ratis.util.RaftUtils;
+import org.apache.ratis.util.StringUtils;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+/** A client who sends requests to a raft service. */
+public final class RaftClientImpl implements RaftClient {
+  public static final long DEFAULT_SEQNUM = 0;
+
+  private final String clientId;
+  private final RaftClientRequestSender requestSender;
+  private final Map<String, RaftPeer> peers;
+  private final int retryInterval;
+
+  private volatile String leaderId;
+
+  public RaftClientImpl(
+      String clientId, Collection<RaftPeer> peers,
+      RaftClientRequestSender requestSender, String leaderId,
+      RaftProperties properties) {
+    this.clientId = clientId;
+    this.requestSender = requestSender;
+    this.peers = peers.stream().collect(
+        Collectors.toMap(RaftPeer::getId, Function.identity()));
+    this.leaderId = leaderId != null? leaderId : peers.iterator().next().getId();
+    this.retryInterval = properties.getInt(
+        RaftClientConfigKeys.RAFT_RPC_TIMEOUT_MS_KEY,
+        RaftClientConfigKeys.RAFT_RPC_TIMEOUT_MS_DEFAULT);
+  }
+
+  @Override
+  public String getId() {
+    return clientId;
+  }
+
+  @Override
+  public RaftClientReply send(Message message) throws IOException {
+    return send(message, false);
+  }
+
+  @Override
+  public RaftClientReply sendReadOnly(Message message) throws IOException {
+    return send(message, true);
+  }
+
+  private RaftClientReply send(Message message, boolean readOnly) throws IOException {
+    return sendRequestWithRetry(() -> new RaftClientRequest(
+        clientId, leaderId, DEFAULT_SEQNUM, message, readOnly));
+  }
+
+  @Override
+  public RaftClientReply setConfiguration(RaftPeer[] peersInNewConf)
+      throws IOException {
+    return sendRequestWithRetry(() -> new SetConfigurationRequest(
+        clientId, leaderId, DEFAULT_SEQNUM, peersInNewConf));
+  }
+
+  private RaftClientReply sendRequestWithRetry(
+      Supplier<RaftClientRequest> supplier)
+      throws InterruptedIOException, StateMachineException {
+    for(;;) {
+      final RaftClientRequest request = supplier.get();
+      LOG.debug("{}: {}", clientId, request);
+      final RaftClientReply reply = sendRequest(request);
+      if (reply != null) {
+        LOG.debug("{}: {}", clientId, reply);
+        return reply;
+      }
+
+      // sleep and then retry
+      try {
+        Thread.sleep(retryInterval);
+      } catch (InterruptedException ie) {
+        Thread.currentThread().interrupt();
+        throw RaftUtils.toInterruptedIOException(
+            "Interrupted when sending " + request, ie);
+      }
+    }
+  }
+
+  private RaftClientReply sendRequest(RaftClientRequest request)
+      throws StateMachineException {
+    try {
+      RaftClientReply reply = requestSender.sendRequest(request);
+      if (reply.isNotLeader()) {
+        handleNotLeaderException(request, reply.getNotLeaderException());
+        return null;
+      } else {
+        return reply;
+      }
+    } catch (StateMachineException e) {
+      throw e;
+    } catch (IOException ioe) {
+      // TODO different retry policies for different exceptions
+      handleIOException(request, ioe, null);
+    }
+    return null;
+  }
+
+  private void handleNotLeaderException(RaftClientRequest request, NotLeaderException nle) {
+    refreshPeers(nle.getPeers());
+    final String newLeader = nle.getSuggestedLeader() == null? null
+        : nle.getSuggestedLeader().getId();
+    handleIOException(request, nle, newLeader);
+  }
+
+  private void refreshPeers(RaftPeer[] newPeers) {
+    if (newPeers != null && newPeers.length > 0) {
+      peers.clear();
+      for (RaftPeer p : newPeers) {
+        peers.put(p.getId(), p);
+      }
+      // also refresh the rpc proxies for these peers
+      requestSender.addServers(Arrays.asList(newPeers));
+    }
+  }
+
+  private void handleIOException(RaftClientRequest request, IOException ioe, String newLeader) {
+    LOG.debug("{}: Failed with {}", clientId, ioe);
+    final String oldLeader = request.getReplierId();
+    if (newLeader == null && oldLeader.equals(leaderId)) {
+      newLeader = StringUtils.next(oldLeader, peers.keySet());
+    }
+    if (newLeader != null && oldLeader.equals(leaderId)) {
+      LOG.debug("{}: change Leader from {} to {}", clientId, oldLeader, newLeader);
+      this.leaderId = newLeader;
+    }
+  }
+
+  @VisibleForTesting
+  public RaftClientRequestSender getRequestSender() {
+    return requestSender;
+  }
+
+  @Override
+  public void close() throws IOException {
+    requestSender.close();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/7e71a2e0/ratis-common/RatisCommon.cmake
----------------------------------------------------------------------
diff --git a/ratis-common/RatisCommon.cmake b/ratis-common/RatisCommon.cmake
new file mode 100644
index 0000000..e8f70eb
--- /dev/null
+++ b/ratis-common/RatisCommon.cmake
@@ -0,0 +1,208 @@
+#
+# 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.
+#
+
+#
+# Common CMake utilities and configuration, shared by all Native components.
+#
+
+#
+# Platform-specific prerequisite checks.
+#
+
+if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
+    # Only 64-bit Java is supported.
+    if(NOT JVM_ARCH_DATA_MODEL EQUAL 64)
+        message(FATAL_ERROR "Unrecognised JVM_ARCH_DATA_MODEL '${JVM_ARCH_DATA_MODEL}'. "
+          "A 64-bit JVM must be used on Solaris, make sure that one is installed and, "
+          "if necessary, the MAVEN_OPTS environment variable includes '-d64'")
+    endif()
+
+    # Only gcc is suported for now.
+    if(NOT(CMAKE_COMPILER_IS_GNUCC AND CMAKE_COMPILER_IS_GNUCXX))
+        message(FATAL_ERROR "Only gcc is supported on Solaris")
+    endif()
+endif()
+
+#
+# Helper functions and macros.
+#
+
+# Add flags to all the CMake compiler variables
+macro(ratis_add_compiler_flags FLAGS)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}")
+endmacro()
+
+# Add flags to all the CMake linker variables.
+macro(ratis_add_linker_flags FLAGS)
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAGS}")
+    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAGS}")
+endmacro()
+
+# Compile a library with both shared and static variants.
+function(ratis_add_dual_library LIBNAME)
+    add_library(${LIBNAME} SHARED ${ARGN})
+    add_library(${LIBNAME}_static STATIC ${ARGN})
+    set_target_properties(${LIBNAME}_static PROPERTIES OUTPUT_NAME ${LIBNAME})
+endfunction()
+
+# Link both a static and a dynamic target against some libraries.
+function(ratis_target_link_dual_libraries LIBNAME)
+    target_link_libraries(${LIBNAME} ${ARGN})
+    target_link_libraries(${LIBNAME}_static ${ARGN})
+endfunction()
+
+# Set all the output directories to the same place.
+function(ratis_output_directory TGT DIR)
+    set_target_properties(${TGT} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${DIR}")
+    set_target_properties(${TGT} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${DIR}")
+    set_target_properties(${TGT} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${DIR}")
+endfunction()
+
+# Set the target directories for dynamic and static builds.
+function(ratis_dual_output_directory TGT DIR)
+    ratis_output_directory(${TGT} "${DIR}")
+    ratis_output_directory(${TGT}_static "${DIR}")
+endfunction()
+
+# Alter the behavior of find_package and find_library so that we find only
+# shared libraries with a given version suffix.  You should save
+# CMAKE_FIND_LIBRARY_SUFFIXES before calling this function and restore it
+# afterwards.  On Windows this function is a no-op.  Windows does not encode
+# version number information information into library path names.
+macro(ratis_set_find_shared_library_version LVERS)
+    if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+        # Mac OS uses .dylib
+        set(CMAKE_FIND_LIBRARY_SUFFIXES ".${LVERS}.dylib")
+    elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
+        # FreeBSD has always .so installed.
+        set(CMAKE_FIND_LIBRARY_SUFFIXES ".so")
+    elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+        # Windows doesn't support finding shared libraries by version.
+    else()
+        # Most UNIX variants use .so
+        set(CMAKE_FIND_LIBRARY_SUFFIXES ".so.${LVERS}")
+    endif()
+endmacro()
+
+# Alter the behavior of find_package and find_library so that we find only
+# shared libraries without any version suffix.  You should save
+# CMAKE_FIND_LIBRARY_SUFFIXES before calling this function and restore it
+# afterwards. On Windows this function is a no-op.  Windows does not encode
+# version number information information into library path names.
+macro(ratis_set_find_shared_library_without_version)
+    if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+        # Mac OS uses .dylib
+        set(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib")
+    elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+        # No effect
+    else()
+        # Most UNIX variants use .so
+        set(CMAKE_FIND_LIBRARY_SUFFIXES ".so")
+    endif()
+endmacro()
+
+#
+# Configuration.
+#
+
+# Initialise the shared gcc/g++ flags if they aren't already defined.
+if(NOT DEFINED GCC_SHARED_FLAGS)
+    set(GCC_SHARED_FLAGS "-g -O2 -Wall -pthread -D_FILE_OFFSET_BITS=64")
+endif()
+
+# Add in support other compilers here, if necessary,
+# the assumption is that GCC or a GCC-compatible compiler is being used.
+
+# Set the shared GCC-compatible compiler and linker flags.
+ratis_add_compiler_flags("${GCC_SHARED_FLAGS}")
+ratis_add_linker_flags("${LINKER_SHARED_FLAGS}")
+
+#
+# Linux-specific configuration.
+#
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+    # Make GNU extensions available.
+    ratis_add_compiler_flags("-D_GNU_SOURCE")
+
+    # If JVM_ARCH_DATA_MODEL is 32, compile all binaries as 32-bit.
+    if(JVM_ARCH_DATA_MODEL EQUAL 32)
+        # Force 32-bit code generation on amd64/x86_64, ppc64, sparc64
+        if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_SYSTEM_PROCESSOR MATCHES ".*64")
+            ratis_add_compiler_flags("-m32")
+            ratis_add_linker_flags("-m32")
+        endif()
+        # Set CMAKE_SYSTEM_PROCESSOR to ensure that find_package(JNI) will use 32-bit libraries
+        if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")
+            set(CMAKE_SYSTEM_PROCESSOR "i686")
+        endif()
+    endif()
+
+    # Determine float ABI of JVM on ARM.
+    if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
+        find_program(READELF readelf)
+        if(READELF MATCHES "NOTFOUND")
+            message(WARNING "readelf not found; JVM float ABI detection disabled")
+        else(READELF MATCHES "NOTFOUND")
+            execute_process(
+                COMMAND ${READELF} -A ${JAVA_JVM_LIBRARY}
+                OUTPUT_VARIABLE JVM_ELF_ARCH
+                ERROR_QUIET)
+            if(NOT JVM_ELF_ARCH MATCHES "Tag_ABI_VFP_args: VFP registers")
+                # Test compilation with -mfloat-abi=softfp using an arbitrary libc function
+                # (typically fails with "fatal error: bits/predefs.h: No such file or directory"
+                # if soft-float dev libraries are not installed)
+                message("Soft-float JVM detected")
+                include(CMakePushCheckState)
+                cmake_push_check_state()
+                set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -mfloat-abi=softfp")
+                include(CheckSymbolExists)
+                check_symbol_exists(exit stdlib.h SOFTFP_AVAILABLE)
+                if(NOT SOFTFP_AVAILABLE)
+                    message(FATAL_ERROR "Soft-float dev libraries required (e.g. 'apt-get install libc6-dev-armel' on Debian/Ubuntu)")
+                endif()
+                cmake_pop_check_state()
+                ratis_add_compiler_flags("-mfloat-abi=softfp")
+            endif()
+        endif()
+    endif()
+
+#
+# Solaris-specific configuration.
+#
+elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
+    # Solaris flags. 64-bit compilation is mandatory, and is checked earlier.
+    ratis_add_compiler_flags("-m64 -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS")
+    set(CMAKE_C_FLAGS "-std=gnu99 ${CMAKE_C_FLAGS}")
+    set(CMAKE_CXX_FLAGS "-std=gnu++98 ${CMAKE_CXX_FLAGS}")
+    ratis_add_linker_flags("-m64")
+
+    # CMAKE_SYSTEM_PROCESSOR is set to the output of 'uname -p', which on Solaris is
+    # the 'lowest' ISA supported, i.e. 'i386' or 'sparc'. However in order for the
+    # standard CMake modules to look in the right places it needs to reflect the required
+    # compilation mode, i.e. 64 bit. We therefore force it to either 'amd64' or 'sparcv9'.
+    if(CMAKE_SYSTEM_PROCESSOR STREQUAL "i386")
+        set(CMAKE_SYSTEM_PROCESSOR "amd64")
+        set(CMAKE_LIBRARY_ARCHITECTURE "amd64")
+    elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "sparc")
+        set(CMAKE_SYSTEM_PROCESSOR "sparcv9")
+        set(CMAKE_LIBRARY_ARCHITECTURE "sparcv9")
+    else()
+        message(FATAL_ERROR "Unrecognised CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}")
+    endif()
+endif()

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/7e71a2e0/ratis-common/RatisJNI.cmake
----------------------------------------------------------------------
diff --git a/ratis-common/RatisJNI.cmake b/ratis-common/RatisJNI.cmake
new file mode 100644
index 0000000..78d7ffd
--- /dev/null
+++ b/ratis-common/RatisJNI.cmake
@@ -0,0 +1,97 @@
+#
+# 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.
+#
+
+#
+# Common JNI detection for CMake, shared by all Native components.
+#
+
+# Check the JVM_ARCH_DATA_MODEL variable as been set to 32 or 64 by maven.
+if(NOT DEFINED JVM_ARCH_DATA_MODEL)
+    message(FATAL_ERROR "JVM_ARCH_DATA_MODEL is not defined")
+elseif(NOT (JVM_ARCH_DATA_MODEL EQUAL 32 OR JVM_ARCH_DATA_MODEL EQUAL 64))
+    message(FATAL_ERROR "JVM_ARCH_DATA_MODEL is not 32 or 64")
+endif()
+
+#
+# Linux-specific JNI configuration.
+#
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+    # Locate JNI_INCLUDE_DIRS and JNI_LIBRARIES.
+    # Since we were invoked from Maven, we know that the JAVA_HOME environment
+    # variable is valid.  So we ignore system paths here and just use JAVA_HOME.
+    file(TO_CMAKE_PATH "$ENV{JAVA_HOME}" _java_home)
+    if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i.86$")
+        set(_java_libarch "i386")
+    elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")
+        set(_java_libarch "amd64")
+    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
+        set(_java_libarch "arm")
+    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le")
+        if(EXISTS "${_java_home}/jre/lib/ppc64le")
+            set(_java_libarch "ppc64le")
+        else()
+            set(_java_libarch "ppc64")
+        endif()
+    else()
+        set(_java_libarch ${CMAKE_SYSTEM_PROCESSOR})
+    endif()
+    set(_JDK_DIRS "${_java_home}/jre/lib/${_java_libarch}/*"
+                  "${_java_home}/jre/lib/${_java_libarch}"
+                  "${_java_home}/jre/lib/*"
+                  "${_java_home}/jre/lib"
+                  "${_java_home}/lib/*"
+                  "${_java_home}/lib"
+                  "${_java_home}/include/*"
+                  "${_java_home}/include"
+                  "${_java_home}"
+    )
+    find_path(JAVA_INCLUDE_PATH
+        NAMES jni.h
+        PATHS ${_JDK_DIRS}
+        NO_DEFAULT_PATH)
+    #In IBM java, it's jniport.h instead of jni_md.h
+    find_path(JAVA_INCLUDE_PATH2
+        NAMES jni_md.h jniport.h
+        PATHS ${_JDK_DIRS}
+        NO_DEFAULT_PATH)
+    set(JNI_INCLUDE_DIRS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
+    find_library(JAVA_JVM_LIBRARY
+        NAMES jvm JavaVM
+        PATHS ${_JDK_DIRS}
+        NO_DEFAULT_PATH)
+    set(JNI_LIBRARIES ${JAVA_JVM_LIBRARY})
+    unset(_java_libarch)
+    unset(_java_home)
+
+    message("JAVA_HOME=${JAVA_HOME}, JAVA_JVM_LIBRARY=${JAVA_JVM_LIBRARY}")
+    message("JAVA_INCLUDE_PATH=${JAVA_INCLUDE_PATH}, JAVA_INCLUDE_PATH2=${JAVA_INCLUDE_PATH2}")
+    if(JAVA_JVM_LIBRARY AND JAVA_INCLUDE_PATH AND JAVA_INCLUDE_PATH2)
+        message("Located all JNI components successfully.")
+    else()
+        message(FATAL_ERROR "Failed to find a viable JVM installation under JAVA_HOME.")
+    endif()
+
+    # Use the standard FindJNI module to locate the JNI components.
+    find_package(JNI REQUIRED)
+
+#
+# Otherwise, use the standard FindJNI module to locate the JNI components.
+#
+else()
+    find_package(JNI REQUIRED)
+endif()

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/7e71a2e0/ratis-common/pom.xml
----------------------------------------------------------------------
diff --git a/ratis-common/pom.xml b/ratis-common/pom.xml
new file mode 100644
index 0000000..1cbf058
--- /dev/null
+++ b/ratis-common/pom.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed 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. See accompanying LICENSE file.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>ratis-project-dist</artifactId>
+    <groupId>org.apache.ratis</groupId>
+    <version>1.0-SNAPSHOT</version>
+    <relativePath>../ratis-project-dist</relativePath>
+  </parent>
+
+  <artifactId>ratis-common</artifactId>
+  <name>Ratis Common</name>
+
+  <dependencies>
+    <dependency>
+      <artifactId>ratis-proto-shaded</artifactId>
+      <groupId>org.apache.ratis</groupId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <profiles>
+    <profile>
+      <id>native</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <properties>
+        <runningWithNative>true</runningWithNative>
+      </properties>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-enforcer-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>enforce-os</id>
+                <goals>
+                  <goal>enforce</goal>
+                </goals>
+                <configuration>
+                  <rules>
+                    <requireOS>
+                      <family>mac</family>
+                      <family>unix</family>
+                      <message>native build only supported on Mac or Unix</message>
+                    </requireOS>
+                  </rules>
+                  <fail>true</fail>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>native-maven-plugin</artifactId>
+            <executions>
+              <execution>
+                <phase>compile</phase>
+                <goals>
+                  <goal>javah</goal>
+                </goals>
+                <configuration>
+                  <javahPath>${env.JAVA_HOME}/bin/javah</javahPath>
+                  <javahClassNames>
+                    <javahClassName>org.apache.ratis.io.nativeio.NativeIO</javahClassName>
+                    <javahClassName>org.apache.ratis.util.NativeCrc32</javahClassName>
+                  </javahClassNames>
+                  <javahOutputDirectory>${project.build.directory}/native/javah</javahOutputDirectory>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-maven-plugins</artifactId>
+            <executions>
+              <execution>
+                <id>cmake-compile</id>
+                <phase>compile</phase>
+                <goals><goal>cmake-compile</goal></goals>
+                <configuration>
+                  <source>${basedir}/src</source>
+                  <vars>
+                    <GENERATED_JAVAH>${project.build.directory}/native/javah</GENERATED_JAVAH>
+                    <JVM_ARCH_DATA_MODEL>${sun.arch.data.model}</JVM_ARCH_DATA_MODEL>
+                  </vars>
+                </configuration>
+              </execution>
+              <execution>
+                <id>test_bulk_crc32</id>
+                <goals><goal>cmake-test</goal></goals>
+                <phase>test</phase>
+                <configuration>
+                  <binary>${project.build.directory}/native/test_bulk_crc32</binary>
+                  <timeout>1200</timeout>
+                  <results>${project.build.directory}/native-results</results>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/7e71a2e0/ratis-common/src/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/ratis-common/src/CMakeLists.txt b/ratis-common/src/CMakeLists.txt
new file mode 100644
index 0000000..460b3b1
--- /dev/null
+++ b/ratis-common/src/CMakeLists.txt
@@ -0,0 +1,108 @@
+#
+# 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.
+#
+
+#
+# CMake configuration.
+#
+
+cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/..)
+include(RatisCommon)
+
+# Source and test locations.
+set(SRC main/native/src/org/apache/ratis)
+set(TST main/native/src/test/org/apache/ratis)
+
+#
+# Main configuration.
+#
+
+# The caller must specify where the generated headers have been placed.
+if(NOT GENERATED_JAVAH)
+    message(FATAL_ERROR "You must set the CMake variable GENERATED_JAVAH")
+endif()
+
+# Configure JNI.
+include(RatisJNI)
+
+# Build hardware CRC32 acceleration, if supported on the platform.
+if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i.86$" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")
+  set(BULK_CRC_ARCH_SOURCE_FIlE "${SRC}/util/bulk_crc32_x86.c")
+elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
+  set(BULK_CRC_ARCH_SOURCE_FIlE "${SRC}/util/bulk_crc32_aarch64.c")
+else()
+  message("No HW CRC acceleration for ${CMAKE_SYSTEM_PROCESSOR}, falling back to SW")
+endif()
+
+# Check for platform-specific functions and libraries.
+include(CheckFunctionExists)
+include(CheckLibraryExists)
+check_function_exists(sync_file_range HAVE_SYNC_FILE_RANGE)
+check_function_exists(posix_fadvise HAVE_POSIX_FADVISE)
+check_library_exists(dl dlopen "" NEED_LINK_DL)
+
+# Configure the build.
+include_directories(
+    ${GENERATED_JAVAH}
+    main/native/src
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/src
+    ${CMAKE_BINARY_DIR}
+    ${JNI_INCLUDE_DIRS}
+    ${SRC}/util
+)
+configure_file(${CMAKE_SOURCE_DIR}/config.h.cmake ${CMAKE_BINARY_DIR}/config.h)
+
+set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
+ratis_add_dual_library(ratis
+    main/native/src/exception.c
+    ${SRC}/io/nativeio/NativeIO.c
+    ${SRC}/io/nativeio/errno_enum.c
+    ${SRC}/io/nativeio/file_descriptor.c
+    ${SRC}/util/NativeCodeLoader.c
+    ${SRC}/util/NativeCrc32.c
+    ${SRC}/util/bulk_crc32.c
+    ${BULK_CRC_ARCH_SOURCE_FIlE}
+)
+if(NEED_LINK_DL)
+   set(LIB_DL dl)
+endif()
+
+ratis_target_link_dual_libraries(ratis ${LIB_DL} ${JAVA_JVM_LIBRARY})
+set(LIBRATIS_VERSION "1.0.0")
+set_target_properties(ratis PROPERTIES SOVERSION ${LIBRATIS_VERSION})
+ratis_dual_output_directory(ratis target/usr/local/lib)
+
+# By embedding '$ORIGIN' into the RPATH of libratis.so, dlopen will look in
+# the directory containing libratis.so. However, $ORIGIN is not supported by
+# all operating systems.
+if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|SunOS")
+    set(RPATH "\$ORIGIN/")
+    if(EXTRA_LIBRATIS_RPATH)
+        set(RPATH "${RPATH}:${EXTRA_LIBRATIS_RPATH}/")
+    endif()
+    set_target_properties(ratis PROPERTIES INSTALL_RPATH "${RPATH}")
+endif()
+
+# Build the CRC32 test executable.
+add_executable(test_bulk_crc32
+    ${SRC}/util/bulk_crc32.c
+    ${BULK_CRC_ARCH_SOURCE_FIlE}
+    ${TST}/util/test_bulk_crc32.c
+)

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/7e71a2e0/ratis-common/src/config.h.cmake
----------------------------------------------------------------------
diff --git a/ratis-common/src/config.h.cmake b/ratis-common/src/config.h.cmake
new file mode 100644
index 0000000..709fc75
--- /dev/null
+++ b/ratis-common/src/config.h.cmake
@@ -0,0 +1,24 @@
+/**
+* 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.
+*/
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#cmakedefine HAVE_SYNC_FILE_RANGE
+#cmakedefine HAVE_POSIX_FADVISE
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/7e71a2e0/ratis-common/src/main/conf/log4j.properties
----------------------------------------------------------------------
diff --git a/ratis-common/src/main/conf/log4j.properties b/ratis-common/src/main/conf/log4j.properties
new file mode 100644
index 0000000..64c1922
--- /dev/null
+++ b/ratis-common/src/main/conf/log4j.properties
@@ -0,0 +1,74 @@
+# 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.
+
+# Define some default values that can be overridden by system properties
+ratis.root.logger=INFO,console
+ratis.log.dir=.
+ratis.log.file=ratis.log
+
+# Define the root logger to the system property "ratis.root.logger".
+log4j.rootLogger=${ratis.root.logger}
+
+# Logging Threshold
+log4j.threshold=ALL
+
+# Null Appender
+log4j.appender.NullAppender=org.apache.log4j.varia.NullAppender
+
+#
+# Rolling File Appender - cap space usage at 5gb.
+#
+ratis.log.maxfilesize=256MB
+ratis.log.maxbackupindex=20
+log4j.appender.RFA=org.apache.log4j.RollingFileAppender
+log4j.appender.RFA.File=${ratis.log.dir}/${ratis.log.file}
+
+log4j.appender.RFA.MaxFileSize=${ratis.log.maxfilesize}
+log4j.appender.RFA.MaxBackupIndex=${ratis.log.maxbackupindex}
+
+log4j.appender.RFA.layout=org.apache.log4j.PatternLayout
+
+# Pattern format: Date LogLevel LoggerName LogMessage
+log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
+# Debugging Pattern format
+#log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n
+
+
+#
+# Daily Rolling File Appender
+#
+log4j.appender.DRFA=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.DRFA.File=${ratis.log.dir}/${ratis.log.file}
+
+# Rollover at midnight
+log4j.appender.DRFA.DatePattern=.yyyy-MM-dd
+
+log4j.appender.DRFA.layout=org.apache.log4j.PatternLayout
+
+# Pattern format: Date LogLevel LoggerName LogMessage
+log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
+# Debugging Pattern format
+#log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n
+
+
+#
+# console
+# Add "console" to rootlogger above if you want to use this
+#
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n