You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ratis.apache.org by sz...@apache.org on 2022/02/01 15:43:39 UTC

[ratis-hadoop-projects] branch main updated: RATIS-1516. Remove non-hadoop modules from ratis-hadoop-projects.git (#1)

This is an automated email from the ASF dual-hosted git repository.

szetszwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ratis-hadoop-projects.git


The following commit(s) were added to refs/heads/main by this push:
     new 6f58b7d  RATIS-1516. Remove non-hadoop modules from ratis-hadoop-projects.git (#1)
6f58b7d is described below

commit 6f58b7d49d0a1e4f0beb35cdaa6e1ae975df4bde
Author: Tsz-Wo Nicholas Sze <sz...@apache.org>
AuthorDate: Tue Feb 1 23:43:36 2022 +0800

    RATIS-1516. Remove non-hadoop modules from ratis-hadoop-projects.git (#1)
---
 .github/workflows/post-commit.yml                  |    4 +-
 pom.xml                                            |  109 +-
 ratis-client/pom.xml                               |   46 -
 .../java/org/apache/ratis/client/AsyncRpcApi.java  |   36 -
 .../org/apache/ratis/client/ClientFactory.java     |   37 -
 .../org/apache/ratis/client/DataStreamClient.java  |  103 --
 .../ratis/client/DataStreamClientFactory.java      |   41 -
 .../apache/ratis/client/DataStreamClientRpc.java   |   39 -
 .../apache/ratis/client/DataStreamOutputRpc.java   |   29 -
 .../org/apache/ratis/client/DataStreamRpcApi.java  |   29 -
 .../client/DisabledDataStreamClientFactory.java    |   41 -
 .../java/org/apache/ratis/client/RaftClient.java   |  169 --
 .../apache/ratis/client/RaftClientConfigKeys.java  |  138 --
 .../org/apache/ratis/client/RaftClientRpc.java     |   64 -
 .../java/org/apache/ratis/client/api/AdminApi.java |   43 -
 .../java/org/apache/ratis/client/api/AsyncApi.java |   71 -
 .../org/apache/ratis/client/api/BlockingApi.java   |   71 -
 .../org/apache/ratis/client/api/DataStreamApi.java |   53 -
 .../apache/ratis/client/api/DataStreamOutput.java  |   80 -
 .../ratis/client/api/GroupManagementApi.java       |   43 -
 .../ratis/client/api/MessageOutputStream.java      |   44 -
 .../apache/ratis/client/api/MessageStreamApi.java  |   55 -
 .../ratis/client/api/SnapshotManagementApi.java    |   32 -
 .../org/apache/ratis/client/impl/AdminImpl.java    |   57 -
 .../org/apache/ratis/client/impl/AsyncImpl.java    |   69 -
 .../org/apache/ratis/client/impl/BlockingImpl.java |  144 --
 .../apache/ratis/client/impl/ClientImplUtils.java  |   45 -
 .../apache/ratis/client/impl/ClientProtoUtils.java |  647 -------
 .../ratis/client/impl/DataStreamClientImpl.java    |  212 ---
 .../ratis/client/impl/GroupManagementImpl.java     |   84 -
 .../ratis/client/impl/MessageStreamImpl.java       |  100 -
 .../org/apache/ratis/client/impl/OrderedAsync.java |  278 ---
 .../ratis/client/impl/OrderedStreamAsync.java      |  173 --
 .../apache/ratis/client/impl/RaftClientImpl.java   |  390 ----
 .../ratis/client/impl/RaftClientRpcWithProxy.java  |   55 -
 .../ratis/client/impl/RaftClientTestUtil.java      |   42 -
 .../apache/ratis/client/impl/RaftOutputStream.java |  136 --
 .../ratis/client/impl/SnapshotManagementImpl.java  |   45 -
 .../apache/ratis/client/impl/UnorderedAsync.java   |  133 --
 .../ratis/client/retry/ClientRetryEvent.java       |   82 -
 .../retry/RequestTypeDependentRetryPolicy.java     |  105 --
 ratis-common/pom.xml                               |   59 -
 ratis-common/src/main/conf/log4j.properties        |   74 -
 .../main/java/org/apache/ratis/RaftConfigKeys.java |   69 -
 .../main/java/org/apache/ratis/conf/ConfUtils.java |  411 -----
 .../java/org/apache/ratis/conf/Parameters.java     |   66 -
 .../java/org/apache/ratis/conf/RaftProperties.java | 1429 ---------------
 .../apache/ratis/datastream/DataStreamFactory.java |   21 -
 .../apache/ratis/datastream/DataStreamType.java    |   70 -
 .../ratis/datastream/SupportedDataStreamType.java  |   59 -
 .../impl/DataStreamPacketByteBuffer.java           |   47 -
 .../datastream/impl/DataStreamPacketImpl.java      |   72 -
 .../datastream/impl/DataStreamReplyByteBuffer.java |  149 --
 .../impl/DataStreamRequestByteBuffer.java          |   47 -
 .../impl/DataStreamRequestFilePositionCount.java   |   56 -
 .../main/java/org/apache/ratis/io/CloseAsync.java  |   42 -
 .../apache/ratis/io/CorruptedFileException.java    |   27 -
 .../org/apache/ratis/io/FilePositionCount.java     |   56 -
 .../src/main/java/org/apache/ratis/io/MD5Hash.java |  215 ---
 .../org/apache/ratis/io/StandardWriteOption.java   |   25 -
 .../main/java/org/apache/ratis/io/WriteOption.java |   30 -
 .../ratis/protocol/AdminAsynchronousProtocol.java  |   38 -
 .../org/apache/ratis/protocol/AdminProtocol.java   |   35 -
 .../java/org/apache/ratis/protocol/ClientId.java   |   60 -
 .../apache/ratis/protocol/ClientInvocationId.java  |   88 -
 .../apache/ratis/protocol/DataStreamPacket.java    |   33 -
 .../ratis/protocol/DataStreamPacketHeader.java     |   49 -
 .../org/apache/ratis/protocol/DataStreamReply.java |   33 -
 .../ratis/protocol/DataStreamReplyHeader.java      |   56 -
 .../apache/ratis/protocol/DataStreamRequest.java   |   25 -
 .../ratis/protocol/DataStreamRequestHeader.java    |   45 -
 .../org/apache/ratis/protocol/GroupInfoReply.java  |   61 -
 .../apache/ratis/protocol/GroupInfoRequest.java    |   28 -
 .../org/apache/ratis/protocol/GroupListReply.java  |   43 -
 .../apache/ratis/protocol/GroupListRequest.java    |   28 -
 .../ratis/protocol/GroupManagementRequest.java     |  111 --
 .../ratis/protocol/LeaderElectionRequest.java      |   73 -
 .../java/org/apache/ratis/protocol/Message.java    |   70 -
 .../protocol/RaftClientAsynchronousProtocol.java   |   28 -
 .../apache/ratis/protocol/RaftClientMessage.java   |   68 -
 .../apache/ratis/protocol/RaftClientProtocol.java  |   24 -
 .../org/apache/ratis/protocol/RaftClientReply.java |  252 ---
 .../apache/ratis/protocol/RaftClientRequest.java   |  392 ----
 .../java/org/apache/ratis/protocol/RaftGroup.java  |  103 --
 .../org/apache/ratis/protocol/RaftGroupId.java     |   60 -
 .../apache/ratis/protocol/RaftGroupMemberId.java   |   71 -
 .../java/org/apache/ratis/protocol/RaftId.java     |  107 --
 .../java/org/apache/ratis/protocol/RaftPeer.java   |  236 ---
 .../java/org/apache/ratis/protocol/RaftPeerId.java |  103 --
 .../org/apache/ratis/protocol/RaftRpcMessage.java  |   29 -
 .../org/apache/ratis/protocol/RoutingTable.java    |  178 --
 .../ratis/protocol/SetConfigurationRequest.java    |   43 -
 .../ratis/protocol/SnapshotManagementRequest.java  |   58 -
 .../ratis/protocol/TransferLeadershipRequest.java  |   32 -
 .../exceptions/AlreadyClosedException.java         |   31 -
 .../exceptions/AlreadyExistsException.java         |   36 -
 .../protocol/exceptions/ChecksumException.java     |   35 -
 .../protocol/exceptions/DataStreamException.java   |   30 -
 .../exceptions/GroupMismatchException.java         |   28 -
 .../exceptions/LeaderNotReadyException.java        |   39 -
 .../exceptions/LeaderSteppingDownException.java    |   29 -
 .../protocol/exceptions/NotLeaderException.java    |   46 -
 .../exceptions/NotReplicatedException.java         |   46 -
 .../ratis/protocol/exceptions/RaftException.java   |   36 -
 .../exceptions/RaftRetryFailureException.java      |   39 -
 .../ReconfigurationInProgressException.java        |   24 -
 .../ReconfigurationTimeoutException.java           |   24 -
 .../exceptions/ResourceUnavailableException.java   |   27 -
 .../exceptions/ServerNotReadyException.java        |   27 -
 .../protocol/exceptions/StaleReadException.java    |   27 -
 .../protocol/exceptions/StateMachineException.java |   64 -
 .../ratis/protocol/exceptions/StreamException.java |   27 -
 .../protocol/exceptions/TimeoutIOException.java    |   35 -
 .../exceptions/TransferLeadershipException.java    |   29 -
 .../ratis/retry/ExceptionDependentRetry.java       |  117 --
 .../ratis/retry/ExponentialBackoffRetry.java       |   90 -
 .../ratis/retry/MultipleLinearRandomRetry.java     |  188 --
 .../java/org/apache/ratis/retry/RetryPolicies.java |  134 --
 .../java/org/apache/ratis/retry/RetryPolicy.java   |   75 -
 .../src/main/java/org/apache/ratis/rpc/CallId.java |   46 -
 .../main/java/org/apache/ratis/rpc/RpcFactory.java |   22 -
 .../main/java/org/apache/ratis/rpc/RpcType.java    |   68 -
 .../org/apache/ratis/rpc/SupportedRpcType.java     |   48 -
 .../apache/ratis/util/AtomicFileOutputStream.java  |  128 --
 .../org/apache/ratis/util/AutoCloseableLock.java   |   69 -
 .../ratis/util/AutoCloseableReadWriteLock.java     |   68 -
 .../java/org/apache/ratis/util/AwaitForSignal.java |   74 -
 .../apache/ratis/util/CodeInjectionForTesting.java |   71 -
 .../org/apache/ratis/util/CollectionUtils.java     |  143 --
 .../org/apache/ratis/util/ConcurrentUtils.java     |  156 --
 .../main/java/org/apache/ratis/util/Daemon.java    |   40 -
 .../org/apache/ratis/util/DataBlockingQueue.java   |  165 --
 .../main/java/org/apache/ratis/util/DataQueue.java |  182 --
 .../main/java/org/apache/ratis/util/ExitUtils.java |  161 --
 .../main/java/org/apache/ratis/util/FileUtils.java |  196 --
 .../main/java/org/apache/ratis/util/IOUtils.java   |  227 ---
 .../main/java/org/apache/ratis/util/JavaUtils.java |  256 ---
 .../java/org/apache/ratis/util/JmxRegister.java    |   77 -
 .../org/apache/ratis/util/JvmPauseMonitor.java     |  163 --
 .../main/java/org/apache/ratis/util/LifeCycle.java |  325 ----
 .../main/java/org/apache/ratis/util/LogUtils.java  |  140 --
 .../java/org/apache/ratis/util/LongMinMax.java     |   76 -
 .../java/org/apache/ratis/util/MD5FileUtil.java    |  185 --
 .../org/apache/ratis/util/MemoizedSupplier.java    |   74 -
 .../main/java/org/apache/ratis/util/NetUtils.java  |  170 --
 .../java/org/apache/ratis/util/OpenCloseState.java |  129 --
 .../java/org/apache/ratis/util/PeerProxyMap.java   |  172 --
 .../java/org/apache/ratis/util/PlatformUtils.java  |   74 -
 .../java/org/apache/ratis/util/Preconditions.java  |  119 --
 .../java/org/apache/ratis/util/ProtoUtils.java     |  248 ---
 .../java/org/apache/ratis/util/PureJavaCrc32C.java |  634 -------
 .../org/apache/ratis/util/ReflectionUtils.java     |  261 ---
 .../org/apache/ratis/util/ResourceSemaphore.java   |  187 --
 .../java/org/apache/ratis/util/SizeInBytes.java    |   85 -
 .../java/org/apache/ratis/util/SlidingWindow.java  |  480 -----
 .../java/org/apache/ratis/util/StringUtils.java    |  171 --
 .../main/java/org/apache/ratis/util/TaskQueue.java |  145 --
 .../java/org/apache/ratis/util/TimeDuration.java   |  377 ----
 .../org/apache/ratis/util/TimeoutScheduler.java    |  198 --
 .../main/java/org/apache/ratis/util/Timestamp.java |  130 --
 .../apache/ratis/util/TraditionalBinaryPrefix.java |  164 --
 .../apache/ratis/util/UncheckedAutoCloseable.java  |   27 -
 .../ratis/util/function/CheckedBiConsumer.java     |   28 -
 .../ratis/util/function/CheckedBiFunction.java     |   28 -
 .../ratis/util/function/CheckedConsumer.java       |   37 -
 .../ratis/util/function/CheckedFunction.java       |   28 -
 .../util/function/CheckedFunctionWithTimeout.java  |   32 -
 .../ratis/util/function/CheckedRunnable.java       |   36 -
 .../ratis/util/function/CheckedSupplier.java       |   28 -
 .../apache/ratis/util/function/FunctionUtils.java  |   34 -
 .../apache/ratis/util/function/TriConsumer.java    |   28 -
 .../src/test/java/org/apache/ratis/BaseTest.java   |  198 --
 .../java/org/apache/ratis/JUnitRunListener.java    |   91 -
 .../java/org/apache/ratis/util/FileUtilsTest.java  |   41 -
 .../java/org/apache/ratis/util/Log4jUtils.java     |   37 -
 .../java/org/apache/ratis/util/TestNetUtils.java   |   37 -
 .../java/org/apache/ratis/util/TestTaskQueue.java  |   49 -
 ratis-docs/README.md                               |   55 -
 ratis-docs/archetypes/default.md                   |   20 -
 ratis-docs/config.yaml                             |   34 -
 ratis-docs/content/_index.md                       |   33 -
 ratis-docs/content/concept/_index.md               |   46 -
 ratis-docs/content/start/_index.md                 |   34 -
 ratis-docs/dev-support/bin/generate-site.sh        |   31 -
 ratis-docs/pom.xml                                 |   72 -
 .../themes/ratisdoc/layouts/_default/section.html  |   75 -
 .../themes/ratisdoc/layouts/_default/single.html   |   61 -
 ratis-docs/themes/ratisdoc/layouts/index.html      |   37 -
 .../themes/ratisdoc/layouts/partials/footer.html   |   22 -
 .../themes/ratisdoc/layouts/partials/header.html   |   34 -
 .../ratisdoc/layouts/partials/languages.html       |   24 -
 .../themes/ratisdoc/layouts/partials/navbar.html   |   38 -
 .../themes/ratisdoc/layouts/partials/sidebar.html  |   70 -
 .../ratisdoc/layouts/shortcodes/buttonlink.html    |   20 -
 .../themes/ratisdoc/layouts/shortcodes/card.html   |   40 -
 .../ratisdoc/layouts/shortcodes/jumbotron.html     |   25 -
 .../ratisdoc/layouts/shortcodes/requirements.html  |   22 -
 .../ratisdoc/static/css/bootstrap-theme.min.css    |    6 -
 .../static/css/bootstrap-theme.min.css.map         |    1 -
 .../themes/ratisdoc/static/css/bootstrap.min.css   |    6 -
 .../ratisdoc/static/css/bootstrap.min.css.map      |    1 -
 ratis-docs/themes/ratisdoc/static/css/ratisdoc.css |  169 --
 .../static/fonts/glyphicons-halflings-regular.eot  |  Bin 20127 -> 0 bytes
 .../static/fonts/glyphicons-halflings-regular.svg  |  288 ---
 .../static/fonts/glyphicons-halflings-regular.ttf  |  Bin 45404 -> 0 bytes
 .../static/fonts/glyphicons-halflings-regular.woff |  Bin 23424 -> 0 bytes
 .../fonts/glyphicons-halflings-regular.woff2       |  Bin 18028 -> 0 bytes
 .../themes/ratisdoc/static/js/bootstrap.min.js     |    6 -
 .../themes/ratisdoc/static/js/jquery-3.4.1.min.js  |    2 -
 ratis-docs/themes/ratisdoc/static/js/ratisdoc.js   |   23 -
 ratis-docs/themes/ratisdoc/theme.toml              |    2 -
 ratis-examples/README.md                           |  148 --
 ratis-examples/pom.xml                             |  206 ---
 ratis-examples/src/main/bin/client.sh              |   35 -
 ratis-examples/src/main/bin/common.sh              |   48 -
 ratis-examples/src/main/bin/server.sh              |   20 -
 ratis-examples/src/main/bin/start-all.sh           |   45 -
 ratis-examples/src/main/bin/stop-all.sh            |   18 -
 ratis-examples/src/main/docker/Dockerfile          |   39 -
 ratis-examples/src/main/docker/docker-compose.yaml |   63 -
 .../examples/arithmetic/ArithmeticLogDump.java     |   51 -
 .../arithmetic/ArithmeticStateMachine.java         |  185 --
 .../examples/arithmetic/AssignmentMessage.java     |   83 -
 .../ratis/examples/arithmetic/Evaluable.java       |   24 -
 .../ratis/examples/arithmetic/cli/Arithmetic.java  |   40 -
 .../ratis/examples/arithmetic/cli/Assign.java      |  111 --
 .../ratis/examples/arithmetic/cli/Client.java      |   57 -
 .../apache/ratis/examples/arithmetic/cli/Get.java  |   48 -
 .../ratis/examples/arithmetic/cli/Server.java      |   86 -
 .../arithmetic/expression/BinaryExpression.java    |  145 --
 .../arithmetic/expression/DoubleValue.java         |   80 -
 .../examples/arithmetic/expression/Expression.java |  113 --
 .../examples/arithmetic/expression/NullValue.java  |   55 -
 .../arithmetic/expression/UnaryExpression.java     |  147 --
 .../examples/arithmetic/expression/Variable.java   |  132 --
 .../org/apache/ratis/examples/common/Runner.java   |   83 -
 .../ratis/examples/common/SubCommandBase.java      |  107 --
 .../ratis/examples/counter/CounterCommon.java      |   50 -
 .../examples/counter/client/CounterClient.java     |   96 -
 .../examples/counter/server/CounterServer.java     |   90 -
 .../counter/server/CounterStateMachine.java        |  210 ---
 .../apache/ratis/examples/filestore/FileInfo.java  |  298 ---
 .../apache/ratis/examples/filestore/FileStore.java |  333 ----
 .../ratis/examples/filestore/FileStoreClient.java  |  210 ---
 .../ratis/examples/filestore/FileStoreCommon.java  |   65 -
 .../examples/filestore/FileStoreStateMachine.java  |  254 ---
 .../ratis/examples/filestore/cli/Client.java       |  220 ---
 .../ratis/examples/filestore/cli/DataStream.java   |  318 ----
 .../ratis/examples/filestore/cli/FileStore.java    |   40 -
 .../ratis/examples/filestore/cli/LoadGen.java      |  136 --
 .../ratis/examples/filestore/cli/Server.java       |  126 --
 ratis-examples/src/main/resources/log4j.properties |   25 -
 .../java/org/apache/ratis/TestMultiRaftGroup.java  |   77 -
 .../ratis/examples/ParameterizedBaseTest.java      |  134 --
 .../ratis/examples/arithmetic/TestArithmetic.java  |  169 --
 .../examples/arithmetic/TestArithmeticLogDump.java |   89 -
 .../examples/arithmetic/cli/TestAssignCli.java     |   87 -
 .../arithmetic/expression/TestExpression.java      |  104 --
 .../ratis/examples/common/TestSubCommand.java      |   44 -
 .../apache/ratis/examples/counter/TestCounter.java |   69 -
 .../examples/filestore/FileStoreAsyncBaseTest.java |  120 --
 .../examples/filestore/FileStoreBaseTest.java      |  135 --
 .../filestore/FileStoreStreamingBaseTest.java      |  141 --
 .../ratis/examples/filestore/FileStoreWriter.java  |  293 ---
 .../filestore/TestFileStoreAsyncWithGrpc.java      |   25 -
 .../TestFileStoreStreamingWithGrpcCluster.java     |   25 -
 .../examples/filestore/TestFileStoreWithGrpc.java  |   25 -
 .../examples/filestore/TestFileStoreWithNetty.java |   25 -
 ratis-examples/src/test/resources/log4j.properties |   18 -
 ratis-experiments/README.md                        |   66 -
 ratis-experiments/pom.xml                          |  162 --
 ratis-experiments/scripts/flatbuf-compile.sh       |   30 -
 .../src/main/flatbufs/FileTransfer.fbs             |   34 -
 .../experiments/flatbuffers/client/ClientFlat.java |  133 --
 .../flatbuffers/client/ClientProto.java            |  132 --
 .../flatbuffers/server/FileTransferFlatbufs.java   |   66 -
 .../flatbuffers/server/FileTransferProtobufs.java  |   60 -
 .../experiments/flatbuffers/server/ServerFlat.java |   46 -
 .../flatbuffers/server/ServerProto.java            |   47 -
 .../nettyzerocopy/client/NettyClient.java          |  150 --
 .../nettyzerocopy/decoders/RequestDecoder.java     |   62 -
 .../decoders/RequestDecoderComposite.java          |   69 -
 .../nettyzerocopy/decoders/ResponseDecoder.java    |   43 -
 .../nettyzerocopy/encoders/RequestEncoder.java     |   46 -
 .../nettyzerocopy/encoders/ResponseEncoder.java    |   46 -
 .../nettyzerocopy/objects/RequestData.java         |   54 -
 .../objects/RequestDataComposite.java              |   42 -
 .../nettyzerocopy/objects/ResponseData.java        |   31 -
 .../nettyzerocopy/server/NettyServer.java          |   96 -
 ratis-grpc/pom.xml                                 |   91 -
 .../java/org/apache/ratis/grpc/GrpcConfigKeys.java |  222 ---
 .../java/org/apache/ratis/grpc/GrpcFactory.java    |  130 --
 .../java/org/apache/ratis/grpc/GrpcTlsConfig.java  |  105 --
 .../main/java/org/apache/ratis/grpc/GrpcUtil.java  |  235 ---
 .../grpc/client/GrpcClientProtocolClient.java      |  404 -----
 .../ratis/grpc/client/GrpcClientProtocolProxy.java |  108 --
 .../apache/ratis/grpc/client/GrpcClientRpc.java    |  187 --
 .../ratis/grpc/metrics/GrpcServerMetrics.java      |  109 --
 .../apache/ratis/grpc/metrics/MessageMetrics.java  |   65 -
 .../metrics/intercept/client/MetricClientCall.java |   44 -
 .../intercept/client/MetricClientCallListener.java |   49 -
 .../intercept/client/MetricClientInterceptor.java  |   63 -
 .../metrics/intercept/server/MetricServerCall.java |   49 -
 .../intercept/server/MetricServerCallListener.java |   46 -
 .../intercept/server/MetricServerInterceptor.java  |   89 -
 .../grpc/server/GrpcAdminProtocolService.java      |   88 -
 .../grpc/server/GrpcClientProtocolService.java     |  407 -----
 .../apache/ratis/grpc/server/GrpcLogAppender.java  |  695 -------
 .../grpc/server/GrpcServerProtocolClient.java      |  125 --
 .../grpc/server/GrpcServerProtocolService.java     |  263 ---
 .../org/apache/ratis/grpc/server/GrpcService.java  |  335 ----
 .../apache/ratis/grpc/MiniRaftClusterWithGrpc.java |   78 -
 .../ratis/grpc/server/TestGrpcServerMetrics.java   |  151 --
 ratis-metrics/pom.xml                              |   80 -
 .../java/org/apache/ratis/metrics/JVMMetrics.java  |   47 -
 .../org/apache/ratis/metrics/MetricRegistries.java |  111 --
 .../ratis/metrics/MetricRegistriesLoader.java      |   97 -
 .../ratis/metrics/MetricRegistryFactory.java       |   33 -
 .../apache/ratis/metrics/MetricRegistryInfo.java   |  100 -
 .../org/apache/ratis/metrics/MetricsReporting.java |   75 -
 .../apache/ratis/metrics/RatisMetricRegistry.java  |   73 -
 .../org/apache/ratis/metrics/RatisMetrics.java     |   57 -
 .../ratis/metrics/impl/MetricRegistriesImpl.java   |  131 --
 .../metrics/impl/MetricRegistryFactoryImpl.java    |   29 -
 .../metrics/impl/RatisMetricRegistryImpl.java      |  149 --
 .../apache/ratis/metrics/impl/RefCountingMap.java  |   94 -
 .../org.apache.ratis.metrics.MetricRegistries      |   18 -
 .../ratis/metrics/TestMetricRegistriesLoader.java  |   54 -
 .../ratis/metrics/impl/TestRefCountingMap.java     |  147 --
 .../src/test/resources/hadoop-metrics2.properties  |   44 -
 ratis-netty/pom.xml                                |   83 -
 .../java/org/apache/ratis/netty/NettyClient.java   |   70 -
 .../org/apache/ratis/netty/NettyConfigKeys.java    |  114 --
 .../apache/ratis/netty/NettyDataStreamFactory.java |   49 -
 .../apache/ratis/netty/NettyDataStreamUtils.java   |  248 ---
 .../java/org/apache/ratis/netty/NettyFactory.java  |   47 -
 .../java/org/apache/ratis/netty/NettyRpcProxy.java |  200 --
 .../apache/ratis/netty/client/NettyClientRpc.java  |   92 -
 .../ratis/netty/client/NettyClientStreamRpc.java   |  271 ---
 .../ratis/netty/server/DataStreamManagement.java   |  482 -----
 .../netty/server/DataStreamRequestByteBuf.java     |   67 -
 .../apache/ratis/netty/server/NettyRpcService.java |  347 ----
 .../ratis/netty/server/NettyServerStreamRpc.java   |  268 ---
 .../ratis/netty/MiniRaftClusterWithNetty.java      |   70 -
 ratis-replicated-map/README.md                     |   36 -
 ratis-replicated-map/pom.xml                       |   93 -
 .../src/test/resources/log4j.properties            |   18 -
 ratis-server-api/pom.xml                           |   58 -
 .../org/apache/ratis/server/DataStreamMap.java     |   34 -
 .../org/apache/ratis/server/DataStreamServer.java  |   30 -
 .../ratis/server/DataStreamServerFactory.java      |   37 -
 .../apache/ratis/server/DataStreamServerRpc.java   |   37 -
 .../java/org/apache/ratis/server/DivisionInfo.java |   72 -
 .../apache/ratis/server/DivisionProperties.java    |   55 -
 .../org/apache/ratis/server/RaftConfiguration.java |   50 -
 .../java/org/apache/ratis/server/RaftServer.java   |  239 ---
 .../apache/ratis/server/RaftServerConfigKeys.java  |  707 --------
 .../org/apache/ratis/server/RaftServerMXBean.java  |   62 -
 .../org/apache/ratis/server/RaftServerRpc.java     |   56 -
 .../ratis/server/RaftServerRpcWithProxy.java       |   87 -
 .../java/org/apache/ratis/server/RetryCache.java   |   70 -
 .../org/apache/ratis/server/ServerFactory.java     |   42 -
 .../apache/ratis/server/leader/FollowerInfo.java   |   92 -
 .../apache/ratis/server/leader/LeaderState.java    |   65 -
 .../apache/ratis/server/leader/LogAppender.java    |  178 --
 .../ratis/server/metrics/RaftLogMetrics.java       |   34 -
 .../ratis/server/metrics/RaftServerMetrics.java    |   25 -
 .../protocol/RaftServerAsynchronousProtocol.java   |   31 -
 .../ratis/server/protocol/RaftServerProtocol.java  |   41 -
 .../apache/ratis/server/protocol/TermIndex.java    |  102 --
 .../ratis/server/raftlog/LogEntryHeader.java       |   86 -
 .../org/apache/ratis/server/raftlog/RaftLog.java   |  166 --
 .../ratis/server/raftlog/RaftLogIOException.java   |   37 -
 .../apache/ratis/server/raftlog/RaftLogIndex.java  |   85 -
 .../ratis/server/raftlog/RaftLogSequentialOps.java |  137 --
 .../org/apache/ratis/server/storage/FileInfo.java  |   59 -
 .../apache/ratis/server/storage/RaftStorage.java   |   38 -
 .../ratis/server/storage/RaftStorageDirectory.java |   53 -
 .../ratis/server/storage/RaftStorageMetadata.java  |   82 -
 .../server/storage/RaftStorageMetadataFile.java    |   32 -
 .../apache/ratis/statemachine/SnapshotInfo.java    |   55 -
 .../statemachine/SnapshotRetentionPolicy.java      |   32 -
 .../apache/ratis/statemachine/StateMachine.java    |  482 -----
 .../ratis/statemachine/StateMachineStorage.java    |   41 -
 .../ratis/statemachine/TransactionContext.java     |  226 ---
 ratis-server/pom.xml                               |  101 --
 .../server/DisabledDataStreamServerFactory.java    |   54 -
 .../apache/ratis/server/impl/CommitInfoCache.java  |   53 -
 .../ratis/server/impl/ConfigurationManager.java    |   97 -
 .../ratis/server/impl/DataStreamMapImpl.java       |   57 -
 .../ratis/server/impl/DataStreamServerImpl.java    |   51 -
 .../ratis/server/impl/DivisionPropertiesImpl.java  |   61 -
 .../apache/ratis/server/impl/FollowerInfoImpl.java |  181 --
 .../apache/ratis/server/impl/FollowerState.java    |  158 --
 .../apache/ratis/server/impl/LeaderElection.java   |  447 -----
 .../apache/ratis/server/impl/LeaderStateImpl.java  | 1089 -----------
 .../ratis/server/impl/MessageStreamRequests.java   |  110 --
 .../ratis/server/impl/PeerConfiguration.java       |  122 --
 .../apache/ratis/server/impl/PendingRequest.java   |  114 --
 .../apache/ratis/server/impl/PendingRequests.java  |  296 ---
 .../ratis/server/impl/RaftConfigurationImpl.java   |  280 ---
 .../apache/ratis/server/impl/RaftServerImpl.java   | 1906 --------------------
 .../apache/ratis/server/impl/RaftServerProxy.java  |  621 -------
 .../apache/ratis/server/impl/RetryCacheImpl.java   |  268 ---
 .../org/apache/ratis/server/impl/RoleInfo.java     |  147 --
 .../apache/ratis/server/impl/ServerImplUtils.java  |   85 -
 .../apache/ratis/server/impl/ServerProtoUtils.java |  163 --
 .../org/apache/ratis/server/impl/ServerState.java  |  486 -----
 .../impl/SnapshotManagementRequestHandler.java     |  123 --
 .../ratis/server/impl/StateMachineMetrics.java     |   75 -
 .../ratis/server/impl/StateMachineUpdater.java     |  329 ----
 .../ratis/server/impl/TransferLeadership.java      |  120 --
 .../org/apache/ratis/server/impl/VoteContext.java  |  158 --
 .../apache/ratis/server/impl/WatchRequests.java    |  213 ---
 .../server/leader/InstallSnapshotRequests.java     |  139 --
 .../ratis/server/leader/LeaderProtoUtils.java      |   73 -
 .../ratis/server/leader/LogAppenderBase.java       |  196 --
 .../ratis/server/leader/LogAppenderDaemon.java     |  127 --
 .../ratis/server/leader/LogAppenderDefault.java    |  192 --
 .../server/metrics/LeaderElectionMetrics.java      |   83 -
 .../ratis/server/metrics/LogAppenderMetrics.java   |   54 -
 .../ratis/server/metrics/RaftLogMetricsBase.java   |   82 -
 .../server/metrics/RaftServerMetricsImpl.java      |  282 ---
 .../server/metrics/SegmentedRaftLogMetrics.java    |  181 --
 .../apache/ratis/server/raftlog/LogProtoUtils.java |  207 ---
 .../apache/ratis/server/raftlog/RaftLogBase.java   |  425 -----
 .../ratis/server/raftlog/memory/MemoryRaftLog.java |  246 ---
 .../raftlog/segmented/BufferedWriteChannel.java    |  125 --
 .../raftlog/segmented/CacheInvalidationPolicy.java |  129 --
 .../ratis/server/raftlog/segmented/LogSegment.java |  451 -----
 .../server/raftlog/segmented/LogSegmentPath.java   |  137 --
 .../raftlog/segmented/LogSegmentStartEnd.java      |  136 --
 .../server/raftlog/segmented/SegmentedRaftLog.java |  521 ------
 .../raftlog/segmented/SegmentedRaftLogCache.java   |  688 -------
 .../raftlog/segmented/SegmentedRaftLogFormat.java  |   82 -
 .../segmented/SegmentedRaftLogInputStream.java     |  257 ---
 .../segmented/SegmentedRaftLogOutputStream.java    |  146 --
 .../raftlog/segmented/SegmentedRaftLogReader.java  |  350 ----
 .../raftlog/segmented/SegmentedRaftLogWorker.java  |  707 --------
 .../ratis/server/storage/FileChunkReader.java      |   95 -
 .../server/storage/RaftStorageDirectoryImpl.java   |  269 ---
 .../ratis/server/storage/RaftStorageImpl.java      |  162 --
 .../storage/RaftStorageMetadataFileImpl.java       |  121 --
 .../ratis/server/storage/SnapshotManager.java      |  141 --
 .../ratis/server/util/ServerStringUtils.java       |  112 --
 .../ratis/statemachine/impl/BaseStateMachine.java  |  246 ---
 .../statemachine/impl/FileListSnapshotInfo.java    |   57 -
 .../impl/SimpleStateMachineStorage.java            |  191 --
 .../statemachine/impl/SingleFileSnapshotInfo.java  |   38 -
 .../statemachine/impl/TransactionContextImpl.java  |  185 --
 .../ratis/InstallSnapshotNotificationTests.java    |  430 -----
 .../java/org/apache/ratis/LogAppenderTests.java    |  222 ---
 .../org/apache/ratis/MessageStreamApiTests.java    |  127 --
 .../org/apache/ratis/OutputStreamBaseTest.java     |  315 ----
 .../org/apache/ratis/RaftAsyncExceptionTests.java  |  124 --
 .../test/java/org/apache/ratis/RaftAsyncTests.java |  489 -----
 .../test/java/org/apache/ratis/RaftBasicTests.java |  522 ------
 .../org/apache/ratis/RaftExceptionBaseTest.java    |  203 ---
 .../test/java/org/apache/ratis/RaftTestUtil.java   |  523 ------
 .../apache/ratis/RequestLimitAsyncBaseTest.java    |  125 --
 .../java/org/apache/ratis/RetryCacheTests.java     |  169 --
 .../java/org/apache/ratis/WatchRequestTests.java   |  508 ------
 .../server/impl/BlockRequestHandlingInjection.java |   99 -
 .../server/impl/DelayLocalExecutionInjection.java  |   80 -
 .../ratis/server/impl/GroupInfoBaseTest.java       |  155 --
 .../ratis/server/impl/GroupManagementBaseTest.java |  455 -----
 .../ratis/server/impl/LeaderElectionTests.java     |  465 -----
 .../apache/ratis/server/impl/MiniRaftCluster.java  |  823 ---------
 .../server/impl/PreAppendLeaderStepDownTest.java   |  111 --
 .../server/impl/RaftReconfigurationBaseTest.java   |  700 -------
 .../ratis/server/impl/RaftServerTestUtil.java      |  188 --
 .../impl/RaftStateMachineExceptionTests.java       |  181 --
 .../ratis/server/impl/RetryCacheTestUtil.java      |   88 -
 .../ratis/server/impl/ServerPauseResumeTest.java   |   88 -
 .../server/impl/StateMachineShutdownTests.java     |  124 --
 .../ratis/server/impl/TestLogAppenderMetrics.java  |  107 --
 .../server/impl/TestRatisServerMetricsBase.java    |   74 -
 .../ratis/server/impl/TestRetryCacheMetrics.java   |  121 --
 .../server/metrics/TestLeaderElectionMetrics.java  |   67 -
 .../segmented/SegmentedRaftLogTestUtils.java       |   31 -
 .../MiniRaftClusterWithSimulatedRpc.java           |  119 --
 .../ratis/server/simulation/RaftServerReply.java   |  140 --
 .../ratis/server/simulation/RaftServerRequest.java |  137 --
 .../ratis/server/simulation/RequestHandler.java    |  142 --
 .../server/simulation/SimulatedClientRpc.java      |   43 -
 .../server/simulation/SimulatedRequestReply.java   |  201 ---
 .../ratis/server/simulation/SimulatedRpc.java      |   83 -
 .../server/simulation/SimulatedServerRpc.java      |  215 ---
 .../ratis/server/storage/RaftStorageTestUtils.java |   75 -
 .../ratis/statemachine/RaftSnapshotBaseTest.java   |  335 ----
 .../statemachine/SimpleStateMachine4Testing.java   |  444 -----
 .../ratis/statemachine/SnapshotManagementTest.java |  146 --
 ratis-shell/pom.xml                                |  117 --
 ratis-shell/src/main/bin/ratis                     |   73 -
 ratis-shell/src/main/conf/log4j.properties         |   31 -
 .../org/apache/ratis/shell/cli/AbstractShell.java  |  149 --
 .../java/org/apache/ratis/shell/cli/Command.java   |  123 --
 .../java/org/apache/ratis/shell/cli/RaftUtils.java |   82 -
 .../org/apache/ratis/shell/cli/sh/RatisShell.java  |   82 -
 .../shell/cli/sh/command/AbstractRatisCommand.java |  199 --
 .../apache/ratis/shell/cli/sh/command/Context.java |   54 -
 .../ratis/shell/cli/sh/command/ElectCommand.java   |  130 --
 .../ratis/shell/cli/sh/command/GroupCommand.java   |   96 -
 .../ratis/shell/cli/sh/command/PeerCommand.java    |  138 --
 .../shell/cli/sh/command/SetPriorityCommand.java   |  114 --
 .../shell/cli/sh/command/SnapshotCommand.java      |   94 -
 .../ratis/shell/cli/sh/group/GroupInfoCommand.java |   84 -
 .../ratis/shell/cli/sh/group/GroupListCommand.java |  113 --
 .../shell/cli/sh/snapshot/TakeSnapshotCommand.java |  111 --
 ratis-shell/src/main/libexec/ratis-shell-config.sh |   72 -
 ratis-test/pom.xml                                 |  109 --
 .../ratis/TestRaftServerNoLeaderTimeout.java       |  100 -
 .../ratis/TestRaftServerSlownessDetection.java     |  131 --
 .../apache/ratis/client/TestClientProtoUtils.java  |  102 --
 .../java/org/apache/ratis/conf/TestConfUtils.java  |   53 -
 .../datastream/DataStreamAsyncClusterTests.java    |  169 --
 .../ratis/datastream/DataStreamBaseTest.java       |  158 --
 .../ratis/datastream/DataStreamClusterTests.java   |  170 --
 .../ratis/datastream/DataStreamTestUtils.java      |  411 -----
 ...usterWithRpcTypeGrpcAndDataStreamTypeNetty.java |   60 -
 ...sterWithRpcTypeNettyAndDataStreamTypeNetty.java |   60 -
 .../ratis/datastream/TestDataStreamDisabled.java   |   55 -
 ...ettyDataStreamChainTopologyWithGrpcCluster.java |   23 -
 ...NettyDataStreamStarTopologyWithGrpcCluster.java |   41 -
 .../datastream/TestNettyDataStreamWithMock.java    |  180 --
 .../TestNettyDataStreamWithNettyCluster.java       |   26 -
 .../apache/ratis/grpc/TestGroupInfoWithGrpc.java   |   25 -
 .../ratis/grpc/TestGroupManagementWithGrpc.java    |   28 -
 .../apache/ratis/grpc/TestGrpcMessageMetrics.java  |   73 -
 .../TestInstallSnapshotNotificationWithGrpc.java   |   25 -
 .../ratis/grpc/TestLeaderElectionWithGrpc.java     |   41 -
 .../apache/ratis/grpc/TestLogAppenderWithGrpc.java |  139 --
 .../ratis/grpc/TestMessageStreamApiWithGrpc.java   |   24 -
 .../grpc/TestPreAppendLeaderStepDownWithGrpc.java  |   25 -
 .../ratis/grpc/TestRaftAsyncExceptionWithGrpc.java |   25 -
 .../apache/ratis/grpc/TestRaftAsyncWithGrpc.java   |   24 -
 .../ratis/grpc/TestRaftExceptionWithGrpc.java      |   25 -
 .../ratis/grpc/TestRaftOutputStreamWithGrpc.java   |   29 -
 .../grpc/TestRaftReconfigurationWithGrpc.java      |   25 -
 .../apache/ratis/grpc/TestRaftServerWithGrpc.java  |  332 ----
 .../ratis/grpc/TestRaftSnapshotWithGrpc.java       |   49 -
 .../TestRaftStateMachineExceptionWithGrpc.java     |   26 -
 .../org/apache/ratis/grpc/TestRaftWithGrpc.java    |  119 --
 .../ratis/grpc/TestRequestLimitAsyncWithGrpc.java  |   25 -
 .../apache/ratis/grpc/TestRetryCacheWithGrpc.java  |   94 -
 .../ratis/grpc/TestServerPauseResumeWithGrpc.java  |   26 -
 .../ratis/grpc/TestServerRestartWithGrpc.java      |   25 -
 .../ratis/grpc/TestSnapshotManagementWithGrpc.java |   25 -
 .../grpc/TestStateMachineShutdownWithGrpc.java     |   26 -
 .../ratis/grpc/TestWatchRequestWithGrpc.java       |   35 -
 .../apache/ratis/netty/TestGroupInfoWithNetty.java |   25 -
 .../ratis/netty/TestGroupManagementWithNetty.java  |   28 -
 .../ratis/netty/TestLeaderElectionWithNetty.java   |   41 -
 .../ratis/netty/TestLogAppenderWithNetty.java      |   25 -
 .../TestPreAppendLeaderStepDownWithNetty.java      |   25 -
 .../ratis/netty/TestRaftExceptionWithNetty.java    |   25 -
 .../netty/TestRaftReconfigurationWithNetty.java    |   25 -
 .../ratis/netty/TestRaftSnapshotWithNetty.java     |   28 -
 .../TestRaftStateMachineExceptionWithNetty.java    |   25 -
 .../org/apache/ratis/netty/TestRaftWithNetty.java  |   34 -
 .../ratis/netty/TestRetryCacheWithNettyRpc.java    |   25 -
 .../netty/TestServerPauseResumeWithNetty.java      |   26 -
 .../ratis/netty/TestServerRestartWithNetty.java    |   29 -
 .../netty/TestSnapshotManagementWithNetty.java     |   25 -
 .../java/org/apache/ratis/protocol/TestRaftId.java |   54 -
 .../apache/ratis/protocol/TestRoutingTable.java    |   91 -
 .../ratis/retry/TestExceptionDependentRetry.java   |  205 ---
 .../ratis/retry/TestExponentialBackoffRetry.java   |   81 -
 .../ratis/retry/TestMultipleLinearRandomRetry.java |   86 -
 .../org/apache/ratis/retry/TestRetryPolicy.java    |  301 ----
 .../apache/ratis/server/ServerRestartTests.java    |  391 ----
 .../ratis/server/TestRaftServerConfigKeys.java     |  118 --
 .../ratis/server/impl/TestPeerConfiguration.java   |   82 -
 .../ratis/server/impl/TestRaftConfiguration.java   |   59 -
 .../ratis/server/impl/TestRaftServerJmx.java       |  112 --
 .../apache/ratis/server/impl/TestServerState.java  |  126 --
 .../ratis/server/raftlog/TestRaftLogIndex.java     |   84 -
 .../ratis/server/raftlog/TestRaftLogMetrics.java   |  185 --
 .../server/raftlog/memory/MemoryRaftLogTest.java   |   97 -
 .../segmented/TestBufferedWriteChannel.java        |  186 --
 .../raftlog/segmented/TestCacheEviction.java       |  203 ---
 .../server/raftlog/segmented/TestLogSegment.java   |  380 ----
 .../raftlog/segmented/TestRaftLogReadWrite.java    |  265 ---
 .../raftlog/segmented/TestSegmentedRaftLog.java    |  681 -------
 .../segmented/TestSegmentedRaftLogCache.java       |  340 ----
 .../simulation/TestGroupInfoWithSimulatedRpc.java  |   25 -
 .../TestGroupManagementWithSimulatedRpc.java       |   28 -
 .../TestLeaderElectionWithSimulatedRpc.java        |   25 -
 .../TestLogAppenderWithSimulatedRpc.java           |   25 -
 ...estPreAppendLeaderStepDownWithSimulatedRpc.java |   25 -
 .../TestRaftExceptionWithSimulation.java           |   25 -
 .../TestRaftReconfigurationWithSimulatedRpc.java   |   25 -
 .../TestRaftSnapshotWithSimulatedRpc.java          |   28 -
 ...tRaftStateMachineExceptionWithSimulatedRpc.java |   25 -
 .../simulation/TestRaftWithSimulatedRpc.java       |   25 -
 .../TestRatisServerMetricsWithSimulatedRpc.java    |   26 -
 .../simulation/TestRetryCacheWithSimulatedRpc.java |   25 -
 .../TestServerPauseResumeWithSimulatedRpc.java     |   26 -
 .../TestServerRestartWithSimulatedRpc.java         |   25 -
 .../TestSnapshotManagementWithSimulatedRpc.java    |   25 -
 .../ratis/server/storage/TestRaftStorage.java      |  279 ---
 .../ratis/statemachine/TestStateMachine.java       |  199 --
 .../apache/ratis/util/TestDataBlockingQueue.java   |  118 --
 .../java/org/apache/ratis/util/TestDataQueue.java  |  229 ---
 .../java/org/apache/ratis/util/TestExitUtils.java  |   59 -
 .../java/org/apache/ratis/util/TestLifeCycle.java  |   53 -
 .../java/org/apache/ratis/util/TestMinMax.java     |   57 -
 .../org/apache/ratis/util/TestPeerProxyMap.java    |   80 -
 .../org/apache/ratis/util/TestPreconditions.java   |   53 -
 .../apache/ratis/util/TestResourceSemaphore.java   |  105 --
 .../org/apache/ratis/util/TestTimeDuration.java    |  264 ---
 .../apache/ratis/util/TestTimeoutScheduler.java    |  242 ---
 .../ratis/util/TestTraditionalBinaryPrefix.java    |  145 --
 ratis-test/src/test/resources/log4j.properties     |   18 -
 .../org.mockito.plugins.MockMaker                  |   13 -
 ratis-tools/pom.xml                                |   40 -
 .../org/apache/ratis/tools/DefaultLogDump.java     |   42 -
 .../java/org/apache/ratis/tools/ParseRatisLog.java |  104 --
 618 files changed, 48 insertions(+), 76923 deletions(-)

diff --git a/.github/workflows/post-commit.yml b/.github/workflows/post-commit.yml
index 7aee48a..70d124a 100644
--- a/.github/workflows/post-commit.yml
+++ b/.github/workflows/post-commit.yml
@@ -83,9 +83,7 @@ jobs:
     strategy:
       matrix:
         profile:
-          - grpc
-          - server
-          - misc
+          - logservice
       fail-fast: ${{ github.event_name == 'pull_request' }}
     steps:
         # TEMPORARY WHILE GITHUB FIXES https://github.com/actions/virtual-environments/issues/3185
diff --git a/pom.xml b/pom.xml
index 8c4bada..9d45f9f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,25 +69,10 @@
   </licenses>
 
   <modules>
-    <module>ratis-docs</module>
     <module>ratis-proto</module>
-    <module>ratis-common</module>
-    <module>ratis-client</module>
-    <module>ratis-server-api</module>
-    <module>ratis-server</module>
     <module>ratis-resource-bundle</module>
-    <module>ratis-grpc</module>
-    <module>ratis-netty</module>
     <module>ratis-hadoop</module>
-
-    <module>ratis-test</module>
-
-    <module>ratis-examples</module>
-    <module>ratis-replicated-map</module>
     <module>ratis-logservice</module>
-    <module>ratis-metrics</module>
-    <module>ratis-tools</module>
-    <module>ratis-shell</module>
     <module>ratis-assembly</module>
   </modules>
 
@@ -99,9 +84,9 @@
   </pluginRepositories>
 
   <scm>
-    <connection>scm:git:git://git.apache.org/ratis.git</connection>
-    <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/ratis.git</developerConnection>
-    <url>https://git-wip-us.apache.org/repos/asf?p=ratis.git</url>
+    <connection>scm:git:git://git.apache.org/ratis-hadoop-projects.git</connection>
+    <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/ratis-hadoop-projects.git</developerConnection>
+    <url>https://git-wip-us.apache.org/repos/asf?p=ratis-hadoop-projects.git</url>
     <tag>HEAD</tag>
   </scm>
 
@@ -198,6 +183,7 @@
 
     <shell-executable>bash</shell-executable>
 
+    <ratis.version>2.3.0-6fb2e54-SNAPSHOT</ratis.version>
     <hadoop.version>3.3.1</hadoop.version>
     <hadoop-maven-plugins.version>${hadoop.version}</hadoop-maven-plugins.version>
 
@@ -233,18 +219,18 @@
       <dependency>
         <artifactId>ratis-docs</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
 
       <dependency>
         <artifactId>ratis-client</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
       <dependency>
         <artifactId>ratis-client</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
         <type>test-jar</type>
         <scope>test</scope>
       </dependency>
@@ -252,12 +238,12 @@
       <dependency>
         <artifactId>ratis-common</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
       <dependency>
         <artifactId>ratis-common</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
         <type>test-jar</type>
         <scope>test</scope>
       </dependency>
@@ -265,70 +251,58 @@
       <dependency>
         <artifactId>ratis-examples</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
       <dependency>
         <artifactId>ratis-examples</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
         <type>test-jar</type>
         <scope>test</scope>
       </dependency>
       <dependency>
         <artifactId>ratis-experiments</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
       <dependency>
        <artifactId>ratis-metrics</artifactId>
        <groupId>org.apache.ratis</groupId>
-       <version>${project.version}</version>
+       <version>${ratis.version}</version>
       </dependency>
       <dependency>
        <artifactId>ratis-metrics</artifactId>
        <groupId>org.apache.ratis</groupId>
-       <version>${project.version}</version>
+       <version>${ratis.version}</version>
        <type>test-jar</type>
        <scope>test</scope>
       </dependency>
       <dependency>
         <artifactId>ratis-tools</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
       <dependency>
         <artifactId>ratis-tools</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
         <type>test-jar</type>
         <scope>test</scope>
       </dependency>
       <dependency>
         <artifactId>ratis-shell</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
       <dependency>
         <artifactId>ratis-grpc</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
       <dependency>
         <artifactId>ratis-grpc</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
-        <type>test-jar</type>
-        <scope>test</scope>
-      </dependency>
-      <dependency>
-        <artifactId>ratis-hadoop</artifactId>
-        <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
-      </dependency>
-      <dependency>
-        <artifactId>ratis-hadoop</artifactId>
-        <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
         <type>test-jar</type>
         <scope>test</scope>
       </dependency>
@@ -336,12 +310,12 @@
       <dependency>
         <artifactId>ratis-netty</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
       <dependency>
         <artifactId>ratis-netty</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
         <type>test-jar</type>
         <scope>test</scope>
       </dependency>
@@ -349,18 +323,18 @@
       <dependency>
         <artifactId>ratis-proto</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
 
       <dependency>
         <artifactId>ratis-replicated-map</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
       <dependency>
         <artifactId>ratis-replicated-map</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
         <type>test-jar</type>
         <scope>test</scope>
       </dependency>
@@ -368,18 +342,18 @@
       <dependency>
         <artifactId>ratis-server-api</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
 
       <dependency>
         <artifactId>ratis-server</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
       <dependency>
         <artifactId>ratis-server</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
         <type>test-jar</type>
         <scope>test</scope>
       </dependency>
@@ -387,11 +361,24 @@
       <dependency>
         <artifactId>ratis-test</artifactId>
         <groupId>org.apache.ratis</groupId>
-        <version>${project.version}</version>
+        <version>${ratis.version}</version>
       </dependency>
       <dependency>
         <artifactId>ratis-test</artifactId>
         <groupId>org.apache.ratis</groupId>
+        <version>${ratis.version}</version>
+        <type>test-jar</type>
+        <scope>test</scope>
+      </dependency>
+
+      <dependency>
+        <artifactId>ratis-hadoop</artifactId>
+        <groupId>org.apache.ratis</groupId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <artifactId>ratis-hadoop</artifactId>
+        <groupId>org.apache.ratis</groupId>
         <version>${project.version}</version>
         <type>test-jar</type>
         <scope>test</scope>
@@ -1050,7 +1037,7 @@
     </profile>
 
     <profile>
-      <id>grpc-tests</id>
+      <id>hadooprpc-tests</id>
       <build>
         <plugins>
           <plugin>
@@ -1058,7 +1045,7 @@
             <artifactId>maven-surefire-plugin</artifactId>
             <configuration>
               <includes>
-                <include>org.apache.ratis.grpc.**</include>
+                <include>org.apache.ratis.hadooprpc.**</include>
               </includes>
             </configuration>
           </plugin>
@@ -1066,7 +1053,7 @@
       </build>
     </profile>
     <profile>
-      <id>server-tests</id>
+      <id>logservice-tests</id>
       <build>
         <plugins>
           <plugin>
@@ -1074,8 +1061,7 @@
             <artifactId>maven-surefire-plugin</artifactId>
             <configuration>
               <includes>
-                <include>org.apache.ratis.datastream.**</include>
-                <include>org.apache.ratis.server.**</include>
+                <include>org.apache.ratis.logservice.**</include>
               </includes>
             </configuration>
           </plugin>
@@ -1091,9 +1077,8 @@
             <artifactId>maven-surefire-plugin</artifactId>
             <configuration>
               <excludes>
-                <exclude>org.apache.ratis.datastream.**</exclude>
-                <exclude>org.apache.ratis.grpc.**</exclude>
-                <exclude>org.apache.ratis.server.**</exclude>
+                <exclude>org.apache.ratis.logservice.**</exclude>
+                <exclude>org.apache.ratis.hadooprpc.**</exclude>
               </excludes>
             </configuration>
           </plugin>
diff --git a/ratis-client/pom.xml b/ratis-client/pom.xml
deleted file mode 100644
index ee45062..0000000
--- a/ratis-client/pom.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?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</artifactId>
-    <groupId>org.apache.ratis</groupId>
-    <version>2.3.0-SNAPSHOT</version>
-  </parent>
-
-  <artifactId>ratis-client</artifactId>
-  <name>Apache Ratis Client</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.ratis</groupId>
-      <artifactId>ratis-thirdparty-misc</artifactId>
-    </dependency>
-    <dependency>
-      <artifactId>ratis-proto</artifactId>
-      <groupId>org.apache.ratis</groupId>
-    </dependency>
-
-    <dependency>
-      <artifactId>ratis-common</artifactId>
-      <groupId>org.apache.ratis</groupId>
-    </dependency>
-    
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/AsyncRpcApi.java b/ratis-client/src/main/java/org/apache/ratis/client/AsyncRpcApi.java
deleted file mode 100644
index 68d536f..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/AsyncRpcApi.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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 org.apache.ratis.client.api.AsyncApi;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftClientRequest;
-
-import java.util.concurrent.CompletableFuture;
-
-/** An RPC interface which extends the user interface {@link AsyncApi}. */
-public interface AsyncRpcApi extends AsyncApi {
-  /**
-   * Send the given RaftClientRequest asynchronously to the raft service.
-   * The RaftClientRequest will wrapped as Message in a new RaftClientRequest
-   * and leader will be decode it from the Message
-   * @param request The RaftClientRequest.
-   * @return a future of the reply.
-   */
-  CompletableFuture<RaftClientReply> sendForward(RaftClientRequest request);
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/ClientFactory.java b/ratis-client/src/main/java/org/apache/ratis/client/ClientFactory.java
deleted file mode 100644
index 08f98f6..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/ClientFactory.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * 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 org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.protocol.ClientId;
-import org.apache.ratis.rpc.RpcFactory;
-
-/** A factory interface for creating client components. */
-public interface ClientFactory extends RpcFactory {
-  static ClientFactory cast(RpcFactory rpcFactory) {
-    if (rpcFactory instanceof ClientFactory) {
-      return (ClientFactory)rpcFactory;
-    }
-    throw new ClassCastException("Cannot cast " + rpcFactory.getClass()
-        + " to " + ClientFactory.class
-        + "; rpc type is " + rpcFactory.getRpcType());
-  }
-
-  /** Create a {@link RaftClientRpc}. */
-  RaftClientRpc newRaftClientRpc(ClientId clientId, RaftProperties properties);
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/DataStreamClient.java b/ratis-client/src/main/java/org/apache/ratis/client/DataStreamClient.java
deleted file mode 100644
index b00f182..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/DataStreamClient.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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 org.apache.ratis.RaftConfigKeys;
-import org.apache.ratis.client.impl.ClientImplUtils;
-import org.apache.ratis.conf.Parameters;
-import org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.datastream.SupportedDataStreamType;
-import org.apache.ratis.protocol.ClientId;
-import org.apache.ratis.protocol.RaftGroupId;
-import org.apache.ratis.protocol.RaftPeer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.Closeable;
-import java.util.Objects;
-import java.util.Optional;
-
-/**
- * A user interface extending {@link DataStreamRpcApi}.
- */
-public interface DataStreamClient extends DataStreamRpcApi, Closeable {
-  Logger LOG = LoggerFactory.getLogger(DataStreamClient.class);
-
-  /** Return the rpc client instance **/
-  DataStreamClientRpc getClientRpc();
-
-  static Builder newBuilder() {
-    return new Builder();
-  }
-
-  /** To build {@link DataStreamClient} objects */
-  class Builder {
-    private RaftPeer dataStreamServer;
-    private DataStreamClientRpc dataStreamClientRpc;
-    private RaftProperties properties;
-    private Parameters parameters;
-    private RaftGroupId raftGroupId;
-    private ClientId clientId;
-
-    private Builder() {}
-
-    public DataStreamClient build() {
-      Objects.requireNonNull(dataStreamServer, "The 'dataStreamServer' field is not initialized.");
-      if (properties != null) {
-        if (dataStreamClientRpc == null) {
-          final SupportedDataStreamType type = RaftConfigKeys.DataStream.type(properties, LOG::info);
-          dataStreamClientRpc = DataStreamClientFactory.newInstance(type, parameters)
-              .newDataStreamClientRpc(dataStreamServer, properties);
-        }
-      }
-      return ClientImplUtils.newDataStreamClient(
-          Optional.ofNullable(clientId).orElseGet(ClientId::randomId),
-          raftGroupId, dataStreamServer, dataStreamClientRpc, properties);
-    }
-
-    public Builder setClientId(ClientId clientId) {
-      this.clientId = clientId;
-      return this;
-    }
-
-    public Builder setRaftGroupId(RaftGroupId raftGroupId) {
-      this.raftGroupId = raftGroupId;
-      return this;
-    }
-
-    public Builder setDataStreamServer(RaftPeer dataStreamServer) {
-      this.dataStreamServer = dataStreamServer;
-      return this;
-    }
-
-    public Builder setDataStreamClientRpc(DataStreamClientRpc dataStreamClientRpc) {
-      this.dataStreamClientRpc = dataStreamClientRpc;
-      return this;
-    }
-
-    public Builder setParameters(Parameters parameters) {
-      this.parameters = parameters;
-      return this;
-    }
-
-    public Builder setProperties(RaftProperties properties) {
-      this.properties = properties;
-      return this;
-    }
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/DataStreamClientFactory.java b/ratis-client/src/main/java/org/apache/ratis/client/DataStreamClientFactory.java
deleted file mode 100644
index 1e1ea3b..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/DataStreamClientFactory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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 org.apache.ratis.conf.Parameters;
-import org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.datastream.DataStreamFactory;
-import org.apache.ratis.datastream.DataStreamType;
-import org.apache.ratis.protocol.RaftPeer;
-
-/**
- * A factory to create streaming client.
- */
-public interface DataStreamClientFactory extends DataStreamFactory {
-  static DataStreamClientFactory newInstance(DataStreamType type, Parameters parameters) {
-    final DataStreamFactory dataStreamFactory = type.newClientFactory(parameters);
-    if (dataStreamFactory instanceof DataStreamClientFactory) {
-      return (DataStreamClientFactory) dataStreamFactory;
-    }
-    throw new ClassCastException("Cannot cast " + dataStreamFactory.getClass()
-        + " to " + DataStreamClientFactory.class + "; stream type is " + type);
-  }
-
-  DataStreamClientRpc newDataStreamClientRpc(RaftPeer server, RaftProperties properties);
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/DataStreamClientRpc.java b/ratis-client/src/main/java/org/apache/ratis/client/DataStreamClientRpc.java
deleted file mode 100644
index a9bcd9d..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/DataStreamClientRpc.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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 org.apache.ratis.protocol.DataStreamReply;
-import org.apache.ratis.protocol.DataStreamRequest;
-import org.apache.ratis.util.JavaUtils;
-
-import java.io.Closeable;
-import java.util.concurrent.CompletableFuture;
-
-/**
- * A client interface for sending stream requests.
- * The underlying implementation is pluggable, depending on the {@link org.apache.ratis.datastream.DataStreamType}.
- * The implementations of this interface define how the requests are transported to the server.
- */
-public interface DataStreamClientRpc extends Closeable {
-  /** Async call to send a request. */
-  default CompletableFuture<DataStreamReply> streamAsync(DataStreamRequest request) {
-    throw new UnsupportedOperationException(getClass() + " does not support "
-        + JavaUtils.getCurrentStackTraceElement().getMethodName());
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/DataStreamOutputRpc.java b/ratis-client/src/main/java/org/apache/ratis/client/DataStreamOutputRpc.java
deleted file mode 100644
index 53e002a..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/DataStreamOutputRpc.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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 org.apache.ratis.client.api.DataStreamOutput;
-import org.apache.ratis.protocol.DataStreamReply;
-
-import java.util.concurrent.CompletableFuture;
-
-/** An RPC interface which extends the user interface {@link DataStreamOutput}. */
-public interface DataStreamOutputRpc extends DataStreamOutput {
-  /** Get the future of the header request. */
-  CompletableFuture<DataStreamReply> getHeaderFuture();
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/DataStreamRpcApi.java b/ratis-client/src/main/java/org/apache/ratis/client/DataStreamRpcApi.java
deleted file mode 100644
index b7b5e3e..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/DataStreamRpcApi.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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 org.apache.ratis.client.api.DataStreamApi;
-import org.apache.ratis.client.api.DataStreamOutput;
-import org.apache.ratis.protocol.RaftClientRequest;
-
-/** An RPC interface which extends the user interface {@link DataStreamApi}. */
-public interface DataStreamRpcApi extends DataStreamApi {
-  /** Create a stream for primary server to send data to peer server. */
-  DataStreamOutput stream(RaftClientRequest request);
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/DisabledDataStreamClientFactory.java b/ratis-client/src/main/java/org/apache/ratis/client/DisabledDataStreamClientFactory.java
deleted file mode 100644
index 7150228..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/DisabledDataStreamClientFactory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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 org.apache.ratis.conf.Parameters;
-import org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.datastream.SupportedDataStreamType;
-import org.apache.ratis.protocol.RaftPeer;
-
-/** A stream factory that does nothing when data stream is disabled. */
-public class DisabledDataStreamClientFactory implements DataStreamClientFactory {
-  public DisabledDataStreamClientFactory(Parameters parameters) {}
-
-  @Override
-  public SupportedDataStreamType getDataStreamType() {
-    return SupportedDataStreamType.DISABLED;
-  }
-
-  @Override
-  public DataStreamClientRpc newDataStreamClientRpc(RaftPeer server, RaftProperties properties) {
-    return new DataStreamClientRpc() {
-      @Override
-      public void close() {}
-    };
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/RaftClient.java b/ratis-client/src/main/java/org/apache/ratis/client/RaftClient.java
deleted file mode 100644
index 30e2879..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/RaftClient.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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 org.apache.ratis.RaftConfigKeys;
-import org.apache.ratis.client.api.AdminApi;
-import org.apache.ratis.client.api.AsyncApi;
-import org.apache.ratis.client.api.BlockingApi;
-import org.apache.ratis.client.api.DataStreamApi;
-import org.apache.ratis.client.api.GroupManagementApi;
-import org.apache.ratis.client.api.MessageStreamApi;
-import org.apache.ratis.client.api.SnapshotManagementApi;
-import org.apache.ratis.client.impl.ClientImplUtils;
-import org.apache.ratis.conf.Parameters;
-import org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.protocol.*;
-import org.apache.ratis.retry.RetryPolicies;
-import org.apache.ratis.retry.RetryPolicy;
-import org.apache.ratis.rpc.RpcType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.Closeable;
-import java.util.Collection;
-import java.util.Objects;
-
-/** A client who sends requests to a raft service. */
-public interface RaftClient extends Closeable {
-  Logger LOG = LoggerFactory.getLogger(RaftClient.class);
-
-  /** @return the id of this client. */
-  ClientId getId();
-
-  /** @return the cluster leaderId recorded by this client. */
-  RaftPeerId getLeaderId();
-
-  /** @return the {@link RaftClientRpc}. */
-  RaftClientRpc getClientRpc();
-
-  /** @return the {@link AdminApi}. */
-  AdminApi admin();
-
-  /** Get the {@link GroupManagementApi} for the given server. */
-  GroupManagementApi getGroupManagementApi(RaftPeerId server);
-
-  /** Get the {@link SnapshotManagementApi} for the given server. */
-  SnapshotManagementApi getSnapshotManagementApi();
-
-  /** Get the {@link SnapshotManagementApi} for the given server. */
-  SnapshotManagementApi getSnapshotManagementApi(RaftPeerId server);
-
-  /** @return the {@link BlockingApi}. */
-  BlockingApi io();
-
-  /** Get the {@link AsyncApi}. */
-  AsyncApi async();
-
-  /** @return the {@link MessageStreamApi}. */
-  MessageStreamApi getMessageStreamApi();
-
-  /** @return the {@link DataStreamApi}. */
-  DataStreamApi getDataStreamApi();
-
-  /** @return a {@link Builder}. */
-  static Builder newBuilder() {
-    return new Builder();
-  }
-
-  /** To build {@link RaftClient} objects. */
-  class Builder {
-    private ClientId clientId;
-    private RaftClientRpc clientRpc;
-    private RaftGroup group;
-    private RaftPeerId leaderId;
-    private RaftPeer primaryDataStreamServer;
-    private RaftProperties properties;
-    private Parameters parameters;
-    private RetryPolicy retryPolicy = RetryPolicies.retryForeverNoSleep();
-
-    private Builder() {}
-
-    /** @return a {@link RaftClient} object. */
-    public RaftClient build() {
-      if (clientId == null) {
-        clientId = ClientId.randomId();
-      }
-      if (properties != null) {
-        if (clientRpc == null) {
-          final RpcType rpcType = RaftConfigKeys.Rpc.type(properties, LOG::debug);
-          final ClientFactory factory = ClientFactory.cast(rpcType.newFactory(parameters));
-          clientRpc = factory.newRaftClientRpc(clientId, properties);
-        }
-      }
-      Objects.requireNonNull(group, "The 'group' field is not initialized.");
-      if (primaryDataStreamServer == null) {
-        final Collection<RaftPeer> peers = group.getPeers();
-        if (!peers.isEmpty()) {
-          primaryDataStreamServer = peers.iterator().next();
-        }
-      }
-      return ClientImplUtils.newRaftClient(clientId, group, leaderId, primaryDataStreamServer,
-          Objects.requireNonNull(clientRpc, "The 'clientRpc' field is not initialized."),
-          properties, retryPolicy);
-    }
-
-    /** Set {@link RaftClient} ID. */
-    public Builder setClientId(ClientId clientId) {
-      this.clientId = clientId;
-      return this;
-    }
-
-    /** Set servers. */
-    public Builder setRaftGroup(RaftGroup grp) {
-      this.group = grp;
-      return this;
-    }
-
-    /** Set leader ID. */
-    public Builder setLeaderId(RaftPeerId leaderId) {
-      this.leaderId = leaderId;
-      return this;
-    }
-
-    /** Set primary server of DataStream. */
-    public Builder setPrimaryDataStreamServer(RaftPeer primaryDataStreamServer) {
-      this.primaryDataStreamServer = primaryDataStreamServer;
-      return this;
-    }
-
-    /** Set {@link RaftClientRpc}. */
-    public Builder setClientRpc(RaftClientRpc clientRpc) {
-      this.clientRpc = clientRpc;
-      return this;
-    }
-
-    /** Set {@link RaftProperties}. */
-    public Builder setProperties(RaftProperties properties) {
-      this.properties = properties;
-      return this;
-    }
-
-    /** Set {@link Parameters}. */
-    public Builder setParameters(Parameters parameters) {
-      this.parameters = parameters;
-      return this;
-    }
-
-    /** Set {@link RetryPolicy}. */
-    public Builder setRetryPolicy(RetryPolicy retryPolicy) {
-      this.retryPolicy = retryPolicy;
-      return this;
-    }
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/RaftClientConfigKeys.java b/ratis-client/src/main/java/org/apache/ratis/client/RaftClientConfigKeys.java
deleted file mode 100644
index c8388bb..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/RaftClientConfigKeys.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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 org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.util.JavaUtils;
-import org.apache.ratis.util.SizeInBytes;
-import org.apache.ratis.util.TimeDuration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
-
-import static org.apache.ratis.conf.ConfUtils.*;
-
-public interface RaftClientConfigKeys {
-  Logger LOG = LoggerFactory.getLogger(RaftClientConfigKeys.class);
-
-  static Consumer<String> getDefaultLog() {
-    return LOG::debug;
-  }
-
-  String PREFIX = "raft.client";
-
-  interface Rpc {
-    String PREFIX = RaftClientConfigKeys.PREFIX + ".rpc";
-
-    String REQUEST_TIMEOUT_KEY = PREFIX + ".request.timeout";
-    TimeDuration REQUEST_TIMEOUT_DEFAULT = TimeDuration.valueOf(3000, TimeUnit.MILLISECONDS);
-    static TimeDuration requestTimeout(RaftProperties properties) {
-      return getTimeDuration(properties.getTimeDuration(REQUEST_TIMEOUT_DEFAULT.getUnit()),
-          REQUEST_TIMEOUT_KEY, REQUEST_TIMEOUT_DEFAULT, getDefaultLog());
-    }
-    static void setRequestTimeout(RaftProperties properties, TimeDuration timeoutDuration) {
-      setTimeDuration(properties::setTimeDuration, REQUEST_TIMEOUT_KEY, timeoutDuration);
-    }
-
-    String WATCH_REQUEST_TIMEOUT_KEY = PREFIX + ".watch.request.timeout";
-    TimeDuration WATCH_REQUEST_TIMEOUT_DEFAULT =
-        TimeDuration.valueOf(10000, TimeUnit.MILLISECONDS);
-    static TimeDuration watchRequestTimeout(RaftProperties properties) {
-      return getTimeDuration(properties.getTimeDuration(WATCH_REQUEST_TIMEOUT_DEFAULT.getUnit()),
-          WATCH_REQUEST_TIMEOUT_KEY, WATCH_REQUEST_TIMEOUT_DEFAULT, getDefaultLog());
-    }
-    static void setWatchRequestTimeout(RaftProperties properties,
-        TimeDuration timeoutDuration) {
-      setTimeDuration(properties::setTimeDuration, WATCH_REQUEST_TIMEOUT_KEY, timeoutDuration);
-    }
-  }
-
-  interface Async {
-    String PREFIX = RaftClientConfigKeys.PREFIX + ".async";
-
-    String OUTSTANDING_REQUESTS_MAX_KEY = PREFIX + ".outstanding-requests.max";
-    int OUTSTANDING_REQUESTS_MAX_DEFAULT = 100;
-    static int outstandingRequestsMax(RaftProperties properties) {
-      return getInt(properties::getInt, OUTSTANDING_REQUESTS_MAX_KEY,
-          OUTSTANDING_REQUESTS_MAX_DEFAULT, getDefaultLog(), requireMin(2));
-    }
-    static void setOutstandingRequestsMax(RaftProperties properties, int outstandingRequests) {
-      setInt(properties::setInt, OUTSTANDING_REQUESTS_MAX_KEY, outstandingRequests);
-    }
-
-    interface Experimental {
-      String PREFIX = Async.PREFIX + "." + JavaUtils.getClassSimpleName(Experimental.class).toLowerCase();
-
-      String SEND_DUMMY_REQUEST_KEY = PREFIX + ".send-dummy-request";
-      boolean SEND_DUMMY_REQUEST_DEFAULT = true;
-      static boolean sendDummyRequest(RaftProperties properties) {
-        return getBoolean(properties::getBoolean, SEND_DUMMY_REQUEST_KEY, SEND_DUMMY_REQUEST_DEFAULT, getDefaultLog());
-      }
-      static void setSendDummyRequest(RaftProperties properties, boolean sendDummyRequest) {
-        setBoolean(properties::setBoolean, SEND_DUMMY_REQUEST_KEY, sendDummyRequest);
-      }
-    }
-  }
-
-  interface DataStream {
-    String PREFIX = RaftClientConfigKeys.PREFIX + ".data-stream";
-
-    String OUTSTANDING_REQUESTS_MAX_KEY = PREFIX + ".outstanding-requests.max";
-    int OUTSTANDING_REQUESTS_MAX_DEFAULT = 10;
-    static int outstandingRequestsMax(RaftProperties properties) {
-      return getInt(properties::getInt, OUTSTANDING_REQUESTS_MAX_KEY,
-          OUTSTANDING_REQUESTS_MAX_DEFAULT, getDefaultLog(), requireMin(2));
-    }
-    static void setOutstandingRequestsMax(RaftProperties properties, int outstandingRequests) {
-      setInt(properties::setInt, OUTSTANDING_REQUESTS_MAX_KEY, outstandingRequests);
-    }
-
-    String REQUEST_TIMEOUT_KEY = PREFIX + ".request.timeout";
-    TimeDuration REQUEST_TIMEOUT_DEFAULT = TimeDuration.valueOf(3000, TimeUnit.MILLISECONDS);
-    static TimeDuration requestTimeout(RaftProperties properties) {
-      return getTimeDuration(properties.getTimeDuration(REQUEST_TIMEOUT_DEFAULT.getUnit()),
-          REQUEST_TIMEOUT_KEY, REQUEST_TIMEOUT_DEFAULT, getDefaultLog());
-    }
-    static void setRequestTimeout(RaftProperties properties, TimeDuration timeoutDuration) {
-      setTimeDuration(properties::setTimeDuration, REQUEST_TIMEOUT_KEY, timeoutDuration);
-    }
-  }
-
-  interface MessageStream {
-    String PREFIX = RaftClientConfigKeys.PREFIX + ".message-stream";
-
-    String SUBMESSAGE_SIZE_KEY = PREFIX + ".submessage-size";
-    SizeInBytes SUBMESSAGE_SIZE_DEFAULT = SizeInBytes.valueOf("1MB");
-    static SizeInBytes submessageSize(RaftProperties properties) {
-      return getSizeInBytes(properties::getSizeInBytes,
-          SUBMESSAGE_SIZE_KEY, SUBMESSAGE_SIZE_DEFAULT, getDefaultLog());
-    }
-    static void setSubmessageSize(RaftProperties properties, SizeInBytes submessageSize) {
-      setSizeInBytes(properties::set, SUBMESSAGE_SIZE_KEY, submessageSize, requireMin(SizeInBytes.ONE_KB));
-    }
-    static void setSubmessageSize(RaftProperties properties) {
-      setSubmessageSize(properties, SUBMESSAGE_SIZE_DEFAULT);
-    }
-  }
-
-  static void main(String[] args) {
-    printAll(RaftClientConfigKeys.class);
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/RaftClientRpc.java b/ratis-client/src/main/java/org/apache/ratis/client/RaftClientRpc.java
deleted file mode 100644
index 9034829..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/RaftClientRpc.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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 org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftClientRequest;
-import org.apache.ratis.protocol.RaftPeer;
-import org.apache.ratis.protocol.RaftPeerId;
-import org.apache.ratis.util.IOUtils;
-import org.apache.ratis.util.JavaUtils;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.concurrent.CompletableFuture;
-
-/** The client side rpc of a raft service. */
-public interface RaftClientRpc extends RaftPeer.Add, Closeable {
-  /** Async call to send a request. */
-  default CompletableFuture<RaftClientReply> sendRequestAsync(RaftClientRequest request) {
-    throw new UnsupportedOperationException(getClass() + " does not support this method.");
-  }
-
-  /** Async call to send a request. */
-  default CompletableFuture<RaftClientReply> sendRequestAsyncUnordered(RaftClientRequest request) {
-    throw new UnsupportedOperationException(getClass() + " does not support "
-        + JavaUtils.getCurrentStackTraceElement().getMethodName());
-  }
-
-  /** Send a request. */
-  RaftClientReply sendRequest(RaftClientRequest request) throws IOException;
-
-  /**
-   * Handle the given throwable. For example, try reconnecting.
-   *
-   * @return true if the given throwable is handled; otherwise, the call is an no-op, return false.
-   */
-  default boolean handleException(RaftPeerId serverId, Throwable t, boolean reconnect) {
-    return false;
-  }
-
-  /**
-   * Determine if the given throwable should be handled. For example, try reconnecting.
-   *
-   * @return true if the given throwable should be handled; otherwise, return false.
-   */
-  default boolean shouldReconnect(Throwable t) {
-    return IOUtils.shouldReconnect(t);
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/api/AdminApi.java b/ratis-client/src/main/java/org/apache/ratis/client/api/AdminApi.java
deleted file mode 100644
index 175fd95..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/api/AdminApi.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.api;
-
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftPeer;
-import org.apache.ratis.protocol.RaftPeerId;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * An API to support administration
- * such as setting raft configuration and transferring leadership.
- */
-public interface AdminApi {
-  /** Set the configuration request to the raft service. */
-  RaftClientReply setConfiguration(List<RaftPeer> serversInNewConf) throws IOException;
-
-  /** The same as setConfiguration(Arrays.asList(serversInNewConf)). */
-  default RaftClientReply setConfiguration(RaftPeer[] serversInNewConf) throws IOException {
-    return setConfiguration(Arrays.asList(serversInNewConf));
-  }
-
-  /** Transfer leadership to the given server.*/
-  RaftClientReply transferLeadership(RaftPeerId newLeader, long timeoutMs) throws IOException;
-}
\ No newline at end of file
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/api/AsyncApi.java b/ratis-client/src/main/java/org/apache/ratis/client/api/AsyncApi.java
deleted file mode 100644
index fd000ad..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/api/AsyncApi.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.api;
-
-import java.util.concurrent.CompletableFuture;
-import org.apache.ratis.proto.RaftProtos.ReplicationLevel;
-import org.apache.ratis.protocol.Message;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftPeerId;
-
-/**
- * Asynchronous API to support operations
- * such as sending message, read-message, stale-read-message and watch-request.
- *
- * Note that this API and {@link BlockingApi} support the same set of operations.
- */
-public interface AsyncApi {
-  /**
-   * Send the given message asynchronously to the raft service.
-   * The message may change the state of the service.
-   * For readonly messages, use {@link #sendReadOnly(Message)} instead.
-   *
-   * @param message The request message.
-   * @return a future of the reply.
-   */
-  CompletableFuture<RaftClientReply> send(Message message);
-
-  /**
-   * Send the given readonly message asynchronously to the raft service.
-   *
-   * @param message The request message.
-   * @return a future of the reply.
-   */
-  CompletableFuture<RaftClientReply> sendReadOnly(Message message);
-
-  /**
-   * Send the given stale-read message asynchronously to the given server (not the raft service).
-   * If the server commit index is larger than or equal to the given min-index, the request will be processed.
-   * Otherwise, the server returns a {@link org.apache.ratis.protocol.exceptions.StaleReadException}.
-   *
-   * @param message The request message.
-   * @param minIndex The minimum log index that the server log must have already committed.
-   * @param server The target server
-   * @return a future of the reply.
-   */
-  CompletableFuture<RaftClientReply> sendStaleRead(Message message, long minIndex, RaftPeerId server);
-
-  /**
-   * Watch the given index asynchronously to satisfy the given replication level.
-   *
-   * @param index The log index to be watched.
-   * @param replication The replication level required.
-   * @return a future of the reply.
-   */
-  CompletableFuture<RaftClientReply> watch(long index, ReplicationLevel replication);
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/api/BlockingApi.java b/ratis-client/src/main/java/org/apache/ratis/client/api/BlockingApi.java
deleted file mode 100644
index e1679b9..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/api/BlockingApi.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.api;
-
-import java.io.IOException;
-import org.apache.ratis.proto.RaftProtos.ReplicationLevel;
-import org.apache.ratis.protocol.Message;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftPeerId;
-
-/**
- * Blocking API to support operations
- * such as sending message, read-message, stale-read-message and watch-request.
- *
- * Note that this API and {@link AsyncApi} support the same set of operations.
- */
-public interface BlockingApi {
-  /**
-   * Send the given message to the raft service.
-   * The message may change the state of the service.
-   * For readonly messages, use {@link #sendReadOnly(Message)} instead.
-   *
-   * @param message The request message.
-   * @return the reply.
-   */
-  RaftClientReply send(Message message) throws IOException;
-
-  /**
-   * Send the given readonly message to the raft service.
-   *
-   * @param message The request message.
-   * @return the reply.
-   */
-  RaftClientReply sendReadOnly(Message message) throws IOException;
-
-  /**
-   * Send the given stale-read message to the given server (not the raft service).
-   * If the server commit index is larger than or equal to the given min-index, the request will be processed.
-   * Otherwise, the server throws a {@link org.apache.ratis.protocol.exceptions.StaleReadException}.
-   *
-   * @param message The request message.
-   * @param minIndex The minimum log index that the server log must have already committed.
-   * @param server The target server
-   * @return the reply.
-   */
-  RaftClientReply sendStaleRead(Message message, long minIndex, RaftPeerId server) throws IOException;
-
-  /**
-   * Watch the given index to satisfy the given replication level.
-   *
-   * @param index The log index to be watched.
-   * @param replication The replication level required.
-   * @return the reply.
-   */
-  RaftClientReply watch(long index, ReplicationLevel replication) throws IOException;
-}
\ No newline at end of file
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/api/DataStreamApi.java b/ratis-client/src/main/java/org/apache/ratis/client/api/DataStreamApi.java
deleted file mode 100644
index 9e5e243..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/api/DataStreamApi.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.api;
-
-import org.apache.ratis.protocol.RoutingTable;
-
-import java.io.Closeable;
-import java.nio.ByteBuffer;
-
-/**
- * Stream data asynchronously to all the servers in the {@link org.apache.ratis.protocol.RaftGroup}.
- * Clients may stream data to the nearest server and then the server will forward the data to the other servers.
- * Once all the servers have received all the data of a request,
- * the leader (may or may not be the nearest server) creates a log entry with a data ID generated by the state machine.
- * Then, the leader sends the log entry to the followers.
- * Since the followers already have received the data from the stream,
- * they may lookup the data from the ID.
- *
- * Since this API allows clients to send data to the nearest server which is not necessarily the leader,
- * this API is more efficient for network-topology-aware clusters
- * than the other APIs that require clients to send data/messages to the leader.
- *
- * Note that this API is different from {@link MessageStreamApi} in the sense that
- * this API streams data to all the servers in the {@link org.apache.ratis.protocol.RaftGroup}
- * but {@link MessageStreamApi} streams messages only to the leader.
- */
-public interface DataStreamApi extends Closeable {
-  /** Create a stream to write data. */
-  default DataStreamOutput stream() {
-    return stream(null);
-  }
-
-  /** Create a stream by providing a customized header message. */
-  DataStreamOutput stream(ByteBuffer headerMessage);
-
-  /** Create a stream by providing a customized header message and route table. */
-  DataStreamOutput stream(ByteBuffer headerMessage, RoutingTable routingTable);
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/api/DataStreamOutput.java b/ratis-client/src/main/java/org/apache/ratis/client/api/DataStreamOutput.java
deleted file mode 100644
index be6d13e..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/api/DataStreamOutput.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.api;
-
-import org.apache.ratis.io.CloseAsync;
-import org.apache.ratis.io.FilePositionCount;
-import org.apache.ratis.io.WriteOption;
-import org.apache.ratis.protocol.DataStreamReply;
-import org.apache.ratis.protocol.RaftClientReply;
-
-import java.io.File;
-import java.nio.ByteBuffer;
-import java.nio.channels.WritableByteChannel;
-import java.util.concurrent.CompletableFuture;
-
-/** An asynchronous output stream supporting zero buffer copying. */
-public interface DataStreamOutput extends CloseAsync<DataStreamReply> {
-  /**
-   * Send out the data in the source buffer asynchronously.
-   *
-   * @param src the source buffer to be sent.
-   * @param options - options specifying how the data was written
-   * @return a future of the reply.
-   */
-  CompletableFuture<DataStreamReply> writeAsync(ByteBuffer src, WriteOption... options);
-
-
-  /**
-   * The same as writeAsync(src, 0, src.length(), sync_default).
-   * where sync_default depends on the underlying implementation.
-   */
-  default CompletableFuture<DataStreamReply> writeAsync(File src) {
-    return writeAsync(src, 0, src.length());
-  }
-
-  /**
-   * The same as writeAsync(FilePositionCount.valueOf(src, position, count), options).
-   */
-  default CompletableFuture<DataStreamReply> writeAsync(File src, long position, long count, WriteOption... options) {
-    return writeAsync(FilePositionCount.valueOf(src, position, count), options);
-  }
-
-  /**
-   * Send out the data in the source file asynchronously.
-   *
-   * @param src the source file with the starting position and the number of bytes.
-   * @param options options specifying how the data was written
-   * @return a future of the reply.
-   */
-  CompletableFuture<DataStreamReply> writeAsync(FilePositionCount src, WriteOption... options);
-
-  /**
-   * Return the future of the {@link RaftClientReply}
-   * which will be received once this stream has been closed successfully.
-   * Note that this method does not trigger closing this stream.
-   *
-   * @return the future of the {@link RaftClientReply}.
-   */
-  CompletableFuture<RaftClientReply> getRaftClientReplyFuture();
-
-  /**
-   * @return a {@link WritableByteChannel} view of this {@link DataStreamOutput}.
-   */
-  WritableByteChannel getWritableByteChannel();
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/api/GroupManagementApi.java b/ratis-client/src/main/java/org/apache/ratis/client/api/GroupManagementApi.java
deleted file mode 100644
index 1d3bc00..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/api/GroupManagementApi.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.api;
-
-import org.apache.ratis.protocol.GroupInfoReply;
-import org.apache.ratis.protocol.GroupListReply;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftGroup;
-import org.apache.ratis.protocol.RaftGroupId;
-
-import java.io.IOException;
-
-/**
- * APIs to support group management operations such as add, remove, list and info to a particular server.
- */
-public interface GroupManagementApi {
-  /** Add a new group. */
-  RaftClientReply add(RaftGroup newGroup) throws IOException;
-
-  /** Remove a group. */
-  RaftClientReply remove(RaftGroupId groupId, boolean deleteDirectory, boolean renameDirectory) throws IOException;
-
-  /** List all the groups.*/
-  GroupListReply list() throws IOException;
-
-  /** Get the info of the given group.*/
-  GroupInfoReply info(RaftGroupId group) throws IOException;
-}
\ No newline at end of file
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/api/MessageOutputStream.java b/ratis-client/src/main/java/org/apache/ratis/client/api/MessageOutputStream.java
deleted file mode 100644
index 358ad28..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/api/MessageOutputStream.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.api;
-
-import org.apache.ratis.io.CloseAsync;
-import org.apache.ratis.protocol.Message;
-import org.apache.ratis.protocol.RaftClientReply;
-
-import java.util.concurrent.CompletableFuture;
-
-/** Stream {@link Message}(s) asynchronously. */
-public interface MessageOutputStream extends CloseAsync<RaftClientReply> {
-  /**
-   * Send asynchronously the given message to this stream.
-   *
-   * If end-of-request is true, this message is the last message of the request.
-   * All the messages accumulated are considered as a single request.
-   *
-   * @param message the message to be sent.
-   * @param endOfRequest Is this an end-of-request?
-   * @return a future of the reply.
-   */
-  CompletableFuture<RaftClientReply> sendAsync(Message message, boolean endOfRequest);
-
-  /** The same as sendAsync(message, false). */
-  default CompletableFuture<RaftClientReply> sendAsync(Message message) {
-    return sendAsync(message, false);
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/api/MessageStreamApi.java b/ratis-client/src/main/java/org/apache/ratis/client/api/MessageStreamApi.java
deleted file mode 100644
index 9a816c8..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/api/MessageStreamApi.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.api;
-
-import org.apache.ratis.protocol.Message;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.util.SizeInBytes;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.CompletableFuture;
-
-/**
- * Stream (large) {@link Message}(s) asynchronously to the leader.
- * Once a stream has been closed or has been signaled an end-of-request,
- * the leader creates a raft log entry for the request
- * and then replicates the log entry to all the followers.
- *
- * Note that this API is similar to {@link AsyncApi#send(Message)}
- * except that {@link MessageStreamApi} divides a (large) message into multiple (small) sub-messages in the stream
- * but {@link AsyncApi#send(Message)} sends the entire message in a single RPC.
- * For sending large messages,
- * {@link MessageStreamApi} is more efficient than {@link AsyncApi#send(Message)}}.
- *
- * Note also that this API is different from {@link DataStreamApi} in the sense that
- * this API streams messages only to the leader
- * but {@link DataStreamApi} streams data to all the servers in the {@link org.apache.ratis.protocol.RaftGroup}.
- */
-public interface MessageStreamApi {
-  Logger LOG = LoggerFactory.getLogger(MessageStreamApi.class);
-
-  /** Create a stream to send a large message. */
-  MessageOutputStream stream();
-
-  /** Send the given (large) message using a stream with the submessage size. */
-  CompletableFuture<RaftClientReply> streamAsync(Message message, SizeInBytes submessageSize);
-
-  /** Send the given message using a stream with submessage size specified in conf. */
-  CompletableFuture<RaftClientReply> streamAsync(Message message);
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/api/SnapshotManagementApi.java b/ratis-client/src/main/java/org/apache/ratis/client/api/SnapshotManagementApi.java
deleted file mode 100644
index edd0475..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/api/SnapshotManagementApi.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.api;
-
-import org.apache.ratis.protocol.RaftClientReply;
-
-import java.io.IOException;
-
-/**
- * An API to support control snapshot
- * such as create and list snapshot file.
- */
-public interface SnapshotManagementApi {
-
-  /** trigger create snapshot file. */
-  RaftClientReply create(long timeoutMs) throws IOException;
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/AdminImpl.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/AdminImpl.java
deleted file mode 100644
index b2160b5..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/AdminImpl.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.client.api.AdminApi;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftPeer;
-import org.apache.ratis.protocol.RaftPeerId;
-import org.apache.ratis.protocol.SetConfigurationRequest;
-import org.apache.ratis.protocol.TransferLeadershipRequest;
-import org.apache.ratis.rpc.CallId;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Objects;
-
-class AdminImpl implements AdminApi {
-  private final RaftClientImpl client;
-
-  AdminImpl(RaftClientImpl client) {
-    this.client = Objects.requireNonNull(client, "client == null");
-  }
-
-  @Override
-  public RaftClientReply setConfiguration(List<RaftPeer> peersInNewConf) throws IOException {
-    Objects.requireNonNull(peersInNewConf, "peersInNewConf == null");
-
-    final long callId = CallId.getAndIncrement();
-    // also refresh the rpc proxies for these peers
-    client.getClientRpc().addRaftPeers(peersInNewConf);
-    return client.io().sendRequestWithRetry(() -> new SetConfigurationRequest(
-        client.getId(), client.getLeaderId(), client.getGroupId(), callId, peersInNewConf));
-  }
-
-  @Override
-  public RaftClientReply transferLeadership(RaftPeerId newLeader, long timeoutMs) throws IOException {
-    Objects.requireNonNull(newLeader, "newLeader == null");
-    final long callId = CallId.getAndIncrement();
-    return client.io().sendRequestWithRetry(() -> new TransferLeadershipRequest(
-        client.getId(), client.getLeaderId(), client.getGroupId(), callId, newLeader, timeoutMs));
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/AsyncImpl.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/AsyncImpl.java
deleted file mode 100644
index e063eeb..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/AsyncImpl.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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 java.util.Objects;
-import java.util.concurrent.CompletableFuture;
-
-import org.apache.ratis.client.AsyncRpcApi;
-import org.apache.ratis.proto.RaftProtos;
-import org.apache.ratis.proto.RaftProtos.ReplicationLevel;
-import org.apache.ratis.protocol.Message;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftClientRequest;
-import org.apache.ratis.protocol.RaftPeerId;
-
-/** Async api implementations. */
-class AsyncImpl implements AsyncRpcApi {
-  private final RaftClientImpl client;
-
-  AsyncImpl(RaftClientImpl client) {
-    this.client = Objects.requireNonNull(client, "client == null");
-  }
-
-  CompletableFuture<RaftClientReply> send(
-      RaftClientRequest.Type type, Message message, RaftPeerId server) {
-    return client.getOrderedAsync().send(type, message, server);
-  }
-
-  @Override
-  public CompletableFuture<RaftClientReply> send(Message message) {
-    return send(RaftClientRequest.writeRequestType(), message, null);
-  }
-
-  @Override
-  public CompletableFuture<RaftClientReply> sendReadOnly(Message message) {
-    return send(RaftClientRequest.readRequestType(), message, null);
-  }
-
-  @Override
-  public CompletableFuture<RaftClientReply> sendStaleRead(Message message, long minIndex, RaftPeerId server) {
-    return send(RaftClientRequest.staleReadRequestType(minIndex), message, server);
-  }
-
-  @Override
-  public CompletableFuture<RaftClientReply> watch(long index, ReplicationLevel replication) {
-    return UnorderedAsync.send(RaftClientRequest.watchRequestType(index, replication), client);
-  }
-
-  @Override
-  public CompletableFuture<RaftClientReply> sendForward(RaftClientRequest request) {
-    final RaftProtos.RaftClientRequestProto proto = ClientProtoUtils.toRaftClientRequestProto(request);
-    return send(RaftClientRequest.forwardRequestType(), Message.valueOf(proto.toByteString()), null);
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/BlockingImpl.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/BlockingImpl.java
deleted file mode 100644
index e234714..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/BlockingImpl.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * 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 java.io.IOException;
-import java.io.InterruptedIOException;
-import java.util.Objects;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-import org.apache.ratis.client.api.BlockingApi;
-import org.apache.ratis.client.retry.ClientRetryEvent;
-import org.apache.ratis.proto.RaftProtos.RaftClientRequestProto.TypeCase;
-import org.apache.ratis.proto.RaftProtos.ReplicationLevel;
-import org.apache.ratis.protocol.Message;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftClientRequest;
-import org.apache.ratis.protocol.RaftPeerId;
-import org.apache.ratis.protocol.exceptions.AlreadyClosedException;
-import org.apache.ratis.protocol.exceptions.AlreadyExistsException;
-import org.apache.ratis.protocol.exceptions.GroupMismatchException;
-import org.apache.ratis.protocol.exceptions.LeaderSteppingDownException;
-import org.apache.ratis.protocol.exceptions.StateMachineException;
-import org.apache.ratis.protocol.exceptions.TransferLeadershipException;
-import org.apache.ratis.retry.RetryPolicy;
-import org.apache.ratis.rpc.CallId;
-import org.apache.ratis.util.TimeDuration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/** Blocking api implementations. */
-class BlockingImpl implements BlockingApi {
-  static final Logger LOG = LoggerFactory.getLogger(BlockingImpl.class);
-
-  private final RaftClientImpl client;
-
-  BlockingImpl(RaftClientImpl client) {
-    this.client = Objects.requireNonNull(client, "client == null");
-  }
-
-  @Override
-  public RaftClientReply send(Message message) throws IOException {
-    return send(RaftClientRequest.writeRequestType(), message, null);
-  }
-
-  @Override
-  public RaftClientReply sendReadOnly(Message message) throws IOException {
-    return send(RaftClientRequest.readRequestType(), message, null);
-  }
-
-  @Override
-  public RaftClientReply sendStaleRead(Message message, long minIndex, RaftPeerId server)
-      throws IOException {
-    return send(RaftClientRequest.staleReadRequestType(minIndex), message, server);
-  }
-
-  @Override
-  public RaftClientReply watch(long index, ReplicationLevel replication) throws IOException {
-    return send(RaftClientRequest.watchRequestType(index, replication), null, null);
-  }
-
-  private RaftClientReply send(RaftClientRequest.Type type, Message message, RaftPeerId server)
-      throws IOException {
-    if (!type.is(TypeCase.WATCH)) {
-      Objects.requireNonNull(message, "message == null");
-    }
-
-    final long callId = CallId.getAndIncrement();
-    return sendRequestWithRetry(() -> client.newRaftClientRequest(server, callId, message, type, null));
-  }
-
-  RaftClientReply sendRequestWithRetry(Supplier<RaftClientRequest> supplier) throws IOException {
-    RaftClientImpl.PendingClientRequest pending = new RaftClientImpl.PendingClientRequest() {
-      @Override
-      public RaftClientRequest newRequestImpl() {
-        return supplier.get();
-      }
-    };
-    while (true) {
-      final RaftClientRequest request = pending.newRequest();
-      IOException ioe = null;
-      try {
-        final RaftClientReply reply = sendRequest(request);
-
-        if (reply != null) {
-          return client.handleReply(request, reply);
-        }
-      } catch (GroupMismatchException | StateMachineException | TransferLeadershipException |
-          LeaderSteppingDownException | AlreadyClosedException | AlreadyExistsException e) {
-        throw e;
-      } catch (IOException e) {
-        ioe = e;
-      }
-
-      pending.incrementExceptionCount(ioe);
-      ClientRetryEvent event = new ClientRetryEvent(request, ioe, pending);
-      final RetryPolicy retryPolicy = client.getRetryPolicy();
-      final RetryPolicy.Action action = retryPolicy.handleAttemptFailure(event);
-      TimeDuration sleepTime = client.getEffectiveSleepTime(ioe, action.getSleepTime());
-
-      if (!action.shouldRetry()) {
-        throw (IOException)client.noMoreRetries(event);
-      }
-
-      try {
-        sleepTime.sleep();
-      } catch (InterruptedException e) {
-        throw new InterruptedIOException("retry policy=" + retryPolicy);
-      }
-    }
-  }
-
-  private RaftClientReply sendRequest(RaftClientRequest request) throws IOException {
-    LOG.debug("{}: send {}", client.getId(), request);
-    RaftClientReply reply;
-    try {
-      reply = client.getClientRpc().sendRequest(request);
-    } catch (GroupMismatchException gme) {
-      throw gme;
-    } catch (IOException ioe) {
-      client.handleIOException(request, ioe);
-      throw ioe;
-    }
-    LOG.debug("{}: receive {}", client.getId(), reply);
-    reply = client.handleLeaderException(request, reply);
-    reply = RaftClientImpl.handleRaftException(reply, Function.identity());
-    return reply;
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientImplUtils.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientImplUtils.java
deleted file mode 100644
index eeddb22..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientImplUtils.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.client.DataStreamClient;
-import org.apache.ratis.client.DataStreamClientRpc;
-import org.apache.ratis.client.RaftClient;
-import org.apache.ratis.client.RaftClientRpc;
-import org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.protocol.RaftGroup;
-import org.apache.ratis.protocol.RaftGroupId;
-import org.apache.ratis.protocol.RaftPeer;
-import org.apache.ratis.retry.RetryPolicy;
-import org.apache.ratis.protocol.ClientId;
-import org.apache.ratis.protocol.RaftPeerId;
-
-/** Client utilities for internal use. */
-public interface ClientImplUtils {
-  static RaftClient newRaftClient(ClientId clientId, RaftGroup group,
-      RaftPeerId leaderId, RaftPeer primaryDataStreamServer, RaftClientRpc clientRpc, RaftProperties properties,
-      RetryPolicy retryPolicy) {
-    return new RaftClientImpl(clientId, group, leaderId, primaryDataStreamServer, clientRpc, properties,
-        retryPolicy);
-  }
-
-  static DataStreamClient newDataStreamClient(ClientId clientId, RaftGroupId groupId, RaftPeer primaryDataStreamServer,
-      DataStreamClientRpc dataStreamClientRpc, RaftProperties properties) {
-    return new DataStreamClientImpl(clientId, groupId, primaryDataStreamServer, dataStreamClientRpc, properties);
-  }
-}
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
deleted file mode 100644
index 9478c89..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientProtoUtils.java
+++ /dev/null
@@ -1,647 +0,0 @@
-/*
- * 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 java.nio.ByteBuffer;
-import java.util.Optional;
-
-import org.apache.ratis.datastream.impl.DataStreamReplyByteBuffer;
-import org.apache.ratis.protocol.*;
-import org.apache.ratis.protocol.exceptions.AlreadyClosedException;
-import org.apache.ratis.protocol.exceptions.DataStreamException;
-import org.apache.ratis.protocol.exceptions.LeaderNotReadyException;
-import org.apache.ratis.protocol.exceptions.LeaderSteppingDownException;
-import org.apache.ratis.protocol.exceptions.NotLeaderException;
-import org.apache.ratis.protocol.exceptions.NotReplicatedException;
-import org.apache.ratis.protocol.exceptions.RaftException;
-import org.apache.ratis.protocol.exceptions.StateMachineException;
-import org.apache.ratis.protocol.exceptions.TransferLeadershipException;
-import org.apache.ratis.rpc.CallId;
-import org.apache.ratis.thirdparty.com.google.protobuf.ByteString;
-import org.apache.ratis.thirdparty.com.google.protobuf.InvalidProtocolBufferException;
-import org.apache.ratis.proto.RaftProtos.*;
-import org.apache.ratis.util.ProtoUtils;
-import org.apache.ratis.util.ReflectionUtils;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-import static org.apache.ratis.proto.RaftProtos.RaftClientReplyProto.ExceptionDetailsCase.ALREADYCLOSEDEXCEPTION;
-import static org.apache.ratis.proto.RaftProtos.RaftClientReplyProto.ExceptionDetailsCase.DATASTREAMEXCEPTION;
-import static org.apache.ratis.proto.RaftProtos.RaftClientReplyProto.ExceptionDetailsCase.LEADERNOTREADYEXCEPTION;
-import static org.apache.ratis.proto.RaftProtos.RaftClientReplyProto.ExceptionDetailsCase.LEADERSTEPPINGDOWNEXCEPTION;
-import static org.apache.ratis.proto.RaftProtos.RaftClientReplyProto.ExceptionDetailsCase.NOTLEADEREXCEPTION;
-import static org.apache.ratis.proto.RaftProtos.RaftClientReplyProto.ExceptionDetailsCase.NOTREPLICATEDEXCEPTION;
-import static org.apache.ratis.proto.RaftProtos.RaftClientReplyProto.ExceptionDetailsCase.STATEMACHINEEXCEPTION;
-import static org.apache.ratis.proto.RaftProtos.RaftClientReplyProto.ExceptionDetailsCase.TRANSFERLEADERSHIPEXCEPTION;
-
-public interface ClientProtoUtils {
-
-  static RaftRpcReplyProto.Builder toRaftRpcReplyProtoBuilder(
-      ByteString requestorId, ByteString replyId, RaftGroupId groupId, Long callId, boolean success) {
-    return RaftRpcReplyProto.newBuilder()
-        .setRequestorId(requestorId)
-        .setReplyId(replyId)
-        .setRaftGroupId(ProtoUtils.toRaftGroupIdProtoBuilder(groupId))
-        .setCallId(Optional.ofNullable(callId).orElseGet(CallId::getDefault))
-        .setSuccess(success);
-  }
-
-  static RaftRpcRequestProto.Builder toRaftRpcRequestProtoBuilder(RaftGroupMemberId requestorId, RaftPeerId replyId) {
-    return toRaftRpcRequestProtoBuilder(requestorId.getPeerId().toByteString(),
-        replyId.toByteString(), requestorId.getGroupId(), null, false, null, null, 0);
-  }
-
-  @SuppressWarnings("parameternumber")
-  static RaftRpcRequestProto.Builder toRaftRpcRequestProtoBuilder(
-      ByteString requesterId, ByteString replyId, RaftGroupId groupId, Long callId, boolean toLeader,
-      SlidingWindowEntry slidingWindowEntry, RoutingTable routingTable, long timeoutMs) {
-    if (slidingWindowEntry == null) {
-      slidingWindowEntry = SlidingWindowEntry.getDefaultInstance();
-    }
-
-    RaftRpcRequestProto.Builder b = RaftRpcRequestProto.newBuilder()
-        .setRequestorId(requesterId)
-        .setReplyId(replyId)
-        .setRaftGroupId(ProtoUtils.toRaftGroupIdProtoBuilder(groupId))
-        .setCallId(Optional.ofNullable(callId).orElseGet(CallId::getDefault))
-        .setToLeader(toLeader)
-        .setSlidingWindowEntry(slidingWindowEntry)
-        .setTimeoutMs(timeoutMs);
-
-    if (routingTable != null) {
-      b.setRoutingTable(routingTable.toProto());
-    }
-
-    return b;
-  }
-
-  @SuppressWarnings("parameternumber")
-  static RaftRpcRequestProto.Builder toRaftRpcRequestProtoBuilder(
-      ClientId requesterId, RaftPeerId replyId, RaftGroupId groupId, long callId, boolean toLeader,
-      SlidingWindowEntry slidingWindowEntry, RoutingTable routingTable, long timeoutMs) {
-    return toRaftRpcRequestProtoBuilder(
-        requesterId.toByteString(), replyId.toByteString(), groupId, callId, toLeader, slidingWindowEntry, routingTable,
-        timeoutMs);
-  }
-
-  static RaftRpcRequestProto.Builder toRaftRpcRequestProtoBuilder(
-      RaftClientRequest request) {
-    return toRaftRpcRequestProtoBuilder(
-        request.getClientId(),
-        request.getServerId(),
-        request.getRaftGroupId(),
-        request.getCallId(),
-        request.isToLeader(),
-        request.getSlidingWindowEntry(),
-        request.getRoutingTable(),
-        request.getTimeoutMs());
-  }
-
-  static RaftClientRequest.Type toRaftClientRequestType(RaftClientRequestProto p) {
-    switch (p.getTypeCase()) {
-      case WRITE:
-        return RaftClientRequest.Type.valueOf(p.getWrite());
-      case DATASTREAM:
-        return RaftClientRequest.Type.valueOf(p.getDataStream());
-      case FORWARD:
-        return RaftClientRequest.Type.valueOf(p.getForward());
-      case MESSAGESTREAM:
-        return RaftClientRequest.Type.valueOf(p.getMessageStream());
-      case READ:
-        return RaftClientRequest.Type.valueOf(p.getRead());
-      case STALEREAD:
-        return RaftClientRequest.Type.valueOf(p.getStaleRead());
-      case WATCH:
-        return RaftClientRequest.Type.valueOf(p.getWatch());
-      default:
-        throw new IllegalArgumentException("Unexpected request type: " + p.getTypeCase()
-            + " in request proto " + p);
-    }
-  }
-
-  static RoutingTable getRoutingTable(RaftRpcRequestProto p) {
-    if (!p.hasRoutingTable()) {
-      return null;
-    }
-
-    RoutingTable.Builder builder = RoutingTable.newBuilder();
-    for (RouteProto routeProto : p.getRoutingTable().getRoutesList()) {
-      RaftPeerId from = RaftPeerId.valueOf(routeProto.getPeerId().getId());
-      List<RaftPeerId> to = routeProto.getSuccessorsList().stream()
-          .map(v -> RaftPeerId.valueOf(v.getId())).collect(Collectors.toList());
-      builder.addSuccessors(from, to);
-    }
-
-    return builder.build();
-  }
-
-  static RaftClientRequest toRaftClientRequest(RaftClientRequestProto p) {
-    final RaftClientRequest.Type type = toRaftClientRequestType(p);
-    final RaftRpcRequestProto request = p.getRpcRequest();
-
-    final RaftClientRequest.Builder b = RaftClientRequest.newBuilder();
-
-    final RaftPeerId perrId = RaftPeerId.valueOf(request.getReplyId());
-    if (request.getToLeader()) {
-      b.setLeaderId(perrId);
-    } else {
-      b.setServerId(perrId);
-    }
-    return b.setClientId(ClientId.valueOf(request.getRequestorId()))
-        .setGroupId(ProtoUtils.toRaftGroupId(request.getRaftGroupId()))
-        .setCallId(request.getCallId())
-        .setMessage(toMessage(p.getMessage()))
-        .setType(type)
-        .setSlidingWindowEntry(request.getSlidingWindowEntry())
-        .setRoutingTable(getRoutingTable(request))
-        .setTimeoutMs(request.getTimeoutMs())
-        .build();
-  }
-
-  static ByteBuffer toRaftClientRequestProtoByteBuffer(RaftClientRequest request) {
-    return toRaftClientRequestProto(request).toByteString().asReadOnlyByteBuffer();
-  }
-
-  static RaftClientRequestProto toRaftClientRequestProto(RaftClientRequest request) {
-    final RaftClientRequestProto.Builder b = RaftClientRequestProto.newBuilder()
-        .setRpcRequest(toRaftRpcRequestProtoBuilder(request));
-    if (request.getMessage() != null) {
-      b.setMessage(toClientMessageEntryProtoBuilder(request.getMessage()));
-    }
-
-    final RaftClientRequest.Type type = request.getType();
-    switch (type.getTypeCase()) {
-      case WRITE:
-        b.setWrite(type.getWrite());
-        break;
-      case DATASTREAM:
-        b.setDataStream(type.getDataStream());
-        break;
-      case FORWARD:
-        b.setForward(type.getForward());
-        break;
-      case MESSAGESTREAM:
-        b.setMessageStream(type.getMessageStream());
-        break;
-      case READ:
-        b.setRead(type.getRead());
-        break;
-      case STALEREAD:
-        b.setStaleRead(type.getStaleRead());
-        break;
-      case WATCH:
-        b.setWatch(type.getWatch());
-        break;
-      default:
-        throw new IllegalArgumentException("Unexpected request type: " + request.getType()
-            + " in request " + request);
-    }
-
-    return b.build();
-  }
-
-  static RaftClientRequestProto toRaftClientRequestProto(
-      ClientId clientId, RaftPeerId serverId, RaftGroupId groupId, long callId,
-      long seqNum, ByteString content) {
-    return RaftClientRequestProto.newBuilder()
-        .setRpcRequest(toRaftRpcRequestProtoBuilder(
-            clientId, serverId, groupId, callId, false, ProtoUtils.toSlidingWindowEntry(seqNum, false), null, 0))
-        .setWrite(WriteRequestTypeProto.getDefaultInstance())
-        .setMessage(toClientMessageEntryProtoBuilder(content))
-        .build();
-  }
-
-  static StateMachineExceptionProto.Builder toStateMachineExceptionProtoBuilder(StateMachineException e) {
-    final Throwable t = e.getCause() != null? e.getCause(): e;
-    return StateMachineExceptionProto.newBuilder()
-        .setExceptionClassName(t.getClass().getName())
-        .setErrorMsg(t.getMessage())
-        .setStacktrace(ProtoUtils.writeObject2ByteString(t.getStackTrace()));
-  }
-
-  static AlreadyClosedExceptionProto.Builder toAlreadyClosedExceptionProtoBuilder(AlreadyClosedException ace) {
-    final Throwable t = ace.getCause() != null ? ace.getCause() : ace;
-    return AlreadyClosedExceptionProto.newBuilder()
-        .setExceptionClassName(t.getClass().getName())
-        .setErrorMsg(ace.getMessage())
-        .setStacktrace(ProtoUtils.writeObject2ByteString(ace.getStackTrace()));
-  }
-
-  static RaftClientReplyProto toRaftClientReplyProto(RaftClientReply reply) {
-    final RaftClientReplyProto.Builder b = RaftClientReplyProto.newBuilder();
-    if (reply != null) {
-      b.setRpcReply(toRaftRpcReplyProtoBuilder(reply.getClientId().toByteString(),
-          reply.getServerId().toByteString(), reply.getRaftGroupId(),
-          reply.getCallId(), reply.isSuccess()));
-      b.setLogIndex(reply.getLogIndex());
-      if (reply.getMessage() != null) {
-        b.setMessage(toClientMessageEntryProtoBuilder(reply.getMessage()));
-      }
-      b.addAllCommitInfos(reply.getCommitInfos());
-
-      final NotLeaderException nle = reply.getNotLeaderException();
-      if (nle != null) {
-        NotLeaderExceptionProto.Builder nleBuilder =
-            NotLeaderExceptionProto.newBuilder();
-        final RaftPeer suggestedLeader = nle.getSuggestedLeader();
-        if (suggestedLeader != null) {
-          nleBuilder.setSuggestedLeader(suggestedLeader.getRaftPeerProto());
-        }
-        nleBuilder.addAllPeersInConf(ProtoUtils.toRaftPeerProtos(nle.getPeers()));
-        b.setNotLeaderException(nleBuilder.build());
-      }
-
-      final NotReplicatedException nre = reply.getNotReplicatedException();
-      if (nre != null) {
-        final NotReplicatedExceptionProto.Builder nreBuilder = NotReplicatedExceptionProto.newBuilder()
-            .setCallId(nre.getCallId())
-            .setReplication(nre.getRequiredReplication())
-            .setLogIndex(nre.getLogIndex());
-        b.setNotReplicatedException(nreBuilder);
-      }
-
-      final LeaderNotReadyException lnre = reply.getLeaderNotReadyException();
-      if (lnre != null) {
-        LeaderNotReadyExceptionProto.Builder lnreBuilder = LeaderNotReadyExceptionProto.newBuilder()
-            .setServerId(ProtoUtils.toRaftGroupMemberIdProtoBuilder(lnre.getServerId()));
-        b.setLeaderNotReadyException(lnreBuilder);
-      }
-
-      Optional.ofNullable(reply.getStateMachineException())
-          .map(ClientProtoUtils::toStateMachineExceptionProtoBuilder)
-          .ifPresent(b::setStateMachineException);
-
-      Optional.ofNullable(reply.getDataStreamException())
-          .map(ProtoUtils::toThrowableProto)
-          .ifPresent(b::setDataStreamException);
-
-      Optional.ofNullable(reply.getAlreadyClosedException())
-          .map(ClientProtoUtils::toAlreadyClosedExceptionProtoBuilder)
-          .ifPresent(b::setAlreadyClosedException);
-
-      Optional.ofNullable(reply.getLeaderSteppingDownException())
-          .map(ProtoUtils::toThrowableProto)
-          .ifPresent(b::setLeaderSteppingDownException);
-
-      Optional.ofNullable(reply.getTransferLeadershipException())
-          .map(ProtoUtils::toThrowableProto)
-          .ifPresent(b::setTransferLeadershipException);
-
-      final RaftClientReplyProto serialized = b.build();
-      final RaftException e = reply.getException();
-      if (e != null) {
-        final RaftClientReply deserialized = toRaftClientReply(serialized);
-        if (!Optional.ofNullable(deserialized.getException())
-            .map(Object::getClass).filter(e.getClass()::equals).isPresent()) {
-          throw new AssertionError("Corruption while serializing reply= " + reply
-              + " but serialized=" + serialized + " and deserialized=" + deserialized, e);
-        }
-      }
-      return serialized;
-    }
-    return b.build();
-  }
-
-  static GroupListReplyProto toGroupListReplyProto(
-      GroupListReply reply) {
-    final GroupListReplyProto.Builder b =
-        GroupListReplyProto.newBuilder();
-    if (reply != null) {
-      b.setRpcReply(toRaftRpcReplyProtoBuilder(reply.getClientId().toByteString(),
-          reply.getServerId().toByteString(), reply.getRaftGroupId(),
-          reply.getCallId(), reply.isSuccess()));
-      if (reply.getGroupIds() != null) {
-        reply.getGroupIds().forEach(groupId -> b.addGroupId(ProtoUtils.toRaftGroupIdProtoBuilder(groupId)));
-      }
-    }
-    return b.build();
-  }
-
-  static GroupInfoReplyProto toGroupInfoReplyProto(GroupInfoReply reply) {
-    final GroupInfoReplyProto.Builder b =
-        GroupInfoReplyProto.newBuilder();
-    if (reply != null) {
-      b.setRpcReply(toRaftRpcReplyProtoBuilder(reply.getClientId().toByteString(),
-          reply.getServerId().toByteString(), reply.getRaftGroupId(),
-          reply.getCallId(), reply.isSuccess()));
-      if (reply.getRaftGroupId() != null) {
-        b.setGroup(ProtoUtils.toRaftGroupProtoBuilder(reply.getGroup()));
-        b.setIsRaftStorageHealthy(reply.isRaftStorageHealthy());
-        b.setRole(reply.getRoleInfoProto());
-        b.addAllCommitInfos(reply.getCommitInfos());
-      }
-    }
-    return b.build();
-  }
-
-  static RaftClientReply getRaftClientReply(DataStreamReply reply) {
-    if (!(reply instanceof DataStreamReplyByteBuffer)) {
-      throw new IllegalStateException("Unexpected " + reply.getClass() + ": reply is " + reply);
-    }
-    try {
-      return toRaftClientReply(((DataStreamReplyByteBuffer) reply).slice());
-    } catch (InvalidProtocolBufferException e) {
-      throw new IllegalStateException("Failed to getRaftClientReply from " + reply, e);
-    }
-  }
-
-  static RaftClientReply toRaftClientReply(ByteBuffer buffer) throws InvalidProtocolBufferException {
-    return toRaftClientReply(RaftClientReplyProto.parseFrom(buffer));
-  }
-
-  static RaftClientReply toRaftClientReply(RaftClientReplyProto replyProto) {
-    final RaftRpcReplyProto rp = replyProto.getRpcReply();
-    final RaftGroupMemberId serverMemberId = ProtoUtils.toRaftGroupMemberId(rp.getReplyId(), rp.getRaftGroupId());
-
-    final RaftException e;
-    if (replyProto.getExceptionDetailsCase().equals(NOTLEADEREXCEPTION)) {
-      NotLeaderExceptionProto nleProto = replyProto.getNotLeaderException();
-      final RaftPeer suggestedLeader = nleProto.hasSuggestedLeader() ?
-          ProtoUtils.toRaftPeer(nleProto.getSuggestedLeader()) : null;
-      final List<RaftPeer> peers = ProtoUtils.toRaftPeers(nleProto.getPeersInConfList());
-      e = new NotLeaderException(serverMemberId, suggestedLeader, peers);
-    } else if (replyProto.getExceptionDetailsCase() == NOTREPLICATEDEXCEPTION) {
-      final NotReplicatedExceptionProto nre = replyProto.getNotReplicatedException();
-      e = new NotReplicatedException(nre.getCallId(), nre.getReplication(), nre.getLogIndex());
-    } else if (replyProto.getExceptionDetailsCase().equals(STATEMACHINEEXCEPTION)) {
-      e = toStateMachineException(serverMemberId, replyProto.getStateMachineException());
-    } else if (replyProto.getExceptionDetailsCase().equals(DATASTREAMEXCEPTION)) {
-      e = ProtoUtils.toThrowable(replyProto.getDataStreamException(), DataStreamException.class);
-    } else if (replyProto.getExceptionDetailsCase().equals(LEADERNOTREADYEXCEPTION)) {
-      LeaderNotReadyExceptionProto lnreProto = replyProto.getLeaderNotReadyException();
-      e = new LeaderNotReadyException(ProtoUtils.toRaftGroupMemberId(lnreProto.getServerId()));
-    } else if (replyProto.getExceptionDetailsCase().equals(ALREADYCLOSEDEXCEPTION)) {
-      e = toAlreadyClosedException(replyProto.getAlreadyClosedException());
-    } else if (replyProto.getExceptionDetailsCase().equals(LEADERSTEPPINGDOWNEXCEPTION)) {
-      e = ProtoUtils.toThrowable(replyProto.getLeaderSteppingDownException(), LeaderSteppingDownException.class);
-    } else if (replyProto.getExceptionDetailsCase().equals(TRANSFERLEADERSHIPEXCEPTION)) {
-      e = ProtoUtils.toThrowable(replyProto.getTransferLeadershipException(), TransferLeadershipException.class);
-    } else {
-      e = null;
-    }
-
-    return RaftClientReply.newBuilder()
-        .setClientId(ClientId.valueOf(rp.getRequestorId()))
-        .setServerId(serverMemberId)
-        .setCallId(rp.getCallId())
-        .setSuccess(rp.getSuccess())
-        .setMessage(toMessage(replyProto.getMessage()))
-        .setException(e)
-        .setLogIndex(replyProto.getLogIndex())
-        .setCommitInfos(replyProto.getCommitInfosList())
-        .build();
-  }
-
-  static StateMachineException toStateMachineException(RaftGroupMemberId memberId, StateMachineExceptionProto proto) {
-    return toStateMachineException(memberId,
-        proto.getExceptionClassName(),
-        proto.getErrorMsg(),
-        proto.getStacktrace());
-  }
-
-  static StateMachineException toStateMachineException(RaftGroupMemberId memberId,
-      String className, String errorMsg, ByteString stackTraceBytes) {
-    StateMachineException sme;
-    if (className == null) {
-      sme = new StateMachineException(errorMsg);
-    } else {
-      try {
-        final Class<?> clazz = Class.forName(className);
-        final Exception e = ReflectionUtils.instantiateException(clazz.asSubclass(Exception.class), errorMsg);
-        sme = new StateMachineException(memberId, e);
-      } catch (Exception e) {
-        sme = new StateMachineException(className + ": " + errorMsg);
-      }
-    }
-    final StackTraceElement[] stacktrace = (StackTraceElement[]) ProtoUtils.toObject(stackTraceBytes);
-    sme.setStackTrace(stacktrace);
-    return sme;
-  }
-
-  static AlreadyClosedException toAlreadyClosedException(AlreadyClosedExceptionProto proto) {
-    return toAlreadyClosedException(
-        proto.getExceptionClassName(),
-        proto.getErrorMsg(),
-        proto.getStacktrace());
-  }
-
-  static AlreadyClosedException toAlreadyClosedException(
-      String className, String errorMsg, ByteString stackTraceBytes) {
-    AlreadyClosedException ace;
-    if (className == null) {
-      ace = new AlreadyClosedException(errorMsg);
-    } else {
-      try {
-        Class<?> clazz = Class.forName(className);
-        final Exception e = ReflectionUtils.instantiateException(clazz.asSubclass(Exception.class), errorMsg);
-        ace = new AlreadyClosedException(errorMsg, e);
-      } catch (Exception e) {
-        ace = new AlreadyClosedException(className + ": " + errorMsg);
-      }
-    }
-    StackTraceElement[] stacktrace =
-        (StackTraceElement[]) ProtoUtils.toObject(stackTraceBytes);
-    ace.setStackTrace(stacktrace);
-    return ace;
-  }
-
-  static GroupListReply toGroupListReply(GroupListReplyProto replyProto) {
-    final RaftRpcReplyProto rpc = replyProto.getRpcReply();
-    final List<RaftGroupId> groupIds = replyProto.getGroupIdList().stream()
-        .map(ProtoUtils::toRaftGroupId)
-        .collect(Collectors.toList());
-    return new GroupListReply(ClientId.valueOf(rpc.getRequestorId()),
-        RaftPeerId.valueOf(rpc.getReplyId()),
-        ProtoUtils.toRaftGroupId(rpc.getRaftGroupId()),
-        rpc.getCallId(),
-        groupIds);
-  }
-
-  static GroupInfoReply toGroupInfoReply(GroupInfoReplyProto replyProto) {
-    final RaftRpcReplyProto rpc = replyProto.getRpcReply();
-    return new GroupInfoReply(ClientId.valueOf(rpc.getRequestorId()),
-        RaftPeerId.valueOf(rpc.getReplyId()),
-        ProtoUtils.toRaftGroupId(rpc.getRaftGroupId()),
-        rpc.getCallId(),
-        replyProto.getCommitInfosList(),
-        ProtoUtils.toRaftGroup(replyProto.getGroup()),
-        replyProto.getRole(),
-        replyProto.getIsRaftStorageHealthy());
-  }
-
-  static Message toMessage(final ClientMessageEntryProto p) {
-    return Message.valueOf(p.getContent());
-  }
-
-  static ClientMessageEntryProto.Builder toClientMessageEntryProtoBuilder(ByteString message) {
-    return ClientMessageEntryProto.newBuilder().setContent(message);
-  }
-
-  static ClientMessageEntryProto.Builder toClientMessageEntryProtoBuilder(Message message) {
-    return toClientMessageEntryProtoBuilder(message.getContent());
-  }
-
-  static SetConfigurationRequest toSetConfigurationRequest(
-      SetConfigurationRequestProto p) {
-    final RaftRpcRequestProto m = p.getRpcRequest();
-    final List<RaftPeer> peers = ProtoUtils.toRaftPeers(p.getPeersList());
-    return new SetConfigurationRequest(
-        ClientId.valueOf(m.getRequestorId()),
-        RaftPeerId.valueOf(m.getReplyId()),
-        ProtoUtils.toRaftGroupId(m.getRaftGroupId()),
-        p.getRpcRequest().getCallId(), peers);
-  }
-
-  static SetConfigurationRequestProto toSetConfigurationRequestProto(
-      SetConfigurationRequest request) {
-    return SetConfigurationRequestProto.newBuilder()
-        .setRpcRequest(toRaftRpcRequestProtoBuilder(request))
-        .addAllPeers(ProtoUtils.toRaftPeerProtos(request.getPeersInNewConf()))
-        .build();
-  }
-
-  static TransferLeadershipRequest toTransferLeadershipRequest(
-      TransferLeadershipRequestProto p) {
-    final RaftRpcRequestProto m = p.getRpcRequest();
-    final RaftPeer newLeader = ProtoUtils.toRaftPeer(p.getNewLeader());
-    return new TransferLeadershipRequest(
-        ClientId.valueOf(m.getRequestorId()),
-        RaftPeerId.valueOf(m.getReplyId()),
-        ProtoUtils.toRaftGroupId(m.getRaftGroupId()),
-        p.getRpcRequest().getCallId(),
-        newLeader.getId(),
-        m.getTimeoutMs());
-  }
-
-  static TransferLeadershipRequestProto toTransferLeadershipRequestProto(
-      TransferLeadershipRequest request) {
-    return TransferLeadershipRequestProto.newBuilder()
-        .setRpcRequest(toRaftRpcRequestProtoBuilder(request))
-        .setNewLeader(RaftPeer.newBuilder().setId(request.getNewLeader()).build().getRaftPeerProto())
-        .build();
-  }
-
-  static GroupManagementRequest toGroupManagementRequest(GroupManagementRequestProto p) {
-    final RaftRpcRequestProto m = p.getRpcRequest();
-    final ClientId clientId = ClientId.valueOf(m.getRequestorId());
-    final RaftPeerId serverId = RaftPeerId.valueOf(m.getReplyId());
-    switch(p.getOpCase()) {
-      case GROUPADD:
-        return GroupManagementRequest.newAdd(clientId, serverId, m.getCallId(),
-            ProtoUtils.toRaftGroup(p.getGroupAdd().getGroup()));
-      case GROUPREMOVE:
-        final GroupRemoveRequestProto remove = p.getGroupRemove();
-        return GroupManagementRequest.newRemove(clientId, serverId, m.getCallId(),
-            ProtoUtils.toRaftGroupId(remove.getGroupId()),
-            remove.getDeleteDirectory(), remove.getRenameDirectory());
-      default:
-        throw new IllegalArgumentException("Unexpected op " + p.getOpCase() + " in " + p);
-    }
-  }
-
-  static GroupInfoRequest toGroupInfoRequest(
-      GroupInfoRequestProto p) {
-    final RaftRpcRequestProto m = p.getRpcRequest();
-    return new GroupInfoRequest(
-        ClientId.valueOf(m.getRequestorId()),
-        RaftPeerId.valueOf(m.getReplyId()),
-        ProtoUtils.toRaftGroupId(m.getRaftGroupId()),
-        m.getCallId());
-  }
-
-  static GroupListRequest toGroupListRequest(
-      GroupListRequestProto p) {
-    final RaftRpcRequestProto m = p.getRpcRequest();
-    return new GroupListRequest(
-        ClientId.valueOf(m.getRequestorId()),
-        RaftPeerId.valueOf(m.getReplyId()),
-        ProtoUtils.toRaftGroupId(m.getRaftGroupId()),
-        m.getCallId());
-  }
-
-
-  static GroupManagementRequestProto toGroupManagementRequestProto(GroupManagementRequest request) {
-    final GroupManagementRequestProto.Builder b = GroupManagementRequestProto.newBuilder()
-        .setRpcRequest(toRaftRpcRequestProtoBuilder(request));
-    final GroupManagementRequest.Add add = request.getAdd();
-    if (add != null) {
-      b.setGroupAdd(GroupAddRequestProto.newBuilder().setGroup(
-          ProtoUtils.toRaftGroupProtoBuilder(add.getGroup())).build());
-    }
-    final GroupManagementRequest.Remove remove = request.getRemove();
-    if (remove != null) {
-      b.setGroupRemove(GroupRemoveRequestProto.newBuilder()
-          .setGroupId(ProtoUtils.toRaftGroupIdProtoBuilder(remove.getGroupId()))
-          .setDeleteDirectory(remove.isDeleteDirectory())
-          .setRenameDirectory(remove.isRenameDirectory())
-          .build());
-    }
-    return b.build();
-  }
-
-  static SnapshotManagementRequest toSnapshotManagementRequest(SnapshotManagementRequestProto p) {
-    final RaftRpcRequestProto m = p.getRpcRequest();
-    final ClientId clientId = ClientId.valueOf(m.getRequestorId());
-    final RaftPeerId serverId = RaftPeerId.valueOf(m.getReplyId());
-    switch(p.getOpCase()) {
-      case CREATE:
-        return SnapshotManagementRequest.newCreate(clientId, serverId,
-            ProtoUtils.toRaftGroupId(m.getRaftGroupId()), m.getCallId(), m.getTimeoutMs());
-      default:
-        throw new IllegalArgumentException("Unexpected op " + p.getOpCase() + " in " + p);
-    }
-  }
-
-  static SnapshotManagementRequestProto toSnapshotManagementRequestProto(
-      SnapshotManagementRequest request) {
-    final SnapshotManagementRequestProto.Builder b = SnapshotManagementRequestProto.newBuilder()
-        .setRpcRequest(toRaftRpcRequestProtoBuilder(request));
-    final SnapshotManagementRequest.Create create = request.getCreate();
-    if (create != null) {
-      b.setCreate(SnapshotCreateRequestProto.newBuilder().build());
-    }
-    return b.build();
-  }
-
-  static GroupInfoRequestProto toGroupInfoRequestProto(
-      GroupInfoRequest request) {
-    return GroupInfoRequestProto.newBuilder()
-        .setRpcRequest(toRaftRpcRequestProtoBuilder(request))
-        .build();
-  }
-
-  static GroupListRequestProto toGroupListRequestProto(
-      GroupListRequest request) {
-    return GroupListRequestProto.newBuilder()
-        .setRpcRequest(toRaftRpcRequestProtoBuilder(request))
-        .build();
-  }
-
-  static String toString(RaftClientRequestProto proto) {
-    final RaftRpcRequestProto rpc = proto.getRpcRequest();
-    return ClientId.valueOf(rpc.getRequestorId()) + "->" + rpc.getReplyId().toStringUtf8()
-        + "#" + rpc.getCallId() + "-" + ProtoUtils.toString(rpc.getSlidingWindowEntry());
-  }
-
-  static String toString(RaftClientReplyProto proto) {
-    final RaftRpcReplyProto rpc = proto.getRpcReply();
-    return ClientId.valueOf(rpc.getRequestorId()) + "<-" + rpc.getReplyId().toStringUtf8()
-        + "#" + rpc.getCallId();
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/DataStreamClientImpl.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/DataStreamClientImpl.java
deleted file mode 100644
index 7e04d2f..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/DataStreamClientImpl.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * 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.client.DataStreamClient;
-import org.apache.ratis.client.DataStreamClientRpc;
-import org.apache.ratis.client.DataStreamOutputRpc;
-import org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.datastream.impl.DataStreamPacketByteBuffer;
-import org.apache.ratis.io.FilePositionCount;
-import org.apache.ratis.io.StandardWriteOption;
-import org.apache.ratis.io.WriteOption;
-import org.apache.ratis.proto.RaftProtos.DataStreamPacketHeaderProto.Type;
-import org.apache.ratis.protocol.ClientId;
-import org.apache.ratis.protocol.ClientInvocationId;
-import org.apache.ratis.protocol.DataStreamReply;
-import org.apache.ratis.protocol.DataStreamRequestHeader;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftClientRequest;
-import org.apache.ratis.protocol.RaftGroupId;
-import org.apache.ratis.protocol.RaftPeer;
-import org.apache.ratis.protocol.exceptions.AlreadyClosedException;
-import org.apache.ratis.rpc.CallId;
-import org.apache.ratis.util.IOUtils;
-import org.apache.ratis.protocol.*;
-import org.apache.ratis.thirdparty.com.google.protobuf.ByteString;
-import org.apache.ratis.util.JavaUtils;
-import org.apache.ratis.util.MemoizedSupplier;
-import org.apache.ratis.util.SlidingWindow;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.WritableByteChannel;
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-
-/**
- * Streaming client implementation
- * allows client to create streams and send asynchronously.
- */
-public class DataStreamClientImpl implements DataStreamClient {
-  private final ClientId clientId;
-  private final RaftGroupId groupId;
-
-  private final RaftPeer dataStreamServer;
-  private final DataStreamClientRpc dataStreamClientRpc;
-  private final OrderedStreamAsync orderedStreamAsync;
-
-  DataStreamClientImpl(ClientId clientId, RaftGroupId groupId, RaftPeer dataStreamServer,
-      DataStreamClientRpc dataStreamClientRpc, RaftProperties properties) {
-    this.clientId = clientId;
-    this.groupId = groupId;
-    this.dataStreamServer = dataStreamServer;
-    this.dataStreamClientRpc = dataStreamClientRpc;
-    this.orderedStreamAsync = new OrderedStreamAsync(dataStreamClientRpc, properties);
-  }
-
-  public final class DataStreamOutputImpl implements DataStreamOutputRpc {
-    private final RaftClientRequest header;
-    private final CompletableFuture<DataStreamReply> headerFuture;
-    private final SlidingWindow.Client<OrderedStreamAsync.DataStreamWindowRequest, DataStreamReply> slidingWindow;
-    private final CompletableFuture<RaftClientReply> raftClientReplyFuture = new CompletableFuture<>();
-    private CompletableFuture<DataStreamReply> closeFuture;
-    private final MemoizedSupplier<WritableByteChannel> writableByteChannelSupplier
-        = JavaUtils.memoize(() -> new WritableByteChannel() {
-      @Override
-      public int write(ByteBuffer src) throws IOException {
-        final int remaining = src.remaining();
-        final DataStreamReply reply = IOUtils.getFromFuture(writeAsync(src),
-            () -> "write(" + remaining + " bytes for " + ClientInvocationId.valueOf(header) + ")");
-        return Math.toIntExact(reply.getBytesWritten());
-      }
-
-      @Override
-      public boolean isOpen() {
-        return !isClosed();
-      }
-
-      @Override
-      public void close() throws IOException {
-        if (isClosed()) {
-          return;
-        }
-        IOUtils.getFromFuture(writeAsync(DataStreamPacketByteBuffer.EMPTY_BYTE_BUFFER, StandardWriteOption.CLOSE),
-            () -> "close(" + ClientInvocationId.valueOf(header) + ")");
-      }
-    });
-
-    private long streamOffset = 0;
-
-    private DataStreamOutputImpl(RaftClientRequest request) {
-      this.header = request;
-      this.slidingWindow = new SlidingWindow.Client<>(ClientInvocationId.valueOf(clientId, header.getCallId()));
-      final ByteBuffer buffer = ClientProtoUtils.toRaftClientRequestProtoByteBuffer(header);
-      this.headerFuture = send(Type.STREAM_HEADER, buffer, buffer.remaining());
-    }
-
-    private CompletableFuture<DataStreamReply> send(Type type, Object data, long length, WriteOption... options) {
-      final DataStreamRequestHeader h =
-          new DataStreamRequestHeader(header.getClientId(), type, header.getCallId(), streamOffset, length, options);
-      return orderedStreamAsync.sendRequest(h, data, slidingWindow);
-    }
-
-    private CompletableFuture<DataStreamReply> combineHeader(CompletableFuture<DataStreamReply> future) {
-      return future.thenCombine(headerFuture, (reply, headerReply) -> headerReply.isSuccess()? reply : headerReply);
-    }
-
-    private CompletableFuture<DataStreamReply> writeAsyncImpl(Object data, long length, WriteOption... options) {
-      if (isClosed()) {
-        return JavaUtils.completeExceptionally(new AlreadyClosedException(
-            clientId + ": stream already closed, request=" + header));
-      }
-      final CompletableFuture<DataStreamReply> f = combineHeader(send(Type.STREAM_DATA, data, length, options));
-      if (WriteOption.containsOption(options, StandardWriteOption.CLOSE)) {
-        closeFuture = f;
-        f.thenApply(ClientProtoUtils::getRaftClientReply).whenComplete(JavaUtils.asBiConsumer(raftClientReplyFuture));
-      }
-      streamOffset += length;
-      return f;
-    }
-
-    @Override
-    public CompletableFuture<DataStreamReply> writeAsync(ByteBuffer src, WriteOption... options) {
-      return writeAsyncImpl(src, src.remaining(), options);
-    }
-
-    @Override
-    public CompletableFuture<DataStreamReply> writeAsync(FilePositionCount src, WriteOption... options) {
-      return writeAsyncImpl(src, src.getCount(), options);
-    }
-
-    boolean isClosed() {
-      return closeFuture != null;
-    }
-
-    @Override
-    public CompletableFuture<DataStreamReply> closeAsync() {
-      return isClosed() ? closeFuture :
-          writeAsync(DataStreamPacketByteBuffer.EMPTY_BYTE_BUFFER, StandardWriteOption.CLOSE);
-    }
-
-    public RaftClientRequest getHeader() {
-      return header;
-    }
-
-    @Override
-    public CompletableFuture<DataStreamReply> getHeaderFuture() {
-      return headerFuture;
-    }
-
-    @Override
-    public CompletableFuture<RaftClientReply> getRaftClientReplyFuture() {
-      return raftClientReplyFuture;
-    }
-
-    @Override
-    public WritableByteChannel getWritableByteChannel() {
-      return writableByteChannelSupplier.get();
-    }
-  }
-
-  @Override
-  public DataStreamClientRpc getClientRpc() {
-    return dataStreamClientRpc;
-  }
-
-  @Override
-  public DataStreamOutputRpc stream(RaftClientRequest request) {
-    return new DataStreamOutputImpl(request);
-  }
-
-  @Override
-  public DataStreamOutputRpc stream(ByteBuffer headerMessage) {
-    return stream(headerMessage, null);
-  }
-
-  @Override
-  public DataStreamOutputRpc stream(ByteBuffer headerMessage, RoutingTable routingTable) {
-    final Message message =
-        Optional.ofNullable(headerMessage).map(ByteString::copyFrom).map(Message::valueOf).orElse(null);
-    RaftClientRequest request = RaftClientRequest.newBuilder()
-        .setClientId(clientId)
-        .setServerId(dataStreamServer.getId())
-        .setGroupId(groupId)
-        .setCallId(CallId.getAndIncrement())
-        .setMessage(message)
-        .setType(RaftClientRequest.dataStreamRequestType())
-        .setRoutingTable(routingTable)
-        .build();
-    return new DataStreamOutputImpl(request);
-  }
-
-  @Override
-  public void close() throws IOException {
-    dataStreamClientRpc.close();
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/GroupManagementImpl.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/GroupManagementImpl.java
deleted file mode 100644
index 27e0bbf..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/GroupManagementImpl.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.client.api.GroupManagementApi;
-import org.apache.ratis.protocol.GroupInfoReply;
-import org.apache.ratis.protocol.GroupInfoRequest;
-import org.apache.ratis.protocol.GroupListReply;
-import org.apache.ratis.protocol.GroupListRequest;
-import org.apache.ratis.protocol.GroupManagementRequest;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftGroup;
-import org.apache.ratis.protocol.RaftGroupId;
-import org.apache.ratis.protocol.RaftPeerId;
-import org.apache.ratis.rpc.CallId;
-import org.apache.ratis.util.Preconditions;
-
-import java.io.IOException;
-import java.util.Objects;
-
-class GroupManagementImpl implements GroupManagementApi {
-  private final RaftPeerId server;
-  private final RaftClientImpl client;
-
-  GroupManagementImpl(RaftPeerId server, RaftClientImpl client) {
-    this.server = Objects.requireNonNull(server, "server == null");
-    this.client = Objects.requireNonNull(client, "client == null");
-  }
-
-  @Override
-  public RaftClientReply add(RaftGroup newGroup) throws IOException {
-    Objects.requireNonNull(newGroup, "newGroup == null");
-
-    final long callId = CallId.getAndIncrement();
-    client.getClientRpc().addRaftPeers(newGroup.getPeers());
-    return client.io().sendRequestWithRetry(
-        () -> GroupManagementRequest.newAdd(client.getId(), server, callId, newGroup));
-  }
-
-  @Override
-  public RaftClientReply remove(RaftGroupId groupId, boolean deleteDirectory, boolean renameDirectory)
-      throws IOException {
-    Objects.requireNonNull(groupId, "groupId == null");
-
-    final long callId = CallId.getAndIncrement();
-    return client.io().sendRequestWithRetry(
-        () -> GroupManagementRequest.newRemove(client.getId(), server, callId, groupId,
-            deleteDirectory, renameDirectory));
-  }
-
-  @Override
-  public GroupListReply list() throws IOException {
-    final long callId = CallId.getAndIncrement();
-    final RaftClientReply reply = client.io().sendRequestWithRetry(
-        () -> new GroupListRequest(client.getId(), server, client.getGroupId(), callId));
-    Preconditions.assertTrue(reply instanceof GroupListReply, () -> "Unexpected reply: " + reply);
-    return (GroupListReply)reply;
-  }
-
-  @Override
-  public GroupInfoReply info(RaftGroupId groupId) throws IOException {
-    final RaftGroupId gid = groupId != null? groupId: client.getGroupId();
-    final long callId = CallId.getAndIncrement();
-    final RaftClientReply reply = client.io().sendRequestWithRetry(
-        () -> new GroupInfoRequest(client.getId(), server, gid, callId));
-    Preconditions.assertTrue(reply instanceof GroupInfoReply, () -> "Unexpected reply: " + reply);
-    return (GroupInfoReply)reply;
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/MessageStreamImpl.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/MessageStreamImpl.java
deleted file mode 100644
index d35bbd0..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/MessageStreamImpl.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.client.RaftClientConfigKeys;
-import org.apache.ratis.client.api.MessageOutputStream;
-import org.apache.ratis.client.api.MessageStreamApi;
-import org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.protocol.Message;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftClientRequest;
-import org.apache.ratis.protocol.RaftClientRequest.Type;
-import org.apache.ratis.thirdparty.com.google.protobuf.ByteString;
-import org.apache.ratis.util.SizeInBytes;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Objects;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicLong;
-
-/** Send ordered asynchronous requests to a raft service. */
-public final class MessageStreamImpl implements MessageStreamApi {
-  public static final Logger LOG = LoggerFactory.getLogger(MessageStreamImpl.class);
-
-  static MessageStreamImpl newInstance(RaftClientImpl client, RaftProperties properties) {
-    return new MessageStreamImpl(client, properties);
-  }
-
-  class MessageOutputStreamImpl implements MessageOutputStream {
-    private final long id;
-    private final AtomicLong messageId = new AtomicLong();
-
-    MessageOutputStreamImpl(long id) {
-      this.id = id;
-    }
-
-    private Type getMessageStreamRequestType(boolean endOfRequest) {
-      return RaftClientRequest.messageStreamRequestType(id, messageId.getAndIncrement(), endOfRequest);
-    }
-
-    @Override
-    public CompletableFuture<RaftClientReply> sendAsync(Message message, boolean endOfRequest) {
-      return client.async().send(getMessageStreamRequestType(endOfRequest), message, null);
-    }
-
-    @Override
-    public CompletableFuture<RaftClientReply> closeAsync() {
-      return client.async().send(getMessageStreamRequestType(true), null, null);
-    }
-  }
-
-  private final RaftClientImpl client;
-  private final SizeInBytes submessageSize;
-  private final AtomicLong streamId = new AtomicLong();
-
-  private MessageStreamImpl(RaftClientImpl client, RaftProperties properties) {
-    this.client = Objects.requireNonNull(client, "client == null");
-    this.submessageSize = RaftClientConfigKeys.MessageStream.submessageSize(properties);
-  }
-
-  @Override
-  public MessageOutputStream stream() {
-    return new MessageOutputStreamImpl(streamId.incrementAndGet());
-  }
-
-  @Override
-  public CompletableFuture<RaftClientReply> streamAsync(Message message, SizeInBytes subSize) {
-    final int n = subSize.getSizeInt();
-    final MessageOutputStream out = stream();
-    final ByteString bytes = message.getContent();
-    for(int i = 0; i < bytes.size(); ) {
-      final int j = Math.min(i + n, bytes.size());
-      final ByteString sub = bytes.substring(i, j);
-      out.sendAsync(Message.valueOf(sub));
-      i = j;
-    }
-    return out.closeAsync();
-  }
-
-  @Override
-  public CompletableFuture<RaftClientReply> streamAsync(Message message) {
-    return streamAsync(message, submessageSize);
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/OrderedAsync.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/OrderedAsync.java
deleted file mode 100644
index 8a530d9..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/OrderedAsync.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * 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.client.retry.ClientRetryEvent;
-import org.apache.ratis.client.RaftClientConfigKeys;
-import org.apache.ratis.client.impl.RaftClientImpl.PendingClientRequest;
-import org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.proto.RaftProtos.RaftClientRequestProto.TypeCase;
-import org.apache.ratis.proto.RaftProtos.SlidingWindowEntry;
-import org.apache.ratis.protocol.exceptions.GroupMismatchException;
-import org.apache.ratis.protocol.Message;
-import org.apache.ratis.protocol.exceptions.NotLeaderException;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftClientRequest;
-import org.apache.ratis.protocol.RaftPeerId;
-import org.apache.ratis.retry.RetryPolicy;
-import org.apache.ratis.rpc.CallId;
-import org.apache.ratis.util.IOUtils;
-import org.apache.ratis.util.JavaUtils;
-import org.apache.ratis.util.Preconditions;
-import org.apache.ratis.util.ProtoUtils;
-import org.apache.ratis.util.SlidingWindow;
-import org.apache.ratis.util.TimeDuration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Function;
-import java.util.function.LongFunction;
-
-/** Send ordered asynchronous requests to a raft service. */
-public final class OrderedAsync {
-  public static final Logger LOG = LoggerFactory.getLogger(OrderedAsync.class);
-
-  static class PendingOrderedRequest extends PendingClientRequest
-      implements SlidingWindow.ClientSideRequest<RaftClientReply> {
-    private final long callId;
-    private final long seqNum;
-    private final AtomicReference<Function<SlidingWindowEntry, RaftClientRequest>> requestConstructor;
-    private volatile boolean isFirst = false;
-
-    PendingOrderedRequest(long callId, long seqNum,
-        Function<SlidingWindowEntry, RaftClientRequest> requestConstructor) {
-      this.callId = callId;
-      this.seqNum = seqNum;
-      this.requestConstructor = new AtomicReference<>(requestConstructor);
-    }
-
-    @Override
-    public RaftClientRequest newRequestImpl() {
-      return Optional.ofNullable(requestConstructor.get())
-          .map(f -> f.apply(ProtoUtils.toSlidingWindowEntry(seqNum, isFirst)))
-          .orElse(null);
-    }
-
-    @Override
-    public void setFirstRequest() {
-      isFirst = true;
-    }
-
-    @Override
-    public long getSeqNum() {
-      return seqNum;
-    }
-
-    @Override
-    public boolean hasReply() {
-      return getReplyFuture().isDone();
-    }
-
-    @Override
-    public void setReply(RaftClientReply reply) {
-      requestConstructor.set(null);
-      getReplyFuture().complete(reply);
-    }
-
-    @Override
-    public void fail(Throwable e) {
-      requestConstructor.set(null);
-      getReplyFuture().completeExceptionally(e);
-    }
-
-    @Override
-    public String toString() {
-      return "[cid=" + callId + ", seq=" + getSeqNum() + "]";
-    }
-  }
-
-  static OrderedAsync newInstance(RaftClientImpl client, RaftProperties properties) {
-    final OrderedAsync ordered = new OrderedAsync(client, properties);
-    // send a dummy watch request to establish the connection
-    // TODO: this is a work around, it is better to fix the underlying RPC implementation
-    if (RaftClientConfigKeys.Async.Experimental.sendDummyRequest(properties)) {
-      ordered.send(RaftClientRequest.watchRequestType(), null, null);
-    }
-    return ordered;
-  }
-
-  private final RaftClientImpl client;
-  /** Map: id -> {@link SlidingWindow}, in order to support async calls to the Raft service or individual servers. */
-  private final ConcurrentMap<String, SlidingWindow.Client<PendingOrderedRequest, RaftClientReply>> slidingWindows
-      = new ConcurrentHashMap<>();
-  private final Semaphore requestSemaphore;
-
-  private OrderedAsync(RaftClientImpl client, RaftProperties properties) {
-    this.client = Objects.requireNonNull(client, "client == null");
-    this.requestSemaphore = new Semaphore(RaftClientConfigKeys.Async.outstandingRequestsMax(properties));
-  }
-
-  private void resetSlidingWindow(RaftClientRequest request) {
-    getSlidingWindow(request).resetFirstSeqNum();
-  }
-
-  private SlidingWindow.Client<PendingOrderedRequest, RaftClientReply> getSlidingWindow(RaftClientRequest request) {
-    return getSlidingWindow(request.is(TypeCase.STALEREAD) ? request.getServerId() : null);
-  }
-
-  private SlidingWindow.Client<PendingOrderedRequest, RaftClientReply> getSlidingWindow(RaftPeerId target) {
-    final String id = target != null ? target.toString() : "RAFT";
-    return slidingWindows.computeIfAbsent(id, key -> new SlidingWindow.Client<>(client.getId() + "->" + key));
-  }
-
-  private void failAllAsyncRequests(RaftClientRequest request, Throwable t) {
-    getSlidingWindow(request).fail(request.getSlidingWindowEntry().getSeqNum(), t);
-  }
-
-  private void handleAsyncRetryFailure(ClientRetryEvent event) {
-    failAllAsyncRequests(event.getRequest(), client.noMoreRetries(event));
-  }
-
-  CompletableFuture<RaftClientReply> send(RaftClientRequest.Type type, Message message, RaftPeerId server) {
-    if (!type.is(TypeCase.WATCH) && !type.is(TypeCase.MESSAGESTREAM)) {
-      Objects.requireNonNull(message, "message == null");
-    }
-    try {
-      requestSemaphore.acquire();
-    } catch (InterruptedException e) {
-      Thread.currentThread().interrupt();
-      return JavaUtils.completeExceptionally(IOUtils.toInterruptedIOException(
-          "Interrupted when sending " + type + ", message=" + message, e));
-    }
-
-    final long callId = CallId.getAndIncrement();
-    final LongFunction<PendingOrderedRequest> constructor = seqNum -> new PendingOrderedRequest(callId, seqNum,
-        slidingWindowEntry -> client.newRaftClientRequest(server, callId, message, type, slidingWindowEntry));
-    return getSlidingWindow(server).submitNewRequest(constructor, this::sendRequestWithRetry
-    ).getReplyFuture(
-    ).thenApply(reply -> RaftClientImpl.handleRaftException(reply, CompletionException::new)
-    ).whenComplete((r, e) -> {
-      if (e != null) {
-        LOG.error("Failed to send request, message=" + message, e);
-      }
-      requestSemaphore.release();
-    });
-  }
-
-  private void sendRequestWithRetry(PendingOrderedRequest pending) {
-    final CompletableFuture<RaftClientReply> f = pending.getReplyFuture();
-    if (f.isDone()) {
-      return;
-    }
-
-    final RaftClientRequest request = pending.newRequestImpl();
-    if (request == null) { // already done
-      LOG.debug("{} newRequestImpl returns null", pending);
-      return;
-    }
-
-    final RetryPolicy retryPolicy = client.getRetryPolicy();
-    sendRequest(pending).thenAccept(reply -> {
-      if (f.isDone()) {
-        return;
-      }
-      if (reply == null) {
-        scheduleWithTimeout(pending, request, retryPolicy, null);
-      } else {
-        client.handleReply(request, reply);
-        f.complete(reply);
-      }
-    }).exceptionally(e -> {
-      if (e instanceof CompletionException) {
-        e = JavaUtils.unwrapCompletionException(e);
-        scheduleWithTimeout(pending, request, retryPolicy, e);
-        return null;
-      }
-      f.completeExceptionally(e);
-      return null;
-    });
-  }
-
-  private void scheduleWithTimeout(PendingOrderedRequest pending,
-      RaftClientRequest request, RetryPolicy retryPolicy, Throwable e) {
-    final int attempt = pending.getAttemptCount();
-    final ClientRetryEvent event = new ClientRetryEvent(request, e, pending);
-    final TimeDuration sleepTime = client.getEffectiveSleepTime(e,
-        retryPolicy.handleAttemptFailure(event).getSleepTime());
-    LOG.debug("schedule* attempt #{} with sleep {} and policy {} for {}", attempt, sleepTime, retryPolicy, request);
-    scheduleWithTimeout(pending, sleepTime, getSlidingWindow(request));
-  }
-
-  private void scheduleWithTimeout(PendingOrderedRequest pending, TimeDuration sleepTime,
-      SlidingWindow.Client<PendingOrderedRequest, RaftClientReply> slidingWindow) {
-    client.getScheduler().onTimeout(sleepTime,
-        () -> slidingWindow.retry(pending, this::sendRequestWithRetry),
-        LOG, () -> "Failed* to retry " + pending);
-  }
-
-  private CompletableFuture<RaftClientReply> sendRequest(PendingOrderedRequest pending) {
-    final RetryPolicy retryPolicy = client.getRetryPolicy();
-    final CompletableFuture<RaftClientReply> f;
-    final RaftClientRequest request;
-    if (getSlidingWindow((RaftPeerId) null).isFirst(pending.getSeqNum())) {
-      pending.setFirstRequest();
-    }
-    request = pending.newRequest();
-    LOG.debug("{}: send* {}", client.getId(), request);
-    f = client.getClientRpc().sendRequestAsync(request);
-    return f.thenApply(reply -> {
-      LOG.debug("{}: receive* {}", client.getId(), reply);
-      getSlidingWindow(request).receiveReply(
-          request.getSlidingWindowEntry().getSeqNum(), reply, this::sendRequestWithRetry);
-      return reply;
-    }).exceptionally(e -> {
-      if (LOG.isTraceEnabled()) {
-        LOG.trace(client.getId() + ": Failed* " + request, e);
-      } else {
-        LOG.debug("{}: Failed* {} with {}", client.getId(), request, e);
-      }
-      e = JavaUtils.unwrapCompletionException(e);
-      if (e instanceof IOException && !(e instanceof GroupMismatchException)) {
-        pending.incrementExceptionCount(e);
-        final ClientRetryEvent event = new ClientRetryEvent(request, e, pending);
-        if (!retryPolicy.handleAttemptFailure(event).shouldRetry()) {
-          handleAsyncRetryFailure(event);
-        } else {
-          if (e instanceof NotLeaderException) {
-            NotLeaderException nle = (NotLeaderException)e;
-            client.handleNotLeaderException(request, nle, this::resetSlidingWindow);
-          } else {
-            client.handleIOException(request, (IOException) e, null, this::resetSlidingWindow);
-          }
-        }
-        throw new CompletionException(e);
-      }
-      failAllAsyncRequests(request, e);
-      return null;
-    });
-  }
-
-  void assertRequestSemaphore(int expectedAvailablePermits, int expectedQueueLength) {
-    Preconditions.assertTrue(requestSemaphore.availablePermits() == expectedAvailablePermits);
-    Preconditions.assertTrue(requestSemaphore.getQueueLength() == expectedQueueLength);
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/OrderedStreamAsync.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/OrderedStreamAsync.java
deleted file mode 100644
index d9f5862..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/OrderedStreamAsync.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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.client.DataStreamClientRpc;
-import org.apache.ratis.client.RaftClientConfigKeys;
-import org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.datastream.impl.DataStreamPacketByteBuffer;
-import org.apache.ratis.datastream.impl.DataStreamRequestByteBuffer;
-import org.apache.ratis.datastream.impl.DataStreamRequestFilePositionCount;
-import org.apache.ratis.io.FilePositionCount;
-import org.apache.ratis.protocol.DataStreamReply;
-import org.apache.ratis.protocol.DataStreamRequest;
-import org.apache.ratis.protocol.DataStreamRequestHeader;
-import org.apache.ratis.protocol.exceptions.TimeoutIOException;
-import org.apache.ratis.util.IOUtils;
-import org.apache.ratis.util.JavaUtils;
-import org.apache.ratis.util.SlidingWindow;
-import org.apache.ratis.util.TimeDuration;
-import org.apache.ratis.util.TimeoutScheduler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.nio.ByteBuffer;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Semaphore;
-import java.util.function.LongFunction;
-
-public class OrderedStreamAsync {
-  public static final Logger LOG = LoggerFactory.getLogger(OrderedStreamAsync.class);
-
-  static class DataStreamWindowRequest implements SlidingWindow.ClientSideRequest<DataStreamReply> {
-    private final DataStreamRequestHeader header;
-    private final Object data;
-    private final long seqNum;
-    private final CompletableFuture<DataStreamReply> replyFuture = new CompletableFuture<>();
-
-    DataStreamWindowRequest(DataStreamRequestHeader header, Object data, long seqNum) {
-      this.header = header;
-      this.data = data;
-      this.seqNum = seqNum;
-    }
-
-    DataStreamRequest getDataStreamRequest() {
-      if (header.getDataLength() == 0) {
-        return new DataStreamRequestByteBuffer(header, DataStreamPacketByteBuffer.EMPTY_BYTE_BUFFER);
-      } else if (data instanceof ByteBuffer) {
-        return new DataStreamRequestByteBuffer(header, (ByteBuffer)data);
-      } else if (data instanceof FilePositionCount) {
-        return new DataStreamRequestFilePositionCount(header, (FilePositionCount)data);
-      }
-      throw new IllegalStateException("Unexpected " + data.getClass());
-    }
-
-    @Override
-    public void setFirstRequest() {
-    }
-
-    @Override
-    public long getSeqNum() {
-      return seqNum;
-    }
-
-    @Override
-    public void setReply(DataStreamReply dataStreamReply) {
-      replyFuture.complete(dataStreamReply);
-    }
-
-    @Override
-    public boolean hasReply() {
-      return replyFuture.isDone();
-    }
-
-    @Override
-    public void fail(Throwable e) {
-      replyFuture.completeExceptionally(e);
-    }
-
-    public CompletableFuture<DataStreamReply> getReplyFuture(){
-      return replyFuture;
-    }
-
-    @Override
-    public String toString() {
-      return JavaUtils.getClassSimpleName(getClass()) + ":seqNum=" + seqNum + "," + header;
-    }
-  }
-
-  private final DataStreamClientRpc dataStreamClientRpc;
-
-  private final Semaphore requestSemaphore;
-  private final TimeDuration requestTimeout;
-  private final TimeoutScheduler scheduler = TimeoutScheduler.getInstance();
-
-  OrderedStreamAsync(DataStreamClientRpc dataStreamClientRpc, RaftProperties properties){
-    this.dataStreamClientRpc = dataStreamClientRpc;
-    this.requestSemaphore = new Semaphore(RaftClientConfigKeys.DataStream.outstandingRequestsMax(properties));
-    this.requestTimeout = RaftClientConfigKeys.DataStream.requestTimeout(properties);
-  }
-
-  CompletableFuture<DataStreamReply> sendRequest(DataStreamRequestHeader header, Object data,
-      SlidingWindow.Client<DataStreamWindowRequest, DataStreamReply> slidingWindow) {
-    try {
-      requestSemaphore.acquire();
-    } catch (InterruptedException e){
-      return JavaUtils.completeExceptionally(IOUtils.toInterruptedIOException(
-          "Interrupted when sending " + JavaUtils.getClassSimpleName(data.getClass()) + ", header= " + header, e));
-    }
-    final LongFunction<DataStreamWindowRequest> constructor
-        = seqNum -> new DataStreamWindowRequest(header, data, seqNum);
-    return slidingWindow.submitNewRequest(constructor, r -> sendRequestToNetwork(r, slidingWindow)).
-           getReplyFuture().whenComplete((r, e) -> {
-             if (e != null) {
-               LOG.error("Failed to send request, header=" + header, e);
-             }
-             requestSemaphore.release();
-           });
-  }
-
-  private void sendRequestToNetwork(DataStreamWindowRequest request,
-      SlidingWindow.Client<DataStreamWindowRequest, DataStreamReply> slidingWindow) {
-    CompletableFuture<DataStreamReply> f = request.getReplyFuture();
-    if(f.isDone()) {
-      return;
-    }
-    if(slidingWindow.isFirst(request.getSeqNum())){
-      request.setFirstRequest();
-    }
-    final CompletableFuture<DataStreamReply> requestFuture = dataStreamClientRpc.streamAsync(
-        request.getDataStreamRequest());
-    long seqNum = request.getSeqNum();
-
-    scheduleWithTimeout(request);
-
-    requestFuture.thenApply(reply -> {
-      slidingWindow.receiveReply(
-          seqNum, reply, r -> sendRequestToNetwork(r, slidingWindow));
-      return reply;
-    }).thenAccept(reply -> {
-      if (f.isDone()) {
-        return;
-      }
-      f.complete(reply);
-    }).exceptionally(e -> {
-      f.completeExceptionally(e);
-      return null;
-    });
-  }
-
-  private void scheduleWithTimeout(DataStreamWindowRequest request) {
-    scheduler.onTimeout(requestTimeout, () -> {
-      if (!request.getReplyFuture().isDone()) {
-        request.getReplyFuture().completeExceptionally(
-            new TimeoutIOException("Timeout " + requestTimeout + ": Failed to send " + request));
-      }
-    }, LOG, () -> "Failed to completeExceptionally for " + request);
-  }
-}
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
deleted file mode 100644
index 9ccb256..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftClientImpl.java
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * 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.client.DataStreamClient;
-import org.apache.ratis.client.RaftClient;
-import org.apache.ratis.client.RaftClientRpc;
-import org.apache.ratis.client.api.DataStreamApi;
-import org.apache.ratis.client.api.SnapshotManagementApi;
-import org.apache.ratis.client.retry.ClientRetryEvent;
-import org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.proto.RaftProtos.SlidingWindowEntry;
-import org.apache.ratis.protocol.ClientId;
-import org.apache.ratis.protocol.Message;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftClientRequest;
-import org.apache.ratis.protocol.RaftGroup;
-import org.apache.ratis.protocol.RaftGroupId;
-import org.apache.ratis.protocol.RaftPeer;
-import org.apache.ratis.protocol.RaftPeerId;
-import org.apache.ratis.protocol.exceptions.LeaderNotReadyException;
-import org.apache.ratis.protocol.exceptions.NotLeaderException;
-import org.apache.ratis.protocol.exceptions.RaftException;
-import org.apache.ratis.protocol.exceptions.RaftRetryFailureException;
-import org.apache.ratis.protocol.exceptions.ResourceUnavailableException;
-import org.apache.ratis.retry.RetryPolicy;
-import org.apache.ratis.thirdparty.com.google.common.cache.Cache;
-import org.apache.ratis.thirdparty.com.google.common.cache.CacheBuilder;
-import org.apache.ratis.util.CollectionUtils;
-import org.apache.ratis.util.JavaUtils;
-import org.apache.ratis.util.MemoizedSupplier;
-import org.apache.ratis.util.TimeDuration;
-import org.apache.ratis.util.TimeoutScheduler;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-/** A client who sends requests to a raft service. */
-public final class RaftClientImpl implements RaftClient {
-  private static final Cache<RaftGroupId, RaftPeerId> LEADER_CACHE = CacheBuilder.newBuilder()
-      .expireAfterAccess(60, TimeUnit.SECONDS)
-      .maximumSize(1024)
-      .build();
-
-  public abstract static class PendingClientRequest {
-    private final long creationTimeInMs = System.currentTimeMillis();
-    private final CompletableFuture<RaftClientReply> replyFuture = new CompletableFuture<>();
-    private final AtomicInteger attemptCount = new AtomicInteger();
-    private final Map<Class<?>, Integer> exceptionCount = new ConcurrentHashMap<>();
-
-    public abstract RaftClientRequest newRequestImpl();
-
-    final RaftClientRequest newRequest() {
-      attemptCount.incrementAndGet();
-      return newRequestImpl();
-    }
-
-    CompletableFuture<RaftClientReply> getReplyFuture() {
-      return replyFuture;
-    }
-
-    public int getAttemptCount() {
-      return attemptCount.get();
-    }
-
-    int incrementExceptionCount(Throwable t) {
-      return t != null ? exceptionCount.compute(t.getClass(), (k, v) -> v != null ? v + 1 : 1) : 0;
-    }
-
-    public int getExceptionCount(Throwable t) {
-      return t != null ? Optional.ofNullable(exceptionCount.get(t.getClass())).orElse(0) : 0;
-    }
-
-    public boolean isRequestTimeout(TimeDuration timeout) {
-      if (timeout == null) {
-        return false;
-      }
-      return System.currentTimeMillis() - creationTimeInMs > timeout.toLong(TimeUnit.MILLISECONDS);
-    }
-  }
-
-  static class RaftPeerList implements Iterable<RaftPeer> {
-    private final AtomicReference<List<RaftPeer>> list = new AtomicReference<>();
-
-    @Override
-    public Iterator<RaftPeer> iterator() {
-      return list.get().iterator();
-    }
-
-    void set(Collection<RaftPeer> newPeers) {
-      list.set(Collections.unmodifiableList(new ArrayList<>(newPeers)));
-    }
-  }
-
-  private final ClientId clientId;
-  private final RaftClientRpc clientRpc;
-  private final RaftPeerList peers = new RaftPeerList();
-  private final RaftGroupId groupId;
-  private final RetryPolicy retryPolicy;
-
-  private volatile RaftPeerId leaderId;
-
-  private final TimeoutScheduler scheduler = TimeoutScheduler.getInstance();
-
-  private final Supplier<OrderedAsync> orderedAsync;
-  private final Supplier<AsyncImpl> asyncApi;
-  private final Supplier<BlockingImpl> blockingApi;
-  private final Supplier<MessageStreamImpl> messageStreamApi;
-  private final MemoizedSupplier<DataStreamApi> dataStreamApi;
-
-  private final Supplier<AdminImpl> adminApi;
-  private final ConcurrentMap<RaftPeerId, GroupManagementImpl> groupManagmenets = new ConcurrentHashMap<>();
-  private final ConcurrentMap<RaftPeerId, SnapshotManagementApi> snapshotManagemenet = new ConcurrentHashMap<>();
-
-  RaftClientImpl(ClientId clientId, RaftGroup group, RaftPeerId leaderId, RaftPeer primaryDataStreamServer,
-      RaftClientRpc clientRpc, RaftProperties properties, RetryPolicy retryPolicy) {
-    this.clientId = clientId;
-    this.peers.set(group.getPeers());
-    this.groupId = group.getGroupId();
-
-    if (leaderId == null) {
-      final RaftPeerId cached = LEADER_CACHE.getIfPresent(groupId);
-      if (cached != null && group.getPeer(cached) != null) {
-        leaderId = cached;
-      }
-    }
-    this.leaderId = leaderId != null? leaderId : getHighestPriorityPeerId();
-    this.retryPolicy = Objects.requireNonNull(retryPolicy, "retry policy can't be null");
-
-    clientRpc.addRaftPeers(group.getPeers());
-    this.clientRpc = clientRpc;
-
-    this.orderedAsync = JavaUtils.memoize(() -> OrderedAsync.newInstance(this, properties));
-    this.messageStreamApi = JavaUtils.memoize(() -> MessageStreamImpl.newInstance(this, properties));
-    this.asyncApi = JavaUtils.memoize(() -> new AsyncImpl(this));
-    this.blockingApi = JavaUtils.memoize(() -> new BlockingImpl(this));
-    this.dataStreamApi = JavaUtils.memoize(() -> DataStreamClient.newBuilder()
-        .setClientId(clientId)
-        .setRaftGroupId(groupId)
-        .setDataStreamServer(primaryDataStreamServer)
-        .setProperties(properties)
-        .build());
-    this.adminApi = JavaUtils.memoize(() -> new AdminImpl(this));
-  }
-
-  public RaftPeerId getLeaderId() {
-    return leaderId;
-  }
-
-  RaftGroupId getGroupId() {
-    return groupId;
-  }
-
-  private RaftPeerId getHighestPriorityPeerId() {
-    int maxPriority = Integer.MIN_VALUE;
-    RaftPeerId highestPriorityPeerId = null;
-    for (RaftPeer peer : peers) {
-      if (maxPriority < peer.getPriority()) {
-        maxPriority = peer.getPriority();
-        highestPriorityPeerId = peer.getId();
-      }
-    }
-
-    return highestPriorityPeerId;
-  }
-
-  @Override
-  public ClientId getId() {
-    return clientId;
-  }
-
-  RetryPolicy getRetryPolicy() {
-    return retryPolicy;
-  }
-
-  TimeDuration getEffectiveSleepTime(Throwable t, TimeDuration sleepDefault) {
-    return t instanceof NotLeaderException && ((NotLeaderException) t).getSuggestedLeader() != null ?
-        TimeDuration.ZERO : sleepDefault;
-  }
-
-  TimeoutScheduler getScheduler() {
-    return scheduler;
-  }
-
-  OrderedAsync getOrderedAsync() {
-    return orderedAsync.get();
-  }
-
-  RaftClientRequest newRaftClientRequest(
-      RaftPeerId server, long callId, Message message, RaftClientRequest.Type type,
-      SlidingWindowEntry slidingWindowEntry) {
-    final RaftClientRequest.Builder b = RaftClientRequest.newBuilder();
-    if (server != null) {
-      b.setServerId(server);
-    } else {
-      b.setLeaderId(leaderId);
-    }
-    return b.setClientId(clientId)
-        .setGroupId(groupId)
-        .setCallId(callId)
-        .setMessage(message)
-        .setType(type)
-        .setSlidingWindowEntry(slidingWindowEntry)
-        .build();
-  }
-
-  @Override
-  public AdminImpl admin() {
-    return adminApi.get();
-  }
-
-  @Override
-  public GroupManagementImpl getGroupManagementApi(RaftPeerId server) {
-    return groupManagmenets.computeIfAbsent(server, id -> new GroupManagementImpl(id, this));
-  }
-
-  @Override
-  public SnapshotManagementApi getSnapshotManagementApi() {
-    return JavaUtils.memoize(() -> new SnapshotManagementImpl(null, this)).get();
-  }
-
-  @Override
-  public SnapshotManagementApi getSnapshotManagementApi(RaftPeerId server) {
-    return snapshotManagemenet.computeIfAbsent(server, id -> new SnapshotManagementImpl(id, this));
-  }
-
-  @Override
-  public BlockingImpl io() {
-    return blockingApi.get();
-  }
-
-  @Override
-  public AsyncImpl async() {
-    return asyncApi.get();
-  }
-
-  @Override
-  public MessageStreamImpl getMessageStreamApi() {
-    return messageStreamApi.get();
-  }
-
-  @Override
-  public DataStreamApi getDataStreamApi() {
-    return dataStreamApi.get();
-  }
-
-  Throwable noMoreRetries(ClientRetryEvent event) {
-    final int attemptCount = event.getAttemptCount();
-    final Throwable throwable = event.getCause();
-    if (attemptCount == 1 && throwable != null) {
-      return throwable;
-    }
-    return new RaftRetryFailureException(event.getRequest(), attemptCount, retryPolicy, throwable);
-  }
-
-  RaftClientReply handleReply(RaftClientRequest request, RaftClientReply reply) {
-    if (request.isToLeader() && reply != null && reply.getException() == null) {
-      LEADER_CACHE.put(reply.getRaftGroupId(), reply.getServerId());
-    }
-    return reply;
-  }
-
-  static <E extends Throwable> RaftClientReply handleRaftException(
-      RaftClientReply reply, Function<RaftException, E> converter) throws E {
-    if (reply != null) {
-      final RaftException e = reply.getException();
-      if (e != null) {
-        throw converter.apply(e);
-      }
-    }
-    return reply;
-  }
-
-  /**
-   * @return null if the reply is null or it has
-   * {@link NotLeaderException} or {@link LeaderNotReadyException}
-   * otherwise return the same reply.
-   */
-  RaftClientReply handleLeaderException(RaftClientRequest request, RaftClientReply reply) {
-    if (reply == null || reply.getException() instanceof LeaderNotReadyException) {
-      return null;
-    }
-    final NotLeaderException nle = reply.getNotLeaderException();
-    if (nle == null) {
-      return reply;
-    }
-    return handleNotLeaderException(request, nle, null);
-  }
-
-  RaftClientReply handleNotLeaderException(RaftClientRequest request, NotLeaderException nle,
-      Consumer<RaftClientRequest> handler) {
-    refreshPeers(nle.getPeers());
-    final RaftPeerId newLeader = nle.getSuggestedLeader() == null ? null
-        : nle.getSuggestedLeader().getId();
-    handleIOException(request, nle, newLeader, handler);
-    return null;
-  }
-
-  private void refreshPeers(Collection<RaftPeer> newPeers) {
-    if (newPeers != null && newPeers.size() > 0) {
-      peers.set(newPeers);
-      // also refresh the rpc proxies for these peers
-      clientRpc.addRaftPeers(newPeers);
-    }
-  }
-
-  void handleIOException(RaftClientRequest request, IOException ioe) {
-    handleIOException(request, ioe, null, null);
-  }
-
-  void handleIOException(RaftClientRequest request, IOException ioe,
-      RaftPeerId newLeader, Consumer<RaftClientRequest> handler) {
-    LOG.debug("{}: suggested new leader: {}. Failed {} with {}",
-        clientId, newLeader, request, ioe);
-    if (LOG.isTraceEnabled()) {
-      LOG.trace("Stack trace", new Throwable("TRACE"));
-    }
-
-    Optional.ofNullable(handler).ifPresent(h -> h.accept(request));
-
-    if (ioe instanceof LeaderNotReadyException || ioe instanceof ResourceUnavailableException) {
-      return;
-    }
-
-    final RaftPeerId oldLeader = request.getServerId();
-    final RaftPeerId curLeader = leaderId;
-    final boolean stillLeader = oldLeader.equals(curLeader);
-    if (newLeader == null && stillLeader) {
-      newLeader = CollectionUtils.random(oldLeader,
-          CollectionUtils.as(peers, RaftPeer::getId));
-    }
-    LOG.debug("{}: oldLeader={},  curLeader={}, newLeader={}", clientId, oldLeader, curLeader, newLeader);
-
-    final boolean changeLeader = newLeader != null && stillLeader;
-    final boolean reconnect = changeLeader || clientRpc.shouldReconnect(ioe);
-    if (reconnect) {
-      if (changeLeader && oldLeader.equals(leaderId)) {
-        LOG.debug("{} {}: client change Leader from {} to {} ex={}", groupId,
-            clientId, oldLeader, newLeader, ioe.getClass().getName());
-        this.leaderId = newLeader;
-      }
-      clientRpc.handleException(oldLeader, ioe, true);
-    }
-  }
-
-  @Override
-  public RaftClientRpc getClientRpc() {
-    return clientRpc;
-  }
-
-  @Override
-  public void close() throws IOException {
-    scheduler.close();
-    clientRpc.close();
-    if (dataStreamApi.isInitialized()) {
-      dataStreamApi.get().close();
-    }
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftClientRpcWithProxy.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftClientRpcWithProxy.java
deleted file mode 100644
index 281ceb3..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftClientRpcWithProxy.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.client.RaftClientRpc;
-import org.apache.ratis.protocol.RaftPeer;
-import org.apache.ratis.protocol.RaftPeerId;
-import org.apache.ratis.util.PeerProxyMap;
-
-import java.io.Closeable;
-import java.util.Collection;
-
-/** An abstract {@link RaftClientRpc} implementation using {@link PeerProxyMap}. */
-public abstract class RaftClientRpcWithProxy<PROXY extends Closeable>
-    implements RaftClientRpc {
-  private final PeerProxyMap<PROXY> proxies;
-
-  protected RaftClientRpcWithProxy(PeerProxyMap<PROXY> proxies) {
-    this.proxies = proxies;
-  }
-
-  public PeerProxyMap<PROXY> getProxies() {
-    return proxies;
-  }
-
-  @Override
-  public void addRaftPeers(Collection<RaftPeer> servers) {
-    proxies.addRaftPeers(servers);
-  }
-
-  @Override
-  public boolean handleException(RaftPeerId serverId, Throwable t, boolean reconnect) {
-    return getProxies().handleException(serverId, t, reconnect);
-  }
-
-  @Override
-  public void close() {
-    proxies.close();
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftClientTestUtil.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftClientTestUtil.java
deleted file mode 100644
index ba00b8f..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftClientTestUtil.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.client.RaftClient;
-import org.apache.ratis.proto.RaftProtos.SlidingWindowEntry;
-import org.apache.ratis.protocol.ClientInvocationId;
-import org.apache.ratis.protocol.Message;
-import org.apache.ratis.protocol.RaftClientRequest;
-import org.apache.ratis.protocol.RaftPeerId;
-import org.apache.ratis.rpc.CallId;
-
-/** Interface for testing raft client. */
-public interface RaftClientTestUtil {
-  static void assertAsyncRequestSemaphore(RaftClient client, int expectedAvailablePermits, int expectedQueueLength) {
-    ((RaftClientImpl) client).getOrderedAsync().assertRequestSemaphore(expectedAvailablePermits, expectedQueueLength);
-  }
-
-  static ClientInvocationId getClientInvocationId(RaftClient client) {
-    return ClientInvocationId.valueOf(client.getId(), CallId.get());
-  }
-
-  static RaftClientRequest newRaftClientRequest(RaftClient client, RaftPeerId server,
-      long callId, Message message, RaftClientRequest.Type type, SlidingWindowEntry slidingWindowEntry) {
-    return ((RaftClientImpl)client).newRaftClientRequest(server, callId, message, type, slidingWindowEntry);
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftOutputStream.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftOutputStream.java
deleted file mode 100644
index 96251ae..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/RaftOutputStream.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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.client.RaftClient;
-import org.apache.ratis.protocol.Message;
-import org.apache.ratis.util.JavaUtils;
-import org.apache.ratis.util.ProtoUtils;
-import org.apache.ratis.util.SizeInBytes;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.LinkedList;
-import java.util.Queue;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Supplier;
-
-/** An {@link OutputStream} implementation using {@link org.apache.ratis.client.api.AsyncApi#send(Message)} API. */
-public class RaftOutputStream extends OutputStream {
-  private final Supplier<RaftClient> client;
-  private final AtomicBoolean closed = new AtomicBoolean();
-  private final Queue<CompletableFuture<Long>> flushFutures = new LinkedList<>();
-
-  private final byte[] buffer;
-  private int byteCount;
-  private long byteFlushed;
-
-  public RaftOutputStream(Supplier<RaftClient> clientSupplier, SizeInBytes bufferSize) {
-    this.client = JavaUtils.memoize(clientSupplier);
-    this.buffer = new byte[bufferSize.getSizeInt()];
-  }
-
-  private RaftClient getClient() {
-    return client.get();
-  }
-
-  @Override
-  public void write(int b) throws IOException {
-    checkClosed();
-    buffer[byteCount++] = (byte)b;
-    flushIfNecessary();
-  }
-
-  @Override
-  public void write(byte[] b, int off, int len) throws IOException {
-    checkClosed();
-    if (off < 0 || len < 0 || off > b.length - len) {
-      throw new ArrayIndexOutOfBoundsException();
-    }
-
-    for(int total = 0; total < len; ) {
-      final int toWrite = Math.min(len - total, buffer.length - byteCount);
-      System.arraycopy(b, off + total, buffer, byteCount, toWrite);
-      byteCount += toWrite;
-      total += toWrite;
-      flushIfNecessary();
-    }
-  }
-
-  private void flushIfNecessary() {
-    if (byteCount == buffer.length) {
-      flushAsync();
-    }
-  }
-
-  /** Non-blocking flush call */
-  private void flushAsync() {
-    final long pos = byteFlushed;
-    if (byteCount == 0) {
-      return;
-    }
-
-    final CompletableFuture<Long> f = getClient().async().send(
-        Message.valueOf(ProtoUtils.toByteString(buffer, 0, byteCount))
-    ).thenApply(reply -> RaftClientImpl.handleRaftException(reply, CompletionException::new)
-    ).thenApply(reply -> reply != null && reply.isSuccess()? pos: null);
-    flushFutures.offer(f);
-
-    byteFlushed += byteCount;
-    byteCount = 0;
-  }
-
-  /** Blocking flush call */
-  private void flushImpl() throws IOException {
-    final long pos = byteFlushed;
-    flushAsync();
-    for(; !flushFutures.isEmpty();) {
-      final Long flushed = flushFutures.poll().join();
-      if (flushed == null) {
-        throw new IOException("Failed to flush at position " + pos);
-      }
-    }
-  }
-
-  @Override
-  public void flush() throws IOException {
-    checkClosed();
-    flushImpl();
-  }
-
-  private void checkClosed() throws IOException {
-    if (closed.get()) {
-      throw new IOException(this + " was closed.");
-    }
-  }
-
-  @Override
-  public void close() throws IOException {
-    if (closed.compareAndSet(false, true)) {
-      flushImpl();
-      getClient().close();
-    }
-  }
-
-  @Override
-  public String toString() {
-    return JavaUtils.getClassSimpleName(getClass()) + "-" + getClient().getId() + ":byteFlushed=" + byteFlushed;
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/SnapshotManagementImpl.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/SnapshotManagementImpl.java
deleted file mode 100644
index 1762dc0..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/SnapshotManagementImpl.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * 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.client.api.SnapshotManagementApi;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftPeerId;
-import org.apache.ratis.protocol.SnapshotManagementRequest;
-import org.apache.ratis.rpc.CallId;
-
-import java.io.IOException;
-import java.util.Objects;
-import java.util.Optional;
-
-class SnapshotManagementImpl implements SnapshotManagementApi {
-  private final RaftClientImpl client;
-  private final RaftPeerId server;
-
-  SnapshotManagementImpl(RaftPeerId server, RaftClientImpl client) {
-    this.server = server;
-    this.client = Objects.requireNonNull(client, "client == null");
-  }
-
-  @Override
-  public RaftClientReply create(long timeoutMs) throws IOException {
-    final long callId = CallId.getAndIncrement();
-    return client.io().sendRequestWithRetry(() -> SnapshotManagementRequest.newCreate(client.getId(),
-        Optional.ofNullable(server).orElseGet(client::getLeaderId), client.getGroupId(), callId, timeoutMs));
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/impl/UnorderedAsync.java b/ratis-client/src/main/java/org/apache/ratis/client/impl/UnorderedAsync.java
deleted file mode 100644
index 432acce..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/impl/UnorderedAsync.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.client.retry.ClientRetryEvent;
-import org.apache.ratis.client.impl.RaftClientImpl.PendingClientRequest;
-import org.apache.ratis.protocol.ClientId;
-import org.apache.ratis.protocol.exceptions.GroupMismatchException;
-import org.apache.ratis.protocol.exceptions.NotLeaderException;
-import org.apache.ratis.protocol.RaftClientReply;
-import org.apache.ratis.protocol.RaftClientRequest;
-import org.apache.ratis.protocol.exceptions.RaftException;
-import org.apache.ratis.retry.RetryPolicy;
-import org.apache.ratis.rpc.CallId;
-import org.apache.ratis.util.JavaUtils;
-import org.apache.ratis.util.TimeDuration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
-import java.util.function.Supplier;
-
-/** Send unordered asynchronous requests to a raft service. */
-public interface UnorderedAsync {
-  Logger LOG = LoggerFactory.getLogger(UnorderedAsync.class);
-
-  class PendingUnorderedRequest extends PendingClientRequest {
-    private final Supplier<RaftClientRequest> requestConstructor;
-
-    PendingUnorderedRequest(Supplier<RaftClientRequest> requestConstructor) {
-      this.requestConstructor = requestConstructor;
-    }
-
-    @Override
-    public RaftClientRequest newRequestImpl() {
-      return requestConstructor.get();
-    }
-  }
-
-  static CompletableFuture<RaftClientReply> send(RaftClientRequest.Type type, RaftClientImpl client) {
-    final long callId = CallId.getAndIncrement();
-    final PendingClientRequest pending = new PendingUnorderedRequest(
-        () -> client.newRaftClientRequest(null, callId, null, type, null));
-    sendRequestWithRetry(pending, client);
-    return pending.getReplyFuture()
-        .thenApply(reply -> RaftClientImpl.handleRaftException(reply, CompletionException::new));
-  }
-
-  static void sendRequestWithRetry(PendingClientRequest pending, RaftClientImpl client) {
-    final CompletableFuture<RaftClientReply> f = pending.getReplyFuture();
-    if (f.isDone()) {
-      return;
-    }
-
-    final RaftClientRequest request = pending.newRequest();
-    final int attemptCount = pending.getAttemptCount();
-
-    final ClientId clientId = client.getId();
-    LOG.debug("{}: attempt #{} send~ {}", clientId, attemptCount, request);
-    client.getClientRpc().sendRequestAsyncUnordered(request).whenCompleteAsync((reply, e) -> {
-      try {
-        LOG.debug("{}: attempt #{} receive~ {}", clientId, attemptCount, reply);
-        final RaftException replyException = reply != null? reply.getException(): null;
-        reply = client.handleLeaderException(request, reply);
-        if (reply != null) {
-          client.handleReply(request, reply);
-          f.complete(reply);
-          return;
-        }
-
-        final Throwable cause = replyException != null ? replyException : e;
-        pending.incrementExceptionCount(cause);
-        final ClientRetryEvent event = new ClientRetryEvent(request, cause, pending);
-        RetryPolicy retryPolicy = client.getRetryPolicy();
-        final RetryPolicy.Action action = retryPolicy.handleAttemptFailure(event);
-        TimeDuration sleepTime = client.getEffectiveSleepTime(cause, action.getSleepTime());
-        if (!action.shouldRetry()) {
-          f.completeExceptionally(client.noMoreRetries(event));
-          return;
-        }
-
-        if (e != null) {
-          if (LOG.isTraceEnabled()) {
-            LOG.trace(clientId + ": attempt #" + attemptCount + " failed~ " + request, e);
-          } else {
-            LOG.debug("{}: attempt #{} failed {} with {}", clientId, attemptCount, request, e);
-          }
-          e = JavaUtils.unwrapCompletionException(e);
-
-          if (e instanceof IOException) {
-            if (e instanceof NotLeaderException) {
-              client.handleNotLeaderException(request, (NotLeaderException) e, null);
-            } else if (e instanceof GroupMismatchException) {
-              f.completeExceptionally(e);
-              return;
-            } else {
-              client.handleIOException(request, (IOException) e);
-            }
-          } else {
-            if (!client.getClientRpc().handleException(request.getServerId(), e, false)) {
-              f.completeExceptionally(e);
-              return;
-            }
-          }
-        }
-
-        LOG.debug("schedule retry for attempt #{}, policy={}, request={}", attemptCount, retryPolicy, request);
-        client.getScheduler().onTimeout(sleepTime,
-            () -> sendRequestWithRetry(pending, client), LOG, () -> clientId + ": Failed~ to retry " + request);
-      } catch (Exception ex) {
-        LOG.error(clientId + ": Failed " + request, ex);
-        f.completeExceptionally(ex);
-      }
-    });
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/retry/ClientRetryEvent.java b/ratis-client/src/main/java/org/apache/ratis/client/retry/ClientRetryEvent.java
deleted file mode 100644
index f0c38ef..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/retry/ClientRetryEvent.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.retry;
-
-import org.apache.ratis.client.impl.RaftClientImpl.PendingClientRequest;
-import org.apache.ratis.protocol.RaftClientRequest;
-import org.apache.ratis.retry.RetryPolicy;
-import org.apache.ratis.thirdparty.com.google.common.annotations.VisibleForTesting;
-import org.apache.ratis.util.JavaUtils;
-import org.apache.ratis.util.TimeDuration;
-
-/** An {@link RetryPolicy.Event} specific to client request failure. */
-public class ClientRetryEvent implements RetryPolicy.Event {
-  private final int attemptCount;
-  private final int causeCount;
-  private final RaftClientRequest request;
-  private final Throwable cause;
-  private PendingClientRequest pending;
-
-  @VisibleForTesting
-  public ClientRetryEvent(int attemptCount, RaftClientRequest request, Throwable cause) {
-    this(attemptCount, request, attemptCount, cause);
-  }
-
-  public ClientRetryEvent(RaftClientRequest request, Throwable t, PendingClientRequest pending) {
-    this(pending.getAttemptCount(), request, pending.getExceptionCount(t), t);
-    this.pending = pending;
-  }
-
-  private ClientRetryEvent(int attemptCount, RaftClientRequest request, int causeCount, Throwable cause) {
-    this.attemptCount = attemptCount;
-    this.causeCount = causeCount;
-    this.request = request;
-    this.cause = cause;
-  }
-
-  @Override
-  public int getAttemptCount() {
-    return attemptCount;
-  }
-
-  @Override
-  public int getCauseCount() {
-    return causeCount;
-  }
-
-  public RaftClientRequest getRequest() {
-    return request;
-  }
-
-  @Override
-  public Throwable getCause() {
-    return cause;
-  }
-
-  boolean isRequestTimeout(TimeDuration timeout) {
-    return pending != null && pending.isRequestTimeout(timeout);
-  }
-
-  @Override
-  public String toString() {
-    return JavaUtils.getClassSimpleName(getClass())
-        + ":attempt=" + attemptCount
-        + ",request=" + request
-        + ",cause=" + cause;
-  }
-}
diff --git a/ratis-client/src/main/java/org/apache/ratis/client/retry/RequestTypeDependentRetryPolicy.java b/ratis-client/src/main/java/org/apache/ratis/client/retry/RequestTypeDependentRetryPolicy.java
deleted file mode 100644
index aa6db4b..0000000
--- a/ratis-client/src/main/java/org/apache/ratis/client/retry/RequestTypeDependentRetryPolicy.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.retry;
-
-import org.apache.ratis.proto.RaftProtos;
-import org.apache.ratis.retry.RetryPolicies;
-import org.apache.ratis.retry.RetryPolicy;
-import org.apache.ratis.util.JavaUtils;
-import org.apache.ratis.util.Preconditions;
-import org.apache.ratis.util.TimeDuration;
-
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Supplier;
-
-/**
- * A {@link org.apache.ratis.protocol.RaftClientRequest.Type} dependent {@link RetryPolicy}
- * such that each type can be set to use an individual policy.
- * When the policy is not set for a particular type,
- * the {@link RetryPolicies#retryForeverNoSleep()} policy is used as the default.
- */
-public final class RequestTypeDependentRetryPolicy implements RetryPolicy {
-  public static class Builder {
-    private final EnumMap<RaftProtos.RaftClientRequestProto.TypeCase, RetryPolicy>
-        retryPolicyMap = new EnumMap<>(RaftProtos.RaftClientRequestProto.TypeCase.class);
-    private EnumMap<RaftProtos.RaftClientRequestProto.TypeCase, TimeDuration>
-        timeoutMap = new EnumMap<>(RaftProtos.RaftClientRequestProto.TypeCase.class);
-
-    /** Set the given policy for the given type. */
-    public Builder setRetryPolicy(RaftProtos.RaftClientRequestProto.TypeCase type, RetryPolicy policy) {
-      final RetryPolicy previous = retryPolicyMap.put(type, policy);
-      Preconditions.assertNull(previous, () -> "The retryPolicy for type " + type + " is already set to " + previous);
-      return this;
-    }
-
-    public Builder setTimeout(RaftProtos.RaftClientRequestProto.TypeCase type, TimeDuration timeout) {
-      final TimeDuration previous = timeoutMap.put(type, timeout);
-      Preconditions.assertNull(previous, () -> "The timeout for type " + type + " is already set to " + previous);
-      return this;
-    }
-
-    public RequestTypeDependentRetryPolicy build() {
-      return new RequestTypeDependentRetryPolicy(retryPolicyMap, timeoutMap);
-    }
-  }
-
-  public static Builder newBuilder() {
-    return new Builder();
-  }
-
-  private final Map<RaftProtos.RaftClientRequestProto.TypeCase, RetryPolicy> retryPolicyMap;
-  private final Map<RaftProtos.RaftClientRequestProto.TypeCase, TimeDuration> timeoutMap;
-  private final Supplier<String> myString;
-
-  private RequestTypeDependentRetryPolicy(
-      EnumMap<RaftProtos.RaftClientRequestProto.TypeCase, RetryPolicy> map,
-      EnumMap<RaftProtos.RaftClientRequestProto.TypeCase, TimeDuration> timeoutMap) {
-    this.retryPolicyMap = Collections.unmodifiableMap(map);
-    this.timeoutMap = timeoutMap;
-    this.myString = () -> {
-      final StringBuilder b = new StringBuilder(JavaUtils.getClassSimpleName(getClass())).append("{");
-      map.forEach((key, value) -> b.append(key).append("->").append(value).append(", "));
-      b.setLength(b.length() - 2);
-      return b.append("}").toString();
-    };
-  }
-
-  @Override
-  public Action handleAttemptFailure(Event event) {
-    if (!(event instanceof ClientRetryEvent)) {
-      return RetryPolicies.retryForeverNoSleep().handleAttemptFailure(event);
-    }
-    final ClientRetryEvent clientEvent = (ClientRetryEvent) event;
-    final TimeDuration timeout = timeoutMap.get(clientEvent.getRequest().getType().getTypeCase());
-    if (timeout != null && clientEvent.isRequestTimeout(timeout)) {
-      return NO_RETRY_ACTION;
-    }
-    return Optional.ofNullable(
-        retryPolicyMap.get(clientEvent.getRequest().getType().getTypeCase()))
-        .orElse(RetryPolicies.retryForeverNoSleep())
-        .handleAttemptFailure(event);
-  }
-
-  @Override
-  public String toString() {
-    return myString.get();
-  }
-}
diff --git a/ratis-common/pom.xml b/ratis-common/pom.xml
deleted file mode 100644
index 9c24c3f..0000000
--- a/ratis-common/pom.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?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</artifactId>
-    <groupId>org.apache.ratis</groupId>
-    <version>2.3.0-SNAPSHOT</version>
-  </parent>
-
-  <artifactId>ratis-common</artifactId>
-  <name>Apache Ratis Common</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.ratis</groupId>
-      <artifactId>ratis-thirdparty-misc</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.ratis</groupId>
-      <artifactId>ratis-proto</artifactId>
-    </dependency>
-
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>com.github.spotbugs</groupId>
-      <artifactId>spotbugs-annotations</artifactId>
-      <scope>provided</scope>
-      <optional>true</optional>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/ratis-common/src/main/conf/log4j.properties b/ratis-common/src/main/conf/log4j.properties
deleted file mode 100644
index 64c1922..0000000
--- a/ratis-common/src/main/conf/log4j.properties
+++ /dev/null
@@ -1,74 +0,0 @@
-# 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
diff --git a/ratis-common/src/main/java/org/apache/ratis/RaftConfigKeys.java b/ratis-common/src/main/java/org/apache/ratis/RaftConfigKeys.java
deleted file mode 100644
index 7c14a47..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/RaftConfigKeys.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * 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;
-
-import static org.apache.ratis.conf.ConfUtils.get;
-import static org.apache.ratis.conf.ConfUtils.printAll;
-import static org.apache.ratis.conf.ConfUtils.set;
-
-import org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.datastream.SupportedDataStreamType;
-import org.apache.ratis.rpc.RpcType;
-import org.apache.ratis.rpc.SupportedRpcType;
-
-import java.util.function.Consumer;
-
-public interface RaftConfigKeys {
-  String PREFIX = "raft";
-
-  interface Rpc {
-    String PREFIX = RaftConfigKeys.PREFIX + ".rpc";
-
-    String TYPE_KEY = PREFIX + ".type";
-    String TYPE_DEFAULT = SupportedRpcType.GRPC.name();
-
-    static RpcType type(RaftProperties properties, Consumer<String> logger) {
-      final String t = get(properties::get, TYPE_KEY, TYPE_DEFAULT, logger);
-      return RpcType.valueOf(t);
-    }
-
-    static void setType(RaftProperties properties, RpcType type) {
-      set(properties::set, TYPE_KEY, type.name());
-    }
-  }
-
-  interface DataStream {
-    String PREFIX = RaftConfigKeys.PREFIX + ".datastream";
-
-    String TYPE_KEY = PREFIX + ".type";
-    String TYPE_DEFAULT = SupportedDataStreamType.DISABLED.name();
-
-    static SupportedDataStreamType type(RaftProperties properties, Consumer<String> logger) {
-      final String t = get(properties::get, TYPE_KEY, TYPE_DEFAULT, logger);
-      return SupportedDataStreamType.valueOfIgnoreCase(t);
-    }
-
-    static void setType(RaftProperties properties, SupportedDataStreamType type) {
-      set(properties::set, TYPE_KEY, type.name());
-    }
-  }
-
-  static void main(String[] args) {
-    printAll(RaftConfigKeys.class);
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/conf/ConfUtils.java b/ratis-common/src/main/java/org/apache/ratis/conf/ConfUtils.java
deleted file mode 100644
index 1d7d9c5..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/conf/ConfUtils.java
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * 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.conf;
-
-import org.apache.ratis.thirdparty.com.google.common.base.Objects;
-import org.apache.ratis.util.NetUtils;
-import org.apache.ratis.util.SizeInBytes;
-import org.apache.ratis.util.TimeDuration;
-import org.apache.ratis.util.function.CheckedBiConsumer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.net.InetSocketAddress;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-import java.util.function.Consumer;
-
-public interface ConfUtils {
-  Logger LOG = LoggerFactory.getLogger(ConfUtils.class);
-
-  static <T> void logGet(String key, T value, T defaultValue, Consumer<String> logger) {
-    if (logger != null) {
-      logger.accept(String.format("%s = %s (%s)", key, value,
-          Objects.equal(value, defaultValue)? "default": "custom"));
-    }
-  }
-
-  static void logSet(String key, Object value) {
-    LOG.debug("set {} = {}", key, value);
-  }
-
-  static BiConsumer<String, Integer> requireMin(int min) {
-    return (key, value) -> {
-      if (value < min) {
-        throw new IllegalArgumentException(
-            key + " = " + value + " < min = " + min);
-      }
-    };
-  }
-
-  static BiConsumer<String, Integer> requireMax(int max) {
-    return (key, value) -> {
-      if (value > max) {
-        throw new IllegalArgumentException(
-            key + " = " + value + " > max = " + max);
-      }
-    };
-  }
-
-  static BiConsumer<String, Double> requireMax(double max) {
-    return (key, value) -> {
-      if (value > max) {
-        throw new IllegalArgumentException(
-            key + " = " + value + " > max = " + max);
-      }
-    };
-  }
-
-  static BiConsumer<String, Long> requireMin(SizeInBytes min) {
-    return requireMin(min.getSize());
-  }
-
-  static BiConsumer<String, Long> requireMin(long min) {
-    return (key, value) -> {
-      if (value < min) {
-        throw new IllegalArgumentException(
-            key + " = " + value + " < min = " + min);
-      }
-    };
-  }
-
-  static BiConsumer<String, SizeInBytes> requireMinSizeInByte(SizeInBytes min) {
-    return (key, value) -> {
-      if (value.getSize() < min.getSize()) {
-        throw new IllegalArgumentException(
-            key + " = " + value + " < min = " + min);
-      }
-    };
-  }
-
-  static BiConsumer<String, Long> requireMax(long max) {
-    return (key, value) -> {
-      if (value > max) {
-        throw new IllegalArgumentException(
-            key + " = " + value + " > max = " + max);
-      }
-    };
-  }
-
-  static BiConsumer<String, TimeDuration> requireNonNegativeTimeDuration() {
-    return (key, value) -> {
-      if (value.isNegative()) {
-        throw new IllegalArgumentException(
-            key + " = " + value + " is negative.");
-      }
-    };
-  }
-
-  static BiConsumer<String, TimeDuration> requirePositive() {
-    return (key, value) -> {
-      if (value.getDuration() <= 0) {
-        throw new IllegalArgumentException(
-            key + " = " + value + " is non-positive.");
-      }
-    };
-  }
-
-  static BiFunction<String, Long, Integer> requireInt() {
-    return (key, value) -> {
-      try {
-        return Math.toIntExact(value);
-      } catch (ArithmeticException ae) {
-        throw new IllegalArgumentException(
-            "Failed to cast " + key + " = " + value + " to int.", ae);
-      }
-    };
-  }
-
-  @SafeVarargs
-  static boolean getBoolean(
-      BiFunction<String, Boolean, Boolean> booleanGetter,
-      String key, boolean defaultValue, Consumer<String> logger, BiConsumer<String, Boolean>... assertions) {
-    return get(booleanGetter, key, defaultValue, logger, assertions);
-  }
-
-  @SafeVarargs
-  static int getInt(
-      BiFunction<String, Integer, Integer> integerGetter,
-      String key, int defaultValue, Consumer<String> logger, BiConsumer<String, Integer>... assertions) {
-    return get(integerGetter, key, defaultValue, logger, assertions);
-  }
-
-  @SafeVarargs
-  static long getLong(
-      BiFunction<String, Long, Long> longGetter,
-      String key, long defaultValue, Consumer<String> logger, BiConsumer<String, Long>... assertions) {
-    return get(longGetter, key, defaultValue, logger, assertions);
-  }
-
-  @SafeVarargs
-  static double getDouble(
-      BiFunction<String, Double, Double> doubleGetter,
-      String key, double defaultValue, Consumer<String> logger, BiConsumer<String, Double>... assertions) {
-    return get(doubleGetter, key, defaultValue, logger, assertions);
-  }
-
-  @SafeVarargs
-  static File getFile(
-      BiFunction<String, File, File> fileGetter,
-      String key, File defaultValue, Consumer<String> logger, BiConsumer<String, File>... assertions) {
-    return get(fileGetter, key, defaultValue, logger, assertions);
-  }
-
-  @SafeVarargs
-  static List<File> getFiles(
-      BiFunction<String, List<File>, List<File>> fileGetter,
-      String key, List<File> defaultValue, Consumer<String> logger, BiConsumer<String, List<File>>... assertions) {
-    return get(fileGetter, key, defaultValue, logger, assertions);
-  }
-
-
-  @SafeVarargs
-  static SizeInBytes getSizeInBytes(
-      BiFunction<String, SizeInBytes, SizeInBytes> getter,
-      String key, SizeInBytes defaultValue, Consumer<String> logger, BiConsumer<String, SizeInBytes>... assertions) {
-    final SizeInBytes value = get(getter, key, defaultValue, logger, assertions);
-    requireMin(0L).accept(key, value.getSize());
-    return value;
-  }
-
-  @SafeVarargs
-  static TimeDuration getTimeDuration(
-      BiFunction<String, TimeDuration, TimeDuration> getter,
-      String key, TimeDuration defaultValue, Consumer<String> logger, BiConsumer<String, TimeDuration>... assertions) {
-    final TimeDuration value = get(getter, key, defaultValue, logger, assertions);
-    requireNonNegativeTimeDuration().accept(key, value);
-    return value;
-  }
-
-  @SafeVarargs
-  static <T> T get(BiFunction<String, T, T> getter,
-      String key, T defaultValue, Consumer<String> logger, BiConsumer<String, T>... assertions) {
-    final T value = getter.apply(key, defaultValue);
-    logGet(key, value, defaultValue, logger);
-    Arrays.asList(assertions).forEach(a -> a.accept(key, value));
-    return value;
-  }
-
-  static InetSocketAddress getInetSocketAddress(
-      BiFunction<String, String, String> stringGetter,
-      String key, String defaultValue, Consumer<String> logger) {
-    return NetUtils.createSocketAddr(get(stringGetter, key, defaultValue, logger));
-  }
-
-  @SafeVarargs
-  static void setBoolean(
-      BiConsumer<String, Boolean> booleanSetter, String key, boolean value,
-      BiConsumer<String, Boolean>... assertions) {
-    set(booleanSetter, key, value, assertions);
-  }
-
-  @SafeVarargs
-  static void setInt(
-      BiConsumer<String, Integer> integerSetter, String key, int value,
-      BiConsumer<String, Integer>... assertions) {
-    set(integerSetter, key, value, assertions);
-  }
-
-  @SafeVarargs
-  static void setLong(
-      BiConsumer<String, Long> longSetter, String key, long value,
-      BiConsumer<String, Long>... assertions) {
-    set(longSetter, key, value, assertions);
-  }
-
-  @SafeVarargs
-  static void setDouble(
-      BiConsumer<String, Double> doubleSetter, String key, double value,
-      BiConsumer<String, Double>... assertions) {
-    set(doubleSetter, key, value, assertions);
-  }
-
-  @SafeVarargs
-  static void setFile(
-      BiConsumer<String, File> fileSetter, String key, File value,
-      BiConsumer<String, File>... assertions) {
-    set(fileSetter, key, value, assertions);
-  }
-
-  @SafeVarargs
-  static void setFiles(
-      BiConsumer<String, List<File>> fileSetter, String key, List<File> value,
-      BiConsumer<String, List<File>>... assertions) {
-    set(fileSetter, key, value, assertions);
-  }
-
-  @SafeVarargs
-  static void setSizeInBytes(
-      BiConsumer<String, String> stringSetter, String key, SizeInBytes value,
-      BiConsumer<String, Long>... assertions) {
-    final long v = value.getSize();
-    Arrays.asList(assertions).forEach(a -> a.accept(key, v));
-    set(stringSetter, key, value.getInput());
-  }
-
-  @SafeVarargs
-  static void setTimeDuration(
-      BiConsumer<String, TimeDuration> timeDurationSetter, String key, TimeDuration value,
-      BiConsumer<String, TimeDuration>... assertions) {
-    set(timeDurationSetter, key, value, assertions);
-  }
-
-  @SafeVarargs
-  static <T> void set(
-      BiConsumer<String, T> setter, String key, T value,
-      BiConsumer<String, T>... assertions) {
-    Arrays.asList(assertions).forEach(a -> a.accept(key, value));
-    setter.accept(key, value);
-    logSet(key, value);
-  }
-
-  static void printAll(Class<?> confClass) {
-    ConfUtils.printAll(confClass, System.out::println);
-  }
-
-  static void printAll(Class<?> confClass, Consumer<Object> out) {
-    if (confClass.isEnum()) {
-      return;
-    }
-    out.accept("");
-    out.accept("******* " + confClass + " *******");
-    Arrays.asList(confClass.getDeclaredFields())
-        .forEach(f -> printField(confClass, out, f));
-    Arrays.asList(confClass.getClasses())
-        .forEach(c -> printAll(c, s -> out.accept("  " + s)));
-  }
-
-  static void printField(Class<?> confClass, Consumer<Object> out, Field f) {
-    final int modifiers = f.getModifiers();
-    if (!Modifier.isStatic(modifiers)) {
-      throw new IllegalStateException("Found non-static field " + f);
-    }
-    if (!Modifier.isFinal(modifiers)) {
-      throw new IllegalStateException("Found non-final field " + f);
-    }
-    if (printKey(confClass, out, f, "KEY", "DEFAULT", ConfUtils::append)) {
-      return;
-    }
-    if (printKey(confClass, out, f, "PARAMETER", "CLASS",
-        (b, classField) -> b.append(classField.get(null)))) {
-      return;
-    }
-    final String fieldName = f.getName();
-    if ("LOG".equals(fieldName)) {
-      return;
-    }
-    if (!"PREFIX".equals(fieldName)) {
-      throw new IllegalStateException("Unexpected field: " + fieldName);
-    }
-    try {
-      out.accept("constant: " + fieldName + " = " + f.get(null));
-    } catch (IllegalAccessException e) {
-      throw new IllegalStateException("Failed to access " + f, e);
-    }
-  }
-
-  static void append(StringBuilder b, Field defaultField) throws IllegalAccessException {
-    b.append(defaultField.getGenericType().getTypeName());
-
-    final Class<?> type = defaultField.getType();
-    if (type.isEnum()) {
-      b.append(" enum[");
-      for(Object e : defaultField.getType().getEnumConstants()) {
-        b.append(e).append(", ");
-      }
-      b.setLength(b.length() - 2);
-      b.append("]");
-    }
-
-    b.append(", ").append("default=").append(defaultField.get(null));
-  }
-
-  static boolean printKey(
-      Class<?> confClass, Consumer<Object> out, Field f, String key, String defaultName,
-      CheckedBiConsumer<StringBuilder, Field, IllegalAccessException> processDefault) {
-    final String fieldName = f.getName();
-    if (fieldName.endsWith("_" + defaultName)) {
-      return true;
-    }
-    if (!fieldName.endsWith("_" + key)) {
-      return false;
-    }
-    final StringBuilder b = new StringBuilder();
-    final Object keyName;
-    try {
-      keyName = f.get(null);
-      b.append(key.toLowerCase()).append(": ").append(keyName);
-    } catch (IllegalAccessException e) {
-      throw new IllegalStateException("Failed to access " + fieldName, e);
-    }
-    assertKey(fieldName, key.length(), keyName, confClass);
-    final String defaultFieldName = fieldName.substring(0, fieldName.length() - key.length()) + defaultName;
-    b.append(" (");
-    try {
-      final Field defaultField = confClass.getDeclaredField(defaultFieldName);
-      processDefault.accept(b, defaultField);
-    } catch (NoSuchFieldException e) {
-      throw new IllegalStateException(defaultName + " not found for field " + f, e);
-    } catch (IllegalAccessException e) {
-      throw new IllegalStateException("Failed to access " + defaultFieldName, e);
-    }
-    b.append(")");
-
-    out.accept(b);
-    return true;
-  }
-
-  static String normalizeName(String name) {
-    return name.replaceAll("[._-]", "").toLowerCase();
-  }
-
-  static void assertKey(String fieldName, int toTruncate, Object keyName, Class<?> confClass) {
-    final String normalizedFieldName = normalizeName(fieldName.substring(0, fieldName.length() - toTruncate));
-    final String normalizedKeyName = normalizeName("" + keyName);
-
-    if (!normalizedKeyName.endsWith(normalizedFieldName)) {
-      throw new IllegalStateException("Field and key mismatched: fieldName = " + fieldName + " (" + normalizedFieldName
-          + ") but keyName = " + keyName + " (" + normalizedKeyName + ")");
-    }
-
-    // check getter and setter methods
-    boolean getter = false;
-    boolean setter = false;
-    for(Method m : confClass.getMethods()) {
-      final String name = m.getName();
-      if (name.equalsIgnoreCase(normalizedFieldName)) {
-        getter = true;
-      }
-      if (name.equalsIgnoreCase("set" + normalizedFieldName)) {
-        setter = true;
-      }
-    }
-    if (!getter) {
-      throw new IllegalStateException("Getter method not found for " + fieldName);
-    }
-    if (!setter) {
-      throw new IllegalStateException("Setter method not found for " + fieldName);
-    }
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/conf/Parameters.java b/ratis-common/src/main/java/org/apache/ratis/conf/Parameters.java
deleted file mode 100644
index f562d24..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/conf/Parameters.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * 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.conf;
-
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * A generic parameter map.
- * The difference between this class and {@link RaftProperties} is that
- * {@link RaftProperties} is {@link String} based, i.e. properties are strings,
- * while this class is {@link Object} based, i.e. parameters can be any objects.
- *
- * Null keys or null values are not supported.
- *
- * This class is thread safe.
- */
-public class Parameters {
-  private final Map<String, Object> map = new ConcurrentHashMap<>();
-
-  /** Put the key-value pair to the map. */
-  public <T> T put(String key, T value, Class<T> valueClass) {
-    return valueClass.cast(map.put(
-        Objects.requireNonNull(key, "key is null"),
-        Objects.requireNonNull(value, () -> "value is null, key=" + key)));
-  }
-
-  /**
-   * @param <T> The value type.
-   * @return The value mapped to the given key;
-   *         or return null if the key does not map to any value.
-   * @throws IllegalArgumentException if the mapped value is not an instance of the given class.
-   */
-  public <T> T get(String key, Class<T> valueClass) {
-    final Object value = map.get(Objects.requireNonNull(key, "key is null"));
-    return valueClass.cast(value);
-  }
-
-  /**
-   * The same as {@link #get(String, Class)} except that this method throws
-   * a {@link NullPointerException} if the key does not map to any value.
-   */
-  public <T> T getNonNull(String key, Class<T> valueClass) {
-    final T value = get(key, valueClass);
-    if (value != null) {
-      return value;
-    }
-    throw new NullPointerException("The key " + key + " does not map to any value.");
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/conf/RaftProperties.java b/ratis-common/src/main/java/org/apache/ratis/conf/RaftProperties.java
deleted file mode 100644
index db5649c..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/conf/RaftProperties.java
+++ /dev/null
@@ -1,1429 +0,0 @@
-/**
- * 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.conf;
-
-import org.apache.ratis.util.ReflectionUtils;
-import org.apache.ratis.util.SizeInBytes;
-import org.apache.ratis.util.StringUtils;
-import org.apache.ratis.util.TimeDuration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Element;
-import org.w3c.dom.Document;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Text;
-import org.xml.sax.SAXException;
-
-import javax.xml.XMLConstants;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.net.JarURLConnection;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Properties;
-import java.util.Set;
-import java.util.WeakHashMap;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.TimeUnit;
-import java.util.function.BiFunction;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-import java.util.stream.Collectors;
-
-/**
- * Provides access to configuration parameters. The current implementation is a
- * simplified version of hadoop's Configuration.
- */
-public class RaftProperties {
-  private static final Logger LOG = LoggerFactory.getLogger(RaftProperties.class);
-
-  private static class Resource {
-    private final Object resource;
-    private final String name;
-
-    Resource(Object resource) {
-      this(resource, resource.toString());
-    }
-
-    Resource(Object resource, String name) {
-      this.resource = resource;
-      this.name = name;
-    }
-
-    public String getName(){
-      return name;
-    }
-
-    public Object getResource() {
-      return resource;
-    }
-
-    @Override
-    public String toString() {
-      return name;
-    }
-  }
-
-  /**
-   * List of configuration resources.
-   */
-  private ArrayList<Resource> resources = new ArrayList<>();
-
-  /**
-   * The value reported as the setting resource when a key is set
-   * by code rather than a file resource by dumpConfiguration.
-   */
-  static final String UNKNOWN_RESOURCE = "Unknown";
-
-  /**
-   * List of configuration parameters marked <b>final</b>.
-   */
-  private Set<String> finalParameters = Collections.newSetFromMap(
-      new ConcurrentHashMap<String, Boolean>());
-
-  private boolean loadDefaults = true;
-
-  /**
-   * Configuration objects
-   */
-  private static final WeakHashMap<RaftProperties, Object> REGISTRY = new WeakHashMap<>();
-
-  /**
-   * List of default Resources. Resources are loaded in the order of the list
-   * entries
-   */
-  private static final CopyOnWriteArrayList<String> DEFAULT_RESOURCES =
-    new CopyOnWriteArrayList<>();
-
-  /**
-   * Stores the mapping of key to the resource which modifies or loads
-   * the key most recently
-   */
-  private Map<String, String[]> updatingResource;
-
-  private Properties properties;
-  private Properties overlay;
-
-  /** A new configuration. */
-  public RaftProperties() {
-    this(true);
-  }
-
-  /** A new configuration where the behavior of reading from the default
-   * resources can be turned off.
-   *
-   * If the parameter {@code loadDefaults} is false, the new instance
-   * will not load resources from the default files.
-   * @param loadDefaults specifies whether to load from the default files
-   */
-  public RaftProperties(boolean loadDefaults) {
-    this.loadDefaults = loadDefaults;
-    updatingResource = new ConcurrentHashMap<>();
-    synchronized(RaftProperties.class) {
-      REGISTRY.put(this, null);
-    }
-  }
-
-  /**
-   * A new RaftProperties with the same settings cloned from another.
-   *
-   * @param other the RaftProperties from which to clone settings.
-   */
-  @SuppressWarnings("unchecked")
-  public RaftProperties(RaftProperties other) {
-    this.resources = (ArrayList<Resource>) other.resources.clone();
-    synchronized(other) {
-      if (other.properties != null) {
-        this.properties = (Properties)other.properties.clone();
-      }
-
-      if (other.overlay!=null) {
-        this.overlay = (Properties)other.overlay.clone();
-      }
-
-      this.updatingResource = new ConcurrentHashMap<>(other.updatingResource);
-      this.finalParameters = Collections.newSetFromMap(
-          new ConcurrentHashMap<String, Boolean>());
-      this.finalParameters.addAll(other.finalParameters);
-    }
-
-    synchronized(RaftProperties.class) {
-      REGISTRY.put(this, null);
-    }
-    this.loadDefaults = other.loadDefaults;
-  }
-
-  /**
-   * Add a default resource. Resources are loaded in the order of the resources
-   * added.
-   * @param name file name. File should be present in the classpath.
-   */
-  public static synchronized void addDefaultResource(String name) {
-    if(!DEFAULT_RESOURCES.contains(name)) {
-      DEFAULT_RESOURCES.add(name);
-      REGISTRY.keySet().stream().filter(conf -> conf.loadDefaults)
-          .forEach(RaftProperties::reloadConfiguration);
-    }
-  }
-
-  /**
-   * Add a configuration resource.
-   *
-   * The properties of this resource will override properties of previously
-   * added resources, unless they were marked <a href="#Final">final</a>.
-   *
-   * @param name resource to be added, the classpath is examined for a file
-   *             with that name.
-   */
-  public void addResource(String name) {
-    addResourceObject(new Resource(name));
-  }
-
-
-  public void addResource(URL path) {
-    addResourceObject(new Resource(path));
-  }
-
-  /**
-   * Add a configuration resource.
-   *
-   * The properties of this resource will override properties of previously
-   * added resources, unless they were marked <a href="#Final">final</a>.
-   *
-   * WARNING: The contents of the InputStream will be cached, by this method.
-   * So use this sparingly because it does increase the memory consumption.
-   *
-   * @param in InputStream to deserialize the object from. In will be read from
-   * when a get or set is called next.  After it is read the stream will be
-   * closed.
-   */
-  public void addResource(InputStream in) {
-    addResourceObject(new Resource(in));
-  }
-
-  /**
-   * Add a configuration resource.
-   *
-   * The properties of this resource will override properties of previously
-   * added resources, unless they were marked <a href="#Final">final</a>.
-   *
-   * @param in InputStream to deserialize the object from.
-   * @param name the name of the resource because InputStream.toString is not
-   * very descriptive some times.
-   */
-  public void addResource(InputStream in, String name) {
-    addResourceObject(new Resource(in, name));
-  }
-
-  /**
-   * Add a configuration resource.
-   *
-   * The properties of this resource will override properties of previously
-   * added resources, unless they were marked <a href="#Final">final</a>.
-   *
-   * @param conf Configuration object from which to load properties
-   */
-  public void addResource(RaftProperties conf) {
-    addResourceObject(new Resource(conf.getProps()));
-  }
-
-
-
-  /**
-   * Reload configuration from previously added resources.
-   *
-   * This method will clear all the configuration read from the added
-   * resources, and final parameters. This will make the resources to
-   * be read again before accessing the values. Values that are added
-   * via set methods will overlay values read from the resources.
-   */
-  public synchronized void reloadConfiguration() {
-    properties = null;                            // trigger reload
-    finalParameters.clear();                      // clear site-limits
-  }
-
-  private synchronized void addResourceObject(Resource resource) {
-    resources.add(resource);                      // add to resources
-    reloadConfiguration();
-  }
-
-  private static final int MAX_SUBST = 20;
-
-  private static final int SUB_START_IDX = 0;
-  private static final int SUB_END_IDX = SUB_START_IDX + 1;
-
-  /**
-   * This is a manual implementation of the following regex
-   * "\\$\\{[^\\}\\$\u0020]+\\}".
-   *
-   * @param eval a string that may contain variables requiring expansion.
-   * @return a 2-element int array res such that
-   * eval.substring(res[0], res[1]) is "var" for the left-most occurrence of
-   * ${var} in eval. If no variable is found -1, -1 is returned.
-   */
-  private static int[] findSubVariable(String eval) {
-    int[] result = {-1, -1};
-
-    int matchStart;
-    int leftBrace;
-
-    // scanning for a brace first because it's less frequent than $
-    // that can occur in nested class names
-    //
-    match_loop:
-    for (matchStart = 1, leftBrace = eval.indexOf('{', matchStart);
-         // minimum left brace position (follows '$')
-         leftBrace > 0
-         // right brace of a smallest valid expression "${c}"
-         && leftBrace + "{c".length() < eval.length();
-         leftBrace = eval.indexOf('{', matchStart)) {
-      int matchedLen = 0;
-      if (eval.charAt(leftBrace - 1) == '$') {
-        int subStart = leftBrace + 1; // after '{'
-        for (int i = subStart; i < eval.length(); i++) {
-          switch (eval.charAt(i)) {
-            case '}':
-              if (matchedLen > 0) { // match
-                result[SUB_START_IDX] = subStart;
-                result[SUB_END_IDX] = subStart + matchedLen;
-                break match_loop;
-              }
-              // fall through to skip 1 char
-            case ' ':
-            case '$':
-              matchStart = i + 1;
-              continue match_loop;
-            default:
-              matchedLen++;
-          }
-        }
-        // scanned from "${"  to the end of eval, and no reset via ' ', '$':
-        //    no match!
-        break;
-      } else {
-        // not a start of a variable
-        //
-        matchStart = leftBrace + 1;
-      }
-    }
-    return result;
-  }
-
-  /**
-   * Attempts to repeatedly expand the value {@code expr} by replacing the
-   * left-most substring of the form "${var}" in the following precedence order
-   * <ol>
-   *   <li>by the value of the environment variable "var" if defined</li>
-   *   <li>by the value of the Java system property "var" if defined</li>
-   *   <li>by the value of the configuration key "var" if defined</li>
-   * </ol>
-   *
-   * If var is unbounded the current state of expansion "prefix${var}suffix" is
-   * returned.
-   *
-   * If a cycle is detected: replacing var1 requires replacing var2 ... requires
-   * replacing var1, i.e., the cycle is shorter than
-   * {@link RaftProperties#MAX_SUBST} then the original expr is returned.
-   *
-   * @param expr the literal value of a config key
-   * @return null if expr is null, otherwise the value resulting from expanding
-   * expr using the algorithm above.
-   * @throws IllegalArgumentException when more than
-   * {@link RaftProperties#MAX_SUBST} replacements are required
-   */
-  private String substituteVars(String expr) {
-    if (expr == null) {
-      return null;
-    }
-    String eval = expr;
-    Set<String> evalSet = null;
-    for(int s = 0; s < MAX_SUBST; s++) {
-      final int[] varBounds = findSubVariable(eval);
-      if (varBounds[SUB_START_IDX] == -1) {
-        return eval;
-      }
-      final String var = eval.substring(varBounds[SUB_START_IDX],
-          varBounds[SUB_END_IDX]);
-      String val = null;
-      try {
-        if (var.startsWith("env.") && 4 < var.length()) {
-          String v = var.substring(4);
-          int i = 0;
-          for (; i < v.length(); i++) {
-            char c = v.charAt(i);
-            if (c == ':' && i < v.length() - 1 && v.charAt(i + 1) == '-') {
-              val = getenv(v.substring(0, i));
-              if (val == null || val.length() == 0) {
-                val = v.substring(i + 2);
-              }
-              break;
-            } else if (c == '-') {
-              val = getenv(v.substring(0, i));
-              if (val == null) {
-                val = v.substring(i + 1);
-              }
-              break;
-            }
-          }
-          if (i == v.length()) {
-            val = getenv(v);
-          }
-        } else {
-          val = getProperty(var);
-        }
-      } catch(SecurityException se) {
-        LOG.warn("Unexpected SecurityException in Configuration", se);
-      }
-      if (val == null) {
-        val = getRaw(var);
-      }
-      if (val == null) {
-        return eval; // return literal ${var}: var is unbound
-      }
-
-      // prevent recursive resolution
-      //
-      final int dollar = varBounds[SUB_START_IDX] - "${".length();
-      final int afterRightBrace = varBounds[SUB_END_IDX] + "}".length();
-      final String refVar = eval.substring(dollar, afterRightBrace);
-      if (evalSet == null) {
-        evalSet = new HashSet<>();
-      }
-      if (!evalSet.add(refVar)) {
-        return expr; // return original expression if there is a loop
-      }
-
-      // substitute
-      eval = eval.substring(0, dollar)
-             + val
-             + eval.substring(afterRightBrace);
-    }
-    throw new IllegalStateException("Variable substitution depth too large: "
-                                    + MAX_SUBST + " " + expr);
-  }
-
-  String getenv(String name) {
-    return System.getenv(name);
-  }
-
-  String getProperty(String key) {
-    return System.getProperty(key);
-  }
-
-  /**
-   * Get the value of the <code>name</code> property, <code>null</code> if
-   * no such property exists. If the key is deprecated, it returns the value of
-   * the first key which replaces the deprecated key and is not null.
-   *
-   * Values are processed for <a href="#VariableExpansion">variable expansion</a>
-   * before being returned.
-   *
-   * @param name the property name, will be trimmed before get value.
-   * @return the value of the <code>name</code> or its replacing property,
-   *         or null if no such property exists.
-   */
-  public String get(String name) {
-    return substituteVars(getRaw(name));
-  }
-
-  /**
-   * Get the value of the <code>name</code> property as a trimmed <code>String</code>,
-   * <code>null</code> if no such property exists.
-   * If the key is deprecated, it returns the value of
-   * the first key which replaces the deprecated key and is not null
-   *
-   * Values are processed for <a href="#VariableExpansion">variable expansion</a>
-   * before being returned.
-   *
-   * @param name the property name.
-   * @return the value of the <code>name</code> or its replacing property,
-   *         or null if no such property exists.
-   */
-  public String getTrimmed(String name) {
-    String value = get(name);
-
-    if (null == value) {
-      return null;
-    } else {
-      return value.trim();
-    }
-  }
-
-  /**
-   * Get the value of the <code>name</code> property as a trimmed <code>String</code>,
-   * <code>defaultValue</code> if no such property exists.
-   * See @{Configuration#getTrimmed} for more details.
-   *
-   * @param name          the property name.
-   * @param defaultValue  the property default value.
-   * @return              the value of the <code>name</code> or defaultValue
-   *                      if it is not set.
-   */
-  public String getTrimmed(String name, String defaultValue) {
-    String ret = getTrimmed(name);
-    return ret == null ? defaultValue : ret;
-  }
-
-  /**
-   * Get the value of the <code>name</code> property, without doing
-   * <a href="#VariableExpansion">variable expansion</a>.If the key is
-   * deprecated, it returns the value of the first key which replaces
-   * the deprecated key and is not null.
-   *
-   * @param name the property name.
-   * @return the value of the <code>name</code> property or
-   *         its replacing property and null if no such property exists.
-   */
-  public String getRaw(String name) {
-    return getProps().getProperty(name.trim());
-  }
-
-  /**
-   * Set the <code>value</code> of the <code>name</code> property. If
-   * <code>name</code> is deprecated, it also sets the <code>value</code> to
-   * the keys that replace the deprecated key. Name will be trimmed before put
-   * into configuration.
-   *
-   * @param name property name.
-   * @param value property value.
-   * @throws IllegalArgumentException when the value or name is null.
-   */
-  public void set(String name, String value) {
-    final String trimmed = Objects.requireNonNull(name, "Property name must be non-null.");
-    Objects.requireNonNull(value, () -> "The value of property " + trimmed + " must be non-null.");
-    name = trimmed;
-    getProps();
-
-    getOverlay().setProperty(name, value);
-    getProps().setProperty(name, value);
-  }
-
-  /**
-   * Unset a previously set property.
-   */
-  public synchronized void unset(String name) {
-    getOverlay().remove(name);
-    getProps().remove(name);
-  }
-
-  /**
-   * Sets a property if it is currently unset.
-   * @param name the property name
-   * @param value the new value
-   */
-  public synchronized void setIfUnset(String name, String value) {
-    if (get(name) == null) {
-      set(name, value);
-    }
-  }
-
-  private synchronized Properties getOverlay() {
-    if (overlay == null){
-      overlay = new Properties();
-    }
-    return overlay;
-  }
-
-  /**
-   * Get the value of the <code>name</code>. If the key is deprecated,
-   * it returns the value of the first key which replaces the deprecated key
-   * and is not null.
-   * If no such property exists,
-   * then <code>defaultValue</code> is returned.
-   *
-   * @param name property name, will be trimmed before get value.
-   * @param defaultValue default value.
-   * @return property value, or <code>defaultValue</code> if the property
-   *         doesn't exist.
-   */
-  public String get(String name, String defaultValue) {
-    return substituteVars(getProps().getProperty(name, defaultValue));
-  }
-
-  /**
-   * Get the value of the <code>name</code> property as an <code>int</code>.
-   *
-   * If no such property exists, the provided default value is returned,
-   * or if the specified value is not a valid <code>int</code>,
-   * then an error is thrown.
-   *
-   * @param name property name.
-   * @param defaultValue default value.
-   * @throws NumberFormatException when the value is invalid
-   * @return property value as an <code>int</code>,
-   *         or <code>defaultValue</code>.
-   */
-  public int getInt(String name, int defaultValue) {
-    String valueString = getTrimmed(name);
-    if (valueString == null) {
-      return defaultValue;
-    }
-    String hexString = getHexDigits(valueString);
-    if (hexString != null) {
-      return Integer.parseInt(hexString, 16);
-    }
-    return Integer.parseInt(valueString);
-  }
-
-  /**
-   * Get the value of the <code>name</code> property as a set of comma-delimited
-   * <code>int</code> values.
-   *
-   * If no such property exists, an empty array is returned.
-   *
-   * @param name property name
-   * @return property value interpreted as an array of comma-delimited
-   *         <code>int</code> values
-   */
-  public int[] getInts(String name) {
-    String[] strings = getTrimmedStrings(name);
-    int[] ints = new int[strings.length];
-    for (int i = 0; i < strings.length; i++) {
-      ints[i] = Integer.parseInt(strings[i]);
-    }
-    return ints;
-  }
-
-  /**
-   * Set the value of the <code>name</code> property to an <code>int</code>.
-   *
-   * @param name property name.
-   * @param value <code>int</code> value of the property.
-   */
-  public void setInt(String name, int value) {
-    set(name, Integer.toString(value));
-  }
-
-
-  /**
-   * Get the value of the <code>name</code> property as a <code>long</code>.
-   * If no such property exists, the provided default value is returned,
-   * or if the specified value is not a valid <code>long</code>,
-   * then an error is thrown.
-   *
-   * @param name property name.
-   * @param defaultValue default value.
-   * @throws NumberFormatException when the value is invalid
-   * @return property value as a <code>long</code>,
-   *         or <code>defaultValue</code>.
-   */
-  public long getLong(String name, long defaultValue) {
-    String valueString = getTrimmed(name);
-    if (valueString == null) {
-      return defaultValue;
-    }
-    String hexString = getHexDigits(valueString);
-    if (hexString != null) {
-      return Long.parseLong(hexString, 16);
-    }
-    return Long.parseLong(valueString);
-  }
-
-  /** @return property value; if it is not set, return the default value. */
-  public File getFile(String name, File defaultValue) {
-    final String valueString = getTrimmed(name);
-    return valueString == null? defaultValue: new File(valueString);
-  }
-
-  /**
-   * Get the value of the <code>name</code> property as a list
-   * of <code>File</code>.
-   * The value of the property specifies a list of comma separated path names.
-   * If no such property is specified, then <code>defaultValue</code> is
-   * returned.
-   *
-   * @param name the property name.
-   * @param defaultValue default value.
-   * @return property value as a List of File, or <code>defaultValue</code>.
-   */
-  public List<File> getFiles(String name, List<File> defaultValue) {
-    String valueString = getRaw(name);
-    if (null == valueString) {
-      return defaultValue;
-    }
-    String[] paths = getTrimmedStrings(name);
-    return Arrays.stream(paths).map(File::new).collect(Collectors.toList());
-  }
-
-  public void setFile(String name, File value) {
-    try {
-      set(name, value.getCanonicalPath());
-    } catch (IOException e) {
-      throw new IllegalArgumentException(
-          "Failed to get canonical path from file " + value + " for " + name, e);
-    }
-  }
-
-  public void setFiles(String name, List<File> value) {
-    String paths = value.stream().map(File::getAbsolutePath)
-        .collect(Collectors.joining(","));
-    set(name, paths);
-  }
-
-  /** @return property value; if it is not set, return the default value. */
-  public SizeInBytes getSizeInBytes(String name, SizeInBytes defaultValue) {
-    final String valueString = getTrimmed(name);
-    return valueString == null? defaultValue: SizeInBytes.valueOf(valueString);
-  }
-
-  private String getHexDigits(String value) {
-    boolean negative = false;
-    String str = value;
-    String hexString;
-    if (value.startsWith("-")) {
-      negative = true;
-      str = value.substring(1);
-    }
-    if (str.startsWith("0x") || str.startsWith("0X")) {
-      hexString = str.substring(2);
-      if (negative) {
-        hexString = "-" + hexString;
-      }
-      return hexString;
-    }
-    return null;
-  }
-
-  /**
-   * Set the value of the <code>name</code> property to a <code>long</code>.
-   *
-   * @param name property name.
-   * @param value <code>long</code> value of the property.
-   */
-  public void setLong(String name, long value) {
-    set(name, Long.toString(value));
-  }
-
-  /**
-   * Get the value of the <code>name</code> property as a <code>float</code>.
-   * If no such property exists, the provided default value is returned,
-   * or if the specified value is not a valid <code>float</code>,
-   * then an error is thrown.
-   *
-   * @param name property name.
-   * @param defaultValue default value.
-   * @throws NumberFormatException when the value is invalid
-   * @return property value as a <code>float</code>,
-   *         or <code>defaultValue</code>.
-   */
-  public float getFloat(String name, float defaultValue) {
-    String valueString = getTrimmed(name);
-    if (valueString == null) {
-      return defaultValue;
-    }
-    return Float.parseFloat(valueString);
-  }
-
-  /**
-   * Set the value of the <code>name</code> property to a <code>float</code>.
-   *
-   * @param name property name.
-   * @param value property value.
-   */
-  public void setFloat(String name, float value) {
-    set(name,Float.toString(value));
-  }
-
-  /**
-   * Get the value of the <code>name</code> property as a <code>double</code>.
-   * If no such property exists, the provided default value is returned,
-   * or if the specified value is not a valid <code>double</code>,
-   * then an error is thrown.
-   *
-   * @param name property name.
-   * @param defaultValue default value.
-   * @throws NumberFormatException when the value is invalid
-   * @return property value as a <code>double</code>,
-   *         or <code>defaultValue</code>.
-   */
-  public double getDouble(String name, double defaultValue) {
-    String valueString = getTrimmed(name);
-    if (valueString == null) {
-      return defaultValue;
-    }
-    return Double.parseDouble(valueString);
-  }
-
-  /**
-   * Set the value of the <code>name</code> property to a <code>double</code>.
-   *
-   * @param name property name.
-   * @param value property value.
-   */
-  public void setDouble(String name, double value) {
-    set(name,Double.toString(value));
-  }
-
-  /**
-   * Get the value of the <code>name</code> property as a <code>boolean</code>.
-   * If no such property is specified, or if the specified value is not a valid
-   * <code>boolean</code>, then <code>defaultValue</code> is returned.
-   *
-   * @param name property name.
-   * @param defaultValue default value.
-   * @return property value as a <code>boolean</code>,
-   *         or <code>defaultValue</code>.
-   */
-  public boolean getBoolean(String name, boolean defaultValue) {
-    String valueString = getTrimmed(name);
-    return StringUtils.string2boolean(valueString, defaultValue);
-  }
-
-  /**
-   * Set the value of the <code>name</code> property to a <code>boolean</code>.
-   *
-   * @param name property name.
-   * @param value <code>boolean</code> value of the property.
-   */
-  public void setBoolean(String name, boolean value) {
-    set(name, Boolean.toString(value));
-  }
-
-  /**
-   * Set the given property, if it is currently unset.
-   * @param name property name
-   * @param value new value
-   */
-  public void setBooleanIfUnset(String name, boolean value) {
-    setIfUnset(name, Boolean.toString(value));
-  }
-
-  /**
-   * Set the value of the <code>name</code> property to the given type. This
-   * is equivalent to <code>set(&lt;name&gt;, value.toString())</code>.
-   * @param name property name
-   * @param value new value
-   */
-  public <T extends Enum<T>> void setEnum(String name, T value) {
-    set(name, value.toString());
-  }
-
-  /**
-   * Return value matching this enumerated type.
-   * Note that the returned value is trimmed by this method.
-   * @param name Property name
-   * @param defaultValue Value returned if no mapping exists
-   * @throws IllegalArgumentException If mapping is illegal for the type
-   * provided
-   */
-  public <T extends Enum<T>> T getEnum(String name, T defaultValue) {
-    final String val = getTrimmed(name);
-    return null == val
-      ? defaultValue
-      : Enum.valueOf(defaultValue.getDeclaringClass(), val);
-  }
-
-  /**
-   * Set the value of <code>name</code> to the given time duration. This
-   * is equivalent to <code>set(&lt;name&gt;, value + &lt;time suffix&gt;)</code>.
-   * @param name Property name
-   * @param value Time duration
-   */
-  public void setTimeDuration(String name, TimeDuration value) {
-    set(name, value.toString());
-  }
-
-  /**
-   * Return time duration in the given time unit. Valid units are encoded in
-   * properties as suffixes: nanoseconds (ns), microseconds (us), milliseconds
-   * (ms), seconds (s), minutes (m), hours (h), and days (d).
-   * @param name Property name
-   * @param defaultValue Value returned if no mapping exists.
-   * @throws NumberFormatException If the property stripped of its unit is not
-   *         a number
-   */
-  public TimeDuration getTimeDuration(
-      String name, TimeDuration defaultValue, TimeUnit defaultUnit) {
-    final String value = getTrimmed(name);
-    if (null == value) {
-      return defaultValue;
-    }
-    try {
-      return TimeDuration.valueOf(value, defaultUnit);
-    } catch(NumberFormatException e) {
-      throw new IllegalArgumentException("Failed to parse "
-          + name + " = " + value, e);
-    }
-  }
-  public BiFunction<String, TimeDuration, TimeDuration> getTimeDuration(TimeUnit defaultUnit) {
-    return (key, defaultValue) -> getTimeDuration(key, defaultValue, defaultUnit);
-  }
-
-  /**
-   * Get the value of the <code>name</code> property as a <code>Pattern</code>.
-   * If no such property is specified, or if the specified value is not a valid
-   * <code>Pattern</code>, then <code>DefaultValue</code> is returned.
-   * Note that the returned value is NOT trimmed by this method.
-   *
-   * @param name property name
-   * @param defaultValue default value
-   * @return property value as a compiled Pattern, or defaultValue
-   */
-  public Pattern getPattern(String name, Pattern defaultValue) {
-    String valString = get(name);
-    if (null == valString || valString.isEmpty()) {
-      return defaultValue;
-    }
-    try {
-      return Pattern.compile(valString);
-    } catch (PatternSyntaxException pse) {
-      LOG.warn("Regular expression '" + valString + "' for property '" +
-               name + "' not valid. Using default", pse);
-      return defaultValue;
-    }
-  }
-
-  /**
-   * Set the given property to <code>Pattern</code>.
-   * If the pattern is passed as null, sets the empty pattern which results in
-   * further calls to getPattern(...) returning the default value.
-   *
-   * @param name property name
-   * @param pattern new value
-   */
-  public void setPattern(String name, Pattern pattern) {
-    assert pattern != null : "Pattern cannot be null";
-    set(name, pattern.pattern());
-  }
-
-  /**
-   * Get the comma delimited values of the <code>name</code> property as
-   * an array of <code>String</code>s, trimmed of the leading and trailing whitespace.
-   * If no such property is specified then an empty array is returned.
-   *
-   * @param name property name.
-   * @return property value as an array of trimmed <code>String</code>s,
-   *         or empty array.
-   */
-  public String[] getTrimmedStrings(String name) {
-    String valueString = get(name);
-    return StringUtils.getTrimmedStrings(valueString);
-  }
-
-
-
-  /**
-   * Get the value of the <code>name</code> property
-   * as an array of <code>Class</code>.
-   * The value of the property specifies a list of comma separated class names.
-   * If no such property is specified, then <code>defaultValue</code> is
-   * returned.
-   *
-   * @param name the property name.
-   * @param defaultValue default value.
-   * @return property value as a <code>Class[]</code>,
-   *         or <code>defaultValue</code>.
-   */
-  public Class<?>[] getClasses(String name, Class<?> ... defaultValue) {
-    String valueString = getRaw(name);
-    if (null == valueString) {
-      return defaultValue;
-    }
-    String[] classnames = getTrimmedStrings(name);
-    try {
-      Class<?>[] classes = new Class<?>[classnames.length];
-      for(int i = 0; i < classnames.length; i++) {
-        classes[i] = ReflectionUtils.getClassByName(classnames[i]);
-      }
-      return classes;
-    } catch (ClassNotFoundException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  /**
-   * Get the value of the <code>name</code> property as a <code>Class</code>.
-   * If no such property is specified, then <code>defaultValue</code> is
-   * returned.
-   *
-   * @param name the class name.
-   * @param defaultValue default value.
-   * @return property value as a <code>Class</code>,
-   *         or <code>defaultValue</code>.
-   */
-  public Class<?> getClass(String name, Class<?> defaultValue) {
-    String valueString = getTrimmed(name);
-    if (valueString == null) {
-      return defaultValue;
-    }
-    try {
-      return ReflectionUtils.getClassByName(valueString);
-    } catch (ClassNotFoundException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  /**
-   * Get the value of the <code>name</code> property as a <code>Class</code>
-   * implementing the interface specified by <code>xface</code>.
-   *
-   * If no such property is specified, then <code>defaultValue</code> is
-   * returned.
-   *
-   * An exception is thrown if the returned class does not implement the named
-   * interface.
-   *
-   * @param name the class name.
-   * @param defaultValue default value.
-   * @param xface the interface implemented by the named class.
-   * @return property value as a <code>Class</code>,
-   *         or <code>defaultValue</code>.
-   */
-  public <BASE> Class<? extends BASE> getClass(
-      String name, Class<? extends BASE> defaultValue, Class<BASE> xface) {
-    try {
-      Class<?> theClass = getClass(name, defaultValue);
-      if (theClass != null && !xface.isAssignableFrom(theClass)) {
-        throw new RuntimeException(theClass+" not "+xface.getName());
-      } else if (theClass != null) {
-        return theClass.asSubclass(xface);
-      } else {
-        return null;
-      }
-
-    } catch (Exception e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  /**
-   * Set the value of the <code>name</code> property to the name of a
-   * <code>theClass</code> implementing the given interface <code>xface</code>.
-   *
-   * An exception is thrown if <code>theClass</code> does not implement the
-   * interface <code>xface</code>.
-   *
-   * @param name property name.
-   * @param theClass property value.
-   * @param xface the interface implemented by the named class.
-   */
-  public void setClass(String name, Class<?> theClass, Class<?> xface) {
-    if (!xface.isAssignableFrom(theClass)) {
-      throw new RuntimeException(theClass+" not "+xface.getName());
-    }
-    set(name, theClass.getName());
-  }
-
-  protected synchronized Properties getProps() {
-    if (properties == null) {
-      properties = new Properties();
-      Map<String, String[]> backup =
-          new ConcurrentHashMap<>(updatingResource);
-      loadResources();
-
-      if (overlay != null) {
-        properties.putAll(overlay);
-        for (Entry<Object,Object> item: overlay.entrySet()) {
-          String key = (String) item.getKey();
-          String[] source = backup.get(key);
-          if(source != null) {
-            updatingResource.put(key, source);
-          }
-        }
-      }
-    }
-    return properties;
-  }
-
-  /**
-   * Return the number of keys in the configuration.
-   *
-   * @return number of keys in the configuration.
-   */
-  public int size() {
-    return getProps().size();
-  }
-
-  /**
-   * Clears all keys from the configuration.
-   */
-  public void clear() {
-    getProps().clear();
-    getOverlay().clear();
-  }
-
-  private Document parse(DocumentBuilder builder, URL url)
-      throws IOException, SAXException {
-    LOG.debug("parsing URL " + url);
-    if (url == null) {
-      return null;
-    }
-
-    URLConnection connection = url.openConnection();
-    if (connection instanceof JarURLConnection) {
-      // Disable caching for JarURLConnection to avoid sharing JarFile
-      // with other users.
-      connection.setUseCaches(false);
-    }
-    return parse(builder, connection.getInputStream(), url.toString());
-  }
-
-  private Document parse(DocumentBuilder builder, InputStream is,
-      String systemId) throws IOException, SAXException {
-    LOG.debug("parsing input stream " + is);
-    if (is == null) {
-      return null;
-    }
-    try {
-      return (systemId == null) ? builder.parse(is) : builder.parse(is,
-          systemId);
-    } finally {
-      is.close();
-    }
-  }
-
-  private void loadResources() {
-    if(loadDefaults) {
-      for (String resource : DEFAULT_RESOURCES) {
-        loadResource(properties, new Resource(resource));
-      }
-    }
-
-    for (int i = 0; i < resources.size(); i++) {
-      Resource ret = loadResource(properties, resources.get(i));
-      if (ret != null) {
-        resources.set(i, ret);
-      }
-    }
-  }
-
-  private Resource loadResource(Properties propts, Resource wrapper) {
-    String name = UNKNOWN_RESOURCE;
-    try {
-      Object resource = wrapper.getResource();
-      name = wrapper.getName();
-
-      DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
-      docBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
-      docBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
-      docBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
-      //ignore all comments inside the xml file
-      docBuilderFactory.setIgnoringComments(true);
-
-      //allow includes in the xml file
-      docBuilderFactory.setNamespaceAware(true);
-      try {
-          docBuilderFactory.setXIncludeAware(true);
-      } catch (UnsupportedOperationException e) {
-        LOG.error("Failed to set setXIncludeAware(true) for parser " + docBuilderFactory + ":" + e, e);
-      }
-      DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
-      Document doc = null;
-      Element root = null;
-      boolean returnCachedProperties = false;
-
-      if (resource instanceof URL) { // an URL resource
-        doc = parse(builder, (URL) resource);
-      } else if (resource instanceof String) { // a CLASSPATH resource
-        URL url = ReflectionUtils.getClassLoader().getResource((String)resource);
-        doc = parse(builder, url);
-      } else if (resource instanceof InputStream) {
-        doc = parse(builder, (InputStream) resource, null);
-        returnCachedProperties = true;
-      } else if (resource instanceof Properties) {
-        overlay(propts, (Properties) resource);
-      } else if (resource instanceof Element) {
-        root = (Element) resource;
-      }
-
-      if (root == null) {
-        if (doc == null) {
-          return null;
-        }
-        root = doc.getDocumentElement();
-      }
-      Properties toAddTo = propts;
-      if(returnCachedProperties) {
-        toAddTo = new Properties();
-      }
-      if (!"configuration".equals(root.getTagName())) {
-        LOG.error("bad conf file: top-level element not <configuration>");
-      }
-      NodeList props = root.getChildNodes();
-      for (int i = 0; i < props.getLength(); i++) {
-        Node propNode = props.item(i);
-        if (!(propNode instanceof Element)) {
-          continue;
-        }
-
-        Element prop = (Element)propNode;
-        if ("configuration".equals(prop.getTagName())) {
-          loadResource(toAddTo, new Resource(prop, name));
-          continue;
-        }
-        if (!"property".equals(prop.getTagName())) {
-          LOG.warn("bad conf file: element not <property>");
-        }
-
-        String attr = null;
-        String value = null;
-        boolean finalParameter = false;
-        LinkedList<String> source = new LinkedList<>();
-
-        Attr propAttr = prop.getAttributeNode("name");
-        if (propAttr != null) {
-          attr = StringUtils.weakIntern(propAttr.getValue());
-        }
-        propAttr = prop.getAttributeNode("value");
-        if (propAttr != null) {
-          value = StringUtils.weakIntern(propAttr.getValue());
-        }
-        propAttr = prop.getAttributeNode("final");
-        if (propAttr != null) {
-          finalParameter = "true".equals(propAttr.getValue());
-        }
-        propAttr = prop.getAttributeNode("source");
-        if (propAttr != null) {
-          source.add(StringUtils.weakIntern(propAttr.getValue()));
-        }
-
-        NodeList fields = prop.getChildNodes();
-        for (int j = 0; j < fields.getLength(); j++) {
-          Node fieldNode = fields.item(j);
-          if (!(fieldNode instanceof Element)) {
-            continue;
-          }
-          Element field = (Element)fieldNode;
-          if ("name".equals(field.getTagName()) && field.hasChildNodes()) {
-            attr = StringUtils.weakIntern(
-                ((Text)field.getFirstChild()).getData().trim());
-          }
-          if ("value".equals(field.getTagName()) && field.hasChildNodes()) {
-            value = StringUtils.weakIntern(
-                ((Text)field.getFirstChild()).getData());
-          }
-          if ("final".equals(field.getTagName()) && field.hasChildNodes()) {
-            finalParameter = "true".equals(((Text)field.getFirstChild()).getData());
-          }
-          if ("source".equals(field.getTagName()) && field.hasChildNodes()) {
-            source.add(StringUtils.weakIntern(
-                ((Text)field.getFirstChild()).getData()));
-          }
-        }
-        source.add(name);
-
-        // Ignore this parameter if it has already been marked as 'final'
-        if (attr != null) {
-          loadProperty(toAddTo, name, attr, value, finalParameter,
-              source.toArray(new String[source.size()]));
-        }
-      }
-
-      if (returnCachedProperties) {
-        overlay(propts, toAddTo);
-        return new Resource(toAddTo, name);
-      }
-      return null;
-    } catch (IOException | DOMException | SAXException |
-        ParserConfigurationException e) {
-      LOG.error("error parsing conf " + name, e);
-      throw new RuntimeException(e);
-    }
-  }
-
-  private void overlay(Properties to, Properties from) {
-    for (Entry<Object, Object> entry: from.entrySet()) {
-      to.put(entry.getKey(), entry.getValue());
-    }
-  }
-
-  private void loadProperty(Properties prop, String name, String attr,
-      String value, boolean finalParameter, String[] source) {
-    if (value != null) {
-      if (!finalParameters.contains(attr)) {
-        prop.setProperty(attr, value);
-        if(source != null) {
-          updatingResource.put(attr, source);
-        }
-      } else if (!value.equals(prop.getProperty(attr))) {
-        LOG.warn(name+":an attempt to override final parameter: "+attr
-            +";  Ignoring.");
-      }
-    }
-    if (finalParameter && attr != null) {
-      finalParameters.add(attr);
-    }
-  }
-
-  /**
-   * Write out the non-default properties in this configuration to the given
-   * {@link OutputStream} using UTF-8 encoding.
-   *
-   * @param out the output stream to write to.
-   */
-  public void writeXml(OutputStream out) throws IOException {
-    writeXml(new OutputStreamWriter(out, "UTF-8"));
-  }
-
-  /**
-   * Write out the non-default properties in this configuration to the given
-   * {@link Writer}.
-   *
-   * @param out the writer to write to.
-   */
-  public void writeXml(Writer out) throws IOException {
-    Document doc = asXmlDocument();
-
-    try {
-      DOMSource source = new DOMSource(doc);
-      StreamResult result = new StreamResult(out);
-      TransformerFactory transFactory = TransformerFactory.newInstance();
-      transFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
-      transFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
-      transFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
-      Transformer transformer = transFactory.newTransformer();
-
-      // Important to not hold Configuration log while writing result, since
-      // 'out' may be an HDFS stream which needs to lock this configuration
-      // from another thread.
-      transformer.transform(source, result);
-    } catch (TransformerException te) {
-      throw new IOException(te);
-    }
-  }
-
-  /**
-   * Return the XML DOM corresponding to this Configuration.
-   */
-  private synchronized Document asXmlDocument() throws IOException {
-    Document doc;
-    try {
-      DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
-      docBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
-      docBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
-      docBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
-      doc = docBuilderFactory.newDocumentBuilder().newDocument();
-    } catch (ParserConfigurationException pe) {
-      throw new IOException(pe);
-    }
-    Element conf = doc.createElement("configuration");
-    doc.appendChild(conf);
-    conf.appendChild(doc.createTextNode("\n"));
-    for (Enumeration<Object> e = properties.keys(); e.hasMoreElements();) {
-      String name = (String)e.nextElement();
-      Object object = properties.get(name);
-      String value;
-      if (object instanceof String) {
-        value = (String) object;
-      }else {
-        continue;
-      }
-      Element propNode = doc.createElement("property");
-      conf.appendChild(propNode);
-
-      Element nameNode = doc.createElement("name");
-      nameNode.appendChild(doc.createTextNode(name));
-      propNode.appendChild(nameNode);
-
-      Element valueNode = doc.createElement("value");
-      valueNode.appendChild(doc.createTextNode(value));
-      propNode.appendChild(valueNode);
-
-      if (updatingResource != null) {
-        String[] sources = updatingResource.get(name);
-        if(sources != null) {
-          for(String s : sources) {
-            Element sourceNode = doc.createElement("source");
-            sourceNode.appendChild(doc.createTextNode(s));
-            propNode.appendChild(sourceNode);
-          }
-        }
-      }
-
-      conf.appendChild(doc.createTextNode("\n"));
-    }
-    return doc;
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder sb = new StringBuilder();
-    sb.append("Configuration: ");
-    if(loadDefaults) {
-      toString(DEFAULT_RESOURCES, sb);
-      if(resources.size()>0) {
-        sb.append(", ");
-      }
-    }
-    toString(resources, sb);
-    return sb.toString();
-  }
-
-  private <T> void toString(List<T> res, StringBuilder sb) {
-    ListIterator<T> i = res.listIterator();
-    while (i.hasNext()) {
-      if (i.nextIndex() != 0) {
-        sb.append(", ");
-      }
-      sb.append(i.next());
-    }
-  }
-
-  /**
-   * get keys matching the the regex
-   * @return a map with matching keys
-   */
-  public Map<String,String> getValByRegex(String regex) {
-    Pattern p = Pattern.compile(regex);
-
-    Map<String,String> result = new HashMap<>();
-    Matcher m;
-
-    for(Entry<Object,Object> item: getProps().entrySet()) {
-      if (item.getKey() instanceof String &&
-          item.getValue() instanceof String) {
-        m = p.matcher((String)item.getKey());
-        if(m.find()) { // match
-          result.put((String) item.getKey(),
-              substituteVars(getProps().getProperty((String) item.getKey())));
-        }
-      }
-    }
-    return result;
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/datastream/DataStreamFactory.java b/ratis-common/src/main/java/org/apache/ratis/datastream/DataStreamFactory.java
deleted file mode 100644
index 1e4874a..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/datastream/DataStreamFactory.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.datastream;
-
-public interface DataStreamFactory extends DataStreamType.Get {
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/datastream/DataStreamType.java b/ratis-common/src/main/java/org/apache/ratis/datastream/DataStreamType.java
deleted file mode 100644
index 58640b0..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/datastream/DataStreamType.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.datastream;
-
-import org.apache.ratis.conf.Parameters;
-import org.apache.ratis.util.JavaUtils;
-import org.apache.ratis.util.ReflectionUtils;
-
-/** The type of data stream implementations. */
-public interface DataStreamType {
-  /**
-   * Parse the given string as a {@link SupportedDataStreamType}
-   * or a user-defined {@link DataStreamType}.
-   *
-   * @param dataStreamType The string representation of an {@link DataStreamType}.
-   * @return a {@link SupportedDataStreamType} or a user-defined {@link DataStreamType}.
-   */
-  static DataStreamType valueOf(String dataStreamType) {
-    final Throwable fromSupportedRpcType;
-    try { // Try parsing it as a SupportedRpcType
-      return SupportedDataStreamType.valueOfIgnoreCase(dataStreamType);
-    } catch (Throwable t) {
-      fromSupportedRpcType = t;
-    }
-
-    try {
-      // Try using it as a class name
-      return ReflectionUtils.newInstance(ReflectionUtils.getClass(dataStreamType, DataStreamType.class));
-    } catch(Throwable t) {
-      final String classname = JavaUtils.getClassSimpleName(DataStreamType.class);
-      final IllegalArgumentException iae = new IllegalArgumentException(
-          "Invalid " + classname + ": \"" + dataStreamType + "\" "
-              + " cannot be used as a user-defined " + classname
-              + " and it is not a " + JavaUtils.getClassSimpleName(SupportedDataStreamType.class) + ".");
-      iae.addSuppressed(t);
-      iae.addSuppressed(fromSupportedRpcType);
-      throw iae;
-    }
-  }
-
-  /** @return the name of the rpc type. */
-  String name();
-
-  /** @return a new client factory created using the given parameters. */
-  DataStreamFactory newClientFactory(Parameters parameters);
-
-  /** @return a new server factory created using the given parameters. */
-  DataStreamFactory newServerFactory(Parameters parameters);
-
-  /** An interface to get {@link DataStreamType}. */
-  interface Get {
-    /** @return the {@link DataStreamType}. */
-    DataStreamType getDataStreamType();
-  }
-}
\ No newline at end of file
diff --git a/ratis-common/src/main/java/org/apache/ratis/datastream/SupportedDataStreamType.java b/ratis-common/src/main/java/org/apache/ratis/datastream/SupportedDataStreamType.java
deleted file mode 100644
index 019093e..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/datastream/SupportedDataStreamType.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.datastream;
-
-import org.apache.ratis.conf.Parameters;
-import org.apache.ratis.util.ReflectionUtils;
-
-public enum SupportedDataStreamType implements DataStreamType {
-  DISABLED("org.apache.ratis.client.DisabledDataStreamClientFactory",
-      "org.apache.ratis.server.DisabledDataStreamServerFactory"),
-  NETTY("org.apache.ratis.netty.NettyDataStreamFactory");
-
-  private static final Class<?>[] ARG_CLASSES = {Parameters.class};
-
-  public static SupportedDataStreamType valueOfIgnoreCase(String s) {
-    return valueOf(s.toUpperCase());
-  }
-
-  private final String clientFactoryClassName;
-  private final String serverFactoryClassName;
-
-  SupportedDataStreamType(String clientFactoryClassName, String serverFactoryClassName) {
-    this.clientFactoryClassName = clientFactoryClassName;
-    this.serverFactoryClassName = serverFactoryClassName;
-  }
-
-  SupportedDataStreamType(String factoryClassName) {
-    this(factoryClassName, factoryClassName);
-  }
-
-  @Override
-  public DataStreamFactory newClientFactory(Parameters parameters) {
-    final Class<? extends DataStreamFactory> clazz = ReflectionUtils.getClass(
-        clientFactoryClassName, DataStreamFactory.class);
-    return ReflectionUtils.newInstance(clazz, ARG_CLASSES, parameters);
-  }
-
-  @Override
-  public DataStreamFactory newServerFactory(Parameters parameters) {
-    final Class<? extends DataStreamFactory> clazz = ReflectionUtils.getClass(
-        serverFactoryClassName, DataStreamFactory.class);
-    return ReflectionUtils.newInstance(clazz, ARG_CLASSES, parameters);
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamPacketByteBuffer.java b/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamPacketByteBuffer.java
deleted file mode 100644
index b8d7b48..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamPacketByteBuffer.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.datastream.impl;
-
-import org.apache.ratis.proto.RaftProtos.DataStreamPacketHeaderProto.Type;
-import org.apache.ratis.protocol.ClientId;
-
-import java.nio.ByteBuffer;
-
-/**
- * Implements {@link org.apache.ratis.protocol.DataStreamPacket} with {@link ByteBuffer}.
- */
-public abstract class DataStreamPacketByteBuffer extends DataStreamPacketImpl {
-  public static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocateDirect(0).asReadOnlyBuffer();
-
-  private final ByteBuffer buffer;
-
-  protected DataStreamPacketByteBuffer(ClientId clientId, Type type, long streamId, long streamOffset,
-      ByteBuffer buffer) {
-    super(clientId, type, streamId, streamOffset);
-    this.buffer = buffer != null? buffer.asReadOnlyBuffer(): EMPTY_BYTE_BUFFER;
-  }
-
-  @Override
-  public long getDataLength() {
-    return buffer.remaining();
-  }
-
-  public ByteBuffer slice() {
-    return buffer.slice();
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamPacketImpl.java b/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamPacketImpl.java
deleted file mode 100644
index 6be0300..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamPacketImpl.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.datastream.impl;
-
-import org.apache.ratis.protocol.ClientId;
-import org.apache.ratis.protocol.DataStreamPacket;
-import org.apache.ratis.proto.RaftProtos.DataStreamPacketHeaderProto.Type;
-import org.apache.ratis.util.JavaUtils;
-
-/**
- * This is an abstract implementation of {@link DataStreamPacket}.
- *
- * This class is immutable.
- */
-public abstract class DataStreamPacketImpl implements DataStreamPacket {
-  private final ClientId clientId;
-  private final Type type;
-  private final long streamId;
-  private final long streamOffset;
-
-  public DataStreamPacketImpl(ClientId clientId, Type type, long streamId, long streamOffset) {
-    this.clientId = clientId;
-    this.type = type;
-    this.streamId = streamId;
-    this.streamOffset = streamOffset;
-  }
-
-  @Override
-  public ClientId getClientId() {
-    return clientId;
-  }
-
-  @Override
-  public Type getType() {
-    return type;
-  }
-
-  @Override
-  public long getStreamId() {
-    return streamId;
-  }
-
-  @Override
-  public long getStreamOffset() {
-    return streamOffset;
-  }
-
-  @Override
-  public String toString() {
-    return JavaUtils.getClassSimpleName(getClass())
-        + ":clientId=" + getClientId()
-        + ",type=" + getType()
-        + ",id=" + getStreamId()
-        + ",offset=" + getStreamOffset()
-        + ",length=" + getDataLength();
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamReplyByteBuffer.java b/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamReplyByteBuffer.java
deleted file mode 100644
index 5cb5569..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamReplyByteBuffer.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.datastream.impl;
-
-import org.apache.ratis.proto.RaftProtos.CommitInfoProto;
-import org.apache.ratis.protocol.ClientId;
-import org.apache.ratis.protocol.DataStreamPacket;
-import org.apache.ratis.protocol.DataStreamReply;
-import org.apache.ratis.protocol.DataStreamReplyHeader;
-import org.apache.ratis.proto.RaftProtos.DataStreamPacketHeaderProto.Type;
-
-import java.nio.ByteBuffer;
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * Implements {@link DataStreamReply} with {@link ByteBuffer}.
- *
- * This class is immutable.
- */
-public final class DataStreamReplyByteBuffer extends DataStreamPacketByteBuffer implements DataStreamReply {
-  public static final class Builder {
-    private ClientId clientId;
-    private Type type;
-    private long streamId;
-    private long streamOffset;
-    private ByteBuffer buffer;
-
-    private boolean success;
-    private long bytesWritten;
-    private Collection<CommitInfoProto> commitInfos;
-
-    private Builder() {}
-
-    public Builder setClientId(ClientId clientId) {
-      this.clientId = clientId;
-      return this;
-    }
-
-    public Builder setType(Type type) {
-      this.type = type;
-      return this;
-    }
-
-    public Builder setStreamId(long streamId) {
-      this.streamId = streamId;
-      return this;
-    }
-
-    public Builder setStreamOffset(long streamOffset) {
-      this.streamOffset = streamOffset;
-      return this;
-    }
-
-    public Builder setBuffer(ByteBuffer buffer) {
-      this.buffer = buffer;
-      return this;
-    }
-
-    public Builder setSuccess(boolean success) {
-      this.success = success;
-      return this;
-    }
-
-    public Builder setBytesWritten(long bytesWritten) {
-      this.bytesWritten = bytesWritten;
-      return this;
-    }
-
-    public Builder setCommitInfos(Collection<CommitInfoProto> commitInfos) {
-      this.commitInfos = commitInfos;
-      return this;
-    }
-
-    public Builder setDataStreamReplyHeader(DataStreamReplyHeader header) {
-      return setDataStreamPacket(header)
-          .setSuccess(header.isSuccess())
-          .setBytesWritten(header.getBytesWritten())
-          .setCommitInfos(header.getCommitInfos());
-    }
-
-    public Builder setDataStreamPacket(DataStreamPacket packet) {
-      return setClientId(packet.getClientId())
-          .setType(packet.getType())
-          .setStreamId(packet.getStreamId())
-          .setStreamOffset(packet.getStreamOffset());
-    }
-
-    public DataStreamReplyByteBuffer build() {
-      return new DataStreamReplyByteBuffer(
-          clientId, type, streamId, streamOffset, buffer, success, bytesWritten, commitInfos);
-    }
-  }
-
-  public static Builder newBuilder() {
-    return new Builder();
-  }
-
-  private final boolean success;
-  private final long bytesWritten;
-  private final Collection<CommitInfoProto> commitInfos;
-
-  @SuppressWarnings("parameternumber")
-  private DataStreamReplyByteBuffer(ClientId clientId, Type type, long streamId, long streamOffset, ByteBuffer buffer,
-      boolean success, long bytesWritten, Collection<CommitInfoProto> commitInfos) {
-    super(clientId, type, streamId, streamOffset, buffer);
-
-    this.success = success;
-    this.bytesWritten = bytesWritten;
-    this.commitInfos = commitInfos != null? commitInfos: Collections.emptyList();
-  }
-
-  @Override
-  public boolean isSuccess() {
-    return success;
-  }
-
-  @Override
-  public long getBytesWritten() {
-    return bytesWritten;
-  }
-
-  @Override
-  public Collection<CommitInfoProto> getCommitInfos() {
-    return commitInfos;
-  }
-
-  @Override
-  public String toString() {
-    return super.toString()
-        + "," + (success? "SUCCESS": "FAILED")
-        + ",bytesWritten=" + bytesWritten;
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamRequestByteBuffer.java b/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamRequestByteBuffer.java
deleted file mode 100644
index 80949f0..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamRequestByteBuffer.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.datastream.impl;
-
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import org.apache.ratis.io.WriteOption;
-import org.apache.ratis.protocol.DataStreamRequest;
-import org.apache.ratis.protocol.DataStreamRequestHeader;
-import org.apache.ratis.util.Preconditions;
-
-import java.nio.ByteBuffer;
-
-/**
- * Implements {@link DataStreamRequest} with {@link ByteBuffer}.
- *
- * This class is immutable.
- */
-public class DataStreamRequestByteBuffer extends DataStreamPacketByteBuffer implements DataStreamRequest {
-  private WriteOption[] options;
-
-  public DataStreamRequestByteBuffer(DataStreamRequestHeader header, ByteBuffer buffer) {
-    super(header.getClientId(), header.getType(), header.getStreamId(), header.getStreamOffset(), buffer);
-    this.options = header.getWriteOptions();
-    Preconditions.assertTrue(header.getDataLength() == buffer.remaining());
-  }
-
-  @Override
-  @SuppressFBWarnings("EI_EXPOSE_REP")
-  public WriteOption[] getWriteOptions() {
-    return options;
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamRequestFilePositionCount.java b/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamRequestFilePositionCount.java
deleted file mode 100644
index 8841455..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/datastream/impl/DataStreamRequestFilePositionCount.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.datastream.impl;
-
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import org.apache.ratis.io.FilePositionCount;
-import org.apache.ratis.io.WriteOption;
-import org.apache.ratis.protocol.DataStreamRequest;
-import org.apache.ratis.protocol.DataStreamRequestHeader;
-
-/**
- * Implements {@link DataStreamRequest} with {@link FilePositionCount}.
- *
- * This class is immutable.
- */
-public class DataStreamRequestFilePositionCount extends DataStreamPacketImpl implements DataStreamRequest {
-  private final FilePositionCount file;
-  private WriteOption[] options;
-
-  public DataStreamRequestFilePositionCount(DataStreamRequestHeader header, FilePositionCount file) {
-    super(header.getClientId(), header.getType(), header.getStreamId(), header.getStreamOffset());
-    this.options = header.getWriteOptions();
-    this.file = file;
-  }
-
-  @Override
-  public long getDataLength() {
-    return file.getCount();
-  }
-
-  /** @return the file with the starting position and the byte count. */
-  public FilePositionCount getFile() {
-    return file;
-  }
-
-  @Override
-  @SuppressFBWarnings("EI_EXPOSE_REP")
-  public WriteOption[] getWriteOptions() {
-    return options;
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/io/CloseAsync.java b/ratis-common/src/main/java/org/apache/ratis/io/CloseAsync.java
deleted file mode 100644
index 408e3d5..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/io/CloseAsync.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.io;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-
-/** Support the {@link CloseAsync#closeAsync()} method. */
-public interface CloseAsync<REPLY> extends AutoCloseable {
-  /** Close asynchronously. */
-  CompletableFuture<REPLY> closeAsync();
-
-  /**
-   * The same as {@link AutoCloseable#close()}.
-   *
-   * The default implementation simply calls {@link CloseAsync#closeAsync()}
-   * and then waits for the returned future to complete.
-   */
-  default void close() throws Exception {
-    try {
-      closeAsync().get();
-    } catch (ExecutionException e) {
-      final Throwable cause = e.getCause();
-      throw cause instanceof Exception? (Exception)cause: e;
-    }
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/io/CorruptedFileException.java b/ratis-common/src/main/java/org/apache/ratis/io/CorruptedFileException.java
deleted file mode 100644
index 3cf525b..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/io/CorruptedFileException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * 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.io;
-
-import java.io.File;
-import java.io.IOException;
-
-public class CorruptedFileException extends IOException {
-  public CorruptedFileException(File file, String message) {
-    super("File " + file + " (exist? " + file.exists() + ", length=" + file.length() + ") is corrupted: " + message);
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/io/FilePositionCount.java b/ratis-common/src/main/java/org/apache/ratis/io/FilePositionCount.java
deleted file mode 100644
index 150e042..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/io/FilePositionCount.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.io;
-
-import java.io.File;
-
-/**
- * Encapsulate a {@link File} with a starting position and a byte count.
- *
- * The class is immutable.
- */
-public final class FilePositionCount {
-  public static FilePositionCount valueOf(File file, long position, long count) {
-    return new FilePositionCount(file, position, count);
-  }
-
-  private final File file;
-  private final long position;
-  private final long count;
-
-  private FilePositionCount(File file, long position, long count) {
-    this.file = file;
-    this.position = position;
-    this.count = count;
-  }
-
-  /** @return the file. */
-  public File getFile() {
-    return file;
-  }
-
-  /** @return the starting position. */
-  public long getPosition() {
-    return position;
-  }
-
-  /** @return the byte count. */
-  public long getCount() {
-    return count;
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/io/MD5Hash.java b/ratis-common/src/main/java/org/apache/ratis/io/MD5Hash.java
deleted file mode 100644
index 76be2d5..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/io/MD5Hash.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
- * 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.io;
-
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
-
-public class MD5Hash {
-  public static final int MD5_LEN = 16;
-
-  private static final ThreadLocal<MessageDigest> DIGESTER_FACTORY =
-      ThreadLocal.withInitial(() -> {
-    try {
-      return MessageDigest.getInstance("MD5");
-    } catch (NoSuchAlgorithmException e) {
-      throw new RuntimeException(e);
-    }
-  });
-
-  private byte[] digest;
-
-  /** Constructs an MD5Hash. */
-  public MD5Hash() {
-    this.digest = new byte[MD5_LEN];
-  }
-
-  /** Constructs an MD5Hash from a hex string. */
-  public MD5Hash(String hex) {
-    setDigest(hex);
-  }
-
-  /** Constructs an MD5Hash with a specified value. */
-  @SuppressFBWarnings("EI_EXPOSE_REP2")
-  public MD5Hash(byte[] digest) {
-    if (digest.length != MD5_LEN) {
-      throw new IllegalArgumentException("Wrong length: " + digest.length);
-    }
-    this.digest = digest;
-  }
-
-  public void readFields(DataInput in) throws IOException {
-    in.readFully(digest);
-  }
-
-  /** Constructs, reads and returns an instance. */
-  public static MD5Hash read(DataInput in) throws IOException {
-    MD5Hash result = new MD5Hash();
-    result.readFields(in);
-    return result;
-  }
-
-  public void write(DataOutput out) throws IOException {
-    out.write(digest);
-  }
-
-  /** Copy the contents of another instance into this instance. */
-  public void set(MD5Hash that) {
-    System.arraycopy(that.digest, 0, this.digest, 0, MD5_LEN);
-  }
-
-  /** Returns the digest bytes. */
-  @SuppressFBWarnings("EI_EXPOSE_REP")
-  public byte[] getDigest() {
-    return digest;
-  }
-
-  /** Construct a hash value for a byte array. */
-  public static MD5Hash digest(byte[] data) {
-    return digest(data, 0, data.length);
-  }
-
-  /**
-   * Create a thread local MD5 digester
-   */
-  public static MessageDigest getDigester() {
-    MessageDigest digester = DIGESTER_FACTORY.get();
-    digester.reset();
-    return digester;
-  }
-
-  /** Construct a hash value for the content from the InputStream. */
-  public static MD5Hash digest(InputStream in) throws IOException {
-    final byte[] buffer = new byte[4*1024];
-
-    final MessageDigest digester = getDigester();
-    for(int n; (n = in.read(buffer)) != -1; ) {
-      digester.update(buffer, 0, n);
-    }
-
-    return new MD5Hash(digester.digest());
-  }
-
-  /** Construct a hash value for a byte array. */
-  public static MD5Hash digest(byte[] data, int start, int len) {
-    byte[] digest;
-    MessageDigest digester = getDigester();
-    digester.update(data, start, len);
-    digest = digester.digest();
-    return new MD5Hash(digest);
-  }
-
-  /** Construct a hash value for an array of byte array. */
-  public static MD5Hash digest(byte[][] dataArr, int start, int len) {
-    byte[] digest;
-    MessageDigest digester = getDigester();
-    for (byte[] data : dataArr) {
-      digester.update(data, start, len);
-    }
-    digest = digester.digest();
-    return new MD5Hash(digest);
-  }
-
-  /** Construct a half-sized version of this MD5.  Fits in a long **/
-  public long halfDigest() {
-    long value = 0;
-    for (int i = 0; i < 8; i++) {
-      value |= ((digest[i] & 0xffL) << (8*(7-i)));
-    }
-    return value;
-  }
-
-  /**
-   * Return a 32-bit digest of the MD5.
-   * @return the first 4 bytes of the md5
-   */
-  public int quarterDigest() {
-    int value = 0;
-    for (int i = 0; i < 4; i++) {
-      value |= ((digest[i] & 0xff) << (8*(3-i)));
-    }
-    return value;
-  }
-
-  /** Returns true iff <code>o</code> is an MD5Hash whose digest contains the
-   * same values.  */
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof MD5Hash)) {
-      return false;
-    }
-    MD5Hash other = (MD5Hash)o;
-    return Arrays.equals(this.digest, other.digest);
-  }
-
-  /** Returns a hash code value for this object.
-   * Only uses the first 4 bytes, since md5s are evenly distributed.
-   */
-  @Override
-  public int hashCode() {
-    return quarterDigest();
-  }
-
-  private static final char[] HEX_DIGITS =
-      {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
-
-  /** Returns a string representation of this object. */
-  @Override
-  public String toString() {
-    StringBuilder buf = new StringBuilder(MD5_LEN*2);
-    for (int i = 0; i < MD5_LEN; i++) {
-      int b = digest[i];
-      buf.append(HEX_DIGITS[(b >> 4) & 0xf]);
-      buf.append(HEX_DIGITS[b & 0xf]);
-    }
-    return buf.toString();
-  }
-
-  /** Sets the digest value from a hex string. */
-  public void setDigest(String hex) {
-    if (hex.length() != MD5_LEN*2) {
-      throw new IllegalArgumentException("Wrong length: " + hex.length());
-    }
-    this.digest = new byte[MD5_LEN];
-    for (int i = 0; i < MD5_LEN; i++) {
-      int j = i << 1;
-      this.digest[i] = (byte)(charToNibble(hex.charAt(j)) << 4 |
-          charToNibble(hex.charAt(j+1)));
-    }
-  }
-
-  private static int charToNibble(char c) {
-    if (c >= '0' && c <= '9') {
-      return c - '0';
-    } else if (c >= 'a' && c <= 'f') {
-      return 0xa + (c - 'a');
-    } else if (c >= 'A' && c <= 'F') {
-      return 0xA + (c - 'A');
-    } else {
-      throw new RuntimeException("Not a hex character: " + c);
-    }
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/io/StandardWriteOption.java b/ratis-common/src/main/java/org/apache/ratis/io/StandardWriteOption.java
deleted file mode 100644
index 0aae8f9..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/io/StandardWriteOption.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.io;
-
-public enum StandardWriteOption implements WriteOption {
-  /** Sync the data to the underlying storage. */
-  SYNC,
-  /** Close the data to the underlying storage. */
-  CLOSE
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/io/WriteOption.java b/ratis-common/src/main/java/org/apache/ratis/io/WriteOption.java
deleted file mode 100644
index 11760c4..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/io/WriteOption.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.io;
-
-public interface WriteOption {
-  static boolean containsOption(WriteOption[] options, WriteOption target) {
-    for (WriteOption option : options) {
-      if (option == target) {
-        return true;
-      }
-    }
-
-    return false;
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/AdminAsynchronousProtocol.java b/ratis-common/src/main/java/org/apache/ratis/protocol/AdminAsynchronousProtocol.java
deleted file mode 100644
index 9c7d62c..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/AdminAsynchronousProtocol.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * 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.protocol;
-
-import java.io.IOException;
-import java.util.concurrent.CompletableFuture;
-
-/** Asynchronous version of {@link AdminProtocol}. */
-public interface AdminAsynchronousProtocol {
-  CompletableFuture<GroupListReply> getGroupListAsync(GroupListRequest request);
-
-  CompletableFuture<GroupInfoReply> getGroupInfoAsync(GroupInfoRequest request);
-
-  CompletableFuture<RaftClientReply> groupManagementAsync(GroupManagementRequest request);
-
-  CompletableFuture<RaftClientReply> snapshotManagementAsync(SnapshotManagementRequest request);
-
-  CompletableFuture<RaftClientReply> setConfigurationAsync(
-      SetConfigurationRequest request) throws IOException;
-
-  CompletableFuture<RaftClientReply> transferLeadershipAsync(
-      TransferLeadershipRequest request) throws IOException;
-}
\ No newline at end of file
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/AdminProtocol.java b/ratis-common/src/main/java/org/apache/ratis/protocol/AdminProtocol.java
deleted file mode 100644
index 849466a..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/AdminProtocol.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * 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.protocol;
-
-import java.io.IOException;
-
-/** For server administration. */
-public interface AdminProtocol {
-  GroupListReply getGroupList(GroupListRequest request) throws IOException;
-
-  GroupInfoReply getGroupInfo(GroupInfoRequest request) throws IOException;
-
-  RaftClientReply groupManagement(GroupManagementRequest request) throws IOException;
-
-  RaftClientReply snapshotManagement(SnapshotManagementRequest request) throws IOException;
-
-  RaftClientReply setConfiguration(SetConfigurationRequest request) throws IOException;
-
-  RaftClientReply transferLeadership(TransferLeadershipRequest request) throws IOException;
-}
\ No newline at end of file
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/ClientId.java b/ratis-common/src/main/java/org/apache/ratis/protocol/ClientId.java
deleted file mode 100644
index 8c3e4c7..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/ClientId.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.thirdparty.com.google.protobuf.ByteString;
-
-import java.util.Optional;
-import java.util.UUID;
-
-/**
- * Id of Raft client. Should be globally unique so that raft peers can use it
- * to correctly identify retry requests from the same client.
- */
-public final class ClientId extends RaftId {
-  private static final ClientId EMPTY_CLIENT_ID = new ClientId(ZERO_UUID_BYTESTRING);
-
-  public static ClientId emptyClientId() {
-    return EMPTY_CLIENT_ID;
-  }
-
-  public static ClientId randomId() {
-    return new ClientId(UUID.randomUUID());
-  }
-
-  public static ClientId valueOf(ByteString data) {
-    return Optional.ofNullable(data).filter(d -> !d.isEmpty()).map(ClientId::new).orElse(EMPTY_CLIENT_ID);
-  }
-
-  public static ClientId valueOf(UUID uuid) {
-    return new ClientId(uuid);
-  }
-
-  private ClientId(ByteString data) {
-    super(data);
-  }
-
-  private ClientId(UUID uuid) {
-    super(uuid);
-  }
-
-  @Override
-  String createUuidString(UUID uuid) {
-    return "client-" + super.createUuidString(uuid);
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/ClientInvocationId.java b/ratis-common/src/main/java/org/apache/ratis/protocol/ClientInvocationId.java
deleted file mode 100644
index 24e491e..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/ClientInvocationId.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.proto.RaftProtos.StateMachineLogEntryProto;
-
-import java.util.Objects;
-import java.util.Optional;
-
-/**
- * The id of a client invocation.
- * A client invocation may be an RPC or a stream.
- *
- * This is a value-based class.
- */
-public final class ClientInvocationId {
-  public static ClientInvocationId valueOf(ClientId clientId, long invocationId) {
-    return new ClientInvocationId(clientId, invocationId);
-  }
-
-  public static ClientInvocationId valueOf(RaftClientMessage message) {
-    return valueOf(message.getClientId(), message.getCallId());
-  }
-
-  public static ClientInvocationId valueOf(StateMachineLogEntryProto proto) {
-    return valueOf(ClientId.valueOf(proto.getClientId()), proto.getCallId());
-  }
-
-  private final ClientId clientId;
-  /** It may be a call id or a stream id. */
-  private final long longId;
-
-  private ClientInvocationId(ClientId clientId, long longId) {
-    this.clientId = clientId;
-    this.longId = longId;
-  }
-
-  public ClientId getClientId() {
-    return clientId;
-  }
-
-  public long getLongId() {
-    return longId;
-  }
-
-  public boolean match(StateMachineLogEntryProto proto) {
-    return longId == proto.getCallId() && Optional.ofNullable(clientId)
-        .map(RaftId::toByteString)
-        .filter(b -> b.equals(proto.getClientId()))
-        .isPresent();
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (this == obj) {
-      return true;
-    } else if (obj == null || getClass() != obj.getClass()) {
-      return false;
-    }
-    final ClientInvocationId that = (ClientInvocationId) obj;
-    return this.longId == that.longId && Objects.equals(this.clientId, that.clientId);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(clientId, longId);
-  }
-
-  @Override
-  public String toString() {
-    return longId + "@" + clientId;
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamPacket.java b/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamPacket.java
deleted file mode 100644
index caebb9e..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamPacket.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.proto.RaftProtos.DataStreamPacketHeaderProto.Type;
-
-public interface DataStreamPacket {
-  ClientId getClientId();
-
-  Type getType();
-
-  long getStreamId();
-
-  long getStreamOffset();
-
-  long getDataLength();
-}
\ No newline at end of file
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamPacketHeader.java b/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamPacketHeader.java
deleted file mode 100644
index 842cf28..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamPacketHeader.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.datastream.impl.DataStreamPacketImpl;
-import org.apache.ratis.proto.RaftProtos.DataStreamPacketHeaderProto.Type;
-import org.apache.ratis.util.SizeInBytes;
-
-/** The header format is streamId, streamOffset, dataLength. */
-public class DataStreamPacketHeader extends DataStreamPacketImpl {
-  private static final SizeInBytes SIZE_OF_HEADER_LEN = SizeInBytes.valueOf(4);
-  private static final SizeInBytes SIZE_OF_HEADER_BODY_LEN = SizeInBytes.valueOf(8);
-
-  private final long dataLength;
-
-  public DataStreamPacketHeader(ClientId clientId, Type type, long streamId, long streamOffset, long dataLength) {
-    super(clientId, type, streamId, streamOffset);
-    this.dataLength = dataLength;
-  }
-
-  @Override
-  public long getDataLength() {
-    return dataLength;
-  }
-
-  public static int getSizeOfHeaderLen() {
-    return SIZE_OF_HEADER_LEN.getSizeInt();
-  }
-
-  public static int getSizeOfHeaderBodyLen() {
-    return SIZE_OF_HEADER_BODY_LEN.getSizeInt();
-  }
-}
\ No newline at end of file
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamReply.java b/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamReply.java
deleted file mode 100644
index 459aee3..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamReply.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.proto.RaftProtos.CommitInfoProto;
-
-import java.util.Collection;
-
-public interface DataStreamReply extends DataStreamPacket {
-
-  boolean isSuccess();
-
-  long getBytesWritten();
-
-  /** @return the commit information when the reply is created. */
-  Collection<CommitInfoProto> getCommitInfos();
-}
\ No newline at end of file
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamReplyHeader.java b/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamReplyHeader.java
deleted file mode 100644
index 502b426..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamReplyHeader.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.proto.RaftProtos.CommitInfoProto;
-import org.apache.ratis.proto.RaftProtos.DataStreamPacketHeaderProto.Type;
-
-import java.util.Collection;
-import java.util.Collections;
-
-/** The header format is {@link DataStreamPacketHeader}, bytesWritten and flags. */
-public class DataStreamReplyHeader extends DataStreamPacketHeader implements DataStreamReply {
-  private final long bytesWritten;
-  private final boolean success;
-  private final Collection<CommitInfoProto> commitInfos;
-
-  @SuppressWarnings("parameternumber")
-  public DataStreamReplyHeader(ClientId clientId, Type type, long streamId, long streamOffset, long dataLength,
-      long bytesWritten, boolean success, Collection<CommitInfoProto> commitInfos) {
-    super(clientId, type, streamId, streamOffset, dataLength);
-    this.bytesWritten = bytesWritten;
-    this.success = success;
-    this.commitInfos = commitInfos != null? commitInfos: Collections.emptyList();
-  }
-
-  @Override
-  public long getBytesWritten() {
-    return bytesWritten;
-  }
-
-  @Override
-  public boolean isSuccess() {
-    return success;
-  }
-
-  @Override
-  public Collection<CommitInfoProto> getCommitInfos() {
-    return commitInfos;
-  }
-}
\ No newline at end of file
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamRequest.java b/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamRequest.java
deleted file mode 100644
index cf09208..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamRequest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.io.WriteOption;
-
-public interface DataStreamRequest extends DataStreamPacket {
-  WriteOption[] getWriteOptions();
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamRequestHeader.java b/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamRequestHeader.java
deleted file mode 100644
index f2fbc15..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/DataStreamRequestHeader.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.protocol;
-
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import org.apache.ratis.io.WriteOption;
-import org.apache.ratis.proto.RaftProtos.DataStreamPacketHeaderProto.Type;
-
-/**
- * The header format is the same {@link DataStreamPacketHeader}
- * since there are no additional fields.
- */
-public class DataStreamRequestHeader extends DataStreamPacketHeader implements DataStreamRequest {
-
-  private final WriteOption[] options;
-
-  @SuppressFBWarnings("EI_EXPOSE_REP2")
-  public DataStreamRequestHeader(ClientId clientId, Type type, long streamId, long streamOffset, long dataLength,
-      WriteOption... options) {
-    super(clientId, type, streamId, streamOffset, dataLength);
-    this.options = options;
-  }
-
-  @Override
-  @SuppressFBWarnings("EI_EXPOSE_REP")
-  public WriteOption[] getWriteOptions() {
-    return options;
-  }
-}
\ No newline at end of file
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/GroupInfoReply.java b/ratis-common/src/main/java/org/apache/ratis/protocol/GroupInfoReply.java
deleted file mode 100644
index 946bf23..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/GroupInfoReply.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.proto.RaftProtos.CommitInfoProto;
-import org.apache.ratis.proto.RaftProtos.RoleInfoProto;
-
-import java.util.Collection;
-
-/**
- * The response of server information request. Sent from server to client.
- */
-public class GroupInfoReply extends RaftClientReply {
-
-  private final RaftGroup group;
-  private final RoleInfoProto roleInfoProto;
-  private final boolean isRaftStorageHealthy;
-
-  public GroupInfoReply(RaftClientRequest request, Collection<CommitInfoProto> commitInfos,
-      RaftGroup group, RoleInfoProto roleInfoProto, boolean isRaftStorageHealthy) {
-    this(request.getClientId(), request.getServerId(), request.getRaftGroupId(), request.getCallId(), commitInfos,
-        group, roleInfoProto, isRaftStorageHealthy);
-  }
-
-  @SuppressWarnings("parameternumber")
-  public GroupInfoReply(ClientId clientId, RaftPeerId serverId, RaftGroupId groupId, long callId,
-      Collection<CommitInfoProto> commitInfos,
-      RaftGroup group, RoleInfoProto roleInfoProto, boolean isRaftStorageHealthy) {
-    super(clientId, serverId, groupId, callId, true, null, null, 0L, commitInfos);
-    this.group = group;
-    this.roleInfoProto = roleInfoProto;
-    this.isRaftStorageHealthy = isRaftStorageHealthy;
-  }
-
-  public RaftGroup getGroup() {
-    return group;
-  }
-
-  public RoleInfoProto getRoleInfoProto() {
-    return roleInfoProto;
-  }
-
-  public boolean isRaftStorageHealthy() {
-    return isRaftStorageHealthy;
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/GroupInfoRequest.java b/ratis-common/src/main/java/org/apache/ratis/protocol/GroupInfoRequest.java
deleted file mode 100644
index a62495e..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/GroupInfoRequest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.protocol;
-
-/**
- * Client sends this request to a server to request for the information about
- * the server itself.
- */
-public class GroupInfoRequest extends RaftClientRequest {
-  public GroupInfoRequest(ClientId clientId, RaftPeerId serverId, RaftGroupId groupId, long callId) {
-    super(clientId, serverId, groupId, callId, false, readRequestType());
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/GroupListReply.java b/ratis-common/src/main/java/org/apache/ratis/protocol/GroupListReply.java
deleted file mode 100644
index bdc13f2..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/GroupListReply.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.protocol;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * The response of group list request. Sent from server to client.
- */
-public class GroupListReply extends RaftClientReply {
-
-  private final List<RaftGroupId> groupIds;
-
-  public GroupListReply(RaftClientRequest request,  List<RaftGroupId> groupIds) {
-    this(request.getClientId(), request.getServerId(), request.getRaftGroupId(), request.getCallId(), groupIds);
-  }
-
-  public GroupListReply(ClientId clientId, RaftPeerId serverId, RaftGroupId groupId, long callId,
-      List<RaftGroupId> groupIds) {
-    super(clientId, serverId, groupId, callId, true, null, null, 0L, null);
-    this.groupIds = Collections.unmodifiableList(groupIds);
-  }
-
-  public List<RaftGroupId> getGroupIds() {
-    return groupIds;
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/GroupListRequest.java b/ratis-common/src/main/java/org/apache/ratis/protocol/GroupListRequest.java
deleted file mode 100644
index e28e7b1..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/GroupListRequest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.protocol;
-
-/**
- * Client sends this request to a server to request for the information about
- * the server itself.
- */
-public class GroupListRequest extends RaftClientRequest {
-  public GroupListRequest(ClientId clientId, RaftPeerId serverId, RaftGroupId groupId, long callId) {
-    super(clientId, serverId, groupId, callId, false, readRequestType());
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/GroupManagementRequest.java b/ratis-common/src/main/java/org/apache/ratis/protocol/GroupManagementRequest.java
deleted file mode 100644
index d370dfc..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/GroupManagementRequest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.util.JavaUtils;
-
-public final class GroupManagementRequest extends RaftClientRequest {
-  public abstract static class Op {
-    public abstract RaftGroupId getGroupId();
-  }
-
-  public static class Add extends Op {
-    private final RaftGroup group;
-
-    public Add(RaftGroup group) {
-      this.group = group;
-    }
-
-    @Override
-    public RaftGroupId getGroupId() {
-      return getGroup().getGroupId();
-    }
-
-    public RaftGroup getGroup() {
-      return group;
-    }
-
-    @Override
-    public String toString() {
-      return JavaUtils.getClassSimpleName(getClass()) + ":" + getGroup();
-    }
-  }
-
-  public static class Remove extends Op {
-    private final RaftGroupId groupId;
-    private final boolean deleteDirectory;
-    private final boolean renameDirectory;
-
-    public Remove(RaftGroupId groupId, boolean deleteDirectory,
-        boolean renameDirectory) {
-      this.groupId = groupId;
-      this.deleteDirectory = deleteDirectory;
-      this.renameDirectory = renameDirectory;
-    }
-
-    @Override
-    public RaftGroupId getGroupId() {
-      return groupId;
-    }
-
-    public boolean isDeleteDirectory() {
-      return deleteDirectory;
-    }
-
-    public boolean isRenameDirectory() {
-      return renameDirectory;
-    }
-
-    @Override
-    public String toString() {
-      return JavaUtils.getClassSimpleName(getClass()) + ":" + getGroupId() + ", "
-          + (deleteDirectory? "delete": (renameDirectory ? "rename" : "retain"))
-          + "-dir";
-    }
-  }
-
-  public static GroupManagementRequest newAdd(ClientId clientId, RaftPeerId serverId, long callId, RaftGroup group) {
-    return new GroupManagementRequest(clientId, serverId, callId, new Add(group));
-  }
-
-  public static GroupManagementRequest newRemove(ClientId clientId, RaftPeerId serverId, long callId,
-      RaftGroupId groupId, boolean deleteDirectory, boolean renameDirectory) {
-    return new GroupManagementRequest(clientId, serverId, callId,
-        new Remove(groupId, deleteDirectory, renameDirectory));
-  }
-
-  private final Op op;
-
-  private GroupManagementRequest(ClientId clientId, RaftPeerId serverId, long callId, Op op) {
-    super(clientId, serverId, op.getGroupId(), callId, false, writeRequestType());
-    this.op = op;
-  }
-
-  public Add getAdd() {
-    return op instanceof Add? (Add)op: null;
-  }
-
-  public Remove getRemove() {
-    return op instanceof Remove? (Remove)op: null;
-  }
-
-  @Override
-  public String toString() {
-    return super.toString() + ", " + op;
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/LeaderElectionRequest.java b/ratis-common/src/main/java/org/apache/ratis/protocol/LeaderElectionRequest.java
deleted file mode 100644
index bce0178..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/LeaderElectionRequest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.util.JavaUtils;
-
-public final class LeaderElectionRequest extends RaftClientRequest{
-  public abstract static class Op {
-
-  }
-  public static class Pause extends Op {
-    @Override
-    public String toString() {
-      return JavaUtils.getClassSimpleName(getClass()) + ":" ;
-    }
-  }
-
-  public static class Resume extends Op {
-    @Override
-    public String toString() {
-      return JavaUtils.getClassSimpleName(getClass()) + ":" ;
-    }
-  }
-
-  public static LeaderElectionRequest newPause(ClientId clientId,
-      RaftPeerId serverId, RaftGroupId groupId, long callId, long timeoutMs) {
-    return new LeaderElectionRequest(clientId,
-        serverId, groupId, callId, timeoutMs,new LeaderElectionRequest.Pause());
-  }
-
-  public static LeaderElectionRequest newResume(ClientId clientId,
-      RaftPeerId serverId, RaftGroupId groupId, long callId, long timeoutMs) {
-    return new LeaderElectionRequest(clientId,
-        serverId, groupId, callId, timeoutMs,new LeaderElectionRequest.Resume());
-  }
-
-  private final Op op;
-
-  public LeaderElectionRequest(
-      ClientId clientId, RaftPeerId serverId, RaftGroupId groupId, long callId, long timeoutMs, Op op) {
-    super(clientId, serverId, groupId, callId, readRequestType(), timeoutMs);
-    this.op = op;
-  }
-
-  public Pause getPause() {
-    return op instanceof Pause ? (Pause) op: null;
-  }
-
-  public Resume getResume() {
-    return op instanceof Resume ? (Resume) op : null;
-  }
-
-
-  @Override
-  public String toString() {
-    return super.toString() + ", " + op;
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/Message.java b/ratis-common/src/main/java/org/apache/ratis/protocol/Message.java
deleted file mode 100644
index b47f430..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/Message.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.thirdparty.com.google.protobuf.ByteString;
-import org.apache.ratis.util.MemoizedSupplier;
-import org.apache.ratis.util.StringUtils;
-
-import java.util.Optional;
-import java.util.function.Supplier;
-
-/**
- * The information clients append to the raft ring.
- */
-@FunctionalInterface
-public interface Message {
-  static Message valueOf(ByteString bytes, Supplier<String> stringSupplier) {
-    return new Message() {
-      private final MemoizedSupplier<String> memoized = MemoizedSupplier.valueOf(stringSupplier);
-
-      @Override
-      public ByteString getContent() {
-        return bytes;
-      }
-
-      @Override
-      public String toString() {
-        return memoized.get();
-      }
-    };
-  }
-
-  static Message valueOf(ByteString bytes) {
-    return valueOf(bytes, () -> "Message:" + StringUtils.bytes2HexShortString(bytes));
-  }
-
-  static Message valueOf(String string) {
-    return valueOf(ByteString.copyFromUtf8(string), () -> "Message:" + string);
-  }
-
-  static int getSize(Message message) {
-    return Optional.ofNullable(message).map(Message::size).orElse(0);
-  }
-
-  Message EMPTY = valueOf(ByteString.EMPTY);
-
-  /**
-   * @return the content of the message
-   */
-  ByteString getContent();
-
-  default int size() {
-    return Optional.ofNullable(getContent()).map(ByteString::size).orElse(0);
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientAsynchronousProtocol.java b/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientAsynchronousProtocol.java
deleted file mode 100644
index 1a9f83c..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientAsynchronousProtocol.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * 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.protocol;
-
-import java.io.IOException;
-import java.util.concurrent.CompletableFuture;
-
-/** Asynchronous version of {@link RaftClientProtocol}. */
-public interface RaftClientAsynchronousProtocol {
-  CompletableFuture<RaftClientReply> submitClientRequestAsync(
-      RaftClientRequest request) throws IOException;
-
-}
\ No newline at end of file
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientMessage.java b/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientMessage.java
deleted file mode 100644
index 8d3104a..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientMessage.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.util.JavaUtils;
-import org.apache.ratis.util.Preconditions;
-
-public abstract class RaftClientMessage implements RaftRpcMessage {
-  private final ClientId clientId;
-  private final RaftPeerId serverId;
-  private final RaftGroupId groupId;
-  private final long callId;
-
-  RaftClientMessage(ClientId clientId, RaftPeerId serverId, RaftGroupId groupId, long callId) {
-    this.clientId = Preconditions.assertNotNull(clientId, "clientId");
-    this.serverId = Preconditions.assertNotNull(serverId, "serverId");
-    this.groupId = Preconditions.assertNotNull(groupId, "groupId");
-    this.callId = callId;
-  }
-
-  @Override
-  public String getRequestorId() {
-    return clientId.toString();
-  }
-
-  @Override
-  public String getReplierId() {
-    return serverId.toString();
-  }
-
-  public ClientId getClientId() {
-    return clientId;
-  }
-
-  public RaftPeerId getServerId() {
-    return serverId;
-  }
-
-  @Override
-  public RaftGroupId getRaftGroupId() {
-    return groupId;
-  }
-
-  public long getCallId() {
-    return callId;
-  }
-
-  @Override
-  public String toString() {
-    return JavaUtils.getClassSimpleName(getClass()) + ":" + clientId + "->" + serverId
-        + (groupId != null? "@" + groupId: "") + ", cid=" + getCallId();
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientProtocol.java b/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientProtocol.java
deleted file mode 100644
index 44178b5..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientProtocol.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * 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.protocol;
-
-import java.io.IOException;
-
-public interface RaftClientProtocol {
-  RaftClientReply submitClientRequest(RaftClientRequest request) throws IOException;
-}
\ No newline at end of file
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientReply.java b/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientReply.java
deleted file mode 100644
index ada67c9..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientReply.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.proto.RaftProtos.CommitInfoProto;
-import org.apache.ratis.protocol.exceptions.AlreadyClosedException;
-import org.apache.ratis.protocol.exceptions.DataStreamException;
-import org.apache.ratis.protocol.exceptions.LeaderNotReadyException;
-import org.apache.ratis.protocol.exceptions.LeaderSteppingDownException;
-import org.apache.ratis.protocol.exceptions.NotLeaderException;
-import org.apache.ratis.protocol.exceptions.NotReplicatedException;
-import org.apache.ratis.protocol.exceptions.RaftException;
-import org.apache.ratis.protocol.exceptions.StateMachineException;
-import org.apache.ratis.protocol.exceptions.TransferLeadershipException;
-import org.apache.ratis.util.JavaUtils;
-import org.apache.ratis.util.Preconditions;
-import org.apache.ratis.util.ProtoUtils;
-import org.apache.ratis.util.ReflectionUtils;
-
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * Reply from server to client
- */
-public class RaftClientReply extends RaftClientMessage {
-  /**
-   * To build {@link RaftClientReply}
-   */
-  public static class Builder {
-    private ClientId clientId;
-    private RaftPeerId serverId;
-    private RaftGroupId groupId;
-    private long callId;
-
-    private boolean success;
-    private Message message;
-    private RaftException exception;
-
-    private long logIndex;
-    private Collection<CommitInfoProto> commitInfos;
-
-    public RaftClientReply build() {
-      return new RaftClientReply(clientId, serverId, groupId, callId,
-          success, message, exception, logIndex, commitInfos);
-    }
-
-    public Builder setClientId(ClientId clientId) {
-      this.clientId = clientId;
-      return this;
-    }
-
-    public Builder setServerId(RaftPeerId serverId) {
-      this.serverId = serverId;
-      return this;
-    }
-
-    public Builder setGroupId(RaftGroupId groupId) {
-      this.groupId = groupId;
-      return this;
-    }
-
-    public Builder setCallId(long callId) {
-      this.callId = callId;
-      return this;
-    }
-
-    public Builder setSuccess(boolean success) {
-      this.success = success;
-      return this;
-    }
-
-    public Builder setSuccess() {
-      return setSuccess(true);
-    }
-
-    public Builder setException(RaftException exception) {
-      this.exception = exception;
-      return this;
-    }
-
-    public Builder setMessage(Message message) {
-      this.message = message;
-      return this;
-    }
-
-    public Builder setLogIndex(long logIndex) {
-      this.logIndex = logIndex;
-      return this;
-    }
-
-    public Builder setCommitInfos(Collection<CommitInfoProto> commitInfos) {
-      this.commitInfos = commitInfos;
-      return this;
-    }
-
-    public Builder setServerId(RaftGroupMemberId serverId) {
-      return setServerId(serverId.getPeerId())
-          .setGroupId(serverId.getGroupId());
-    }
-
-    public Builder setClientInvocationId(ClientInvocationId invocationId) {
-      return setClientId(invocationId.getClientId())
-          .setCallId(invocationId.getLongId());
-    }
-
-    public Builder setRequest(RaftClientRequest request) {
-      return setClientId(request.getClientId())
-          .setServerId(request.getServerId())
-          .setGroupId(request.getRaftGroupId())
-          .setCallId(request.getCallId());
-    }
-  }
-
-  public static Builder newBuilder() {
-    return new Builder();
-  }
-
-  private final boolean success;
-
-  /**
-   * We mainly track two types of exceptions here:
-   * 1. NotLeaderException if the server is not leader
-   * 2. StateMachineException if the server's state machine returns an exception
-   */
-  private final RaftException exception;
-  private final Message message;
-
-  /**
-   * This field is the log index of the transaction
-   * if (1) the request is {@link org.apache.ratis.proto.RaftProtos.RaftClientRequestProto.TypeCase#WRITE} and (2) the
-   * reply is success.
-   * Otherwise, this field is not used.
-   */
-  private final long logIndex;
-  /** The commit information when the reply is created. */
-  private final Collection<CommitInfoProto> commitInfos;
-
-  @SuppressWarnings("parameternumber")
-  RaftClientReply(ClientId clientId, RaftPeerId serverId, RaftGroupId groupId,
-      long callId, boolean success, Message message, RaftException exception,
-      long logIndex, Collection<CommitInfoProto> commitInfos) {
-    super(clientId, serverId, groupId, callId);
-    this.success = success;
-    this.message = message;
-    this.exception = exception;
-    this.logIndex = logIndex;
-    this.commitInfos = commitInfos != null? commitInfos: Collections.emptyList();
-
-    if (exception != null) {
-      Preconditions.assertTrue(!success,
-          () -> "Inconsistent parameters: success && exception != null: " + this);
-      Preconditions.assertTrue(ReflectionUtils.isInstance(exception,
-          AlreadyClosedException.class,
-          NotLeaderException.class, NotReplicatedException.class,
-          LeaderNotReadyException.class, StateMachineException.class, DataStreamException.class,
-          LeaderSteppingDownException.class, TransferLeadershipException.class),
-          () -> "Unexpected exception class: " + this);
-    }
-  }
-
-  /**
-   * Get the commit information for the entire group.
-   * The commit information may be unavailable for exception reply.
-   *
-   * @return the commit information if it is available; otherwise, return null.
-   */
-  public Collection<CommitInfoProto> getCommitInfos() {
-    return commitInfos;
-  }
-
-  @Override
-  public final boolean isRequest() {
-    return false;
-  }
-
-  public long getLogIndex() {
-    return logIndex;
-  }
-
-  @Override
-  public String toString() {
-    return super.toString() + ", "
-        + (isSuccess()? "SUCCESS":  "FAILED " + exception)
-        + ", logIndex=" + getLogIndex() + ", commits" + ProtoUtils.toString(commitInfos);
-  }
-
-  public boolean isSuccess() {
-    return success;
-  }
-
-  public Message getMessage() {
-    return message;
-  }
-
-  /** If this reply has {@link AlreadyClosedException}, return it; otherwise return null. */
-  public AlreadyClosedException getAlreadyClosedException() {
-    return JavaUtils.cast(exception, AlreadyClosedException.class);
-  }
-
-  /** If this reply has {@link NotLeaderException}, return it; otherwise return null. */
-  public NotLeaderException getNotLeaderException() {
-    return JavaUtils.cast(exception, NotLeaderException.class);
-  }
-
-  /** If this reply has {@link NotReplicatedException}, return it; otherwise return null. */
-  public NotReplicatedException getNotReplicatedException() {
-    return JavaUtils.cast(exception, NotReplicatedException.class);
-  }
-
-  /** If this reply has {@link StateMachineException}, return it; otherwise return null. */
-  public StateMachineException getStateMachineException() {
-    return JavaUtils.cast(exception, StateMachineException.class);
-  }
-
-  /** If this reply has {@link DataStreamException}, return it; otherwise return null. */
-  public DataStreamException getDataStreamException() {
-    return JavaUtils.cast(exception, DataStreamException.class);
-  }
-
-  public LeaderNotReadyException getLeaderNotReadyException() {
-    return JavaUtils.cast(exception, LeaderNotReadyException.class);
-  }
-
-  public LeaderSteppingDownException getLeaderSteppingDownException() {
-    return JavaUtils.cast(exception, LeaderSteppingDownException.class);
-  }
-
-  public TransferLeadershipException getTransferLeadershipException() {
-    return JavaUtils.cast(exception, TransferLeadershipException.class);
-  }
-
-  /** @return the exception, if there is any; otherwise, return null. */
-  public RaftException getException() {
-    return exception;
-  }
-}
diff --git a/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientRequest.java b/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientRequest.java
deleted file mode 100644
index 8fef42d..0000000
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/RaftClientRequest.java
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * 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.protocol;
-
-import org.apache.ratis.proto.RaftProtos.*;
-import org.apache.ratis.util.Preconditions;
-import org.apache.ratis.util.ProtoUtils;
-
-import java.util.Objects;
-
-import static org.apache.ratis.proto.RaftProtos.RaftClientRequestProto.TypeCase.*;
-
-/**
- * Request from client to server
- */
-public class RaftClientRequest extends RaftClientMessage {
-  private static final Type DATA_STREAM_DEFAULT = new Type(DataStreamRequestTypeProto.getDefaultInstance());
-  private static final Type FORWARD_DEFAULT = new Type(ForwardRequestTypeProto.getDefaultInstance());
-  private static final Type WRITE_DEFAULT = new Type(WriteRequestTypeProto.getDefaultInstance());
-  private static final Type WATCH_DEFAULT = new Type(
-      WatchRequestTypeProto.newBuilder().setIndex(0L).setReplication(ReplicationLevel.MAJORITY).build());
-
-  private static final Type READ_DEFAULT = new Type(ReadRequestTypeProto.getDefaultInstance());
-  private static final Type STALE_READ_DEFAULT = new Type(StaleReadRequestTypeProto.getDefaultInstance());
-
-  public static Type writeRequestType() {
-    return WRITE_DEFAULT;
-  }
-
-  public static Type dataStreamRequestType() {
-    return DATA_STREAM_DEFAULT;
-  }
-
-  public static Type forwardRequestType() {
-    return FORWARD_DEFAULT;
-  }
-
-  public static Type messageStreamRequestType(long streamId, long messageId, boolean endOfRequest) {
-    return new Type(MessageStreamRequestTypeProto.newBuilder()
-        .setStreamId(streamId)
-        .setMessageId(messageId)
-        .setEndOfRequest(endOfRequest)
-        .build());
-  }
-
-  public static Type readRequestType() {
-    return READ_DEFAULT;
-  }
-
-  public static Type staleReadRequestType(long minIndex) {
-    return minIndex == 0L? STALE_READ_DEFAULT
-        : new Type(StaleReadRequestTypeProto.newBuilder().setMinIndex(minIndex).build());
-  }
-
-  public static Type watchRequestType() {
-    return WATCH_DEFAULT;
-  }
-  public static Type watchRequestType(long index, ReplicationLevel replication) {
-    return new Type(WatchRequestTypeProto.newBuilder().setIndex(index).setReplication(replication).build());
-  }
-
-  /** The type of a request (oneof write, read, staleRead, watch; see the message RaftClientRequestProto). */
-  public static final class Type {
-    public static Type valueOf(WriteRequestTypeProto write) {
-      return WRITE_DEFAULT;
-    }
-
-    public static Type valueOf(DataStreamRequestTypeProto dataStream) {
-      return DATA_STREAM_DEFAULT;
-    }
-
-    public static Type valueOf(ForwardRequestTypeProto forward) {
-      return FORWARD_DEFAULT;
-    }
-
-    public static Type valueOf(ReadRequestTypeProto read) {
-      return READ_DEFAULT;
-    }
-
-    public static Type valueOf(StaleReadRequestTypeProto staleRead) {
-      return staleRead.getMinIndex() == 0? STALE_READ_DEFAULT: new Type(staleRead);
-    }
-
-    public static Type valueOf(WatchRequestTypeProto watch) {
-      return watchRequestType(watch.getIndex(), watch.getReplication());
-    }
-
-    public static Type valueOf(MessageStreamRequestTypeProto messageStream) {
-      return messageStreamRequestType(
-          messageStream.getStreamId(), messageStream.getMessageId(), messageStream.getEndOfRequest());
-    }
-
-    /**
-     * The type case of the proto.
-     * Only the corresponding proto (must be non-null) is used.
-     * The other protos are ignored.
-     */
-    private final RaftClientRequestProto.TypeCase typeCase;
-    private final Object proto;
-
-    private Type(RaftClientRequestProto.TypeCase typeCase, Object proto) {
-      this.typeCase = Objects.requireNonNull(typeCase, "typeCase == null");
-      this.proto = Objects.requireNonNull(proto, "proto == null");
-    }
-
-    private Type(WriteRequestTypeProto write) {
-      this(WRITE, write);
-    }
-
-    private Type(DataStreamRequestTypeProto dataStream) {
-      this(DATASTREAM, dataStream);
-    }
-
-    private Type(ForwardRequestTypeProto forward) {
-      this(FORWARD, forward);
-    }
-
-    private Type(MessageStreamRequestTypeProto messageStream) {
-      this(MESSAGESTREAM, messageStream);
-    }
-
-    private Type(ReadRequestTypeProto read) {
-      this(READ, read);
-    }
-
-    private Type(StaleReadRequestTypeProto staleRead) {
-      this(STALEREAD, staleRead);
-    }
-
-    private Type(WatchRequestTypeProto watch) {
-      this(WATCH, watch);
-    }
-
-    public boolean is(RaftClientRequestProto.TypeCase tCase) {
-      return getTypeCase().equals(tCase);
-    }
-
-    public RaftClientRequestProto.TypeCase getTypeCase() {
-      return typeCase;
-    }
-
-    public WriteRequestTypeProto getWrite() {
-      Preconditions.assertTrue(is(WRITE));
-      return (WriteRequestTypeProto)proto;
-    }
-
-    public DataStreamRequestTypeProto getDataStream() {
-      Preconditions.assertTrue(is(DATASTREAM));
-      return (DataStreamRequestTypeProto)proto;
-    }
-
-    public ForwardRequestTypeProto getForward() {
-      Preconditions.assertTrue(is(FORWARD));
-      return (ForwardRequestTypeProto)proto;
-    }
-
-    public MessageStreamRequestTypeProto getMessageStream() {
-      Preconditions.assertTrue(is(MESSAGESTREAM), () -> "proto = " + proto);
-      return (MessageStreamRequestTypeProto)proto;
-    }
-
-    public ReadRequestTypeProto getRead() {
-      Preconditions.assertTrue(is(READ));
-      return (ReadRequestTypeProto)proto;
-    }
-
-    public StaleReadRequestTypeProto getStaleRead() {
-      Preconditions.assertTrue(is(STALEREAD));
-      return (StaleReadRequestTypeProto)proto;
-    }
-
-    public WatchRequestTypeProto getWatch() {
-      Preconditions.assertTrue(is(WATCH));
-      return (WatchRequestTypeProto)proto;
-    }
-
-    public static String toString(ReplicationLevel replication) {
-      return replication == ReplicationLevel.MAJORITY? "": "-" + replication;
-    }
-
-    public static String toString(WatchRequestTypeProto w) {
-      return "Watch" + toString(w.getReplication()) + "(" + w.getIndex() + ")";
-    }
-
-    public static String toString(MessageStreamRequestTypeProto s) {
-      return "MessageStream" + s.getStreamId() + "-" + s.getMessageId() + (s.getEndOfRequest()? "-eor": "");
-    }
-
-    @Override
-    public String toString() {
-      switch (typeCase) {
-        case WRITE:
-          return "RW";
-        case DATASTREAM:
-          return "DataStream";
-        case FORWARD:
-          return "Forward";
-        case MESSAGESTREAM:
-          return toString(getMessageStream());
-        case READ:
-          return "RO";
-        case STALEREAD:
-          return "StaleRead(" + getStaleRead().getMinIndex() + ")";
-        case WATCH:
-          return toString(getWatch());
... 71568 lines suppressed ...