You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by ya...@apache.org on 2022/08/03 05:19:36 UTC
[doris-thirdparty] 02/21: Initial commit
This is an automated email from the ASF dual-hosted git repository.
yangzhg pushed a commit to branch libhdfs3
in repository https://gitbox.apache.org/repos/asf/doris-thirdparty.git
commit 9eff2afbfcd01d56ac6a754e06540f5f068920a5
Author: yangzhg <ya...@gmail.com>
AuthorDate: Mon Jun 6 10:44:53 2022 +0800
Initial commit
---
CMake/CMakeTestCompileNestedException.cpp | 10 +
CMake/CMakeTestCompileSteadyClock.cpp | 7 +
CMake/CMakeTestCompileStrerror.cpp | 10 +
CMake/CodeCoverage.cmake | 48 +
CMake/FindBoost.cmake | 1162 ++++++++++++++++++
CMake/FindGSasl.cmake | 26 +
CMake/FindGoogleTest.cmake | 73 ++
CMake/FindKERBEROS.cmake | 23 +
CMake/FindLibUUID.cmake | 23 +
CMake/Functions.cmake | 46 +
CMake/Options.cmake | 169 +++
CMake/Platform.cmake | 33 +
CMakeLists.txt | 65 +
Makefile | 76 ++
Makefile.global.in | 40 +
README.md | 83 ++
bootstrap | 138 +++
debian/.gitignore | 15 +
debian/build.sh | 118 ++
debian/changelog.in | 3 +
debian/compat | 1 +
debian/control | 27 +
debian/copyright | 21 +
debian/libhdfs3-dev.dirs | 2 +
debian/libhdfs3-dev.install | 4 +
debian/libhdfs3-dev.lintian-overrides | 1 +
debian/libhdfs3.dirs | 1 +
debian/libhdfs3.install | 1 +
debian/libhdfs3.lintian-overrides | 1 +
debian/rules | 24 +
debian/source/format | 1 +
mock/CMakeLists.txt | 7 +
mock/MockBufferedSocketReader.h | 43 +
mock/MockDatanode.h | 44 +
mock/MockFileSystemInter.h | 111 ++
mock/MockLeaseRenewer.h | 56 +
mock/MockNamenode.h | 110 ++
mock/MockOperationCanceledCallback.h | 48 +
mock/MockPipeline.h | 47 +
mock/MockRpcChannel.h | 43 +
mock/MockRpcClient.h | 48 +
mock/MockRpcRemoteCall.h | 46 +
mock/MockSockCall.h | 59 +
mock/MockSocket.h | 60 +
mock/MockSystem.cpp | 142 +++
mock/MockSystem.h | 106 ++
mock/NamenodeStub.h | 49 +
mock/PipelineStub.h | 49 +
mock/TestDatanodeStub.h | 42 +
mock/TestRpcChannelStub.h | 50 +
mock/TestUtil.h | 94 ++
rpms/.gitignore | 7 +
rpms/build.sh | 111 ++
rpms/libhdfs3.spec | 91 ++
src/.gitignore | 2 +
src/CMakeLists.txt | 127 ++
src/client/BlockLocation.h | 91 ++
src/client/BlockReader.h | 60 +
src/client/DataTransferProtocol.h | 117 ++
src/client/DataTransferProtocolSender.cpp | 197 ++++
src/client/DataTransferProtocolSender.h | 137 +++
src/client/DirectoryIterator.cpp | 94 ++
src/client/DirectoryIterator.h | 57 +
src/client/EncryptionZoneInfo.h | 80 ++
src/client/EncryptionZoneIterator.cpp | 86 ++
src/client/EncryptionZoneIterator.h | 56 +
src/client/FileEncryptionInfo.h | 93 ++
src/client/FileStatus.h | 178 +++
src/client/FileSystem.cpp | 639 ++++++++++
src/client/FileSystem.h | 320 +++++
src/client/FileSystemImpl.cpp | 867 ++++++++++++++
src/client/FileSystemImpl.h | 541 +++++++++
src/client/FileSystemInter.h | 528 +++++++++
src/client/FileSystemKey.cpp | 93 ++
src/client/FileSystemKey.h | 101 ++
src/client/FileSystemStats.h | 83 ++
src/client/Hdfs.cpp | 1565 +++++++++++++++++++++++++
src/client/InputStream.cpp | 101 ++
src/client/InputStream.h | 93 ++
src/client/InputStreamImpl.cpp | 806 +++++++++++++
src/client/InputStreamImpl.h | 154 +++
src/client/InputStreamInter.h | 98 ++
src/client/KerberosName.cpp | 115 ++
src/client/KerberosName.h | 98 ++
src/client/LeaseRenewer.cpp | 161 +++
src/client/LeaseRenewer.h | 76 ++
src/client/LocalBlockReader.cpp | 282 +++++
src/client/LocalBlockReader.h | 99 ++
src/client/OutputStream.cpp | 90 ++
src/client/OutputStream.h | 126 ++
src/client/OutputStreamImpl.cpp | 636 ++++++++++
src/client/OutputStreamImpl.h | 167 +++
src/client/OutputStreamInter.h | 92 ++
src/client/Packet.cpp | 150 +++
src/client/Packet.h | 125 ++
src/client/PacketHeader.cpp | 120 ++
src/client/PacketHeader.h | 62 +
src/client/PacketPool.cpp | 57 +
src/client/PacketPool.h | 65 +
src/client/PeerCache.cpp | 76 ++
src/client/PeerCache.h | 59 +
src/client/Permission.cpp | 42 +
src/client/Permission.h | 218 ++++
src/client/Pipeline.cpp | 786 +++++++++++++
src/client/Pipeline.h | 197 ++++
src/client/PipelineAck.h | 86 ++
src/client/ReadShortCircuitInfo.cpp | 358 ++++++
src/client/ReadShortCircuitInfo.h | 187 +++
src/client/RemoteBlockReader.cpp | 367 ++++++
src/client/RemoteBlockReader.h | 105 ++
src/client/Token.cpp | 174 +++
src/client/Token.h | 85 ++
src/client/TokenInternal.h | 30 +
src/client/UserInfo.cpp | 75 ++
src/client/UserInfo.h | 102 ++
src/client/hdfs.h | 795 +++++++++++++
src/common/Atomic.h | 55 +
src/common/BigEndian.h | 58 +
src/common/CFileWrapper.cpp | 121 ++
src/common/Checksum.h | 66 ++
src/common/DateTime.h | 73 ++
src/common/Exception.cpp | 90 ++
src/common/Exception.h | 535 +++++++++
src/common/ExceptionInternal.cpp | 185 +++
src/common/ExceptionInternal.h | 293 +++++
src/common/FileWrapper.h | 89 ++
src/common/Function.h | 54 +
src/common/HWCrc32c.cpp | 159 +++
src/common/HWCrc32c.h | 80 ++
src/common/Hash.cpp | 93 ++
src/common/Hash.h | 145 +++
src/common/Logger.cpp | 112 ++
src/common/Logger.h | 63 +
src/common/LruMap.h | 144 +++
src/common/MappedFileWrapper.cpp | 148 +++
src/common/Memory.h | 52 +
src/common/SWCrc32c.cpp | 103 ++
src/common/SWCrc32c.h | 96 ++
src/common/SessionConfig.cpp | 182 +++
src/common/SessionConfig.h | 368 ++++++
src/common/StackPrinter.cpp | 675 +++++++++++
src/common/StackPrinter.h | 41 +
src/common/StringUtil.h | 98 ++
src/common/Thread.cpp | 48 +
src/common/Thread.h | 101 ++
src/common/Unordered.h | 56 +
src/common/WritableUtils.cpp | 188 +++
src/common/WritableUtils.h | 69 ++
src/common/WriteBuffer.cpp | 74 ++
src/common/WriteBuffer.h | 239 ++++
src/common/XmlConfig.cpp | 391 +++++++
src/common/XmlConfig.h | 186 +++
src/doxyfile.in | 1824 +++++++++++++++++++++++++++++
src/libhdfs3.pc.in | 27 +
src/network/BufferedSocketReader.cpp | 151 +++
src/network/BufferedSocketReader.h | 135 +++
src/network/DomainSocket.cpp | 153 +++
src/network/DomainSocket.h | 97 ++
src/network/Socket.h | 166 +++
src/network/Syscall.h | 60 +
src/network/TcpSocket.cpp | 404 +++++++
src/network/TcpSocket.h | 183 +++
src/platform.h.in | 51 +
src/proto/ClientDatanodeProtocol.proto | 164 +++
src/proto/ClientNamenodeProtocol.proto | 763 ++++++++++++
src/proto/IpcConnectionContext.proto | 52 +
src/proto/ProtobufRpcEngine.proto | 67 ++
src/proto/RpcHeader.proto | 159 +++
src/proto/Security.proto | 63 +
src/proto/datatransfer.proto | 228 ++++
src/proto/encryption.proto | 67 ++
src/proto/hdfs.proto | 521 ++++++++
src/rpc/RpcAuth.cpp | 49 +
src/rpc/RpcAuth.h | 100 ++
src/rpc/RpcCall.h | 78 ++
src/rpc/RpcChannel.cpp | 853 ++++++++++++++
src/rpc/RpcChannel.h | 270 +++++
src/rpc/RpcChannelKey.cpp | 49 +
src/rpc/RpcChannelKey.h | 89 ++
src/rpc/RpcClient.cpp | 192 +++
src/rpc/RpcClient.h | 159 +++
src/rpc/RpcConfig.cpp | 39 +
src/rpc/RpcConfig.h | 149 +++
src/rpc/RpcContentWrapper.cpp | 59 +
src/rpc/RpcContentWrapper.h | 48 +
src/rpc/RpcProtocolInfo.cpp | 33 +
src/rpc/RpcProtocolInfo.h | 80 ++
src/rpc/RpcRemoteCall.cpp | 81 ++
src/rpc/RpcRemoteCall.h | 112 ++
src/rpc/RpcServerInfo.cpp | 35 +
src/rpc/RpcServerInfo.h | 82 ++
src/rpc/SaslClient.cpp | 160 +++
src/rpc/SaslClient.h | 62 +
src/server/BlockLocalPathInfo.h | 65 +
src/server/Datanode.cpp | 95 ++
src/server/Datanode.h | 104 ++
src/server/DatanodeInfo.h | 130 ++
src/server/ExtendedBlock.h | 98 ++
src/server/LocatedBlock.h | 112 ++
src/server/LocatedBlocks.cpp | 74 ++
src/server/LocatedBlocks.h | 113 ++
src/server/Namenode.h | 850 ++++++++++++++
src/server/NamenodeImpl.cpp | 869 ++++++++++++++
src/server/NamenodeImpl.h | 245 ++++
src/server/NamenodeInfo.cpp | 62 +
src/server/NamenodeInfo.h | 61 +
src/server/NamenodeProxy.cpp | 552 +++++++++
src/server/NamenodeProxy.h | 165 +++
src/server/RpcHelper.h | 318 +++++
test/CMakeLists.txt | 43 +
test/data/checksum1.in | 512 ++++++++
test/data/checksum2.in | 512 ++++++++
test/data/function-secure.xml | 43 +
test/data/function-secure.xml.sample | 43 +
test/data/function-test.xml | 117 ++
test/data/function-test.xml.sample | 107 ++
test/data/hdfs-default.xml | 1136 ++++++++++++++++++
test/data/invalid.xml | 6 +
test/data/invalidha.xml | 29 +
test/data/unit-config.xml | 83 ++
test/data/validha.xml | 35 +
test/function/CMakeLists.txt | 71 ++
test/function/FunctionTestMain.cpp | 32 +
test/function/TestCInterface.cpp | 1629 ++++++++++++++++++++++++++
test/function/TestFileSystem.cpp | 322 +++++
test/function/TestInputStream.cpp | 490 ++++++++
test/function/TestOutputStream.cpp | 780 ++++++++++++
test/secure/CMakeLists.txt | 70 ++
test/secure/FunctionTestSecureMain.cpp | 32 +
test/secure/SecureFunctionTest.cpp | 396 +++++++
test/secure/TestSecureCInterface.cpp | 177 +++
test/unit/CMakeLists.txt | 66 ++
test/unit/TestBufferedSocketReader.cpp | 174 +++
test/unit/TestChecksum.cpp | 135 +++
test/unit/TestException.cpp | 116 ++
test/unit/TestGetHANamenodes.cpp | 54 +
test/unit/TestLeaseRenewer.cpp | 42 +
test/unit/TestLocatedBlocks.cpp | 87 ++
test/unit/TestLruMap.cpp | 58 +
test/unit/TestRpcChannel.cpp | 437 +++++++
test/unit/TestRpcClient.cpp | 104 ++
test/unit/TestSessionConfig.cpp | 33 +
test/unit/TestSocket.cpp | 450 +++++++
test/unit/TestXmlConfig.cpp | 66 ++
test/unit/UnitTestInputStream.cpp | 218 ++++
test/unit/UnitTestMain.cpp | 32 +
test/unit/UnitTestOutputStream.cpp | 404 +++++++
test/unit/UnitTestUtils.h | 63 +
248 files changed, 44103 insertions(+)
diff --git a/CMake/CMakeTestCompileNestedException.cpp b/CMake/CMakeTestCompileNestedException.cpp
new file mode 100644
index 0000000..66918ca
--- /dev/null
+++ b/CMake/CMakeTestCompileNestedException.cpp
@@ -0,0 +1,10 @@
+#include <exception>
+#include <stdexcept>
+
+int main() {
+ try {
+ throw 2;
+ } catch (int) {
+ std::throw_with_nested(std::runtime_error("test"));
+ }
+}
diff --git a/CMake/CMakeTestCompileSteadyClock.cpp b/CMake/CMakeTestCompileSteadyClock.cpp
new file mode 100644
index 0000000..afcbe1b
--- /dev/null
+++ b/CMake/CMakeTestCompileSteadyClock.cpp
@@ -0,0 +1,7 @@
+#include <chrono>
+
+using std::chrono::steady_clock;
+
+void foo(const steady_clock &clock) {
+ return;
+}
diff --git a/CMake/CMakeTestCompileStrerror.cpp b/CMake/CMakeTestCompileStrerror.cpp
new file mode 100644
index 0000000..0ef4eda
--- /dev/null
+++ b/CMake/CMakeTestCompileStrerror.cpp
@@ -0,0 +1,10 @@
+#include <string.h>
+
+int main()
+{
+ // We can't test "char *p = strerror_r()" because that only causes a
+ // compiler warning when strerror_r returns an integer.
+ char *buf = 0;
+ int i = strerror_r(0, buf, 100);
+ return i;
+}
diff --git a/CMake/CodeCoverage.cmake b/CMake/CodeCoverage.cmake
new file mode 100644
index 0000000..ce99792
--- /dev/null
+++ b/CMake/CodeCoverage.cmake
@@ -0,0 +1,48 @@
+# Check prereqs
+FIND_PROGRAM(GCOV_PATH gcov)
+FIND_PROGRAM(LCOV_PATH lcov)
+FIND_PROGRAM(GENHTML_PATH genhtml)
+
+IF(NOT GCOV_PATH)
+ MESSAGE(FATAL_ERROR "gcov not found! Aborting...")
+ENDIF(NOT GCOV_PATH)
+
+IF(NOT CMAKE_BUILD_TYPE STREQUAL Debug)
+ MESSAGE(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
+ENDIF(NOT CMAKE_BUILD_TYPE STREQUAL Debug)
+
+#Setup compiler options
+ADD_DEFINITIONS(-fprofile-arcs -ftest-coverage)
+
+SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs ")
+SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fprofile-arcs ")
+
+IF(NOT LCOV_PATH)
+ MESSAGE(FATAL_ERROR "lcov not found! Aborting...")
+ENDIF(NOT LCOV_PATH)
+
+IF(NOT GENHTML_PATH)
+ MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
+ENDIF(NOT GENHTML_PATH)
+
+#Setup target
+ADD_CUSTOM_TARGET(ShowCoverage
+ #Capturing lcov counters and generating report
+ COMMAND ${LCOV_PATH} --directory . --capture --output-file CodeCoverage.info
+ COMMAND ${LCOV_PATH} --remove CodeCoverage.info '${CMAKE_CURRENT_BINARY_DIR}/*' 'test/*' 'mock/*' '/usr/*' '/opt/*' '*ext/rhel5_x86_64*' '*ext/osx*' --output-file CodeCoverage.info.cleaned
+ COMMAND ${GENHTML_PATH} -o CodeCoverageReport CodeCoverage.info.cleaned
+)
+
+
+ADD_CUSTOM_TARGET(ShowAllCoverage
+ #Capturing lcov counters and generating report
+ COMMAND ${LCOV_PATH} -a CodeCoverage.info.cleaned -a CodeCoverage.info.cleaned_withoutHA -o AllCodeCoverage.info
+ COMMAND sed -e 's|/.*/src|${CMAKE_SOURCE_DIR}/src|' -ig AllCodeCoverage.info
+ COMMAND ${GENHTML_PATH} -o AllCodeCoverageReport AllCodeCoverage.info
+)
+
+ADD_CUSTOM_TARGET(ResetCoverage
+ #Cleanup lcov
+ COMMAND ${LCOV_PATH} --directory . --zerocounters
+)
+
diff --git a/CMake/FindBoost.cmake b/CMake/FindBoost.cmake
new file mode 100644
index 0000000..914a0a5
--- /dev/null
+++ b/CMake/FindBoost.cmake
@@ -0,0 +1,1162 @@
+# - Find Boost include dirs and libraries
+# Use this module by invoking find_package with the form:
+# find_package(Boost
+# [version] [EXACT] # Minimum or EXACT version e.g. 1.36.0
+# [REQUIRED] # Fail with error if Boost is not found
+# [COMPONENTS <libs>...] # Boost libraries by their canonical name
+# ) # e.g. "date_time" for "libboost_date_time"
+# This module finds headers and requested component libraries OR a CMake
+# package configuration file provided by a "Boost CMake" build. For the
+# latter case skip to the "Boost CMake" section below. For the former
+# case results are reported in variables:
+# Boost_FOUND - True if headers and requested libraries were found
+# Boost_INCLUDE_DIRS - Boost include directories
+# Boost_LIBRARY_DIRS - Link directories for Boost libraries
+# Boost_LIBRARIES - Boost component libraries to be linked
+# Boost_<C>_FOUND - True if component <C> was found (<C> is upper-case)
+# Boost_<C>_LIBRARY - Libraries to link for component <C> (may include
+# target_link_libraries debug/optimized keywords)
+# Boost_VERSION - BOOST_VERSION value from boost/version.hpp
+# Boost_LIB_VERSION - Version string appended to library filenames
+# Boost_MAJOR_VERSION - Boost major version number (X in X.y.z)
+# Boost_MINOR_VERSION - Boost minor version number (Y in x.Y.z)
+# Boost_SUBMINOR_VERSION - Boost subminor version number (Z in x.y.Z)
+# Boost_LIB_DIAGNOSTIC_DEFINITIONS (Windows)
+# - Pass to add_definitions() to have diagnostic
+# information about Boost's automatic linking
+# displayed during compilation
+#
+# This module reads hints about search locations from variables:
+# BOOST_ROOT - Preferred installation prefix
+# (or BOOSTROOT)
+# BOOST_INCLUDEDIR - Preferred include directory e.g. <prefix>/include
+# BOOST_LIBRARYDIR - Preferred library directory e.g. <prefix>/lib
+# Boost_NO_SYSTEM_PATHS - Set to ON to disable searching in locations not
+# specified by these hint variables. Default is OFF.
+# Boost_ADDITIONAL_VERSIONS
+# - List of Boost versions not known to this module
+# (Boost install locations may contain the version)
+# and saves search results persistently in CMake cache entries:
+# Boost_INCLUDE_DIR - Directory containing Boost headers
+# Boost_LIBRARY_DIR - Directory containing Boost libraries
+# Boost_<C>_LIBRARY_DEBUG - Component <C> library debug variant
+# Boost_<C>_LIBRARY_RELEASE - Component <C> library release variant
+# Users may set these hints or results as cache entries. Projects should
+# not read these entries directly but instead use the above result variables.
+# Note that some hint names start in upper-case "BOOST". One may specify
+# these as environment variables if they are not specified as CMake variables
+# or cache entries.
+#
+# This module first searches for the Boost header files using the above hint
+# variables (excluding BOOST_LIBRARYDIR) and saves the result in
+# Boost_INCLUDE_DIR. Then it searches for requested component libraries using
+# the above hints (excluding BOOST_INCLUDEDIR and Boost_ADDITIONAL_VERSIONS),
+# "lib" directories near Boost_INCLUDE_DIR, and the library name configuration
+# settings below. It saves the library directory in Boost_LIBRARY_DIR and
+# individual library locations in Boost_<C>_LIBRARY_DEBUG and
+# Boost_<C>_LIBRARY_RELEASE. When one changes settings used by previous
+# searches in the same build tree (excluding environment variables) this
+# module discards previous search results affected by the changes and searches
+# again.
+#
+# Boost libraries come in many variants encoded in their file name. Users or
+# projects may tell this module which variant to find by setting variables:
+# Boost_USE_MULTITHREADED - Set to OFF to use the non-multithreaded
+# libraries ('mt' tag). Default is ON.
+# Boost_USE_STATIC_LIBS - Set to ON to force the use of the static
+# libraries. Default is OFF.
+# Boost_USE_STATIC_RUNTIME - Set to ON or OFF to specify whether to use
+# libraries linked statically to the C++ runtime
+# ('s' tag). Default is platform dependent.
+# Boost_USE_DEBUG_PYTHON - Set to ON to use libraries compiled with a
+# debug Python build ('y' tag). Default is OFF.
+# Boost_USE_STLPORT - Set to ON to use libraries compiled with
+# STLPort ('p' tag). Default is OFF.
+# Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS
+# - Set to ON to use libraries compiled with
+# STLPort deprecated "native iostreams"
+# ('n' tag). Default is OFF.
+# Boost_COMPILER - Set to the compiler-specific library suffix
+# (e.g. "-gcc43"). Default is auto-computed
+# for the C++ compiler in use.
+# Boost_THREADAPI - Suffix for "thread" component library name,
+# such as "pthread" or "win32". Names with
+# and without this suffix will both be tried.
+# Other variables one may set to control this module are:
+# Boost_DEBUG - Set to ON to enable debug output from FindBoost.
+# Please enable this before filing any bug report.
+# Boost_DETAILED_FAILURE_MSG
+# - Set to ON to add detailed information to the
+# failure message even when the REQUIRED option
+# is not given to the find_package call.
+# Boost_REALPATH - Set to ON to resolve symlinks for discovered
+# libraries to assist with packaging. For example,
+# the "system" component library may be resolved to
+# "/usr/lib/libboost_system.so.1.42.0" instead of
+# "/usr/lib/libboost_system.so". This does not
+# affect linking and should not be enabled unless
+# the user needs this information.
+# On Visual Studio and Borland compilers Boost headers request automatic
+# linking to corresponding libraries. This requires matching libraries to be
+# linked explicitly or available in the link library search path. In this
+# case setting Boost_USE_STATIC_LIBS to OFF may not achieve dynamic linking.
+# Boost automatic linking typically requests static libraries with a few
+# exceptions (such as Boost.Python). Use
+# add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS})
+# to ask Boost to report information about automatic linking requests.
+#
+# Example to find Boost headers only:
+# find_package(Boost 1.36.0)
+# if(Boost_FOUND)
+# include_directories(${Boost_INCLUDE_DIRS})
+# add_executable(foo foo.cc)
+# endif()
+# Example to find Boost headers and some libraries:
+# set(Boost_USE_STATIC_LIBS ON)
+# set(Boost_USE_MULTITHREADED ON)
+# set(Boost_USE_STATIC_RUNTIME OFF)
+# find_package(Boost 1.36.0 COMPONENTS date_time filesystem system ...)
+# if(Boost_FOUND)
+# include_directories(${Boost_INCLUDE_DIRS})
+# add_executable(foo foo.cc)
+# target_link_libraries(foo ${Boost_LIBRARIES})
+# endif()
+#
+# Boost CMake ----------------------------------------------------------
+#
+# If Boost was built using the boost-cmake project it provides a package
+# configuration file for use with find_package's Config mode. This module
+# looks for the package configuration file called BoostConfig.cmake or
+# boost-config.cmake and stores the result in cache entry "Boost_DIR". If
+# found, the package configuration file is loaded and this module returns with
+# no further action. See documentation of the Boost CMake package
+# configuration for details on what it provides.
+#
+# Set Boost_NO_BOOST_CMAKE to ON to disable the search for boost-cmake.
+
+#=============================================================================
+# Copyright 2006-2012 Kitware, Inc.
+# Copyright 2006-2008 Andreas Schneider <ma...@cynapses.org>
+# Copyright 2007 Wengo
+# Copyright 2007 Mike Jackson
+# Copyright 2008 Andreas Pakulat <ap...@gmx.de>
+# Copyright 2008-2012 Philip Lowman <ph...@yhbt.com>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+
+#-------------------------------------------------------------------------------
+# Before we go searching, check whether boost-cmake is available, unless the
+# user specifically asked NOT to search for boost-cmake.
+#
+# If Boost_DIR is set, this behaves as any find_package call would. If not,
+# it looks at BOOST_ROOT and BOOSTROOT to find Boost.
+#
+if (NOT Boost_NO_BOOST_CMAKE)
+ # If Boost_DIR is not set, look for BOOSTROOT and BOOST_ROOT as alternatives,
+ # since these are more conventional for Boost.
+ if ("$ENV{Boost_DIR}" STREQUAL "")
+ if (NOT "$ENV{BOOST_ROOT}" STREQUAL "")
+ set(ENV{Boost_DIR} $ENV{BOOST_ROOT})
+ elseif (NOT "$ENV{BOOSTROOT}" STREQUAL "")
+ set(ENV{Boost_DIR} $ENV{BOOSTROOT})
+ endif()
+ endif()
+
+ # Do the same find_package call but look specifically for the CMake version.
+ # Note that args are passed in the Boost_FIND_xxxxx variables, so there is no
+ # need to delegate them to this find_package call.
+ find_package(Boost QUIET NO_MODULE)
+ mark_as_advanced(Boost_DIR)
+
+ # If we found boost-cmake, then we're done. Print out what we found.
+ # Otherwise let the rest of the module try to find it.
+ if (Boost_FOUND)
+ message("Boost ${Boost_FIND_VERSION} found.")
+ if (Boost_FIND_COMPONENTS)
+ message("Found Boost components:")
+ message(" ${Boost_FIND_COMPONENTS}")
+ endif()
+ return()
+ endif()
+endif()
+
+
+#-------------------------------------------------------------------------------
+# FindBoost functions & macros
+#
+
+############################################
+#
+# Check the existence of the libraries.
+#
+############################################
+# This macro was taken directly from the FindQt4.cmake file that is included
+# with the CMake distribution. This is NOT my work. All work was done by the
+# original authors of the FindQt4.cmake file. Only minor modifications were
+# made to remove references to Qt and make this file more generally applicable
+# And ELSE/ENDIF pairs were removed for readability.
+#########################################################################
+
+macro(_Boost_ADJUST_LIB_VARS basename)
+ if(Boost_INCLUDE_DIR )
+ if(Boost_${basename}_LIBRARY_DEBUG AND Boost_${basename}_LIBRARY_RELEASE)
+ # if the generator supports configuration types then set
+ # optimized and debug libraries, or if the CMAKE_BUILD_TYPE has a value
+ if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
+ set(Boost_${basename}_LIBRARY optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG})
+ else()
+ # if there are no configuration types and CMAKE_BUILD_TYPE has no value
+ # then just use the release libraries
+ set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} )
+ endif()
+ # FIXME: This probably should be set for both cases
+ set(Boost_${basename}_LIBRARIES optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG})
+ endif()
+
+ # if only the release version was found, set the debug variable also to the release version
+ if(Boost_${basename}_LIBRARY_RELEASE AND NOT Boost_${basename}_LIBRARY_DEBUG)
+ set(Boost_${basename}_LIBRARY_DEBUG ${Boost_${basename}_LIBRARY_RELEASE})
+ set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE})
+ set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE})
+ endif()
+
+ # if only the debug version was found, set the release variable also to the debug version
+ if(Boost_${basename}_LIBRARY_DEBUG AND NOT Boost_${basename}_LIBRARY_RELEASE)
+ set(Boost_${basename}_LIBRARY_RELEASE ${Boost_${basename}_LIBRARY_DEBUG})
+ set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_DEBUG})
+ set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_DEBUG})
+ endif()
+
+ # If the debug & release library ends up being the same, omit the keywords
+ if(${Boost_${basename}_LIBRARY_RELEASE} STREQUAL ${Boost_${basename}_LIBRARY_DEBUG})
+ set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} )
+ set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE} )
+ endif()
+
+ if(Boost_${basename}_LIBRARY)
+ set(Boost_${basename}_FOUND ON)
+ endif()
+
+ endif()
+ # Make variables changeable to the advanced user
+ mark_as_advanced(
+ Boost_${basename}_LIBRARY_RELEASE
+ Boost_${basename}_LIBRARY_DEBUG
+ )
+endmacro()
+
+macro(_Boost_CHANGE_DETECT changed_var)
+ set(${changed_var} 0)
+ foreach(v ${ARGN})
+ if(DEFINED _Boost_COMPONENTS_SEARCHED)
+ if(${v})
+ if(_${v}_LAST)
+ string(COMPARE NOTEQUAL "${${v}}" "${_${v}_LAST}" _${v}_CHANGED)
+ else()
+ set(_${v}_CHANGED 1)
+ endif()
+ elseif(_${v}_LAST)
+ set(_${v}_CHANGED 1)
+ endif()
+ if(_${v}_CHANGED)
+ set(${changed_var} 1)
+ endif()
+ else()
+ set(_${v}_CHANGED 0)
+ endif()
+ endforeach()
+endmacro()
+
+macro(_Boost_FIND_LIBRARY var)
+ find_library(${var} ${ARGN})
+
+ # If we found the first library save Boost_LIBRARY_DIR.
+ if(${var} AND NOT Boost_LIBRARY_DIR)
+ get_filename_component(_dir "${${var}}" PATH)
+ set(Boost_LIBRARY_DIR "${_dir}" CACHE PATH "Boost library directory" FORCE)
+ endif()
+
+ # If Boost_LIBRARY_DIR is known then search only there.
+ if(Boost_LIBRARY_DIR)
+ set(_boost_LIBRARY_SEARCH_DIRS ${Boost_LIBRARY_DIR} NO_DEFAULT_PATH)
+ endif()
+endmacro()
+
+#-------------------------------------------------------------------------------
+
+#
+# Runs compiler with "-dumpversion" and parses major/minor
+# version with a regex.
+#
+function(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION)
+
+ exec_program(${CMAKE_CXX_COMPILER}
+ ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion
+ OUTPUT_VARIABLE _boost_COMPILER_VERSION
+ )
+ string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2"
+ _boost_COMPILER_VERSION ${_boost_COMPILER_VERSION})
+
+ set(${_OUTPUT_VERSION} ${_boost_COMPILER_VERSION} PARENT_SCOPE)
+endfunction()
+
+#
+# Take a list of libraries with "thread" in it
+# and prepend duplicates with "thread_${Boost_THREADAPI}"
+# at the front of the list
+#
+function(_Boost_PREPEND_LIST_WITH_THREADAPI _output)
+ set(_orig_libnames ${ARGN})
+ string(REPLACE "thread" "thread_${Boost_THREADAPI}" _threadapi_libnames "${_orig_libnames}")
+ set(${_output} ${_threadapi_libnames} ${_orig_libnames} PARENT_SCOPE)
+endfunction()
+
+#
+# If a library is found, replace its cache entry with its REALPATH
+#
+function(_Boost_SWAP_WITH_REALPATH _library _docstring)
+ if(${_library})
+ get_filename_component(_boost_filepathreal ${${_library}} REALPATH)
+ unset(${_library} CACHE)
+ set(${_library} ${_boost_filepathreal} CACHE FILEPATH "${_docstring}")
+ endif()
+endfunction()
+
+function(_Boost_CHECK_SPELLING _var)
+ if(${_var})
+ string(TOUPPER ${_var} _var_UC)
+ message(FATAL_ERROR "ERROR: ${_var} is not the correct spelling. The proper spelling is ${_var_UC}.")
+ endif()
+endfunction()
+
+# Guesses Boost's compiler prefix used in built library names
+# Returns the guess by setting the variable pointed to by _ret
+function(_Boost_GUESS_COMPILER_PREFIX _ret)
+ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel"
+ OR "${CMAKE_CXX_COMPILER}" MATCHES "icl"
+ OR "${CMAKE_CXX_COMPILER}" MATCHES "icpc")
+ if(WIN32)
+ set (_boost_COMPILER "-iw")
+ else()
+ set (_boost_COMPILER "-il")
+ endif()
+ elseif (MSVC12)
+ set(_boost_COMPILER "-vc120")
+ elseif (MSVC11)
+ set(_boost_COMPILER "-vc110")
+ elseif (MSVC10)
+ set(_boost_COMPILER "-vc100")
+ elseif (MSVC90)
+ set(_boost_COMPILER "-vc90")
+ elseif (MSVC80)
+ set(_boost_COMPILER "-vc80")
+ elseif (MSVC71)
+ set(_boost_COMPILER "-vc71")
+ elseif (MSVC70) # Good luck!
+ set(_boost_COMPILER "-vc7") # yes, this is correct
+ elseif (MSVC60) # Good luck!
+ set(_boost_COMPILER "-vc6") # yes, this is correct
+ elseif (BORLAND)
+ set(_boost_COMPILER "-bcb")
+ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "SunPro")
+ set(_boost_COMPILER "-sw")
+ elseif (MINGW)
+ if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34)
+ set(_boost_COMPILER "-mgw") # no GCC version encoding prior to 1.34
+ else()
+ _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION)
+ set(_boost_COMPILER "-mgw${_boost_COMPILER_VERSION}")
+ endif()
+ elseif (UNIX)
+ if (CMAKE_COMPILER_IS_GNUCXX)
+ if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34)
+ set(_boost_COMPILER "-gcc") # no GCC version encoding prior to 1.34
+ else()
+ _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION)
+ # Determine which version of GCC we have.
+ if(APPLE)
+ if(Boost_MINOR_VERSION)
+ if(${Boost_MINOR_VERSION} GREATER 35)
+ # In Boost 1.36.0 and newer, the mangled compiler name used
+ # on Mac OS X/Darwin is "xgcc".
+ set(_boost_COMPILER "-xgcc${_boost_COMPILER_VERSION}")
+ else()
+ # In Boost <= 1.35.0, there is no mangled compiler name for
+ # the Mac OS X/Darwin version of GCC.
+ set(_boost_COMPILER "")
+ endif()
+ else()
+ # We don't know the Boost version, so assume it's
+ # pre-1.36.0.
+ set(_boost_COMPILER "")
+ endif()
+ else()
+ set(_boost_COMPILER "-gcc${_boost_COMPILER_VERSION}")
+ endif()
+ endif()
+ endif ()
+ else()
+ # TODO at least Boost_DEBUG here?
+ set(_boost_COMPILER "")
+ endif()
+ set(${_ret} ${_boost_COMPILER} PARENT_SCOPE)
+endfunction()
+
+#
+# End functions/macros
+#
+#-------------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------------
+# main.
+#-------------------------------------------------------------------------------
+
+if(NOT DEFINED Boost_USE_MULTITHREADED)
+ set(Boost_USE_MULTITHREADED TRUE)
+endif()
+
+# Check the version of Boost against the requested version.
+if(Boost_FIND_VERSION AND NOT Boost_FIND_VERSION_MINOR)
+ message(SEND_ERROR "When requesting a specific version of Boost, you must provide at least the major and minor version numbers, e.g., 1.34")
+endif()
+
+if(Boost_FIND_VERSION_EXACT)
+ # The version may appear in a directory with or without the patch
+ # level, even when the patch level is non-zero.
+ set(_boost_TEST_VERSIONS
+ "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}.${Boost_FIND_VERSION_PATCH}"
+ "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}")
+else()
+ # The user has not requested an exact version. Among known
+ # versions, find those that are acceptable to the user request.
+ set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS}
+ "1.56.0" "1.56" "1.55.0" "1.55" "1.54.0" "1.54"
+ "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51"
+ "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1"
+ "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" "1.43" "1.42.0" "1.42"
+ "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37"
+ "1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0"
+ "1.34" "1.33.1" "1.33.0" "1.33")
+ set(_boost_TEST_VERSIONS)
+ if(Boost_FIND_VERSION)
+ set(_Boost_FIND_VERSION_SHORT "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}")
+ # Select acceptable versions.
+ foreach(version ${_Boost_KNOWN_VERSIONS})
+ if(NOT "${version}" VERSION_LESS "${Boost_FIND_VERSION}")
+ # This version is high enough.
+ list(APPEND _boost_TEST_VERSIONS "${version}")
+ elseif("${version}.99" VERSION_EQUAL "${_Boost_FIND_VERSION_SHORT}.99")
+ # This version is a short-form for the requested version with
+ # the patch level dropped.
+ list(APPEND _boost_TEST_VERSIONS "${version}")
+ endif()
+ endforeach()
+ else()
+ # Any version is acceptable.
+ set(_boost_TEST_VERSIONS "${_Boost_KNOWN_VERSIONS}")
+ endif()
+endif()
+
+# The reason that we failed to find Boost. This will be set to a
+# user-friendly message when we fail to find some necessary piece of
+# Boost.
+set(Boost_ERROR_REASON)
+
+if(Boost_DEBUG)
+ # Output some of their choices
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}")
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "Boost_USE_MULTITHREADED = ${Boost_USE_MULTITHREADED}")
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "Boost_USE_STATIC_LIBS = ${Boost_USE_STATIC_LIBS}")
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "Boost_USE_STATIC_RUNTIME = ${Boost_USE_STATIC_RUNTIME}")
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "Boost_ADDITIONAL_VERSIONS = ${Boost_ADDITIONAL_VERSIONS}")
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "Boost_NO_SYSTEM_PATHS = ${Boost_NO_SYSTEM_PATHS}")
+endif()
+
+if(WIN32)
+ # In windows, automatic linking is performed, so you do not have
+ # to specify the libraries. If you are linking to a dynamic
+ # runtime, then you can choose to link to either a static or a
+ # dynamic Boost library, the default is to do a static link. You
+ # can alter this for a specific library "whatever" by defining
+ # BOOST_WHATEVER_DYN_LINK to force Boost library "whatever" to be
+ # linked dynamically. Alternatively you can force all Boost
+ # libraries to dynamic link by defining BOOST_ALL_DYN_LINK.
+
+ # This feature can be disabled for Boost library "whatever" by
+ # defining BOOST_WHATEVER_NO_LIB, or for all of Boost by defining
+ # BOOST_ALL_NO_LIB.
+
+ # If you want to observe which libraries are being linked against
+ # then defining BOOST_LIB_DIAGNOSTIC will cause the auto-linking
+ # code to emit a #pragma message each time a library is selected
+ # for linking.
+ set(Boost_LIB_DIAGNOSTIC_DEFINITIONS "-DBOOST_LIB_DIAGNOSTIC")
+endif()
+
+_Boost_CHECK_SPELLING(Boost_ROOT)
+_Boost_CHECK_SPELLING(Boost_LIBRARYDIR)
+_Boost_CHECK_SPELLING(Boost_INCLUDEDIR)
+
+# Collect environment variable inputs as hints. Do not consider changes.
+foreach(v BOOSTROOT BOOST_ROOT BOOST_INCLUDEDIR BOOST_LIBRARYDIR)
+ set(_env $ENV{${v}})
+ if(_env)
+ file(TO_CMAKE_PATH "${_env}" _ENV_${v})
+ else()
+ set(_ENV_${v} "")
+ endif()
+endforeach()
+if(NOT _ENV_BOOST_ROOT AND _ENV_BOOSTROOT)
+ set(_ENV_BOOST_ROOT "${_ENV_BOOSTROOT}")
+endif()
+
+# Collect inputs and cached results. Detect changes since the last run.
+if(NOT BOOST_ROOT AND BOOSTROOT)
+ set(BOOST_ROOT "${BOOSTROOT}")
+endif()
+set(_Boost_VARS_DIR
+ BOOST_ROOT
+ Boost_NO_SYSTEM_PATHS
+ )
+
+if(Boost_DEBUG)
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "Declared as CMake or Environmental Variables:")
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ " BOOST_ROOT = ${BOOST_ROOT}")
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ " BOOST_INCLUDEDIR = ${BOOST_INCLUDEDIR}")
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ " BOOST_LIBRARYDIR = ${BOOST_LIBRARYDIR}")
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}")
+endif()
+
+# ------------------------------------------------------------------------
+# Search for Boost include DIR
+# ------------------------------------------------------------------------
+
+set(_Boost_VARS_INC BOOST_INCLUDEDIR Boost_INCLUDE_DIR Boost_ADDITIONAL_VERSIONS)
+_Boost_CHANGE_DETECT(_Boost_CHANGE_INCDIR ${_Boost_VARS_DIR} ${_Boost_VARS_INC})
+# Clear Boost_INCLUDE_DIR if it did not change but other input affecting the
+# location did. We will find a new one based on the new inputs.
+if(_Boost_CHANGE_INCDIR AND NOT _Boost_INCLUDE_DIR_CHANGED)
+ unset(Boost_INCLUDE_DIR CACHE)
+endif()
+
+if(NOT Boost_INCLUDE_DIR)
+ set(_boost_INCLUDE_SEARCH_DIRS "")
+ if(BOOST_INCLUDEDIR)
+ list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_INCLUDEDIR})
+ elseif(_ENV_BOOST_INCLUDEDIR)
+ list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_INCLUDEDIR})
+ endif()
+
+ if( BOOST_ROOT )
+ list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_ROOT}/include ${BOOST_ROOT})
+ elseif( _ENV_BOOST_ROOT )
+ list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_ROOT}/include ${_ENV_BOOST_ROOT})
+ endif()
+
+ if( Boost_NO_SYSTEM_PATHS)
+ list(APPEND _boost_INCLUDE_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH)
+ else()
+ list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS
+ C:/boost/include
+ C:/boost
+ /sw/local/include
+ )
+ endif()
+
+ # Try to find Boost by stepping backwards through the Boost versions
+ # we know about.
+ # Build a list of path suffixes for each version.
+ set(_boost_PATH_SUFFIXES)
+ foreach(_boost_VER ${_boost_TEST_VERSIONS})
+ # Add in a path suffix, based on the required version, ideally
+ # we could read this from version.hpp, but for that to work we'd
+ # need to know the include dir already
+ set(_boost_BOOSTIFIED_VERSION)
+
+ # Transform 1.35 => 1_35 and 1.36.0 => 1_36_0
+ if(_boost_VER MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+")
+ string(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\1_\\2_\\3"
+ _boost_BOOSTIFIED_VERSION ${_boost_VER})
+ elseif(_boost_VER MATCHES "[0-9]+\\.[0-9]+")
+ string(REGEX REPLACE "([0-9]+)\\.([0-9]+)" "\\1_\\2"
+ _boost_BOOSTIFIED_VERSION ${_boost_VER})
+ endif()
+
+ list(APPEND _boost_PATH_SUFFIXES
+ "boost-${_boost_BOOSTIFIED_VERSION}"
+ "boost_${_boost_BOOSTIFIED_VERSION}"
+ "boost/boost-${_boost_BOOSTIFIED_VERSION}"
+ "boost/boost_${_boost_BOOSTIFIED_VERSION}"
+ )
+
+ endforeach()
+
+ if(Boost_DEBUG)
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "Include debugging info:")
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ " _boost_INCLUDE_SEARCH_DIRS = ${_boost_INCLUDE_SEARCH_DIRS}")
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ " _boost_PATH_SUFFIXES = ${_boost_PATH_SUFFIXES}")
+ endif()
+
+ # Look for a standard boost header file.
+ find_path(Boost_INCLUDE_DIR
+ NAMES boost/config.hpp
+ HINTS ${_boost_INCLUDE_SEARCH_DIRS}
+ PATH_SUFFIXES ${_boost_PATH_SUFFIXES}
+ )
+endif()
+
+# ------------------------------------------------------------------------
+# Extract version information from version.hpp
+# ------------------------------------------------------------------------
+
+# Set Boost_FOUND based only on header location and version.
+# It will be updated below for component libraries.
+if(Boost_INCLUDE_DIR)
+ if(Boost_DEBUG)
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "location of version.hpp: ${Boost_INCLUDE_DIR}/boost/version.hpp")
+ endif()
+
+ # Extract Boost_VERSION and Boost_LIB_VERSION from version.hpp
+ set(Boost_VERSION 0)
+ set(Boost_LIB_VERSION "")
+ file(STRINGS "${Boost_INCLUDE_DIR}/boost/version.hpp" _boost_VERSION_HPP_CONTENTS REGEX "#define BOOST_(LIB_)?VERSION ")
+ set(_Boost_VERSION_REGEX "([0-9]+)")
+ set(_Boost_LIB_VERSION_REGEX "\"([0-9_]+)\"")
+ foreach(v VERSION LIB_VERSION)
+ if("${_boost_VERSION_HPP_CONTENTS}" MATCHES ".*#define BOOST_${v} ${_Boost_${v}_REGEX}.*")
+ set(Boost_${v} "${CMAKE_MATCH_1}")
+ endif()
+ endforeach()
+ unset(_boost_VERSION_HPP_CONTENTS)
+
+ math(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000")
+ math(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000")
+ math(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100")
+
+ set(Boost_ERROR_REASON
+ "${Boost_ERROR_REASON}Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}\nBoost include path: ${Boost_INCLUDE_DIR}")
+ if(Boost_DEBUG)
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "version.hpp reveals boost "
+ "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}")
+ endif()
+
+ if(Boost_FIND_VERSION)
+ # Set Boost_FOUND based on requested version.
+ set(_Boost_VERSION "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}")
+ if("${_Boost_VERSION}" VERSION_LESS "${Boost_FIND_VERSION}")
+ set(Boost_FOUND 0)
+ set(_Boost_VERSION_AGE "old")
+ elseif(Boost_FIND_VERSION_EXACT AND
+ NOT "${_Boost_VERSION}" VERSION_EQUAL "${Boost_FIND_VERSION}")
+ set(Boost_FOUND 0)
+ set(_Boost_VERSION_AGE "new")
+ else()
+ set(Boost_FOUND 1)
+ endif()
+ if(NOT Boost_FOUND)
+ # State that we found a version of Boost that is too new or too old.
+ set(Boost_ERROR_REASON
+ "${Boost_ERROR_REASON}\nDetected version of Boost is too ${_Boost_VERSION_AGE}. Requested version was ${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}")
+ if (Boost_FIND_VERSION_PATCH)
+ set(Boost_ERROR_REASON
+ "${Boost_ERROR_REASON}.${Boost_FIND_VERSION_PATCH}")
+ endif ()
+ if (NOT Boost_FIND_VERSION_EXACT)
+ set(Boost_ERROR_REASON "${Boost_ERROR_REASON} (or newer)")
+ endif ()
+ set(Boost_ERROR_REASON "${Boost_ERROR_REASON}.")
+ endif ()
+ else()
+ # Caller will accept any Boost version.
+ set(Boost_FOUND 1)
+ endif()
+else()
+ set(Boost_FOUND 0)
+ set(Boost_ERROR_REASON
+ "${Boost_ERROR_REASON}Unable to find the Boost header files. Please set BOOST_ROOT to the root directory containing Boost or BOOST_INCLUDEDIR to the directory containing Boost's headers.")
+endif()
+
+# ------------------------------------------------------------------------
+# Suffix initialization and compiler suffix detection.
+# ------------------------------------------------------------------------
+
+set(_Boost_VARS_NAME
+ Boost_COMPILER
+ Boost_THREADAPI
+ Boost_USE_DEBUG_PYTHON
+ Boost_USE_MULTITHREADED
+ Boost_USE_STATIC_LIBS
+ Boost_USE_STATIC_RUNTIME
+ Boost_USE_STLPORT
+ Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS
+ )
+_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBNAME ${_Boost_VARS_NAME})
+
+# Setting some more suffixes for the library
+set(Boost_LIB_PREFIX "")
+if ( WIN32 AND Boost_USE_STATIC_LIBS AND NOT CYGWIN)
+ set(Boost_LIB_PREFIX "lib")
+endif()
+
+if (Boost_COMPILER)
+ set(_boost_COMPILER ${Boost_COMPILER})
+ if(Boost_DEBUG)
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "using user-specified Boost_COMPILER = ${_boost_COMPILER}")
+ endif()
+else()
+ # Attempt to guess the compiler suffix
+ # NOTE: this is not perfect yet, if you experience any issues
+ # please report them and use the Boost_COMPILER variable
+ # to work around the problems.
+ _Boost_GUESS_COMPILER_PREFIX(_boost_COMPILER)
+ if(Boost_DEBUG)
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "guessed _boost_COMPILER = ${_boost_COMPILER}")
+ endif()
+endif()
+
+set (_boost_MULTITHREADED "-mt")
+if( NOT Boost_USE_MULTITHREADED )
+ set (_boost_MULTITHREADED "")
+endif()
+if(Boost_DEBUG)
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "_boost_MULTITHREADED = ${_boost_MULTITHREADED}")
+endif()
+
+#======================
+# Systematically build up the Boost ABI tag
+# http://boost.org/doc/libs/1_41_0/more/getting_started/windows.html#library-naming
+set( _boost_RELEASE_ABI_TAG "-")
+set( _boost_DEBUG_ABI_TAG "-")
+# Key Use this library when:
+# s linking statically to the C++ standard library and
+# compiler runtime support libraries.
+if(Boost_USE_STATIC_RUNTIME)
+ set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}s")
+ set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}s")
+endif()
+# g using debug versions of the standard and runtime
+# support libraries
+if(WIN32)
+ if(MSVC OR "${CMAKE_CXX_COMPILER}" MATCHES "icl"
+ OR "${CMAKE_CXX_COMPILER}" MATCHES "icpc")
+ set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}g")
+ endif()
+endif()
+# y using special debug build of python
+if(Boost_USE_DEBUG_PYTHON)
+ set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}y")
+endif()
+# d using a debug version of your code
+set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}d")
+# p using the STLport standard library rather than the
+# default one supplied with your compiler
+if(Boost_USE_STLPORT)
+ set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}p")
+ set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}p")
+endif()
+# n using the STLport deprecated "native iostreams" feature
+if(Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS)
+ set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}n")
+ set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}n")
+endif()
+
+if(Boost_DEBUG)
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "_boost_RELEASE_ABI_TAG = ${_boost_RELEASE_ABI_TAG}")
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "_boost_DEBUG_ABI_TAG = ${_boost_DEBUG_ABI_TAG}")
+endif()
+
+# ------------------------------------------------------------------------
+# Begin finding boost libraries
+# ------------------------------------------------------------------------
+set(_Boost_VARS_LIB BOOST_LIBRARYDIR Boost_LIBRARY_DIR)
+_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBDIR ${_Boost_VARS_DIR} ${_Boost_VARS_LIB} Boost_INCLUDE_DIR)
+# Clear Boost_LIBRARY_DIR if it did not change but other input affecting the
+# location did. We will find a new one based on the new inputs.
+if(_Boost_CHANGE_LIBDIR AND NOT _Boost_LIBRARY_DIR_CHANGED)
+ unset(Boost_LIBRARY_DIR CACHE)
+endif()
+
+if(Boost_LIBRARY_DIR)
+ set(_boost_LIBRARY_SEARCH_DIRS ${Boost_LIBRARY_DIR} NO_DEFAULT_PATH)
+else()
+ set(_boost_LIBRARY_SEARCH_DIRS "")
+ if(BOOST_LIBRARYDIR)
+ list(APPEND _boost_LIBRARY_SEARCH_DIRS ${BOOST_LIBRARYDIR})
+ elseif(_ENV_BOOST_LIBRARYDIR)
+ list(APPEND _boost_LIBRARY_SEARCH_DIRS ${_ENV_BOOST_LIBRARYDIR})
+ endif()
+
+ if(BOOST_ROOT)
+ list(APPEND _boost_LIBRARY_SEARCH_DIRS ${BOOST_ROOT}/lib ${BOOST_ROOT}/stage/lib)
+ elseif(_ENV_BOOST_ROOT)
+ list(APPEND _boost_LIBRARY_SEARCH_DIRS ${_ENV_BOOST_ROOT}/lib ${_ENV_BOOST_ROOT}/stage/lib)
+ endif()
+
+ list(APPEND _boost_LIBRARY_SEARCH_DIRS
+ ${Boost_INCLUDE_DIR}/lib
+ ${Boost_INCLUDE_DIR}/../lib
+ ${Boost_INCLUDE_DIR}/stage/lib
+ )
+ if( Boost_NO_SYSTEM_PATHS )
+ list(APPEND _boost_LIBRARY_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH)
+ else()
+ list(APPEND _boost_LIBRARY_SEARCH_DIRS PATHS
+ C:/boost/lib
+ C:/boost
+ /sw/local/lib
+ )
+ endif()
+endif()
+
+if(Boost_DEBUG)
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "_boost_LIBRARY_SEARCH_DIRS = ${_boost_LIBRARY_SEARCH_DIRS}")
+endif()
+
+# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
+if( Boost_USE_STATIC_LIBS )
+ set( _boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ if(WIN32)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ else()
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
+ endif()
+endif()
+
+# We want to use the tag inline below without risking double dashes
+if(_boost_RELEASE_ABI_TAG)
+ if(${_boost_RELEASE_ABI_TAG} STREQUAL "-")
+ set(_boost_RELEASE_ABI_TAG "")
+ endif()
+endif()
+if(_boost_DEBUG_ABI_TAG)
+ if(${_boost_DEBUG_ABI_TAG} STREQUAL "-")
+ set(_boost_DEBUG_ABI_TAG "")
+ endif()
+endif()
+
+# The previous behavior of FindBoost when Boost_USE_STATIC_LIBS was enabled
+# on WIN32 was to:
+# 1. Search for static libs compiled against a SHARED C++ standard runtime library (use if found)
+# 2. Search for static libs compiled against a STATIC C++ standard runtime library (use if found)
+# We maintain this behavior since changing it could break people's builds.
+# To disable the ambiguous behavior, the user need only
+# set Boost_USE_STATIC_RUNTIME either ON or OFF.
+set(_boost_STATIC_RUNTIME_WORKAROUND false)
+if(WIN32 AND Boost_USE_STATIC_LIBS)
+ if(NOT DEFINED Boost_USE_STATIC_RUNTIME)
+ set(_boost_STATIC_RUNTIME_WORKAROUND true)
+ endif()
+endif()
+
+# On versions < 1.35, remove the System library from the considered list
+# since it wasn't added until 1.35.
+if(Boost_VERSION AND Boost_FIND_COMPONENTS)
+ if(Boost_VERSION LESS 103500)
+ list(REMOVE_ITEM Boost_FIND_COMPONENTS system)
+ endif()
+endif()
+
+# If the user changed any of our control inputs flush previous results.
+if(_Boost_CHANGE_LIBDIR OR _Boost_CHANGE_LIBNAME)
+ foreach(COMPONENT ${_Boost_COMPONENTS_SEARCHED})
+ string(TOUPPER ${COMPONENT} UPPERCOMPONENT)
+ foreach(c DEBUG RELEASE)
+ set(_var Boost_${UPPERCOMPONENT}_LIBRARY_${c})
+ unset(${_var} CACHE)
+ set(${_var} "${_var}-NOTFOUND")
+ endforeach()
+ endforeach()
+ set(_Boost_COMPONENTS_SEARCHED "")
+endif()
+
+foreach(COMPONENT ${Boost_FIND_COMPONENTS})
+ string(TOUPPER ${COMPONENT} UPPERCOMPONENT)
+
+ set( _boost_docstring_release "Boost ${COMPONENT} library (release)")
+ set( _boost_docstring_debug "Boost ${COMPONENT} library (debug)")
+
+ #
+ # Find RELEASE libraries
+ #
+ set(_boost_RELEASE_NAMES
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT} )
+ if(_boost_STATIC_RUNTIME_WORKAROUND)
+ set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}")
+ list(APPEND _boost_RELEASE_NAMES
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} )
+ endif()
+ if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread")
+ _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_RELEASE_NAMES ${_boost_RELEASE_NAMES})
+ endif()
+ if(Boost_DEBUG)
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "Searching for ${UPPERCOMPONENT}_LIBRARY_RELEASE: ${_boost_RELEASE_NAMES}")
+ endif()
+
+ # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing.
+ string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}")
+
+ _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE
+ NAMES ${_boost_RELEASE_NAMES}
+ HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp}
+ NAMES_PER_DIR
+ DOC "${_boost_docstring_release}"
+ )
+
+ #
+ # Find DEBUG libraries
+ #
+ set(_boost_DEBUG_NAMES
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT} )
+ if(_boost_STATIC_RUNTIME_WORKAROUND)
+ set(_boost_DEBUG_STATIC_ABI_TAG "-s${_boost_DEBUG_ABI_TAG}")
+ list(APPEND _boost_DEBUG_NAMES
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION}
+ ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} )
+ endif()
+ if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread")
+ _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_DEBUG_NAMES ${_boost_DEBUG_NAMES})
+ endif()
+ if(Boost_DEBUG)
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "Searching for ${UPPERCOMPONENT}_LIBRARY_DEBUG: ${_boost_DEBUG_NAMES}")
+ endif()
+
+ # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing.
+ string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}")
+
+ _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG
+ NAMES ${_boost_DEBUG_NAMES}
+ HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp}
+ NAMES_PER_DIR
+ DOC "${_boost_docstring_debug}"
+ )
+
+ if(Boost_REALPATH)
+ _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE "${_boost_docstring_release}")
+ _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG "${_boost_docstring_debug}" )
+ endif()
+
+ _Boost_ADJUST_LIB_VARS(${UPPERCOMPONENT})
+
+endforeach()
+
+# Restore the original find library ordering
+if( Boost_USE_STATIC_LIBS )
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ${_boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
+endif()
+
+# ------------------------------------------------------------------------
+# End finding boost libraries
+# ------------------------------------------------------------------------
+
+set(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR})
+set(Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR})
+
+# The above setting of Boost_FOUND was based only on the header files.
+# Update it for the requested component libraries.
+if(Boost_FOUND)
+ # The headers were found. Check for requested component libs.
+ set(_boost_CHECKED_COMPONENT FALSE)
+ set(_Boost_MISSING_COMPONENTS "")
+ foreach(COMPONENT ${Boost_FIND_COMPONENTS})
+ string(TOUPPER ${COMPONENT} COMPONENT)
+ set(_boost_CHECKED_COMPONENT TRUE)
+ if(NOT Boost_${COMPONENT}_FOUND)
+ string(TOLOWER ${COMPONENT} COMPONENT)
+ list(APPEND _Boost_MISSING_COMPONENTS ${COMPONENT})
+ endif()
+ endforeach()
+
+ if(Boost_DEBUG)
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] Boost_FOUND = ${Boost_FOUND}")
+ endif()
+
+ if (_Boost_MISSING_COMPONENTS)
+ set(Boost_FOUND 0)
+ # We were unable to find some libraries, so generate a sensible
+ # error message that lists the libraries we were unable to find.
+ set(Boost_ERROR_REASON
+ "${Boost_ERROR_REASON}\nCould not find the following")
+ if(Boost_USE_STATIC_LIBS)
+ set(Boost_ERROR_REASON "${Boost_ERROR_REASON} static")
+ endif()
+ set(Boost_ERROR_REASON
+ "${Boost_ERROR_REASON} Boost libraries:\n")
+ foreach(COMPONENT ${_Boost_MISSING_COMPONENTS})
+ set(Boost_ERROR_REASON
+ "${Boost_ERROR_REASON} boost_${COMPONENT}\n")
+ endforeach()
+
+ list(LENGTH Boost_FIND_COMPONENTS Boost_NUM_COMPONENTS_WANTED)
+ list(LENGTH _Boost_MISSING_COMPONENTS Boost_NUM_MISSING_COMPONENTS)
+ if (${Boost_NUM_COMPONENTS_WANTED} EQUAL ${Boost_NUM_MISSING_COMPONENTS})
+ set(Boost_ERROR_REASON
+ "${Boost_ERROR_REASON}No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.")
+ else ()
+ set(Boost_ERROR_REASON
+ "${Boost_ERROR_REASON}Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.")
+ endif ()
+ endif ()
+
+ if( NOT Boost_LIBRARY_DIRS AND NOT _boost_CHECKED_COMPONENT )
+ # Compatibility Code for backwards compatibility with CMake
+ # 2.4's FindBoost module.
+
+ # Look for the boost library path.
+ # Note that the user may not have installed any libraries
+ # so it is quite possible the Boost_LIBRARY_DIRS may not exist.
+ set(_boost_LIB_DIR ${Boost_INCLUDE_DIR})
+
+ if("${_boost_LIB_DIR}" MATCHES "boost-[0-9]+")
+ get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH)
+ endif()
+
+ if("${_boost_LIB_DIR}" MATCHES "/include$")
+ # Strip off the trailing "/include" in the path.
+ get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH)
+ endif()
+
+ if(EXISTS "${_boost_LIB_DIR}/lib")
+ set(_boost_LIB_DIR ${_boost_LIB_DIR}/lib)
+ else()
+ if(EXISTS "${_boost_LIB_DIR}/stage/lib")
+ set(_boost_LIB_DIR ${_boost_LIB_DIR}/stage/lib)
+ else()
+ set(_boost_LIB_DIR "")
+ endif()
+ endif()
+
+ if(_boost_LIB_DIR AND EXISTS "${_boost_LIB_DIR}")
+ set(Boost_LIBRARY_DIRS ${_boost_LIB_DIR})
+ endif()
+
+ endif()
+else()
+ # Boost headers were not found so no components were found.
+ foreach(COMPONENT ${Boost_FIND_COMPONENTS})
+ string(TOUPPER ${COMPONENT} UPPERCOMPONENT)
+ set(Boost_${UPPERCOMPONENT}_FOUND 0)
+ endforeach()
+endif()
+
+# ------------------------------------------------------------------------
+# Notification to end user about what was found
+# ------------------------------------------------------------------------
+
+set(Boost_LIBRARIES "")
+if(Boost_FOUND)
+ if(NOT Boost_FIND_QUIETLY)
+ message(STATUS "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}")
+ if(Boost_FIND_COMPONENTS)
+ message(STATUS "Found the following Boost libraries:")
+ endif()
+ endif()
+ foreach( COMPONENT ${Boost_FIND_COMPONENTS} )
+ string( TOUPPER ${COMPONENT} UPPERCOMPONENT )
+ if( Boost_${UPPERCOMPONENT}_FOUND )
+ if(NOT Boost_FIND_QUIETLY)
+ message (STATUS " ${COMPONENT}")
+ endif()
+ list(APPEND Boost_LIBRARIES ${Boost_${UPPERCOMPONENT}_LIBRARY})
+ endif()
+ endforeach()
+else()
+ if(Boost_FIND_REQUIRED)
+ message(SEND_ERROR "Unable to find the requested Boost libraries.\n${Boost_ERROR_REASON}")
+ else()
+ if(NOT Boost_FIND_QUIETLY)
+ # we opt not to automatically output Boost_ERROR_REASON here as
+ # it could be quite lengthy and somewhat imposing in its requests
+ # Since Boost is not always a required dependency we'll leave this
+ # up to the end-user.
+ if(Boost_DEBUG OR Boost_DETAILED_FAILURE_MSG)
+ message(STATUS "Could NOT find Boost\n${Boost_ERROR_REASON}")
+ else()
+ message(STATUS "Could NOT find Boost")
+ endif()
+ endif()
+ endif()
+endif()
+
+# Configure display of cache entries in GUI.
+foreach(v BOOSTROOT BOOST_ROOT ${_Boost_VARS_INC} ${_Boost_VARS_LIB})
+ get_property(_type CACHE ${v} PROPERTY TYPE)
+ if(_type)
+ set_property(CACHE ${v} PROPERTY ADVANCED 1)
+ if("x${_type}" STREQUAL "xUNINITIALIZED")
+ if("x${v}" STREQUAL "xBoost_ADDITIONAL_VERSIONS")
+ set_property(CACHE ${v} PROPERTY TYPE STRING)
+ else()
+ set_property(CACHE ${v} PROPERTY TYPE PATH)
+ endif()
+ endif()
+ endif()
+endforeach()
+
+# Record last used values of input variables so we can
+# detect on the next run if the user changed them.
+foreach(v
+ ${_Boost_VARS_INC} ${_Boost_VARS_LIB}
+ ${_Boost_VARS_DIR} ${_Boost_VARS_NAME}
+ )
+ if(DEFINED ${v})
+ set(_${v}_LAST "${${v}}" CACHE INTERNAL "Last used ${v} value.")
+ else()
+ unset(_${v}_LAST CACHE)
+ endif()
+endforeach()
+
+# Maintain a persistent list of components requested anywhere since
+# the last flush.
+set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}")
+list(APPEND _Boost_COMPONENTS_SEARCHED ${Boost_FIND_COMPONENTS})
+list(REMOVE_DUPLICATES _Boost_COMPONENTS_SEARCHED)
+list(SORT _Boost_COMPONENTS_SEARCHED)
+set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}"
+ CACHE INTERNAL "Components requested for this build tree.")
diff --git a/CMake/FindGSasl.cmake b/CMake/FindGSasl.cmake
new file mode 100644
index 0000000..19ca7c3
--- /dev/null
+++ b/CMake/FindGSasl.cmake
@@ -0,0 +1,26 @@
+# - Try to find the GNU sasl library (gsasl)
+#
+# Once done this will define
+#
+# GSASL_FOUND - System has gnutls
+# GSASL_INCLUDE_DIR - The gnutls include directory
+# GSASL_LIBRARIES - The libraries needed to use gnutls
+# GSASL_DEFINITIONS - Compiler switches required for using gnutls
+
+
+IF (GSASL_INCLUDE_DIR AND GSASL_LIBRARIES)
+ # in cache already
+ SET(GSasl_FIND_QUIETLY TRUE)
+ENDIF (GSASL_INCLUDE_DIR AND GSASL_LIBRARIES)
+
+FIND_PATH(GSASL_INCLUDE_DIR gsasl.h)
+
+FIND_LIBRARY(GSASL_LIBRARIES gsasl)
+
+INCLUDE(FindPackageHandleStandardArgs)
+
+# handle the QUIETLY and REQUIRED arguments and set GSASL_FOUND to TRUE if
+# all listed variables are TRUE
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GSASL DEFAULT_MSG GSASL_LIBRARIES GSASL_INCLUDE_DIR)
+
+MARK_AS_ADVANCED(GSASL_INCLUDE_DIR GSASL_LIBRARIES)
\ No newline at end of file
diff --git a/CMake/FindGoogleTest.cmake b/CMake/FindGoogleTest.cmake
new file mode 100644
index 0000000..edfb020
--- /dev/null
+++ b/CMake/FindGoogleTest.cmake
@@ -0,0 +1,73 @@
+include(CheckCXXSourceRuns)
+
+find_path(GTest_INCLUDE_DIR gtest/gtest.h
+ NO_DEFAULT_PATH
+ PATHS
+ "/opt/dependency/package/include"
+ "${PROJECT_SOURCE_DIR}/../thirdparty/googletest/googletest/include"
+ "/usr/local/include"
+ "/usr/include")
+
+find_path(GMock_INCLUDE_DIR gmock/gmock.h
+ NO_DEFAULT_PATH
+ PATHS
+ "/opt/dependency/package/include"
+ "${PROJECT_SOURCE_DIR}/../thirdparty/googletest/googlemock/include"
+ "/usr/local/include"
+ "/usr/include")
+
+find_library(Gtest_LIBRARY
+ NAMES libgtest.a
+ HINTS
+ "/opt/dependency/package/lib"
+ "${PROJECT_SOURCE_DIR}/../thirdparty/googletest/build/googlemock/gtest"
+ "/usr/local/lib"
+ "/usr/lib")
+
+find_library(Gmock_LIBRARY
+ NAMES libgmock.a
+ HINTS
+ "/opt/dependency/package/lib"
+ "${PROJECT_SOURCE_DIR}/../thirdparty/googletest/build/googlemock"
+ "/usr/local/lib"
+ "/usr/lib")
+
+message(STATUS "Find GoogleTest include path: ${GTest_INCLUDE_DIR}")
+message(STATUS "Find GoogleMock include path: ${GMock_INCLUDE_DIR}")
+message(STATUS "Find Gtest library path: ${Gtest_LIBRARY}")
+message(STATUS "Find Gmock library path: ${Gmock_LIBRARY}")
+
+set(CMAKE_REQUIRED_INCLUDES ${GTest_INCLUDE_DIR} ${GMock_INCLUDE_DIR})
+set(CMAKE_REQUIRED_LIBRARIES ${Gtest_LIBRARY} ${Gmock_LIBRARY})
+set(CMAKE_REQUIRED_FLAGS "-lpthread")
+IF(OS_LINUX)
+ SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -lc++")
+ENDIF(OS_LINUX)
+
+check_cxx_source_runs("
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+int main(int argc, char *argv[])
+{
+ double pi = 3.14;
+ EXPECT_EQ(pi, 3.14);
+ return 0;
+}
+" GoogleTest_CHECK_FINE)
+message(STATUS "GoogleTest check: ${GoogleTest_CHECK_FINE}")
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(
+ GoogleTest
+ REQUIRED_VARS
+ GTest_INCLUDE_DIR
+ GMock_INCLUDE_DIR
+ Gtest_LIBRARY
+ Gmock_LIBRARY
+ GoogleTest_CHECK_FINE)
+
+set(GoogleTest_INCLUDE_DIR ${GTest_INCLUDE_DIR} ${GMock_INCLUDE_DIR})
+set(GoogleTest_LIBRARIES ${Gtest_LIBRARY} ${Gmock_LIBRARY})
+mark_as_advanced(
+ GoogleTest_INCLUDE_DIR
+ GoogleTest_LIBRARIES)
diff --git a/CMake/FindKERBEROS.cmake b/CMake/FindKERBEROS.cmake
new file mode 100644
index 0000000..5fc5823
--- /dev/null
+++ b/CMake/FindKERBEROS.cmake
@@ -0,0 +1,23 @@
+# - Find kerberos
+# Find the native KERBEROS includes and library
+#
+# KERBEROS_INCLUDE_DIRS - where to find krb5.h, etc.
+# KERBEROS_LIBRARIES - List of libraries when using krb5.
+# KERBEROS_FOUND - True if krb5 found.
+
+IF (KERBEROS_INCLUDE_DIRS)
+ # Already in cache, be silent
+ SET(KERBEROS_FIND_QUIETLY TRUE)
+ENDIF (KERBEROS_INCLUDE_DIRS)
+
+FIND_PATH(KERBEROS_INCLUDE_DIRS krb5.h)
+
+SET(KERBEROS_NAMES krb5 k5crypto com_err)
+FIND_LIBRARY(KERBEROS_LIBRARIES NAMES ${KERBEROS_NAMES})
+
+# handle the QUIETLY and REQUIRED arguments and set KERBEROS_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(KERBEROS DEFAULT_MSG KERBEROS_LIBRARIES KERBEROS_INCLUDE_DIRS)
+
+MARK_AS_ADVANCED(KERBEROS_LIBRARIES KERBEROS_INCLUDE_DIRS)
diff --git a/CMake/FindLibUUID.cmake b/CMake/FindLibUUID.cmake
new file mode 100644
index 0000000..ac6e726
--- /dev/null
+++ b/CMake/FindLibUUID.cmake
@@ -0,0 +1,23 @@
+# - Find libuuid
+# Find the native LIBUUID includes and library
+#
+# LIBUUID_INCLUDE_DIRS - where to find uuid/uuid.h, etc.
+# LIBUUID_LIBRARIES - List of libraries when using uuid.
+# LIBUUID_FOUND - True if uuid found.
+
+IF (LIBUUID_INCLUDE_DIRS)
+ # Already in cache, be silent
+ SET(LIBUUID_FIND_QUIETLY TRUE)
+ENDIF (LIBUUID_INCLUDE_DIRS)
+
+FIND_PATH(LIBUUID_INCLUDE_DIRS uuid/uuid.h)
+
+SET(LIBUUID_NAMES uuid)
+FIND_LIBRARY(LIBUUID_LIBRARIES NAMES ${LIBUUID_NAMES})
+
+# handle the QUIETLY and REQUIRED arguments and set LIBUUID_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUUID DEFAULT_MSG LIBUUID_LIBRARIES LIBUUID_INCLUDE_DIRS)
+
+MARK_AS_ADVANCED(LIBUUID_LIBRARIES LIBUUID_INCLUDE_DIRS)
diff --git a/CMake/Functions.cmake b/CMake/Functions.cmake
new file mode 100644
index 0000000..a771b60
--- /dev/null
+++ b/CMake/Functions.cmake
@@ -0,0 +1,46 @@
+FUNCTION(AUTO_SOURCES RETURN_VALUE PATTERN SOURCE_SUBDIRS)
+
+ IF ("${SOURCE_SUBDIRS}" STREQUAL "RECURSE")
+ SET(PATH ".")
+ IF (${ARGC} EQUAL 4)
+ LIST(GET ARGV 3 PATH)
+ ENDIF ()
+ ENDIF()
+
+ IF ("${SOURCE_SUBDIRS}" STREQUAL "RECURSE")
+ UNSET(${RETURN_VALUE})
+ FILE(GLOB SUBDIR_FILES "${PATH}/${PATTERN}")
+ LIST(APPEND ${RETURN_VALUE} ${SUBDIR_FILES})
+
+ FILE(GLOB SUBDIRS RELATIVE ${PATH} ${PATH}/*)
+
+ FOREACH(DIR ${SUBDIRS})
+ IF (IS_DIRECTORY ${PATH}/${DIR})
+ IF (NOT "${DIR}" STREQUAL "CMAKEFILES")
+ FILE(GLOB_RECURSE SUBDIR_FILES "${PATH}/${DIR}/${PATTERN}")
+ LIST(APPEND ${RETURN_VALUE} ${SUBDIR_FILES})
+ ENDIF()
+ ENDIF()
+ ENDFOREACH()
+ ELSE ()
+ FILE(GLOB ${RETURN_VALUE} "${PATTERN}")
+
+ FOREACH (PATH ${SOURCE_SUBDIRS})
+ FILE(GLOB SUBDIR_FILES "${PATH}/${PATTERN}")
+ LIST(APPEND ${RETURN_VALUE} ${SUBDIR_FILES})
+ ENDFOREACH(PATH ${SOURCE_SUBDIRS})
+ ENDIF ()
+
+ IF (${FILTER_OUT})
+ LIST(REMOVE_ITEM ${RETURN_VALUE} ${FILTER_OUT})
+ ENDIF()
+
+ SET(${RETURN_VALUE} ${${RETURN_VALUE}} PARENT_SCOPE)
+ENDFUNCTION(AUTO_SOURCES)
+
+FUNCTION(CONTAINS_STRING FILE SEARCH RETURN_VALUE)
+ FILE(STRINGS ${FILE} FILE_CONTENTS REGEX ".*${SEARCH}.*")
+ IF (FILE_CONTENTS)
+ SET(${RETURN_VALUE} TRUE PARENT_SCOPE)
+ ENDIF()
+ENDFUNCTION(CONTAINS_STRING)
diff --git a/CMake/Options.cmake b/CMake/Options.cmake
new file mode 100644
index 0000000..8141cab
--- /dev/null
+++ b/CMake/Options.cmake
@@ -0,0 +1,169 @@
+OPTION(ENABLE_COVERAGE "enable code coverage" OFF)
+OPTION(ENABLE_DEBUG "enable debug build" OFF)
+OPTION(ENABLE_SSE "enable SSE4.2 buildin function" ON)
+OPTION(ENABLE_FRAME_POINTER "enable frame pointer on 64bit system with flag -fno-omit-frame-pointer, on 32bit system, it is always enabled" ON)
+OPTION(ENABLE_LIBCPP "using libc++ instead of libstdc++, only valid for clang compiler" OFF)
+OPTION(ENABLE_BOOST "using boost instead of native compiler c++0x support" OFF)
+
+INCLUDE (CheckFunctionExists)
+CHECK_FUNCTION_EXISTS(dladdr HAVE_DLADDR)
+CHECK_FUNCTION_EXISTS(nanosleep HAVE_NANOSLEEP)
+
+IF(ENABLE_DEBUG STREQUAL ON)
+ SET(CMAKE_BUILD_TYPE Debug CACHE
+ STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
+ SET(CMAKE_CXX_FLAGS_DEBUG "-g -O0" CACHE STRING "compiler flags for debug" FORCE)
+ SET(CMAKE_C_FLAGS_DEBUG "-g -O0" CACHE STRING "compiler flags for debug" FORCE)
+ELSE(ENABLE_DEBUG STREQUAL ON)
+ SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE
+ STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
+ENDIF(ENABLE_DEBUG STREQUAL ON)
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing")
+
+IF(ENABLE_COVERAGE STREQUAL ON)
+ INCLUDE(CodeCoverage)
+ENDIF(ENABLE_COVERAGE STREQUAL ON)
+
+IF(ENABLE_FRAME_POINTER STREQUAL ON)
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer")
+ENDIF(ENABLE_FRAME_POINTER STREQUAL ON)
+
+IF(ENABLE_SSE STREQUAL ON)
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.2")
+ENDIF(ENABLE_SSE STREQUAL ON)
+
+IF(NOT TEST_HDFS_PREFIX)
+SET(TEST_HDFS_PREFIX "./" CACHE STRING "default directory prefix used for test." FORCE)
+ENDIF(NOT TEST_HDFS_PREFIX)
+
+ADD_DEFINITIONS(-DTEST_HDFS_PREFIX="${TEST_HDFS_PREFIX}")
+ADD_DEFINITIONS(-D__STDC_FORMAT_MACROS)
+ADD_DEFINITIONS(-D_GNU_SOURCE)
+
+IF(OS_MACOSX AND CMAKE_COMPILER_IS_GNUCXX)
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-bind_at_load")
+ENDIF(OS_MACOSX AND CMAKE_COMPILER_IS_GNUCXX)
+
+IF(OS_LINUX)
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--export-dynamic")
+ENDIF(OS_LINUX)
+
+SET(BOOST_ROOT ${CMAKE_PREFIX_PATH})
+IF(ENABLE_BOOST STREQUAL ON)
+ MESSAGE(STATUS "using boost instead of native compiler c++0x support.")
+ FIND_PACKAGE(Boost 1.50 REQUIRED)
+ SET(NEED_BOOST true CACHE INTERNAL "boost is required")
+ELSE(ENABLE_BOOST STREQUAL ON)
+ SET(NEED_BOOST false CACHE INTERNAL "boost is required")
+ENDIF(ENABLE_BOOST STREQUAL ON)
+
+IF(CMAKE_COMPILER_IS_GNUCXX)
+ IF(ENABLE_LIBCPP STREQUAL ON)
+ MESSAGE(FATAL_ERROR "Unsupport using GCC compiler with libc++")
+ ENDIF(ENABLE_LIBCPP STREQUAL ON)
+
+ IF((GCC_COMPILER_VERSION_MAJOR EQUAL 4) AND (GCC_COMPILER_VERSION_MINOR EQUAL 4) AND OS_MACOSX)
+ SET(NEED_GCCEH true CACHE INTERNAL "Explicitly link with gcc_eh")
+ MESSAGE(STATUS "link with -lgcc_eh for TLS")
+ ENDIF((GCC_COMPILER_VERSION_MAJOR EQUAL 4) AND (GCC_COMPILER_VERSION_MINOR EQUAL 4) AND OS_MACOSX)
+
+ IF((GCC_COMPILER_VERSION_MAJOR LESS 4) OR ((GCC_COMPILER_VERSION_MAJOR EQUAL 4) AND (GCC_COMPILER_VERSION_MINOR LESS 4)))
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
+ IF(NOT ENABLE_BOOST STREQUAL ON)
+ MESSAGE(STATUS "gcc version is older than 4.6.0, boost is required.")
+ FIND_PACKAGE(Boost 1.50 REQUIRED)
+ SET(NEED_BOOST true CACHE INTERNAL "boost is required")
+ ENDIF(NOT ENABLE_BOOST STREQUAL ON)
+ ELSEIF((GCC_COMPILER_VERSION_MAJOR EQUAL 4) AND (GCC_COMPILER_VERSION_MINOR LESS 7))
+ IF(NOT ENABLE_BOOST STREQUAL ON)
+ MESSAGE(STATUS "gcc version is older than 4.6.0, boost is required.")
+ FIND_PACKAGE(Boost 1.50 REQUIRED)
+ SET(NEED_BOOST true CACHE INTERNAL "boost is required")
+ ENDIF(NOT ENABLE_BOOST STREQUAL ON)
+ MESSAGE(STATUS "adding c++0x support for gcc compiler")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+ ELSE((GCC_COMPILER_VERSION_MAJOR LESS 4) OR ((GCC_COMPILER_VERSION_MAJOR EQUAL 4) AND (GCC_COMPILER_VERSION_MINOR LESS 4)))
+ MESSAGE(STATUS "adding c++0x support for gcc compiler")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+ ENDIF((GCC_COMPILER_VERSION_MAJOR LESS 4) OR ((GCC_COMPILER_VERSION_MAJOR EQUAL 4) AND (GCC_COMPILER_VERSION_MINOR LESS 4)))
+
+ IF(NEED_BOOST)
+ IF((Boost_MAJOR_VERSION LESS 1) OR ((Boost_MAJOR_VERSION EQUAL 1) AND (Boost_MINOR_VERSION LESS 50)))
+ MESSAGE(FATAL_ERROR "boost 1.50+ is required")
+ ENDIF()
+ ELSE(NEED_BOOST)
+ IF(HAVE_NANOSLEEP)
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GLIBCXX_USE_NANOSLEEP")
+ ELSE(HAVE_NANOSLEEP)
+ MESSAGE(FATAL_ERROR "nanosleep() is required")
+ ENDIF(HAVE_NANOSLEEP)
+ ENDIF(NEED_BOOST)
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
+ELSEIF(CMAKE_COMPILER_IS_CLANG)
+ MESSAGE(STATUS "adding c++0x support for clang compiler")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+ SET(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++0x")
+ IF(ENABLE_LIBCPP STREQUAL ON)
+ MESSAGE(STATUS "using libc++ instead of libstdc++")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
+ SET(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
+ ENDIF(ENABLE_LIBCPP STREQUAL ON)
+ENDIF(CMAKE_COMPILER_IS_GNUCXX)
+
+TRY_COMPILE(STRERROR_R_RETURN_INT
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/CMake/CMakeTestCompileStrerror.cpp
+ CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'"
+ OUTPUT_VARIABLE OUTPUT)
+
+MESSAGE(STATUS "Checking whether strerror_r returns an int")
+
+IF(STRERROR_R_RETURN_INT)
+ MESSAGE(STATUS "Checking whether strerror_r returns an int -- yes")
+ELSE(STRERROR_R_RETURN_INT)
+ MESSAGE(STATUS "Checking whether strerror_r returns an int -- no")
+ENDIF(STRERROR_R_RETURN_INT)
+
+TRY_COMPILE(HAVE_STEADY_CLOCK
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/CMake/CMakeTestCompileSteadyClock.cpp
+ CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'"
+ OUTPUT_VARIABLE OUTPUT)
+
+TRY_COMPILE(HAVE_NESTED_EXCEPTION
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/CMake/CMakeTestCompileNestedException.cpp
+ CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'"
+ OUTPUT_VARIABLE OUTPUT)
+
+FILE(WRITE ${CMAKE_BINARY_DIR}/test.cpp "#include <boost/chrono.hpp>")
+TRY_COMPILE(HAVE_BOOST_CHRONO
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/test.cpp
+ CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'"
+ -DINCLUDE_DIRECTORIES=${Boost_INCLUDE_DIR}
+ OUTPUT_VARIABLE OUTPUT)
+
+FILE(WRITE ${CMAKE_BINARY_DIR}/test.cpp "#include <chrono>")
+TRY_COMPILE(HAVE_STD_CHRONO
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/test.cpp
+ CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'"
+ OUTPUT_VARIABLE OUTPUT)
+
+FILE(WRITE ${CMAKE_BINARY_DIR}/test.cpp "#include <boost/atomic.hpp>")
+TRY_COMPILE(HAVE_BOOST_ATOMIC
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/test.cpp
+ CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'"
+ -DINCLUDE_DIRECTORIES=${Boost_INCLUDE_DIR}
+ OUTPUT_VARIABLE OUTPUT)
+
+FILE(WRITE ${CMAKE_BINARY_DIR}/test.cpp "#include <atomic>")
+TRY_COMPILE(HAVE_STD_ATOMIC
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/test.cpp
+ CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'"
+ OUTPUT_VARIABLE OUTPUT)
diff --git a/CMake/Platform.cmake b/CMake/Platform.cmake
new file mode 100644
index 0000000..ea00fa3
--- /dev/null
+++ b/CMake/Platform.cmake
@@ -0,0 +1,33 @@
+IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ SET(OS_LINUX true CACHE INTERNAL "Linux operating system")
+ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ SET(OS_MACOSX true CACHE INTERNAL "Mac Darwin operating system")
+ELSE(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ MESSAGE(FATAL_ERROR "Unsupported OS: \"${CMAKE_SYSTEM_NAME}\"")
+ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+
+IF(CMAKE_COMPILER_IS_GNUCXX)
+ EXECUTE_PROCESS(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_COMPILER_VERSION)
+
+ IF (NOT GCC_COMPILER_VERSION)
+ MESSAGE(FATAL_ERROR "Cannot get gcc version")
+ ENDIF (NOT GCC_COMPILER_VERSION)
+
+ STRING(REGEX MATCHALL "[0-9]+" GCC_COMPILER_VERSION ${GCC_COMPILER_VERSION})
+
+ LIST(GET GCC_COMPILER_VERSION 0 GCC_COMPILER_VERSION_MAJOR)
+ LIST(GET GCC_COMPILER_VERSION 1 GCC_COMPILER_VERSION_MINOR)
+
+ SET(GCC_COMPILER_VERSION_MAJOR ${GCC_COMPILER_VERSION_MAJOR} CACHE INTERNAL "gcc major version")
+ SET(GCC_COMPILER_VERSION_MINOR ${GCC_COMPILER_VERSION_MINOR} CACHE INTERNAL "gcc minor version")
+
+ MESSAGE(STATUS "checking compiler: GCC (${GCC_COMPILER_VERSION_MAJOR}.${GCC_COMPILER_VERSION_MINOR}.${GCC_COMPILER_VERSION_PATCH})")
+ELSE(CMAKE_COMPILER_IS_GNUCXX)
+ EXECUTE_PROCESS(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_VARIABLE COMPILER_OUTPUT)
+ IF(COMPILER_OUTPUT MATCHES "clang")
+ SET(CMAKE_COMPILER_IS_CLANG true CACHE INTERNAL "using clang as compiler")
+ MESSAGE(STATUS "checking compiler: CLANG")
+ ELSE(COMPILER_OUTPUT MATCHES "clang")
+ MESSAGE(FATAL_ERROR "Unsupported compiler: \"${CMAKE_CXX_COMPILER}\"")
+ ENDIF(COMPILER_OUTPUT MATCHES "clang")
+ENDIF(CMAKE_COMPILER_IS_GNUCXX)
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..f49e68d
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,65 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+PROJECT(libhdfs3)
+
+SET(CMAKE_VERBOSE_MAKEFILE ON CACHE STRING "Verbose build." FORCE)
+
+IF(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
+ MESSAGE(FATAL_ERROR "cannot build the project in the source directory! Out-of-source build is enforced!")
+ENDIF()
+
+SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
+SET(DOXYFILE_PATH ${CMAKE_SOURCE_DIR}/docs)
+
+INCLUDE(Platform)
+INCLUDE(Functions)
+INCLUDE(Options)
+
+
+SET(CMAKE_PREFIX_PATH "/opt/dependency/package" "/opt/dependency/tools")
+
+FIND_PACKAGE(LibXml2 REQUIRED)
+FIND_PACKAGE(Protobuf REQUIRED)
+FIND_PACKAGE(KERBEROS REQUIRED)
+FIND_PACKAGE(GSasl REQUIRED)
+FIND_PACKAGE(GoogleTest REQUIRED)
+INCLUDE_DIRECTORIES(${GoogleTest_INCLUDE_DIR})
+LINK_LIBRARIES(${GoogleTest_LIBRARIES})
+
+IF(OS_LINUX)
+ FIND_PACKAGE(LibUUID REQUIRED)
+ENDIF(OS_LINUX)
+
+ADD_SUBDIRECTORY(mock)
+ADD_SUBDIRECTORY(src)
+ADD_SUBDIRECTORY(test)
+
+CONFIGURE_FILE(src/libhdfs3.pc.in ${CMAKE_SOURCE_DIR}/src/libhdfs3.pc @ONLY)
+CONFIGURE_FILE(debian/changelog.in ${CMAKE_SOURCE_DIR}/debian/changelog @ONLY)
+
+ADD_CUSTOM_TARGET(debian-package
+ COMMAND dpkg-buildpackage -us -uc -b
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMENT "Create debian package..."
+)
+
+ADD_CUSTOM_TARGET(rpm-package
+ COMMAND rpmbuild -bb --define "_topdir ${CMAKE_SOURCE_DIR}/rpms" --define "version ${libhdfs3_VERSION_STRING}" ${CMAKE_SOURCE_DIR}/rpms/libhdfs3.spec
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMENT "Create rpm package..."
+)
+
+ADD_CUSTOM_TARGET(doc
+ COMMAND doxygen ${CMAKE_BINARY_DIR}/src/doxyfile
+ WORKING_DIRECTORY ${DOXYFILE_PATH}
+ COMMENT "Generate documents..."
+)
+
+ADD_CUSTOM_TARGET(style
+ COMMAND astyle --style=attach --indent=spaces=4 --indent-preprocessor --break-blocks --pad-oper --pad-header --unpad-paren --delete-empty-lines --suffix=none --align-pointer=middle --lineend=linux --indent-col1-comments ${libhdfs3_SOURCES}
+ COMMAND astyle --style=attach --indent=spaces=4 --indent-preprocessor --break-blocks --pad-oper --pad-header --unpad-paren --delete-empty-lines --suffix=none --align-pointer=middle --lineend=linux --indent-col1-comments ${unit_SOURCES}
+ COMMAND astyle --style=attach --indent=spaces=4 --indent-preprocessor --break-blocks --pad-oper --pad-header --unpad-paren --delete-empty-lines --suffix=none --align-pointer=middle --lineend=linux --indent-col1-comments ${function_SOURCES}
+ COMMAND astyle --style=attach --indent=spaces=4 --indent-preprocessor --break-blocks --pad-oper --pad-header --unpad-paren --delete-empty-lines --suffix=none --align-pointer=middle --lineend=linux --indent-col1-comments ${secure_SOURCES}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMENT "format code style..."
+)
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..8f631f8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,76 @@
+# 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.
+#
+# -*-makefile-*-
+#------------------------------------------------------------------------------
+# A makefile that integrate building this module with hawq
+#------------------------------------------------------------------------------
+subdir = depends/libhdfs3
+top_builddir = ../../
+include Makefile.global
+
+PRE_CFG_ARG =
+# get argument for running ../boostrap
+ifeq ($(enable_debug), yes)
+ PRE_CFG_ARG += --enable-debug
+endif # enable_debug
+
+ifeq ($(enable_coverage), yes)
+ PRE_CFG_ARG += --enable-coverage
+endif # enable_coverage
+
+##########################################################################
+#
+.PHONY: build all install distclean maintainer-clean clean pre-config
+
+ifeq ($(with_libhdfs3), yes)
+
+# We will need to install it temporarily under build/install for hawq building.
+all: build
+ cd $(top_builddir)/$(subdir)/build; mkdir -p install; \
+ $(MAKE) install
+
+install: build
+ cd $(top_builddir)/$(subdir)/build && $(MAKE) install
+
+distclean:
+ rm -rf $(top_builddir)/$(subdir)/build
+
+maintainer-clean: distclean
+
+clean:
+ if [ -d $(top_builddir)/$(subdir)/build ]; then \
+ cd $(top_builddir)/$(subdir)/build && $(MAKE) clean && rm -f libhdfs3_build_timestamp; \
+ fi
+
+build: pre-config
+ cd $(top_builddir)/$(subdir)/build && $(MAKE)
+
+# trigger bootstrap only once.
+pre-config:
+ cd $(top_builddir)/$(subdir)/; \
+ mkdir -p build; \
+ cd build; \
+ if [ ! -f libhdfs3_build_timestamp ]; then \
+ $(abs_top_srcdir)/$(subdir)/bootstrap --prefix=$(prefix) $(PRE_CFG_ARG) && touch libhdfs3_build_timestamp; \
+ fi
+
+else
+
+all install distclean maintainer-clean clean pre-config:
+
+endif
diff --git a/Makefile.global.in b/Makefile.global.in
new file mode 100644
index 0000000..a1b1d6c
--- /dev/null
+++ b/Makefile.global.in
@@ -0,0 +1,40 @@
+# 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.
+#
+# -*-makefile-*-
+#------------------------------------------------------------------------------
+# A makefile that integrate building this module with hawq
+#------------------------------------------------------------------------------
+
+prefix := @prefix@
+enable_debug = @enable_debug@
+enable_coverage = @enable_coverage@
+with_libhdfs3 = @with_libhdfs3@
+
+# Support for VPATH builds
+vpath_build = @vpath_build@
+abs_top_srcdir = @abs_top_srcdir@
+abs_top_builddir = @abs_top_builddir@
+
+ifneq ($(vpath_build),yes)
+top_srcdir = $(top_builddir)
+srcdir = .
+else # vpath_build = yes
+top_srcdir = $(abs_top_srcdir)
+srcdir = $(top_srcdir)/$(subdir)
+VPATH = $(srcdir)
+endif
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ccca78f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,83 @@
+libhdfs3
+========================
+
+**A Native C/C++ HDFS Client**
+
+## Description
+
+The Hadoop Distributed File System (HDFS) is a distributed file system designed to run on commodity hardware. HDFS is highly fault-tolerant and is designed to be deployed on low-cost hardware. HDFS provides high throughput access to application data and is suitable for applications that have large data sets.
+
+HDFS is implemented in JAVA language and additionally provides a JNI based C language library *libhdfs*. To use libhdfs, users must deploy the HDFS jars on every machine. This adds operational complexity for non-Java clients that just want to integrate with HDFS.
+
+**Libhdfs3**, designed as an alternative implementation of libhdfs, is implemented based on native Hadoop RPC protocol and HDFS data transfer protocol. It gets rid of the drawbacks of JNI, and it has a lightweight, small memory footprint code base. In addition, it is easy to use and deploy.
+
+Libhdfs3 is developed by [Pivotal](http://www.pivotal.io/) and used in HAWQ, which is a massive parallel database engine in [Pivotal Hadoop Distribution](http://www.pivotal.io/big-data/pivotal-hd).
+
+========================
+## Installation
+
+### Requirement
+
+To build libhdfs3, the following libraries are needed.
+
+ cmake (2.8+) http://www.cmake.org/
+ boost (tested on 1.53+) http://www.boost.org/
+ google protobuf http://code.google.com/p/protobuf/
+ libxml2 http://www.xmlsoft.org/
+ kerberos http://web.mit.edu/kerberos/
+ libuuid http://sourceforge.net/projects/libuuid/
+ libgsasl http://www.gnu.org/software/gsasl/
+
+To run tests, the following libraries are needed.
+
+ gtest (tested on 1.7.0) already integrated in the source code
+ gmock (tested on 1.7.0) already integrated in the source code
+
+To run code coverage test, the following tools are needed.
+
+ gcov (included in gcc distribution)
+ lcov (tested on 1.9) http://ltp.sourceforge.net/coverage/lcov.php
+
+### Configuration
+
+Assume libhdfs3 home directory is LIBHDFS3_HOME.
+
+ cd LIBHDFS3_HOME
+ mkdir build
+ cd build
+ ../bootstrap
+
+Environment variable CC and CXX can be used to setup the compiler.
+Script "bootstrap" is basically a wrapper of cmake command, user can use cmake directly to tune the configuration.
+
+Run command "../bootstrap --help" for more configuration.
+
+### Build
+
+Run command to build
+
+ make
+
+To build concurrently, rum make with -j option.
+
+ make -j8
+
+### Test
+
+To do unit test, run command
+
+ make unittest
+
+To do function test, first start HDFS, and create the function test configure file at LIBHDFS3_HOME/test/data/function-test.xml, an example can be found at LIBHDFS3_HOME/test/data/function-test.xml.example. And run command.
+
+ make functiontest
+
+To show code coverage result, run command. Code coverage result can be found at BUILD_DIR/CodeCoverageReport/index.html
+
+ make ShowCoverage
+
+### Install
+
+To install libhdfs3, run command
+
+ make install
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000..e435b8e
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,138 @@
+#!/bin/bash
+# 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.
+#
+die() {
+ echo "$@" 1>&2 ; exit 1
+}
+
+arg () {
+ echo "$1" | sed "s/^${2-[^=]*=}//" | sed "s/:/;/g"
+}
+
+# Detect directory information.
+source_dir=`cd "\`dirname \"$0\"\`";pwd`
+binary_dir=`pwd`
+
+# Choose the default install prefix.
+default_prefix=${source_dir}/dist
+
+# Choose the default dependency install prefix
+default_dependency=${DEPENDENCY_INSTALL_PREFIX}
+
+if [ x"${default_dependency}" = x"" ]; then
+ default_dependency="/opt/dependency"
+fi
+
+# Display bootstrap usage
+usage() {
+echo '
+Usage: '"$0"' [<options>]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --help print this message
+ --prefix=PREFIX install files in tree rooted at PREFIX
+ ['"${default_prefix}"']
+ --dependency=DIRs specify the dependencies at DIRs, separated by colon
+ ['"${default_dependency}"']
+ --enable-debug enable debug build
+ --enable-boost force to enable boost
+ --enable-coverage enable build with code coverage support
+ --enable-libc++ using libc++ instead of libstdc++, only valid for clang compiler
+
+Dependencies:
+ c/c++ compiler
+ GNU make
+ cmake http://www.cmake.org/
+ protobuf https://code.google.com/p/protobuf/
+ kerberos http://web.mit.edu/kerberos/
+ libgsasl http://www.gnu.org/software/gsasl/
+ libxml2 http://xmlsoft.org/
+ libuuid http://sourceforge.net/projects/libuuid/
+ boost 1.53+ http://www.boost.org/
+ [boost is not required if c++ compiler is g++ 4.6.0+ or clang++ with stdc++]
+
+Example:
+ mkdir build
+ cd build
+ ../bootstrap --prefix=/path/to/install --dependency=/path/to/protobuf:/path/to/kerberos/:path/to/others
+ make
+ make install
+'
+ exit 10
+}
+
+# Parse arguments
+prefix_dirs="${default_prefix}"
+dependency_dir="${default_dependency}"
+build_type="Release"
+enable_boost="OFF"
+enable_coverage="OFF"
+enable_clang_lib="OFF"
+while test $# != 0; do
+ case "$1" in
+ --prefix=*) dir=`arg "$1"`
+ prefix_dirs="$dir";;
+ --dependency=*) dir=`arg "$1"`
+ dependency_dir="$dir";;
+ --enable-debug) enable_build="ON";;
+ --enable-boost) enable_boost="ON";;
+ --enable-coverage) enable_coverage="ON";;
+ --enable-libc++) enable_clang_lib="ON";;
+ --help) usage ;;
+ *) die "Unknown option: $1" ;;
+ esac
+ shift
+done
+
+if [ ${source_dir} = ${binary_dir} ]; then
+ die "cannot build the project in the source directory! Out-of-source build is enforced!"
+fi
+
+# Check clang compiler
+if [[ x"${CC}" = x"" ]]; then
+ CC=gcc
+fi
+
+if [[ x"${CXX}" = x"" ]]; then
+ CXX=g++
+fi
+
+c_compiler=`which ${CC}`
+cxx_compiler=`which ${CXX}`
+cmake=`which cmake`
+
+if [[ ! -x ${c_compiler} ]]; then
+ die "cannot found c compiler"
+fi
+
+if [[ ! -x ${cxx_compiler} ]]; then
+ die "cannot found cplusplus compiler"
+fi
+
+if [[ ! -x ${cmake} ]]; then
+ die "cannot found cmake"
+fi
+
+# Configure
+${cmake} -DENABLE_DEBUG=${enable_build} -DCMAKE_INSTALL_PREFIX=${prefix_dirs} \
+ -DCMAKE_C_COMPILER=${c_compiler} -DCMAKE_CXX_COMPILER=${cxx_compiler} \
+ -DCMAKE_PREFIX_PATH=${dependency_dir} -DENABLE_BOOST=${enable_boost} \
+ -DENABLE_COVERAGE=${enable_coverage} -DENABLE_LIBCPP=${enable_clang_lib} ${source_dir} \
+ || die "failed to configure the project"
+
+echo 'bootstrap success. Run "make" to build.'
diff --git a/debian/.gitignore b/debian/.gitignore
new file mode 100644
index 0000000..f757c9a
--- /dev/null
+++ b/debian/.gitignore
@@ -0,0 +1,15 @@
+files
+libhdfs3.postinst.debhelper
+libhdfs3.postrm.debhelper
+libhdfs3.debhelper.log
+libhdfs3.substvars
+libhdfs3-1.postinst.debhelper
+libhdfs3-1.postrm.debhelper
+libhdfs3-1.substvars
+libhdfs3-1/
+libhdfs3-dev.debhelper.log
+libhdfs3-dev.substvars
+libhdfs3-dev/
+libhdfs3/
+tmp/
+changelog
diff --git a/debian/build.sh b/debian/build.sh
new file mode 100755
index 0000000..dc95425
--- /dev/null
+++ b/debian/build.sh
@@ -0,0 +1,118 @@
+#!/bin/bash
+
+# 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.
+#
+
+this_dir=`cd "\`dirname \"$0\"\`";pwd`
+top_dir=${this_dir}/../
+
+die() {
+ echo "$@" 1>&2 ; popd 2>/dev/null; exit 1
+}
+
+install_depends() {
+ apt-get install -qq software-properties-common || die "cannot install software-properties-common"
+ add-apt-repository -y ppa:ubuntu-toolchain-r/test || die "cannot add repository"
+ apt-get update || die "cannot update repository"
+ apt-get install -qq \
+ dpkg-dev debhelper g++ cmake libxml2-dev uuid-dev protobuf-compiler \
+ libprotobuf-dev libgsasl7-dev libkrb5-dev libboost-all-dev || die "cannot install dependencies"
+}
+
+build_with_boost() {
+ pushd ${top_dir}
+ rm -rf build && mkdir -p build && cd build || die "cannot create build directory"
+ ../bootstrap --enable-boost || die "bootstrap failed"
+ make -j2 unittest || die "failed to run unit tests"
+ popd
+}
+
+build_with_debug() {
+ pushd ${top_dir}
+ rm -rf build && mkdir -p build && cd build || die "cannot create build directory"
+ ../bootstrap --enable-debug || die "bootstrap failed"
+ make -j2 unittest || die "failed to run unit tests"
+ popd
+}
+
+create_package() {
+ pushd ${top_dir}
+ rm -rf build && mkdir -p build && cd build || die "cannot create build directory"
+ ../bootstrap || die "bootstrap failed"
+ make debian-package || die "failed to create debian package"
+ popd
+}
+
+
+deploy() {
+ pushd ${top_dir}
+
+ version=$(cat ${top_dir}/obj-x86_64-linux-gnu/version)
+
+ if [ -z "${version}" ]; then
+ die "cannot get version"
+ fi
+
+ if [ -z "${BINTRAY_KEY}" ]; then
+ die "bintray api key not set"
+ fi
+
+ message=`curl -H "X-Bintray-Publish: 1" -H "X-Bintray-Override: 1" -H "X-Bintray-Debian-Distribution: trusty" -H "X-Bintray-Debian-Component: contrib" -H "X-Bintray-Debian-Architecture: amd64" \
+ -T ${top_dir}/../libhdfs3_${version}-1_amd64.deb -uwangzw:${BINTRAY_KEY} \
+ https://api.bintray.com/content/wangzw/deb/libhdfs3/${version}/dists/trusty/contrib/binary-amd64/libhdfs3_${version}-1_amd64.deb`
+
+ if [ -z `echo ${message} | grep "success"` ]; then
+ echo ${message}
+ die "failed to upload libhdfs3_${version}-1_amd64.deb"
+ fi
+
+ message=`curl -H "X-Bintray-Publish: 1" -H "X-Bintray-Override: 1" -H "X-Bintray-Debian-Distribution: trusty" -H "X-Bintray-Debian-Component: contrib" -H "X-Bintray-Debian-Architecture: amd64" \
+ -T ${top_dir}/../libhdfs3-dev_${version}-1_amd64.deb -uwangzw:${BINTRAY_KEY} \
+ https://api.bintray.com/content/wangzw/deb/libhdfs3/${version}/dists/trusty/contrib/binary-amd64/libhdfs3-dev_${version}-1_amd64.deb`
+
+ if [ -z `echo ${message} | grep "success"` ]; then
+ echo ${message}
+ die "failed to upload libhdfs3-dev_${version}-1_amd64.deb"
+ fi
+
+ popd
+}
+
+run() {
+ install_depends || die "failed to install dependencies"
+ build_with_boost || die "build failed with boost"
+ build_with_debug || die "build failed with debug mode"
+ create_package || die "failed to create debian package"
+
+ version=$(cat ${top_dir}/obj-x86_64-linux-gnu/version)
+ echo "version ${version}"
+
+ if [ -z "${BRANCH}" ]; then
+ echo "skip deploy since environment variable BRANCH is not set"
+ return
+ fi
+
+ if [ "${BRANCH}" = "v${version}" ]; then
+ echo "deploy libhdfs3 version ${version}"
+ deploy || die "failed to deploy libhdfs3 rpms"
+ else
+ echo "skip deploy for branch ${BRANCH}"
+ fi
+}
+
+"$@"
diff --git a/debian/changelog.in b/debian/changelog.in
new file mode 100644
index 0000000..ea9dde9
--- /dev/null
+++ b/debian/changelog.in
@@ -0,0 +1,3 @@
+libhdfs3 (@libhdfs3_VERSION_STRING@-1) unstable; urgency=low
+
+ * Initial release
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..5aa30c4
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,27 @@
+Source: libhdfs3
+Priority: optional
+Build-Depends: debhelper (>= 9), cmake, libprotobuf-dev, protobuf-compiler, libxml2-dev, libkrb5-dev, uuid-dev, libgsasl7-dev
+Standards-Version: 3.9.5
+Section: libs
+
+Package: libhdfs3-dev
+Section: libdevel
+Architecture: any
+Depends: libhdfs3 (= ${binary:Version}), ${misc:Depends}
+Description: Native C/C++ HDFS Client - development files
+ Libhdfs3, designed as an alternative implementation of libhdfs,
+ is implemented based on native Hadoop RPC protocol and
+ HDFS data transfer protocol.
+ It gets rid of the drawbacks of JNI, and it has a lightweight,
+ small memory footprint code base. In addition, it is easy to use and deploy.
+
+Package: libhdfs3
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Native C/C++ HDFS Client
+ Libhdfs3, designed as an alternative implementation of libhdfs,
+ is implemented based on native Hadoop RPC protocol and
+ HDFS data transfer protocol.
+ It gets rid of the drawbacks of JNI, and it has a lightweight,
+ small memory footprint code base. In addition, it is easy to use and deploy.
+ .
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..83e9730
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,21 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: libhdfs3
+
+Files: *
+License: Apache-2.0
+
+License: Apache-2.0
+ 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.
+ .
+ On Debian systems, the complete text of the Apache version 2.0 license
+ can be found in "/usr/share/common-licenses/Apache-2.0".
diff --git a/debian/libhdfs3-dev.dirs b/debian/libhdfs3-dev.dirs
new file mode 100644
index 0000000..4418816
--- /dev/null
+++ b/debian/libhdfs3-dev.dirs
@@ -0,0 +1,2 @@
+usr/lib
+usr/include
diff --git a/debian/libhdfs3-dev.install b/debian/libhdfs3-dev.install
new file mode 100644
index 0000000..6cd8ddd
--- /dev/null
+++ b/debian/libhdfs3-dev.install
@@ -0,0 +1,4 @@
+usr/include/*
+usr/lib/lib*.a
+usr/lib/lib*.so
+usr/lib/pkgconfig/*
diff --git a/debian/libhdfs3-dev.lintian-overrides b/debian/libhdfs3-dev.lintian-overrides
new file mode 100644
index 0000000..ac1eacb
--- /dev/null
+++ b/debian/libhdfs3-dev.lintian-overrides
@@ -0,0 +1 @@
+libhdfs3-dev: new-package-should-close-itp-bug
diff --git a/debian/libhdfs3.dirs b/debian/libhdfs3.dirs
new file mode 100644
index 0000000..6845771
--- /dev/null
+++ b/debian/libhdfs3.dirs
@@ -0,0 +1 @@
+usr/lib
diff --git a/debian/libhdfs3.install b/debian/libhdfs3.install
new file mode 100644
index 0000000..d0dbfd1
--- /dev/null
+++ b/debian/libhdfs3.install
@@ -0,0 +1 @@
+usr/lib/lib*.so.*
diff --git a/debian/libhdfs3.lintian-overrides b/debian/libhdfs3.lintian-overrides
new file mode 100644
index 0000000..520836b
--- /dev/null
+++ b/debian/libhdfs3.lintian-overrides
@@ -0,0 +1 @@
+libhdfs3-1: new-package-should-close-itp-bug
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..1f6d4da
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,24 @@
+#!/usr/bin/make -f
+# See debhelper(7) (uncomment to enable)
+# output every command that modifies files on the build system.
+#DH_VERBOSE = 1
+
+# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/*
+DPKG_EXPORT_BUILDFLAGS = 1
+include /usr/share/dpkg/default.mk
+
+# see FEATURE AREAS in dpkg-buildflags(1)
+#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+
+# main packaging script based on dh7 syntax
+%:
+ dh $@ --parallel
+
+# debmake generated override targets
+# This is example for Cmake (See http://bugs.debian.org/641051 )
+#override_dh_auto_configure:
+# dh_auto_configure -- \
+# -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)
+
+# Tests needs a running Hadoop cluster
+override_dh_auto_test:
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/mock/CMakeLists.txt b/mock/CMakeLists.txt
new file mode 100644
index 0000000..2d01f84
--- /dev/null
+++ b/mock/CMakeLists.txt
@@ -0,0 +1,7 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+AUTO_SOURCES(files "*.cpp" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}")
+LIST(APPEND libhdfs3_MOCK_SOURCES ${files})
+
+SET(libhdfs3_MOCK_SOURCES ${libhdfs3_MOCK_SOURCES} PARENT_SCOPE)
+
diff --git a/mock/MockBufferedSocketReader.h b/mock/MockBufferedSocketReader.h
new file mode 100644
index 0000000..803530c
--- /dev/null
+++ b/mock/MockBufferedSocketReader.h
@@ -0,0 +1,43 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_MOCKBUFFEREDSOCKETREADER_H_
+#define _HDFS_LIBHDFS3_MOCK_MOCKBUFFEREDSOCKETREADER_H_
+
+#include "gmock/gmock.h"
+#include "network/BufferedSocketReader.h"
+
+namespace Hdfs {
+namespace Mock {
+
+class MockBufferedSocketReader: public Hdfs::Internal::BufferedSocketReader {
+public:
+ MOCK_METHOD2(read, int32_t(char * b, int32_t s));
+ MOCK_METHOD3(readFully, void(char * b, int32_t s, int timeout));
+ MOCK_METHOD1(readBigEndianInt32, int32_t(int timeout));
+ MOCK_METHOD1(readVarint32, int32_t(int timeout));
+ MOCK_METHOD1(poll, bool(int timeout));
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_MOCKBUFFEREDSOCKETREADER_H_ */
diff --git a/mock/MockDatanode.h b/mock/MockDatanode.h
new file mode 100644
index 0000000..2bd7e0b
--- /dev/null
+++ b/mock/MockDatanode.h
@@ -0,0 +1,44 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_MOCKDATANODE_H_
+#define _HDFS_LIBHDFS3_MOCK_MOCKDATANODE_H_
+
+#include "gmock/gmock.h"
+#include "server/Datanode.h"
+
+using namespace Hdfs::Internal;
+namespace Hdfs {
+
+namespace Mock {
+
+class MockDatanode: public Datanode {
+public:
+ MOCK_METHOD1(getReplicaVisibleLength, int64_t (const Hdfs::Internal::ExtendedBlock & b));
+ MOCK_METHOD3(getBlockLocalPathInfo, void (const Hdfs::Internal::ExtendedBlock & block,
+ const Hdfs::Internal::Token & token, Hdfs::Internal::BlockLocalPathInfo & info));
+
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_MOCKDATANODE_H_ */
diff --git a/mock/MockFileSystemInter.h b/mock/MockFileSystemInter.h
new file mode 100644
index 0000000..336db7e
--- /dev/null
+++ b/mock/MockFileSystemInter.h
@@ -0,0 +1,111 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_MOCKFILESYSTEMINTER_H_
+#define _HDFS_LIBHDFS3_MOCK_MOCKFILESYSTEMINTER_H_
+
+#include "gmock/gmock.h"
+
+#include "client/DirectoryIterator.h"
+#include "client/FileStatus.h"
+#include "client/FileSystem.h"
+#include "client/FileSystemInter.h"
+#include "client/FileSystemKey.h"
+#include "client/FileSystemStats.h"
+#include "client/Permission.h"
+#include "client/UserInfo.h"
+#include "Memory.h"
+#include "server/DatanodeInfo.h"
+#include "server/ExtendedBlock.h"
+#include "server/LocatedBlock.h"
+#include "server/LocatedBlocks.h"
+#include "SessionConfig.h"
+
+#include <string>
+#include <vector>
+
+class MockFileSystemInter: public Hdfs::Internal::FileSystemInter {
+public:
+ MOCK_METHOD0(connect, void());
+ MOCK_METHOD0(disconnect, void());
+ MOCK_METHOD1(getStandardPath, const std::string(const char * path));
+ MOCK_METHOD0(getClientName, const char *());
+ MOCK_CONST_METHOD0(getDefaultReplication, int());
+ MOCK_CONST_METHOD0(getDefaultBlockSize, int64_t());
+ MOCK_CONST_METHOD0(getHomeDirectory, std::string());
+ MOCK_METHOD2(deletePath, bool(const char * path, bool recursive));
+ MOCK_METHOD2(mkdir, bool(const char * path, const Hdfs::Permission & permission));
+ MOCK_METHOD2(mkdirs, bool(const char * path, const Hdfs::Permission & permission));
+ MOCK_METHOD1(getFileStatus, Hdfs::FileStatus(const char * path));
+ MOCK_METHOD3(setOwner, void(const char * path, const char * username, const char * groupname));
+ MOCK_METHOD3(setTimes, void(const char * path, int64_t mtime, int64_t atime));
+ MOCK_METHOD2(setPermission, void(const char * path, const Hdfs::Permission &));
+ MOCK_METHOD2(setReplication, bool(const char * path, short replication));
+ MOCK_METHOD2(rename, bool(const char * src, const char * dst));
+ MOCK_METHOD1(setWorkingDirectory, void(const char * path));
+ MOCK_CONST_METHOD0(getWorkingDirectory, std::string());
+ MOCK_METHOD1(exist, bool(const char * path));
+ MOCK_METHOD0(getFsStats, Hdfs::FileSystemStats());
+ MOCK_METHOD2(truncate, bool(const char * src, int64_t size));
+ MOCK_METHOD1(getDelegationToken, std::string(const char * renewer));
+ MOCK_METHOD0(getDelegationToken, std::string());
+ MOCK_METHOD1(renewDelegationToken, int64_t(const std::string & token));
+ MOCK_METHOD1(cancelDelegationToken, void(const std::string & token));
+ MOCK_METHOD6(create, void(const std::string & src, const Hdfs::Permission & masked, int flag, bool createParent, short replication, int64_t blockSize));
+ MOCK_METHOD1(append, std::pair<Hdfs::Internal::shared_ptr<Hdfs::Internal::LocatedBlock>,
+ Hdfs::Internal::shared_ptr<Hdfs::FileStatus> >(const std::string & src));
+ MOCK_METHOD2(abandonBlock, void(const Hdfs::Internal::ExtendedBlock & b, const std::string & srcr));
+ MOCK_METHOD3(addBlock, Hdfs::Internal::shared_ptr<Hdfs::Internal::LocatedBlock>(const std::string & src,
+ const Hdfs::Internal::ExtendedBlock * previous,
+ const std::vector<Hdfs::Internal::DatanodeInfo> & excludeNodes));
+ MOCK_METHOD6(getAdditionalDatanode, Hdfs::Internal::shared_ptr<Hdfs::Internal::LocatedBlock> (const std::string & src,
+ const Hdfs::Internal::ExtendedBlock & blk,
+ const std::vector<Hdfs::Internal::DatanodeInfo> & existings,
+ const std::vector<std::string> & storageIDs,
+ const std::vector<Hdfs::Internal::DatanodeInfo> & excludes, int numAdditionalNodes));
+ MOCK_METHOD2(complete, bool(const std::string & src,
+ const Hdfs::Internal::ExtendedBlock * last));
+ MOCK_METHOD1(reportBadBlocks, void(const std::vector<Hdfs::Internal::LocatedBlock> & blocks));
+ MOCK_METHOD1(fsync, void(const std::string & src));
+ MOCK_METHOD1(updateBlockForPipeline, Hdfs::Internal::shared_ptr<Hdfs::Internal::LocatedBlock>(const Hdfs::Internal::ExtendedBlock & block));
+ MOCK_METHOD4(updatePipeline, void(const Hdfs::Internal::ExtendedBlock & oldBlock,
+ const Hdfs::Internal::ExtendedBlock & newBlock,
+ const std::vector<Hdfs::Internal::DatanodeInfo> & newNodes,
+ const std::vector<std::string> & storageIDs));
+ MOCK_CONST_METHOD0(getConf, const Hdfs::Internal::SessionConfig &());
+ MOCK_CONST_METHOD0(getUserInfo, const Hdfs::Internal::UserInfo &());
+ MOCK_METHOD4(getBlockLocations, void(const std::string & src, int64_t offset, int64_t length, Hdfs::Internal::LocatedBlocks & lbs));
+ MOCK_METHOD4(getListing, bool(const std::string & src, const std::string & , bool needLocation, std::vector<Hdfs::FileStatus> &));
+ MOCK_METHOD2(listDirectory, Hdfs::DirectoryIterator(const char *, bool));
+ MOCK_METHOD0(renewLease, bool());
+ MOCK_METHOD0(registerOpenedOutputStream, void());
+ MOCK_METHOD0(unregisterOpenedOutputStream, bool());
+ MOCK_METHOD3(getFileBlockLocations, std::vector<Hdfs::BlockLocation> (const char * path, int64_t start, int64_t len));
+ MOCK_METHOD2(listAllDirectoryItems, std::vector<Hdfs::FileStatus> (const char * path, bool needLocation));
+ MOCK_METHOD0(getPeerCache, Hdfs::Internal::PeerCache &());
+ MOCK_METHOD2(createEncryptionZone, bool(const char * path, const char * keyName));
+ MOCK_METHOD1(getEZForPath, Hdfs::EncryptionZoneInfo(const char * path));
+ MOCK_METHOD2(listEncryptionZones, bool(const int64_t id, std::vector<Hdfs::EncryptionZoneInfo> &));
+ MOCK_METHOD0(listEncryptionZone, Hdfs::EncryptionZoneIterator());
+ MOCK_METHOD0(listAllEncryptionZoneItems, std::vector<Hdfs::EncryptionZoneInfo>());
+};
+
+#endif /* _HDFS_LIBHDFS3_MOCK_MOCKSOCKET_H_ */
diff --git a/mock/MockLeaseRenewer.h b/mock/MockLeaseRenewer.h
new file mode 100644
index 0000000..73b71ec
--- /dev/null
+++ b/mock/MockLeaseRenewer.h
@@ -0,0 +1,56 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_MOCKLEASERENEWER_H_
+#define _HDFS_LIBHDFS3_MOCK_MOCKLEASERENEWER_H_
+
+#include "client/LeaseRenewer.h"
+#include "gmock/gmock.h"
+
+namespace Hdfs {
+namespace Mock {
+
+class MockLeaseRenewer: public Hdfs::Internal::LeaseRenewer {
+public:
+ MOCK_METHOD1(StartRenew, void(shared_ptr<FileSystemInter>));
+ MOCK_METHOD1(StopRenew, void(shared_ptr<FileSystemInter>));
+};
+
+static inline shared_ptr<LeaseRenewer> MakeMockLeaseRenewer() {
+ Hdfs::Internal::LeaseRenewer::GetLeaseRenewer();
+ shared_ptr<LeaseRenewer> old = Hdfs::Internal::LeaseRenewer::renewer;
+ Hdfs::Internal::LeaseRenewer::renewer = shared_ptr<LeaseRenewer>(new MockLeaseRenewer);
+ return old;
+}
+
+static inline MockLeaseRenewer & GetMockLeaseRenewer(){
+ assert(Hdfs::Internal::LeaseRenewer::renewer);
+ return static_cast<MockLeaseRenewer &> (*Hdfs::Internal::LeaseRenewer::renewer);
+}
+
+static inline void ResetMockLeaseRenewer(shared_ptr<LeaseRenewer> old){
+ Hdfs::Internal::LeaseRenewer::renewer = old;
+}
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_MOCKLEASERENEWER_H_ */
diff --git a/mock/MockNamenode.h b/mock/MockNamenode.h
new file mode 100644
index 0000000..1a52d83
--- /dev/null
+++ b/mock/MockNamenode.h
@@ -0,0 +1,110 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_MOCKNAMENODE_H_
+#define _HDFS_LIBHDFS3_MOCK_MOCKNAMENODE_H_
+
+#include "gmock/gmock.h"
+#include "server/Namenode.h"
+#include "server/LocatedBlocks.h"
+#include "server/LocatedBlock.h"
+#include "server/ExtendedBlock.h"
+#include "server/DatanodeInfo.h"
+#include "client/FileStatus.h"
+
+using namespace Hdfs::Internal;
+namespace Hdfs {
+
+namespace Mock {
+
+class MockNamenode: public Namenode {
+public:
+ MOCK_METHOD4(getBlockLocations, void(const std::string & src, int64_t offset,
+ int64_t length, LocatedBlocks & lbs));
+ MOCK_METHOD7(create, void(const std::string & src, const Permission & masked,
+ const std::string & clientName, int flag, bool createParent,
+ short replication, int64_t blockSize));
+ MOCK_METHOD2(append, std::pair<shared_ptr<LocatedBlock>,
+ shared_ptr<FileStatus> >(const std::string & src, const std::string & clientName));
+ MOCK_METHOD2(setReplication, bool(const std::string & src, short replication));
+ MOCK_METHOD2(setPermission, void(const std::string & src,
+ const Permission & permission));
+ MOCK_METHOD3(setOwner, void(const std::string & src, const std::string & username, const std::string & groupname));
+ MOCK_METHOD3(abandonBlock, void(const ExtendedBlock & b, const std::string & src,
+ const std::string & holder));
+ MOCK_METHOD4(addBlock, shared_ptr<LocatedBlock>(const std::string & src,
+ const std::string & clientName, const ExtendedBlock * previous,
+ const std::vector<DatanodeInfo> & excludeNodes));
+ MOCK_METHOD7(getAdditionalDatanode, shared_ptr<LocatedBlock>(const std::string & src,
+ const ExtendedBlock & blk,
+ const std::vector<DatanodeInfo> & existings,
+ const std::vector<std::string> & storageIDs,
+ const std::vector<DatanodeInfo> & excludes, int numAdditionalNodes,
+ const std::string & clientName));
+ MOCK_METHOD3(complete, bool(const std::string & src,
+ const std::string & clientName, const ExtendedBlock * last));
+ MOCK_METHOD1(reportBadBlocks, void(const std::vector<LocatedBlock> & blocks));
+ MOCK_METHOD2(concat, void(const std::string & trg,
+ const std::vector<std::string> & srcs));
+ MOCK_METHOD3(truncate, bool(const std::string & src, int64_t size,
+ const std::string & clientName));
+ MOCK_METHOD2(getLease, void(const std::string & src,
+ const std::string & clientName)) ;
+ MOCK_METHOD2(releaseLease, void(const std::string & src,
+ const std::string & clientName));
+ MOCK_METHOD2(deleteFile, bool(const std::string & src, bool recursive));
+ MOCK_METHOD3(mkdirs, bool(const std::string & src, const Permission & masked,
+ bool createParent)) ;
+ MOCK_METHOD1(renewLease, void(const std::string & clientName));
+ MOCK_METHOD2(recoverLease, bool(const std::string & src,
+ const std::string & clientName));
+ MOCK_METHOD0(getFsStats, std::vector<int64_t>());
+ MOCK_METHOD1(metaSave, void(
+ const std::string & filename));
+ MOCK_METHOD2(getFileInfo, FileStatus(const std::string & src, bool *exist));
+ MOCK_METHOD1(getFileLinkInfo, FileStatus(const std::string & src));
+ MOCK_METHOD3(setQuota, void(const std::string & path, int64_t namespaceQuota,
+ int64_t diskspaceQuota));
+ MOCK_METHOD2(fsync, void(const std::string & src, const std::string & client));
+ MOCK_METHOD3(setTimes, void(const std::string & src, int64_t mtime, int64_t atime));
+ MOCK_METHOD4(createSymlink, void(const std::string & target,
+ const std::string & link, const Permission & dirPerm,
+ bool createParent));
+ MOCK_METHOD1(getLinkTarget, std::string(const std::string & path));
+ MOCK_METHOD2(updateBlockForPipeline, shared_ptr<LocatedBlock>(const ExtendedBlock & block,
+ const std::string & clientName));
+ MOCK_METHOD5(updatePipeline, void(const std::string & clientName,
+ const ExtendedBlock & oldBlock, const ExtendedBlock & newBlock,
+ const std::vector<DatanodeInfo> & newNodes,
+ const std::vector<std::string> & storageIDs));
+ MOCK_METHOD4(getListing, bool(const std::string & src,
+ const std::string & startAfter, bool needLocation,
+ std::vector<FileStatus> & dl));
+ MOCK_METHOD2(rename, bool(const std::string & src, const std::string & dst));
+ MOCK_METHOD1(getDelegationToken, Token(const std::string & renewer) );
+ MOCK_METHOD1(renewDelegationToken, int64_t(const Token & token));
+ MOCK_METHOD1(cancelDelegationToken, void(const Token & token));
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_MOCKNAMENODE_H_ */
diff --git a/mock/MockOperationCanceledCallback.h b/mock/MockOperationCanceledCallback.h
new file mode 100644
index 0000000..0300081
--- /dev/null
+++ b/mock/MockOperationCanceledCallback.h
@@ -0,0 +1,48 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_MOCKOPERATIONCANCELEDCALLBACK_H_
+#define _HDFS_LIBHDFS3_MOCK_MOCKOPERATIONCANCELEDCALLBACK_H_
+
+#include "gmock/gmock.h"
+
+namespace Hdfs {
+namespace Mock {
+
+class MockCancelObject {
+public:
+ bool canceled() {
+ return check();
+ }
+ virtual bool check() = 0;
+ virtual ~MockCancelObject() {
+ }
+};
+
+class MockOperationCanceledCallback: public MockCancelObject {
+public:
+ MOCK_METHOD0(check, bool());
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_MOCKOPERATIONCANCELEDCALLBACK_H_ */
diff --git a/mock/MockPipeline.h b/mock/MockPipeline.h
new file mode 100644
index 0000000..aab35e8
--- /dev/null
+++ b/mock/MockPipeline.h
@@ -0,0 +1,47 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_MOCKPIPELINE_H_
+#define _HDFS_LIBHDFS3_MOCK_MOCKPIPELINE_H_
+
+#include "gmock/gmock.h"
+#include "client/Packet.h"
+#include "server/ExtendedBlock.h"
+#include "client/FileSystem.h"
+
+using namespace Hdfs::Internal;
+namespace Hdfs {
+
+namespace Mock {
+
+class MockPipeline: public Pipeline {
+public:
+ MOCK_METHOD0(flush, void());
+ MOCK_METHOD1(close, shared_ptr<LocatedBlock> (shared_ptr<Packet> lastPacket));
+ MOCK_METHOD1(send, void (shared_ptr<Packet> packet));
+ MOCK_METHOD1(setFilesystem, void (FileSystemInter * fs));
+
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_MOCKPIPELINE_H_ */
diff --git a/mock/MockRpcChannel.h b/mock/MockRpcChannel.h
new file mode 100644
index 0000000..c0e193a
--- /dev/null
+++ b/mock/MockRpcChannel.h
@@ -0,0 +1,43 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_MOCKRPCCHANNEL_H_
+#define _HDFS_LIBHDFS3_MOCK_MOCKRPCCHANNEL_H_
+
+#include "gmock/gmock.h"
+#include "rpc/RpcChannel.h"
+
+namespace Hdfs {
+namespace Mock {
+
+class MockRpcChannel: public Hdfs::Internal::RpcChannel {
+public:
+ MOCK_METHOD0(close, void());
+ MOCK_METHOD1(invoke, void(const Hdfs::Internal::RpcCall &));
+ MOCK_METHOD0(checkIdle, bool());
+ MOCK_METHOD0(waitForExit, void());
+ MOCK_METHOD0(addRef, void());
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_MOCKRPCCHANNEL_H_ */
diff --git a/mock/MockRpcClient.h b/mock/MockRpcClient.h
new file mode 100644
index 0000000..2441520
--- /dev/null
+++ b/mock/MockRpcClient.h
@@ -0,0 +1,48 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_MOCKRPCCLIENT_H_
+#define _HDFS_LIBHDFS3_MOCK_MOCKRPCCLIENT_H_
+
+#include "gmock/gmock.h"
+#include "rpc/RpcClient.h"
+
+using namespace Hdfs::Internal;
+namespace Hdfs {
+namespace Mock {
+
+class MockRpcClient: public RpcClient {
+public:
+ MOCK_METHOD0(isRunning, bool());
+
+ MOCK_METHOD4(getChannel, RpcChannel & (const RpcAuth &,
+ const RpcProtocolInfo &, const RpcServerInfo &,
+ const RpcConfig &));
+
+ MOCK_CONST_METHOD0(getClientId, std::string());
+
+ MOCK_METHOD0(getCallId, int32_t());
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_MOCKRPCCLIENT_H_ */
diff --git a/mock/MockRpcRemoteCall.h b/mock/MockRpcRemoteCall.h
new file mode 100644
index 0000000..7b19655
--- /dev/null
+++ b/mock/MockRpcRemoteCall.h
@@ -0,0 +1,46 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_MOCKRPCREMOTECALL_H_
+#define _HDFS_LIBHDFS3_MOCK_MOCKRPCREMOTECALL_H_
+
+#include "gmock/gmock.h"
+#include "rpc/RpcRemoteCall.h"
+
+using namespace Hdfs::Internal;
+namespace Hdfs {
+namespace Mock {
+
+class MockRpcRemoteCall: public RpcRemoteCall {
+public:
+ MockRpcRemoteCall(const RpcCall & c, int32_t id, const std::string & clientId) :
+ RpcRemoteCall(c, id, clientId) {
+ }
+
+ MOCK_METHOD2(serialize, void(const RpcProtocolInfo&, WriteBuffer &));
+ MOCK_METHOD1(cancel, void(exception_ptr ));
+
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_MOCKRPCREMOTECALL_H_ */
diff --git a/mock/MockSockCall.h b/mock/MockSockCall.h
new file mode 100644
index 0000000..27d8d40
--- /dev/null
+++ b/mock/MockSockCall.h
@@ -0,0 +1,59 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_MOCKSOCKCALL_H_
+#define _HDFS_LIBHDFS3_MOCK_MOCKSOCKCALL_H_
+
+#include "gmock/gmock.h"
+
+#include "MockSystem.h"
+
+namespace Hdfs {
+namespace Mock {
+
+class MockSockSysCall: public MockSockSysCallInterface {
+public:
+ MOCK_METHOD4(recv , ssize_t (int sock, void * buffer, size_t size, int flag));
+ MOCK_METHOD4(send , ssize_t (int sock, const void * buffer, size_t size,
+ int flag));
+ MOCK_METHOD3(recvmsg , ssize_t (int socket, struct msghdr *message, int flags));
+ MOCK_METHOD4(getaddrinfo , int (const char * __restrict host,
+ const char * __restrict port,
+ const struct addrinfo * __restrict hint,
+ struct addrinfo ** __restrict addr));
+ MOCK_METHOD1(freeaddrinfo , void (struct addrinfo * addr));
+ MOCK_METHOD3(socket , int (int family, int type, int protocol));
+ MOCK_METHOD3(connect , int (int sock, const struct sockaddr * addr,
+ socklen_t len));
+ MOCK_METHOD3(getpeername , int (int sock, struct sockaddr * __restrict peer,
+ socklen_t * __restrict len));
+ MOCK_METHOD3(fcntl , int (int sock, int flag, int value));
+ MOCK_METHOD5(setsockopt , int (int sock, int level, int optname, const void *optval,
+ socklen_t optlen));
+ MOCK_METHOD3(poll , int (struct pollfd * pfd, nfds_t size, int timeout));
+ MOCK_METHOD2(shutdown , int (int sock, int how));
+ MOCK_METHOD1(close , int (int sock));
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_MOCKSOCKCALL_H_ */
diff --git a/mock/MockSocket.h b/mock/MockSocket.h
new file mode 100644
index 0000000..2c3fb16
--- /dev/null
+++ b/mock/MockSocket.h
@@ -0,0 +1,60 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_MOCKSOCKET_H_
+#define _HDFS_LIBHDFS3_MOCK_MOCKSOCKET_H_
+
+#include "gmock/gmock.h"
+
+#include "network/Socket.h"
+
+class MockSocket: public Hdfs::Internal::Socket {
+public:
+
+ MOCK_METHOD2(read, int32_t(char * buffer, int32_t size));
+
+ MOCK_METHOD3(readFully, void(char * buffer, int32_t size, int timeout));
+
+ MOCK_METHOD2(write, int32_t(const char * buffer, int32_t size));
+
+ MOCK_METHOD3(writeFully, void(const char * buffer, int32_t size, int timeout));
+
+ MOCK_METHOD3(connect, void(const char * host, int port, int timeout));
+
+ MOCK_METHOD3(connect, void(const char * host, const char * port, int timeout));
+
+ MOCK_METHOD4(connect, void(struct addrinfo * paddr, const char * host, const char * port,
+ int timeout));
+
+ MOCK_METHOD3(poll, bool(bool read, bool write, int timeout));
+
+ MOCK_METHOD1(setBlockMode, void(bool enable));
+
+ MOCK_METHOD1(setNoDelay, void(bool enable));
+
+ MOCK_METHOD1(setLingerTimeout, void(int timeout));
+
+ MOCK_METHOD0(disableSigPipe, void());
+
+ MOCK_METHOD0(close, void());
+};
+
+#endif /* _HDFS_LIBHDFS3_MOCK_MOCKSOCKET_H_ */
diff --git a/mock/MockSystem.cpp b/mock/MockSystem.cpp
new file mode 100644
index 0000000..eabd464
--- /dev/null
+++ b/mock/MockSystem.cpp
@@ -0,0 +1,142 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <cassert>
+#include <climits>
+#include <errno.h>
+#include <poll.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netdb.h>
+
+#include <string.h>
+
+#include "MockSystem.h"
+
+namespace MockSystem {
+
+Hdfs::Mock::MockSockSysCallInterface * MockSockSysCallObj = NULL;
+
+ssize_t recv(int sock, void * buffer, size_t size, int flag) {
+ if (MockSockSysCallObj) {
+ return MockSockSysCallObj->recv(sock, buffer, size, flag);
+ }
+ return ::recv(sock, buffer, size, flag);
+}
+
+ssize_t send(int sock, const void * buffer, size_t size, int flag) {
+ if (MockSockSysCallObj) {
+ return MockSockSysCallObj->send(sock, buffer, size, flag);
+ }
+ return ::send(sock, buffer, size, flag);
+}
+
+ssize_t recvmsg(int socket, struct msghdr *message, int flags) {
+ if (MockSockSysCallObj) {
+ return MockSockSysCallObj->recvmsg(socket, message, flags);
+ }
+ return ::recvmsg(socket, message, flags);
+}
+
+int getaddrinfo(const char * __restrict host, const char * __restrict port,
+ const struct addrinfo * __restrict hint,
+ struct addrinfo ** __restrict addr) {
+ if (MockSockSysCallObj) {
+ return MockSockSysCallObj->getaddrinfo(host, port, hint, addr);
+ }
+ return ::getaddrinfo(host, port, hint, addr);
+}
+
+void freeaddrinfo(struct addrinfo * addr) {
+ if (MockSockSysCallObj) {
+ MockSockSysCallObj->freeaddrinfo(addr);
+ } else {
+ ::freeaddrinfo(addr);
+ }
+}
+
+int socket(int family, int type, int protocol) {
+ if (MockSockSysCallObj) {
+ return MockSockSysCallObj->socket(family, type, protocol);
+ }
+ return ::socket(family, type, protocol);
+}
+
+int connect(int sock, const struct sockaddr * addr, socklen_t len) {
+ if (MockSockSysCallObj) {
+ return MockSockSysCallObj->connect(sock, addr, len);
+ }
+ return ::connect(sock, addr, len);
+}
+
+int getpeername(int sock, struct sockaddr * __restrict peer,
+ socklen_t * __restrict len) {
+ if (MockSockSysCallObj) {
+ return MockSockSysCallObj->getpeername(sock, peer, len);
+ }
+ return ::getpeername(sock, peer, len);
+}
+
+int fcntl(int sock, int flag, int value) {
+ if (MockSockSysCallObj) {
+ return MockSockSysCallObj->fcntl(sock, flag, value);
+ }
+ return ::fcntl(sock, flag, value);
+}
+
+int setsockopt(int sock, int level, int optname, const void *optval,
+ socklen_t optlen) {
+ if (MockSockSysCallObj) {
+ return MockSockSysCallObj->setsockopt(sock, level, optname, optval,
+ optlen);
+ }
+ return ::setsockopt(sock, level, optname, optval, optlen);
+}
+
+int poll(struct pollfd * pfd, nfds_t size, int timeout) {
+ if (MockSockSysCallObj) {
+ return MockSockSysCallObj->poll(pfd, size, timeout);
+ }
+ return ::poll(pfd, size, timeout);
+}
+
+int shutdown(int sock, int how) {
+ if (MockSockSysCallObj) {
+ return MockSockSysCallObj->shutdown(sock, how);
+ }
+ return ::shutdown(sock, how);
+}
+
+int close(int sock) {
+ if (MockSockSysCallObj) {
+ return MockSockSysCallObj->close(sock);
+ }
+ return ::close(sock);
+}
+
+}
diff --git a/mock/MockSystem.h b/mock/MockSystem.h
new file mode 100644
index 0000000..a7656b3
--- /dev/null
+++ b/mock/MockSystem.h
@@ -0,0 +1,106 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_MOCKSYSTEM_H_
+#define _HDFS_LIBHDFS3_MOCK_MOCKSYSTEM_H_
+
+#include <poll.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netdb.h>
+
+namespace Hdfs {
+namespace Mock {
+
+class MockSockSysCallInterface {
+public:
+ virtual ~MockSockSysCallInterface() {
+ }
+
+ virtual ssize_t recv(int sock, void * buffer, size_t size, int flag) = 0;
+ virtual ssize_t send(int sock, const void * buffer, size_t size,
+ int flag) = 0;
+ virtual ssize_t recvmsg(int socket, struct msghdr *message, int flags) = 0;
+ virtual int getaddrinfo(const char * __restrict host,
+ const char * __restrict port,
+ const struct addrinfo * __restrict hint,
+ struct addrinfo ** __restrict addr) = 0;
+ virtual void freeaddrinfo(struct addrinfo * addr) = 0;
+ virtual int socket(int family, int type, int protocol) = 0;
+ virtual int connect(int sock, const struct sockaddr * addr,
+ socklen_t len) = 0;
+ virtual int getpeername(int sock, struct sockaddr * __restrict peer,
+ socklen_t * __restrict len) = 0;
+ virtual int fcntl(int sock, int flag, int value) = 0;
+ virtual int setsockopt(int sock, int level, int optname, const void *optval,
+ socklen_t optlen) = 0;
+ virtual int poll(struct pollfd * pfd, nfds_t size, int timeout) = 0;
+ virtual int shutdown(int sock, int how) = 0;
+ virtual int close(int sock) = 0;
+};
+
+}
+}
+
+namespace MockSystem {
+
+extern Hdfs::Mock::MockSockSysCallInterface * MockSockSysCallObj;
+
+ssize_t recv(int sock, void * buffer, size_t size, int flag);
+
+ssize_t send(int sock, const void * buffer, size_t size, int flag);
+
+ssize_t recvmsg(int socket, struct msghdr *message, int flags);
+
+int getaddrinfo(const char * __restrict host, const char * __restrict port,
+ const struct addrinfo * __restrict hint,
+ struct addrinfo ** __restrict addr);
+
+void freeaddrinfo(struct addrinfo * addr);
+
+int socket(int family, int type, int protocol);
+
+int connect(int sock, const struct sockaddr * addr, socklen_t len);
+
+int getpeername(int sock, struct sockaddr * __restrict peer,
+ socklen_t * __restrict len);
+
+int fcntl(int sock, int flag, int value);
+
+int setsockopt(int sock, int level, int optname, const void *optval,
+ socklen_t optlen);
+
+int poll(struct pollfd * pfd, nfds_t size, int timeout);
+
+int shutdown(int sock, int how);
+
+int close(int sock);
+
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_MOCKSYSTEM_H_ */
diff --git a/mock/NamenodeStub.h b/mock/NamenodeStub.h
new file mode 100644
index 0000000..8e49aaf
--- /dev/null
+++ b/mock/NamenodeStub.h
@@ -0,0 +1,49 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_NAMENODESTUB_H_
+#define _HDFS_LIBHDFS3_MOCK_NAMENODESTUB_H_
+
+#include "MockNamenode.h"
+
+#include <memory>
+
+using namespace Hdfs;
+using namespace Internal;
+
+namespace Hdfs {
+
+namespace Mock {
+
+class NamenodeStub {
+public:
+
+ virtual ~NamenodeStub() {
+ }
+
+ virtual MockNamenode * getNamenode() = 0;
+
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_NAMENODESTUB_H_ */
diff --git a/mock/PipelineStub.h b/mock/PipelineStub.h
new file mode 100644
index 0000000..a5419c0
--- /dev/null
+++ b/mock/PipelineStub.h
@@ -0,0 +1,49 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_PIPELINESTUB_H_
+#define _HDFS_LIBHDFS3_MOCK_PIPELINESTUB_H_
+
+#include "MockPipeline.h"
+
+#include <memory>
+
+using namespace Hdfs;
+using namespace Internal;
+
+namespace Hdfs {
+
+namespace Mock {
+
+class PipelineStub {
+public:
+
+ virtual ~PipelineStub() {
+ }
+
+ virtual shared_ptr<MockPipeline> getPipeline() = 0;
+
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_PIPELINESTUB_H_ */
diff --git a/mock/TestDatanodeStub.h b/mock/TestDatanodeStub.h
new file mode 100644
index 0000000..d179c7c
--- /dev/null
+++ b/mock/TestDatanodeStub.h
@@ -0,0 +1,42 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_TESTDATANODESTUB_H_
+#define _HDFS_LIBHDFS3_MOCK_TESTDATANODESTUB_H_
+
+#include "MockDatanode.h"
+
+namespace Hdfs {
+
+namespace Mock {
+
+class TestDatanodeStub {
+public:
+ virtual ~TestDatanodeStub() {
+ }
+
+ virtual shared_ptr<MockDatanode> getDatanode() = 0;
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_TESTDATANODESTUB_H_ */
diff --git a/mock/TestRpcChannelStub.h b/mock/TestRpcChannelStub.h
new file mode 100644
index 0000000..8165009
--- /dev/null
+++ b/mock/TestRpcChannelStub.h
@@ -0,0 +1,50 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_TESTRPCCHANNELSTUB_H_
+#define _HDFS_LIBHDFS3_MOCK_TESTRPCCHANNELSTUB_H_
+
+#include "rpc/RpcChannel.h"
+
+namespace Hdfs {
+namespace Internal {
+
+class RpcClient;
+
+}
+
+namespace Mock {
+
+class TestRpcChannelStub {
+public:
+ virtual ~TestRpcChannelStub() {
+ }
+
+ virtual Hdfs::Internal::RpcChannel* getChannel(
+ Hdfs::Internal::RpcChannelKey key,
+ Hdfs::Internal::RpcClient & c) = 0;
+
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_MOCK_TESTRPCCHANNELSTUB_H_ */
diff --git a/mock/TestUtil.h b/mock/TestUtil.h
new file mode 100644
index 0000000..25cd140
--- /dev/null
+++ b/mock/TestUtil.h
@@ -0,0 +1,94 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_MOCK_TESTUTIL_H_
+#define _HDFS_LIBHDFS3_MOCK_TESTUTIL_H_
+
+#include <cstddef>
+#include <cassert>
+
+#include "Logger.h"
+
+namespace Hdfs {
+
+/**
+ * Fill the buffer with "012345678\n".
+ * @param buffer The buffer to be filled.
+ * @param size The size of the buffer.
+ * @param offset Start offset of the content to be filled.
+ */
+static inline void FillBuffer(char * buffer, size_t size, size_t offset) {
+ int64_t todo = size;
+
+ char c;
+ while (todo-- > 0) {
+ c = offset++ % 10;
+ c = c < 9 ? c + '0' : '\n';
+ *buffer++ = c;
+ }
+}
+
+/**
+ * Check the content of buffer if it is filled with "012345678\n"
+ * @param buffer The buffer to be checked.
+ * @param size The size of buffer.
+ * @param offset Start offset of the content in buffer.
+ * @return Return true if the content of buffer is filled with expected data.
+ */
+static inline bool CheckBuffer(const char * buffer, size_t size,
+ size_t offset) {
+ int64_t todo = size;
+
+ char c;
+ while (todo-- > 0) {
+ c = offset++ % 10;
+ c = c < 9 ? c + '0' : '\n';
+ if (*buffer++ != c) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static inline const char * GetEnv(const char * key, const char * defaultValue) {
+ const char * retval = getenv(key);
+ if (retval && strlen(retval) > 0) {
+ return retval;
+ }
+ return defaultValue;
+}
+
+}
+
+#define DebugException(function) \
+ try { \
+ function ; \
+ } catch (const Hdfs::HdfsException & e) { \
+ std::string buffer; \
+ LOG(LOG_ERROR, "DEBUG:\n%s", Hdfs::Internal::GetExceptionDetail(e, buffer)); \
+ throw; \
+ } catch (const std::exception & e) { \
+ LOG(LOG_ERROR, "DEBUG:\n%s", e.what()); \
+ throw; \
+ }
+
+#endif
diff --git a/rpms/.gitignore b/rpms/.gitignore
new file mode 100644
index 0000000..3561700
--- /dev/null
+++ b/rpms/.gitignore
@@ -0,0 +1,7 @@
+BUILD
+BUILDROOT
+RPMS
+SOURCES
+SPECS
+SRPMS
+
diff --git a/rpms/build.sh b/rpms/build.sh
new file mode 100755
index 0000000..48c5de6
--- /dev/null
+++ b/rpms/build.sh
@@ -0,0 +1,111 @@
+#!/bin/bash
+# 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.
+#
+this_dir=`cd "\`dirname \"$0\"\`";pwd`
+top_dir=${this_dir}/../
+
+die() {
+ echo "$@" 1>&2 ; popd 2>/dev/null; exit 1
+}
+
+install_depends() {
+ yum install -y epel-release || die "cannot install epel"
+ yum install -y \
+ which make rpmdevtools gcc-c++ cmake boost-devel libxml2-devel libuuid-devel krb5-devel libgsasl-devel \
+ protobuf-devel || die "cannot install dependencies"
+}
+
+build_with_boost() {
+ pushd ${top_dir}
+ rm -rf build && mkdir -p build && cd build || die "cannot create build directory"
+ ../bootstrap --enable-boost || die "bootstrap failed"
+ make -j2 unittest || die "failed to run unit tests"
+ popd
+}
+
+build_with_debug() {
+ pushd ${top_dir}
+ rm -rf build && mkdir -p build && cd build || die "cannot create build directory"
+ ../bootstrap --enable-debug || die "bootstrap failed"
+ make -j2 unittest || die "failed to run unit tests"
+ popd
+}
+
+create_package() {
+ pushd ${top_dir}
+ rm -rf build && mkdir -p build && cd build || die "cannot create build directory"
+ ../bootstrap || die "bootstrap failed"
+ make rpm-package || die "failed to create debian package"
+ popd
+}
+
+deploy() {
+ pushd ${top_dir}
+
+ version=$(cat ${top_dir}/rpms/BUILD/version)
+
+ if [ -z "${version}" ]; then
+ die "cannot get version"
+ fi
+
+ if [ -z "${BINTRAY_KEY}" ]; then
+ die "bintray api key not set"
+ fi
+
+ message=`curl -H "X-Bintray-Publish: 1" -H "X-Bintray-Override: 1" -T ${top_dir}/rpms/RPMS/x86_64/libhdfs3-${version}-1.el7.centos.x86_64.rpm -uwangzw:${BINTRAY_KEY} \
+ https://api.bintray.com/content/wangzw/rpm/libhdfs3/${version}/centos7/x86_64/libhdfs3-${version}-1.el7.centos.x86_64.rpm`
+
+ if [ -z `echo ${message} | grep "success"` ]; then
+ echo ${message}
+ die "failed to upload libhdfs3-${version}-1.el7.centos.x86_64.rpm"
+ fi
+
+ message=`curl -H "X-Bintray-Publish: 1" -H "X-Bintray-Override: 1" -T ${top_dir}/rpms/RPMS/x86_64/libhdfs3-devel-${version}-1.el7.centos.x86_64.rpm -uwangzw:${BINTRAY_KEY} \
+ https://api.bintray.com/content/wangzw/rpm/libhdfs3/${version}/centos7/x86_64/libhdfs3-devel-${version}-1.el7.centos.x86_64.rpm`
+
+ if [ -z `echo ${message} | grep "success"` ]; then
+ echo ${message}
+ die "failed to upload libhdfs3-devel-${version}-1.el7.centos.x86_64.rpm"
+ fi
+
+ popd
+}
+
+run() {
+ install_depends || die "failed to install dependencies"
+ build_with_boost || die "build failed with boost"
+ build_with_debug || die "build failed with debug mode"
+ create_package || die "failed to create debian package"
+
+ version=$(cat ${top_dir}/rpms/BUILD/version)
+ echo "version ${version}"
+
+ if [ -z "${BRANCH}" ]; then
+ echo "skip deploy since environment variable BRANCH is not set"
+ return
+ fi
+
+ if [ "${BRANCH}" = "v${version}" ]; then
+ echo "deploy libhdfs3 version ${version}"
+ deploy || die "failed to deploy libhdfs3 rpms"
+ else
+ echo "skip deploy for branch ${BRANCH}"
+ fi
+}
+
+"$@"
diff --git a/rpms/libhdfs3.spec b/rpms/libhdfs3.spec
new file mode 100644
index 0000000..9192f3b
--- /dev/null
+++ b/rpms/libhdfs3.spec
@@ -0,0 +1,91 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+%define name libhdfs3
+%define release 1%{?dist}
+
+Name: %{name}
+Version: %{version}
+Release: %{release}
+Summary: Native C/C++ HDFS Client.
+Group: Development/Libraries
+Source0: libhdfs3-%{version}.tar.gz
+
+License: Apache-2.0
+BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
+
+BuildRequires: gcc-c++
+BuildRequires: make
+BuildRequires: cmake
+BuildRequires: libuuid-devel
+BuildRequires: libxml2-devel
+BuildRequires: krb5-devel
+BuildRequires: libgsasl-devel
+BuildRequires: protobuf-devel
+
+%description
+Libhdfs3, designed as an alternative implementation of libhdfs,
+is implemented based on native Hadoop RPC protocol and
+HDFS data transfer protocol.
+It gets rid of the drawbacks of JNI, and it has a lightweight,
+small memory footprint code base. In addition, it is easy to use and deploy.
+.
+
+%package devel
+Summary: Native C/C++ HDFS Client - development files
+Requires: %{name} = %{version}-%{release}
+Group: Development/Libraries
+Requires: libhdfs3 = %{version}-%{release}
+Requires: libuuid-devel libxml2-devel krb5-devel libgsasl-devel protobuf-devel pkgconfig
+
+%description devel
+Libhdfs3, designed as an alternative implementation of libhdfs,
+is implemented based on native Hadoop RPC protocol and
+HDFS data transfer protocol.
+It gets rid of the drawbacks of JNI, and it has a lightweight,
+small memory footprint code base. In addition, it is easy to use and deploy.
+
+%build
+%{_sourcedir}/../../bootstrap --prefix=${RPM_BUILD_ROOT}/usr
+%{__make}
+
+%install
+%{__rm} -rf $RPM_BUILD_ROOT
+%{__make} install
+
+%clean
+%{__rm} -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root,-)
+%{_prefix}/lib/lib*.so.*
+
+%files devel
+%defattr(-,root,root,-)
+%{_prefix}/lib/lib*.so
+%{_prefix}/lib/*.a
+%{_prefix}/lib/pkgconfig/*
+%{_prefix}/include/*
+
+%post
+/sbin/ldconfig
+
+%postun
+/sbin/ldconfig
+
+%changelog
+- Initial RPM release
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..fd8a241
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,2 @@
+libhdfs3.pc
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..bc20d08
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,127 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+SET(libhdfs3_VERSION_MAJOR 2)
+SET(libhdfs3_VERSION_MINOR 2)
+SET(libhdfs3_VERSION_PATCH 31)
+SET(libhdfs3_VERSION_STRING "${libhdfs3_VERSION_MAJOR}.${libhdfs3_VERSION_MINOR}.${libhdfs3_VERSION_PATCH}")
+SET(libhdfs3_VERSION_API 1)
+SET(libhdfs3_ROOT_SOURCES_DIR ${CMAKE_SOURCE_DIR}/src)
+SET(libhdfs3_COMMON_SOURCES_DIR ${libhdfs3_ROOT_SOURCES_DIR}/common)
+
+IF(ENABLE_DEBUG)
+ SET(libhdfs3_VERSION_STRING "${libhdfs3_VERSION_STRING}d")
+ENDIF(ENABLE_DEBUG)
+
+CONFIGURE_FILE(platform.h.in platform.h)
+CONFIGURE_FILE(doxyfile.in doxyfile)
+
+AUTO_SOURCES(files "*.cpp" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}")
+LIST(APPEND libhdfs3_SOURCES ${files})
+
+AUTO_SOURCES(files "*.cc" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}")
+LIST(APPEND libhdfs3_SOURCES ${files})
+
+AUTO_SOURCES(files "*.c" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}")
+LIST(APPEND libhdfs3_SOURCES ${files})
+
+AUTO_SOURCES(files "*.h" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}")
+LIST(APPEND libhdfs3_SOURCES ${files})
+
+AUTO_SOURCES(libhdfs3_PROTO_FILES "proto/*.proto" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}")
+SET(libhdfs3_PROTO_FILES ${libhdfs3_PROTO_FILES} PARENT_SCOPE)
+
+PROTOBUF_GENERATE_CPP(libhdfs3_PROTO_SOURCES libhdfs3_PROTO_HEADERS ${libhdfs3_PROTO_FILES})
+
+SET(HEADER
+ client/BlockLocation.h
+ client/DirectoryIterator.h
+ client/FileStatus.h
+ client/FileSystem.h
+ client/FileSystemStats.h
+ client/hdfs.h
+ client/InputStream.h
+ client/OutputStream.h
+ client/Permission.h
+ common/Exception.h
+ common/XmlConfig.h)
+
+ADD_LIBRARY(libhdfs3-static STATIC ${libhdfs3_SOURCES} ${libhdfs3_PROTO_SOURCES} ${libhdfs3_PROTO_HEADERS})
+ADD_LIBRARY(libhdfs3-shared SHARED ${libhdfs3_SOURCES} ${libhdfs3_PROTO_SOURCES} ${libhdfs3_PROTO_HEADERS})
+
+ADD_CUSTOM_COMMAND(
+ TARGET libhdfs3-shared libhdfs3-static
+ PRE_BUILD
+ COMMAND echo ${libhdfs3_VERSION_STRING} > version
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+)
+
+TARGET_LINK_LIBRARIES(libhdfs3-static pthread)
+TARGET_LINK_LIBRARIES(libhdfs3-shared pthread)
+
+IF(NEED_BOOST)
+ INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR})
+ TARGET_LINK_LIBRARIES(libhdfs3-static boost_thread)
+ TARGET_LINK_LIBRARIES(libhdfs3-static boost_chrono)
+ TARGET_LINK_LIBRARIES(libhdfs3-static boost_system)
+ TARGET_LINK_LIBRARIES(libhdfs3-static boost_atomic)
+ TARGET_LINK_LIBRARIES(libhdfs3-static boost_iostreams)
+ TARGET_LINK_LIBRARIES(libhdfs3-shared boost_thread)
+ TARGET_LINK_LIBRARIES(libhdfs3-shared boost_chrono)
+ TARGET_LINK_LIBRARIES(libhdfs3-shared boost_system)
+ TARGET_LINK_LIBRARIES(libhdfs3-shared boost_atomic)
+ TARGET_LINK_LIBRARIES(libhdfs3-shared boost_iostreams)
+ENDIF(NEED_BOOST)
+
+IF(NEED_GCCEH)
+ TARGET_LINK_LIBRARIES(libhdfs3-static gcc_eh)
+ TARGET_LINK_LIBRARIES(libhdfs3-shared gcc_eh)
+ENDIF(NEED_GCCEH)
+
+IF(OS_LINUX)
+ TARGET_LINK_LIBRARIES(libhdfs3-static ${LIBUUID_LIBRARIES})
+ TARGET_LINK_LIBRARIES(libhdfs3-shared ${LIBUUID_LIBRARIES})
+ INCLUDE_DIRECTORIES(${LIBUUID_INCLUDE_DIRS})
+ENDIF(OS_LINUX)
+
+INCLUDE_DIRECTORIES(${libhdfs3_ROOT_SOURCES_DIR})
+INCLUDE_DIRECTORIES(${libhdfs3_COMMON_SOURCES_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${KERBEROS_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(${GSASL_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/mock)
+
+TARGET_LINK_LIBRARIES(libhdfs3-static ${PROTOBUF_LIBRARIES})
+TARGET_LINK_LIBRARIES(libhdfs3-static ${LIBXML2_LIBRARIES})
+TARGET_LINK_LIBRARIES(libhdfs3-static ${KERBEROS_LIBRARIES})
+TARGET_LINK_LIBRARIES(libhdfs3-static ${GSASL_LIBRARIES})
+
+TARGET_LINK_LIBRARIES(libhdfs3-shared ${PROTOBUF_LIBRARIES})
+TARGET_LINK_LIBRARIES(libhdfs3-shared ${LIBXML2_LIBRARIES})
+TARGET_LINK_LIBRARIES(libhdfs3-shared ${KERBEROS_LIBRARIES})
+TARGET_LINK_LIBRARIES(libhdfs3-shared ${GSASL_LIBRARIES})
+
+SET_TARGET_PROPERTIES(libhdfs3-static PROPERTIES OUTPUT_NAME "hdfs3")
+SET_TARGET_PROPERTIES(libhdfs3-shared PROPERTIES OUTPUT_NAME "hdfs3")
+
+IF(NEED_BOOST)
+ SET_TARGET_PROPERTIES(libhdfs3-shared libhdfs3-static PROPERTIES LINK_FLAGS "-L${Boost_LIBRARY_DIRS}")
+ENDIF(NEED_BOOST)
+
+SET_TARGET_PROPERTIES(libhdfs3-shared PROPERTIES
+ VERSION ${libhdfs3_VERSION_MAJOR}.${libhdfs3_VERSION_MINOR}.${libhdfs3_VERSION_PATCH}
+ SOVERSION ${libhdfs3_VERSION_API})
+
+INSTALL(TARGETS libhdfs3-static libhdfs3-shared
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib)
+INSTALL(FILES ${HEADER} DESTINATION include/hdfs)
+INSTALL(FILES libhdfs3.pc DESTINATION lib/pkgconfig)
+
+SET(libhdfs3_SOURCES ${libhdfs3_SOURCES} PARENT_SCOPE)
+SET(libhdfs3_PLATFORM_HEADER_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
+SET(libhdfs3_ROOT_SOURCES_DIR ${libhdfs3_ROOT_SOURCES_DIR} PARENT_SCOPE)
+SET(libhdfs3_COMMON_SOURCES_DIR ${libhdfs3_COMMON_SOURCES_DIR} PARENT_SCOPE)
+SET(libhdfs3_VERSION_STRING ${libhdfs3_VERSION_STRING} PARENT_SCOPE)
diff --git a/src/client/BlockLocation.h b/src/client/BlockLocation.h
new file mode 100644
index 0000000..5fee1c4
--- /dev/null
+++ b/src/client/BlockLocation.h
@@ -0,0 +1,91 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_CLIENT_BLOCKLOCATION_H_
+#define _HDFS_LIBHDFS3_CLIENT_BLOCKLOCATION_H_
+
+#include <string>
+#include <vector>
+
+namespace Hdfs {
+
+class BlockLocation {
+public:
+ bool isCorrupt() const {
+ return corrupt;
+ }
+
+ void setCorrupt(bool corrupt) {
+ this->corrupt = corrupt;
+ }
+
+ const std::vector<std::string> & getHosts() const {
+ return hosts;
+ }
+
+ void setHosts(const std::vector<std::string> & hosts) {
+ this->hosts = hosts;
+ }
+
+ int64_t getLength() const {
+ return length;
+ }
+
+ void setLength(int64_t length) {
+ this->length = length;
+ }
+
+ const std::vector<std::string> & getNames() const {
+ return names;
+ }
+
+ void setNames(const std::vector<std::string> & names) {
+ this->names = names;
+ }
+
+ int64_t getOffset() const {
+ return offset;
+ }
+
+ void setOffset(int64_t offset) {
+ this->offset = offset;
+ }
+
+ const std::vector<std::string> & getTopologyPaths() const {
+ return topologyPaths;
+ }
+
+ void setTopologyPaths(const std::vector<std::string> & topologyPaths) {
+ this->topologyPaths = topologyPaths;
+ }
+
+private:
+ bool corrupt;
+ int64_t length;
+ int64_t offset; // Offset of the block in the file
+ std::vector<std::string> hosts; // Datanode hostnames
+ std::vector<std::string> names; // Datanode IP:xferPort for accessing the block
+ std::vector<std::string> topologyPaths; // Full path name in network topology
+};
+
+}
+
+#endif /* _HDFS_LIBHDFS3_CLIENT_BLOCKLOCATION_H_ */
diff --git a/src/client/BlockReader.h b/src/client/BlockReader.h
new file mode 100644
index 0000000..35f3fe6
--- /dev/null
+++ b/src/client/BlockReader.h
@@ -0,0 +1,60 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_CLIENT_BLOCKREADER_H_
+#define _HDFS_LIBHDFS3_CLIENT_BLOCKREADER_H_
+
+#include <stdint.h>
+
+namespace Hdfs {
+namespace Internal {
+
+class BlockReader {
+public:
+ virtual ~BlockReader() {
+ }
+
+ /**
+ * Get how many bytes can be read without blocking.
+ * @return The number of bytes can be read without blocking.
+ */
+ virtual int64_t available() = 0;
+
+ /**
+ * To read data from block.
+ * @param buf the buffer used to filled.
+ * @param size the number of bytes to be read.
+ * @return return the number of bytes filled in the buffer,
+ * it may less than size. Return 0 if reach the end of block.
+ */
+ virtual int32_t read(char * buf, int32_t size) = 0;
+
+ /**
+ * Move the cursor forward len bytes.
+ * @param len The number of bytes to skip.
+ */
+ virtual void skip(int64_t len) = 0;
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_CLIENT_BLOCKREADER_H_ */
diff --git a/src/client/DataTransferProtocol.h b/src/client/DataTransferProtocol.h
new file mode 100644
index 0000000..d45c264
--- /dev/null
+++ b/src/client/DataTransferProtocol.h
@@ -0,0 +1,117 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS_3_CLIENT_DATATRANSFERPROTOCOL_H_
+#define _HDFS_LIBHDFS_3_CLIENT_DATATRANSFERPROTOCOL_H_
+
+#include "client/Token.h"
+#include "server/DatanodeInfo.h"
+#include "server/ExtendedBlock.h"
+
+#include <vector>
+
+namespace Hdfs {
+namespace Internal {
+
+/**
+ * Transfer data to/from datanode using a streaming protocol.
+ */
+class DataTransferProtocol {
+public:
+ virtual ~DataTransferProtocol() {
+ }
+ /**
+ * Read a block.
+ *
+ * @param blk the block being read.
+ * @param blockToken security token for accessing the block.
+ * @param clientName client's name.
+ * @param blockOffset offset of the block.
+ * @param length maximum number of bytes for this read.
+ */
+ virtual void readBlock(const ExtendedBlock & blk,
+ const Token & blockToken, const char * clientName,
+ int64_t blockOffset, int64_t length) = 0;
+
+ /**
+ * Write a block to a datanode pipeline.
+ *
+ * @param blk the block being written.
+ * @param blockToken security token for accessing the block.
+ * @param clientName client's name.
+ * @param targets target datanodes in the pipeline.
+ * @param source source datanode.
+ * @param stage pipeline stage.
+ * @param pipelineSize the size of the pipeline.
+ * @param minBytesRcvd minimum number of bytes received.
+ * @param maxBytesRcvd maximum number of bytes received.
+ * @param latestGenerationStamp the latest generation stamp of the block.
+ */
+ virtual void writeBlock(const ExtendedBlock & blk,
+ const Token & blockToken, const char * clientName,
+ const std::vector<DatanodeInfo> & targets, int stage,
+ int pipelineSize, int64_t minBytesRcvd, int64_t maxBytesRcvd,
+ int64_t latestGenerationStamp, int checksumType,
+ int bytesPerChecksum) = 0;
+
+ /**
+ * Transfer a block to another datanode.
+ * The block stage must be
+ * either {@link BlockConstructionStage#TRANSFER_RBW}
+ * or {@link BlockConstructionStage#TRANSFER_FINALIZED}.
+ *
+ * @param blk the block being transferred.
+ * @param blockToken security token for accessing the block.
+ * @param clientName client's name.
+ * @param targets target datanodes.
+ */
+ virtual void transferBlock(const ExtendedBlock & blk,
+ const Token & blockToken, const char * clientName,
+ const std::vector<DatanodeInfo> & targets) = 0;
+
+ /**
+ * Get block checksum (MD5 of CRC32).
+ *
+ * @param blk a block.
+ * @param blockToken security token for accessing the block.
+ * @throw HdfsIOException
+ */
+ virtual void blockChecksum(const ExtendedBlock & blk,
+ const Token & blockToken) = 0;
+
+ /**
+ * Request short circuit access file descriptors from a DataNode.
+ *
+ * @param blk The block to get file descriptors for.
+ * @param blockToken Security token for accessing the block.
+ * @param clientName client's name.
+ * @param maxVersion Maximum version of the block data the client
+ * can understand.
+ */
+ virtual void requestShortCircuitFds(const ExtendedBlock blk,
+ const Token& blockToken,
+ uint32_t maxVersion) = 0;
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS_3_CLIENT_DATATRANSFERPROTOCOL_H_ */
diff --git a/src/client/DataTransferProtocolSender.cpp b/src/client/DataTransferProtocolSender.cpp
new file mode 100644
index 0000000..ff62e9b
--- /dev/null
+++ b/src/client/DataTransferProtocolSender.cpp
@@ -0,0 +1,197 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "client/Token.h"
+#include "datatransfer.pb.h"
+#include "DataTransferProtocolSender.h"
+#include "Exception.h"
+#include "ExceptionInternal.h"
+#include "hdfs.pb.h"
+#include "Security.pb.h"
+#include "WriteBuffer.h"
+
+using namespace google::protobuf;
+
+namespace Hdfs {
+namespace Internal {
+
+static inline void Send(Socket & sock, DataTransferOp op, Message * msg,
+ int writeTimeout) {
+ WriteBuffer buffer;
+ buffer.writeBigEndian(static_cast<int16_t>(DATA_TRANSFER_VERSION));
+ buffer.write(static_cast<char>(op));
+ int msgSize = msg->ByteSize();
+ buffer.writeVarint32(msgSize);
+ char * b = buffer.alloc(msgSize);
+
+ if (!msg->SerializeToArray(b, msgSize)) {
+ THROW(HdfsIOException,
+ "DataTransferProtocolSender cannot serialize header to send buffer.");
+ }
+
+ sock.writeFully(buffer.getBuffer(0), buffer.getDataSize(0), writeTimeout);
+}
+
+static inline void BuildBaseHeader(const ExtendedBlock & block,
+ const Token & accessToken, BaseHeaderProto * header) {
+ ExtendedBlockProto * eb = header->mutable_block();
+ TokenProto * token = header->mutable_token();
+ eb->set_blockid(block.getBlockId());
+ eb->set_generationstamp(block.getGenerationStamp());
+ eb->set_numbytes(block.getNumBytes());
+ eb->set_poolid(block.getPoolId());
+ token->set_identifier(accessToken.getIdentifier());
+ token->set_password(accessToken.getPassword());
+ token->set_kind(accessToken.getKind());
+ token->set_service(accessToken.getService());
+}
+
+static inline void BuildClientHeader(const ExtendedBlock & block,
+ const Token & accessToken, const char * clientName,
+ ClientOperationHeaderProto * header) {
+ header->set_clientname(clientName);
+ BuildBaseHeader(block, accessToken, header->mutable_baseheader());
+}
+
+static inline void BuildNodeInfo(const DatanodeInfo & node,
+ DatanodeInfoProto * info) {
+ DatanodeIDProto * id = info->mutable_id();
+ id->set_hostname(node.getHostName());
+ id->set_infoport(node.getInfoPort());
+ id->set_ipaddr(node.getIpAddr());
+ id->set_ipcport(node.getIpcPort());
+ id->set_datanodeuuid(node.getDatanodeId());
+ id->set_xferport(node.getXferPort());
+ info->set_location(node.getLocation());
+}
+
+static inline void BuildNodesInfo(const std::vector<DatanodeInfo> & nodes,
+ RepeatedPtrField<DatanodeInfoProto> * infos) {
+ for (std::size_t i = 0; i < nodes.size(); ++i) {
+ BuildNodeInfo(nodes[i], infos->Add());
+ }
+}
+
+DataTransferProtocolSender::DataTransferProtocolSender(Socket & sock,
+ int writeTimeout, const std::string & datanodeAddr) :
+ sock(sock), writeTimeout(writeTimeout), datanode(datanodeAddr) {
+}
+
+DataTransferProtocolSender::~DataTransferProtocolSender() {
+}
+
+void DataTransferProtocolSender::readBlock(const ExtendedBlock & blk,
+ const Token & blockToken, const char * clientName,
+ int64_t blockOffset, int64_t length) {
+ try {
+ OpReadBlockProto op;
+ op.set_len(length);
+ op.set_offset(blockOffset);
+ BuildClientHeader(blk, blockToken, clientName, op.mutable_header());
+ Send(sock, READ_BLOCK, &op, writeTimeout);
+ } catch (const HdfsCanceled & e) {
+ throw;
+ } catch (const HdfsException & e) {
+ NESTED_THROW(HdfsIOException,
+ "DataTransferProtocolSender cannot send read request to datanode %s.",
+ datanode.c_str());
+ }
+}
+
+void DataTransferProtocolSender::writeBlock(const ExtendedBlock & blk,
+ const Token & blockToken, const char * clientName,
+ const std::vector<DatanodeInfo> & targets, int stage, int pipelineSize,
+ int64_t minBytesRcvd, int64_t maxBytesRcvd,
+ int64_t latestGenerationStamp, int checksumType, int bytesPerChecksum) {
+ try {
+ OpWriteBlockProto op;
+ op.set_latestgenerationstamp(latestGenerationStamp);
+ op.set_minbytesrcvd(minBytesRcvd);
+ op.set_maxbytesrcvd(maxBytesRcvd);
+ op.set_pipelinesize(targets.size());
+ op.set_stage((OpWriteBlockProto_BlockConstructionStage) stage);
+ BuildClientHeader(blk, blockToken, clientName, op.mutable_header());
+ ChecksumProto * ck = op.mutable_requestedchecksum();
+ ck->set_bytesperchecksum(bytesPerChecksum);
+ ck->set_type((ChecksumTypeProto) checksumType);
+ BuildNodesInfo(targets, op.mutable_targets());
+ Send(sock, WRITE_BLOCK, &op, writeTimeout);
+ } catch (const HdfsCanceled & e) {
+ throw;
+ } catch (const HdfsException & e) {
+ NESTED_THROW(HdfsIOException,
+ "DataTransferProtocolSender cannot send write request to datanode %s.",
+ datanode.c_str());
+ }
+}
+
+void DataTransferProtocolSender::transferBlock(const ExtendedBlock & blk,
+ const Token & blockToken, const char * clientName,
+ const std::vector<DatanodeInfo> & targets) {
+ try {
+ OpTransferBlockProto op;
+ BuildClientHeader(blk, blockToken, clientName, op.mutable_header());
+ BuildNodesInfo(targets, op.mutable_targets());
+ Send(sock, TRANSFER_BLOCK, &op, writeTimeout);
+ } catch (const HdfsCanceled & e) {
+ throw;
+ } catch (const HdfsException & e) {
+ NESTED_THROW(HdfsIOException,
+ "DataTransferProtocolSender cannot send transfer request to datanode %s.",
+ datanode.c_str());
+ }
+}
+
+void DataTransferProtocolSender::blockChecksum(const ExtendedBlock & blk,
+ const Token & blockToken) {
+ try {
+ //TODO
+ } catch (const HdfsCanceled & e) {
+ throw;
+ } catch (const HdfsException & e) {
+ NESTED_THROW(HdfsIOException,
+ "DataTransferProtocolSender cannot send checksum request to datanode %s.",
+ datanode.c_str());
+ }
+}
+
+void DataTransferProtocolSender::requestShortCircuitFds(const ExtendedBlock blk,
+ const Token& blockToken,
+ uint32_t maxVersion) {
+ try {
+ OpRequestShortCircuitAccessProto op;
+ BuildBaseHeader(blk, blockToken, op.mutable_header());
+ op.set_maxversion(maxVersion);
+
+ Send(sock, REQUEST_SHORT_CIRCUIT_FDS, &op, writeTimeout);
+ } catch (const HdfsCanceled& e) {
+ throw;
+ } catch (const HdfsException& e) {
+ NESTED_THROW(HdfsIOException,
+ "DataTransferProtocolSender cannot send request "
+ "short-circuit fds request "
+ "to datanode %s.",
+ datanode.c_str());
+ }
+}
+}
+}
+
diff --git a/src/client/DataTransferProtocolSender.h b/src/client/DataTransferProtocolSender.h
new file mode 100644
index 0000000..41ad8f0
--- /dev/null
+++ b/src/client/DataTransferProtocolSender.h
@@ -0,0 +1,137 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS_3_CLIENT_DATATRANSFERPROTOCOLSENDER_H_
+#define _HDFS_LIBHDFS_3_CLIENT_DATATRANSFERPROTOCOLSENDER_H_
+
+#include "DataTransferProtocol.h"
+#include "network/Socket.h"
+
+/**
+ * Version 28:
+ * Declare methods in DataTransferProtocol interface.
+ */
+#define DATA_TRANSFER_VERSION 28
+
+namespace Hdfs {
+namespace Internal {
+
+enum DataTransferOp {
+ WRITE_BLOCK = 80,
+ READ_BLOCK = 81,
+ READ_METADATA = 82,
+ REPLACE_BLOCK = 83,
+ COPY_BLOCK = 84,
+ BLOCK_CHECKSUM = 85,
+ TRANSFER_BLOCK = 86,
+ REQUEST_SHORT_CIRCUIT_FDS = 87,
+ RELEASE_SHORT_CIRCUIT_FDS = 88
+};
+
+/**
+ * Transfer data to/from datanode using a streaming protocol.
+ */
+class DataTransferProtocolSender: public DataTransferProtocol {
+public:
+ DataTransferProtocolSender(Socket & sock, int writeTimeout,
+ const std::string & datanodeAddr);
+
+ virtual ~DataTransferProtocolSender();
+
+ /**
+ * Read a block.
+ *
+ * @param blk the block being read.
+ * @param blockToken security token for accessing the block.
+ * @param clientName client's name.
+ * @param blockOffset offset of the block.
+ * @param length maximum number of bytes for this read.
+ */
+ virtual void readBlock(const ExtendedBlock & blk, const Token & blockToken,
+ const char * clientName, int64_t blockOffset, int64_t length);
+
+ /**
+ * Write a block to a datanode pipeline.
+ *
+ * @param blk the block being written.
+ * @param blockToken security token for accessing the block.
+ * @param clientName client's name.
+ * @param targets target datanodes in the pipeline.
+ * @param source source datanode.
+ * @param stage pipeline stage.
+ * @param pipelineSize the size of the pipeline.
+ * @param minBytesRcvd minimum number of bytes received.
+ * @param maxBytesRcvd maximum number of bytes received.
+ * @param latestGenerationStamp the latest generation stamp of the block.
+ */
+ virtual void writeBlock(const ExtendedBlock & blk, const Token & blockToken,
+ const char * clientName, const std::vector<DatanodeInfo> & targets,
+ int stage, int pipelineSize, int64_t minBytesRcvd,
+ int64_t maxBytesRcvd, int64_t latestGenerationStamp,
+ int checksumType, int bytesPerChecksum);
+
+ /**
+ * Transfer a block to another datanode.
+ * The block stage must be
+ * either {@link BlockConstructionStage#TRANSFER_RBW}
+ * or {@link BlockConstructionStage#TRANSFER_FINALIZED}.
+ *
+ * @param blk the block being transferred.
+ * @param blockToken security token for accessing the block.
+ * @param clientName client's name.
+ * @param targets target datanodes.
+ */
+ virtual void transferBlock(const ExtendedBlock & blk,
+ const Token & blockToken, const char * clientName,
+ const std::vector<DatanodeInfo> & targets);
+
+ /**
+ * Get block checksum (MD5 of CRC32).
+ *
+ * @param blk a block.
+ * @param blockToken security token for accessing the block.
+ * @throw HdfsIOException
+ */
+ virtual void blockChecksum(const ExtendedBlock & blk,
+ const Token & blockToken);
+
+ /**
+ * Request short circuit access file descriptors from a DataNode.
+ *
+ * @param blk The block to get file descriptors for.
+ * @param blockToken Security token for accessing the block.
+ * @param maxVersion Maximum version of the block data the client
+ * can understand.
+ */
+ virtual void requestShortCircuitFds(const ExtendedBlock blk,
+ const Token& blockToken,
+ uint32_t maxVersion);
+
+private:
+ Socket & sock;
+ int writeTimeout;
+ std::string datanode;
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS_3_CLIENT_DATATRANSFERPROTOCOLSENDER_H_ */
diff --git a/src/client/DirectoryIterator.cpp b/src/client/DirectoryIterator.cpp
new file mode 100644
index 0000000..40b39a4
--- /dev/null
+++ b/src/client/DirectoryIterator.cpp
@@ -0,0 +1,94 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "DirectoryIterator.h"
+#include "FileStatus.h"
+#include "Exception.h"
+#include "ExceptionInternal.h"
+#include "FileSystemImpl.h"
+
+namespace Hdfs {
+
+DirectoryIterator::DirectoryIterator() :
+ needLocations(false), filesystem(NULL), next(0) {
+}
+
+DirectoryIterator::DirectoryIterator(Hdfs::Internal::FileSystemImpl * const fs,
+ std::string path, bool needLocations) :
+ needLocations(needLocations), filesystem(fs), next(0), path(path) {
+}
+
+DirectoryIterator::DirectoryIterator(const DirectoryIterator & it) :
+ needLocations(it.needLocations), filesystem(it.filesystem), next(it.next), path(it.path), startAfter(
+ it.startAfter), lists(it.lists) {
+}
+
+DirectoryIterator & DirectoryIterator::operator =(const DirectoryIterator & it) {
+ if (this == &it) {
+ return *this;
+ }
+
+ needLocations = it.needLocations;
+ filesystem = it.filesystem;
+ next = it.next;
+ path = it.path;
+ startAfter = it.startAfter;
+ lists = it.lists;
+ return *this;
+}
+
+bool DirectoryIterator::getListing() {
+ bool more;
+
+ if (NULL == filesystem) {
+ return false;
+ }
+
+ next = 0;
+ lists.clear();
+ more = filesystem->getListing(path, startAfter, needLocations, lists);
+
+ if (!lists.empty()) {
+ startAfter = lists.back().getPath();
+ }
+
+ return more || !lists.empty();
+}
+
+bool DirectoryIterator::hasNext() {
+ if (next >= lists.size()) {
+ return getListing();
+ }
+
+ return true;
+}
+
+Hdfs::FileStatus DirectoryIterator::getNext() {
+ if (next >= lists.size()) {
+ if (!getListing()) {
+ THROW(HdfsIOException, "End of the dir flow");
+ }
+ }
+
+ return lists[next++];
+}
+
+}
diff --git a/src/client/DirectoryIterator.h b/src/client/DirectoryIterator.h
new file mode 100644
index 0000000..932f086
--- /dev/null
+++ b/src/client/DirectoryIterator.h
@@ -0,0 +1,57 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHFDS3_CLIENT_DIRECTORY_ITERATOR_H_
+#define _HDFS_LIBHFDS3_CLIENT_DIRECTORY_ITERATOR_H_
+
+#include "FileStatus.h"
+#include <vector>
+
+namespace Hdfs {
+namespace Internal {
+class FileSystemImpl;
+}
+
+class DirectoryIterator {
+public:
+ DirectoryIterator();
+ DirectoryIterator(Hdfs::Internal::FileSystemImpl * const fs,
+ std::string path, bool needLocations);
+ DirectoryIterator(const DirectoryIterator & it);
+ DirectoryIterator & operator = (const DirectoryIterator & it);
+ bool hasNext();
+ FileStatus getNext();
+
+private:
+ bool getListing();
+
+private:
+ bool needLocations;
+ Hdfs::Internal::FileSystemImpl * filesystem;
+ size_t next;
+ std::string path;
+ std::string startAfter;
+ std::vector<FileStatus> lists;
+};
+
+}
+
+#endif /* _HDFS_LIBHFDS3_CLIENT_DIRECTORY_ITERATOR_H_ */
diff --git a/src/client/EncryptionZoneInfo.h b/src/client/EncryptionZoneInfo.h
new file mode 100644
index 0000000..d436ae7
--- /dev/null
+++ b/src/client/EncryptionZoneInfo.h
@@ -0,0 +1,80 @@
+/**
+ * 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 _HDFS_LIBHDFS3_CLIENT_ENCRYPTIONZONEINFO_H_
+#define _HDFS_LIBHDFS3_CLIENT_ENCRYPTIONZONEINFO_H_
+
+#include <string>
+
+namespace Hdfs {
+
+class EncryptionZoneInfo {
+public:
+ EncryptionZoneInfo() :
+ suite(0), cryptoProtocolVersion(0), id(0) {
+ }
+
+ int getSuite() const {
+ return suite;
+ }
+
+ void setSuite(int suite) {
+ this->suite = suite;
+ }
+
+ int getCryptoProtocolVersion() const {
+ return cryptoProtocolVersion;
+ }
+
+ void setCryptoProtocolVersion(int cryptoProtocolVersion) {
+ this->cryptoProtocolVersion = cryptoProtocolVersion;
+ }
+
+ int getId() const {
+ return id;
+ }
+
+ void setId(int id) {
+ this->id = id;
+ }
+
+ const char * getPath() const{
+ return path.c_str();
+ }
+
+ void setPath(const char * path){
+ this->path = path;
+ }
+
+ const char * getKeyName() const{
+ return keyName.c_str();
+ }
+
+ void setKeyName(const char * keyName){
+ this->keyName = keyName;
+ }
+
+private:
+ int suite;
+ int cryptoProtocolVersion;
+ int64_t id;
+ std::string path;
+ std::string keyName;
+};
+
+}
+#endif
diff --git a/src/client/EncryptionZoneIterator.cpp b/src/client/EncryptionZoneIterator.cpp
new file mode 100644
index 0000000..085541a
--- /dev/null
+++ b/src/client/EncryptionZoneIterator.cpp
@@ -0,0 +1,86 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "EncryptionZoneIterator.h"
+#include "Exception.h"
+#include "ExceptionInternal.h"
+#include "EncryptionZoneInfo.h"
+#include "FileSystemImpl.h"
+
+namespace Hdfs {
+EncryptionZoneIterator::EncryptionZoneIterator() :filesystem(NULL), id(0), next(0) {
+}
+
+EncryptionZoneIterator::EncryptionZoneIterator(Hdfs::Internal::FileSystemImpl * const fs,
+ const int64_t id) :filesystem(fs), id(id), next(0) {
+}
+
+EncryptionZoneIterator::EncryptionZoneIterator(const EncryptionZoneIterator & it) :
+ filesystem(it.filesystem), id(it.id), next(it.next), lists(it.lists) {
+}
+
+EncryptionZoneIterator & EncryptionZoneIterator::operator =(const EncryptionZoneIterator & it) {
+ if (this == &it) {
+ return *this;
+ }
+
+ filesystem = it.filesystem;
+ id = it.id;
+ next = it.next;
+ lists = it.lists;
+ return *this;
+}
+
+bool EncryptionZoneIterator::listEncryptionZones() {
+ bool more;
+
+ if (NULL == filesystem) {
+ return false;
+ }
+
+ next = 0;
+ lists.clear();
+ more = filesystem->listEncryptionZones(id, lists);
+ if (!lists.empty()){
+ id = lists.back().getId();
+ }
+
+ return more || !lists.empty();
+}
+
+bool EncryptionZoneIterator::hasNext() {
+ if (next >= lists.size()) {
+ return listEncryptionZones();
+ }
+
+ return true;
+}
+
+Hdfs::EncryptionZoneInfo EncryptionZoneIterator::getNext() {
+ if (next >= lists.size()) {
+ if (!listEncryptionZones()) {
+ THROW(HdfsIOException, "End of the dir flow");
+ }
+ }
+ return lists[next++];
+}
+
+}
diff --git a/src/client/EncryptionZoneIterator.h b/src/client/EncryptionZoneIterator.h
new file mode 100644
index 0000000..9e37559
--- /dev/null
+++ b/src/client/EncryptionZoneIterator.h
@@ -0,0 +1,56 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHFDS3_CLIENT_ENCRYPTIONZONE_ITERATOR_H_
+#define _HDFS_LIBHFDS3_CLIENT_ENCRYPTIONZONE_ITERATOR_H_
+
+#include "FileStatus.h"
+#include "EncryptionZoneInfo.h"
+#include <vector>
+
+namespace Hdfs {
+namespace Internal {
+class FileSystemImpl;
+}
+
+class EncryptionZoneIterator {
+public:
+ EncryptionZoneIterator();
+ EncryptionZoneIterator(Hdfs::Internal::FileSystemImpl * const fs,
+ const int64_t id);
+ EncryptionZoneIterator(const EncryptionZoneIterator & it);
+ EncryptionZoneIterator & operator = (const EncryptionZoneIterator & it);
+ bool hasNext();
+ EncryptionZoneInfo getNext();
+
+private:
+ bool listEncryptionZones();
+
+private:
+ Hdfs::Internal::FileSystemImpl * filesystem;
+ int64_t id;
+ size_t next;
+ std::vector<EncryptionZoneInfo> lists;
+};
+
+}
+
+#endif /* _HDFS_LIBHFDS3_CLIENT_ENCRYPTIONZONE_ITERATOR_H_ */
diff --git a/src/client/FileEncryptionInfo.h b/src/client/FileEncryptionInfo.h
new file mode 100644
index 0000000..32ead6c
--- /dev/null
+++ b/src/client/FileEncryptionInfo.h
@@ -0,0 +1,93 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_CLIENT_FILEENCRYPTIONINFO_H_
+#define _HDFS_LIBHDFS3_CLIENT_FILEENCRYPTIONINFO_H_
+
+#include <string>
+
+namespace Hdfs {
+
+class FileEncryptionInfo {
+public:
+ FileEncryptionInfo() :
+ cryptoProtocolVersion(0), suite(0){
+ }
+
+ int getSuite() const {
+ return suite;
+ }
+
+ void setSuite(int suite) {
+ this->suite = suite;
+ }
+
+ int getCryptoProtocolVersion() const {
+ return cryptoProtocolVersion;
+ }
+
+ void setCryptoProtocolVersion(int cryptoProtocolVersion) {
+ this->cryptoProtocolVersion = cryptoProtocolVersion;
+ }
+
+ const std::string & getKey() const{
+ return key;
+ }
+
+ void setKey(const std::string & key){
+ this->key = key;
+ }
+
+ const std::string & getKeyName() const{
+ return keyName;
+ }
+
+ void setKeyName(const std::string & keyName){
+ this->keyName = keyName;
+ }
+
+ const std::string & getIv() const{
+ return iv;
+ }
+
+ void setIv(const std::string & iv){
+ this->iv = iv;
+ }
+
+ const std::string & getEzKeyVersionName() const{
+ return ezKeyVersionName;
+ }
+
+ void setEzKeyVersionName(const std::string & ezKeyVersionName){
+ this->ezKeyVersionName = ezKeyVersionName;
+ }
+
+private:
+ int suite;
+ int cryptoProtocolVersion;
+ std::string key;
+ std::string iv;
+ std::string keyName;
+ std::string ezKeyVersionName;
+};
+
+}
+#endif
diff --git a/src/client/FileStatus.h b/src/client/FileStatus.h
new file mode 100644
index 0000000..1033b80
--- /dev/null
+++ b/src/client/FileStatus.h
@@ -0,0 +1,178 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_CLIENT_FILESTATUS_H_
+#define _HDFS_LIBHDFS3_CLIENT_FILESTATUS_H_
+
+#include "Permission.h"
+#include "client/FileEncryptionInfo.h"
+
+#include <string.h>
+
+namespace Hdfs {
+
+class FileStatus {
+public:
+ FileStatus() :
+ isdir(false), atime(0), blocksize(0), length(0), mtime(
+ 0), permission(0644), replications(0) {
+ }
+
+ int64_t getAccessTime() const {
+ return atime;
+ }
+
+ void setAccessTime(int64_t accessTime) {
+ atime = accessTime;
+ }
+
+ short getReplication() const {
+ return replications;
+ }
+
+ void setReplication(short blockReplication) {
+ replications = blockReplication;
+ }
+
+ int64_t getBlockSize() const {
+ return blocksize;
+ }
+
+ void setBlocksize(int64_t blocksize) {
+ this->blocksize = blocksize;
+ }
+
+ const char * getGroup() const {
+ return group.c_str();
+ }
+
+ void setGroup(const char * group) {
+ this->group = group;
+ }
+
+ /**
+ * Is this a directory?
+ * @return true if this is a directory
+ */
+ bool isDirectory() const {
+ return isdir;
+ }
+
+ void setIsdir(bool isdir) {
+ this->isdir = isdir;
+ }
+
+ int64_t getLength() const {
+ return length;
+ }
+
+ void setLength(int64_t length) {
+ this->length = length;
+ }
+
+ int64_t getModificationTime() const {
+ return mtime;
+ }
+
+ void setModificationTime(int64_t modificationTime) {
+ mtime = modificationTime;
+ }
+
+ const char * getOwner() const {
+ return owner.c_str();
+ }
+
+ void setOwner(const char * owner) {
+ this->owner = owner;
+ }
+
+ const char * getPath() const {
+ return path.c_str();
+ }
+
+ void setPath(const char * path) {
+ this->path = path;
+ }
+
+ const Permission & getPermission() const {
+ return permission;
+ }
+
+ void setPermission(const Permission & permission) {
+ this->permission = permission;
+ }
+
+ const char * getSymlink() const {
+ return symlink.c_str();
+ }
+
+ void setSymlink(const char * symlink) {
+ this->symlink = symlink;
+ }
+
+ /**
+ * Is this a file?
+ * @return true if this is a file
+ */
+ bool isFile() {
+ return !isdir && !isSymlink();
+ }
+
+ /**
+ * Is this a symbolic link?
+ * @return true if this is a symbolic link
+ */
+ bool isSymlink() {
+ return !symlink.empty();
+ }
+
+ /**
+ * Get encryption information for a file.
+ */
+ FileEncryptionInfo* getFileEncryption(){
+ return &fileEncryption;
+ }
+
+ /**
+ * Is an encryption file?
+ * @return true is this is an encryption file
+ */
+ bool isFileEncrypted() const {
+ return fileEncryption.getKey().length() > 0 && fileEncryption.getKeyName().length() > 0;
+ }
+
+private:
+ bool isdir;
+ int64_t atime;
+ int64_t blocksize;
+ int64_t length;
+ int64_t mtime;
+ Permission permission;
+ short replications;
+ std::string group;
+ std::string owner;
+ std::string path;
+ std::string symlink;
+ FileEncryptionInfo fileEncryption;
+};
+
+}
+#endif
diff --git a/src/client/FileSystem.cpp b/src/client/FileSystem.cpp
new file mode 100644
index 0000000..8c18590
--- /dev/null
+++ b/src/client/FileSystem.cpp
@@ -0,0 +1,639 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "DirectoryIterator.h"
+#include "EncryptionZoneIterator.h"
+#include "Exception.h"
+#include "ExceptionInternal.h"
+#include "FileSystem.h"
+#include "FileSystemImpl.h"
+#include "FileSystemKey.h"
+#include "Hash.h"
+#include "SessionConfig.h"
+#include "Thread.h"
+#include "Token.h"
+#include "Unordered.h"
+#include "WritableUtils.h"
+
+#include <algorithm>
+#include <string>
+#include <krb5/krb5.h>
+
+using namespace Hdfs::Internal;
+
+namespace Hdfs {
+
+namespace Internal {
+
+static std::string ExtractPrincipalFromTicketCache(
+ const std::string & cachePath) {
+ krb5_context cxt = NULL;
+ krb5_ccache ccache = NULL;
+ krb5_principal principal = NULL;
+ krb5_error_code ec = 0;
+ std::string errmsg, retval;
+ char * priName = NULL;
+
+ if (!cachePath.empty()) {
+ if (0 != setenv("KRB5CCNAME", cachePath.c_str(), 1)) {
+ THROW(HdfsIOException, "Cannot set env parameter \"KRB5CCNAME\"");
+ }
+ }
+
+ do {
+ if (0 != (ec = krb5_init_context(&cxt))) {
+ break;
+ }
+
+ if (0 != (ec = krb5_cc_default(cxt, &ccache))) {
+ break;
+ }
+
+ if (0 != (ec = krb5_cc_get_principal(cxt, ccache, &principal))) {
+ break;
+ }
+
+ if (0 != (ec = krb5_unparse_name(cxt, principal, &priName))) {
+ break;
+ }
+ } while (0);
+
+ if (!ec) {
+ retval = priName;
+ } else {
+ if (cxt) {
+ errmsg = krb5_get_error_message(cxt, ec);
+ } else {
+ errmsg = "Cannot initialize kerberos context";
+ }
+ }
+
+ if (priName != NULL) {
+ krb5_free_unparsed_name(cxt, priName);
+ }
+
+ if (principal != NULL) {
+ krb5_free_principal(cxt, principal);
+ }
+
+ if (ccache != NULL) {
+ krb5_cc_close(cxt, ccache);
+ }
+
+ if (cxt != NULL) {
+ krb5_free_context(cxt);
+ }
+
+ if (!errmsg.empty()) {
+ THROW(HdfsIOException,
+ "FileSystem: Failed to extract principal from ticket cache: %s",
+ errmsg.c_str());
+ }
+
+ return retval;
+}
+
+
+static std::string ExtractPrincipalFromToken(const Token & token) {
+ std::string realUser, owner;
+ std::string identifier = token.getIdentifier();
+ WritableUtils cin(&identifier[0], identifier.size());
+ char version;
+
+ try {
+ version = cin.readByte();
+
+ if (version != 0) {
+ THROW(HdfsIOException, "Unknown version of delegation token");
+ }
+
+ owner = cin.ReadText();
+ cin.ReadText();
+ realUser = cin.ReadText();
+ return realUser.empty() ? owner : realUser;
+ } catch (const std::range_error & e) {
+ }
+
+ THROW(HdfsIOException, "Cannot extract principal from token");
+}
+}
+
+FileSystem::FileSystem(const Config & conf) :
+ conf(conf), impl(NULL) {
+}
+
+FileSystem::FileSystem(const FileSystem & other) :
+ conf(other.conf), impl(NULL) {
+ if (other.impl) {
+ impl = new FileSystemWrapper(other.impl->filesystem);
+ }
+}
+
+FileSystem & FileSystem::operator =(const FileSystem & other) {
+ if (this == &other) {
+ return *this;
+ }
+
+ conf = other.conf;
+
+ if (impl) {
+ delete impl;
+ impl = NULL;
+ }
+
+ if (other.impl) {
+ impl = new FileSystemWrapper(other.impl->filesystem);
+ }
+
+ return *this;
+}
+
+FileSystem::~FileSystem() {
+ if (impl) {
+ try {
+ disconnect();
+ } catch (...) {
+ }
+ }
+}
+
+void FileSystem::connect() {
+ Internal::SessionConfig sconf(conf);
+ connect(sconf.getDefaultUri().c_str(), NULL, NULL);
+}
+
+/**
+ * Connect to hdfs
+ * @param uri hdfs connection uri, hdfs://host:port
+ */
+void FileSystem::connect(const char * uri) {
+ connect(uri, NULL, NULL);
+}
+
+static FileSystemWrapper * ConnectInternal(const char * uri,
+ const std::string & principal, const Token * token, Config & conf) {
+ if (NULL == uri || 0 == strlen(uri)) {
+ THROW(InvalidParameter, "Invalid HDFS uri.");
+ }
+
+ FileSystemKey key(uri, principal.c_str());
+
+ if (token) {
+ key.addToken(*token);
+ }
+
+ return new FileSystemWrapper(shared_ptr<FileSystemInter>(new FileSystemImpl(key, conf)));
+}
+
+/**
+ * Connect to hdfs with user or token
+ * username and token cannot be set at the same time
+ * @param uri connection uri.
+ * @param username user used to connect to hdfs
+ * @param token token used to connect to hdfs
+ */
+void FileSystem::connect(const char * uri, const char * username, const char * token) {
+ AuthMethod auth;
+ std::string principal;
+
+ if (impl) {
+ THROW(HdfsIOException, "FileSystem: already connected.");
+ }
+
+ try {
+ SessionConfig sconf(conf);
+ auth = RpcAuth::ParseMethod(sconf.getRpcAuthMethod());
+
+ if (token && auth != AuthMethod::SIMPLE) {
+ Token t;
+ t.fromString(token);
+ principal = ExtractPrincipalFromToken(t);
+ impl = ConnectInternal(uri, principal, &t, conf);
+ impl->filesystem->connect();
+ return;
+ } else if (username) {
+ principal = username;
+ }
+
+ if (auth == AuthMethod::KERBEROS) {
+ principal = ExtractPrincipalFromTicketCache(sconf.getKerberosCachePath());
+ }
+
+ impl = ConnectInternal(uri, principal, NULL, conf);
+ impl->filesystem->connect();
+ } catch (...) {
+ delete impl;
+ impl = NULL;
+ throw;
+ }
+}
+
+/**
+ * disconnect from hdfs
+ */
+void FileSystem::disconnect() {
+ delete impl;
+ impl = NULL;
+}
+
+/**
+ * To get default number of replication.
+ * @return the default number of replication.
+ */
+int FileSystem::getDefaultReplication() const {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->getDefaultReplication();
+}
+
+/**
+ * To get the default number of block size.
+ * @return the default block size.
+ */
+int64_t FileSystem::getDefaultBlockSize() const {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->getDefaultBlockSize();
+}
+
+/**
+ * To get the home directory.
+ * @return home directory.
+ */
+std::string FileSystem::getHomeDirectory() const {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->getHomeDirectory();
+}
+
+/**
+ * To delete a file or directory.
+ * @param path the path to be deleted.
+ * @param recursive if path is a directory, delete the contents recursively.
+ * @return return true if success.
+ */
+bool FileSystem::deletePath(const char * path, bool recursive) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->deletePath(path, recursive);
+}
+
+/**
+ * To create a directory which given permission.
+ * @param path the directory path which is to be created.
+ * @param permission directory permission.
+ * @return return true if success.
+ */
+bool FileSystem::mkdir(const char * path, const Permission & permission) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->mkdir(path, permission);
+}
+
+/**
+ * To create a directory which given permission.
+ * If parent path does not exits, create it.
+ * @param path the directory path which is to be created.
+ * @param permission directory permission.
+ * @return return true if success.
+ */
+bool FileSystem::mkdirs(const char * path, const Permission & permission) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->mkdirs(path, permission);
+}
+
+/**
+ * To get path information.
+ * @param path the path which information is to be returned.
+ * @return the path information.
+ */
+FileStatus FileSystem::getFileStatus(const char * path) const {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->getFileStatus(path);
+}
+
+/**
+ * Return an array containing hostnames, offset and size of
+ * portions of the given file.
+ *
+ * This call is most helpful with DFS, where it returns
+ * hostnames of machines that contain the given file.
+ *
+ * The FileSystem will simply return an elt containing 'localhost'.
+ *
+ * @param path path is used to identify an FS since an FS could have
+ * another FS that it could be delegating the call to
+ * @param start offset into the given file
+ * @param len length for which to get locations for
+ */
+std::vector<BlockLocation> FileSystem::getFileBlockLocations(const char * path,
+ int64_t start, int64_t len) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->getFileBlockLocations(path, start, len);
+}
+
+/**
+ * list the contents of a directory.
+ * @param path the directory path.
+ * @return Return a iterator to visit all elements in this directory.
+ */
+DirectoryIterator FileSystem::listDirectory(const char * path) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->listDirectory(path, false);
+}
+
+/**
+ * list all the contents of a directory.
+ * @param path The directory path.
+ * @return Return a vector of file informations in the directory.
+ */
+std::vector<FileStatus> FileSystem::listAllDirectoryItems(const char * path) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->listAllDirectoryItems(path, false);
+}
+
+/**
+ * To set the owner and the group of the path.
+ * username and groupname cannot be empty at the same time.
+ * @param path the path which owner of group is to be changed.
+ * @param username new user name.
+ * @param groupname new group.
+ */
+void FileSystem::setOwner(const char * path, const char * username,
+ const char * groupname) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ impl->filesystem->setOwner(path, username, groupname);
+}
+
+/**
+ * To set the access time or modification time of a path.
+ * @param path the path which access time or modification time is to be changed.
+ * @param mtime new modification time.
+ * @param atime new access time.
+ */
+void FileSystem::setTimes(const char * path, int64_t mtime, int64_t atime) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ impl->filesystem->setTimes(path, mtime, atime);
+}
+
+/**
+ * To set the permission of a path.
+ * @param path the path which permission is to be changed.
+ * @param permission new permission.
+ */
+void FileSystem::setPermission(const char * path,
+ const Permission & permission) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ impl->filesystem->setPermission(path, permission);
+}
+
+/**
+ * To set the number of replication.
+ * @param path the path which number of replication is to be changed.
+ * @param replication new number of replication.
+ * @return return true if success.
+ */
+bool FileSystem::setReplication(const char * path, short replication) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->setReplication(path, replication);
+}
+
+/**
+ * To rename a path.
+ * @param src old path.
+ * @param dst new path.
+ * @return return true if success.
+ */
+bool FileSystem::rename(const char * src, const char * dst) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->rename(src, dst);
+}
+
+/**
+ * To set working directory.
+ * @param path new working directory.
+ */
+void FileSystem::setWorkingDirectory(const char * path) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ impl->filesystem->setWorkingDirectory(path);
+}
+
+/**
+ * To get working directory.
+ * @return working directory.
+ */
+std::string FileSystem::getWorkingDirectory() const {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->getWorkingDirectory();
+}
+
+/**
+ * To test if the path exist.
+ * @param path the path which is to be tested.
+ * @return return true if the path exist.
+ */
+bool FileSystem::exist(const char * path) const {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->exist(path);
+}
+
+/**
+ * To get the file system status.
+ * @return the file system status.
+ */
+FileSystemStats FileSystem::getStats() const {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->getFsStats();
+}
+
+/**
+ * Truncate the file in the indicated path to the indicated size.
+ * @param src The path to the file to be truncated
+ * @param size The size the file is to be truncated to
+ *
+ * @return true if and client does not need to wait for block recovery,
+ * false if client needs to wait for block recovery.
+ */
+bool FileSystem::truncate(const char * src, int64_t size) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->truncate(src, size);
+}
+
+std::string FileSystem::getDelegationToken(const char * renewer) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->getDelegationToken(renewer);
+}
+
+/**
+ * Get a valid Delegation Token using the default user as renewer.
+ *
+ * @return Token
+ * @throws IOException
+ */
+std::string FileSystem::getDelegationToken() {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->getDelegationToken();
+}
+
+/**
+ * Renew an existing delegation token.
+ *
+ * @param token delegation token obtained earlier
+ * @return the new expiration time
+ * @throws IOException
+ */
+int64_t FileSystem::renewDelegationToken(const std::string & token) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->renewDelegationToken(token);
+}
+
+/**
+ * Cancel an existing delegation token.
+ *
+ * @param token delegation token
+ * @throws IOException
+ */
+void FileSystem::cancelDelegationToken(const std::string & token) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ impl->filesystem->cancelDelegationToken(token);
+}
+
+
+/**
+ * Create encryption zone for the directory with specific key name
+ * @param path the directory path which is to be created.
+ * @param keyname The key name of the encryption zone
+ * @return return true if success.
+ */
+bool FileSystem::createEncryptionZone(const char * path, const char * keyName) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->createEncryptionZone(path, keyName);
+}
+
+/**
+* To get encryption zone information.
+* @param path the path which information is to be returned.
+* @return the encryption zone information.
+*/
+EncryptionZoneInfo FileSystem::getEZForPath(const char * path) {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->getEZForPath(path);
+}
+
+/**
+ * list the contents of an encryption zone.
+ * @return Return a iterator to visit all elements in this encryption zone.
+ */
+EncryptionZoneIterator FileSystem::listEncryptionZone() {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->listEncryptionZone();
+}
+
+/**
+* list all the contents of encryption zones.
+* @param id the index of encryption zones.
+* @return Return a vector of encryption zones information..
+*/
+std::vector<EncryptionZoneInfo> FileSystem::listAllEncryptionZoneItems() {
+ if (!impl) {
+ THROW(HdfsIOException, "FileSystem: not connected.");
+ }
+
+ return impl->filesystem->listAllEncryptionZoneItems();
+}
+
+}
diff --git a/src/client/FileSystem.h b/src/client/FileSystem.h
new file mode 100644
index 0000000..e1f4dd2
--- /dev/null
+++ b/src/client/FileSystem.h
@@ -0,0 +1,320 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_CLIENT_FILESYSTEM_H_
+#define _HDFS_LIBHDFS3_CLIENT_FILESYSTEM_H_
+
+#include "BlockLocation.h"
+#include "DirectoryIterator.h"
+#include "EncryptionZoneIterator.h"
+#include "FileStatus.h"
+#include "FileSystemStats.h"
+#include "EncryptionZoneInfo.h"
+#include "Permission.h"
+#include "XmlConfig.h"
+
+#include <vector>
+
+namespace Hdfs {
+namespace Internal {
+struct FileSystemWrapper;
+}
+
+class FileSystem {
+public:
+
+ /**
+ * Construct a FileSystem
+ * @param conf hdfs configuration
+ */
+ FileSystem(const Config & conf);
+
+ /**
+ * Copy construct of FileSystem
+ */
+ FileSystem(const FileSystem & other);
+
+ /**
+ * Assign operator of FileSystem
+ */
+ FileSystem & operator = (const FileSystem & other);
+
+ /**
+ * Destroy a HdfsFileSystem instance
+ */
+ ~FileSystem();
+
+ /**
+ * Connect to default hdfs.
+ */
+ void connect();
+
+ /**
+ * Connect to hdfs
+ * @param uri hdfs connection uri, hdfs://host:port
+ */
+ void connect(const char * uri);
+
+ /**
+ * Connect to hdfs with user or token
+ * username and token cannot be set at the same time
+ * @param uri connection uri.
+ * @param username user used to connect to hdfs
+ * @param token token used to connect to hdfs
+ */
+ void connect(const char * uri, const char * username, const char * token);
+
+ /**
+ * disconnect from hdfs
+ */
+ void disconnect();
+
+ /**
+ * To get default number of replication.
+ * @return the default number of replication.
+ */
+ int getDefaultReplication() const;
+
+ /**
+ * To get the default number of block size.
+ * @return the default block size.
+ */
+ int64_t getDefaultBlockSize() const;
+
+ /**
+ * To get the home directory.
+ * @return home directory.
+ */
+ std::string getHomeDirectory() const;
+
+ /**
+ * To delete a file or directory.
+ * @param path the path to be deleted.
+ * @param recursive if path is a directory, delete the contents recursively.
+ * @return return true if success.
+ */
+ bool deletePath(const char * path, bool recursive);
+
+ /**
+ * To create a directory which given permission.
+ * @param path the directory path which is to be created.
+ * @param permission directory permission.
+ * @return return true if success.
+ */
+ bool mkdir(const char * path, const Permission & permission);
+
+ /**
+ * To create a directory which given permission.
+ * If parent path does not exits, create it.
+ * @param path the directory path which is to be created.
+ * @param permission directory permission.
+ * @return return true if success.
+ */
+ bool mkdirs(const char * path, const Permission & permission);
+
+ /**
+ * To get path information.
+ * @param path the path which information is to be returned.
+ * @return the path information.
+ */
+ FileStatus getFileStatus(const char * path) const;
+
+ /**
+ * Return an array containing hostnames, offset and size of
+ * portions of the given file.
+ *
+ * This call is most helpful with DFS, where it returns
+ * hostnames of machines that contain the given file.
+ *
+ * The FileSystem will simply return an elt containing 'localhost'.
+ *
+ * @param path path is used to identify an FS since an FS could have
+ * another FS that it could be delegating the call to
+ * @param start offset into the given file
+ * @param len length for which to get locations for
+ */
+ std::vector<BlockLocation> getFileBlockLocations(const char * path,
+ int64_t start, int64_t len);
+
+ /**
+ * list the contents of a directory.
+ * @param path The directory path.
+ * @return Return a iterator to visit all elements in this directory.
+ */
+ DirectoryIterator listDirectory(const char * path);
+
+ /**
+ * list all the contents of a directory.
+ * @param path The directory path.
+ * @return Return a vector of file informations in the directory.
+ */
+ std::vector<FileStatus> listAllDirectoryItems(const char * path);
+
+ /**
+ * To set the owner and the group of the path.
+ * username and groupname cannot be empty at the same time.
+ * @param path the path which owner of group is to be changed.
+ * @param username new user name.
+ * @param groupname new group.
+ */
+ void setOwner(const char * path, const char * username,
+ const char * groupname);
+
+ /**
+ * To set the access time or modification time of a path.
+ * @param path the path which access time or modification time is to be changed.
+ * @param mtime new modification time.
+ * @param atime new access time.
+ */
+ void setTimes(const char * path, int64_t mtime, int64_t atime);
+
+ /**
+ * To set the permission of a path.
+ * @param path the path which permission is to be changed.
+ * @param permission new permission.
+ */
+ void setPermission(const char * path, const Permission & permission);
+
+ /**
+ * To set the number of replication.
+ * @param path the path which number of replication is to be changed.
+ * @param replication new number of replication.
+ * @return return true if success.
+ */
+ bool setReplication(const char * path, short replication);
+
+ /**
+ * To rename a path.
+ * @param src old path.
+ * @param dst new path.
+ * @return return true if success.
+ */
+ bool rename(const char * src, const char * dst);
+
+ /**
+ * To set working directory.
+ * @param path new working directory.
+ */
+ void setWorkingDirectory(const char * path);
+
+ /**
+ * To get working directory.
+ * @return working directory.
+ */
+ std::string getWorkingDirectory() const;
+
+ /**
+ * To test if the path exist.
+ * @param path the path which is to be tested.
+ * @return return true if the path exist.
+ */
+ bool exist(const char * path) const;
+
+ /**
+ * To get the file system status.
+ * @return the file system status.
+ */
+ FileSystemStats getStats() const;
+
+ /**
+ * Truncate the file in the indicated path to the indicated size.
+ * @param src The path to the file to be truncated
+ * @param size The size the file is to be truncated to
+ *
+ * @return true if and client does not need to wait for block recovery,
+ * false if client needs to wait for block recovery.
+ */
+ bool truncate(const char * src, int64_t size);
+
+ /**
+ * Get a valid Delegation Token.
+ *
+ * @param renewer the designated renewer for the token
+ * @return Token string
+ * @throws IOException
+ */
+ std::string getDelegationToken(const char * renewer);
+
+ /**
+ * Get a valid Delegation Token using the default user as renewer.
+ *
+ * @return Token string
+ * @throws IOException
+ */
+ std::string getDelegationToken();
+
+ /**
+ * Renew an existing delegation token.
+ *
+ * @param token delegation token obtained earlier
+ * @return the new expiration time
+ * @throws IOException
+ */
+ int64_t renewDelegationToken(const std::string & token);
+
+ /**
+ * Cancel an existing delegation token.
+ *
+ * @param token delegation token
+ * @throws IOException
+ */
+ void cancelDelegationToken(const std::string & token);
+
+ /**
+ * Create encryption zone for the directory with specific key name
+ * @param path the directory path which is to be created.
+ * @param keyname The key name of the encryption zone
+ * @return return true if success.
+ */
+ bool createEncryptionZone(const char * path, const char * keyName);
+
+ /**
+ * To get encryption zone information.
+ * @param path the path which information is to be returned.
+ * @return the encryption zone information.
+ */
+ EncryptionZoneInfo getEZForPath(const char * path);
+
+ /**
+ * list the contents of an encryption zone;
+ * @return Return a iterator to visit all elements in this encryption zone.
+ */
+ EncryptionZoneIterator listEncryptionZone();
+
+
+ /**
+ * list all the contents of encryption zones.
+ * @param id the index of encryption zones.
+ * @return Return a vector of encryption zones information..
+ */
+ std::vector<EncryptionZoneInfo> listAllEncryptionZoneItems();
+
+
+private:
+ Config conf;
+ Internal::FileSystemWrapper * impl;
+
+ friend class InputStream;
+ friend class OutputStream;
+};
+
+}
+#endif /* _HDFS_LIBHDFS3_CLIENT_FILESYSTEM_H_ */
diff --git a/src/client/FileSystemImpl.cpp b/src/client/FileSystemImpl.cpp
new file mode 100644
index 0000000..6ee2b91
--- /dev/null
+++ b/src/client/FileSystemImpl.cpp
@@ -0,0 +1,867 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "Atomic.h"
+#include "BlockLocation.h"
+#include "DirectoryIterator.h"
+#include "EncryptionZoneIterator.h"
+#include "Exception.h"
+#include "ExceptionInternal.h"
+#include "FileStatus.h"
+#include "FileSystemImpl.h"
+#include "FileSystemStats.h"
+#include "EncryptionZoneInfo.h"
+#include "InputStream.h"
+#include "LeaseRenewer.h"
+#include "Logger.h"
+#include "OutputStream.h"
+#include "OutputStreamImpl.h"
+#include "server/LocatedBlocks.h"
+#include "server/NamenodeInfo.h"
+#include "server/NamenodeProxy.h"
+#include "StringUtil.h"
+
+#include <cstring>
+#include <inttypes.h>
+#include <libxml/uri.h>
+#include <strings.h>
+
+namespace Hdfs {
+namespace Internal {
+
+static const std::string GetAbsPath(const std::string & prefix,
+ const std::string & path) {
+ if (path.empty()) {
+ return prefix;
+ }
+
+ if ('/' == path[0]) {
+ return path;
+ } else {
+ return prefix + "/" + path;
+ }
+}
+
+/*
+ * Return the canonical absolute name of file NAME.
+ * A canonical name does not contain any `.', `..' components nor any repeated path separators ('/')
+ */
+static const std::string CanonicalizePath(const std::string & path) {
+ int skip = 0;
+ std::string retval;
+ std::vector<std::string> components = StringSplit(path, "/");
+ std::deque<std::string> tmp;
+ std::vector<std::string>::reverse_iterator s = components.rbegin();
+
+ while (s != components.rend()) {
+ if (s->empty() || *s == ".") {
+ ++s;
+ } else if (*s == "..") {
+ ++skip;
+ ++s;
+ } else {
+ if (skip <= 0) {
+ tmp.push_front(*s);
+ } else {
+ --skip;
+ }
+
+ ++s;
+ }
+ }
+
+ for (size_t i = 0; i < tmp.size(); ++i) {
+ retval += "/";
+ retval += tmp[i];
+ }
+
+ return retval.empty() ? "/" : retval;
+}
+
+FileSystemImpl::FileSystemImpl(const FileSystemKey& key, const Config& c)
+ : conf(c),
+ key(key),
+ openedOutputStream(0),
+ nn(NULL),
+ sconf(c),
+ user(key.getUser()) {
+ static atomic<uint32_t> count(0);
+ std::stringstream ss;
+ ss.imbue(std::locale::classic());
+ srand((unsigned int) time(NULL));
+ ss << "libhdfs3_client_random_" << rand() << "_count_" << ++count << "_pid_"
+ << getpid() << "_tid_" << pthread_self();
+ clientName = ss.str();
+ workingDir = std::string("/user/") + user.getEffectiveUser();
+ peerCache = shared_ptr<PeerCache>(new PeerCache(sconf));
+#ifdef MOCK
+ stub = NULL;
+#endif
+ //set log level
+ RootLogger.setLogSeverity(sconf.getLogSeverity());
+}
+
+/**
+ * Destroy a FileSystemBase instance
+ */
+FileSystemImpl::~FileSystemImpl() {
+ try {
+ disconnect();
+ } catch (...) {
+ }
+}
+
+const std::string FileSystemImpl::getStandardPath(const char * path) {
+ std::string base;
+ {
+ lock_guard<mutex> lock(mutWorkingDir);
+ base = workingDir;
+ }
+ return CanonicalizePath(GetAbsPath(base, path));
+}
+
+const char * FileSystemImpl::getClientName() {
+ return clientName.c_str();
+}
+
+void FileSystemImpl::connect() {
+ std::string host, port, uri;
+ std::vector<NamenodeInfo> namenodeInfos;
+
+ if (nn) {
+ THROW(HdfsIOException, "FileSystemImpl: already connected.");
+ }
+
+ host = key.getHost();
+ port = key.getPort();
+ uri += key.getScheme() + "://" + host;
+
+ if (port.empty()) {
+ try {
+ namenodeInfos = NamenodeInfo::GetHANamenodeInfo(key.getHost(), conf);
+ } catch (const HdfsConfigNotFound & e) {
+ NESTED_THROW(InvalidParameter, "Cannot parse URI: %s, missing port or invalid HA configuration", uri.c_str());
+ }
+
+ tokenService = "ha-hdfs:";
+ tokenService += host;
+ } else {
+ std::stringstream ss;
+ ss.imbue(std::locale::classic());
+ ss << host << ":" << port;
+ namenodeInfos.resize(1);
+ namenodeInfos[0].setRpcAddr(ss.str());
+ tokenService = namenodeInfos[0].getRpcAddr();
+ }
+
+#ifdef MOCK
+ nn = stub->getNamenode();
+#else
+ nn = new NamenodeProxy(namenodeInfos, tokenService, sconf, RpcAuth(user, RpcAuth::ParseMethod(sconf.getRpcAuthMethod())));
+#endif
+ /*
+ * To test if the connection is ok
+ */
+ getFsStats();
+}
+
+/**
+ * disconnect from hdfs
+ */
+void FileSystemImpl::disconnect() {
+ if (nn) {
+ nn->close();
+ delete nn;
+ }
+
+ nn = NULL;
+}
+
+/**
+ * To get default number of replication.
+ * @return the default number of replication.
+ */
+int FileSystemImpl::getDefaultReplication() const {
+ return sconf.getDefaultReplica();
+}
+
+/**
+ * To get the default number of block size.
+ * @return the default block size.
+ */
+int64_t FileSystemImpl::getDefaultBlockSize() const {
+ return sconf.getDefaultBlockSize();
+}
+
+/**
+ * To get the home directory.
+ * @return home directory.
+ */
+std::string FileSystemImpl::getHomeDirectory() const {
+ return std::string("/user/") + user.getEffectiveUser();
+}
+
+/**
+ * To delete a file or directory.
+ * @param path the path to be deleted.
+ * @param recursive if path is a directory, delete the contents recursively.
+ * @return return true if success.
+ */
+
+bool FileSystemImpl::deletePath(const char * path, bool recursive) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ return nn->deleteFile(getStandardPath(path), recursive);
+}
+
+/**
+ * To create a directory which given permission.
+ * @param path the directory path which is to be created.
+ * @param permission directory permission.
+ * @return return true if success.
+ */
+
+bool FileSystemImpl::mkdir(const char * path, const Permission & permission) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ return nn->mkdirs(getStandardPath(path), permission, false);
+}
+
+/**
+ * To create a directory which given permission.
+ * If parent path does not exits, create it.
+ * @param path the directory path which is to be created.
+ * @param permission directory permission.
+ * @return return true if success.
+ */
+
+bool FileSystemImpl::mkdirs(const char * path, const Permission & permission) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ return nn->mkdirs(getStandardPath(path), permission, true);
+}
+
+/**
+ * To get path information.
+ * @param path the path which information is to be returned.
+ * @return the path information.
+ */
+FileStatus FileSystemImpl::getFileStatus(const char * path) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ return nn->getFileInfo(getStandardPath(path), NULL);
+}
+
+static void Convert(BlockLocation & bl, const LocatedBlock & lb) {
+ const std::vector<DatanodeInfo> & nodes = lb.getLocations();
+ bl.setCorrupt(lb.isCorrupt());
+ bl.setLength(lb.getNumBytes());
+ bl.setOffset(lb.getOffset());
+ std::vector<std::string> hosts(nodes.size());
+ std::vector<std::string> names(nodes.size());
+ std::vector<std::string> topologyPaths(nodes.size());
+
+ for (size_t i = 0 ; i < nodes.size() ; ++i) {
+ hosts[i] = nodes[i].getHostName();
+ names[i] = nodes[i].getXferAddr();
+ topologyPaths[i] = nodes[i].getLocation() + '/' + nodes[i].getXferAddr();
+ }
+
+ bl.setNames(names);
+ bl.setHosts(hosts);
+ bl.setTopologyPaths(topologyPaths);
+}
+
+std::vector<BlockLocation> FileSystemImpl::getFileBlockLocations(
+ const char * path, int64_t start, int64_t len) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ if (start < 0) {
+ THROW(InvalidParameter, "Invalid input: start offset should be positive");
+ }
+
+ if (len < 0) {
+ THROW(InvalidParameter, "Invalid input: length should be positive");
+ }
+
+ LocatedBlocksImpl lbs;
+ nn->getBlockLocations(getStandardPath(path), start, len, lbs);
+ std::vector<LocatedBlock> blocks = lbs.getBlocks();
+ std::vector<BlockLocation> retval(blocks.size());
+
+ for (size_t i = 0; i < blocks.size(); ++i) {
+ Convert(retval[i], blocks[i]);
+ }
+
+ return retval;
+}
+
+/**
+ * list the contents of a directory.
+ * @param path the directory path.
+ * @return return the path informations in the given directory.
+ */
+DirectoryIterator FileSystemImpl::listDirectory(const char * path,
+ bool needLocation) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ return DirectoryIterator(this, getStandardPath(path), needLocation);
+}
+
+/**
+ * list all the contents of a directory.
+ * @param path The directory path.
+ * @return Return a vector of file informations in the directory.
+ */
+std::vector<FileStatus> FileSystemImpl::listAllDirectoryItems(const char * path,
+ bool needLocation) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ std::string startAfter;
+ std::string p = getStandardPath(path);
+ std::vector<FileStatus> retval;
+
+ while (getListing(p, startAfter, needLocation, retval)) {
+ startAfter = retval.back().getPath();
+ }
+
+ return retval;
+}
+
+/**
+ * To set the owner and the group of the path.
+ * username and groupname cannot be empty at the same time.
+ * @param path the path which owner of group is to be changed.
+ * @param username new user name.
+ * @param groupname new group.
+ */
+void FileSystemImpl::setOwner(const char * path, const char * username,
+ const char * groupname) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ if ((NULL == username || !strlen(username))
+ && (NULL == groupname || !strlen(groupname))) {
+ THROW(InvalidParameter,
+ "Invalid input: username and groupname should not be empty");
+ }
+
+ nn->setOwner(getStandardPath(path), username != NULL ? username : "",
+ groupname != NULL ? groupname : "");
+}
+
+/**
+ * To set the access time or modification time of a path.
+ * @param path the path which access time or modification time is to be changed.
+ * @param mtime new modification time.
+ * @param atime new access time.
+ */
+void FileSystemImpl::setTimes(const char * path, int64_t mtime, int64_t atime) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ nn->setTimes(getStandardPath(path), mtime, atime);
+}
+
+/**
+ * To set the permission of a path.
+ * @param path the path which permission is to be changed.
+ * @param permission new permission.
+ */
+void FileSystemImpl::setPermission(const char * path,
+ const Permission & permission) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ nn->setPermission(getStandardPath(path), permission);
+}
+
+/**
+ * To set the number of replication.
+ * @param path the path which number of replication is to be changed.
+ * @param replication new number of replication.
+ * @return return true if success.
+ */
+
+bool FileSystemImpl::setReplication(const char * path, short replication) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ return nn->setReplication(getStandardPath(path), replication);
+}
+
+/**
+ * To rename a path.
+ * @param src old path.
+ * @param dst new path.
+ * @return return true if success.
+ */
+
+bool FileSystemImpl::rename(const char * src, const char * dst) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == src || !strlen(src)) {
+ THROW(InvalidParameter, "Invalid input: src should not be empty");
+ }
+
+ if (NULL == dst || !strlen(dst)) {
+ THROW(InvalidParameter, "Invalid input: dst should not be empty");
+ }
+
+ return nn->rename(getStandardPath(src), getStandardPath(dst));
+}
+
+/**
+ * To set working directory.
+ * @param path new working directory.
+ */
+void FileSystemImpl::setWorkingDirectory(const char * path) {
+ if (NULL == path) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ if (!strlen(path) || '/' != path[0]) {
+ THROW(InvalidParameter,
+ "Invalid input: path should be an absolute path");
+ }
+
+ lock_guard<mutex> lock(mutWorkingDir);
+ workingDir = path;
+}
+
+/**
+ * To get working directory.
+ * @return working directory.
+ */
+std::string FileSystemImpl::getWorkingDirectory() const {
+ return workingDir;
+}
+
+/**
+ * To test if the path exist.
+ * @param path the path which is to be tested.
+ * @return return true if the path exist.
+ */
+
+bool FileSystemImpl::exist(const char * path) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ try {
+ bool retval = true;
+ nn->getFileInfo(getStandardPath(path), &retval);
+ return retval;
+ } catch (const FileNotFoundException & e) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * To get the file system status.
+ * @return the file system status.
+ */
+FileSystemStats FileSystemImpl::getFsStats() {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ std::vector<int64_t> retval = nn->getFsStats();
+ assert(retval.size() >= 3);
+ return FileSystemStats(retval[0], retval[1], retval[2]);
+}
+
+/**
+ * Truncate the file in the indicated path to the indicated size.
+ * @param path The path to the file to be truncated
+ * @param size The size the file is to be truncated to
+ *
+ * @return true if and client does not need to wait for block recovery,
+ * false if client needs to wait for block recovery.
+ */
+bool FileSystemImpl::truncate(const char * path, int64_t size) {
+ LOG(DEBUG1, "truncate file %s to length %" PRId64, path, size);
+
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: src should not be empty.");
+ }
+
+ std::string absPath = getStandardPath(path);
+
+ return nn->truncate(absPath, size, clientName);
+}
+
+std::string FileSystemImpl::getDelegationToken(const char * renewer) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == renewer || !strlen(renewer)) {
+ THROW(InvalidParameter, "Invalid input: renewer should not be empty.");
+ }
+
+ Token retval = nn->getDelegationToken(renewer);
+ retval.setService(tokenService);
+ return retval.toString();
+}
+
+std::string FileSystemImpl::getDelegationToken() {
+ return getDelegationToken(key.getUser().getPrincipal().c_str());
+}
+
+int64_t FileSystemImpl::renewDelegationToken(const std::string & token) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ Token t;
+ t.fromString(token);
+ return nn->renewDelegationToken(t);
+}
+
+void FileSystemImpl::cancelDelegationToken(const std::string & token) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ Token t;
+ t.fromString(token);
+ nn->cancelDelegationToken(t);
+}
+
+void FileSystemImpl::getBlockLocations(const std::string & src, int64_t offset,
+ int64_t length, LocatedBlocks & lbs) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ nn->getBlockLocations(src, offset, length, lbs);
+}
+
+void FileSystemImpl::create(const std::string & src, const Permission & masked,
+ int flag, bool createParent, short replication, int64_t blockSize) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ nn->create(src, masked, clientName, flag, createParent, replication,
+ blockSize);
+}
+
+std::pair<shared_ptr<LocatedBlock>, shared_ptr<FileStatus> >
+FileSystemImpl::append(const std::string& src) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ return nn->append(src, clientName);
+}
+
+void FileSystemImpl::abandonBlock(const ExtendedBlock & b,
+ const std::string & src) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ nn->abandonBlock(b, src, clientName);
+}
+
+shared_ptr<LocatedBlock> FileSystemImpl::addBlock(const std::string & src,
+ const ExtendedBlock * previous,
+ const std::vector<DatanodeInfo> & excludeNodes) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ return nn->addBlock(src, clientName, previous, excludeNodes);
+}
+
+shared_ptr<LocatedBlock> FileSystemImpl::getAdditionalDatanode(
+ const std::string & src, const ExtendedBlock & blk,
+ const std::vector<DatanodeInfo> & existings,
+ const std::vector<std::string> & storageIDs,
+ const std::vector<DatanodeInfo> & excludes, int numAdditionalNodes) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ return nn->getAdditionalDatanode(src, blk, existings, storageIDs, excludes,
+ numAdditionalNodes, clientName);
+}
+
+bool FileSystemImpl::complete(const std::string & src,
+ const ExtendedBlock * last) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ return nn->complete(src, clientName, last);
+}
+
+/*void FileSystemImpl::reportBadBlocks(const std::vector<LocatedBlock> & blocks) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ nn->reportBadBlocks(blocks);
+}*/
+
+void FileSystemImpl::fsync(const std::string & src) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ nn->fsync(src, clientName);
+}
+
+shared_ptr<LocatedBlock> FileSystemImpl::updateBlockForPipeline(
+ const ExtendedBlock & block) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ return nn->updateBlockForPipeline(block, clientName);
+}
+
+void FileSystemImpl::updatePipeline(const ExtendedBlock & oldBlock,
+ const ExtendedBlock & newBlock,
+ const std::vector<DatanodeInfo> & newNodes,
+ const std::vector<std::string> & storageIDs) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ nn->updatePipeline(clientName, oldBlock, newBlock, newNodes, storageIDs);
+}
+
+bool FileSystemImpl::getListing(const std::string & src,
+ const std::string & startAfter, bool needLocation,
+ std::vector<FileStatus> & dl) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ return nn->getListing(src, startAfter, needLocation, dl);
+}
+
+bool FileSystemImpl::renewLease() {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ //protected by LeaseRenewer's lock
+ if (0 == openedOutputStream) {
+ return false;
+ }
+
+ try {
+ nn->renewLease(clientName);
+ return true;
+ } catch (const HdfsException & e) {
+ std::string buffer;
+ LOG(LOG_ERROR,
+ "Failed to renew lease for filesystem which client name is %s, since:\n%s",
+ getClientName(), GetExceptionDetail(e, buffer));
+ } catch (const std::exception & e) {
+ LOG(LOG_ERROR,
+ "Failed to renew lease for filesystem which client name is %s, since:\n%s",
+ getClientName(), e.what());
+ }
+
+ return false;
+}
+
+void FileSystemImpl::registerOpenedOutputStream() {
+ //protected by LeaseRenewer's lock
+ ++openedOutputStream;
+}
+
+bool FileSystemImpl::unregisterOpenedOutputStream() {
+ //protected by LeaseRenewer's lock
+ if (openedOutputStream > 0) {
+ --openedOutputStream;
+ }
+
+ return openedOutputStream == 0;
+}
+
+/**
+ * Create encryption zone for the directory with specific key name
+ * @param path the directory path which is to be created.
+ * @param keyname The key name of the encryption zone
+ * @return return true if success.
+ */
+
+bool FileSystemImpl::createEncryptionZone(const char * path, const char * keyName) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ if (NULL == keyName || !strlen(keyName)) {
+ THROW(InvalidParameter, "Invalid input: key name should not be empty");
+ }
+
+ return nn->createEncryptionZone(getStandardPath(path), keyName);
+}
+
+
+/**
+ * To get encryption zone information.
+ * @param path the path which information is to be returned.
+ * @return the encryption zone information.
+ */
+
+EncryptionZoneInfo FileSystemImpl::getEZForPath(const char * path) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ if (NULL == path || !strlen(path)) {
+ THROW(InvalidParameter, "Invalid input: path should not be empty");
+ }
+
+ return nn->getEncryptionZoneInfo(getStandardPath(path), NULL);
+}
+
+bool FileSystemImpl::listEncryptionZones(const int64_t id,
+ std::vector<EncryptionZoneInfo> & ezl) {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ return nn->listEncryptionZones(id, ezl);
+}
+
+/**
+ * list the contents of an encryption zone.
+ * @return return the encryption zone information.
+ */
+EncryptionZoneIterator FileSystemImpl::listEncryptionZone() {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ return EncryptionZoneIterator(this, 0);
+}
+/**
+ * list all the contents of encryption zones.
+ * @param id the index of the encyrption zones.
+ * @return Return a vector of encryption zones information.
+ */
+
+std::vector<EncryptionZoneInfo> FileSystemImpl::listAllEncryptionZoneItems() {
+ if (!nn) {
+ THROW(HdfsIOException, "FileSystemImpl: not connected.");
+ }
+
+ std::vector<EncryptionZoneInfo> retval;
+ retval.clear();
+ int64_t id = 0;
+
+ EncryptionZoneIterator it;
+ it = FileSystemImpl::listEncryptionZone();
+
+ while (it.hasNext()) {
+ retval.push_back(it.getNext());
+ }
+ return retval;
+}
+
+}
+}
diff --git a/src/client/FileSystemImpl.h b/src/client/FileSystemImpl.h
new file mode 100644
index 0000000..1c11a61
--- /dev/null
+++ b/src/client/FileSystemImpl.h
@@ -0,0 +1,541 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_CLIENT_FILESYSTEMIMPL_H_
+#define _HDFS_LIBHDFS3_CLIENT_FILESYSTEMIMPL_H_
+
+#include "BlockLocation.h"
+#include "DirectoryIterator.h"
+#include "EncryptionZoneIterator.h"
+#include "FileStatus.h"
+#include "FileSystemInter.h"
+#include "FileSystemKey.h"
+#include "FileSystemStats.h"
+#include "EncryptionZoneInfo.h"
+#include "Permission.h"
+#include "server/Namenode.h"
+#include "SessionConfig.h"
+#include "Unordered.h"
+#include "UserInfo.h"
+#include "XmlConfig.h"
+#ifdef MOCK
+#include "NamenodeStub.h"
+#endif
+
+#include <string>
+#include <vector>
+
+namespace Hdfs {
+namespace Internal {
+
+class InputStreamInter;
+class OutputStreamInter;
+
+class FileSystemImpl: public FileSystemInter {
+public:
+ /**
+ * Construct a FileSystemImpl instance.
+ * @param key a key which can be uniquely identify a FileSystemImpl instance.
+ * @param c a configuration objecto used to initialize the instance.
+ */
+ FileSystemImpl(const FileSystemKey & key, const Config & c);
+
+ /**
+ * Destroy a FileSystemBase instance
+ */
+ ~FileSystemImpl();
+
+ /**
+ * Format the path to a absolute canonicalized path.
+ * @param path target path to be hendled.
+ * @return return a absolute canonicalized path.
+ */
+ const std::string getStandardPath(const char * path);
+
+ /**
+ * To get the client unique ID.
+ * @return return the client unique ID.
+ */
+ const char * getClientName();
+
+ /**
+ * Connect to hdfs
+ */
+ void connect();
+
+ /**
+ * disconnect from hdfs
+ */
+ void disconnect();
+
+ /**
+ * To get default number of replication.
+ * @return the default number of replication.
+ */
+ int getDefaultReplication() const;
+
+ /**
+ * To get the default block size.
+ * @return the default block size.
+ */
+ int64_t getDefaultBlockSize() const;
+
+ /**
+ * To get the home directory.
+ * @return home directory.
+ */
+ std::string getHomeDirectory() const;
+
+ /**
+ * To delete a file or directory.
+ * @param path the path to be deleted.
+ * @param recursive if path is a directory, delete the contents recursively.
+ * @return return true if success.
+ */
+ bool deletePath(const char * path, bool recursive);
+
+ /**
+ * To create a directory with given permission.
+ * @param path the directory path which is to be created.
+ * @param permission directory permission.
+ * @return return true if success.
+ */
+ bool mkdir(const char * path, const Permission & permission);
+
+ /**
+ * To create a directory which given permission.
+ * If parent path does not exits, create it.
+ * @param path the directory path which is to be created.
+ * @param permission directory permission.
+ * @return return true if success.
+ */
+ bool mkdirs(const char * path, const Permission & permission);
+
+ /**
+ * To get path information.
+ * @param path the path which information is to be returned.
+ * @return the path information.
+ */
+ FileStatus getFileStatus(const char * path);
+
+ /**
+ * Return an array containing hostnames, offset and size of
+ * portions of the given file.
+ *
+ * This call is most helpful with DFS, where it returns
+ * hostnames of machines that contain the given file.
+ *
+ * The FileSystem will simply return an elt containing 'localhost'.
+ *
+ * @param path path is used to identify an FS since an FS could have
+ * another FS that it could be delegating the call to
+ * @param start offset into the given file
+ * @param len length for which to get locations for
+ */
+ std::vector<BlockLocation> getFileBlockLocations(
+ const char * path, int64_t start, int64_t len);
+
+ /**
+ * list the contents of a directory.
+ * @param path the directory path.
+ * @return Return a iterator to visit all elements in this directory.
+ */
+ DirectoryIterator listDirectory(const char * path, bool needLocation);
+
+ /**
+ * list all the contents of a directory.
+ * @param path The directory path.
+ * @return Return a vector of file informations in the directory.
+ */
+ std::vector<FileStatus> listAllDirectoryItems(const char * path,
+ bool needLocation);
+
+ /**
+ * To set the owner and the group of the path.
+ * username and groupname cannot be empty at the same time.
+ * @param path the path which owner of group is to be changed.
+ * @param username new user name.
+ * @param groupname new group.
+ */
+ void setOwner(const char * path, const char * username,
+ const char * groupname);
+
+ /**
+ * To set the access time or modification time of a path.
+ * @param path the path which access time or modification time is to be changed.
+ * @param mtime new modification time.
+ * @param atime new access time.
+ */
+ void setTimes(const char * path, int64_t mtime, int64_t atime);
+
+ /**
+ * To set the permission of a path.
+ * @param path the path which permission is to be changed.
+ * @param permission new permission.
+ */
+ void setPermission(const char * path, const Permission & permission);
+
+ /**
+ * To set the number of replication.
+ * @param path the path which number of replication is to be changed.
+ * @param replication new number of replication.
+ * @return return true if success.
+ */
+ bool setReplication(const char * path, short replication);
+
+ /**
+ * To rename a path.
+ * @param src old path.
+ * @param dst new path.
+ * @return return true if success.
+ */
+ bool rename(const char * src, const char * dst);
+
+ /**
+ * To set working directory.
+ * @param path new working directory.
+ */
+ void setWorkingDirectory(const char * path);
+
+ /**
+ * To get working directory.
+ * @return working directory.
+ */
+ std::string getWorkingDirectory() const;
+
+ /**
+ * To test if the path exist.
+ * @param path the path which is to be tested.
+ * @return return true if the path exist.
+ */
+ bool exist(const char * path);
+
+ /**
+ * To get the file system status.
+ * @return the file system status.
+ */
+ FileSystemStats getFsStats();
+
+ /**
+ * Truncate the file in the indicated path to the indicated size.
+ * @param path The path to the file to be truncated
+ * @param size The size the file is to be truncated to
+ *
+ * @return true if and client does not need to wait for block recovery,
+ * false if client needs to wait for block recovery.
+ */
+ bool truncate(const char * path, int64_t size);
+
+ /**
+ * Get a valid Delegation Token.
+ *
+ * @param renewer the designated renewer for the token
+ * @return Token
+ * @throws IOException
+ */
+ std::string getDelegationToken(const char * renewer);
+
+ /**
+ * Get a valid Delegation Token using default user as renewer.
+ *
+ * @return Token
+ * @throws IOException
+ */
+ std::string getDelegationToken();
+
+ /**
+ * Renew an existing delegation token.
+ *
+ * @param token delegation token obtained earlier
+ * @return the new expiration time
+ * @throws IOException
+ */
+ int64_t renewDelegationToken(const std::string & token);
+
+ /**
+ * Cancel an existing delegation token.
+ *
+ * @param token delegation token
+ * @throws IOException
+ */
+ void cancelDelegationToken(const std::string & token);
+
+ /**
+ * Get locations of the blocks of the specified file within the specified range.
+ * DataNode locations for each block are sorted by
+ * the proximity to the client.
+ *
+ * The client will then have to contact
+ * one of the indicated DataNodes to obtain the actual data.
+ *
+ * @param src file name
+ * @param offset range start offset
+ * @param length range length
+ * @param lbs output the returned blocks
+ */
+ void getBlockLocations(const std::string & src, int64_t offset,
+ int64_t length, LocatedBlocks & lbs);
+
+ /**
+ * Create a new file entry in the namespace.
+ *
+ * @param src path of the file being created.
+ * @param masked masked permission.
+ * @param flag indicates whether the file should be
+ * overwritten if it already exists or create if it does not exist or append.
+ * @param createParent create missing parent directory if true
+ * @param replication block replication factor.
+ * @param blockSize maximum block size.
+ */
+ void create(const std::string & src, const Permission & masked, int flag,
+ bool createParent, short replication, int64_t blockSize);
+
+ /**
+ * Append to the end of the file.
+ *
+ * @param src path of the file being created.
+ * @return return the last partial block if any
+ */
+ std::pair<shared_ptr<LocatedBlock>, shared_ptr<FileStatus> > append(
+ const std::string& src);
+
+ /**
+ * The client can give up on a block by calling abandonBlock().
+ * The client can then either obtain a new block, or complete or abandon the file.
+ * Any partial writes to the block will be discarded.
+ *
+ * @param b the block to be abandoned.
+ * @param src the file which the block belongs to.
+ */
+ void abandonBlock(const ExtendedBlock & b, const std::string & src);
+
+ /**
+ * A client that wants to write an additional block to the
+ * indicated filename (which must currently be open for writing)
+ * should call addBlock().
+ *
+ * addBlock() allocates a new block and datanodes the block data
+ * should be replicated to.
+ *
+ * addBlock() also commits the previous block by reporting
+ * to the name-node the actual generation stamp and the length
+ * of the block that the client has transmitted to data-nodes.
+ *
+ * @param src the file being created
+ * @param previous previous block
+ * @param excludeNodes a list of nodes that should not be allocated for the current block.
+ * @return return the new block.
+ */
+ shared_ptr<LocatedBlock> addBlock(const std::string & src,
+ const ExtendedBlock * previous,
+ const std::vector<DatanodeInfo> & excludeNodes);
+
+ /**
+ * Get a datanode for an existing pipeline.
+ *
+ * @param src the file being written
+ * @param blk the block being written
+ * @param existings the existing nodes in the pipeline
+ * @param excludes the excluded nodes
+ * @param numAdditionalNodes number of additional datanodes
+ * @return return a new block information which contains new datanode.
+ */
+ shared_ptr<LocatedBlock> getAdditionalDatanode(const std::string & src,
+ const ExtendedBlock & blk,
+ const std::vector<DatanodeInfo> & existings,
+ const std::vector<std::string> & storageIDs,
+ const std::vector<DatanodeInfo> & excludes, int numAdditionalNodes);
+
+ /**
+ * The client is done writing data to the given filename, and would
+ * like to complete it.
+ *
+ * The function returns whether the file has been closed successfully.
+ * If the function returns false, the caller should try again.
+ *
+ * close() also commits the last block of file by reporting
+ * to the name-node the actual generation stamp and the length
+ * of the block that the client has transmitted to data-nodes.
+ *
+ * A call to complete() will not return true until all the file's
+ * blocks have been replicated the minimum number of times. Thus,
+ * DataNode failures may cause a client to call complete() several
+ * times before succeeding.
+ *
+ * @param src the file being written.
+ * @param last last block to be committed.
+ * @return return false if the client should retry.
+ */
+ bool complete(const std::string & src, const ExtendedBlock * last);
+
+ /**
+ * The client wants to report corrupted blocks (blocks with specified
+ * locations on datanodes).
+ * @param blocks Array of located blocks to report
+ */
+ /*void reportBadBlocks(const std::vector<LocatedBlock> & blocks);*/
+
+ /**
+ * Write all metadata for this file into persistent storage.
+ * The file must be currently open for writing.
+ * @param src The const std::string & representation of the path
+ */
+ void fsync(const std::string & src);
+
+ /**
+ * Get a new generation stamp together with an access token for
+ * a block under construction
+ *
+ * This method is called only when a client needs to recover a failed
+ * pipeline or set up a pipeline for appending to a block.
+ *
+ * @param block a block
+ * @return return a located block with a new generation stamp and an access token
+ */
+ shared_ptr<LocatedBlock> updateBlockForPipeline(
+ const ExtendedBlock & block);
+
+ /**
+ * Update a pipeline for a block under construction
+ *
+ * @param oldBlock the old block
+ * @param newBlock the new block containing new generation stamp and length
+ * @param newNodes datanodes in the pipeline
+ */
+ void updatePipeline(const ExtendedBlock & oldBlock,
+ const ExtendedBlock & newBlock,
+ const std::vector<DatanodeInfo> & newNodes,
+ const std::vector<std::string> & storageIDs);
+
+ /**
+ * register the output stream in filespace when it is opened.
+ */
+ void registerOpenedOutputStream();
+
+ /**
+ * unregister the output stream from filespace when it is closed.
+ */
+ bool unregisterOpenedOutputStream();
+
+ /**
+ * Get the configuration used in filesystem.
+ * @return return the configuration instance.
+ */
+ const SessionConfig & getConf() const {
+ return sconf;
+ }
+
+ /**
+ * Get the user used in filesystem.
+ * @return return the user information.
+ */
+ const UserInfo & getUserInfo() const {
+ return user;
+ }
+
+ /**
+ * Get a partial listing of the indicated directory
+ *
+ * @param src the directory name
+ * @param startAfter the name to start listing after encoded in java UTF8
+ * @param needLocation if the FileStatus should contain block locations
+ * @param dl append the returned directories.
+ * @return return true if there are more items.
+ */
+ bool getListing(const std::string & src, const std::string & startAfter,
+ bool needLocation, std::vector<FileStatus> & dl);
+
+ /**
+ * To renew the lease.
+ *
+ * @return return false if the filesystem no long needs to renew lease.
+ */
+ bool renewLease();
+
+ /**
+ * Get the peer cache.
+ *
+ * @return return the peer cache.
+ */
+ PeerCache& getPeerCache() {
+ return *peerCache;
+ }
+
+ /**
+ * Create encryption zone for the directory with specific key name
+ * @param path the directory path which is to be created.
+ * @param keyname The key name of the encryption zone
+ * @return return true if success.
+ */
+ bool createEncryptionZone(const char * path, const char * keyName);
+
+ /**
+ * To get encryption zone information.
+ * @param path the path which information is to be returned.
+ * @return the encryption zone information.
+ */
+ EncryptionZoneInfo getEZForPath(const char * path);
+
+ /**
+ * Get a partial listing of the indicated encryption zones
+ *
+ * @param id the index of encryption zones.
+ * @param ezl append the returned encryption zones.
+ * @return return true if there are more items.
+ */
+ bool listEncryptionZones(const int64_t id, std::vector<EncryptionZoneInfo> & ezl);
+
+ /**
+ * list the contents of an encryption zone.
+ * @return Return a iterator to visit all elements in this encryption zone.
+ */
+ EncryptionZoneIterator listEncryptionZone();
+
+
+ /**
+ * list all the contents of encryption zones.
+ * @param id the index of encryption zones.
+ * @return Return a vector of encryption zones information..
+ */
+ std::vector<EncryptionZoneInfo> listAllEncryptionZoneItems();
+
+private:
+ Config conf;
+ FileSystemKey key;
+ int openedOutputStream;
+ mutex mutWorkingDir;
+ Namenode * nn;
+ SessionConfig sconf;
+ shared_ptr<PeerCache> peerCache;
+ std::string clientName;
+ std::string tokenService;
+ std::string workingDir;
+ UserInfo user;
+#ifdef MOCK
+private:
+ Hdfs::Mock::NamenodeStub * stub;
+#endif
+};
+
+}
+}
+
+#endif /* _HDFS_LIBHDFS3_CLIENT_FILESYSTEMIMPL_H_ */
diff --git a/src/client/FileSystemInter.h b/src/client/FileSystemInter.h
new file mode 100644
index 0000000..45df347
--- /dev/null
+++ b/src/client/FileSystemInter.h
@@ -0,0 +1,528 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_CLIENT_FILESYSTEMINTER_H_
+#define _HDFS_LIBHDFS3_CLIENT_FILESYSTEMINTER_H_
+
+#include <string>
+#include <vector>
+
+#include "BlockLocation.h"
+#include "DirectoryIterator.h"
+#include "EncryptionZoneIterator.h"
+#include "FileStatus.h"
+#include "FileSystemKey.h"
+#include "FileSystemStats.h"
+#include "EncryptionZoneInfo.h"
+#include "PeerCache.h"
+#include "Permission.h"
+#include "server/LocatedBlocks.h"
+#include "SessionConfig.h"
+#include "Unordered.h"
+#include "UserInfo.h"
+#include "XmlConfig.h"
+
+namespace Hdfs {
+
+class FileSystem;
+
+namespace Internal {
+
+class InputStreamInter;
+class OutputStreamInter;
+class FileSystemInter;
+
+struct FileSystemWrapper {
+public:
+ FileSystemWrapper(shared_ptr<FileSystemInter> fs) :
+ filesystem(fs) {
+ }
+
+ shared_ptr<FileSystemInter> filesystem;
+};
+
+class FileSystemInter {
+public:
+ /**
+ * Destroy a FileSystemInter instance
+ */
+ virtual ~FileSystemInter() {
+ }
+
+ /**
+ * Format the path to a absolute canonicalized path.
+ * @param path target path to be hendled.
+ * @return return a absolute canonicalized path.
+ */
+ virtual const std::string getStandardPath(const char * path) = 0;
+
+ /**
+ * To get the client unique ID.
+ * @return return the client unique ID.
+ */
+ virtual const char * getClientName() = 0;
+
+ /**
+ * Connect to hdfs
+ */
+ virtual void connect() = 0;
+
+ /**
+ * disconnect from hdfs
+ */
+ virtual void disconnect() = 0;
+
+ /**
+ * To get default number of replication.
+ * @return the default number of replication.
+ */
+ virtual int getDefaultReplication() const = 0;
+
+ /**
+ * To get the default block size.
+ * @return the default block size.
+ */
+ virtual int64_t getDefaultBlockSize() const = 0;
+
+ /**
+ * To get the home directory.
+ * @return home directory.
+ */
+ virtual std::string getHomeDirectory() const = 0;
+
+ /**
+ * To delete a file or directory.
+ * @param path the path to be deleted.
+ * @param recursive if path is a directory, delete the contents recursively.
+ * @return return true if success.
+ */
+ virtual bool deletePath(const char * path, bool recursive) = 0;
+
+ /**
+ * To create a directory which given permission.
+ * @param path the directory path which is to be created.
+ * @param permission directory permission.
+ * @return return true if success.
+ */
+ virtual bool mkdir(const char * path, const Permission & permission) = 0;
+
+ /**
+ * To create a directory which given permission.
+ * If parent path does not exits, create it.
+ * @param path the directory path which is to be created.
+ * @param permission directory permission.
+ * @return return true if success.
+ */
+ virtual bool mkdirs(const char * path, const Permission & permission) = 0;
+
+ /**
+ * To get path information.
+ * @param path the path which information is to be returned.
+ * @return the path information.
+ */
+ virtual FileStatus getFileStatus(const char * path) = 0;
+
+ /**
+ * Return an array containing hostnames, offset and size of
+ * portions of the given file.
+ *
+ * This call is most helpful with DFS, where it returns
+ * hostnames of machines that contain the given file.
+ *
+ * The FileSystem will simply return an elt containing 'localhost'.
+ *
+ * @param path path is used to identify an FS since an FS could have
+ * another FS that it could be delegating the call to
+ * @param start offset into the given file
+ * @param len length for which to get locations for
+ */
+ virtual std::vector<BlockLocation> getFileBlockLocations(
+ const char * path, int64_t start, int64_t len) = 0;
+
+ /**
+ * list the contents of a directory.
+ * @param path the directory path.
+ * @return Return a iterator to visit all elements in this directory.
+ */
+ virtual DirectoryIterator listDirectory(const char * path,
+ bool needLocation) = 0;
+
+ /**
+ * list all the contents of a directory.
+ * @param path The directory path.
+ * @return Return a vector of file informations in the directory.
+ */
+ virtual std::vector<FileStatus> listAllDirectoryItems(const char * path,
+ bool needLocation) = 0;
+
+ /**
+ * To set the owner and the group of the path.
+ * username and groupname cannot be empty at the same time.
+ * @param path the path which owner of group is to be changed.
+ * @param username new user name.
+ * @param groupname new group.
+ */
+ virtual void setOwner(const char * path, const char * username,
+ const char * groupname) = 0;
+
+ /**
+ * To set the access time or modification time of a path.
+ * @param path the path which access time or modification time is to be changed.
+ * @param mtime new modification time.
+ * @param atime new access time.
+ */
+ virtual void setTimes(const char * path, int64_t mtime, int64_t atime) = 0;
+
+ /**
+ * To set the permission of a path.
+ * @param path the path which permission is to be changed.
+ * @param permission new permission.
+ */
+ virtual void setPermission(const char * path,
+ const Permission & permission) = 0;
+
+ /**
+ * To set the number of replication.
+ * @param path the path which number of replication is to be changed.
+ * @param replication new number of replication.
+ * @return return true if success.
+ */
+ virtual bool setReplication(const char * path, short replication) = 0;
+
+ /**
+ * To rename a path.
+ * @param src old path.
+ * @param dst new path.
+ * @return return true if success.
+ */
+ virtual bool rename(const char * src, const char * dst) = 0;
+
+ /**
+ * To set working directory.
+ * @param path new working directory.
+ */
+ virtual void setWorkingDirectory(const char * path) = 0;
+
+ /**
+ * To get working directory.
+ * @return working directory.
+ */
+ virtual std::string getWorkingDirectory() const = 0;
+
+ /**
+ * To test if the path exist.
+ * @param path the path which is to be tested.
+ * @return return true if the path exist.
+ */
+ virtual bool exist(const char * path) = 0;
+
+ /**
+ * To get the file system status.
+ * @return the file system status.
+ */
+ virtual FileSystemStats getFsStats() = 0;
+
+ /**
+ * Truncate the file in the indicated path to the indicated size.
+ * @param src The path we will find the file to be truncated.
+ * @param size the position we will truncate to.
+ * @throw IOException
+ */
+ virtual bool truncate(const char * src, int64_t size) /* throw AccessControlException,
+ FileNotFoundException, UnresolvedLinkException, HdfsIOException */ = 0;
+
+ /**
+ * Get a valid Delegation Token.
+ *
+ * @param renewer the designated renewer for the token
+ * @return Token<DelegationTokenIdentifier>
+ * @throws IOException
+ */
+ virtual std::string getDelegationToken(const char * renewer) = 0;
+
+ /**
+ * Get a valid Delegation Token using the default user as renewer.
+ *
+ * @return Token<DelegationTokenIdentifier>
+ * @throws IOException
+ */
+ virtual std::string getDelegationToken() = 0;
+
+ /**
+ * Renew an existing delegation token.
+ *
+ * @param token delegation token obtained earlier
+ * @return the new expiration time
+ * @throws IOException
+ */
+ virtual int64_t renewDelegationToken(const std::string & token) = 0;
+
+ /**
+ * Cancel an existing delegation token.
+ *
+ * @param token delegation token
+ * @throws IOException
+ */
+ virtual void cancelDelegationToken(const std::string & token) = 0;
+
+ /**
+ * Get locations of the blocks of the specified file within the specified range.
+ * DataNode locations for each block are sorted by
+ * the proximity to the client.
+ *
+ * The client will then have to contact
+ * one of the indicated DataNodes to obtain the actual data.
+ *
+ * @param src file name
+ * @param offset range start offset
+ * @param length range length
+ * @param lbs output the returned blocks
+ */
+ virtual void getBlockLocations(const std::string & src, int64_t offset,
+ int64_t length, LocatedBlocks & lbs) = 0;
+
+ /**
+ * Create a new file entry in the namespace.
+ *
+ * @param src path of the file being created.
+ * @param masked masked permission.
+ * @param flag indicates whether the file should be
+ * overwritten if it already exists or create if it does not exist or append.
+ * @param createParent create missing parent directory if true
+ * @param replication block replication factor.
+ * @param blockSize maximum block size.
+ */
+ virtual void create(const std::string & src, const Permission & masked,
+ int flag, bool createParent, short replication,
+ int64_t blockSize) = 0;
+
+ /**
+ * Append to the end of the file.
+ *
+ * @param src path of the file being created.
+ * @return return the last partial block if any
+ */
+ virtual std::pair<shared_ptr<LocatedBlock>, shared_ptr<FileStatus> > append(
+ const std::string& src) = 0;
+
+ /**
+ * The client can give up on a block by calling abandonBlock().
+ * The client can then either obtain a new block, or complete or abandon the file.
+ * Any partial writes to the block will be discarded.
+ *
+ * @param b the block to be abandoned.
+ * @param src the file which the block belongs to.
+ */
+ virtual void abandonBlock(const ExtendedBlock & b,
+ const std::string & srcr) = 0;
+
+ /**
+ * A client that wants to write an additional block to the
+ * indicated filename (which must currently be open for writing)
+ * should call addBlock().
+ *
+ * addBlock() allocates a new block and datanodes the block data
+ * should be replicated to.
+ *
+ * addBlock() also commits the previous block by reporting
+ * to the name-node the actual generation stamp and the length
+ * of the block that the client has transmitted to data-nodes.
+ *
+ * @param src the file being created
+ * @param previous previous block
+ * @param excludeNodes a list of nodes that should not be allocated for the current block.
+ * @return return the new block.
+ */
+ virtual shared_ptr<LocatedBlock> addBlock(const std::string & src,
+ const ExtendedBlock * previous,
+ const std::vector<DatanodeInfo> & excludeNodes) = 0;
+
+ /**
+ * Get a datanode for an existing pipeline.
+ *
+ * @param src the file being written
+ * @param blk the block being written
+ * @param existings the existing nodes in the pipeline
+ * @param excludes the excluded nodes
+ * @param numAdditionalNodes number of additional datanodes
+ * @return return a new block information which contains new datanode.
+ */
+ virtual shared_ptr<LocatedBlock> getAdditionalDatanode(
+ const std::string & src, const ExtendedBlock & blk,
+ const std::vector<DatanodeInfo> & existings,
+ const std::vector<std::string> & storageIDs,
+ const std::vector<DatanodeInfo> & excludes,
+ int numAdditionalNodes) = 0;
+
+ /**
+ * The client is done writing data to the given filename, and would
+ * like to complete it.
+ *
+ * The function returns whether the file has been closed successfully.
+ * If the function returns false, the caller should try again.
+ *
+ * close() also commits the last block of file by reporting
+ * to the name-node the actual generation stamp and the length
+ * of the block that the client has transmitted to data-nodes.
+ *
+ * A call to complete() will not return true until all the file's
+ * blocks have been replicated the minimum number of times. Thus,
+ * DataNode failures may cause a client to call complete() several
+ * times before succeeding.
+ *
+ * @param src the file being written.
+ * @param last last block to be committed.
+ * @return return false if the client should retry.
+ */
+ virtual bool complete(const std::string & src,
+ const ExtendedBlock * last) = 0;
+
+ /**
+ * The client wants to report corrupted blocks (blocks with specified
+ * locations on datanodes).
+ * @param blocks Array of located blocks to report
+ */
+ /*virtual void reportBadBlocks(const std::vector<LocatedBlock> & blocks) = 0;*/
+
+ /**
+ * Write all metadata for this file into persistent storage.
+ * The file must be currently open for writing.
+ * @param src The const std::string & representation of the path
+ */
+ virtual void fsync(const std::string & src) = 0;
+
+ /**
+ * Get a new generation stamp together with an access token for
+ * a block under construction
+ *
+ * This method is called only when a client needs to recover a failed
+ * pipeline or set up a pipeline for appending to a block.
+ *
+ * @param block a block
+ * @return return a located block with a new generation stamp and an access token
+ */
+ virtual shared_ptr<LocatedBlock> updateBlockForPipeline(
+ const ExtendedBlock & block) = 0;
+
+ /**
+ * Update a pipeline for a block under construction
+ *
+ * @param clientName the name of the client
+ * @param oldBlock the old block
+ * @param newBlock the new block containing new generation stamp and length
+ * @param newNodes datanodes in the pipeline
+ * @throw HdfsIOException if any error occurs
+ */
+ virtual void updatePipeline(const ExtendedBlock & oldBlock,
+ const ExtendedBlock & newBlock,
+ const std::vector<DatanodeInfo> & newNodes,
+ const std::vector<std::string> & storageIDs) = 0;
+
+ /**
+ * register the output stream in filespace when it is opened.
+ */
+ virtual void registerOpenedOutputStream() = 0;
+
+ /**
+ * unregister the output stream from filespace when it is closed.
+ */
+ virtual bool unregisterOpenedOutputStream() = 0;
+
+ /**
+ * Get the configuration used in filesystem.
+ * @return return the configuration instance.
+ */
+ virtual const SessionConfig & getConf() const = 0;
+
+ /**
+ * Get the user used in filesystem.
+ * @return return the user information.
+ */
+ virtual const UserInfo & getUserInfo() const = 0;
+
+ /**
+ * Get a partial listing of the indicated directory
+ *
+ * @param src the directory name
+ * @param startAfter the name to start listing after encoded in java UTF8
+ * @param needLocation if the FileStatus should contain block locations
+ * @param dl append the returned directories.
+ * @return return true if there are more items.
+ */
+ virtual bool getListing(const std::string & src, const std::string & startAfter,
+ bool needLocation, std::vector<FileStatus> & dl) = 0;
+
+ /**
+ * To renew the lease.
+ *
+ * @return return false if the filesystem no long needs to renew lease.
+ */
+ virtual bool renewLease() = 0;
+
+ /**
+ * Get the peer cache.
+ *
+ * @return return the peer cache.
+ */
+ virtual PeerCache& getPeerCache() = 0;
+
+ /**
+ * Create encryption zone for the directory with specific key name
+ * @param path the directory path which is to be created.
+ * @param keyname The key name of the encryption zone
+ * @return return true if success.
+ */
+ virtual bool createEncryptionZone(const char * path, const char * keyName) = 0;
+
+ /**
+ * To get encryption zone information.
+ * @param path the path which information is to be returned.
+ * @return the encryption zone information.
+ */
+ virtual EncryptionZoneInfo getEZForPath(const char * path) = 0;
+
+ /**
+ * Get a partial listing of the indicated encryption zones
+ *
+ * @param id the index of encryption zones.
+ * @param ezl append the returned encryption zones.
+ * @return return true if there are more items.
+ */
+ virtual bool listEncryptionZones(const int64_t id, std::vector<EncryptionZoneInfo> & ezl) = 0;
+
+ /**
+ * list the contents of an encryption zone.
+ * @return Return a iterator to visit all elements in this encryption zone.
+ */
+ virtual EncryptionZoneIterator listEncryptionZone() = 0;
+
+
+ /**
+ * list all the contents of encryption zones.
+ * @param id the index of encryption zones.
+ * @return Return a vector of encryption zones information..
+ */
+ virtual std::vector<EncryptionZoneInfo> listAllEncryptionZoneItems() = 0;
+};
+
+}
+}
+#endif /* _HDFS_LIBHDFS3_CLIENT_FILESYSTEMINTER_H_ */
diff --git a/src/client/FileSystemKey.cpp b/src/client/FileSystemKey.cpp
new file mode 100644
index 0000000..09318f8
--- /dev/null
+++ b/src/client/FileSystemKey.cpp
@@ -0,0 +1,93 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "Exception.h"
+#include "ExceptionInternal.h"
+#include "FileSystemKey.h"
+
+#include <algorithm>
+#include <libxml/uri.h>
+#include <sstream>
+
+namespace Hdfs {
+namespace Internal {
+
+FileSystemKey::FileSystemKey(const std::string & uri, const char * u) {
+ xmlURIPtr uriobj;
+ std::stringstream ss;
+ ss.imbue(std::locale::classic());
+ uriobj = xmlParseURI(uri.c_str());
+
+ try {
+ if (!uriobj || uriobj->server == NULL || 0 == strlen(uriobj->server)) {
+ THROW(InvalidParameter,
+ "Invalid input: uri: %s is not a valid URI type.", uri.c_str());
+ }
+
+ host = uriobj->server;
+
+ if (NULL == uriobj->scheme || 0 == strlen(uriobj->scheme)) {
+ scheme = "hdfs";
+ } else {
+ scheme = uriobj->scheme;
+ }
+
+ if (strcasecmp(scheme.c_str(), "hdfs")) {
+ THROW(InvalidParameter,
+ "Invalid input: uri is not a valid URI type.");
+ }
+
+ if (u && strlen(u) > 0) {
+ user = UserInfo(u);
+ } else if (NULL == uriobj->user || 0 == strlen(uriobj->user)) {
+ user = UserInfo::LocalUser();
+ } else {
+ user = UserInfo(uriobj->user);
+ }
+
+ ss << user.getEffectiveUser();
+
+ if (uriobj->port == 0) {
+ ss << "@" << uriobj->server;
+ } else {
+ std::stringstream s;
+ s.imbue(std::locale::classic());
+ s << uriobj->port;
+ port = s.str();
+ ss << "@" << uriobj->server << ":" << uriobj->port;
+ }
+
+ authority = ss.str();
+ } catch (...) {
+ if (uriobj) {
+ xmlFreeURI(uriobj);
+ }
+
+ throw;
+ }
+
+ xmlFreeURI(uriobj);
+ std::transform(authority.begin(), authority.end(), authority.begin(), tolower);
+ std::transform(scheme.begin(), scheme.end(), scheme.begin(), tolower);
+}
+
+}
+}
diff --git a/src/client/FileSystemKey.h b/src/client/FileSystemKey.h
new file mode 100644
index 0000000..83be25c
--- /dev/null
+++ b/src/client/FileSystemKey.h
@@ -0,0 +1,101 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_CLIENT_FILESYSTEMKEY_H_
+#define _HDFS_LIBHDFS3_CLIENT_FILESYSTEMKEY_H_
+
+#include "Hash.h"
+#include "UserInfo.h"
+
+#include <string>
+
+namespace Hdfs {
+namespace Internal {
+
+class FileSystemKey {
+public:
+ FileSystemKey(const std::string & uri, const char * user);
+
+ FileSystemKey(const std::string & auth, const std::string & host,
+ const std::string & port, const std::string & scheme,
+ const std::string & user, size_t u) :
+ authority(auth), host(host), port(port), scheme(scheme), user(user) {
+ }
+
+ bool operator ==(const FileSystemKey & other) const {
+ return scheme == other.scheme && authority == other.authority;
+ }
+
+ size_t hash_value() const {
+ size_t values[] = { StringHasher(scheme), StringHasher(authority)};
+ return CombineHasher(values, sizeof(values) / sizeof(values[0]));
+ }
+
+ const std::string & getHost() const {
+ return host;
+ }
+
+ void setHost(const std::string & host) {
+ this->host = host;
+ }
+
+ const std::string & getPort() const {
+ return port;
+ }
+
+ void setPort(const std::string & port) {
+ this->port = port;
+ }
+
+ const std::string & getScheme() const {
+ return scheme;
+ }
+
+ void setScheme(const std::string & scheme) {
+ this->scheme = scheme;
+ }
+
+ const UserInfo & getUser() const {
+ return user;
+ }
+
+ void setUser(const UserInfo & user) {
+ this->user = user;
+ }
+
+ void addToken(const Token & token) {
+ user.addToken(token);
+ }
+
+private:
+ std::string authority;
+ std::string host;
+ std::string port;
+ std::string scheme;
+ UserInfo user;
+};
+
+}
+}
+
+HDFS_HASH_DEFINE(Hdfs::Internal::FileSystemKey);
+
+#endif /* _HDFS_LIBHDFS3_CLIENT_FILESYSTEMKEY_H_ */
diff --git a/src/client/FileSystemStats.h b/src/client/FileSystemStats.h
new file mode 100644
index 0000000..8c9b0f2
--- /dev/null
+++ b/src/client/FileSystemStats.h
@@ -0,0 +1,83 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HDFS_LIBHDFS3_CLIENT_FSSTATS_H_
+#define _HDFS_LIBHDFS3_CLIENT_FSSTATS_H_
+
+#include <stdint.h>
+
+namespace Hdfs {
+
+/**
+ * file system statistics
+ */
+class FileSystemStats {
+public:
+ /**
+ * To construct a FileSystemStats.
+ */
+ FileSystemStats() :
+ capacity(-1), used(-1), remaining(-1) {
+ }
+
+ /**
+ * To construct a FileSystemStats with given values.
+ * @param capacity the capacity of file system.
+ * @param used the space which has been used.
+ * @param remaining available space on file system.
+ */
+ FileSystemStats(int64_t capacity, int64_t used, int64_t remaining) :
+ capacity(capacity), used(used), remaining(remaining) {
+ }
+
+ /**
+ * Return the capacity in bytes of the file system
+ * @return capacity of file system.
+ */
+ int64_t getCapacity() {
+ return capacity;
+ }
+
+ /**
+ * Return the number of bytes used on the file system
+ * @return return used space.
+ */
+ int64_t getUsed() {
+ return used;
+ }
+
+ /**
+ * Return the number of remaining bytes on the file system
+ * @return return available space.
+ */
+ int64_t getRemaining() {
+ return remaining;
+ }
+
+private:
+ int64_t capacity;
+ int64_t used;
+ int64_t remaining;
+
+};
+
+}
+#endif /* _HDFS_LIBHDFS3_CLIENT_FSSTATS_H_ */
diff --git a/src/client/Hdfs.cpp b/src/client/Hdfs.cpp
new file mode 100644
index 0000000..2840adc
--- /dev/null
+++ b/src/client/Hdfs.cpp
@@ -0,0 +1,1565 @@
+/********************************************************************
+ * 2014 -
+ * open source under Apache License Version 2.0
+ ********************************************************************/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "platform.h"
+
+#include "Exception.h"
+#include "ExceptionInternal.h"
+#include "FileSystem.h"
+#include "hdfs.h"
+#include "InputStream.h"
+#include "Logger.h"
+#include "Logger.h"
+#include "Memory.h"
+#include "OutputStream.h"
+#include "server/NamenodeInfo.h"
+#include "SessionConfig.h"
+#include "Thread.h"
+#include "XmlConfig.h"
+
+#include <vector>
+#include <string>
+#include <libxml/uri.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define KERBEROS_TICKET_CACHE_PATH "hadoop.security.kerberos.ticket.cache.path"
+
+#ifndef ERROR_MESSAGE_BUFFER_SIZE
+#define ERROR_MESSAGE_BUFFER_SIZE 4096
+#endif
+
+static THREAD_LOCAL char ErrorMessage[ERROR_MESSAGE_BUFFER_SIZE] = "Success";
+
+static void SetLastException(Hdfs::exception_ptr e) {
+ std::string buffer;
+ const char *p;
+ p = Hdfs::Internal::GetExceptionMessage(e, buffer);
+ strncpy(ErrorMessage, p, sizeof(ErrorMessage) - 1);
+ ErrorMessage[sizeof(ErrorMessage) - 1] = 0;
+}
+
+static void SetErrorMessage(const char *msg) {
+ assert(NULL != msg);
+ strncpy(ErrorMessage, msg, sizeof(ErrorMessage) - 1);
+ ErrorMessage[sizeof(ErrorMessage) - 1] = 0;
+}
+
+#define PARAMETER_ASSERT(para, retval, eno) \
+ if (!(para)) { \
+ SetErrorMessage(Hdfs::Internal::GetSystemErrorInfo(eno)); \
+ errno = eno; \
+ return retval; \
+ }
+
+static inline char * Strdup(const char * str) {
+ if (str == NULL) {
+ return NULL;
+ }
+
+ int len = strlen(str);
+ char * retval = new char[len + 1];
+ memcpy(retval, str, len + 1);
+ return retval;
+}
+
+using Hdfs::InputStream;
+using Hdfs::OutputStream;
+using Hdfs::FileSystem;
+using Hdfs::exception_ptr;
+using Hdfs::Config;
+using Hdfs::Internal::shared_ptr;
+using Hdfs::NamenodeInfo;
+using Hdfs::FileNotFoundException;
+
+struct HdfsFileInternalWrapper {
+public:
+ HdfsFileInternalWrapper() :
+ input(true), stream(NULL) {
+ }
+
+ ~HdfsFileInternalWrapper() {
+ if (input) {
+ delete static_cast<InputStream *>(stream);
+ } else {
+ delete static_cast<OutputStream *>(stream);
+ }
+ }
+
+ InputStream & getInputStream() {
+ if (!input) {
+ THROW(Hdfs::HdfsException,
+ "Internal error: file was not opened for read.");
+ }
+
+ if (!stream) {
+ THROW(Hdfs::HdfsIOException, "File is not opened.");
+ }
+
+ return *static_cast<InputStream *>(stream);
+ }
+ OutputStream & getOutputStream() {
+ if (input) {
+ THROW(Hdfs::HdfsException,
+ "Internal error: file was not opened for write.");
+ }
+
+ if (!stream) {
+ THROW(Hdfs::HdfsIOException, "File is not opened.");
+ }
+
+ return *static_cast<OutputStream *>(stream);
+ }
+
+ bool isInput() const {
+ return input;
+ }
+
+ void setInput(bool input) {
+ this->input = input;
+ }
+
+ void setStream(void * stream) {
+ this->stream = stream;
+ }
+
+private:
+ bool input;
+ void * stream;
+};
+
+struct HdfsFileSystemInternalWrapper {
+public:
+ HdfsFileSystemInternalWrapper(FileSystem * fs) :
+ filesystem(fs) {
+ }
+
+ ~HdfsFileSystemInternalWrapper() {
+ delete filesystem;
+ }
+
+ FileSystem & getFilesystem() {
+ return *filesystem;
+ }
+
+private:
+ FileSystem * filesystem;
+};
+
+class DefaultConfig {
+public:
+ DefaultConfig() : conf(new Hdfs::Config) {
+ bool reportError = false;
+ const char * env = getenv("LIBHDFS3_CONF");
+ std::string confPath = env ? env : "";
+
+ if (!confPath.empty()) {
+ size_t pos = confPath.find_first_of('=');
+
+ if (pos != confPath.npos) {
+ confPath = confPath.c_str() + pos + 1;
+ }
+
+ reportError = true;
+ } else {
+ confPath = "hdfs-client.xml";
+ }
+
+ init(confPath, reportError);
+ }
+
+ DefaultConfig(const char * path) : conf(new Hdfs::Config) {
+ assert(path != NULL && strlen(path) > 0);
+ init(path, true);
+ }
+
+ shared_ptr<Config> getConfig() {
+ return conf;
+ }
+
+private:
+ void init(const std::string & confPath, bool reportError) {
+ if (access(confPath.c_str(), R_OK)) {
+ if (reportError) {
+ LOG(Hdfs::Internal::LOG_ERROR,
+ "Environment variable LIBHDFS3_CONF is set but %s cannot be read",
+ confPath.c_str());
+ } else {
+ return;
+ }
+ }
+
+ conf->update(confPath.c_str());
+ }
+private:
+ shared_ptr<Config> conf;
+};
+
+struct hdfsBuilder {
+public:
+ hdfsBuilder() :
+ conf(DefaultConfig().getConfig()), port(0) {
+ }
+
+ ~hdfsBuilder() {
+ }
+
+public:
+ std::string token;
+ shared_ptr<Config> conf;
+ std::string nn;
+ std::string userName;
+ tPort port;
+};
+
+static void handleException(Hdfs::exception_ptr error) {
+ try {
+ Hdfs::rethrow_exception(error);
+
+#ifndef NDEBUG
+ std::string buffer;
+ LOG(Hdfs::Internal::LOG_ERROR, "Handle Exception: %s",
+ Hdfs::Internal::GetExceptionDetail(error, buffer));
+#endif
+ } catch (Hdfs::AccessControlException &) {
+ errno = EACCES;
+ } catch (Hdfs::AlreadyBeingCreatedException &) {
+ errno = EBUSY;
+ } catch (Hdfs::ChecksumException &) {
+ errno = EIO;
+ } catch (Hdfs::DSQuotaExceededException &) {
+ errno = ENOSPC;
+ } catch (Hdfs::FileAlreadyExistsException &) {
+ errno = EEXIST;
+ } catch (Hdfs::FileNotFoundException &) {
+ errno = ENOENT;
+ } catch (const Hdfs::HdfsBadBoolFoumat &) {
+ errno = EINVAL;
+ } catch (const Hdfs::HdfsBadConfigFoumat &) {
+ errno = EINVAL;
+ } catch (const Hdfs::HdfsBadNumFoumat &) {
+ errno = EINVAL;
+ } catch (const Hdfs::HdfsCanceled &) {
+ errno = EIO;
+ } catch (const Hdfs::HdfsConfigInvalid &) {
+ errno = EINVAL;
+ } catch (const Hdfs::HdfsConfigNotFound &) {
+ errno = EINVAL;
+ } catch (const Hdfs::HdfsEndOfStream &) {
+ errno = EOVERFLOW;
+ } catch (const Hdfs::HdfsInvalidBlockToken &) {
+ errno = EPERM;
+ } catch (const Hdfs::HdfsTimeoutException &) {
+ errno = EIO;
+ } catch (Hdfs::HadoopIllegalArgumentException &) {
+ errno = EINVAL;
+ } catch (Hdfs::InvalidParameter &) {
+ errno = EINVAL;
+ } catch (Hdfs::InvalidPath &) {
+ errno = EINVAL;
+ } catch (Hdfs::NotReplicatedYetException &) {
+ errno = EINVAL;
+ } catch (Hdfs::NSQuotaExceededException &) {
+ errno = EINVAL;
+ } catch (Hdfs::ParentNotDirectoryException &) {
+ errno = EACCES;
+ } catch (Hdfs::ReplicaNotFoundException &) {
+ errno = EACCES;
+ } catch (Hdfs::SafeModeException &) {
+ errno = EIO;
+ } catch (Hdfs::UnresolvedLinkException &) {
+ errno = EACCES;
+ } catch (Hdfs::HdfsRpcException &) {
+ errno = EIO;
+ } catch (Hdfs::HdfsNetworkException &) {
+ errno = EIO;
+ } catch (Hdfs::RpcNoSuchMethodException &) {
+ errno = ENOTSUP;
+ } catch (Hdfs::UnsupportedOperationException &) {
+ errno = ENOTSUP;
+ } catch (Hdfs::SaslException &) {
+ errno = EACCES;
+ } catch (Hdfs::NameNodeStandbyException &) {
+ errno = EIO;
+ } catch (Hdfs::RecoveryInProgressException &){
+ errno = EBUSY;
+ } catch (Hdfs::HdfsIOException &) {
+ std::string buffer;
+ LOG(Hdfs::Internal::LOG_ERROR, "Handle Exception: %s", Hdfs::Internal::GetExceptionDetail(error, buffer));
+ errno = EIO;
+ } catch (Hdfs::HdfsException & e) {
+ std::string buffer;
+ LOG(Hdfs::Internal::LOG_ERROR, "Unexpected exception %s: %s", typeid(e).name(),
+ Hdfs::Internal::GetExceptionDetail(e, buffer));
+ errno = EINTERNAL;
+ } catch (std::exception & e) {
+ LOG(Hdfs::Internal::LOG_ERROR, "Unexpected exception %s: %s", typeid(e).name(), e.what());
+ errno = EINTERNAL;
+ }
+}
+
+const char * hdfsGetLastError() {
+ return ErrorMessage;
+}
+
+int hdfsFileIsOpenForRead(hdfsFile file) {
+ PARAMETER_ASSERT(file, 0, EINVAL);
+ return file->isInput() ? 1 : 0;
+}
+
+int hdfsFileIsOpenForWrite(hdfsFile file) {
+ PARAMETER_ASSERT(file, 0, EINVAL);
+ return !file->isInput() ? 1 : 0;
+}
+
+hdfsFS hdfsConnectAsUser(const char * host, tPort port, const char * user) {
+ hdfsFS retVal = NULL;
+ PARAMETER_ASSERT(host != NULL && strlen(host) > 0, NULL, EINVAL);
+ PARAMETER_ASSERT(port > 0, NULL, EINVAL);
+ PARAMETER_ASSERT(user != NULL && strlen(user) > 0, NULL, EINVAL);
+ struct hdfsBuilder * bld = hdfsNewBuilder();
+
+ if (!bld)
+ return NULL;
+
+ hdfsBuilderSetNameNode(bld, host);
+ hdfsBuilderSetNameNodePort(bld, port);
+ hdfsBuilderSetUserName(bld, user);
+ retVal = hdfsBuilderConnect(bld);
+ hdfsFreeBuilder(bld);
+ return retVal;
+}
+
+hdfsFS hdfsConnect(const char * host, tPort port) {
+ hdfsFS retVal = NULL;
+ PARAMETER_ASSERT(host != NULL && strlen(host) > 0, NULL, EINVAL);
+ PARAMETER_ASSERT(port > 0, NULL, EINVAL);
+ struct hdfsBuilder * bld = hdfsNewBuilder();
+
+ if (!bld)
+ return NULL;
+
+ hdfsBuilderSetNameNode(bld, host);
+ hdfsBuilderSetNameNodePort(bld, port);
+ retVal = hdfsBuilderConnect(bld);
+ hdfsFreeBuilder(bld);
+ return retVal;
+}
+
+hdfsFS hdfsConnectAsUserNewInstance(const char * host, tPort port,
+ const char * user) {
+ hdfsFS retVal = NULL;
+ PARAMETER_ASSERT(host != NULL && strlen(host) > 0, NULL, EINVAL);
+ PARAMETER_ASSERT(port > 0, NULL, EINVAL);
+ PARAMETER_ASSERT(user != NULL && strlen(user) > 0, NULL, EINVAL);
+ struct hdfsBuilder * bld = hdfsNewBuilder();
+
+ if (!bld)
+ return NULL;
+
+ hdfsBuilderSetNameNode(bld, host);
+ hdfsBuilderSetNameNodePort(bld, port);
+ hdfsBuilderSetForceNewInstance(bld);
+ hdfsBuilderSetUserName(bld, user);
+ retVal = hdfsBuilderConnect(bld);
+ hdfsFreeBuilder(bld);
+ return retVal;
+}
+
+hdfsFS hdfsConnectNewInstance(const char * host, tPort port) {
+ hdfsFS retVal = NULL;
+ PARAMETER_ASSERT(host != NULL && strlen(host) > 0, NULL, EINVAL);
+ PARAMETER_ASSERT(port > 0, NULL, EINVAL);
+ struct hdfsBuilder * bld = hdfsNewBuilder();
+
+ if (!bld)
+ return NULL;
+
+ hdfsBuilderSetNameNode(bld, host);
+ hdfsBuilderSetNameNodePort(bld, port);
+ hdfsBuilderSetForceNewInstance(bld);
+ retVal = hdfsBuilderConnect(bld);
+ hdfsFreeBuilder(bld);
+ return retVal;
+}
+
+hdfsFS hdfsBuilderConnect(struct hdfsBuilder * bld) {
+ PARAMETER_ASSERT(bld && !bld->nn.empty(), NULL, EINVAL);
+ Hdfs::Internal::SessionConfig conf(*bld->conf);
+ std::string uri;
+ std::stringstream ss;
+ ss.imbue(std::locale::classic());
+ xmlURIPtr uriobj;
+ FileSystem * fs = NULL;
+
+ if (0 == strcasecmp(bld->nn.c_str(), "default")) {
+ uri = conf.getDefaultUri();
+ } else {
+ /*
+ * handle scheme
+ */
+ if (bld->nn.find("://") == bld->nn.npos) {
+ uri = "hdfs://";
+ }
+
+ uri += bld->nn;
+ }
+
+ uriobj = xmlParseURI(uri.c_str());
+
+ try {
+ if (!uriobj) {
+ THROW(Hdfs::InvalidParameter, "Cannot parse connection URI");
+ }
+
+ if (uriobj->port != 0 && bld->port != 0) {
+ THROW(Hdfs::InvalidParameter, "Cannot determinate port");
+ }
+
+ if (uriobj->user && !bld->userName.empty()) {
+ THROW(Hdfs::InvalidParameter, "Cannot determinate user name");
+ }
+
+ ss << uriobj->scheme << "://";
+
+ if (uriobj->user || !bld->userName.empty()) {
+ ss << (uriobj->user ? uriobj->user : bld->userName.c_str())
+ << '@';
+ }
+
+ if (bld->port == 0 && uriobj->port == 0) {
+ ss << uriobj->server;
+ } else {
+ ss << uriobj->server << ":" << (uriobj->port ? uriobj->port : bld->port);
+ }
+
+ uri = ss.str();
+ } catch (const std::bad_alloc & e) {
+ if (uriobj) {
+ xmlFreeURI(uriobj);
+ }
+
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ return NULL;
+ } catch (...) {
+ if (uriobj) {
+ xmlFreeURI(uriobj);
+ }
+
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ return NULL;
+ }
+
+ xmlFreeURI(uriobj);
+
+ try {
+ fs = new FileSystem(*bld->conf);
+
+ if (!bld->token.empty()) {
+ fs->connect(uri.c_str(), NULL, bld->token.c_str());
+ } else {
+ fs->connect(uri.c_str());
+ }
+
+ return new HdfsFileSystemInternalWrapper(fs);
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ delete fs;
+ errno = ENOMEM;
+ } catch (...) {
+ delete fs;
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return NULL;
+}
+
+struct hdfsBuilder * hdfsNewBuilder(void) {
+ try {
+ return new struct hdfsBuilder;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return NULL;
+}
+
+void hdfsFreeBuilder(struct hdfsBuilder * bld) {
+ delete bld;
+}
+
+void hdfsBuilderSetForceNewInstance(struct hdfsBuilder * bld) {
+ assert(bld);
+}
+
+void hdfsBuilderSetNameNode(struct hdfsBuilder * bld, const char * nn) {
+ assert(bld != NULL && nn != NULL);
+ bld->nn = nn;
+}
+
+void hdfsBuilderSetNameNodePort(struct hdfsBuilder * bld, tPort port) {
+ assert(bld != NULL && port > 0);
+ bld->port = port;
+}
+
+void hdfsBuilderSetUserName(struct hdfsBuilder * bld, const char * userName) {
+ assert(bld && userName && strlen(userName) > 0);
+ bld->userName = userName;
+}
+
+void hdfsBuilderSetKerbTicketCachePath(struct hdfsBuilder * bld,
+ const char * kerbTicketCachePath) {
+ assert(bld && kerbTicketCachePath && strlen(kerbTicketCachePath) > 0);
+ hdfsBuilderConfSetStr(bld, KERBEROS_TICKET_CACHE_PATH, kerbTicketCachePath);
+}
+
+void hdfsBuilderSetToken(struct hdfsBuilder * bld, const char * token) {
+ assert(bld && token && strlen(token) > 0 && bld->userName.empty());
+
+ try {
+ bld->token = token;
+ } catch (const std::bad_alloc & e) {
+ errno = ENOMEM;
+ } catch (...) {
+ handleException(Hdfs::current_exception());
+ }
+}
+
+int hdfsBuilderConfSetStr(struct hdfsBuilder * bld, const char * key,
+ const char * val) {
+ PARAMETER_ASSERT(bld && key && strlen(key) > 0, -1, EINVAL);
+ PARAMETER_ASSERT(val && strlen(val) > 0, -1, EINVAL);
+
+ try {
+ bld->conf->set(key, val);
+ return 0;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+int hdfsConfGetStr(const char * key, char ** val) {
+ PARAMETER_ASSERT(key && strlen(key) > 0 && val, -1, EINVAL);
+
+ try {
+ std::string retval = DefaultConfig().getConfig()->getString(key);
+ *val = Strdup(retval.c_str());
+ return 0;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+void hdfsConfStrFree(char * val) {
+ delete[] val;
+}
+
+int hdfsConfGetInt(const char * key, int32_t * val) {
+ PARAMETER_ASSERT(key && strlen(key) > 0 && val, -1, EINVAL);
+
+ try {
+ *val = DefaultConfig().getConfig()->getInt32(key);
+ return 0;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+int hdfsDisconnect(hdfsFS fs) {
+ try {
+ if (fs) {
+ fs->getFilesystem().disconnect();
+ delete fs;
+ }
+
+ return 0;
+ } catch (const std::bad_alloc & e) {
+ delete fs;
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ delete fs;
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+hdfsFile hdfsOpenFile(hdfsFS fs, const char * path, int flags, int bufferSize,
+ short replication, tOffset blocksize) {
+ PARAMETER_ASSERT(fs && path && strlen(path) > 0, NULL, EINVAL);
+ PARAMETER_ASSERT(bufferSize >= 0 && replication >= 0 && blocksize >= 0, NULL, EINVAL);
+ PARAMETER_ASSERT(!(flags & O_RDWR) && !((flags & O_EXCL) && (flags & O_CREAT)), NULL, ENOTSUP);
+ HdfsFileInternalWrapper * file = NULL;
+ OutputStream * os = NULL;
+ InputStream * is = NULL;
+
+ try {
+ file = new HdfsFileInternalWrapper();
+
+ if ((flags & O_CREAT) || (flags & O_APPEND) || (flags & O_WRONLY)) {
+ int internalFlags = 0;
+
+ if (flags & O_CREAT) {
+ internalFlags |= Hdfs::Create;
+ } else if ((flags & O_APPEND) && (flags & O_WRONLY)) {
+ internalFlags |= Hdfs::Create;
+ internalFlags |= Hdfs::Append;
+ } else if (flags & O_WRONLY) {
+ internalFlags |= Hdfs::Create;
+ internalFlags |= Hdfs::Overwrite;
+ }
+
+ if (flags & O_SYNC) {
+ internalFlags |= Hdfs::SyncBlock;
+ }
+
+ file->setInput(false);
+ os = new OutputStream;
+ os->open(fs->getFilesystem(), path, internalFlags, 0777, false, replication,
+ blocksize);
+ file->setStream(os);
+ } else {
+ file->setInput(true);
+ is = new InputStream;
+ is->open(fs->getFilesystem(), path, true);
+ file->setStream(is);
+ }
+
+ return file;
+ } catch (const std::bad_alloc & e) {
+ delete file;
+ delete os;
+ delete is;
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ delete file;
+ delete os;
+ delete is;
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return NULL;
+}
+
+int hdfsCloseFile(hdfsFS fs, hdfsFile file) {
+ PARAMETER_ASSERT(fs, -1, EINVAL);
+
+ try {
+ if (file) {
+ if (file->isInput()) {
+ file->getInputStream().close();
+ } else {
+ file->getOutputStream().close();
+ }
+
+ delete file;
+ }
+
+ return 0;
+ } catch (const std::bad_alloc & e) {
+ delete file;
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ delete file;
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+int hdfsExists(hdfsFS fs, const char * path) {
+ PARAMETER_ASSERT(fs && path && strlen(path) > 0, -1, EINVAL);
+
+ try {
+ return fs->getFilesystem().exist(path) ? 0 : -1;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+int hdfsSeek(hdfsFS fs, hdfsFile file, tOffset desiredPos) {
+ PARAMETER_ASSERT(fs && file && desiredPos >= 0, -1, EINVAL);
+ PARAMETER_ASSERT(file->isInput(), -1, EINVAL);
+
+ try {
+ file->getInputStream().seek(desiredPos);
+ return 0;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+tOffset hdfsTell(hdfsFS fs, hdfsFile file) {
+ PARAMETER_ASSERT(fs && file, -1, EINVAL);
+
+ try {
+ if (file->isInput()) {
+ return file->getInputStream().tell();
+ } else {
+ return file->getOutputStream().tell();
+ }
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+tSize hdfsRead(hdfsFS fs, hdfsFile file, void * buffer, tSize length) {
+ PARAMETER_ASSERT(fs && file && buffer && length > 0, -1, EINVAL);
+ PARAMETER_ASSERT(file->isInput(), -1, EINVAL);
+
+ try {
+ return file->getInputStream().read(static_cast<char *>(buffer), length);
+ } catch (const Hdfs::HdfsEndOfStream & e) {
+ return 0;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+tSize hdfsWrite(hdfsFS fs, hdfsFile file, const void * buffer, tSize length) {
+ PARAMETER_ASSERT(fs && file && buffer && length > 0, -1, EINVAL);
+ PARAMETER_ASSERT(!file->isInput(), -1, EINVAL);
+
+ try {
+ file->getOutputStream().append(static_cast<const char *>(buffer),
+ length);
+ return length;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+int hdfsFlush(hdfsFS fs, hdfsFile file) {
+ PARAMETER_ASSERT(fs && file && file, -1, EINVAL);
+ return hdfsHFlush(fs, file);
+}
+
+int hdfsHFlush(hdfsFS fs, hdfsFile file) {
+ PARAMETER_ASSERT(fs && file && file, -1, EINVAL);
+ PARAMETER_ASSERT(!file->isInput(), -1, EINVAL);
+
+ try {
+ file->getOutputStream().flush();
+ return 0;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+int hdfsSync(hdfsFS fs, hdfsFile file) {
+ PARAMETER_ASSERT(fs && file && file, -1, EINVAL);
+ PARAMETER_ASSERT(!file->isInput(), -1, EINVAL);
+
+ try {
+ file->getOutputStream().sync();
+ return 0;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+int hdfsAvailable(hdfsFS fs, hdfsFile file) {
+ PARAMETER_ASSERT(fs && file && file, -1, EINVAL);
+ PARAMETER_ASSERT(file->isInput(), -1, EINVAL);
+
+ try {
+ int max = std::numeric_limits<int>::max();
+ int64_t retval = file->getInputStream().available();
+ return retval < max ? retval : max;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+int hdfsCopy(hdfsFS srcFS, const char *src, hdfsFS dstFS, const char *dst) {
+ PARAMETER_ASSERT(srcFS && dstFS, -1, EINVAL);
+ PARAMETER_ASSERT(src && strlen(src) > 0, -1, EINVAL);
+ PARAMETER_ASSERT(dst && strlen(dst) > 0, -1, EINVAL);
+
+ errno = ENOTSUP;
+ return -1;
+}
+
+int hdfsMove(hdfsFS srcFS, const char *src, hdfsFS dstFS, const char *dst) {
+ PARAMETER_ASSERT(srcFS && dstFS, -1, EINVAL);
+ PARAMETER_ASSERT(src && strlen(src) > 0, -1, EINVAL);
+ PARAMETER_ASSERT(dst && strlen(dst) > 0, -1, EINVAL);
+
+ errno = ENOTSUP;
+ return -1;
+}
+
+int hdfsDelete(hdfsFS fs, const char * path, int recursive) {
+ PARAMETER_ASSERT(fs && path && strlen(path) > 0, -1, EINVAL);
+
+ try {
+ return fs->getFilesystem().deletePath(path, recursive) ? 0 : -1;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+int hdfsRename(hdfsFS fs, const char * oldPath, const char * newPath) {
+ PARAMETER_ASSERT(fs && oldPath && strlen(oldPath) > 0, -1, EINVAL);
+ PARAMETER_ASSERT(newPath && strlen(newPath) > 0, -1, EINVAL);
+
+ try {
+ return fs->getFilesystem().rename(oldPath, newPath) ? 0 : -1;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+char * hdfsGetWorkingDirectory(hdfsFS fs, char * buffer, size_t bufferSize) {
+ PARAMETER_ASSERT(fs && buffer && bufferSize > 0, NULL, EINVAL);
+
+ try {
+ std::string retval = fs->getFilesystem().getWorkingDirectory();
+ PARAMETER_ASSERT(retval.length() + 1 <= bufferSize, NULL, ENOMEM);
+ strncpy(buffer, retval.c_str(), bufferSize);
+ return buffer;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return NULL;
+}
+
+int hdfsSetWorkingDirectory(hdfsFS fs, const char * path) {
+ PARAMETER_ASSERT(fs && path && strlen(path) > 0, -1, EINVAL);
+
+ try {
+ fs->getFilesystem().setWorkingDirectory(path);
+ return 0;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+int hdfsCreateDirectory(hdfsFS fs, const char * path) {
+ PARAMETER_ASSERT(fs && path && strlen(path) > 0, -1, EINVAL);
+
+ try {
+ return fs->getFilesystem().mkdirs(path, 0755) ? 0 : -1;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+int hdfsSetReplication(hdfsFS fs, const char * path, int16_t replication) {
+ PARAMETER_ASSERT(fs && path && strlen(path) > 0 && replication > 0, -1, EINVAL);
+
+ try {
+ return fs->getFilesystem().setReplication(path, replication) ? 0 : -1;
+ } catch (const std::bad_alloc & e) {
+ SetErrorMessage("Out of memory");
+ errno = ENOMEM;
+ } catch (...) {
+ SetLastException(Hdfs::current_exception());
+ handleException(Hdfs::current_exception());
+ }
+
+ return -1;
+}
+
+static void ConstructHdfsEncryptionZoneInfo(hdfsEncryptionZoneInfo * infoEn,
+ std::vector<Hdfs::EncryptionZoneInfo> & enStatus) {
+ size_t size = enStatus.size();
+
+ for (size_t i = 0; i < size; ++i) {
+ infoEn[i].mSuite = enStatus[i].getSuite();
+ infoEn[i].mCryptoProtocolVersion = enStatus[i].getCryptoProtocolVersion();
+ infoEn[i].mId = enStatus[i].getId();
+ infoEn[i].mPath = Strdup(enStatus[i].getPath());
+ infoEn[i].mKeyName = Strdup(enStatus[i].getKeyName());
+ }
+}
+
+static void ConstructHdfsEncryptionFileInfo(hdfsEncryptionFileInfo * infoEn,
+ Hdfs::FileEncryptionInfo* enStatus) {
+ infoEn->mSuite = enStatus->getSuite();
+ infoEn->mCryptoProtocolVersion = enStatus->getCryptoProtocolVersion();
+ infoEn->mKey = const_cast<char*>(enStatus->getKey().c_str());
+ infoEn->mKeyName = const_cast<char*>(enStatus->getKeyName().c_str());
+ infoEn->mIv = const_cast<char*>(enStatus->getIv().c_str());
+ infoEn->mEzKeyVersionName = const_cast<char*>(enStatus->getEzKeyVersionName().c_str());
+}
+
+static void ConstructHdfsFileInfo(hdfsFileInfo * infos,
+ std::vector<Hdfs::FileStatus> & status) {
+ size_t size = status.size();
+
+ for (size_t i = 0; i < size; ++i) {
... 35849 lines suppressed ...
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org