This is an automated email from the ASF dual-hosted git repository.
siyao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 354d3dc5a1 HDDS-8028. JNI for RocksDB SST Dump tool (#4315)
354d3dc5a1 is described below
commit 354d3dc5a16eade52bdcbd566bfb952ac3a1d8b6
Author: Swaminathan Balachandran <[email protected]>
AuthorDate: Fri Mar 10 14:22:33 2023 -0800
HDDS-8028. JNI for RocksDB SST Dump tool (#4315)
---
hadoop-hdds/pom.xml | 6 +
hadoop-hdds/rocks-native/pom.xml | 421 +++++++++++++++++
hadoop-hdds/rocks-native/src/CMakeLists.txt | 78 +++
.../apache/hadoop/hdds/utils/NativeConstants.java | 31 ++
.../hadoop/hdds/utils/NativeLibraryLoader.java | 150 ++++++
.../utils/NativeLibraryNotLoadedException.java | 30 ++
.../utils/db/managed/ManagedSSTDumpIterator.java | 225 +++++++++
.../hdds/utils/db/managed/ManagedSSTDumpTool.java | 103 ++++
.../hdds/utils/db/managed/PipeInputStream.java | 99 ++++
.../hadoop/hdds/utils/db/managed/package-info.java | 24 +
.../org/apache/hadoop/hdds/utils/package-info.java | 24 +
hadoop-hdds/rocks-native/src/main/native/Pipe.cpp | 37 ++
hadoop-hdds/rocks-native/src/main/native/Pipe.h | 55 +++
.../src/main/native/PipeInputStream.cpp | 48 ++
.../rocks-native/src/main/native/SSTDumpTool.cpp | 48 ++
.../src/main/native/cplusplus_to_java_convert.h | 55 +++
.../src/main/patches/rocks-native.patch | 522 +++++++++++++++++++++
hadoop-ozone/dist/pom.xml | 6 +-
hadoop-ozone/dist/src/main/license/bin/LICENSE.txt | 2 +-
hadoop-ozone/dist/src/main/license/jar-report.txt | 1 +
hadoop-ozone/pom.xml | 5 +
pom.xml | 11 +
22 files changed, 1979 insertions(+), 2 deletions(-)
diff --git a/hadoop-hdds/pom.xml b/hadoop-hdds/pom.xml
index 58ef24a162..6735b2b978 100644
--- a/hadoop-hdds/pom.xml
+++ b/hadoop-hdds/pom.xml
@@ -49,6 +49,7 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd">
<module>config</module>
<module>test-utils</module>
<module>erasurecode</module>
+ <module>rocks-native</module>
</modules>
<repositories>
@@ -248,6 +249,11 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>bcpkix-jdk15on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.ozone</groupId>
+ <artifactId>hdds-rocks-native</artifactId>
+ <version>${hdds.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
<dependencies>
diff --git a/hadoop-hdds/rocks-native/pom.xml b/hadoop-hdds/rocks-native/pom.xml
new file mode 100644
index 0000000000..6112326cc7
--- /dev/null
+++ b/hadoop-hdds/rocks-native/pom.xml
@@ -0,0 +1,421 @@
+<?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">
+ <parent>
+ <artifactId>hdds</artifactId>
+ <groupId>org.apache.ozone</groupId>
+ <version>1.4.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <name>Apache Ozone HDDS RocksDB Tools</name>
+ <artifactId>hdds-rocks-native</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.ozone</groupId>
+ <artifactId>hdds-managed-rocksdb</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-io</artifactId>
+ </dependency>
+ </dependencies>
+ <properties>
+ <maven.compiler.source>8</maven.compiler.source>
+ <maven.compiler.target>8</maven.compiler.target>
+ </properties>
+
+ <profiles>
+ <profile>
+ <id>rocks_tools_native</id>
+ <activation>
+ <property>
+ <name>rocks_tools_native</name>
+ </property>
+ </activation>
+ <properties>
+ <cmake.standards>23</cmake.standards>
+ <sstDump.include>true</sstDump.include>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>get-cpu-count</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>cpu-count</goal>
+ </goals>
+ <configuration>
+ <cpuCount>system.numCores</cpuCount>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>com.googlecode.maven-download-plugin</groupId>
+ <artifactId>download-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>rocksdb source download</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>wget</goal>
+ </goals>
+ <configuration>
+
<url>https://github.com/facebook/rocksdb/archive/refs/tags/v${rocksdb.version}.tar.gz</url>
+
<outputFileName>rocksdb-v${rocksdb.version}.tar.gz</outputFileName>
+
<outputDirectory>${project.build.directory}/rocksdb</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>zlib source download</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>wget</goal>
+ </goals>
+ <configuration>
+
<url>https://zlib.net/zlib-${zlib.version}.tar.gz</url>
+
<outputFileName>zlib-${zlib.version}.tar.gz</outputFileName>
+
<outputDirectory>${project.build.directory}/zlib</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>bzip2 source download</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>wget</goal>
+ </goals>
+ <configuration>
+
<url>https://sourceware.org/pub/bzip2/bzip2-${bzip2.version}.tar.gz</url>
+
<outputFileName>bzip2-v${bzip2.version}.tar.gz</outputFileName>
+
<outputDirectory>${project.build.directory}/bzip2</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>lz4 source download</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>wget</goal>
+ </goals>
+ <configuration>
+
<url>https://github.com/lz4/lz4/archive/refs/tags/v${lz4.version}.tar.gz</url>
+
<outputFileName>lz4-v${lz4.version}.tar.gz</outputFileName>
+
<outputDirectory>${project.build.directory}/lz4</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>snappy source download</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>wget</goal>
+ </goals>
+ <configuration>
+
<url>https://github.com/google/snappy/archive/refs/tags/${snappy.version}.tar.gz</url>
+
<outputFileName>snappy-v${snappy.version}.tar.gz</outputFileName>
+
<outputDirectory>${project.build.directory}/snappy</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>zstd source download</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>wget</goal>
+ </goals>
+ <configuration>
+
<url>https://github.com/facebook/zstd/archive/refs/tags/v${zstd.version}.tar.gz</url>
+
<outputFileName>zstd-v${zstd.version}.tar.gz</outputFileName>
+
<outputDirectory>${project.build.directory}/zstd</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-patch-plugin</artifactId>
+ <version>1.1.1</version>
+ <configuration>
+
<patchFile>${basedir}/src/main/patches/rocks-native.patch</patchFile>
+ <strip>1</strip>
+
<targetDirectory>${project.build.directory}/rocksdb/rocksdb-${rocksdb.version}</targetDirectory>
+ </configuration>
+ <executions>
+ <execution>
+ <id>patch</id>
+ <phase>process-sources</phase>
+ <goals>
+ <goal>apply</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unzip-artifact</id>
+ <phase>generate-sources</phase>
+ <configuration>
+ <tasks>
+ <untar
src="${project.build.directory}/rocksdb/rocksdb-v${rocksdb.version}.tar.gz"
compression="gzip" dest="${project.build.directory}/rocksdb/" />
+ <untar
src="${project.build.directory}/zlib/zlib-${zlib.version}.tar.gz"
compression="gzip" dest="${project.build.directory}/zlib/" />
+ <untar
src="${project.build.directory}/bzip2/bzip2-v${bzip2.version}.tar.gz"
compression="gzip" dest="${project.build.directory}/bzip2/" />
+ <untar
src="${project.build.directory}/lz4/lz4-v${lz4.version}.tar.gz"
compression="gzip" dest="${project.build.directory}/lz4/" />
+ <untar
src="${project.build.directory}/snappy/snappy-v${snappy.version}.tar.gz"
compression="gzip" dest="${project.build.directory}/snappy/" />
+ <untar
src="${project.build.directory}/zstd/zstd-v${zstd.version}.tar.gz"
compression="gzip" dest="${project.build.directory}/zstd/" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>build-zlib</id>
+ <phase>process-sources</phase>
+ <configuration>
+ <tasks>
+ <chmod
file="${project.build.directory}/zlib/zlib-${zlib.version}/configure"
perm="775" />
+ <exec executable="./configure"
dir="${project.build.directory}/zlib/zlib-${zlib.version}" failonerror="true">
+ <arg line="--static"/>
+ <env key="CFLAGS" value="-fPIC"/>
+ </exec>
+ <exec executable="make"
dir="${project.build.directory}/zlib/zlib-${zlib.version}" failonerror="true"/>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>build-bzip2</id>
+ <phase>process-sources</phase>
+ <configuration>
+ <tasks>
+ <exec executable="make"
dir="${project.build.directory}/bzip2/bzip2-${bzip2.version}"
failonerror="true">
+ <arg line="CFLAGS='-fPIC'"/>
+ </exec>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>build-lz4</id>
+ <phase>process-sources</phase>
+ <configuration>
+ <tasks>
+ <exec executable="make"
dir="${project.build.directory}/lz4/lz4-${lz4.version}" failonerror="true">
+ <arg line="CFLAGS='-fPIC'"/>
+ </exec>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>build-zstd</id>
+ <phase>process-sources</phase>
+ <configuration>
+ <tasks>
+ <exec executable="make"
dir="${project.build.directory}/zstd/zstd-${zstd.version}" failonerror="true">
+ <arg line="CFLAGS='-fPIC'"/>
+ </exec>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>build-snappy</id>
+ <phase>process-sources</phase>
+ <configuration>
+ <tasks>
+ <mkdir
dir="${project.build.directory}/snappy/lib"/>
+ <exec executable="cmake"
failonerror="true" dir="${project.build.directory}/snappy/lib">
+ <arg
line="${project.build.directory}/snappy/snappy-${snappy.version}"/>
+ <env key="CFLAGS" value="-fPIC"/>
+ <env key="CXXFLAGS" value="-fPIC"/>
+ </exec>
+ <exec executable="make"
dir="${project.build.directory}/snappy/lib" failonerror="true"/>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>build-rocksjava</id>
+ <phase>process-resources</phase>
+ <configuration>
+ <tasks>
+ <exec executable="chmod"
failonerror="true">
+ <arg line="-R"/>
+ <arg line="775"/>
+ <arg
line="${project.build.directory}/rocksdb/rocksdb-${rocksdb.version}"/>
+ </exec>
+ <exec executable="make"
dir="${project.build.directory}/rocksdb/rocksdb-${rocksdb.version}"
failonerror="true">
+ <arg line="EXTRA_CXXFLAGS='-fPIC
-I${project.build.directory}/snappy/lib
-I${project.build.directory}/snappy/snappy-${snappy.version}
-I${project.build.directory}/lz4/lz4-${lz4.version}/lib
-I${project.build.directory}/zstd/zstd-${zstd.version}/lib
-I${project.build.directory}/zstd/zstd-${zstd.version}/lib/dictBuilder
-I${project.build.directory}/bzip2/bzip2-${bzip2.version}
-I${project.build.directory}/zlib/zlib-${zlib.version}'"/>
+ <arg
line="EXTRA_LDFLAGS='-L${project.build.directory}/snappy/lib
-L${project.build.directory}/lz4/lz4-${lz4.version}/lib
-L${project.build.directory}/zstd/zstd-${zstd.version}/lib
-L${project.build.directory}/bzip2/bzip2-${bzip2.version}
-L${project.build.directory}/zlib/zlib-${zlib.version}'"/>
+ <arg line="-j${system.numCores}"/>
+ <arg line="tools"/>
+ </exec>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>build-rocks-tools</id>
+ <phase>process-classes</phase>
+ <configuration>
+ <tasks>
+ <mkdir
dir="${project.build.directory}/native/rocksdb"/>
+ <exec executable="cmake"
failonerror="true" dir="${project.build.directory}/native/rocksdb">
+ <env key="CFLAGS" value="-fPIC"/>
+ <env key="CXXFLAGS" value="-fPIC"/>
+ <arg line="${basedir}/src"/>
+ <arg
line="-DGENERATED_JAVAH=${project.build.directory}/native/javah"/>
+ <arg
line="-DNATIVE_DIR=${basedir}/src/main/native"/>
+ <arg
line="-DSST_DUMP_INCLUDE=${sstDump.include}"/>
+ <arg
line="-DCMAKE_STANDARDS=${cmake.standards}"/>
+ <arg
line="-DROCKSDB_HEADERS=${project.build.directory}/rocksdb/rocksdb-${rocksdb.version}/include"/>
+ <arg
line="-DROCKSDB_LIB=${project.build.directory}/rocksdb/rocksdb-${rocksdb.version}"/>
+ <arg
line="-DZLIB_LIB=${project.build.directory}/zlib/zlib-${zlib.version}"/>
+ <arg
line="-DBZIP2_LIB=${project.build.directory}/bzip2/bzip2-${bzip2.version}"/>
+ <arg
line="-DLZ4_LIB=${project.build.directory}/lz4/lz4-${lz4.version}/lib"/>
+ <arg
line="-DSNAPPY_LIB=${project.build.directory}/snappy/lib"/>
+ <arg
line="-DZSTD_LIB=${project.build.directory}/zstd/zstd-${zstd.version}/lib"/>
+ </exec>
+ <exec executable="make"
dir="${project.build.directory}/native/rocksdb" failonerror="true"/>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>copy-lib-file</id>
+ <phase>prepare-package</phase>
+ <configuration>
+ <tasks>
+ <copy
toDir="${project.build.outputDirectory}">
+ <fileset
dir="${project.build.directory}/native/rocksdb" includes="**/lib*.*" />
+ </copy>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>${maven-jar-plugin.version}</version>
+ <configuration>
+ <includes>
+ <include>**/*.class</include>
+ <include>**/lib*.dylib</include>
+ <include>**/lib*.so</include>
+ <include>**/lib*.jnilib</include>
+ <include>**/lib*.dll</include>
+ </includes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>java-8</id>
+ <activation>
+ <jdk>1.8</jdk>
+ <property>
+ <name>rocks_tools_native</name>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>native-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <goals>
+ <goal>javah</goal>
+ </goals>
+ <configuration>
+
<javahPath>${env.JAVA_HOME}/bin/javah</javahPath>
+ <javahClassNames>
+
<javahClassName>org.apache.hadoop.hdds.utils.db.managed.ManagedSSTDumpTool</javahClassName>
+
<javahClassName>org.apache.hadoop.hdds.utils.db.managed.PipeInputStream</javahClassName>
+ </javahClassNames>
+
<javahOutputDirectory>${project.build.directory}/native/javah</javahOutputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>java-11</id>
+ <activation>
+ <jdk>11</jdk>
+ <property>
+ <name>rocks_tools_native</name>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>javach</id>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <phase>compile</phase>
+ <configuration>
+
<executable>${env.JAVA_HOME}/bin/javac</executable>
+ <arguments>
+ <argument>-classpath</argument>
+
<argument>${project.build.outputDirectory}</argument>
+ <argument>-h</argument>
+
<argument>${project.build.directory}/native/javah</argument>
+
<argument>${project.basedir}/src/main/java/org/apache/hadoop/hdds/utils/db/managed/ManagedSSTDumpTool.java</argument>
+
<argument>${project.basedir}/src/main/java/org/apache/hadoop/hdds/utils/db/managed/PipeInputStream.java</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/hadoop-hdds/rocks-native/src/CMakeLists.txt
b/hadoop-hdds/rocks-native/src/CMakeLists.txt
new file mode 100644
index 0000000000..84463fc169
--- /dev/null
+++ b/hadoop-hdds/rocks-native/src/CMakeLists.txt
@@ -0,0 +1,78 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# CMake configuration.
+#
+
+cmake_minimum_required(VERSION 2.8)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+project(ozone_native)
+set(CMAKE_BUILD_TYPE Release)
+find_package(JNI REQUIRED)
+include_directories(${JNI_INCLUDE_DIRS})
+set(CMAKE_CXX_STANDARD ${CMAKE_STANDARDS})
+
+set(linked_libraries "")
+if(NOT GENERATED_JAVAH)
+ message(FATAL_ERROR "You must set the CMake variable GENERATED_JAVAH")
+endif()
+include_directories(${GENERATED_JAVAH})
+if(${SST_DUMP_INCLUDE})
+ include_directories(${ROCKSDB_HEADERS})
+ set(SOURCE_FILES ${NATIVE_DIR}/SSTDumpTool.cpp
${NATIVE_DIR}/PipeInputStream.cpp ${NATIVE_DIR}/Pipe.h ${NATIVE_DIR}/Pipe.cpp
${NATIVE_DIR}/cplusplus_to_java_convert.h)
+ ADD_LIBRARY(rocksdb STATIC IMPORTED)
+ set_target_properties(
+ rocksdb
+ PROPERTIES
+ IMPORTED_LOCATION ${ROCKSDB_LIB}/librocksdb_debug.a)
+ ADD_LIBRARY(rocks_tools STATIC IMPORTED)
+ set_target_properties(
+ rocks_tools
+ PROPERTIES
+ IMPORTED_LOCATION ${ROCKSDB_LIB}/librocksdb_tools_debug.a)
+ ADD_LIBRARY(bz2 STATIC IMPORTED)
+ set_target_properties(
+ bz2
+ PROPERTIES
+ IMPORTED_LOCATION ${BZIP2_LIB}/libbz2.a)
+ ADD_LIBRARY(zlib STATIC IMPORTED)
+ set_target_properties(
+ zlib
+ PROPERTIES
+ IMPORTED_LOCATION ${ZLIB_LIB}/libz.a)
+ ADD_LIBRARY(lz4 STATIC IMPORTED)
+ set_target_properties(
+ lz4
+ PROPERTIES
+ IMPORTED_LOCATION ${LZ4_LIB}/liblz4.a)
+ ADD_LIBRARY(snappy STATIC IMPORTED)
+ set_target_properties(
+ snappy
+ PROPERTIES
+ IMPORTED_LOCATION ${SNAPPY_LIB}/libsnappy.a)
+ ADD_LIBRARY(zstd STATIC IMPORTED)
+ set_target_properties(
+ zstd
+ PROPERTIES
+ IMPORTED_LOCATION ${ZSTD_LIB}/libzstd.a)
+ set(linked_libraries ${linked_libraries} bz2 zlib rocks_tools rocksdb lz4
snappy zstd)
+endif()
+add_library(ozone_rocksdb_tools SHARED ${SOURCE_FILES})
+target_link_libraries(ozone_rocksdb_tools ${linked_libraries})
diff --git
a/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/NativeConstants.java
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/NativeConstants.java
new file mode 100644
index 0000000000..d3121144d3
--- /dev/null
+++
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/NativeConstants.java
@@ -0,0 +1,31 @@
+/*
+ * 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.hdds.utils;
+
+/**
+ * Native Constants.
+ */
+public final class NativeConstants {
+
+ private NativeConstants() {
+
+ }
+ public static final String ROCKS_TOOLS_NATIVE_LIBRARY_NAME
+ = "ozone_rocksdb_tools";
+}
diff --git
a/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/NativeLibraryLoader.java
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/NativeLibraryLoader.java
new file mode 100644
index 0000000000..35427c822f
--- /dev/null
+++
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/NativeLibraryLoader.java
@@ -0,0 +1,150 @@
+/*
+ * 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.hdds.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Class to load Native Libraries.
+ */
+public class NativeLibraryLoader {
+
+ private static final Logger LOG =
+ LoggerFactory.getLogger(NativeLibraryLoader.class);
+ private static final String OS = System.getProperty("os.name").toLowerCase();
+ private Map<String, Boolean> librariesLoaded;
+ private static volatile NativeLibraryLoader instance;
+
+ public NativeLibraryLoader(final Map<String, Boolean> librariesLoaded) {
+ this.librariesLoaded = librariesLoaded;
+ }
+
+ private static synchronized void initNewInstance() {
+ if (instance == null) {
+ instance = new NativeLibraryLoader(new ConcurrentHashMap<>());
+ }
+ }
+
+ public static NativeLibraryLoader getInstance() {
+ if (instance == null) {
+ initNewInstance();
+ }
+ return instance;
+ }
+
+ public static String getJniLibraryFileName(String libraryName) {
+ return appendLibOsSuffix("lib" + libraryName);
+ }
+
+ public static boolean isMac() {
+ return OS.startsWith("mac");
+ }
+
+ public static boolean isWindows() {
+ return OS.startsWith("win");
+ }
+
+ public static boolean isLinux() {
+ return OS.startsWith("linux");
+ }
+
+ private static String getLibOsSuffix() {
+ if (isMac()) {
+ return ".dylib";
+ } else if (isWindows()) {
+ return ".dll";
+ } else if (isLinux()) {
+ return ".so";
+ }
+ throw new UnsatisfiedLinkError(String.format("Unsupported OS %s", OS));
+ }
+
+ private static String appendLibOsSuffix(String libraryFileName) {
+ return libraryFileName + getLibOsSuffix();
+ }
+
+ public static boolean isLibraryLoaded(final String libraryName) {
+ return getInstance().librariesLoaded
+ .getOrDefault(libraryName, false);
+ }
+
+ public synchronized boolean loadLibrary(final String libraryName) {
+ if (isLibraryLoaded(libraryName)) {
+ return true;
+ }
+ boolean loaded = false;
+ try {
+ loaded = false;
+ try {
+ System.loadLibrary(libraryName);
+ loaded = true;
+ } catch (Throwable e) {
+
+ }
+ if (!loaded) {
+ Optional<File> file = copyResourceFromJarToTemp(libraryName);
+ if (file.isPresent()) {
+ System.load(file.get().getAbsolutePath());
+ loaded = true;
+ }
+ }
+ } catch (Throwable e) {
+ LOG.warn("Unable to load library: {}", libraryName, e);
+ }
+ this.librariesLoaded.put(libraryName, loaded);
+ return isLibraryLoaded(libraryName);
+ }
+
+ private Optional<File> copyResourceFromJarToTemp(final String libraryName)
+ throws IOException {
+ final String libraryFileName = getJniLibraryFileName(libraryName);
+ InputStream is = null;
+ try {
+ is = getClass().getClassLoader().getResourceAsStream(libraryFileName);
+ if (is == null) {
+ return Optional.empty();
+ }
+
+ // create a temporary file to copy the library to
+ final File temp = File.createTempFile(libraryName, getLibOsSuffix());
+ if (!temp.exists()) {
+ return Optional.empty();
+ } else {
+ temp.deleteOnExit();
+ }
+
+ Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ return Optional.ofNullable(temp);
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+ }
+}
diff --git
a/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/NativeLibraryNotLoadedException.java
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/NativeLibraryNotLoadedException.java
new file mode 100644
index 0000000000..b4313a607d
--- /dev/null
+++
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/NativeLibraryNotLoadedException.java
@@ -0,0 +1,30 @@
+/*
+ * 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.hdds.utils;
+
+/**
+ Exception when native library not loaded.
+ */
+public class NativeLibraryNotLoadedException extends Exception {
+ public NativeLibraryNotLoadedException(String libraryName) {
+ super(String.format("Unable to load library %s from both " +
+ "java.library.path & resource file %s from jar.", libraryName,
+ NativeLibraryLoader.getJniLibraryFileName(libraryName)));
+ }
+}
diff --git
a/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/db/managed/ManagedSSTDumpIterator.java
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/db/managed/ManagedSSTDumpIterator.java
new file mode 100644
index 0000000000..35aaeb33b0
--- /dev/null
+++
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/db/managed/ManagedSSTDumpIterator.java
@@ -0,0 +1,225 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.hdds.utils.db.managed;
+
+import org.apache.hadoop.hdds.utils.NativeLibraryNotLoadedException;
+import org.eclipse.jetty.io.RuntimeIOException;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Iterator to Parse output of RocksDBSSTDumpTool.
+ */
+public class ManagedSSTDumpIterator implements
+ Iterator<ManagedSSTDumpIterator.KeyValue>, AutoCloseable {
+ private static final String SST_DUMP_TOOL_CLASS =
+ "org.apache.hadoop.hdds.utils.db.managed.ManagedSSTDumpTool";
+ private static final String PATTERN_REGEX =
+ "'([^=>]+)' seq:([0-9]+), type:([0-9]+) => ";
+
+ public static final int PATTERN_KEY_GROUP_NUMBER = 1;
+ public static final int PATTERN_SEQ_GROUP_NUMBER = 2;
+ public static final int PATTERN_TYPE_GROUP_NUMBER = 3;
+ private static final Pattern PATTERN_MATCHER =
+ Pattern.compile(PATTERN_REGEX);
+ private BufferedReader processOutput;
+ private StringBuilder stdoutString;
+
+ private Matcher currentMatcher;
+ private int prevMatchEndIndex;
+ private KeyValue currentKey;
+ private char[] charBuffer;
+ private KeyValue nextKey;
+
+ private ManagedSSTDumpTool.SSTDumpToolTask sstDumpToolTask;
+ private AtomicBoolean open;
+
+
+ public ManagedSSTDumpIterator(ManagedSSTDumpTool sstDumpTool,
+ String sstFilePath,
+ ManagedOptions options) throws IOException,
+ NativeLibraryNotLoadedException {
+ File sstFile = new File(sstFilePath);
+ if (!sstFile.exists()) {
+ throw new IOException(String.format("File in path : %s doesn't exist",
+ sstFile.getAbsolutePath()));
+ }
+ if (!sstFile.isFile()) {
+ throw new IOException(String.format("Path given: %s is not a file",
+ sstFile.getAbsolutePath()));
+ }
+ init(sstDumpTool, sstFile, options);
+ }
+
+ private void init(ManagedSSTDumpTool sstDumpTool, File sstFile,
+ ManagedOptions options)
+ throws NativeLibraryNotLoadedException {
+ String[] args = {"--file=" + sstFile.getAbsolutePath(),
+ "--command=scan"};
+ this.sstDumpToolTask = sstDumpTool.run(args, options);
+ processOutput = new BufferedReader(new InputStreamReader(
+ sstDumpToolTask.getPipedOutput(), StandardCharsets.UTF_8));
+ stdoutString = new StringBuilder();
+ currentMatcher = PATTERN_MATCHER.matcher(stdoutString);
+ charBuffer = new char[8192];
+ open = new AtomicBoolean(true);
+ next();
+ }
+
+ /**
+ * Throws Runtime exception in the case iterator is closed or
+ * the native Dumptool exited with non zero exit value.
+ */
+ private void checkSanityOfProcess() {
+ if (!this.open.get()) {
+ throw new RuntimeException("Iterator has been closed");
+ }
+ if (sstDumpToolTask.getFuture().isDone()
+ && sstDumpToolTask.exitValue() != 0) {
+ throw new RuntimeException("Process Terminated with non zero " +
+ String.format("exit value %d", sstDumpToolTask.exitValue()));
+ }
+ }
+
+ /**
+ * Checks the status of the process & sees if there is another record.
+ * @return True if next exists & false otherwise
+ * Throws Runtime Exception in case of SST File read failure
+ */
+
+ @Override
+ public boolean hasNext() {
+ checkSanityOfProcess();
+ return nextKey != null;
+ }
+
+ /**
+ * Returns the next record from SSTDumpTool.
+ * @return next Key
+ * Throws Runtime Exception incase of failure.
+ */
+ @Override
+ public KeyValue next() {
+ checkSanityOfProcess();
+ currentKey = nextKey;
+ nextKey = null;
+ while (!currentMatcher.find()) {
+ try {
+ if (prevMatchEndIndex != 0) {
+ stdoutString = new StringBuilder(stdoutString.substring(
+ prevMatchEndIndex, stdoutString.length()));
+ prevMatchEndIndex = 0;
+ currentMatcher = PATTERN_MATCHER.matcher(stdoutString);
+ }
+ int numberOfCharsRead = processOutput.read(charBuffer);
+ if (numberOfCharsRead < 0) {
+ if (currentKey != null) {
+ currentKey.setValue(stdoutString.substring(0,
+ Math.max(stdoutString.length() - 1, 0)));
+ }
+ return currentKey;
+ }
+ stdoutString.append(charBuffer, 0, numberOfCharsRead);
+ currentMatcher.reset();
+ } catch (IOException e) {
+ throw new RuntimeIOException(e);
+ }
+ }
+ if (currentKey != null) {
+ currentKey.setValue(stdoutString.substring(prevMatchEndIndex,
+ currentMatcher.start() - 1));
+ }
+ prevMatchEndIndex = currentMatcher.end();
+ nextKey = new KeyValue(
+ currentMatcher.group(PATTERN_KEY_GROUP_NUMBER),
+ currentMatcher.group(PATTERN_SEQ_GROUP_NUMBER),
+ currentMatcher.group(PATTERN_TYPE_GROUP_NUMBER));
+ return currentKey;
+ }
+
+ @Override
+ public synchronized void close() throws Exception {
+ if (this.sstDumpToolTask != null) {
+ if (!this.sstDumpToolTask.getFuture().isDone()) {
+ this.sstDumpToolTask.getFuture().cancel(true);
+ }
+ this.processOutput.close();
+ }
+ open.compareAndSet(true, false);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ this.close();
+ }
+
+ /**
+ * Class containing Parsed KeyValue Record from Sst Dumptool output.
+ */
+ public static final class KeyValue {
+ private String key;
+ private Integer sequence;
+ private Integer type;
+
+ private String value;
+
+ private KeyValue(String key, String sequence, String type) {
+ this.key = key;
+ this.sequence = Integer.valueOf(sequence);
+ this.type = Integer.valueOf(type);
+ }
+
+ private void setValue(String value) {
+ this.value = value;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public Integer getSequence() {
+ return sequence;
+ }
+
+ public Integer getType() {
+ return type;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return "KeyValue{" +
+ "key='" + key + '\'' +
+ ", sequence=" + sequence +
+ ", type=" + type +
+ ", value='" + value + '\'' +
+ '}';
+ }
+ }
+}
diff --git
a/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/db/managed/ManagedSSTDumpTool.java
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/db/managed/ManagedSSTDumpTool.java
new file mode 100644
index 0000000000..940438a457
--- /dev/null
+++
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/db/managed/ManagedSSTDumpTool.java
@@ -0,0 +1,103 @@
+/*
+ * 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.hdds.utils.db.managed;
+
+import org.apache.hadoop.hdds.utils.NativeLibraryLoader;
+import org.apache.hadoop.hdds.utils.NativeLibraryNotLoadedException;
+
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import static
org.apache.hadoop.hdds.utils.NativeConstants.ROCKS_TOOLS_NATIVE_LIBRARY_NAME;
+
+/**
+ * JNI for RocksDB SSTDumpTool. Pipes the output to an output stream
+ */
+public class ManagedSSTDumpTool {
+
+ static {
+ NativeLibraryLoader.getInstance()
+ .loadLibrary(ROCKS_TOOLS_NATIVE_LIBRARY_NAME);
+ }
+ private int bufferCapacity;
+ private ExecutorService executorService;
+
+ public ManagedSSTDumpTool(ExecutorService executorService,
+ int bufferCapacity)
+ throws NativeLibraryNotLoadedException {
+ if (!NativeLibraryLoader.isLibraryLoaded(ROCKS_TOOLS_NATIVE_LIBRARY_NAME))
{
+ throw new NativeLibraryNotLoadedException(
+ ROCKS_TOOLS_NATIVE_LIBRARY_NAME);
+ }
+ this.bufferCapacity = bufferCapacity;
+ this.executorService = executorService;
+ }
+
+ public SSTDumpToolTask run(String[] args, ManagedOptions options)
+ throws NativeLibraryNotLoadedException {
+ PipeInputStream pipeInputStream = new PipeInputStream(bufferCapacity);
+ return new SSTDumpToolTask(this.executorService.submit(() ->
+ this.runInternal(args, options.getNativeHandle(),
+ pipeInputStream.getNativeHandle())), pipeInputStream);
+ }
+
+ public SSTDumpToolTask run(Map<String, String> args, ManagedOptions options)
+ throws NativeLibraryNotLoadedException {
+ return this.run(args.entrySet().stream().map(e -> "--"
+ + (e.getValue() == null || e.getValue().isEmpty() ? e.getKey() :
+ e.getKey() + "=" + e.getValue())).toArray(String[]::new), options);
+ }
+
+ private native int runInternal(String[] args, long optionsHandle,
+ long pipeHandle);
+
+ /**
+ * Class holding piped output of SST Dumptool & future of command.
+ */
+ static class SSTDumpToolTask {
+ private Future<Integer> future;
+ private PipeInputStream pipedOutput;
+
+ SSTDumpToolTask(Future<Integer> future, PipeInputStream pipedOutput) {
+ this.future = future;
+ this.pipedOutput = pipedOutput;
+ }
+
+ public Future<Integer> getFuture() {
+ return future;
+ }
+
+ public PipeInputStream getPipedOutput() {
+ return pipedOutput;
+ }
+
+ public int exitValue() {
+ if (this.future.isDone()) {
+ try {
+ return future.get();
+ } catch (InterruptedException | ExecutionException e) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+ }
+}
diff --git
a/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/db/managed/PipeInputStream.java
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/db/managed/PipeInputStream.java
new file mode 100644
index 0000000000..741761ae49
--- /dev/null
+++
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/db/managed/PipeInputStream.java
@@ -0,0 +1,99 @@
+/*
+ * 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.hdds.utils.db.managed;
+
+import org.apache.hadoop.hdds.utils.NativeLibraryLoader;
+import org.apache.hadoop.hdds.utils.NativeLibraryNotLoadedException;
+import java.io.InputStream;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static
org.apache.hadoop.hdds.utils.NativeConstants.ROCKS_TOOLS_NATIVE_LIBRARY_NAME;
+
+/**
+ * JNI for reading data from pipe.
+ */
+public class PipeInputStream extends InputStream {
+
+ static {
+ NativeLibraryLoader.getInstance()
+ .loadLibrary(ROCKS_TOOLS_NATIVE_LIBRARY_NAME);
+ }
+ private byte[] byteBuffer;
+ private long nativeHandle;
+ private int numberOfBytesLeftToRead;
+ private int index = 0;
+ private int capacity;
+
+ private AtomicBoolean cleanup;
+
+ PipeInputStream(int capacity) throws NativeLibraryNotLoadedException {
+ if (!NativeLibraryLoader.isLibraryLoaded(ROCKS_TOOLS_NATIVE_LIBRARY_NAME))
{
+ throw new NativeLibraryNotLoadedException(
+ ROCKS_TOOLS_NATIVE_LIBRARY_NAME);
+ }
+
+ this.byteBuffer = new byte[capacity];
+ this.numberOfBytesLeftToRead = 0;
+ this.capacity = capacity;
+ this.nativeHandle = newPipe();
+ this.cleanup = new AtomicBoolean(false);
+ }
+
+ long getNativeHandle() {
+ return nativeHandle;
+ }
+
+ @Override
+ public int read() {
+ if (numberOfBytesLeftToRead < 0) {
+ this.close();
+ return -1;
+ }
+ if (numberOfBytesLeftToRead == 0) {
+ numberOfBytesLeftToRead = readInternal(byteBuffer, capacity,
+ nativeHandle);
+ index = 0;
+ return read();
+ }
+ numberOfBytesLeftToRead--;
+ int ret = byteBuffer[index] & 0xFF;
+ index += 1;
+ return ret;
+ }
+
+ private native long newPipe();
+
+ private native int readInternal(byte[] buff, int numberOfBytes,
+ long pipeHandle);
+
+ private native void closeInternal(long pipeHandle);
+
+ @Override
+ public void close() {
+ if (this.cleanup.compareAndSet(false, true)) {
+ closeInternal(this.nativeHandle);
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ close();
+ super.finalize();
+ }
+}
diff --git
a/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/db/managed/package-info.java
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/db/managed/package-info.java
new file mode 100644
index 0000000000..2388b6ab08
--- /dev/null
+++
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/db/managed/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Annotation processors used at compile time by the Ozone project to validate
+ * internal annotations and related code as needed, if needed.
+ */
+
+package org.apache.hadoop.hdds.utils.db.managed;
diff --git
a/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/package-info.java
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/package-info.java
new file mode 100644
index 0000000000..4b60561661
--- /dev/null
+++
b/hadoop-hdds/rocks-native/src/main/java/org/apache/hadoop/hdds/utils/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Annotation processors used at compile time by the Ozone project to validate
+ * internal annotations and related code as needed, if needed.
+ */
+
+package org.apache.hadoop.hdds.utils;
diff --git a/hadoop-hdds/rocks-native/src/main/native/Pipe.cpp
b/hadoop-hdds/rocks-native/src/main/native/Pipe.cpp
new file mode 100644
index 0000000000..f1dd544387
--- /dev/null
+++ b/hadoop-hdds/rocks-native/src/main/native/Pipe.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#include "Pipe.h"
+#include <unistd.h>
+
+const int Pipe::READ_FILE_DESCRIPTOR_IDX = 0;
+const int Pipe::WRITE_FILE_DESCRIPTOR_IDX = 1;
+
+Pipe::Pipe() {
+ pipe(p);
+ open = true;
+}
+
+Pipe::~Pipe() {
+ ::close(p[Pipe::READ_FILE_DESCRIPTOR_IDX]);
+ ::close(p[Pipe::WRITE_FILE_DESCRIPTOR_IDX]);
+}
+
+void Pipe::close() {
+ open = false;
+}
diff --git a/hadoop-hdds/rocks-native/src/main/native/Pipe.h
b/hadoop-hdds/rocks-native/src/main/native/Pipe.h
new file mode 100644
index 0000000000..aa75c6311c
--- /dev/null
+++ b/hadoop-hdds/rocks-native/src/main/native/Pipe.h
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ROCKS_NATIVE_PIPE_H
+#define ROCKS_NATIVE_PIPE_H
+
+#include <stdio.h>
+
+class Pipe {
+ public:
+ static const int READ_FILE_DESCRIPTOR_IDX;
+ static const int WRITE_FILE_DESCRIPTOR_IDX;
+ Pipe();
+ ~Pipe();
+ void close();
+ int getReadFd() {
+ return getPipeFileDescriptorIndex(READ_FILE_DESCRIPTOR_IDX);
+ }
+
+ int getWriteFd() {
+ return getPipeFileDescriptorIndex(WRITE_FILE_DESCRIPTOR_IDX);
+ }
+
+ int getPipeFileDescriptorIndex(int idx) {
+ return p[idx];
+ }
+
+ bool isOpen() {
+ return open;
+ }
+
+
+ private:
+ int p[2];
+ FILE* wr;
+ bool open;
+
+};
+
+#endif //ROCKS_NATIVE_PIPE_H
diff --git a/hadoop-hdds/rocks-native/src/main/native/PipeInputStream.cpp
b/hadoop-hdds/rocks-native/src/main/native/PipeInputStream.cpp
new file mode 100644
index 0000000000..53f60cdd65
--- /dev/null
+++ b/hadoop-hdds/rocks-native/src/main/native/PipeInputStream.cpp
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+#include <iostream>
+#include "Pipe.h"
+#include "cplusplus_to_java_convert.h"
+#include "org_apache_hadoop_hdds_utils_db_managed_PipeInputStream.h"
+
+
+jlong
Java_org_apache_hadoop_hdds_utils_db_managed_PipeInputStream_newPipe(JNIEnv *,
jobject) {
+ Pipe *pipe = new Pipe();
+ return GET_CPLUSPLUS_POINTER(pipe);
+}
+
+jint
Java_org_apache_hadoop_hdds_utils_db_managed_PipeInputStream_readInternal(JNIEnv
*env, jobject object, jbyteArray jbyteArray, jint capacity, jlong
nativeHandle) {
+ int cap_int = capacity;
+ Pipe *pipe = reinterpret_cast<Pipe *>(nativeHandle);
+ jbyte *b = (env)->GetByteArrayElements(jbyteArray, JNI_FALSE);
+ cap_int = read(pipe->getReadFd(), b, cap_int);
+ if (cap_int == 0) {
+ if (!pipe->isOpen()) {
+ cap_int = -1;
+ }
+ }
+ env->ReleaseByteArrayElements(jbyteArray, b, 0);
+ return cap_int;
+}
+
+void
Java_org_apache_hadoop_hdds_utils_db_managed_PipeInputStream_closeInternal(JNIEnv
*env, jobject object, jlong nativeHandle) {
+ delete reinterpret_cast<Pipe *>(nativeHandle);
+}
+
diff --git a/hadoop-hdds/rocks-native/src/main/native/SSTDumpTool.cpp
b/hadoop-hdds/rocks-native/src/main/native/SSTDumpTool.cpp
new file mode 100644
index 0000000000..b200f49c0b
--- /dev/null
+++ b/hadoop-hdds/rocks-native/src/main/native/SSTDumpTool.cpp
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "org_apache_hadoop_hdds_utils_db_managed_ManagedSSTDumpTool.h"
+#include "rocksdb/options.h"
+#include "rocksdb/sst_dump_tool.h"
+#include <string>
+#include "cplusplus_to_java_convert.h"
+#include "Pipe.h"
+#include <iostream>
+
+jint
Java_org_apache_hadoop_hdds_utils_db_managed_ManagedSSTDumpTool_runInternal(JNIEnv
*env, jobject obj,
+ jobjectArray argsArray, jlong optionsHandle, jlong pipeHandle) {
+ ROCKSDB_NAMESPACE::SSTDumpTool dumpTool;
+ ROCKSDB_NAMESPACE::Options *options =
reinterpret_cast<ROCKSDB_NAMESPACE::Options *>(optionsHandle);
+ Pipe *pipe = reinterpret_cast<Pipe *>(pipeHandle);
+ int length = env->GetArrayLength(argsArray);
+ char *args[length + 1];
+ for (int i = 0; i < length; i++) {
+ jstring str_val = (jstring)env->GetObjectArrayElement(argsArray,
(jsize)i);
+ char *utf_str = (char *)env->GetStringUTFChars(str_val, JNI_FALSE);
+ args[i + 1] = utf_str;
+ }
+ FILE *wr = fdopen(pipe->getWriteFd(), "w");
+ int ret = dumpTool.Run(length + 1, args, *options, wr);
+ for (int i = 1; i < length + 1; i++) {
+ jstring str_val = (jstring)env->GetObjectArrayElement(argsArray,
(jsize)(i - 1));
+ env->ReleaseStringUTFChars(str_val, args[i]);
+ }
+ fclose(wr);
+ pipe->close();
+ return ret;
+}
diff --git
a/hadoop-hdds/rocks-native/src/main/native/cplusplus_to_java_convert.h
b/hadoop-hdds/rocks-native/src/main/native/cplusplus_to_java_convert.h
new file mode 100644
index 0000000000..efe9d4a5be
--- /dev/null
+++ b/hadoop-hdds/rocks-native/src/main/native/cplusplus_to_java_convert.h
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
+// This source code is licensed under both the GPLv2 (found in the
+// COPYING file in the root directory) and Apache 2.0 License
+// (found in the LICENSE.Apache file in the root directory).
+
+#pragma once
+
+/*
+ * This macro is used for 32 bit OS. In 32 bit OS, the result number is a
+ negative number if we use reinterpret_cast<jlong>(pointer).
+ * For example, jlong ptr = reinterpret_cast<jlong>(pointer), ptr is a negative
+ number in 32 bit OS.
+ * If we check ptr using ptr > 0, it fails. For example, the following code is
+ not correct.
+ * if (jblock_cache_handle > 0) {
+ std::shared_ptr<ROCKSDB_NAMESPACE::Cache> *pCache =
+ reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::Cache> *>(
+ jblock_cache_handle);
+ options.block_cache = *pCache;
+ }
+ * But the result number is positive number if we do
+ reinterpret_cast<size_t>(pointer) first and then cast it to jlong. size_t is 4
+ bytes long in 32 bit OS and 8 bytes long in 64 bit OS.
+ static_cast<jlong>(reinterpret_cast<size_t>(_pointer)) is also working in 64
+ bit OS.
+ *
+ * We don't need an opposite cast because it works from jlong to c++ pointer in
+ both 32 bit and 64 bit OS.
+ * For example, the following code is working in both 32 bit and 64 bit OS.
+ jblock_cache_handle is jlong.
+ * std::shared_ptr<ROCKSDB_NAMESPACE::Cache> *pCache =
+ reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::Cache> *>(
+ jblock_cache_handle);
+*/
+
+#define GET_CPLUSPLUS_POINTER(_pointer) \
+ static_cast<jlong>(reinterpret_cast<size_t>(_pointer))
diff --git a/hadoop-hdds/rocks-native/src/main/patches/rocks-native.patch
b/hadoop-hdds/rocks-native/src/main/patches/rocks-native.patch
new file mode 100644
index 0000000000..c58a9a12f1
--- /dev/null
+++ b/hadoop-hdds/rocks-native/src/main/patches/rocks-native.patch
@@ -0,0 +1,522 @@
+/*
+ * 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.
+ */
+
+diff --git a/include/rocksdb/sst_dump_tool.h b/include/rocksdb/sst_dump_tool.h
+index 9261ba47d..09ed123e5 100644
+--- a/include/rocksdb/sst_dump_tool.h
++++ b/include/rocksdb/sst_dump_tool.h
+@@ -11,7 +11,8 @@ namespace ROCKSDB_NAMESPACE {
+
+ class SSTDumpTool {
+ public:
+- int Run(int argc, char const* const* argv, Options options = Options());
++ int Run(int argc, char const* const* argv,Options options = Options(),
++ FILE* out = stdout, FILE* err = stderr);
+ };
+
+ } // namespace ROCKSDB_NAMESPACE
+diff --git a/table/sst_file_dumper.cc b/table/sst_file_dumper.cc
+index eefbaaeee..2c8106298 100644
+--- a/table/sst_file_dumper.cc
++++ b/table/sst_file_dumper.cc
+@@ -45,7 +45,7 @@ SstFileDumper::SstFileDumper(const Options& options,
+ Temperature file_temp, size_t readahead_size,
+ bool verify_checksum, bool output_hex,
+ bool decode_blob_index, const EnvOptions&
soptions,
+- bool silent)
++ bool silent, FILE* out, FILE* err)
+ : file_name_(file_path),
+ read_num_(0),
+ file_temp_(file_temp),
+@@ -57,10 +57,13 @@ SstFileDumper::SstFileDumper(const Options& options,
+ ioptions_(options_),
+ moptions_(ColumnFamilyOptions(options_)),
+ read_options_(verify_checksum, false),
+- internal_comparator_(BytewiseComparator()) {
++ internal_comparator_(BytewiseComparator()),
++ out(out),
++ err(err)
++ {
+ read_options_.readahead_size = readahead_size;
+ if (!silent_) {
+- fprintf(stdout, "Process %s\n", file_path.c_str());
++ fprintf(out, "Process %s\n", file_path.c_str());
+ }
+ init_result_ = GetTableReader(file_name_);
+ }
+@@ -253,17 +256,17 @@ Status SstFileDumper::ShowAllCompressionSizes(
+ int32_t compress_level_from, int32_t compress_level_to,
+ uint32_t max_dict_bytes, uint32_t zstd_max_train_bytes,
+ uint64_t max_dict_buffer_bytes, bool use_zstd_dict_trainer) {
+- fprintf(stdout, "Block Size: %" ROCKSDB_PRIszt "\n", block_size);
++ fprintf(out, "Block Size: %" ROCKSDB_PRIszt "\n", block_size);
+ for (auto& i : compression_types) {
+ if (CompressionTypeSupported(i.first)) {
+- fprintf(stdout, "Compression: %-24s\n", i.second);
++ fprintf(out, "Compression: %-24s\n", i.second);
+ CompressionOptions compress_opt;
+ compress_opt.max_dict_bytes = max_dict_bytes;
+ compress_opt.zstd_max_train_bytes = zstd_max_train_bytes;
+ compress_opt.max_dict_buffer_bytes = max_dict_buffer_bytes;
+ compress_opt.use_zstd_dict_trainer = use_zstd_dict_trainer;
+ for (int32_t j = compress_level_from; j <= compress_level_to; j++) {
+- fprintf(stdout, "Compression level: %d", j);
++ fprintf(out, "Compression level: %d", j);
+ compress_opt.level = j;
+ Status s = ShowCompressionSize(block_size, i.first, compress_opt);
+ if (!s.ok()) {
+@@ -271,7 +274,7 @@ Status SstFileDumper::ShowAllCompressionSizes(
+ }
+ }
+ } else {
+- fprintf(stdout, "Unsupported compression type: %s.\n", i.second);
++ fprintf(out, "Unsupported compression type: %s.\n", i.second);
+ }
+ }
+ return Status::OK();
+@@ -307,9 +310,9 @@ Status SstFileDumper::ShowCompressionSize(
+ }
+
+ std::chrono::steady_clock::time_point end =
std::chrono::steady_clock::now();
+- fprintf(stdout, " Size: %10" PRIu64, file_size);
+- fprintf(stdout, " Blocks: %6" PRIu64, num_data_blocks);
+- fprintf(stdout, " Time Taken: %10s microsecs",
++ fprintf(out, " Size: %10" PRIu64, file_size);
++ fprintf(out, " Blocks: %6" PRIu64, num_data_blocks);
++ fprintf(out, " Time Taken: %10s microsecs",
+ std::to_string(
+ std::chrono::duration_cast<std::chrono::microseconds>(end -
start)
+ .count())
+@@ -342,11 +345,11 @@ Status SstFileDumper::ShowCompressionSize(
+ : ((static_cast<double>(not_compressed_blocks) /
+ static_cast<double>(num_data_blocks)) *
+ 100.0);
+- fprintf(stdout, " Compressed: %6" PRIu64 " (%5.1f%%)", compressed_blocks,
++ fprintf(out, " Compressed: %6" PRIu64 " (%5.1f%%)", compressed_blocks,
+ compressed_pcnt);
+- fprintf(stdout, " Not compressed (ratio): %6" PRIu64 " (%5.1f%%)",
++ fprintf(out, " Not compressed (ratio): %6" PRIu64 " (%5.1f%%)",
+ ratio_not_compressed_blocks, ratio_not_compressed_pcnt);
+- fprintf(stdout, " Not compressed (abort): %6" PRIu64 " (%5.1f%%)\n",
++ fprintf(out, " Not compressed (abort): %6" PRIu64 " (%5.1f%%)\n",
+ not_compressed_blocks, not_compressed_pcnt);
+ return Status::OK();
+ }
+@@ -362,7 +365,7 @@ Status SstFileDumper::ReadTableProperties(uint64_t
table_magic_number,
+ /* memory_allocator= */ nullptr, prefetch_buffer);
+ if (!s.ok()) {
+ if (!silent_) {
+- fprintf(stdout, "Not able to read table properties\n");
++ fprintf(out, "Not able to read table properties\n");
+ }
+ }
+ return s;
+@@ -382,7 +385,7 @@ Status SstFileDumper::SetTableOptionsByMagicNumber(
+
+ options_.table_factory.reset(bbtf);
+ if (!silent_) {
+- fprintf(stdout, "Sst file format: block-based\n");
++ fprintf(out, "Sst file format: block-based\n");
+ }
+
+ auto& props = table_properties_->user_collected_properties;
+@@ -410,7 +413,7 @@ Status SstFileDumper::SetTableOptionsByMagicNumber(
+
+ options_.table_factory.reset(NewPlainTableFactory(plain_table_options));
+ if (!silent_) {
+- fprintf(stdout, "Sst file format: plain table\n");
++ fprintf(out, "Sst file format: plain table\n");
+ }
+ } else {
+ char error_msg_buffer[80];
+@@ -427,7 +430,7 @@ Status SstFileDumper::SetOldTableOptions() {
+ assert(table_properties_ == nullptr);
+ options_.table_factory = std::make_shared<BlockBasedTableFactory>();
+ if (!silent_) {
+- fprintf(stdout, "Sst file format: block-based(old version)\n");
++ fprintf(out, "Sst file format: block-based(old version)\n");
+ }
+
+ return Status::OK();
+@@ -478,7 +481,7 @@ Status SstFileDumper::ReadSequential(bool print_kv,
uint64_t read_num,
+
+ if (print_kv) {
+ if (!decode_blob_index_ || ikey.type != kTypeBlobIndex) {
+- fprintf(stdout, "%s => %s\n",
++ fprintf(out, "%s => %s\n",
+ ikey.DebugString(true, output_hex_).c_str(),
+ value.ToString(output_hex_).c_str());
+ } else {
+@@ -486,12 +489,12 @@ Status SstFileDumper::ReadSequential(bool print_kv,
uint64_t read_num,
+
+ const Status s = blob_index.DecodeFrom(value);
+ if (!s.ok()) {
+- fprintf(stderr, "%s => error decoding blob index\n",
++ fprintf(err, "%s => error decoding blob index\n",
+ ikey.DebugString(true, output_hex_).c_str());
+ continue;
+ }
+
+- fprintf(stdout, "%s => %s\n",
++ fprintf(out, "%s => %s\n",
+ ikey.DebugString(true, output_hex_).c_str(),
+ blob_index.DebugString(output_hex_).c_str());
+ }
+diff --git a/table/sst_file_dumper.h b/table/sst_file_dumper.h
+index 7be876390..20e35ac2a 100644
+--- a/table/sst_file_dumper.h
++++ b/table/sst_file_dumper.h
+@@ -22,7 +22,9 @@ class SstFileDumper {
+ bool verify_checksum, bool output_hex,
+ bool decode_blob_index,
+ const EnvOptions& soptions = EnvOptions(),
+- bool silent = false);
++ bool silent = false,
++ FILE* out = stdout,
++ FILE* err = stderr);
+
+ Status ReadSequential(bool print_kv, uint64_t read_num, bool has_from,
+ const std::string& from_key, bool has_to,
+@@ -94,6 +96,8 @@ class SstFileDumper {
+ ReadOptions read_options_;
+ InternalKeyComparator internal_comparator_;
+ std::unique_ptr<TableProperties> table_properties_;
++ FILE* out;
++ FILE* err;
+ };
+
+ } // namespace ROCKSDB_NAMESPACE
+diff --git a/tools/sst_dump_tool.cc b/tools/sst_dump_tool.cc
+index 7053366e7..b063f8e24 100644
+--- a/tools/sst_dump_tool.cc
++++ b/tools/sst_dump_tool.cc
+@@ -31,7 +31,7 @@ static const std::vector<std::pair<CompressionType, const
char*>>
+
+ namespace {
+
+-void print_help(bool to_stderr) {
++void print_help(bool to_stderr, FILE* out, FILE* err) {
+ std::string supported_compressions;
+ for (CompressionType ct : GetSupportedCompressions()) {
+ if (!supported_compressions.empty()) {
+@@ -43,7 +43,7 @@ void print_help(bool to_stderr) {
+ supported_compressions += str;
+ }
+ fprintf(
+- to_stderr ? stderr : stdout,
++ to_stderr ? err : out,
+ R"(sst_dump --file=<data_dir_OR_sst_file>
[--command=check|scan|raw|recompress|identify]
+ --file=<data_dir_OR_sst_file>
+ Path to SST file or directory containing SST files
+@@ -149,7 +149,8 @@ bool ParseIntArg(const char* arg, const std::string
arg_name,
+ }
+ } // namespace
+
+-int SSTDumpTool::Run(int argc, char const* const* argv, Options options) {
++int SSTDumpTool::Run(int argc, char const* const* argv, Options options,
++ FILE* out, FILE* err) {
+ std::string env_uri, fs_uri;
+ const char* dir_or_file = nullptr;
+ uint64_t read_num = std::numeric_limits<uint64_t>::max();
+@@ -248,7 +249,7 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ return curr.second == compression_type;
+ });
+ if (iter == kCompressions.end()) {
+- fprintf(stderr, "%s is not a valid CompressionType\n",
++ fprintf(err, "%s is not a valid CompressionType\n",
+ compression_type.c_str());
+ exit(1);
+ }
+@@ -273,7 +274,7 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ std::cerr << pik_status.getState() << "\n";
+ retc = -1;
+ }
+- fprintf(stdout, "key=%s\n", ikey.DebugString(true, true).c_str());
++ fprintf(out, "key=%s\n", ikey.DebugString(true, true).c_str());
+ return retc;
+ } else if (ParseIntArg(argv[i], "--compression_level_from=",
+ "compression_level_from must be numeric",
+@@ -288,9 +289,9 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ "compression_max_dict_bytes must be numeric",
+ &tmp_val)) {
+ if (tmp_val < 0 || tmp_val > std::numeric_limits<uint32_t>::max()) {
+- fprintf(stderr, "compression_max_dict_bytes must be a uint32_t:
'%s'\n",
++ fprintf(err, "compression_max_dict_bytes must be a uint32_t: '%s'\n",
+ argv[i]);
+- print_help(/*to_stderr*/ true);
++ print_help(/*to_stderr*/ true, out, err);
+ return 1;
+ }
+ compression_max_dict_bytes = static_cast<uint32_t>(tmp_val);
+@@ -298,10 +299,10 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ "compression_zstd_max_train_bytes must be numeric",
+ &tmp_val)) {
+ if (tmp_val < 0 || tmp_val > std::numeric_limits<uint32_t>::max()) {
+- fprintf(stderr,
++ fprintf(err,
+ "compression_zstd_max_train_bytes must be a uint32_t: '%s'\n",
+ argv[i]);
+- print_help(/*to_stderr*/ true);
++ print_help(/*to_stderr*/ true, out, err);
+ return 1;
+ }
+ compression_zstd_max_train_bytes = static_cast<uint32_t>(tmp_val);
+@@ -309,41 +310,41 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ "compression_max_dict_buffer_bytes must be
numeric",
+ &tmp_val)) {
+ if (tmp_val < 0) {
+- fprintf(stderr,
++ fprintf(err,
+ "compression_max_dict_buffer_bytes must be positive: '%s'\n",
+ argv[i]);
+- print_help(/*to_stderr*/ true);
++ print_help(/*to_stderr*/ true, out, err);
+ return 1;
+ }
+ compression_max_dict_buffer_bytes = static_cast<uint64_t>(tmp_val);
+ } else if (strcmp(argv[i], "--compression_use_zstd_finalize_dict") == 0) {
+ compression_use_zstd_finalize_dict = true;
+ } else if (strcmp(argv[i], "--help") == 0) {
+- print_help(/*to_stderr*/ false);
++ print_help(/*to_stderr*/ false, out, err);
+ return 0;
+ } else if (strcmp(argv[i], "--version") == 0) {
+ printf("%s\n", GetRocksBuildInfoAsString("sst_dump").c_str());
+ return 0;
+ } else {
+- fprintf(stderr, "Unrecognized argument '%s'\n\n", argv[i]);
+- print_help(/*to_stderr*/ true);
++ fprintf(err, "Unrecognized argument '%s'\n\n", argv[i]);
++ print_help(/*to_stderr*/ true, out, err);
+ return 1;
+ }
+ }
+
+ if(has_compression_level_from && has_compression_level_to) {
+ if(!has_specified_compression_types || compression_types.size() != 1) {
+- fprintf(stderr, "Specify one compression type.\n\n");
++ fprintf(err, "Specify one compression type.\n\n");
+ exit(1);
+ }
+ } else if(has_compression_level_from || has_compression_level_to) {
+- fprintf(stderr, "Specify both --compression_level_from and "
++ fprintf(err, "Specify both --compression_level_from and "
+ "--compression_level_to.\n\n");
+ exit(1);
+ }
+
+ if (use_from_as_prefix && has_from) {
+- fprintf(stderr, "Cannot specify --prefix and --from\n\n");
++ fprintf(err, "Cannot specify --prefix and --from\n\n");
+ exit(1);
+ }
+
+@@ -357,8 +358,8 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ }
+
+ if (dir_or_file == nullptr) {
+- fprintf(stderr, "file or directory must be specified.\n\n");
+- print_help(/*to_stderr*/ true);
++ fprintf(err, "file or directory must be specified.\n\n");
++ print_help(/*to_stderr*/ true, out, err);
+ exit(1);
+ }
+
+@@ -373,10 +374,10 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ Status s = Env::CreateFromUri(config_options, env_uri, fs_uri,
&options.env,
+ &env_guard);
+ if (!s.ok()) {
+- fprintf(stderr, "CreateEnvFromUri: %s\n", s.ToString().c_str());
++ fprintf(err, "CreateEnvFromUri: %s\n", s.ToString().c_str());
+ exit(1);
+ } else {
+- fprintf(stdout, "options.env is %p\n", options.env);
++ fprintf(out, "options.env is %p\n", options.env);
+ }
+ }
+
+@@ -390,7 +391,7 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ Status s = env->FileExists(dir_or_file);
+ // dir_or_file does not exist
+ if (!s.ok()) {
+- fprintf(stderr, "%s%s: No such file or directory\n",
s.ToString().c_str(),
++ fprintf(err, "%s%s: No such file or directory\n", s.ToString().c_str(),
+ dir_or_file);
+ return 1;
+ }
+@@ -418,13 +419,13 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ if (dir) {
+ filename = std::string(dir_or_file) + "/" + filename;
+ }
+-
+ ROCKSDB_NAMESPACE::SstFileDumper dumper(
+ options, filename, Temperature::kUnknown, readahead_size,
+- verify_checksum, output_hex, decode_blob_index);
++ verify_checksum, output_hex, decode_blob_index, EnvOptions(),
++ false,out, err);
+ // Not a valid SST
+ if (!dumper.getStatus().ok()) {
+- fprintf(stderr, "%s: %s\n", filename.c_str(),
++ fprintf(err, "%s: %s\n", filename.c_str(),
+ dumper.getStatus().ToString().c_str());
+ continue;
+ } else {
+@@ -434,7 +435,7 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ if (valid_sst_files.size() == 1) {
+ // from_key and to_key are only used for "check", "scan", or ""
+ if (command == "check" || command == "scan" || command == "") {
+- fprintf(stdout, "from [%s] to [%s]\n",
++ fprintf(out, "from [%s] to [%s]\n",
+ ROCKSDB_NAMESPACE::Slice(from_key).ToString(true).c_str(),
+ ROCKSDB_NAMESPACE::Slice(to_key).ToString(true).c_str());
+ }
+@@ -449,7 +450,7 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ compression_zstd_max_train_bytes, compression_max_dict_buffer_bytes,
+ !compression_use_zstd_finalize_dict);
+ if (!st.ok()) {
+- fprintf(stderr, "Failed to recompress: %s\n", st.ToString().c_str());
++ fprintf(err, "Failed to recompress: %s\n", st.ToString().c_str());
+ exit(1);
+ }
+ return 0;
+@@ -461,10 +462,10 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+
+ st = dumper.DumpTable(out_filename);
+ if (!st.ok()) {
+- fprintf(stderr, "%s: %s\n", filename.c_str(), st.ToString().c_str());
++ fprintf(err, "%s: %s\n", filename.c_str(), st.ToString().c_str());
+ exit(1);
+ } else {
+- fprintf(stdout, "raw dump written to file %s\n", &out_filename[0]);
++ fprintf(out, "raw dump written to file %s\n", &out_filename[0]);
+ }
+ continue;
+ }
+@@ -476,7 +477,7 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ has_from || use_from_as_prefix, from_key, has_to, to_key,
+ use_from_as_prefix);
+ if (!st.ok()) {
+- fprintf(stderr, "%s: %s\n", filename.c_str(),
++ fprintf(err, "%s: %s\n", filename.c_str(),
+ st.ToString().c_str());
+ }
+ total_read += dumper.GetReadNumber();
+@@ -488,10 +489,10 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ if (command == "verify") {
+ st = dumper.VerifyChecksum();
+ if (!st.ok()) {
+- fprintf(stderr, "%s is corrupted: %s\n", filename.c_str(),
++ fprintf(err, "%s is corrupted: %s\n", filename.c_str(),
+ st.ToString().c_str());
+ } else {
+- fprintf(stdout, "The file is ok\n");
++ fprintf(out, "The file is ok\n");
+ }
+ continue;
+ }
+@@ -503,15 +504,15 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ table_properties_from_reader;
+ st = dumper.ReadTableProperties(&table_properties_from_reader);
+ if (!st.ok()) {
+- fprintf(stderr, "%s: %s\n", filename.c_str(), st.ToString().c_str());
+- fprintf(stderr, "Try to use initial table properties\n");
++ fprintf(err, "%s: %s\n", filename.c_str(), st.ToString().c_str());
++ fprintf(err, "Try to use initial table properties\n");
+ table_properties = dumper.GetInitTableProperties();
+ } else {
+ table_properties = table_properties_from_reader.get();
+ }
+ if (table_properties != nullptr) {
+ if (show_properties) {
+- fprintf(stdout,
++ fprintf(out,
+ "Table Properties:\n"
+ "------------------------------\n"
+ " %s",
+@@ -523,30 +524,30 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ total_index_block_size += table_properties->index_size;
+ total_filter_block_size += table_properties->filter_size;
+ if (show_properties) {
+- fprintf(stdout,
++ fprintf(out,
+ "Raw user collected properties\n"
+ "------------------------------\n");
+ for (const auto& kv : table_properties->user_collected_properties) {
+ std::string prop_name = kv.first;
+ std::string prop_val = Slice(kv.second).ToString(true);
+- fprintf(stdout, " # %s: 0x%s\n", prop_name.c_str(),
++ fprintf(out, " # %s: 0x%s\n", prop_name.c_str(),
+ prop_val.c_str());
+ }
+ }
+ } else {
+- fprintf(stderr, "Reader unexpectedly returned null properties\n");
++ fprintf(err, "Reader unexpectedly returned null properties\n");
+ }
+ }
+ }
+ if (show_summary) {
+- fprintf(stdout, "total number of files: %" PRIu64 "\n", total_num_files);
+- fprintf(stdout, "total number of data blocks: %" PRIu64 "\n",
++ fprintf(out, "total number of files: %" PRIu64 "\n", total_num_files);
++ fprintf(out, "total number of data blocks: %" PRIu64 "\n",
+ total_num_data_blocks);
+- fprintf(stdout, "total data block size: %" PRIu64 "\n",
++ fprintf(out, "total data block size: %" PRIu64 "\n",
+ total_data_block_size);
+- fprintf(stdout, "total index block size: %" PRIu64 "\n",
++ fprintf(out, "total index block size: %" PRIu64 "\n",
+ total_index_block_size);
+- fprintf(stdout, "total filter block size: %" PRIu64 "\n",
++ fprintf(out, "total filter block size: %" PRIu64 "\n",
+ total_filter_block_size);
+ }
+
+@@ -554,24 +555,24 @@ int SSTDumpTool::Run(int argc, char const* const* argv,
Options options) {
+ // No valid SST files are found
+ // Exit with an error state
+ if (dir) {
+- fprintf(stdout, "------------------------------\n");
+- fprintf(stderr, "No valid SST files found in %s\n", dir_or_file);
++ fprintf(out, "------------------------------\n");
++ fprintf(err, "No valid SST files found in %s\n", dir_or_file);
+ } else {
+- fprintf(stderr, "%s is not a valid SST file\n", dir_or_file);
++ fprintf(err, "%s is not a valid SST file\n", dir_or_file);
+ }
+ return 1;
+ } else {
+ if (command == "identify") {
+ if (dir) {
+- fprintf(stdout, "------------------------------\n");
+- fprintf(stdout, "List of valid SST files found in %s:\n",
dir_or_file);
++ fprintf(out, "------------------------------\n");
++ fprintf(out, "List of valid SST files found in %s:\n", dir_or_file);
+ for (const auto& f : valid_sst_files) {
+- fprintf(stdout, "%s\n", f.c_str());
++ fprintf(out, "%s\n", f.c_str());
+ }
+- fprintf(stdout, "Number of valid SST files: %zu\n",
++ fprintf(out, "Number of valid SST files: %zu\n",
+ valid_sst_files.size());
+ } else {
+- fprintf(stdout, "%s is a valid SST file\n", dir_or_file);
++ fprintf(out, "%s is a valid SST file\n", dir_or_file);
+ }
+ }
+ // At least one valid SST
diff --git a/hadoop-ozone/dist/pom.xml b/hadoop-ozone/dist/pom.xml
index 40a55033f9..053d2c9fcd 100644
--- a/hadoop-ozone/dist/pom.xml
+++ b/hadoop-ozone/dist/pom.xml
@@ -75,7 +75,7 @@
<includes>*.classpath</includes>
<includeArtifactIds>
hdds-server-scm,ozone-common,ozone-csi,ozone-datanode,ozone-httpfsgateway,
-
ozone-insight,ozone-manager,ozone-recon,ozone-s3gateway,ozone-tools
+
ozone-insight,ozone-manager,ozone-recon,ozone-s3gateway,ozone-tools,hdds-rocks-native
</includeArtifactIds>
</configuration>
</execution>
@@ -227,6 +227,10 @@
<groupId>org.apache.ozone</groupId>
<artifactId>ozone-httpfsgateway</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.ozone</groupId>
+ <artifactId>hdds-rocks-native</artifactId>
+ </dependency>
</dependencies>
<profiles>
<profile>
diff --git a/hadoop-ozone/dist/src/main/license/bin/LICENSE.txt
b/hadoop-ozone/dist/src/main/license/bin/LICENSE.txt
index bc0277fa3c..6bf1824601 100644
--- a/hadoop-ozone/dist/src/main/license/bin/LICENSE.txt
+++ b/hadoop-ozone/dist/src/main/license/bin/LICENSE.txt
@@ -514,7 +514,7 @@ WTFPL
--------------------------------------------------------------------------------
-hdds-server-scm, ozone-manager, ozone-s3gateway and hdds-server-framework
+hdds-server-scm, ozone-manager, ozone-s3gateway, hdds-rocks-native and
hdds-server-framework
contains the source of the following javascript/css components (See licenses/
for text of these licenses):
Apache Software Foundation License 2.0
diff --git a/hadoop-ozone/dist/src/main/license/jar-report.txt
b/hadoop-ozone/dist/src/main/license/jar-report.txt
index f83427959e..e6da280004 100644
--- a/hadoop-ozone/dist/src/main/license/jar-report.txt
+++ b/hadoop-ozone/dist/src/main/license/jar-report.txt
@@ -76,6 +76,7 @@ share/ozone/lib/hdds-hadoop-dependency-server.jar
share/ozone/lib/hdds-interface-admin.jar
share/ozone/lib/hdds-interface-client.jar
share/ozone/lib/hdds-interface-server.jar
+share/ozone/lib/hdds-rocks-native.jar
share/ozone/lib/hdds-managed-rocksdb.jar
share/ozone/lib/hdds-server-framework.jar
share/ozone/lib/hdds-server-scm.jar
diff --git a/hadoop-ozone/pom.xml b/hadoop-ozone/pom.xml
index 3097140a4e..16ec897f6b 100644
--- a/hadoop-ozone/pom.xml
+++ b/hadoop-ozone/pom.xml
@@ -268,6 +268,11 @@
<artifactId>bcprov-jdk15on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.ozone</groupId>
+ <artifactId>hdds-rocks-native</artifactId>
+ <version>${hdds.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
<dependencies>
diff --git a/pom.xml b/pom.xml
index 8295a82ae0..7fd86e5d0a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -126,6 +126,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xs
<commons-pool2.version>2.6.0</commons-pool2.version>
<commons-text.version>1.4</commons-text.version>
<commons-validator.version>1.6</commons-validator.version>
+ <download-maven-plugin.version>1.6.8</download-maven-plugin.version>
<test.build.dir>${project.build.directory}/test-dir</test.build.dir>
<test.build.data>${test.build.dir}</test.build.data>
@@ -294,6 +295,11 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xs
<aspectj-plugin.version>1.14.0</aspectj-plugin.version>
<restrict-imports.enforcer.version>2.0.0</restrict-imports.enforcer.version>
<awaitility.version>4.2.0</awaitility.version>
+ <bzip2.version>1.0.8</bzip2.version>
+ <zlib.version>1.2.13</zlib.version>
+ <lz4.version>1.9.3</lz4.version>
+ <snappy.version>1.1.8</snappy.version>
+ <zstd.version>1.4.9</zstd.version>
</properties>
@@ -1811,6 +1817,11 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xs
<artifactId>docker-maven-plugin</artifactId>
<version>${docker-maven-plugin.version}</version>
</plugin>
+ <plugin>
+ <groupId>com.googlecode.maven-download-plugin</groupId>
+ <artifactId>download-maven-plugin</artifactId>
+ <version>${download-maven-plugin.version}</version>
+ </plugin>
</plugins>
</pluginManagement>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]