Return-Path: Delivered-To: apmail-hadoop-common-commits-archive@www.apache.org Received: (qmail 64820 invoked from network); 1 Dec 2010 08:05:38 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 1 Dec 2010 08:05:38 -0000 Received: (qmail 9397 invoked by uid 500); 1 Dec 2010 08:05:38 -0000 Delivered-To: apmail-hadoop-common-commits-archive@hadoop.apache.org Received: (qmail 9364 invoked by uid 500); 1 Dec 2010 08:05:38 -0000 Mailing-List: contact common-commits-help@hadoop.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: common-dev@hadoop.apache.org Delivered-To: mailing list common-commits@hadoop.apache.org Received: (qmail 9357 invoked by uid 99); 1 Dec 2010 08:05:38 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 01 Dec 2010 08:05:38 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 01 Dec 2010 08:05:33 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 466EE2388A3B; Wed, 1 Dec 2010 08:04:00 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1040883 [3/3] - in /hadoop/common/trunk: ./ src/java/org/apache/hadoop/io/ src/java/org/apache/hadoop/io/nativeio/ src/native/ src/native/lib/ src/native/src/ src/native/src/org/apache/hadoop/io/nativeio/ src/test/core/org/apache/hadoop/io... Date: Wed, 01 Dec 2010 08:03:59 -0000 To: common-commits@hadoop.apache.org From: ddas@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20101201080400.466EE2388A3B@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: hadoop/common/trunk/src/native/configure.ac URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/native/configure.ac?rev=1040883&r1=1040882&r2=1040883&view=diff ============================================================================== --- hadoop/common/trunk/src/native/configure.ac (original) +++ hadoop/common/trunk/src/native/configure.ac Wed Dec 1 08:03:58 2010 @@ -38,6 +38,7 @@ AC_INIT(src/org_apache_hadoop.h) AC_CONFIG_SRCDIR([src/org_apache_hadoop.h]) AC_CONFIG_AUX_DIR(config) AC_CONFIG_HEADER([config.h]) +AC_SYS_LARGEFILE AM_INIT_AUTOMAKE(hadoop,1.0.0) @@ -95,6 +96,9 @@ AC_C_CONST # Checks for library functions. AC_CHECK_FUNCS([memset]) +# Check for nonstandard STRERROR_R +AC_FUNC_STRERROR_R + AC_CONFIG_FILES([Makefile]) AC_OUTPUT Modified: hadoop/common/trunk/src/native/lib/Makefile.am URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/native/lib/Makefile.am?rev=1040883&r1=1040882&r2=1040883&view=diff ============================================================================== --- hadoop/common/trunk/src/native/lib/Makefile.am (original) +++ hadoop/common/trunk/src/native/lib/Makefile.am Wed Dec 1 08:03:58 2010 @@ -36,7 +36,7 @@ AM_LDFLAGS = @JNI_LDFLAGS@ -m$(JVM_DATA_ lib_LTLIBRARIES = libhadoop.la libhadoop_la_SOURCES = -libhadoop_la_LDFLAGS = -version-info 1:0:0 +libhadoop_la_LDFLAGS = -version-info 1:0:0 $(AM_LDFLAGS) libhadoop_la_LIBADD = $(HADOOP_OBJS) -ldl -ljvm # Added: hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/NativeIO.c URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/NativeIO.c?rev=1040883&view=auto ============================================================================== --- hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/NativeIO.c (added) +++ hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/NativeIO.c Wed Dec 1 08:03:58 2010 @@ -0,0 +1,277 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// get the autoconf settings +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "org_apache_hadoop.h" +#include "org_apache_hadoop_io_nativeio_NativeIO.h" +#include "file_descriptor.h" +#include "errno_enum.h" + +// the NativeIO$Stat inner class and its constructor +static jclass stat_clazz; +static jmethodID stat_ctor; + +// the NativeIOException class and its constructor +static jclass nioe_clazz; +static jmethodID nioe_ctor; + +// Internal functions +static void throw_ioe(JNIEnv* env, int errnum); +static ssize_t get_pw_buflen(); + + +static void stat_init(JNIEnv *env) { + // Init Stat + jclass clazz = (*env)->FindClass(env, "org/apache/hadoop/io/nativeio/NativeIO$Stat"); + PASS_EXCEPTIONS(env); + stat_clazz = (*env)->NewGlobalRef(env, clazz); + stat_ctor = (*env)->GetMethodID(env, stat_clazz, "", + "(Ljava/lang/String;Ljava/lang/String;I)V"); +} + +static void stat_deinit(JNIEnv *env) { + if (stat_clazz != NULL) { + (*env)->DeleteGlobalRef(env, stat_clazz); + stat_clazz = NULL; + } +} + +static void nioe_init(JNIEnv *env) { + // Init NativeIOException + nioe_clazz = (*env)->FindClass( + env, "org/apache/hadoop/io/nativeio/NativeIOException"); + PASS_EXCEPTIONS(env); + + nioe_clazz = (*env)->NewGlobalRef(env, nioe_clazz); + nioe_ctor = (*env)->GetMethodID(env, nioe_clazz, "", + "(Ljava/lang/String;Lorg/apache/hadoop/io/nativeio/Errno;)V"); +} + +static void nioe_deinit(JNIEnv *env) { + if (nioe_clazz != NULL) { + (*env)->DeleteGlobalRef(env, nioe_clazz); + nioe_clazz = NULL; + } + nioe_ctor = NULL; +} + +/* + * private static native void initNative(); + * + * We rely on this function rather than lazy initialization because + * the lazy approach may have a race if multiple callers try to + * init at the same time. + */ +JNIEXPORT void JNICALL +Java_org_apache_hadoop_io_nativeio_NativeIO_initNative( + JNIEnv *env, jclass clazz) { + + stat_init(env); + PASS_EXCEPTIONS_GOTO(env, error); + nioe_init(env); + PASS_EXCEPTIONS_GOTO(env, error); + fd_init(env); + PASS_EXCEPTIONS_GOTO(env, error); + errno_enum_init(env); + PASS_EXCEPTIONS_GOTO(env, error); + return; +error: + // these are all idempodent and safe to call even if the + // class wasn't initted yet + stat_deinit(env); + nioe_deinit(env); + fd_deinit(env); + errno_enum_deinit(env); +} + +/* + * public static native Stat fstat(FileDescriptor fd); + */ +JNIEXPORT jobject JNICALL +Java_org_apache_hadoop_io_nativeio_NativeIO_fstat( + JNIEnv *env, jclass clazz, jobject fd_object) +{ + jobject ret = NULL; + char *pw_buf = NULL; + + int fd = fd_get(env, fd_object); + PASS_EXCEPTIONS_GOTO(env, cleanup); + + struct stat s; + int rc = fstat(fd, &s); + if (rc != 0) { + throw_ioe(env, errno); + goto cleanup; + } + + size_t pw_buflen = get_pw_buflen(); + if ((pw_buf = malloc(pw_buflen)) == NULL) { + THROW(env, "java/lang/OutOfMemoryError", "Couldn't allocate memory for pw buffer"); + goto cleanup; + } + + // Grab username + struct passwd pwd, *pwdp; + while ((rc = getpwuid_r(s.st_uid, &pwd, pw_buf, pw_buflen, &pwdp)) != 0) { + if (rc != ERANGE) { + throw_ioe(env, rc); + goto cleanup; + } + free(pw_buf); + pw_buflen *= 2; + if ((pw_buf = malloc(pw_buflen)) == NULL) { + THROW(env, "java/lang/OutOfMemoryError", "Couldn't allocate memory for pw buffer"); + goto cleanup; + } + } + assert(pwdp == &pwd); + + jstring jstr_username = (*env)->NewStringUTF(env, pwd.pw_name); + if (jstr_username == NULL) goto cleanup; + + // Grab group + struct group grp, *grpp; + while ((rc = getgrgid_r(s.st_gid, &grp, pw_buf, pw_buflen, &grpp)) != 0) { + if (rc != ERANGE) { + throw_ioe(env, rc); + goto cleanup; + } + free(pw_buf); + pw_buflen *= 2; + if ((pw_buf = malloc(pw_buflen)) == NULL) { + THROW(env, "java/lang/OutOfMemoryError", "Couldn't allocate memory for pw buffer"); + goto cleanup; + } + } + assert(grpp == &grp); + + jstring jstr_groupname = (*env)->NewStringUTF(env, grp.gr_name); + PASS_EXCEPTIONS_GOTO(env, cleanup); + + // Construct result + ret = (*env)->NewObject(env, stat_clazz, stat_ctor, + jstr_username, jstr_groupname, s.st_mode); + +cleanup: + if (pw_buf != NULL) free(pw_buf); + return ret; +} + + +/* + * public static native FileDescriptor open(String path, int flags, int mode); + */ +JNIEXPORT jobject JNICALL +Java_org_apache_hadoop_io_nativeio_NativeIO_open( + JNIEnv *env, jclass clazz, jstring j_path, + jint flags, jint mode) +{ + jobject ret = NULL; + + const char *path = (*env)->GetStringUTFChars(env, j_path, NULL); + if (path == NULL) goto cleanup; // JVM throws Exception for us + + int fd; + if (flags & O_CREAT) { + fd = open(path, flags, mode); + } else { + fd = open(path, flags); + } + + if (fd == -1) { + throw_ioe(env, errno); + goto cleanup; + } + + ret = fd_create(env, fd); + +cleanup: + if (path != NULL) { + (*env)->ReleaseStringUTFChars(env, j_path, path); + } + return ret; +} + +/* + * Throw a java.IO.IOException, generating the message from errno. + */ +static void throw_ioe(JNIEnv* env, int errnum) +{ + const char* message; + char buffer[80]; + jstring jstr_message; + + buffer[0] = 0; +#ifdef STRERROR_R_CHAR_P + // GNU strerror_r + message = strerror_r(errnum, buffer, sizeof(buffer)); + assert (message != NULL); +#else + int ret = strerror_r(errnum, buffer, sizeof(buffer)); + if (ret == 0) { + message = buffer; + } else { + message = "Unknown error"; + } +#endif + jobject errno_obj = errno_to_enum(env, errnum); + + if ((jstr_message = (*env)->NewStringUTF(env, message)) == NULL) + goto err; + + jthrowable obj = (jthrowable)(*env)->NewObject(env, nioe_clazz, nioe_ctor, + jstr_message, errno_obj); + if (obj == NULL) goto err; + + (*env)->Throw(env, obj); + return; + +err: + if (jstr_message != NULL) + (*env)->ReleaseStringUTFChars(env, jstr_message, message); +} + + +/* + * Determine how big a buffer we need for reentrant getpwuid_r and getgrnam_r + */ +ssize_t get_pw_buflen() { + size_t ret = 0; + #ifdef _SC_GETPW_R_SIZE_MAX + ret = sysconf(_SC_GETPW_R_SIZE_MAX); + #endif + return (ret > 512) ? ret : 512; +} +/** + * vim: sw=2: ts=2: et: + */ + Added: hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/errno_enum.c URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/errno_enum.c?rev=1040883&view=auto ============================================================================== --- hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/errno_enum.c (added) +++ hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/errno_enum.c Wed Dec 1 08:03:58 2010 @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include + #include + #include + +#include "org_apache_hadoop.h" + +typedef struct errno_mapping { + int errno_val; + char *errno_str; +} errno_mapping_t; + +// Macro to define structs like {FOO, "FOO"} for each errno value +#define MAPPING(x) {x, #x} +static errno_mapping_t ERRNO_MAPPINGS[] = { + MAPPING(EPERM), + MAPPING(ENOENT), + MAPPING(ESRCH), + MAPPING(EINTR), + MAPPING(EIO), + MAPPING(ENXIO), + MAPPING(E2BIG), + MAPPING(ENOEXEC), + MAPPING(EBADF), + MAPPING(ECHILD), + MAPPING(EAGAIN), + MAPPING(ENOMEM), + MAPPING(EACCES), + MAPPING(EFAULT), + MAPPING(ENOTBLK), + MAPPING(EBUSY), + MAPPING(EEXIST), + MAPPING(EXDEV), + MAPPING(ENODEV), + MAPPING(ENOTDIR), + MAPPING(EISDIR), + MAPPING(EINVAL), + MAPPING(ENFILE), + MAPPING(EMFILE), + MAPPING(ENOTTY), + MAPPING(ETXTBSY), + MAPPING(EFBIG), + MAPPING(ENOSPC), + MAPPING(ESPIPE), + MAPPING(EROFS), + MAPPING(EMLINK), + MAPPING(EPIPE), + MAPPING(EDOM), + MAPPING(ERANGE), + {-1, NULL} +}; + +static jclass enum_class; +static jmethodID enum_valueOf; +static jclass errno_class; + +void errno_enum_init(JNIEnv *env) { + if (enum_class != NULL) return; + + enum_class = (*env)->FindClass(env, "java/lang/Enum"); + PASS_EXCEPTIONS(env); + enum_class = (*env)->NewGlobalRef(env, enum_class); + enum_valueOf = (*env)->GetStaticMethodID(env, enum_class, + "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;"); + PASS_EXCEPTIONS(env); + + errno_class = (*env)->FindClass(env, "org/apache/hadoop/io/nativeio/Errno"); + PASS_EXCEPTIONS(env); + errno_class = (*env)->NewGlobalRef(env, errno_class); +} + +void errno_enum_deinit(JNIEnv *env) { + if (enum_class != NULL) { + (*env)->DeleteGlobalRef(env, enum_class); + enum_class = NULL; + } + if (errno_class != NULL) { + (*env)->DeleteGlobalRef(env, errno_class); + errno_class = NULL; + } + enum_valueOf = NULL; +} + + +static char *errno_to_string(int errnum) { + int i; + for (i = 0; ERRNO_MAPPINGS[i].errno_str != NULL; i++) { + if (ERRNO_MAPPINGS[i].errno_val == errnum) + return ERRNO_MAPPINGS[i].errno_str; + } + return "UNKNOWN"; +} + +jobject errno_to_enum(JNIEnv *env, int errnum) { + char *str = errno_to_string(errnum); + assert(str != NULL); + + jstring jstr = (*env)->NewStringUTF(env, str); + PASS_EXCEPTIONS_RET(env, NULL); + + return (*env)->CallStaticObjectMethod( + env, enum_class, enum_valueOf, errno_class, jstr); +} Added: hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/errno_enum.h URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/errno_enum.h?rev=1040883&view=auto ============================================================================== --- hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/errno_enum.h (added) +++ hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/errno_enum.h Wed Dec 1 08:03:58 2010 @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ERRNO_ENUM_H +#define ERRNO_ENUM_H + +#include + +void errno_enum_init(JNIEnv *env); +void errno_enum_deinit(JNIEnv *env); +jobject errno_to_enum(JNIEnv *env, int errnum); + +#endif Added: hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/file_descriptor.c URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/file_descriptor.c?rev=1040883&view=auto ============================================================================== --- hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/file_descriptor.c (added) +++ hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/file_descriptor.c Wed Dec 1 08:03:58 2010 @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "file_descriptor.h" +#include "org_apache_hadoop.h" + +// class of java.io.FileDescriptor +static jclass fd_class; +// the internal field for the integer fd +static jfieldID fd_descriptor; +// the no-argument constructor +static jmethodID fd_constructor; + + +void fd_init(JNIEnv* env) +{ + if (fd_class != NULL) return; // already initted + + fd_class = (*env)->FindClass(env, "java/io/FileDescriptor"); + PASS_EXCEPTIONS(env); + fd_class = (*env)->NewGlobalRef(env, fd_class); + + fd_descriptor = (*env)->GetFieldID(env, fd_class, "fd", "I"); + PASS_EXCEPTIONS(env); + fd_constructor = (*env)->GetMethodID(env, fd_class, "", "()V"); +} + +void fd_deinit(JNIEnv *env) { + if (fd_class != NULL) { + (*env)->DeleteGlobalRef(env, fd_class); + fd_class = NULL; + } + fd_descriptor = NULL; + fd_constructor = NULL; +} + +/* + * Given an instance 'obj' of java.io.FileDescriptor, return the + * underlying fd, or throw if unavailable + */ +int fd_get(JNIEnv* env, jobject obj) { + return (*env)->GetIntField(env, obj, fd_descriptor); +} + +/* + * Create a FileDescriptor object corresponding to the given int fd + */ +jobject fd_create(JNIEnv *env, int fd) { + jobject obj = (*env)->NewObject(env, fd_class, fd_constructor); + PASS_EXCEPTIONS_RET(env, NULL); + + (*env)->SetIntField(env, obj, fd_descriptor, fd); + return obj; +} Added: hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/file_descriptor.h URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/file_descriptor.h?rev=1040883&view=auto ============================================================================== --- hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/file_descriptor.h (added) +++ hadoop/common/trunk/src/native/src/org/apache/hadoop/io/nativeio/file_descriptor.h Wed Dec 1 08:03:58 2010 @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FILE_DESCRIPTOR_H +#define FILE_DESCRIPTOR_H + +#include + +void fd_init(JNIEnv *env); +void fd_deinit(JNIEnv *env); + +int fd_get(JNIEnv* env, jobject obj); +jobject fd_create(JNIEnv *env, int fd); + +#endif Modified: hadoop/common/trunk/src/native/src/org_apache_hadoop.h URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/native/src/org_apache_hadoop.h?rev=1040883&r1=1040882&r2=1040883&view=diff ============================================================================== --- hadoop/common/trunk/src/native/src/org_apache_hadoop.h (original) +++ hadoop/common/trunk/src/native/src/org_apache_hadoop.h Wed Dec 1 08:03:58 2010 @@ -50,6 +50,22 @@ } \ } +/* Helper macro to return if an exception is pending */ +#define PASS_EXCEPTIONS(env) \ + { \ + if ((*env)->ExceptionCheck(env)) return; \ + } + +#define PASS_EXCEPTIONS_GOTO(env, target) \ + { \ + if ((*env)->ExceptionCheck(env)) goto target; \ + } + +#define PASS_EXCEPTIONS_RET(env, ret) \ + { \ + if ((*env)->ExceptionCheck(env)) return (ret); \ + } + /** * A helper function to dlsym a 'symbol' from a given library-handle. * Added: hadoop/common/trunk/src/test/core/org/apache/hadoop/io/TestSecureIOUtils.java URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/test/core/org/apache/hadoop/io/TestSecureIOUtils.java?rev=1040883&view=auto ============================================================================== --- hadoop/common/trunk/src/test/core/org/apache/hadoop/io/TestSecureIOUtils.java (added) +++ hadoop/common/trunk/src/test/core/org/apache/hadoop/io/TestSecureIOUtils.java Wed Dec 1 08:03:58 2010 @@ -0,0 +1,83 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.io; + +import org.apache.hadoop.fs.FileStatus; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.io.nativeio.NativeIO; + +import org.junit.BeforeClass; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assume.*; +import static org.junit.Assert.*; +import java.io.IOException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; + +public class TestSecureIOUtils { + private static String realOwner, realGroup; + private static final File testFilePath = + new File(System.getProperty("test.build.data"), "TestSecureIOContext"); + + @BeforeClass + public static void makeTestFile() throws Exception { + FileOutputStream fos = new FileOutputStream(testFilePath); + fos.write("hello".getBytes("UTF-8")); + fos.close(); + + Configuration conf = new Configuration(); + FileSystem rawFS = FileSystem.getLocal(conf).getRaw(); + FileStatus stat = rawFS.getFileStatus( + new Path(testFilePath.toString())); + realOwner = stat.getOwner(); + realGroup = stat.getGroup(); + } + + @Test + public void testReadUnrestricted() throws IOException { + SecureIOUtils.openForRead(testFilePath, null, null).close(); + } + + @Test + public void testReadCorrectlyRestrictedWithSecurity() throws IOException { + SecureIOUtils + .openForRead(testFilePath, realOwner, realGroup).close(); + } + + @Test(expected=IOException.class) + public void testReadIncorrectlyRestrictedWithSecurity() throws IOException { + SecureIOUtils + .openForRead(testFilePath, "invalidUser", null).close(); + fail("Didn't throw expection for wrong ownership!"); + } + + @Test + public void testCreateForWrite() throws IOException { + try { + SecureIOUtils.createForWrite(testFilePath, 0777); + fail("Was able to create file at " + testFilePath); + } catch (SecureIOUtils.AlreadyExistsException aee) { + // expected + } + } +} Added: hadoop/common/trunk/src/test/core/org/apache/hadoop/io/nativeio/TestNativeIO.java URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/test/core/org/apache/hadoop/io/nativeio/TestNativeIO.java?rev=1040883&view=auto ============================================================================== --- hadoop/common/trunk/src/test/core/org/apache/hadoop/io/nativeio/TestNativeIO.java (added) +++ hadoop/common/trunk/src/test/core/org/apache/hadoop/io/nativeio/TestNativeIO.java Wed Dec 1 08:03:58 2010 @@ -0,0 +1,137 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.io.nativeio; + +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.io.IOException; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assume.*; +import static org.junit.Assert.*; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.fs.FileUtil; +import org.apache.hadoop.util.NativeCodeLoader; + +public class TestNativeIO { + static final Log LOG = LogFactory.getLog(TestNativeIO.class); + + static final File TEST_DIR = new File( + System.getProperty("test.build.data"), "testnativeio"); + + @Before + public void checkLoaded() { + assumeTrue(NativeCodeLoader.isNativeCodeLoaded()); + } + + @Before + public void setupTestDir() throws IOException { + FileUtil.fullyDelete(TEST_DIR); + TEST_DIR.mkdirs(); + } + + @Test + public void testFstat() throws Exception { + FileOutputStream fos = new FileOutputStream( + new File(TEST_DIR, "testfstat")); + NativeIO.Stat stat = NativeIO.fstat(fos.getFD()); + fos.close(); + LOG.info("Stat: " + String.valueOf(stat)); + + assertEquals(System.getProperty("user.name"), stat.getOwner()); + assertNotNull(stat.getGroup()); + assertTrue(!"".equals(stat.getGroup())); + assertEquals("Stat mode field should indicate a regular file", + NativeIO.Stat.S_IFREG, stat.getMode() & NativeIO.Stat.S_IFMT); + } + + @Test + public void testFstatClosedFd() throws Exception { + FileOutputStream fos = new FileOutputStream( + new File(TEST_DIR, "testfstat2")); + fos.close(); + try { + NativeIO.Stat stat = NativeIO.fstat(fos.getFD()); + } catch (NativeIOException nioe) { + LOG.info("Got expected exception", nioe); + assertEquals(Errno.EBADF, nioe.getErrno()); + } + } + + @Test + public void testOpenMissingWithoutCreate() throws Exception { + LOG.info("Open a missing file without O_CREAT and it should fail"); + try { + FileDescriptor fd = NativeIO.open( + new File(TEST_DIR, "doesntexist").getAbsolutePath(), + NativeIO.O_WRONLY, 0700); + fail("Able to open a new file without O_CREAT"); + } catch (NativeIOException nioe) { + LOG.info("Got expected exception", nioe); + assertEquals(Errno.ENOENT, nioe.getErrno()); + } + } + + @Test + public void testOpenWithCreate() throws Exception { + LOG.info("Test creating a file with O_CREAT"); + FileDescriptor fd = NativeIO.open( + new File(TEST_DIR, "testWorkingOpen").getAbsolutePath(), + NativeIO.O_WRONLY | NativeIO.O_CREAT, 0700); + assertNotNull(true); + assertTrue(fd.valid()); + FileOutputStream fos = new FileOutputStream(fd); + fos.write("foo".getBytes()); + fos.close(); + + assertFalse(fd.valid()); + + LOG.info("Test exclusive create"); + try { + fd = NativeIO.open( + new File(TEST_DIR, "testWorkingOpen").getAbsolutePath(), + NativeIO.O_WRONLY | NativeIO.O_CREAT | NativeIO.O_EXCL, 0700); + fail("Was able to create existing file with O_EXCL"); + } catch (NativeIOException nioe) { + LOG.info("Got expected exception for failed exclusive create", nioe); + assertEquals(Errno.EEXIST, nioe.getErrno()); + } + } + + /** + * Test that opens and closes a file 10000 times - this would crash with + * "Too many open files" if we leaked fds using this access pattern. + */ + @Test + public void testFDDoesntLeak() throws IOException { + for (int i = 0; i < 10000; i++) { + FileDescriptor fd = NativeIO.open( + new File(TEST_DIR, "testNoFdLeak").getAbsolutePath(), + NativeIO.O_WRONLY | NativeIO.O_CREAT, 0700); + assertNotNull(true); + assertTrue(fd.valid()); + FileOutputStream fos = new FileOutputStream(fd); + fos.write("foo".getBytes()); + fos.close(); + } + } + +}