The Oracle NoSQL Database C API is a JNI-based library used to build client applications capable of interacting with Oracle NoSQL Database. This C API is released in source form. This page describes how to build the library so that it can be used with your application code.
A Java JDK (Java 7 or later). You should make sure that the JAVA_HOME environment variable is properly set (for CMake)
A C compiler.
Installation of CMake. There are precompiled, ready-to-install binaries for various Linux distributions that can be installed directly. Download links are here, including dmg images for Mac OS X:
Built and installed Avro C library (also requires CMake).
Download source from http://avro.apache.org/releases.html (currently using 1.7.6). Following the download link you can download either the entire source (avro-src-1.7.6.tar.gz) or just the C api source (avro-c-1.7.6.tar.gz). This affects the paths below.
Untar the package. If you downloaded the full source then cd lang/c. If you downloaded the C source just start at the top level directory. Read the INSTALL file, which discusses building from source. Before building, also edit CMakeLists.txt and uncomment the line that reads:
add_definitions(-DAVRO_ALLOW_MISSING_FIELDS_IN_RESOLVED_WRITER)
Build and install the library. If you use a non-standard prefix in -DCMAKE_INSTALL_PREFIX remember that for later. This definition tells CMake where to install the built library and header files. If you use a standard location such as /usr/local or /usr, the default build will find it.
Path to NoSQL Database (kvstore.jar for testing, kvclient.jar for general client applications).
Java runtime (Java 6 or later).
Create a build directory. All build and CMake artifacts reside here for easy cleanup. The build directory can be anywhere as long as the cmake command is:
cmake <path-to-top-level-directory>.
This keeps the source tree clean of build artifacts.
$mkdir build
cd build
Generate makefiles (from build). Make sure that JAVA_HOME is properly set to allow CMake to find the JNI library.
$ cmake <options>
These options are available on the cmake command line:
-DCMAKE_INSTALL_PREFIX=<path-to-install-directory>
This defaults to /usr/local
-DCMAKE_BUILD_TYPE=<type>
Types are: Debug, Release, RelWithDebInfo and MinSizeRel Default is RelWithDebInfo.
-DAVRO_PREFIX_DIR=<path-to-avro-installation>
If Avro has been installed in a non-standard location, this must be passed to locate Avro.
-DKV_PATH_TO_JAR=<path-to-kvstore.jar>
This is required for the "make test" target to find the required jar. This option is recommended for simple testing.
-DKV_TEST_ROOT_DIR=<path-to-root-for-test>
This is used as the root directory for "make test." It defaults to build/test/kvstore.
This command will fail if it is unable to locate either the JNI runtime or Avro. It can be invoked using --trace (see cmake usage) to get additional information about failures.
Once cmake has succeeded, build.
$ make
If there is a problem, some additional information, such as the specific compiler flags being used can be had by doing this:
$ VERBOSE=1 make
The build artifacts end up in build/build/{bin,lib,include} The libraries required to run the interface are lib/libkvstore* and libavro* (wherever that was built). The test suite and example binaries are built into bin but are not required for deployment.
Tests can be run either by directly invoking kvsuite or if KV_PATH_TO_JAR was specified for cmake via make.
$ make test
Output of make test ends up in the file Testing/Temporary/LastTest.log. It can be examined for detailed success and failure information.
Direct test invocation has this usage:
$ build/bin/kvsuite -r <path-to-kvroot> -k <path-to-kvstore.jar> -v
Note the following:
The path to kvroot must contain "kvstore" in it, or it will not work. That is, use something like /tmp/kvstore or /tmp/kvstore/ctest.
Note that the test will only create the final directory in the path, so the rest must exist before running the test.
Make sure there are no stores running on the current node that might collide with respect to registry port.
The "hello" example is built by default. In order to run there must be a store available. KVLite will do on the local machine. For example if you have the Oracle NoSQL Database on your machine you can do this:
java -jar <path-to-kvstore.jar> kvlite
The default port is 5000 on host localhost, with store name kvstore.
Run the program:
build/bin/hello -store kvstore -port 5000 -host localhost \
-jar <path-to-kvclient.jar>
The program can be directed to other stores as well. The hello program stores a simple record, reads it, and outputs the value, which is "Big Data World!" It is a good example of a simple program to perform initialize, open, put, get, and close on a store from the C interface.
Once the build is verified it can be installed to the location specified in the cmake arguments.
$ make install
If additional permissions are required for the installation directory you may need to use
$ sudo make installCompilation requires kvstore.h and must link with libkvstore. For example, if you used -DCMAKE_INSTALL_PREFIX=$HOME/install, on linux you could compile a single file program this way
$ gcc -o myprog myprog.c -I $HOME/install/include -lkvstore -L$HOME/install/lib
Running can be more complicated because libkvstore depends on libavro as well as the the JNI libraries. On Linux LD_LIBRARY_PATH must include paths to all 3.
$ export LD_LIBRARY_PATH=$HOME/install/lib:$JAVA_HOME/
$ ./myprog ...
On MacOS use DYLD_LIBRARY_PATH instead of LD_LIBRARY_PATH and the path to the Java library in $JAVA_HOME is not required.
The CMake framework can be leveraged for your own applications. The simplest way to do this is to add your code to the template provided in examples/CMakeLists.txt file. That file has instructions in its comments. The advantage to this approach is that it will hard-wire the paths to the dependent libraries into the executable (using -rpath in the link step).
Any C program using this interface must have access to the kvclient.jar file and initialize the Java VM. The libraries required for the JVM will have been linked with libkvstore during the build.
There are two ways code that uses the C API can initialize the JVM.
Supply the classpath to the kvclient.jar and use the simple API:
kv_error_t kv_create_jni_impl(kv_impl_t **impl, const char *classpath);
This interface initializes the JVM internally and is what the hello.c example does. It is simple but does not allow the caller to pass additional arguments to the JVM such as min/max heap size or other potentially useful parameters.
Initialize the JVM externally and pass it into the API. This is a little more work but gives the application more flexibility in how the JVM is initialized. This interface is used to pass the JVM object:
kv_error_t kv_create_jni_impl_from_jvm(kv_impl_t **impl, void *jvm);
The void *jvm must be a JavaVM * that was created by a call to the JNI function JNI_CreateJavaVM(). The classpath used to create the JavaVM object must include kvclient.jar.