hdfsJniHelper.c
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:13k
源码类别:

网格计算

开发平台:

Java

  1. /**
  2.  * Copyright 2006 The Apache Software Foundation
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *     http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. #include <string.h> 
  17. #include <error.h>
  18. #include "hdfsJniHelper.h"
  19. static pthread_mutex_t hdfsHashMutex = PTHREAD_MUTEX_INITIALIZER;
  20. static pthread_mutex_t jvmMutex = PTHREAD_MUTEX_INITIALIZER;
  21. static volatile int hashTableInited = 0;
  22. #define LOCK_HASH_TABLE() pthread_mutex_lock(&hdfsHashMutex)
  23. #define UNLOCK_HASH_TABLE() pthread_mutex_unlock(&hdfsHashMutex)
  24. #define LOCK_JVM_MUTEX() pthread_mutex_lock(&jvmMutex)
  25. #define UNLOCK_JVM_MUTEX() pthread_mutex_unlock(&jvmMutex)
  26. /** The Native return types that methods could return */
  27. #define VOID          'V'
  28. #define JOBJECT       'L'
  29. #define JARRAYOBJECT  '['
  30. #define JBOOLEAN      'Z'
  31. #define JBYTE         'B'
  32. #define JCHAR         'C'
  33. #define JSHORT        'S'
  34. #define JINT          'I'
  35. #define JLONG         'J'
  36. #define JFLOAT        'F'
  37. #define JDOUBLE       'D'
  38. /**
  39.  * MAX_HASH_TABLE_ELEM: The maximum no. of entries in the hashtable.
  40.  * It's set to 4096 to account for (classNames + No. of threads)
  41.  */
  42. #define MAX_HASH_TABLE_ELEM 4096
  43. static int validateMethodType(MethType methType)
  44. {
  45.     if (methType != STATIC && methType != INSTANCE) {
  46.         fprintf(stderr, "Unimplemented method typen");
  47.         return 0;
  48.     }
  49.     return 1;
  50. }
  51. static int hashTableInit(void)
  52. {
  53.     if (!hashTableInited) {
  54.         LOCK_HASH_TABLE();
  55.         if (!hashTableInited) {
  56.             if (hcreate(MAX_HASH_TABLE_ELEM) == 0) {
  57.                 fprintf(stderr, "error creating hashtable, <%d>: %sn",
  58.                         errno, strerror(errno));
  59.                 return 0;
  60.             } 
  61.             hashTableInited = 1;
  62.         }
  63.         UNLOCK_HASH_TABLE();
  64.     }
  65.     return 1;
  66. }
  67. static int insertEntryIntoTable(const char *key, void *data)
  68. {
  69.     ENTRY e, *ep;
  70.     if (key == NULL || data == NULL) {
  71.         return 0;
  72.     }
  73.     if (! hashTableInit()) {
  74.       return -1;
  75.     }
  76.     e.data = data;
  77.     e.key = (char*)key;
  78.     LOCK_HASH_TABLE();
  79.     ep = hsearch(e, ENTER);
  80.     UNLOCK_HASH_TABLE();
  81.     if (ep == NULL) {
  82.         fprintf(stderr, "warn adding key (%s) to hash table, <%d>: %sn",
  83.                 key, errno, strerror(errno));
  84.     }  
  85.     return 0;
  86. }
  87. static void* searchEntryFromTable(const char *key)
  88. {
  89.     ENTRY e,*ep;
  90.     if (key == NULL) {
  91.         return NULL;
  92.     }
  93.     hashTableInit();
  94.     e.key = (char*)key;
  95.     LOCK_HASH_TABLE();
  96.     ep = hsearch(e, FIND);
  97.     UNLOCK_HASH_TABLE();
  98.     if (ep != NULL) {
  99.         return ep->data;
  100.     }
  101.     return NULL;
  102. }
  103. int invokeMethod(JNIEnv *env, RetVal *retval, Exc *exc, MethType methType,
  104.                  jobject instObj, const char *className,
  105.                  const char *methName, const char *methSignature, ...)
  106. {
  107.     va_list args;
  108.     jclass cls;
  109.     jmethodID mid;
  110.     jthrowable jthr;
  111.     const char *str; 
  112.     char returnType;
  113.     
  114.     if (! validateMethodType(methType)) {
  115.       return -1;
  116.     }
  117.     cls = globalClassReference(className, env);
  118.     if (cls == NULL) {
  119.       return -2;
  120.     }
  121.     mid = methodIdFromClass(className, methName, methSignature, 
  122.                             methType, env);
  123.     if (mid == NULL) {
  124.         (*env)->ExceptionDescribe(env);
  125.         return -3;
  126.     }
  127.    
  128.     str = methSignature;
  129.     while (*str != ')') str++;
  130.     str++;
  131.     returnType = *str;
  132.     va_start(args, methSignature);
  133.     if (returnType == JOBJECT || returnType == JARRAYOBJECT) {
  134.         jobject jobj = NULL;
  135.         if (methType == STATIC) {
  136.             jobj = (*env)->CallStaticObjectMethodV(env, cls, mid, args);
  137.         }
  138.         else if (methType == INSTANCE) {
  139.             jobj = (*env)->CallObjectMethodV(env, instObj, mid, args);
  140.         }
  141.         retval->l = jobj;
  142.     }
  143.     else if (returnType == VOID) {
  144.         if (methType == STATIC) {
  145.             (*env)->CallStaticVoidMethodV(env, cls, mid, args);
  146.         }
  147.         else if (methType == INSTANCE) {
  148.             (*env)->CallVoidMethodV(env, instObj, mid, args);
  149.         }
  150.     }
  151.     else if (returnType == JBOOLEAN) {
  152.         jboolean jbool = 0;
  153.         if (methType == STATIC) {
  154.             jbool = (*env)->CallStaticBooleanMethodV(env, cls, mid, args);
  155.         }
  156.         else if (methType == INSTANCE) {
  157.             jbool = (*env)->CallBooleanMethodV(env, instObj, mid, args);
  158.         }
  159.         retval->z = jbool;
  160.     }
  161.     else if (returnType == JSHORT) {
  162.         jshort js = 0;
  163.         if (methType == STATIC) {
  164.             js = (*env)->CallStaticShortMethodV(env, cls, mid, args);
  165.         }
  166.         else if (methType == INSTANCE) {
  167.             js = (*env)->CallShortMethodV(env, instObj, mid, args);
  168.         }
  169.         retval->s = js;
  170.     }
  171.     else if (returnType == JLONG) {
  172.         jlong jl = -1;
  173.         if (methType == STATIC) {
  174.             jl = (*env)->CallStaticLongMethodV(env, cls, mid, args);
  175.         }
  176.         else if (methType == INSTANCE) {
  177.             jl = (*env)->CallLongMethodV(env, instObj, mid, args);
  178.         }
  179.         retval->j = jl;
  180.     }
  181.     else if (returnType == JINT) {
  182.         jint ji = -1;
  183.         if (methType == STATIC) {
  184.             ji = (*env)->CallStaticIntMethodV(env, cls, mid, args);
  185.         }
  186.         else if (methType == INSTANCE) {
  187.             ji = (*env)->CallIntMethodV(env, instObj, mid, args);
  188.         }
  189.         retval->i = ji;
  190.     }
  191.     va_end(args);
  192.     jthr = (*env)->ExceptionOccurred(env);
  193.     if (jthr != NULL) {
  194.         if (exc != NULL)
  195.             *exc = jthr;
  196.         else
  197.             (*env)->ExceptionDescribe(env);
  198.         return -1;
  199.     }
  200.     return 0;
  201. }
  202. jarray constructNewArrayString(JNIEnv *env, Exc *exc, const char **elements, int size) {
  203.   const char *className = "Ljava/lang/String;";
  204.   jobjectArray result;
  205.   int i;
  206.   jclass arrCls = (*env)->FindClass(env, className);
  207.   if (arrCls == NULL) {
  208.     fprintf(stderr, "could not find class %sn",className);
  209.     return NULL; /* exception thrown */
  210.   }
  211.   result = (*env)->NewObjectArray(env, size, arrCls,
  212.                                   NULL);
  213.   if (result == NULL) {
  214.     fprintf(stderr, "ERROR: could not construct new arrayn");
  215.     return NULL; /* out of memory error thrown */
  216.   }
  217.   for (i = 0; i < size; i++) {
  218.     jstring jelem = (*env)->NewStringUTF(env,elements[i]);
  219.     if (jelem == NULL) {
  220.       fprintf(stderr, "ERROR: jelem == NULLn");
  221.     }
  222.     (*env)->SetObjectArrayElement(env, result, i, jelem);
  223.   }
  224.   return result;
  225. }
  226. jobject constructNewObjectOfClass(JNIEnv *env, Exc *exc, const char *className, 
  227.                                   const char *ctorSignature, ...)
  228. {
  229.     va_list args;
  230.     jclass cls;
  231.     jmethodID mid; 
  232.     jobject jobj;
  233.     jthrowable jthr;
  234.     cls = globalClassReference(className, env);
  235.     if (cls == NULL) {
  236.         (*env)->ExceptionDescribe(env);
  237.       return NULL;
  238.     }
  239.     mid = methodIdFromClass(className, "<init>", ctorSignature, 
  240.                             INSTANCE, env);
  241.     if (mid == NULL) {
  242.         (*env)->ExceptionDescribe(env);
  243.         return NULL;
  244.     } 
  245.     va_start(args, ctorSignature);
  246.     jobj = (*env)->NewObjectV(env, cls, mid, args);
  247.     va_end(args);
  248.     jthr = (*env)->ExceptionOccurred(env);
  249.     if (jthr != NULL) {
  250.         if (exc != NULL)
  251.             *exc = jthr;
  252.         else
  253.             (*env)->ExceptionDescribe(env);
  254.     }
  255.     return jobj;
  256. }
  257. jmethodID methodIdFromClass(const char *className, const char *methName, 
  258.                             const char *methSignature, MethType methType, 
  259.                             JNIEnv *env)
  260. {
  261.     jclass cls = globalClassReference(className, env);
  262.     if (cls == NULL) {
  263.       fprintf(stderr, "could not find class %sn", className);
  264.       return NULL;
  265.     }
  266.     jmethodID mid = 0;
  267.     if (!validateMethodType(methType)) {
  268.       fprintf(stderr, "invalid method typen");
  269.       return NULL;
  270.     }
  271.     if (methType == STATIC) {
  272.         mid = (*env)->GetStaticMethodID(env, cls, methName, methSignature);
  273.     }
  274.     else if (methType == INSTANCE) {
  275.         mid = (*env)->GetMethodID(env, cls, methName, methSignature);
  276.     }
  277.     if (mid == NULL) {
  278.       fprintf(stderr, "could not find method %s from class %s with signature %sn",methName, className, methSignature);
  279.     }
  280.     return mid;
  281. }
  282. jclass globalClassReference(const char *className, JNIEnv *env)
  283. {
  284.     jclass clsLocalRef;
  285.     jclass cls = searchEntryFromTable(className);
  286.     if (cls) {
  287.         return cls; 
  288.     }
  289.     clsLocalRef = (*env)->FindClass(env,className);
  290.     if (clsLocalRef == NULL) {
  291.         (*env)->ExceptionDescribe(env);
  292.         return NULL;
  293.     }
  294.     cls = (*env)->NewGlobalRef(env, clsLocalRef);
  295.     if (cls == NULL) {
  296.         (*env)->ExceptionDescribe(env);
  297.         return NULL;
  298.     }
  299.     (*env)->DeleteLocalRef(env, clsLocalRef);
  300.     insertEntryIntoTable(className, cls);
  301.     return cls;
  302. }
  303. char *classNameOfObject(jobject jobj, JNIEnv *env) {
  304.     jclass cls, clsClass;
  305.     jmethodID mid;
  306.     jstring str;
  307.     const char *cstr;
  308.     char *newstr;
  309.     cls = (*env)->GetObjectClass(env, jobj);
  310.     if (cls == NULL) {
  311.         (*env)->ExceptionDescribe(env);
  312.         return NULL;
  313.     }
  314.     clsClass = (*env)->FindClass(env, "java/lang/Class");
  315.     if (clsClass == NULL) {
  316.         (*env)->ExceptionDescribe(env);
  317.         return NULL;
  318.     }
  319.     mid = (*env)->GetMethodID(env, clsClass, "getName", "()Ljava/lang/String;");
  320.     if (mid == NULL) {
  321.         (*env)->ExceptionDescribe(env);
  322.         return NULL;
  323.     }
  324.     str = (*env)->CallObjectMethod(env, cls, mid);
  325.     if (str == NULL) {
  326.         (*env)->ExceptionDescribe(env);
  327.         return NULL;
  328.     }
  329.     cstr = (*env)->GetStringUTFChars(env, str, NULL);
  330.     newstr = strdup(cstr);
  331.     (*env)->ReleaseStringUTFChars(env, str, cstr);
  332.     if (newstr == NULL) {
  333.         perror("classNameOfObject: strdup");
  334.         return NULL;
  335.     }
  336.     return newstr;
  337. }
  338. /**
  339.  * getJNIEnv: A helper function to get the JNIEnv* for the given thread.
  340.  * If no JVM exists, then one will be created. JVM command line arguments
  341.  * are obtained from the LIBHDFS_OPTS environment variable.
  342.  *
  343.  * @param: None.
  344.  * @return The JNIEnv* corresponding to the thread.
  345.  */
  346. JNIEnv* getJNIEnv(void)
  347. {
  348.     const jsize vmBufLength = 1;
  349.     JavaVM* vmBuf[vmBufLength]; 
  350.     JNIEnv *env;
  351.     jint rv = 0; 
  352.     jint noVMs = 0;
  353.     // Only the first thread should create the JVM. The other trheads should
  354.     // just use the JVM created by the first thread.
  355.     LOCK_JVM_MUTEX();
  356.     rv = JNI_GetCreatedJavaVMs(&(vmBuf[0]), vmBufLength, &noVMs);
  357.     if (rv != 0) {
  358.         fprintf(stderr, "JNI_GetCreatedJavaVMs failed with error: %dn", rv);
  359.         UNLOCK_JVM_MUTEX();
  360.         return NULL;
  361.     }
  362.     if (noVMs == 0) {
  363.         //Get the environment variables for initializing the JVM
  364.         char *hadoopClassPath = getenv("CLASSPATH");
  365.         if (hadoopClassPath == NULL) {
  366.             fprintf(stderr, "Environment variable CLASSPATH not set!n");
  367.             UNLOCK_JVM_MUTEX();
  368.             return NULL;
  369.         } 
  370.         char *hadoopClassPathVMArg = "-Djava.class.path=";
  371.         size_t optHadoopClassPathLen = strlen(hadoopClassPath) + 
  372.           strlen(hadoopClassPathVMArg) + 1;
  373.         char *optHadoopClassPath = malloc(sizeof(char)*optHadoopClassPathLen);
  374.         snprintf(optHadoopClassPath, optHadoopClassPathLen,
  375.                 "%s%s", hadoopClassPathVMArg, hadoopClassPath);
  376.         int noArgs = 1;
  377.         //determine how many arguments were passed as LIBHDFS_OPTS env var
  378.         char *hadoopJvmArgs = getenv("LIBHDFS_OPTS");
  379.         char jvmArgDelims[] = " ";
  380.         if (hadoopJvmArgs != NULL)  {
  381.                 char *result = NULL;
  382.                 result = strtok( hadoopJvmArgs, jvmArgDelims );
  383.                 while ( result != NULL ) {
  384.                         noArgs++;
  385.          result = strtok( NULL, jvmArgDelims);
  386.             }
  387.         }
  388.         JavaVMOption options[noArgs];
  389.         options[0].optionString = optHadoopClassPath;
  390. //fill in any specified arguments
  391. if (hadoopJvmArgs != NULL)  {
  392.             char *result = NULL;
  393.             result = strtok( hadoopJvmArgs, jvmArgDelims );
  394.             int argNum = 1;
  395.             for (;argNum < noArgs ; argNum++) {
  396.                 options[argNum].optionString = result; //optHadoopArg;
  397.             }
  398.         }
  399.         //Create the VM
  400.         JavaVMInitArgs vm_args;
  401.         JavaVM *vm;
  402.         vm_args.version = JNI_VERSION_1_2;
  403.         vm_args.options = options;
  404.         vm_args.nOptions = noArgs; 
  405.         vm_args.ignoreUnrecognized = 1;
  406.         rv = JNI_CreateJavaVM(&vm, (void*)&env, &vm_args);
  407.         if (rv != 0) {
  408.             fprintf(stderr, "Call to JNI_CreateJavaVM failed "
  409.                     "with error: %dn", rv);
  410.             UNLOCK_JVM_MUTEX();
  411.             return NULL;
  412.         }
  413.         free(optHadoopClassPath);
  414.     }
  415.     else {
  416.         //Attach this thread to the VM
  417.         JavaVM* vm = vmBuf[0];
  418.         rv = (*vm)->AttachCurrentThread(vm, (void*)&env, 0);
  419.         if (rv != 0) {
  420.             fprintf(stderr, "Call to AttachCurrentThread "
  421.                     "failed with error: %dn", rv);
  422.             UNLOCK_JVM_MUTEX();
  423.             return NULL;
  424.         }
  425.     }
  426.     UNLOCK_JVM_MUTEX();
  427.     return env;
  428. }