Skip to content

Commit

Permalink
HDDS-359. RocksDB Profiles support. Contributed by Anu Engineer.
Browse files Browse the repository at this point in the history
  • Loading branch information
elek committed Aug 28, 2018
1 parent df21e1b commit c61824a
Show file tree
Hide file tree
Showing 13 changed files with 1,040 additions and 20 deletions.
Expand Up @@ -17,6 +17,8 @@
*/
package org.apache.hadoop.hdds;

import org.apache.hadoop.utils.db.DBProfile;

/**
* This class contains constants for configuration keys and default values
* used in hdds.
Expand Down Expand Up @@ -58,4 +60,8 @@ private HddsConfigKeys() {
public static final String HDDS_DATANODE_VOLUME_CHOOSING_POLICY =
"hdds.datanode.volume.choosing.policy";

// DB Profiles used by ROCKDB instances.
public static final String HDDS_DB_PROFILE = "hdds.db.profile";
public static final DBProfile HDDS_DEFAULT_DB_PROFILE = DBProfile.SSD;

}
@@ -0,0 +1,134 @@
/*
* 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.utils.db;

import com.google.common.base.Preconditions;
import org.eclipse.jetty.util.StringUtil;
import org.rocksdb.ColumnFamilyDescriptor;
import org.rocksdb.DBOptions;
import org.rocksdb.Env;
import org.rocksdb.OptionsUtil;
import org.rocksdb.RocksDBException;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

/**
* A Class that controls the standard config options of RocksDB.
* <p>
* Important : Some of the functions in this file are magic functions designed
* for the use of OZONE developers only. Due to that this information is
* documented in this files only and is *not* intended for end user consumption.
* Please do not use this information to tune your production environments.
* Please remember the SpiderMan principal; with great power comes great
* responsibility.
*/
public final class DBConfigFromFile {
public static final String CONFIG_DIR = "HADOOP_CONF_DIR";

private DBConfigFromFile() {
}

public static File getConfigLocation() throws IOException {
String path = System.getenv(CONFIG_DIR);

// Make testing easy.
// If there is No Env. defined, let us try to read the JVM property
if (StringUtil.isBlank(path)) {
path = System.getProperty(CONFIG_DIR);
}

if (StringUtil.isBlank(path)) {
throw new IOException("Unable to find the configuration directory. "
+ "Please make sure that HADOOP_CONF_DIR is setup correctly ");
}
return new File(path);

}

/**
* This class establishes a magic pattern where we look for DBFile.ini as the
* options for RocksDB.
*
* @param dbFileName - The DBFile Name. For example, OzoneManager.db
* @return Name of the DB File options
*/
public static String getOptionsFileNameFromDB(String dbFileName) {
Preconditions.checkNotNull(dbFileName);
return dbFileName + ".ini";
}

/**
* One of the Magic functions designed for the use of Ozone Developers *ONLY*.
* This function takes the name of DB file and looks up the a .ini file that
* follows the ROCKSDB config format and uses that file for DBOptions and
* Column family Options. The Format for this file is specified by RockDB.
* <p>
* Here is a sample config from RocksDB sample Repo.
* <p>
* https://github.com/facebook/rocksdb/blob/master/examples
* /rocksdb_option_file_example.ini
* <p>
* We look for a specific pattern, say OzoneManager.db will have its configs
* specified in OzoneManager.db.ini. This option is used only by the
* performance testing group to allow tuning of all parameters freely.
* <p>
* For the end users we offer a set of Predefined options that is easy to use
* and the user does not need to become an expert in RockDB config.
* <p>
* This code assumes the .ini file is placed in the same directory as normal
* config files. That is in $HADOOP_DIR/etc/hadoop. For example, if we want to
* control OzoneManager.db configs from a file, we need to create a file
* called OzoneManager.db.ini and place that file in $HADOOP_DIR/etc/hadoop.
*
* @param dbFileName - The DB File Name, for example, OzoneManager.db.
* @param cfDescs - ColumnFamily Handles.
* @return DBOptions, Options to be used for opening/creating the DB.
* @throws IOException
*/
public static DBOptions readFromFile(String dbFileName,
List<ColumnFamilyDescriptor> cfDescs) throws IOException {
Preconditions.checkNotNull(dbFileName);
Preconditions.checkNotNull(cfDescs);
Preconditions.checkArgument(cfDescs.size() > 0);

//TODO: Add Documentation on how to support RocksDB Mem Env.
Env env = Env.getDefault();
DBOptions options = null;
Path optionsFile = Paths.get(getConfigLocation().toString(),
getOptionsFileNameFromDB(dbFileName));

if (optionsFile.toFile().exists()) {
options = new DBOptions();
try {
OptionsUtil.loadOptionsFromFile(optionsFile.toString(),
env, options, cfDescs, true);

} catch (RocksDBException rdEx) {
RDBTable.toIOException("Unable to find/open Options file.", rdEx);
}
}
return options;
}

}
@@ -0,0 +1,120 @@
/*
* 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.utils.db;

import org.apache.hadoop.conf.StorageUnit;
import org.rocksdb.BlockBasedTableConfig;
import org.rocksdb.BloomFilter;
import org.rocksdb.ColumnFamilyOptions;
import org.rocksdb.CompactionStyle;
import org.rocksdb.DBOptions;

import java.math.BigDecimal;

/**
* User visible configs based RocksDB tuning page. Documentation for Options.
* <p>
* https://github.com/facebook/rocksdb/blob/master/include/rocksdb/options.h
* <p>
* Most tuning parameters are based on this URL.
* <p>
* https://github.com/facebook/rocksdb/wiki/Setup-Options-and-Basic-Tuning
*/
public enum DBProfile {
//TODO : Add more profiles like TEST etc.
SSD {
@Override
public String toString() {
return "DBProfile.SSD";
}

@Override
public ColumnFamilyOptions getColumnFamilyOptions() {

// Set BlockCacheSize to 256 MB. This should not be an issue for HADOOP.
final long blockCacheSize = toLong(StorageUnit.MB.toBytes(256.00));

// Set the Default block size to 16KB
final long blockSize = toLong(StorageUnit.KB.toBytes(16));

// Write Buffer Size -- set to 128 MB
final long writeBufferSize = toLong(StorageUnit.MB.toBytes(128));

return new ColumnFamilyOptions()
.setLevelCompactionDynamicLevelBytes(true)
.setWriteBufferSize(writeBufferSize)
.setTableFormatConfig(
new BlockBasedTableConfig()
.setBlockCacheSize(blockCacheSize)
.setBlockSize(blockSize)
.setCacheIndexAndFilterBlocks(true)
.setPinL0FilterAndIndexBlocksInCache(true)
.setFilter(new BloomFilter()));
}

@Override
public DBOptions getDBOptions() {
final int maxBackgroundCompactions = 4;
final int maxBackgroundFlushes = 2;
final long bytesPerSync = toLong(StorageUnit.MB.toBytes(1.00));
final boolean createIfMissing = true;
final boolean createMissingColumnFamilies = true;
return new DBOptions()
.setIncreaseParallelism(Runtime.getRuntime().availableProcessors())
.setMaxBackgroundCompactions(maxBackgroundCompactions)
.setMaxBackgroundFlushes(maxBackgroundFlushes)
.setBytesPerSync(bytesPerSync)
.setCreateIfMissing(createIfMissing)
.setCreateMissingColumnFamilies(createMissingColumnFamilies);
}


},
DISK {
@Override
public String toString() {
return "DBProfile.DISK";
}

@Override
public DBOptions getDBOptions() {
final long readAheadSize = toLong(StorageUnit.MB.toBytes(4.00));
return SSD.getDBOptions().setCompactionReadaheadSize(readAheadSize);
}

@Override
public ColumnFamilyOptions getColumnFamilyOptions() {
ColumnFamilyOptions columnFamilyOptions = SSD.getColumnFamilyOptions();
columnFamilyOptions.setCompactionStyle(CompactionStyle.LEVEL);
return columnFamilyOptions;
}


};

private static long toLong(double value) {
BigDecimal temp = new BigDecimal(value);
return temp.longValue();
}

public abstract DBOptions getDBOptions();

public abstract ColumnFamilyOptions getColumnFamilyOptions();
}

0 comments on commit c61824a

Please sign in to comment.