diff --git a/hadoop-hdds/common/src/main/resources/ozone-default.xml b/hadoop-hdds/common/src/main/resources/ozone-default.xml
index d8e6c78e020..001153be9ab 100644
--- a/hadoop-hdds/common/src/main/resources/ozone-default.xml
+++ b/hadoop-hdds/common/src/main/resources/ozone-default.xml
@@ -1412,7 +1412,103 @@
1MB
OZONE, CLIENT, MANAGEMENT
Checksum will be computed for every bytes per checksum number
- of bytes and stored sequentially.
+ of bytes and stored sequentially. The minimum value for this config is
+ 256KB.
+
+
+
+
+ ozone.om.ratis.enable
+ false
+ OZONE, OM, RATIS, MANAGEMENT
+ Property to enable or disable Ratis server on OM.
+ Please note - this is a temporary property to disable OM Ratis server.
+
+
+
+
+ ozone.om.ratis.port
+ 9872
+ OZONE, OM, RATIS
+
+ The port number of the OzoneManager's Ratis server.
+
+
+
+
+ ozone.om.ratis.random.port
+ false
+ OZONE, OM, RATIS, DEBUG
+ Allocates a random free port for OM's Ratis server. This is
+ used only while running unit tests.
+
+
+
+
+ ozone.om.ratis.rpc.type
+ GRPC
+ OZONE, OM, RATIS, MANAGEMENT
+ Ratis supports different kinds of transports like netty, GRPC,
+ Hadoop RPC etc. This picks one of those for this cluster.
+
+
+
+
+ ozone.om.ratis.storage.dir
+
+ OZONE, OM, STORAGE, MANAGEMENT, RATIS
+ This directory is used for storing OM's Ratis metadata like
+ logs. If this is not set then default metadata dirs is used. A warning
+ will be logged if this not set. Ideally, this should be mapped to a
+ fast disk like an SSD.
+
+
+
+
+ ozone.om.ratis.segment.size
+ 16KB
+ OZONE, OM, RATIS, PERFORMANCE
+ The size of the raft segment used by Apache Ratis on OM.
+ (16 KB by default)
+
+
+
+
+ ozone.om.ratis.segment.preallocated.size
+ 128MB
+ OZONE, OM, RATIS, PERFORMANCE
+ The size of the buffer which is preallocated for raft segment
+ used by Apache Ratis on OM.(128 MB by default)
+
+
+
+
+ ozone.om.ratis.server.request.timeout
+ 3s
+ OZONE, OM, RATIS, MANAGEMENT
+ The timeout duration for OM's ratis server request .
+
+
+
+ ozone.om.ratis.server.retry.cache.timeout
+ 600000ms
+ OZONE, OM, RATIS, MANAGEMENT
+ Retry Cache entry timeout for OM's ratis server.
+
+
+
+ ozone.om.ratis.minimum.timeout
+ 1s
+ OZONE, OM, RATIS, MANAGEMENT
+ The minimum timeout duration for OM's Ratis server rpc.
+
+
+
+
+ ozone.om.ratis.client.request.timeout
+ 3s
+ OZONE, OM, RATIS, MANAGEMENT
+ The timeout duration for OM Ratis client request.
diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/HddsServerUtil.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/HddsServerUtil.java
index 40b3d7af42c..7a432f8dafb 100644
--- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/HddsServerUtil.java
+++ b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/HddsServerUtil.java
@@ -337,13 +337,16 @@ public static String getOzoneDatanodeRatisDirectory(Configuration conf) {
OzoneConfigKeys.DFS_CONTAINER_RATIS_DATANODE_STORAGE_DIR);
if (Strings.isNullOrEmpty(storageDir)) {
- LOG.warn("Storage directory for Ratis is not configured." +
- "Mapping Ratis storage under {}. It is a good idea " +
- "to map this to an SSD disk. Falling back to {}",
- storageDir, HddsConfigKeys.OZONE_METADATA_DIRS);
- File metaDirPath = ServerUtils.getOzoneMetaDirPath(conf);
- storageDir = (new File (metaDirPath, "ratis")).getPath();
+ storageDir = getDefaultRatisDirectory(conf);
}
return storageDir;
}
+
+ public static String getDefaultRatisDirectory(Configuration conf) {
+ LOG.warn("Storage directory for Ratis is not configured. It is a good " +
+ "idea to map this to an SSD disk. Falling back to {}",
+ HddsConfigKeys.OZONE_METADATA_DIRS);
+ File metaDirPath = ServerUtils.getOzoneMetaDirPath(conf);
+ return (new File(metaDirPath, "ratis")).getPath();
+ }
}
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java
index 739c75e456a..423d2516715 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java
@@ -17,7 +17,10 @@
package org.apache.hadoop.ozone.om;
+import java.util.concurrent.TimeUnit;
+
import org.apache.hadoop.ozone.OzoneAcl;
+import org.apache.ratis.util.TimeDuration;
/**
* Ozone Manager Constants.
@@ -86,4 +89,61 @@ private OMConfigKeys() {
public static final String OZONE_OM_METRICS_SAVE_INTERVAL =
"ozone.om.save.metrics.interval";
public static final String OZONE_OM_METRICS_SAVE_INTERVAL_DEFAULT = "5m";
+
+ /**
+ * OM Ratis related configurations.
+ */
+ public static final String OZONE_OM_RATIS_ENABLE_KEY
+ = "ozone.om.ratis.enable";
+ public static final boolean OZONE_OM_RATIS_ENABLE_DEFAULT
+ = false;
+ public static final String OZONE_OM_RATIS_PORT_KEY
+ = "ozone.om.ratis.port";
+ public static final int OZONE_OM_RATIS_PORT_DEFAULT
+ = 9872;
+ // When set to true, allocate a random free port for ozone ratis server
+ public static final String OZONE_OM_RATIS_RANDOM_PORT_KEY =
+ "ozone.om.ratis.random.port";
+ public static final boolean OZONE_OM_RATIS_RANDOM_PORT_KEY_DEFAULT
+ = false;
+ public static final String OZONE_OM_RATIS_RPC_TYPE_KEY
+ = "ozone.om.ratis.rpc.type";
+ public static final String OZONE_OM_RATIS_RPC_TYPE_DEFAULT
+ = "GRPC";
+
+ // OM Ratis Log configurations
+ public static final String OZONE_OM_RATIS_STORAGE_DIR
+ = "ozone.om.ratis.storage.dir";
+ public static final String OZONE_OM_RATIS_SEGMENT_SIZE_KEY
+ = "ozone.om.ratis.segment.size";
+ public static final String OZONE_OM_RATIS_SEGMENT_SIZE_DEFAULT
+ = "16KB";
+ public static final String OZONE_OM_RATIS_SEGMENT_PREALLOCATED_SIZE_KEY
+ = "ozone.om.ratis.segment.preallocated.size";
+ public static final String OZONE_OM_RATIS_SEGMENT_PREALLOCATED_SIZE_DEFAULT
+ = "128MB";
+
+ // OM Ratis server configurations
+ public static final String OZONE_OM_RATIS_SERVER_REQUEST_TIMEOUT_KEY
+ = "ozone.om.ratis.server.request.timeout";
+ public static final TimeDuration
+ OZONE_OM_RATIS_SERVER_REQUEST_TIMEOUT_DEFAULT
+ = TimeDuration.valueOf(3000, TimeUnit.MILLISECONDS);
+ public static final String
+ OZONE_OM_RATIS_SERVER_RETRY_CACHE_TIMEOUT_KEY
+ = "ozone.om.ratis.server.retry.cache.timeout";
+ public static final TimeDuration
+ OZONE_OM_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DEFAULT
+ = TimeDuration.valueOf(600000, TimeUnit.MILLISECONDS);
+ public static final String OZONE_OM_RATIS_MINIMUM_TIMEOUT_KEY
+ = "ozone.om.ratis.minimum.timeout";
+ public static final TimeDuration OZONE_OM_RATIS_MINIMUM_TIMEOUT_DEFAULT
+ = TimeDuration.valueOf(1, TimeUnit.SECONDS);
+
+ // OM Ratis client configurations
+ public static final String OZONE_OM_RATIS_CLIENT_REQUEST_TIMEOUT_KEY
+ = "ozone.om.ratis.client.request.timeout";
+ public static final TimeDuration
+ OZONE_OM_RATIS_CLIENT_REQUEST_TIMEOUT_DEFAULT
+ = TimeDuration.valueOf(3000, TimeUnit.MILLISECONDS);
}
diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManager.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManager.java
index 6f699c955d9..b75c6a60938 100644
--- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManager.java
+++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManager.java
@@ -62,6 +62,7 @@
import org.apache.hadoop.utils.db.Table;
import org.apache.hadoop.utils.db.Table.KeyValue;
import org.apache.hadoop.utils.db.TableIterator;
+import org.apache.ratis.util.LifeCycle;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
@@ -1368,4 +1369,25 @@ public void testGetServiceList() throws IOException {
Assert.assertEquals(NetUtils.createSocketAddr(
conf.get(OZONE_SCM_CLIENT_ADDRESS_KEY)), scmAddress);
}
+
+ /**
+ * Test that OM Ratis server is started only when OZONE_OM_RATIS_ENABLE_KEY is
+ * set to true.
+ */
+ @Test
+ public void testRatsiServerOnOmInitialization() throws IOException {
+ // OM Ratis server should not be started when OZONE_OM_RATIS_ENABLE_KEY
+ // is not set to true
+ Assert.assertNull("OM Ratis server started though OM Ratis is disabled.",
+ cluster.getOzoneManager().getOmRatisServerState());
+
+ // Enable OM Ratis and restart OM
+ conf.setBoolean(OMConfigKeys.OZONE_OM_RATIS_ENABLE_KEY, true);
+ cluster.restartOzoneManager();
+
+ // On enabling OM Ratis, the Ratis server should be started
+ Assert.assertEquals("OM Ratis server did not start",
+ LifeCycle.State.RUNNING,
+ cluster.getOzoneManager().getOmRatisServerState());
+ }
}
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
index 71dde34c69e..e79a923e742 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
@@ -66,6 +66,7 @@
import org.apache.hadoop.ozone.om.helpers.ServiceInfo;
import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol;
import org.apache.hadoop.ozone.om.protocolPB.OzoneManagerProtocolPB;
+import org.apache.hadoop.ozone.om.ratis.OzoneManagerRatisServer;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneAclInfo;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServicePort;
import org.apache.hadoop.ozone.protocolPB.OzoneManagerProtocolServerSideTranslatorPB;
@@ -73,6 +74,7 @@
import org.apache.hadoop.util.GenericOptionsParser;
import org.apache.hadoop.util.ShutdownHookManager;
import org.apache.hadoop.util.StringUtils;
+import org.apache.ratis.util.LifeCycle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -136,6 +138,7 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
private final OzoneConfiguration configuration;
private RPC.Server omRpcServer;
private InetSocketAddress omRpcAddress;
+ private OzoneManagerRatisServer omRatisServer;
private final OMMetadataManager metadataManager;
private final VolumeManager volumeManager;
private final BucketManager bucketManager;
@@ -509,6 +512,15 @@ public OMStorage getOmStorage() {
return omStorage;
}
+ @VisibleForTesting
+ public LifeCycle.State getOmRatisServerState() {
+ if (omRatisServer == null) {
+ return null;
+ } else {
+ return omRatisServer.getServerState();
+ }
+ }
+
/**
* Get metadata manager.
*
@@ -542,6 +554,22 @@ public void start() throws IOException {
LOG.info(buildRpcServerStartMessage("OzoneManager RPC server",
omRpcAddress));
+ boolean omRatisEnabled = configuration.getBoolean(
+ OMConfigKeys.OZONE_OM_RATIS_ENABLE_KEY,
+ OMConfigKeys.OZONE_OM_RATIS_ENABLE_DEFAULT);
+ // This is a temporary check. Once fully implemented, all OM state change
+ // should go through Ratis, either standalone (for non-HA) or replicated
+ // (for HA).
+ if (omRatisEnabled) {
+ omRatisServer = OzoneManagerRatisServer.newOMRatisServer(
+ omStorage.getOmId(), configuration);
+ omRatisServer.start();
+
+ LOG.info("OzoneManager Ratis server started at port {}",
+ omRatisServer.getServerPort());
+ } else {
+ omRatisServer = null;
+ }
DefaultMetricsSystem.initialize("OzoneManager");
@@ -584,6 +612,9 @@ public void stop() {
metricsTimer = null;
scheduleOMMetricsWriteTask = null;
omRpcServer.stop();
+ if (omRatisServer != null) {
+ omRatisServer.stop();
+ }
keyManager.stop();
httpServer.stop();
metadataManager.stop();
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/OzoneManagerRatisServer.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/OzoneManagerRatisServer.java
new file mode 100644
index 00000000000..de1fd6070dc
--- /dev/null
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/OzoneManagerRatisServer.java
@@ -0,0 +1,271 @@
+/*
+ * 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.hadoop.ozone.om.ratis;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Strings;
+import java.io.File;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.SocketAddress;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.conf.StorageUnit;
+import org.apache.hadoop.hdds.scm.HddsServerUtil;
+import org.apache.hadoop.ozone.om.OMConfigKeys;
+import org.apache.ratis.RaftConfigKeys;
+import org.apache.ratis.client.RaftClientConfigKeys;
+import org.apache.ratis.conf.RaftProperties;
+import org.apache.ratis.grpc.GrpcConfigKeys;
+import org.apache.ratis.netty.NettyConfigKeys;
+import org.apache.ratis.protocol.RaftGroupId;
+import org.apache.ratis.protocol.RaftPeerId;
+import org.apache.ratis.rpc.RpcType;
+import org.apache.ratis.rpc.SupportedRpcType;
+import org.apache.ratis.server.RaftServer;
+import org.apache.ratis.server.RaftServerConfigKeys;
+import org.apache.ratis.statemachine.impl.BaseStateMachine;
+import org.apache.ratis.util.LifeCycle;
+import org.apache.ratis.util.SizeInBytes;
+import org.apache.ratis.util.TimeDuration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Creates a Ratis server endpoint for OM.
+ */
+public final class OzoneManagerRatisServer {
+ private static final Logger LOG = LoggerFactory
+ .getLogger(OzoneManagerRatisServer.class);
+
+ private final int port;
+ private final RaftServer server;
+
+ private OzoneManagerRatisServer(String omId, int port, Configuration conf)
+ throws IOException {
+ Objects.requireNonNull(omId, "omId == null");
+ this.port = port;
+ RaftProperties serverProperties = newRaftProperties(conf);
+
+ this.server = RaftServer.newBuilder()
+ .setServerId(RaftPeerId.valueOf(omId))
+ .setProperties(serverProperties)
+ .setStateMachineRegistry(this::getStateMachine)
+ .build();
+ }
+
+ public static OzoneManagerRatisServer newOMRatisServer(String omId,
+ Configuration ozoneConf) throws IOException {
+ int localPort = ozoneConf.getInt(
+ OMConfigKeys.OZONE_OM_RATIS_PORT_KEY,
+ OMConfigKeys.OZONE_OM_RATIS_PORT_DEFAULT);
+
+ // Get an available port on current node and
+ // use that as the container port
+ if (ozoneConf.getBoolean(
+ OMConfigKeys.OZONE_OM_RATIS_RANDOM_PORT_KEY,
+ OMConfigKeys.OZONE_OM_RATIS_RANDOM_PORT_KEY_DEFAULT)) {
+ try (ServerSocket socket = new ServerSocket()) {
+ socket.setReuseAddress(true);
+ SocketAddress address = new InetSocketAddress(0);
+ socket.bind(address);
+ localPort = socket.getLocalPort();
+ LOG.info("Found a free port for the OM Ratis server : {}", localPort);
+ } catch (IOException e) {
+ LOG.error("Unable find a random free port for the server, "
+ + "fallback to use default port {}", localPort, e);
+ }
+ }
+ return new OzoneManagerRatisServer(omId, localPort, ozoneConf);
+ }
+
+ /**
+ * Return a dummy StateMachine.
+ * TODO: Implement a state machine on OM.
+ */
+ private BaseStateMachine getStateMachine(RaftGroupId gid) {
+ return new BaseStateMachine();
+ }
+
+ public void start() throws IOException {
+ LOG.info("Starting {} {} at port {}", getClass().getSimpleName(),
+ server.getId(), port);
+ server.start();
+ }
+
+ public void stop() {
+ try {
+ server.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private RaftProperties newRaftProperties(Configuration conf) {
+ final RaftProperties properties = new RaftProperties();
+
+ // Set RPC type
+ final String rpcType = conf.get(
+ OMConfigKeys.OZONE_OM_RATIS_RPC_TYPE_KEY,
+ OMConfigKeys.OZONE_OM_RATIS_RPC_TYPE_DEFAULT);
+ final RpcType rpc = SupportedRpcType.valueOfIgnoreCase(rpcType);
+ RaftConfigKeys.Rpc.setType(properties, rpc);
+
+ // Set the ratis port number
+ if (rpc == SupportedRpcType.GRPC) {
+ GrpcConfigKeys.Server.setPort(properties, port);
+ } else if (rpc == SupportedRpcType.NETTY) {
+ NettyConfigKeys.Server.setPort(properties, port);
+ }
+
+ // Set Ratis storage directory
+ String storageDir = getOMRatisDirectory(conf);
+ RaftServerConfigKeys.setStorageDirs(properties,
+ Collections.singletonList(new File(storageDir)));
+
+ // Set RAFT segment size
+ final int raftSegmentSize = (int) conf.getStorageSize(
+ OMConfigKeys.OZONE_OM_RATIS_SEGMENT_SIZE_KEY,
+ OMConfigKeys.OZONE_OM_RATIS_SEGMENT_SIZE_DEFAULT,
+ StorageUnit.BYTES);
+ RaftServerConfigKeys.Log.setSegmentSizeMax(properties,
+ SizeInBytes.valueOf(raftSegmentSize));
+
+ // Set RAFT segment pre-allocated size
+ final int raftSegmentPreallocatedSize = (int) conf.getStorageSize(
+ OMConfigKeys.OZONE_OM_RATIS_SEGMENT_PREALLOCATED_SIZE_KEY,
+ OMConfigKeys.OZONE_OM_RATIS_SEGMENT_PREALLOCATED_SIZE_DEFAULT,
+ StorageUnit.BYTES);
+ RaftServerConfigKeys.Log.Appender.setBufferCapacity(properties,
+ SizeInBytes.valueOf(raftSegmentPreallocatedSize));
+ RaftServerConfigKeys.Log.setPreallocatedSize(properties,
+ SizeInBytes.valueOf(raftSegmentPreallocatedSize));
+
+ // For grpc set the maximum message size
+ // TODO: calculate the max message size based on the max size of a
+ // PutSmallFileRequest's file size limit
+ GrpcConfigKeys.setMessageSizeMax(properties,
+ SizeInBytes.valueOf(raftSegmentPreallocatedSize));
+
+ // Set the server request timeout
+ TimeUnit serverRequestTimeoutUnit =
+ OMConfigKeys.OZONE_OM_RATIS_SERVER_REQUEST_TIMEOUT_DEFAULT.getUnit();
+ long serverRequestTimeoutDuration = conf.getTimeDuration(
+ OMConfigKeys.OZONE_OM_RATIS_SERVER_REQUEST_TIMEOUT_KEY,
+ OMConfigKeys.OZONE_OM_RATIS_SERVER_REQUEST_TIMEOUT_DEFAULT
+ .getDuration(), serverRequestTimeoutUnit);
+ final TimeDuration serverRequestTimeout = TimeDuration.valueOf(
+ serverRequestTimeoutDuration, serverRequestTimeoutUnit);
+ RaftServerConfigKeys.Rpc.setRequestTimeout(properties,
+ serverRequestTimeout);
+
+ // Set timeout for server retry cache entry
+ TimeUnit retryCacheTimeoutUnit = OMConfigKeys
+ .OZONE_OM_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DEFAULT.getUnit();
+ long retryCacheTimeoutDuration = conf.getTimeDuration(
+ OMConfigKeys.OZONE_OM_RATIS_SERVER_RETRY_CACHE_TIMEOUT_KEY,
+ OMConfigKeys.OZONE_OM_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DEFAULT
+ .getDuration(), retryCacheTimeoutUnit);
+ final TimeDuration retryCacheTimeout = TimeDuration.valueOf(
+ retryCacheTimeoutDuration, retryCacheTimeoutUnit);
+ RaftServerConfigKeys.RetryCache
+ .setExpiryTime(properties, retryCacheTimeout);
+
+ // Set the server min and max timeout
+ TimeUnit serverMinTimeoutUnit =
+ OMConfigKeys.OZONE_OM_RATIS_MINIMUM_TIMEOUT_DEFAULT.getUnit();
+ long serverMinTimeoutDuration = conf.getTimeDuration(
+ OMConfigKeys.OZONE_OM_RATIS_MINIMUM_TIMEOUT_KEY,
+ OMConfigKeys.OZONE_OM_RATIS_MINIMUM_TIMEOUT_DEFAULT
+ .getDuration(), serverMinTimeoutUnit);
+ final TimeDuration serverMinTimeout = TimeDuration.valueOf(
+ serverMinTimeoutDuration, serverMinTimeoutUnit);
+ long serverMaxTimeoutDuration =
+ serverMinTimeout.toLong(TimeUnit.MILLISECONDS) + 200;
+ final TimeDuration serverMaxTimeout = TimeDuration.valueOf(
+ serverMaxTimeoutDuration, serverMinTimeoutUnit);
+ RaftServerConfigKeys.Rpc.setTimeoutMin(properties,
+ serverMinTimeout);
+ RaftServerConfigKeys.Rpc.setTimeoutMax(properties,
+ serverMaxTimeout);
+
+ // Enable batch append on raft server
+ RaftServerConfigKeys.Log.Appender.setBatchEnabled(properties, true);
+
+ // Set the number of maximum cached segments
+ RaftServerConfigKeys.Log.setMaxCachedSegmentNum(properties, 2);
+
+ // Set the client request timeout
+ TimeUnit clientRequestTimeoutUnit =
+ OMConfigKeys.OZONE_OM_RATIS_CLIENT_REQUEST_TIMEOUT_DEFAULT.getUnit();
+ long clientRequestTimeoutDuration = conf.getTimeDuration(
+ OMConfigKeys.OZONE_OM_RATIS_CLIENT_REQUEST_TIMEOUT_KEY,
+ OMConfigKeys.OZONE_OM_RATIS_CLIENT_REQUEST_TIMEOUT_DEFAULT
+ .getDuration(), clientRequestTimeoutUnit);
+ final TimeDuration clientRequestTimeout = TimeDuration.valueOf(
+ clientRequestTimeoutDuration, clientRequestTimeoutUnit);
+ RaftClientConfigKeys.Rpc.setRequestTimeout(properties,
+ clientRequestTimeout);
+
+ // TODO: set max write buffer size
+
+ /**
+ * TODO: when state machine is implemented, enable StateMachineData sync
+ * and set sync timeout and number of sync retries.
+ */
+
+ /**
+ * TODO: set following ratis leader election related configs when
+ * replicated ratis server is implemented.
+ * 1. leader election timeout
+ * 2. node failure timeout
+ * 3.
+ */
+
+ /**
+ * TODO: when ratis snapshots are implemented, set snapshot threshold and
+ * queue size.
+ */
+
+ return properties;
+ }
+
+ public int getServerPort() {
+ return port;
+ }
+
+ @VisibleForTesting
+ public LifeCycle.State getServerState() {
+ return server.getLifeCycleState();
+ }
+
+ public static String getOMRatisDirectory(Configuration conf) {
+ String storageDir = conf.get(OMConfigKeys.OZONE_OM_RATIS_STORAGE_DIR);
+
+ if (Strings.isNullOrEmpty(storageDir)) {
+ storageDir = HddsServerUtil.getDefaultRatisDirectory(conf);
+ }
+ return storageDir;
+ }
+
+}
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/package-info.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/package-info.java
new file mode 100644
index 00000000000..ea25f133ebb
--- /dev/null
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/package-info.java
@@ -0,0 +1,22 @@
+/**
+ * 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.hadoop.ozone.om.ratis;
+
+/**
+ * This package contains classes for the OM Ratis server implementation.
+ */
\ No newline at end of file
diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/ratis/TestOzoneManagerRatisServer.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/ratis/TestOzoneManagerRatisServer.java
new file mode 100644
index 00000000000..564deb2e67b
--- /dev/null
+++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/ratis/TestOzoneManagerRatisServer.java
@@ -0,0 +1,69 @@
+/*
+ * 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.hadoop.ozone.om.ratis;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.UUID;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hdds.HddsConfigKeys;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.test.GenericTestUtils;
+import org.apache.ratis.util.LifeCycle;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test OM Ratis server.
+ */
+public class TestOzoneManagerRatisServer {
+
+ private Configuration conf;
+ private OzoneManagerRatisServer omRatisServer;
+ private String omID;
+
+ @Before
+ public void init() {
+ conf = new OzoneConfiguration();
+ omID = UUID.randomUUID().toString();
+ final String path = GenericTestUtils.getTempPath(omID);
+ Path metaDirPath = Paths.get(path, "om-meta");
+ conf.set(HddsConfigKeys.OZONE_METADATA_DIRS, metaDirPath.toString());
+ }
+
+ @After
+ public void shutdown() {
+ if (omRatisServer != null) {
+ omRatisServer.stop();
+ }
+ }
+
+ /**
+ * Start a OM Ratis Server and checks its state.
+ */
+ @Test
+ public void testStartOMRatisServer() throws Exception {
+ omRatisServer = OzoneManagerRatisServer.newOMRatisServer(omID, conf);
+ omRatisServer.start();
+ Assert.assertEquals("Ratis Server should be in running state",
+ LifeCycle.State.RUNNING, omRatisServer.getServerState());
+ }
+}