exception.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #include "exception.h"
  19. #include "hdfs.h"
  20. #include "jni_helper.h"
  21. #include "platform.h"
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #define EXCEPTION_INFO_LEN (sizeof(gExceptionInfo)/sizeof(gExceptionInfo[0]))
  26. struct ExceptionInfo {
  27. const char * const name;
  28. int noPrintFlag;
  29. int excErrno;
  30. };
  31. static const struct ExceptionInfo gExceptionInfo[] = {
  32. {
  33. "java.io.FileNotFoundException",
  34. NOPRINT_EXC_FILE_NOT_FOUND,
  35. ENOENT,
  36. },
  37. {
  38. "org.apache.hadoop.security.AccessControlException",
  39. NOPRINT_EXC_ACCESS_CONTROL,
  40. EACCES,
  41. },
  42. {
  43. "org.apache.hadoop.fs.UnresolvedLinkException",
  44. NOPRINT_EXC_UNRESOLVED_LINK,
  45. ENOLINK,
  46. },
  47. {
  48. "org.apache.hadoop.fs.ParentNotDirectoryException",
  49. NOPRINT_EXC_PARENT_NOT_DIRECTORY,
  50. ENOTDIR,
  51. },
  52. {
  53. "java.lang.IllegalArgumentException",
  54. NOPRINT_EXC_ILLEGAL_ARGUMENT,
  55. EINVAL,
  56. },
  57. {
  58. "java.lang.OutOfMemoryError",
  59. 0,
  60. ENOMEM,
  61. },
  62. {
  63. "org.apache.hadoop.hdfs.server.namenode.SafeModeException",
  64. 0,
  65. EROFS,
  66. },
  67. {
  68. "org.apache.hadoop.fs.FileAlreadyExistsException",
  69. 0,
  70. EEXIST,
  71. },
  72. {
  73. "org.apache.hadoop.hdfs.protocol.QuotaExceededException",
  74. 0,
  75. EDQUOT,
  76. },
  77. {
  78. "org.apache.hadoop.hdfs.server.namenode.LeaseExpiredException",
  79. 0,
  80. ESTALE,
  81. },
  82. };
  83. void getExceptionInfo(const char *excName, int noPrintFlags,
  84. int *excErrno, int *shouldPrint)
  85. {
  86. int i;
  87. for (i = 0; i < EXCEPTION_INFO_LEN; i++) {
  88. if (strstr(gExceptionInfo[i].name, excName)) {
  89. break;
  90. }
  91. }
  92. if (i < EXCEPTION_INFO_LEN) {
  93. *shouldPrint = !(gExceptionInfo[i].noPrintFlag & noPrintFlags);
  94. *excErrno = gExceptionInfo[i].excErrno;
  95. } else {
  96. *shouldPrint = 1;
  97. *excErrno = EINTERNAL;
  98. }
  99. }
  100. int printExceptionAndFreeV(JNIEnv *env, jthrowable exc, int noPrintFlags,
  101. const char *fmt, va_list ap)
  102. {
  103. int i, noPrint, excErrno;
  104. char *className = NULL;
  105. jstring jStr = NULL;
  106. jvalue jVal;
  107. jthrowable jthr;
  108. const char *stackTrace;
  109. jthr = classNameOfObject(exc, env, &className);
  110. if (jthr) {
  111. fprintf(stderr, "PrintExceptionAndFree: error determining class name "
  112. "of exception.\n");
  113. className = strdup("(unknown)");
  114. destroyLocalReference(env, jthr);
  115. }
  116. for (i = 0; i < EXCEPTION_INFO_LEN; i++) {
  117. if (!strcmp(gExceptionInfo[i].name, className)) {
  118. break;
  119. }
  120. }
  121. if (i < EXCEPTION_INFO_LEN) {
  122. noPrint = (gExceptionInfo[i].noPrintFlag & noPrintFlags);
  123. excErrno = gExceptionInfo[i].excErrno;
  124. } else {
  125. noPrint = 0;
  126. excErrno = EINTERNAL;
  127. }
  128. if (!noPrint) {
  129. vfprintf(stderr, fmt, ap);
  130. fprintf(stderr, " error:\n");
  131. // We don't want to use ExceptionDescribe here, because that requires a
  132. // pending exception. Instead, use ExceptionUtils.
  133. jthr = invokeMethod(env, &jVal, STATIC, NULL,
  134. "org/apache/commons/lang/exception/ExceptionUtils",
  135. "getStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;", exc);
  136. if (jthr) {
  137. fprintf(stderr, "(unable to get stack trace for %s exception: "
  138. "ExceptionUtils::getStackTrace error.)\n", className);
  139. destroyLocalReference(env, jthr);
  140. } else {
  141. jStr = jVal.l;
  142. stackTrace = (*env)->GetStringUTFChars(env, jStr, NULL);
  143. if (!stackTrace) {
  144. fprintf(stderr, "(unable to get stack trace for %s exception: "
  145. "GetStringUTFChars error.)\n", className);
  146. } else {
  147. fprintf(stderr, "%s", stackTrace);
  148. (*env)->ReleaseStringUTFChars(env, jStr, stackTrace);
  149. }
  150. }
  151. }
  152. destroyLocalReference(env, jStr);
  153. destroyLocalReference(env, exc);
  154. free(className);
  155. return excErrno;
  156. }
  157. int printExceptionAndFree(JNIEnv *env, jthrowable exc, int noPrintFlags,
  158. const char *fmt, ...)
  159. {
  160. va_list ap;
  161. int ret;
  162. va_start(ap, fmt);
  163. ret = printExceptionAndFreeV(env, exc, noPrintFlags, fmt, ap);
  164. va_end(ap);
  165. return ret;
  166. }
  167. int printPendingExceptionAndFree(JNIEnv *env, int noPrintFlags,
  168. const char *fmt, ...)
  169. {
  170. va_list ap;
  171. int ret;
  172. jthrowable exc;
  173. exc = (*env)->ExceptionOccurred(env);
  174. if (!exc) {
  175. va_start(ap, fmt);
  176. vfprintf(stderr, fmt, ap);
  177. va_end(ap);
  178. fprintf(stderr, " error: (no exception)");
  179. ret = 0;
  180. } else {
  181. (*env)->ExceptionClear(env);
  182. va_start(ap, fmt);
  183. ret = printExceptionAndFreeV(env, exc, noPrintFlags, fmt, ap);
  184. va_end(ap);
  185. }
  186. return ret;
  187. }
  188. jthrowable getPendingExceptionAndClear(JNIEnv *env)
  189. {
  190. jthrowable jthr = (*env)->ExceptionOccurred(env);
  191. if (!jthr)
  192. return NULL;
  193. (*env)->ExceptionClear(env);
  194. return jthr;
  195. }
  196. jthrowable newRuntimeError(JNIEnv *env, const char *fmt, ...)
  197. {
  198. char buf[512];
  199. jobject out, exc;
  200. jstring jstr;
  201. va_list ap;
  202. va_start(ap, fmt);
  203. vsnprintf(buf, sizeof(buf), fmt, ap);
  204. va_end(ap);
  205. jstr = (*env)->NewStringUTF(env, buf);
  206. if (!jstr) {
  207. // We got an out of memory exception rather than a RuntimeException.
  208. // Too bad...
  209. return getPendingExceptionAndClear(env);
  210. }
  211. exc = constructNewObjectOfClass(env, &out, "RuntimeException",
  212. "(java/lang/String;)V", jstr);
  213. (*env)->DeleteLocalRef(env, jstr);
  214. // Again, we'll either get an out of memory exception or the
  215. // RuntimeException we wanted.
  216. return (exc) ? exc : out;
  217. }