Skip to content

Commit

Permalink
[ALLUXIO-51] Provide C++ binding (#6514)
Browse files Browse the repository at this point in the history
* add basic classes

* fix license header

* fix

* fix

* add

* delete blank space

* fix style

* fix style

* fix style

* fix

* small fix

* add rw test function

* fix bug

* fix version

* fix

* add cmake

* fix test failed

* fix

* fix mistakes

* fix mistakes

* fix mistakes

* fix

* small fix

* small fix

* Add pom

* fix

* add mvn unit

* add fix

* add space

* fix ljvm miss

* delete dir

* add

* fix environment variable

* delete

* fix README

* fix ctest exception

* delete

* fix

* add JNIHelper test unit

* fix

* fix README

* fix README

* fix

* fix

* add client doc

* fix priority

* fix
  • Loading branch information
Lichongjie authored and apc999 committed Mar 8, 2018
1 parent 435d826 commit 5bac80b
Show file tree
Hide file tree
Showing 26 changed files with 3,060 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -17,6 +17,7 @@
.project
.settings/
/client/
/cpp/build/*
/conf/alluxio-env.sh
/conf/metrics.properties
/conf/alluxio-env.sh.bootstrap.bk
Expand Down
89 changes: 89 additions & 0 deletions cpp/CMakeLists.txt
@@ -0,0 +1,89 @@
#
# The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
# (the "License"). You may not use this work except in compliance with the License, which is
# available at www.apache.org/licenses/LICENSE-2.0
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied, as more fully set forth in the License.
#
# See the NOTICE file distributed with this work for information regarding copyright ownership.
#

cmake_minimum_required(VERSION 3.0.1 FATAL_ERROR)

PROJECT(Alluxio_cpp_client)

SET(CMAKE_BUILE_TYPE DEBUG)
SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

SET(ALLUXIO_CPP_VERSION 1.0)

if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
# Locate JNI_INCLUDE_DIRS and JNI_LIBRARIES.
# Since we were invoked from Maven, we know that the JAVA_HOME environment
# variable is valid. So we ignore system paths here and just use JAVA_HOME.
file(TO_CMAKE_PATH "$ENV{JAVA_HOME}" _java_home)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i.86$")
set(_java_libarch "i386")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")
set(_java_libarch "amd64")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
set(_java_libarch "arm")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le")
if(EXISTS "${_java_home}/jre/lib/ppc64le")
set(_java_libarch "ppc64le")
else()
set(_java_libarch "ppc64")
endif()
else()
set(_java_libarch ${CMAKE_SYSTEM_PROCESSOR})
endif()
set(_JDK_DIRS "${_java_home}/jre/lib/${_java_libarch}/*"
"${_java_home}/jre/lib/${_java_libarch}"
"${_java_home}/jre/lib/*"
"${_java_home}/jre/lib"
"${_java_home}/lib/*"
"${_java_home}/lib"
"${_java_home}/include/*"
"${_java_home}/include"
"${_java_home}"
)
find_path(JAVA_INCLUDE_PATH
NAMES jni.h
PATHS ${_JDK_DIRS}
NO_DEFAULT_PATH)
#In IBM java, it's jniport.h instead of jni_md.h
find_path(JAVA_INCLUDE_PATH2
NAMES jni_md.h jniport.h
PATHS ${_JDK_DIRS}
NO_DEFAULT_PATH)
set(JNI_INCLUDE_DIRS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
find_library(JAVA_JVM_LIBRARY
NAMES jvm JavaVM
PATHS ${_JDK_DIRS}
NO_DEFAULT_PATH)
set(JNI_LIBRARIES ${JAVA_JVM_LIBRARY})
unset(_java_libarch)
unset(_java_home)

message("JAVA_HOME=${JAVA_HOME}, JAVA_JVM_LIBRARY=${JAVA_JVM_LIBRARY}")
message("JAVA_INCLUDE_PATH=${JAVA_INCLUDE_PATH}, JAVA_INCLUDE_PATH2=${JAVA_INCLUDE_PATH2}")
if(JAVA_JVM_LIBRARY AND JAVA_INCLUDE_PATH AND JAVA_INCLUDE_PATH2)
message("Located all JNI components successfully.")
else()
message(FATAL_ERROR "Failed to find a viable JVM installation under JAVA_HOME.")
endif()

# Use the standard FindJNI module to locate the JNI components.
find_package(JNI REQUIRED)

#
# Otherwise, use the standard FindJNI module to locate the JNI components.
#
else()
find_package(JNI REQUIRED)
endif()

ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(test)
85 changes: 85 additions & 0 deletions cpp/README.md
@@ -0,0 +1,85 @@
# Alluxio C++ API

### Introduction
The C++ client is implemented through JNI to native Java client. Generally the
performance of using java client directly is better than calling c++ client,
because JNI calling type needs to cross programming language barrier.

### Environment variables configuration
- $JAVA_HOME must be set
- Java 8 is needed.
- Add path "$JAVA_HOME/jre/lib/i386/server"(32bit) or "$JAVA_HOME/jre/lib/amd64/server"(64bit)or
"$JAVA_HOME/jre/lib/server"(Darwin) to "LD_LIBRARY_PATH" depending on your OS platform version
- Append $ALLUXIO_CLIENT_CLASSPATH to CLASSPATH in libexec/alluxio-config.sh.
```
. alluxio-config.sh
export CLASSPATH=$CLASSPATH:$ALLUXIO_CLIENT_CLASSPATH
```

### Example
- Use cmake to build library
```
cd $ALLUXIO_HOME/cpp
mkdir build
cd build
cmake ../
make
```
You will get a static library `liballuxio1.0.a`, a shared link library
`liballuxio1.0.so`(linux) or `liballuxio1.0.dylib`(macOS) in cpp/build/src

- Build library of cpp module by mvn
```
cd ${ALLUXIO_HOME}/cpp
mvn clean install
```
Both the static library and the shared library are generated at cpp/target/native/src

- Compile and run your application
```
g++ test.cpp liballuxio.a
-I${ALLUXIO_HOME}/cpp/include -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux
-L${JRE_HOME}/lib/amd64/server -lpthread -ljvm -o test
# run the application
./test
```
This is a simple example to link library to your program `test.cpp`. Notice
that JNI included paths are needed. Or you can use CMake or autotools to build
your project. The executable file `test` will be generated.

- C++ example
```
#include <fileSystem.h>
using namespace alluxio;
int main(void){
FileSystem* fileSystem = new FileSystem();
AlluxioURI* uri = new AlluxioURI("/foo");
FileOutStream* out;
Status stus = fileSystem->CreateFile(*uri, &out);
if (stus.ok) {
out->Write("test write", 0, 10);
out->Close();
}
delete uri;
delete out;
delete fileSystem;
return 0;
}
```

### Test

- You can run executable files mapping to different test cases directly
```
cd $ALLUXIO_HOME/cpp/build/test
./fileSystemTest
./fileRWTest
```
- Or use mvn tools to test all cases included in cpp module
```
cd ${ALLUXIO_HOME}/cpp
mvn test
```
49 changes: 49 additions & 0 deletions cpp/include/alluxioURI.h
@@ -0,0 +1,49 @@
/**
* The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
* (the "License"). You may not use this work except in compliance with the License, which is
* available at www.apache.org/licenses/LICENSE-2.0
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied, as more fully set forth in the License.
*
* See the NOTICE file distributed with this work for information regarding copyright ownership.
*/

#ifndef CPP_INCLUDE_ALLUXIOURI_H_
#define CPP_INCLUDE_ALLUXIOURI_H_

#include "jniHelper.h"

#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <string>

using ::jnihelper::JniHelper;

namespace alluxio {
class AlluxioURI {
public:
explicit AlluxioURI(const std::string& path) {
uri = JniHelper::CreateObjectMethod("alluxio/AlluxioURI", path);
}

explicit AlluxioURI(jobject localObj) {
uri = localObj;
}

~AlluxioURI() {
JniHelper::DeleteObjectRef(uri);
}

const jobject& getObj() const {
return uri;
}

protected:
jobject uri;
};

} // namespace alluxio

#endif // CPP_INCLUDE_ALLUXIOURI_H_
48 changes: 48 additions & 0 deletions cpp/include/fileInStream.h
@@ -0,0 +1,48 @@
/**
* The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
* (the "License"). You may not use this work except in compliance with the License, which is
* available at www.apache.org/licenses/LICENSE-2.0
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied, as more fully set forth in the License.
*
* See the NOTICE file distributed with this work for information regarding copyright ownership.
*/

#ifndef CPP_INCLUDE_FILEINSTREAM_H_
#define CPP_INCLUDE_FILEINSTREAM_H_

#include "jniHelper.h"

using ::jnihelper::JniHelper;

namespace alluxio {

// A streaming API to read a file. This API represents a file as a stream of
// bytes and provides a collection of read methods to access this stream of
// bytes.
class FileInStream {
public:
explicit FileInStream(jobject alluxioInStream);
~FileInStream();
// Reads one byte to b
Status Read(char* b);
// Reads len bytes into buf starting offset off of length len,
Status Read(char* buf, size_t off, size_t len, size_t* result);
// Moves the starting read position of the stream to the specified position
// which is relative to the start of the stream. Seeking to a position before
// the current read position is supported.
Status Seek(size_t pos);
// Skips over and discards <code>n</code> bytes of data from this input
// stream
Status Skip(size_t pos);
// Closes this input stream
Status Close();

private:
jobject inStream;
};

} // namespace alluxio

#endif // CPP_INCLUDE_FILEINSTREAM_H_
44 changes: 44 additions & 0 deletions cpp/include/fileOutStream.h
@@ -0,0 +1,44 @@
/**
* The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
* (the "License"). You may not use this work except in compliance with the License, which is
* available at www.apache.org/licenses/LICENSE-2.0
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied, as more fully set forth in the License.
*
* See the NOTICE file distributed with this work for information regarding copyright ownership.
*/

#ifndef CPP_INCLUDE_FILEOUTSTREAM_H_
#define CPP_INCLUDE_FILEOUTSTREAM_H_

#include "jniHelper.h"

using ::jnihelper::JniHelper;

namespace alluxio {
// Provides a streaming API to write a file
class FileOutStream {
public:
explicit FileOutStream(jobject AlluxioOutStream);
~FileOutStream();
// Writes the specified byte to this output stream
Status Write(char b);
// Writes len bytes from the specified byte array
// starting at offset to this output stream.
Status Write(const char* buf, size_t off, size_t len);
// Flushes this output stream and forces any buffered output bytes
// to be written out.
Status Flush();
// Cancels write operation, closing current stream
Status Cancel();
// Closes current stream
Status Close();

private:
jobject outStream;
};

} // namespace alluxio

#endif // CPP_INCLUDE_FILEOUTSTREAM_H_

0 comments on commit 5bac80b

Please sign in to comment.