All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bigdata.btree.BytesUtil.c Maven / Gradle / Ivy

/**

Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

Contact:
     SYSTAP, LLC DBA Blazegraph
     2501 Calvert ST NW #106
     Washington, DC 20008
     [email protected]

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
/*
 * This file contains JNI implementations of routines declared by
 * BytesUtil.java.
 *
 * @see http://java.sun.com/docs/books/jni/html/jniTOC.html
 */

/*
 * Compile the Java class and then generate the C header file from that class.
 * From the bigdata directory, do:

# Note: This approach no longer works as executed due to new imports that
# can not be trivially resolved by javac.
#
# cd bigdata
# javac src/java/com/bigdata/btree/BytesUtil.java
# javah -classpath src/java com.bigdata.btree.BytesUtil

# The easiest thing to do is "ant jar" first to generate the class files.
# Then you can do something like:
#
ant bundleJar # generate the class files, the jar, and colocate the dependency jars.
cd bigdata
javah -classpath ../ant-build/classes com.bigdata.btree.BytesUtil

This places the .h files in the bigdata directory.

Now compile the C file. You can compile this under linux as follows:

## For linux.
export JAVA_HOME="/usr/java/jdk1.7.0_25"
export JAVA_INCLUDE=$JAVA_HOME/include
## For OSX
export JAVA_HOME=$(/usr/libexec/java_home)
export JAVA_INCLUDE=/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers

# For both : put the java version on the command path.
export PATH=$JAVA_HOME/bin:$PATH

# For linux.
gcc -fPIC -g -I$JAVA_INCLUDE -I$JAVA_INCLUDE/linux -c src/java/com/bigdata/btree/BytesUtil.c
#
# For OSX
gcc -fPIC -g -I. -I$JAVA_INCLUDE -c src/java/com/bigdata/btree/BytesUtil.c

# Works for linux/OSX.
gcc -shared -W1,-soname,libBytesUtil.so -o libBytesUtil.so BytesUtil.o -lc

## At this point you have something like the following in the cwd:
# header files from javac.
# com_bigdata_btree_BytesUtil.h
# com_bigdata_btree_BytesUtil_UnsignedByteArrayComparator.h
# Compiled version of BytesUtil.c
# BytesUtil.o
# Shared library for BytesUtil.o
# libBytesUtil.so - shared library.

# For both : specify the location of the shared libraries (once compiled).
export LD_LIBRARY_PATH=.

# Execute the test program:
java -Dcom.bigdata.btree.BytesUtil.jni=true -classpath ../ant-build/classes:../ant-build/lib/log4j-1.2.17.jar com.bigdata.btree.BytesUtil

----

 * On Win32, the following command builds a dynamic link library (DLL)
 * using the Microsoft Visual C++ compiler:

cl -I. "-I%JAVA_HOME%\include" "-I%JAVA_HOME%\include\win32" -LD src/java/com/bigdata/btree/BytesUtil.c -FeBytesUtil.dll

other things tried, some of which may work or have useful optimizations:

cl options
/nologo /G6 /MTd /W3 /Gm /GX /ZI /Od /YX

link options:
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
/nologo /dll /incremental:no /machine:I386 /pdbtype:sept

cl "-I%JAVA_HOME%\include" "-I%JAVA_HOME%\include\win32" -c /G6 /MTd /W3 /Gm /GX /ZI /Od /YX BytesUtil.c

cl "-I%JAVA_HOME%\include" "-I%JAVA_HOME%\include\win32" -c BytesUtil.c

link /dll /debug /incremental:no /machine:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib BytesUtil.obj

cl /GD /LD "-I%JAVA_HOME%\include" "-I%JAVA_HOME%\include\win32" BytesUtil.c

-- some possible options: /W3 /WX /MD 

or try something like:

cl /O1 /Zi /MD /D _STATIC_CPPLIB /W3 /DNDEBUG /DWIN32 /DIAL /D_LITTLE_ENDIAN /D_X86_ /Dx86 /DWIN32_LEAN_AND_MEAN /c *.c 

link /dll /opt:REF /incremental:no /debug /out:XXX.dll *.obj 

See http://weblogs.java.net/blog/kellyohair/archive/2006/01/index.html for this example.

*/
 
/* Java on the Win32 platform requires a different declaration for
   jlong (__int64 vs long long).  This causes problems that I have not
   been able to resolve when trying to use cygwin/gcc to compile the
   code under windows.

   typedef long long jlong;
*/

#include 
#include 
#include "com_bigdata_btree_BytesUtil.h"

/**
 * Bit-wise comparison of unsigned byte[]s.
 * 
 * @param a A byte[].
 * 
 * @param b A byte[].
 * 
 * @return a negative integer, zero, or a positive integer as the
 * first argument is less than, equal to, or greater than the second.
 */
JNIEXPORT jint JNICALL Java_com_bigdata_btree_BytesUtil__1compareBytes
  (JNIEnv *env, jclass cl, jint alen, jbyteArray a, jint blen, jbyteArray b)
{

   // lock (or maybe copy) the array contents.
   register jbyte *a1 = (*env)->GetPrimitiveArrayCritical(env, a, 0);

   register jbyte *b1 = (*env)->GetPrimitiveArrayCritical(env, b, 0);

   register int i;

   register int ret;

   /* We need to check in case the VM tried to make a copy. */
   if (a1 != NULL && b1 != NULL) {

     // data are good - compare unsigned byte[]s.
     for ( i = 0; i < alen && i < blen; i++) {

       ret = ((unsigned char)a1[i]) - ((unsigned char)b1[i]);

       if (ret != 0) {

         // release lock on arrays.
         (*env)->ReleasePrimitiveArrayCritical(env, b, b1, 0);
         (*env)->ReleasePrimitiveArrayCritical(env, a, a1, 0);

	 // done: arrays differ at index[i].
         return ret;

       }

     }

     // release lock on arrays.
     (*env)->ReleasePrimitiveArrayCritical(env, b, b1, 0);
     (*env)->ReleasePrimitiveArrayCritical(env, a, a1, 0);

     // done.
     return alen - blen;

     } else {

       /* Throw an out of memory exception */

       jclass newExcCls;

       // release lock on arrays.

       if(b1 != NULL) (*env)->ReleasePrimitiveArrayCritical(env, b, b1, 0);

       if(a1 != NULL) (*env)->ReleasePrimitiveArrayCritical(env, a, a1, 0);

       newExcCls = (*env)->FindClass(env, 
                       "java/lang/OutOfMemoryError");

         if (newExcCls == NULL) {

             /* Unable to find the exception class, give up. */

             return 0;

         }

         (*env)->ThrowNew(env, newExcCls, "in ByteUtils JNI code");

	 return 0; // keep the compiler happy.

     }

}

/**
 * Byte-wise comparison of byte[]s (the arrays are treated as arrays of
 * unsigned bytes).
 * 
 * @param aoff The offset into a at which the comparison will
 * begin.
 *
 * @param alen The #of bytes in a to consider starting at
 * aoff.
 *
 * @param a A byte[].
 *
 * @param boff The offset into b at which the comparison will
 * begin.
 *
 * @param blen The #of bytes in b to consider starting at
 * boff.
 *
 * @param b A byte[].
 * 
 * @return a negative integer, zero, or a positive integer as the
 * first argument is less than, equal to, or greater than the second.
 */
JNIEXPORT jint JNICALL Java_com_bigdata_btree_BytesUtil__1compareBytesWithOffsetAndLen
  (JNIEnv *env, jclass cl,
   jint aoff, jint alen, jbyteArray a, 
   jint boff, jint blen, jbyteArray b
   )
{

   // lock (or maybe copy) the array contents.
   register jbyte *a1 = (*env)->GetPrimitiveArrayCritical(env, a, 0);

   register jbyte *b1 = (*env)->GetPrimitiveArrayCritical(env, b, 0);

   // last index to consider in a[].
   const jint alimit = aoff + alen;

   // last index to consider in b[].
   const jint blimit = boff + blen;

   register int i, j;

   register int ret;

   /* We need to check in case the VM tried to make a copy. */
   if (a1 != NULL && b1 != NULL) {

     for ( i = aoff, j = boff; i < alimit && j < blimit; i++, j++) {

       ret = ((unsigned char)a1[i]) - ((unsigned char)b1[j]);

       if (ret != 0) {

         // release lock on arrays.

         (*env)->ReleasePrimitiveArrayCritical(env, b, b1, 0);

         (*env)->ReleasePrimitiveArrayCritical(env, a, a1, 0);

         return ret;

       }

     }

     // release lock on arrays.

     (*env)->ReleasePrimitiveArrayCritical(env, b, b1, 0);

     (*env)->ReleasePrimitiveArrayCritical(env, a, a1, 0);

     return alen - blen;

     } else {

       /* Throw an out of memory exception */

       jclass newExcCls;

       // release lock on arrays.

       if(b1 != NULL) (*env)->ReleasePrimitiveArrayCritical(env, b, b1, 0);

       if(a1 != NULL) (*env)->ReleasePrimitiveArrayCritical(env, a, a1, 0);

       newExcCls = (*env)->FindClass(env, 
                       "java/lang/OutOfMemoryError");

         if (newExcCls == NULL) {

             /* Unable to find the exception class, give up. */

             return 0;

         }

         (*env)->ThrowNew(env, newExcCls, "in ByteUtils JNI code");

	 return 0; // keep the compiler happy.

     }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy