You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by cm...@apache.org on 2014/06/12 21:56:25 UTC
svn commit: r1602280 [3/6] - in
/hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native: ./
common/ fs/ jni/ ndfs/ rpc/ test/ test/common/ test/common/conf/ test/fs/
Added: hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/fs/hdfs.h
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/fs/hdfs.h?rev=1602280&view=auto
==============================================================================
--- hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/fs/hdfs.h (added)
+++ hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/fs/hdfs.h Thu Jun 12 19:56:23 2014
@@ -0,0 +1,872 @@
+/**
+ * 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 LIBHDFS_HDFS_H
+#define LIBHDFS_HDFS_H
+
+#include <errno.h> /* for EINTERNAL, etc. */
+#include <fcntl.h> /* for O_RDONLY, O_WRONLY */
+#include <stdint.h> /* for uint64_t, etc. */
+#include <time.h> /* for time_t */
+
+/**
+ * This is the public API for libhdfs.
+ *
+ * libhdfs allows C programs to interact with Hadoop filesystems. There are
+ * several existing libhdfs filesystems.
+ *
+ * IMPLEMENTATIONS
+ * NDFS: the pure native HDFS client. NDFS is an all-C implementation of the
+ * Hadoop Distributed Filesystem client. Because it does not use a Java virtual
+ * machine, its startup time is very quick. However, it can only talk to HDFS,
+ * not other filesystems.
+ *
+ * jniFS: JNIfs uses the Hadoop FileSystem.java code to interact with
+ * filesystems. One way of looking at jniFS is as a window into Hadoop's Java
+ * code. The advantage of jniFS is that it can do anything that Hadoop's Java
+ * code can do. The moment someone writes a subclass of
+ * org.apache.hadoop.fs.FileSystem, it is accessible through jniFS. However,
+ * JNI has many disadvantages. It takes a while to start up, and may use a lot
+ * of memory, since it needs to start a JVM. It is difficult to debug a C
+ * program which uses a lot of JNI code. Partly this is because you don't have
+ * a lot of visibility into the Java part of the program. Another reason is
+ * because JNI uses signals internally very heavily, which confuses debuggers
+ * like gdb. jniFS requires the CLASSPATH environment variable to be set up
+ * correctly. Keep in mind that JNI cannot handle wildcards in CLASSPATH.
+ *
+ * ERROR HANDLING
+ * Most functions here follow the error reporting pattern laid down by POSIX: on
+ * error, they return -1 or NULL, and set errno. Errno is a thread-local
+ * variable. It should be checked immediately after the failure is detected,
+ * since many functions from the C standard library overwrite errno-- even
+ * functions like printf. Also keep in mind that libhdfs will not set errno on
+ * success, so you cannot simply always check errno. You must only check it if
+ * you know there is a failure.
+ *
+ * TODO: we ought to create a new version of this API which doesn't use errno.
+ * It is difficult for clients correctly deal with errno, and it makes the code
+ * harder to read.
+ *
+ * THREAD-SAFETY
+ * In general, it is thread-safe to use the same filesystem (hdfsFS) object
+ * from multiple threads at once, as long as you don't call setWorkingDirectory.
+ * You must not use the same file object from more than one thread at once.
+ * In other words, file objects are not thread-safe.
+ *
+ * These guarantees are the same as provided by Filesystem.java implementations
+ * in Java.
+ *
+ * CLEANUP
+ * Every FileSystem object you create with hdfsBuilderConnect should be
+ * eventually cleaned up with hdfsDisconnect. Similarly, every file you open
+ * should be closed eventually.
+ *
+ * IMPLEMENTER NOTES
+ * Since this is a public API, we have to be careful about making
+ * non-backwards-compatible changes. It is also important to provide a
+ * deallocation function for each structure that we provide a way to allocate.
+ * We should not assume that the client's implementation of "malloc" and "free"
+ * is the same as that used by our library. In general, it is often better to
+ * use a forward declaration and accessor functions, rather than declaring
+ * structures in this file. This leaves us more flexibility for the future.
+ */
+
+#if defined(unix) || defined(__MACH__)
+// Make all functions and structures inside this block externally visible.
+#pragma GCC visibility push(default)
+#endif
+
+#ifndef O_RDONLY
+#define O_RDONLY 1
+#endif
+
+#ifndef O_WRONLY
+#define O_WRONLY 2
+#endif
+
+#ifndef EINTERNAL
+#define EINTERNAL 255
+#endif
+
+#define ELASTIC_BYTE_BUFFER_POOL_CLASS \
+ "org/apache/hadoop/io/ElasticByteBufferPool"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ /**
+ * Some utility decls used in libhdfs.
+ */
+ struct hdfsBuilder;
+ typedef int32_t tSize; /// size of data for read/write io ops
+ typedef time_t tTime; /// time type in seconds
+ typedef int64_t tOffset;/// offset within the file
+ typedef uint16_t tPort; /// port
+ typedef enum tObjectKind {
+ kObjectKindFile = 'F',
+ kObjectKindDirectory = 'D',
+ } tObjectKind;
+
+
+ /**
+ * The C reflection of org.apache.org.hadoop.FileSystem .
+ */
+ struct hdfs_internal;
+ typedef struct hdfs_internal* hdfsFS;
+
+ struct hdfsFile_internal;
+ typedef struct hdfsFile_internal* hdfsFile;
+
+ struct hadoopRzOptions;
+
+ struct hadoopRzBuffer;
+
+ /**
+ * Determine if a file is open for read.
+ *
+ * @param file The HDFS file
+ * @return 1 if the file is open for read; 0 otherwise
+ */
+ int hdfsFileIsOpenForRead(hdfsFile file);
+
+ /**
+ * Determine if a file is open for write.
+ *
+ * @param file The HDFS file
+ * @return 1 if the file is open for write; 0 otherwise
+ */
+ int hdfsFileIsOpenForWrite(hdfsFile file);
+
+ struct hdfsReadStatistics {
+ uint64_t totalBytesRead;
+ uint64_t totalLocalBytesRead;
+ uint64_t totalShortCircuitBytesRead;
+ uint64_t totalZeroCopyBytesRead;
+ };
+
+ /**
+ * Get read statistics about a file. This is only applicable to files
+ * opened for reading.
+ *
+ * @param file The HDFS file
+ * @param stats (out parameter) on a successful return, the read
+ * statistics. Unchanged otherwise. You must free the
+ * returned statistics with hdfsFileFreeReadStatistics.
+ * @return 0 if the statistics were successfully returned,
+ * -1 otherwise. On a failure, please check errno against
+ * ENOTSUP. webhdfs, LocalFilesystem, and so forth may
+ * not support read statistics.
+ */
+ int hdfsFileGetReadStatistics(hdfsFile file,
+ struct hdfsReadStatistics **stats);
+
+ /**
+ * @param stats HDFS read statistics for a file.
+ *
+ * @return the number of remote bytes read.
+ */
+ int64_t hdfsReadStatisticsGetRemoteBytesRead(
+ const struct hdfsReadStatistics *stats);
+
+ /**
+ * Free some HDFS read statistics.
+ *
+ * @param stats The HDFS read statistics to free.
+ */
+ void hdfsFileFreeReadStatistics(struct hdfsReadStatistics *stats);
+
+ /**
+ * hdfsConnectAsUser - Connect to a hdfs file system as a specific user
+ * Connect to the hdfs.
+ * @param nn The NameNode. See hdfsBuilderSetNameNode for details.
+ * @param port The port on which the server is listening.
+ * @param user the user name (this is hadoop domain user). Or NULL is equivelant to hhdfsConnect(host, port)
+ * @return Returns a handle to the filesystem or NULL on error.
+ * @deprecated Use hdfsBuilderConnect instead.
+ */
+ hdfsFS hdfsConnectAsUser(const char* nn, tPort port, const char *user);
+
+ /**
+ * hdfsConnect - Connect to a hdfs file system.
+ * Connect to the hdfs.
+ * @param nn The NameNode. See hdfsBuilderSetNameNode for details.
+ * @param port The port on which the server is listening.
+ * @return Returns a handle to the filesystem or NULL on error.
+ * @deprecated Use hdfsBuilderConnect instead.
+ */
+ hdfsFS hdfsConnect(const char* nn, tPort port);
+
+ /**
+ * hdfsConnect - Connect to an hdfs file system.
+ *
+ * Forces a new instance to be created
+ *
+ * @param nn The NameNode. See hdfsBuilderSetNameNode for details.
+ * @param port The port on which the server is listening.
+ * @param user The user name to use when connecting
+ * @return Returns a handle to the filesystem or NULL on error.
+ * @deprecated Use hdfsBuilderConnect instead.
+ */
+ hdfsFS hdfsConnectAsUserNewInstance(const char* nn, tPort port, const char *user );
+
+ /**
+ * hdfsConnect - Connect to an hdfs file system.
+ *
+ * Forces a new instance to be created
+ *
+ * @param nn The NameNode. See hdfsBuilderSetNameNode for details.
+ * @param port The port on which the server is listening.
+ * @return Returns a handle to the filesystem or NULL on error.
+ * @deprecated Use hdfsBuilderConnect instead.
+ */
+ hdfsFS hdfsConnectNewInstance(const char* nn, tPort port);
+
+ /**
+ * Connect to HDFS using the parameters defined by the builder.
+ *
+ * The HDFS builder will be freed, whether or not the connection was
+ * successful.
+ *
+ * Every successful call to hdfsBuilderConnect should be matched with a call
+ * to hdfsDisconnect, when the hdfsFS is no longer needed.
+ *
+ * @param bld The HDFS builder
+ * @return Returns a handle to the filesystem, or NULL on error.
+ */
+ hdfsFS hdfsBuilderConnect(struct hdfsBuilder *bld);
+
+ /**
+ * Create an HDFS builder.
+ *
+ * @return The HDFS builder, or NULL on error.
+ */
+ struct hdfsBuilder *hdfsNewBuilder(void);
+
+ /**
+ * Force the builder to always create a new instance of the FileSystem,
+ * rather than possibly finding one in the cache.
+ *
+ * @param bld The HDFS builder
+ */
+ void hdfsBuilderSetForceNewInstance(struct hdfsBuilder *bld);
+
+ /**
+ * Set the HDFS NameNode to connect to.
+ *
+ * @param bld The HDFS builder
+ * @param nn The NameNode to use.
+ *
+ * If the string given is 'default', the default NameNode
+ * configuration will be used (from the XML configuration files)
+ *
+ * If NULL is given, a LocalFileSystem will be created.
+ *
+ * If the string starts with a protocol type such as file:// or
+ * hdfs://, this protocol type will be used. If not, the
+ * hdfs:// protocol type will be used.
+ *
+ * You may specify a NameNode port in the usual way by
+ * passing a string of the format hdfs://<hostname>:<port>.
+ * Alternately, you may set the port with
+ * hdfsBuilderSetNameNodePort. However, you must not pass the
+ * port in two different ways.
+ */
+ void hdfsBuilderSetNameNode(struct hdfsBuilder *bld, const char *nn);
+
+ /**
+ * Set the port of the HDFS NameNode to connect to.
+ *
+ * @param bld The HDFS builder
+ * @param port The port.
+ */
+ void hdfsBuilderSetNameNodePort(struct hdfsBuilder *bld, tPort port);
+
+ /**
+ * Set the username to use when connecting to the HDFS cluster.
+ *
+ * @param bld The HDFS builder
+ * @param userName The user name. The string will be shallow-copied.
+ */
+ void hdfsBuilderSetUserName(struct hdfsBuilder *bld, const char *userName);
+
+ /**
+ * Set the path to the Kerberos ticket cache to use when connecting to
+ * the HDFS cluster.
+ *
+ * @param bld The HDFS builder
+ * @param kerbTicketCachePath The Kerberos ticket cache path. The string
+ * will be shallow-copied.
+ */
+ void hdfsBuilderSetKerbTicketCachePath(struct hdfsBuilder *bld,
+ const char *kerbTicketCachePath);
+
+ /**
+ * Free an HDFS builder.
+ *
+ * It is normally not necessary to call this function since
+ * hdfsBuilderConnect frees the builder.
+ *
+ * @param bld The HDFS builder
+ */
+ void hdfsFreeBuilder(struct hdfsBuilder *bld);
+
+ /**
+ * Set a configuration string for an HdfsBuilder.
+ *
+ * @param key The key to set.
+ * @param val The value, or NULL to set no value.
+ * This will be shallow-copied. You are responsible for
+ * ensuring that it remains valid until the builder is
+ * freed.
+ *
+ * @return 0 on success; nonzero error code otherwise.
+ */
+ int hdfsBuilderConfSetStr(struct hdfsBuilder *bld, const char *key,
+ const char *val);
+
+ /**
+ * Get a configuration string.
+ *
+ * @param key The key to find
+ * @param val (out param) The value. This will be set to NULL if the
+ * key isn't found. You must free this string with
+ * hdfsConfStrFree.
+ *
+ * @return 0 on success; nonzero error code otherwise.
+ * Failure to find the key is not an error.
+ */
+ int hdfsConfGetStr(const char *key, char **val);
+
+ /**
+ * Get a configuration integer.
+ *
+ * @param key The key to find
+ * @param val (out param) The value. This will NOT be changed if the
+ * key isn't found.
+ *
+ * @return 0 on success; nonzero error code otherwise.
+ * Failure to find the key is not an error.
+ */
+ int hdfsConfGetInt(const char *key, int32_t *val);
+
+ /**
+ * Free a configuration string found with hdfsConfGetStr.
+ *
+ * @param val A configuration string obtained from hdfsConfGetStr
+ */
+ void hdfsConfStrFree(char *val);
+
+ /**
+ * hdfsDisconnect - Disconnect from the hdfs file system.
+ * Disconnect from hdfs.
+ * @param fs The configured filesystem handle.
+ * @return Returns 0 on success, -1 on error.
+ * Even if there is an error, the resources associated with the
+ * hdfsFS will be freed.
+ */
+ int hdfsDisconnect(hdfsFS fs);
+
+
+ /**
+ * hdfsOpenFile - Open a hdfs file in given mode.
+ * @param fs The configured filesystem handle.
+ * @param path The full path to the file.
+ * @param flags - an | of bits/fcntl.h file flags - supported flags are O_RDONLY, O_WRONLY (meaning create or overwrite i.e., implies O_TRUNCAT),
+ * O_WRONLY|O_APPEND. Other flags are generally ignored other than (O_RDWR || (O_EXCL & O_CREAT)) which return NULL and set errno equal ENOTSUP.
+ * @param bufferSize Size of buffer for read/write - pass 0 if you want
+ * to use the default configured values.
+ * @param replication Block replication - pass 0 if you want to use
+ * the default configured values.
+ * @param blocksize Size of block - pass 0 if you want to use the
+ * default configured values.
+ * @return Returns the handle to the open file or NULL on error.
+ */
+ hdfsFile hdfsOpenFile(hdfsFS fs, const char* path, int flags,
+ int bufferSize, short replication, tSize blocksize);
+
+
+ /**
+ * hdfsCloseFile - Close an open file.
+ * @param fs The configured filesystem handle.
+ * @param file The file handle.
+ * @return Returns 0 on success, -1 on error.
+ * On error, errno will be set appropriately.
+ * If the hdfs file was valid, the memory associated with it will
+ * be freed at the end of this call, even if there was an I/O
+ * error.
+ */
+ int hdfsCloseFile(hdfsFS fs, hdfsFile file);
+
+
+ /**
+ * hdfsExists - Checks if a given path exsits on the filesystem
+ * @param fs The configured filesystem handle.
+ * @param path The path to look for
+ * @return Returns 0 on success, -1 on error.
+ */
+ int hdfsExists(hdfsFS fs, const char *path);
+
+
+ /**
+ * hdfsSeek - Seek to given offset in file.
+ * This works only for files opened in read-only mode.
+ * @param fs The configured filesystem handle.
+ * @param file The file handle.
+ * @param desiredPos Offset into the file to seek into.
+ * @return Returns 0 on success, -1 on error.
+ */
+ int hdfsSeek(hdfsFS fs, hdfsFile file, tOffset desiredPos);
+
+
+ /**
+ * hdfsTell - Get the current offset in the file, in bytes.
+ * @param fs The configured filesystem handle.
+ * @param file The file handle.
+ * @return Current offset, -1 on error.
+ */
+ tOffset hdfsTell(hdfsFS fs, hdfsFile file);
+
+
+ /**
+ * hdfsRead - Read data from an open file.
+ * @param fs The configured filesystem handle.
+ * @param file The file handle.
+ * @param buffer The buffer to copy read bytes into.
+ * @param length The length of the buffer.
+ * @return On success, a positive number indicating how many bytes
+ * were read.
+ * On end-of-file, 0.
+ * On error, -1. Errno will be set to the error code.
+ * Just like the POSIX read function, hdfsRead will return -1
+ * and set errno to EINTR if data is temporarily unavailable,
+ * but we are not yet at the end of the file.
+ */
+ tSize hdfsRead(hdfsFS fs, hdfsFile file, void* buffer, tSize length);
+
+ /**
+ * hdfsPread - Positional read of data from an open file.
+ * @param fs The configured filesystem handle.
+ * @param file The file handle.
+ * @param position Position from which to read
+ * @param buffer The buffer to copy read bytes into.
+ * @param length The length of the buffer.
+ * @return See hdfsRead
+ */
+ tSize hdfsPread(hdfsFS fs, hdfsFile file, tOffset position,
+ void* buffer, tSize length);
+
+
+ /**
+ * hdfsWrite - Write data into an open file.
+ * @param fs The configured filesystem handle.
+ * @param file The file handle.
+ * @param buffer The data.
+ * @param length The no. of bytes to write.
+ * @return Returns the number of bytes written, -1 on error.
+ */
+ tSize hdfsWrite(hdfsFS fs, hdfsFile file, const void* buffer,
+ tSize length);
+
+
+ /**
+ * hdfsWrite - Flush the data.
+ * @param fs The configured filesystem handle.
+ * @param file The file handle.
+ * @return Returns 0 on success, -1 on error.
+ */
+ int hdfsFlush(hdfsFS fs, hdfsFile file);
+
+
+ /**
+ * hdfsHFlush - Flush out the data in client's user buffer. After the
+ * return of this call, new readers will see the data.
+ * @param fs configured filesystem handle
+ * @param file file handle
+ * @return 0 on success, -1 on error and sets errno
+ */
+ int hdfsHFlush(hdfsFS fs, hdfsFile file);
+
+
+ /**
+ * hdfsHSync - Similar to posix fsync, Flush out the data in client's
+ * user buffer. all the way to the disk device (but the disk may have
+ * it in its cache).
+ * @param fs configured filesystem handle
+ * @param file file handle
+ * @return 0 on success, -1 on error and sets errno
+ */
+ int hdfsHSync(hdfsFS fs, hdfsFile file);
+
+
+ /**
+ * hdfsAvailable - Number of bytes that can be read from this
+ * input stream without blocking.
+ * @param fs The configured filesystem handle.
+ * @param file The file handle.
+ * @return Returns available bytes; -1 on error.
+ */
+ int hdfsAvailable(hdfsFS fs, hdfsFile file);
+
+
+ /**
+ * hdfsCopy - Copy file from one filesystem to another.
+ * @param srcFS The handle to source filesystem.
+ * @param src The path of source file.
+ * @param dstFS The handle to destination filesystem.
+ * @param dst The path of destination file.
+ * @return Returns 0 on success, -1 on error.
+ */
+ int hdfsCopy(hdfsFS srcFS, const char* src, hdfsFS dstFS, const char* dst);
+
+
+ /**
+ * hdfsMove - Move file from one filesystem to another.
+ * @param srcFS The handle to source filesystem.
+ * @param src The path of source file.
+ * @param dstFS The handle to destination filesystem.
+ * @param dst The path of destination file.
+ * @return Returns 0 on success, -1 on error.
+ */
+ int hdfsMove(hdfsFS srcFS, const char* src, hdfsFS dstFS, const char* dst);
+
+
+ /**
+ * hdfsDelete - Delete file.
+ * @param fs The configured filesystem handle.
+ * @param path The path of the file.
+ * @param recursive if path is a directory and set to
+ * non-zero, the directory is deleted else throws an exception. In
+ * case of a file the recursive argument is irrelevant.
+ * @return Returns 0 on success, -1 on error.
+ */
+ int hdfsDelete(hdfsFS fs, const char* path, int recursive);
+
+ /**
+ * hdfsRename - Rename file.
+ * @param fs The configured filesystem handle.
+ * @param oldPath The path of the source file.
+ * @param newPath The path of the destination file.
+ * @return Returns 0 on success, -1 on error.
+ */
+ int hdfsRename(hdfsFS fs, const char* oldPath, const char* newPath);
+
+
+ /**
+ * hdfsGetWorkingDirectory - Get the current working directory for
+ * the given filesystem.
+ * @param fs The configured filesystem handle.
+ * @param buffer The user-buffer to copy path of cwd into.
+ * @param bufferSize The length of user-buffer.
+ * @return Returns buffer, NULL on error.
+ */
+ char* hdfsGetWorkingDirectory(hdfsFS fs, char *buffer, size_t bufferSize);
+
+
+ /**
+ * hdfsSetWorkingDirectory - Set the working directory. All relative
+ * paths will be resolved relative to it.
+ * @param fs The configured filesystem handle.
+ * @param path The path of the new 'cwd'.
+ * @return Returns 0 on success, -1 on error.
+ */
+ int hdfsSetWorkingDirectory(hdfsFS fs, const char* path);
+
+
+ /**
+ * hdfsCreateDirectory - Make the given file and all non-existent
+ * parents into directories.
+ * @param fs The configured filesystem handle.
+ * @param path The path of the directory.
+ * @return Returns 0 on success, -1 on error.
+ */
+ int hdfsCreateDirectory(hdfsFS fs, const char* path);
+
+
+ /**
+ * hdfsSetReplication - Set the replication of the specified
+ * file to the supplied value
+ * @param fs The configured filesystem handle.
+ * @param path The path of the file.
+ * @return Returns 0 on success, -1 on error.
+ */
+ int hdfsSetReplication(hdfsFS fs, const char* path, int16_t replication);
+
+
+ /**
+ * hdfsFileInfo - Information about a file/directory.
+ */
+ typedef struct file_info {
+ tObjectKind mKind; /* file or directory */
+ char *mName; /* the name of the file */
+ tTime mLastMod; /* the last modification time for the file in seconds */
+ tOffset mSize; /* the size of the file in bytes */
+ short mReplication; /* the count of replicas */
+ tOffset mBlockSize; /* the block size for the file */
+ char *mOwner; /* the owner of the file */
+ char *mGroup; /* the group associated with the file */
+ short mPermissions; /* the permissions associated with the file */
+ tTime mLastAccess; /* the last access time for the file in seconds */
+ } hdfsFileInfo;
+
+
+ /**
+ * hdfsListDirectory - Get list of files/directories for a given
+ * directory-path. hdfsFreeFileInfo should be called to deallocate memory.
+ * @param fs The configured filesystem handle.
+ * @param path The path of the directory.
+ * @param numEntries Set to the number of files/directories in path.
+ * @return Returns a dynamically-allocated array of hdfsFileInfo
+ * objects; NULL on error.
+ */
+ hdfsFileInfo *hdfsListDirectory(hdfsFS fs, const char* path,
+ int *numEntries);
+
+
+ /**
+ * hdfsGetPathInfo - Get information about a path as a (dynamically
+ * allocated) single hdfsFileInfo struct. hdfsFreeFileInfo should be
+ * called when the pointer is no longer needed.
+ * @param fs The configured filesystem handle.
+ * @param path The path of the file.
+ * @return Returns a dynamically-allocated hdfsFileInfo object;
+ * NULL on error.
+ */
+ hdfsFileInfo *hdfsGetPathInfo(hdfsFS fs, const char* path);
+
+
+ /**
+ * hdfsFreeFileInfo - Free up the hdfsFileInfo array (including fields)
+ * @param hdfsFileInfo The array of dynamically-allocated hdfsFileInfo
+ * objects.
+ * @param numEntries The size of the array.
+ */
+ void hdfsFreeFileInfo(hdfsFileInfo *hdfsFileInfo, int numEntries);
+
+
+ /**
+ * hdfsGetHosts - Get hostnames where a particular block (determined by
+ * pos & blocksize) of a file is stored. The last element in the array
+ * is NULL. Due to replication, a single block could be present on
+ * multiple hosts.
+ * @param fs The configured filesystem handle.
+ * @param path The path of the file.
+ * @param start The start of the block.
+ * @param length The length of the block.
+ * @return Returns a dynamically-allocated 2-d array of blocks-hosts;
+ * NULL on error.
+ */
+ char*** hdfsGetHosts(hdfsFS fs, const char* path,
+ tOffset start, tOffset length);
+
+
+ /**
+ * hdfsFreeHosts - Free up the structure returned by hdfsGetHosts
+ * @param hdfsFileInfo The array of dynamically-allocated hdfsFileInfo
+ * objects.
+ * @param numEntries The size of the array.
+ */
+ void hdfsFreeHosts(char ***blockHosts);
+
+
+ /**
+ * hdfsGetDefaultBlockSize - Get the default blocksize.
+ *
+ * @param fs The configured filesystem handle.
+ * @deprecated Use hdfsGetDefaultBlockSizeAtPath instead.
+ *
+ * @return Returns the default blocksize, or -1 on error.
+ */
+ tOffset hdfsGetDefaultBlockSize(hdfsFS fs);
+
+
+ /**
+ * hdfsGetDefaultBlockSizeAtPath - Get the default blocksize at the
+ * filesystem indicated by a given path.
+ *
+ * @param fs The configured filesystem handle.
+ * @param path The given path will be used to locate the actual
+ * filesystem. The full path does not have to exist.
+ *
+ * @return Returns the default blocksize, or -1 on error.
+ */
+ tOffset hdfsGetDefaultBlockSizeAtPath(hdfsFS fs, const char *path);
+
+
+ /**
+ * hdfsGetCapacity - Return the raw capacity of the filesystem.
+ * @param fs The configured filesystem handle.
+ * @return Returns the raw-capacity; -1 on error.
+ */
+ tOffset hdfsGetCapacity(hdfsFS fs);
+
+
+ /**
+ * hdfsGetUsed - Return the total raw size of all files in the filesystem.
+ * @param fs The configured filesystem handle.
+ * @return Returns the total-size; -1 on error.
+ */
+ tOffset hdfsGetUsed(hdfsFS fs);
+
+ /**
+ * Change the user and/or group of a file or directory.
+ *
+ * @param fs The configured filesystem handle.
+ * @param path the path to the file or directory
+ * @param owner User string. Set to NULL for 'no change'
+ * @param group Group string. Set to NULL for 'no change'
+ * @return 0 on success else -1
+ */
+ int hdfsChown(hdfsFS fs, const char* path, const char *owner,
+ const char *group);
+
+ /**
+ * hdfsChmod
+ * @param fs The configured filesystem handle.
+ * @param path the path to the file or directory
+ * @param mode the bitmask to set it to
+ * @return 0 on success else -1
+ */
+ int hdfsChmod(hdfsFS fs, const char* path, short mode);
+
+ /**
+ * hdfsUtime
+ * @param fs The configured filesystem handle.
+ * @param path the path to the file or directory
+ * @param mtime new modification time or -1 for no change
+ * @param atime new access time or -1 for no change
+ * @return 0 on success else -1
+ */
+ int hdfsUtime(hdfsFS fs, const char* path, tTime mtime, tTime atime);
+
+ /**
+ * Allocate a zero-copy options structure.
+ *
+ * You must free all options structures allocated with this function using
+ * hadoopRzOptionsFree.
+ *
+ * @return A zero-copy options structure, or NULL if one could
+ * not be allocated. If NULL is returned, errno will
+ * contain the error number.
+ */
+ struct hadoopRzOptions *hadoopRzOptionsAlloc(void);
+
+ /**
+ * Determine whether we should skip checksums in read0.
+ *
+ * @param opts The options structure.
+ * @param skip Nonzero to skip checksums sometimes; zero to always
+ * check them.
+ *
+ * @return 0 on success; -1 plus errno on failure.
+ */
+ int hadoopRzOptionsSetSkipChecksum(
+ struct hadoopRzOptions *opts, int skip);
+
+ /**
+ * Set the ByteBufferPool to use with read0.
+ *
+ * @param opts The options structure.
+ * @param className If this is NULL, we will not use any
+ * ByteBufferPool. If this is non-NULL, it will be
+ * treated as the name of the pool class to use.
+ * For example, you can use
+ * ELASTIC_BYTE_BUFFER_POOL_CLASS.
+ *
+ * @return 0 if the ByteBufferPool class was found and
+ * instantiated;
+ * -1 plus errno otherwise.
+ */
+ int hadoopRzOptionsSetByteBufferPool(
+ struct hadoopRzOptions *opts, const char *className);
+
+ /**
+ * Free a hadoopRzOptionsFree structure.
+ *
+ * @param opts The options structure to free.
+ * Any associated ByteBufferPool will also be freed.
+ */
+ void hadoopRzOptionsFree(struct hadoopRzOptions *opts);
+
+ /**
+ * Perform a byte buffer read.
+ * If possible, this will be a zero-copy (mmap) read.
+ *
+ * @param file The file to read from.
+ * @param opts An options structure created by hadoopRzOptionsAlloc.
+ * @param maxLength The maximum length to read. We may read fewer bytes
+ * than this length.
+ *
+ * @return On success, we will return a new hadoopRzBuffer.
+ * This buffer will continue to be valid and readable
+ * until it is released by readZeroBufferFree. Failure to
+ * release a buffer will lead to a memory leak.
+ * You can access the data within the hadoopRzBuffer with
+ * hadoopRzBufferGet. If you have reached EOF, the data
+ * within the hadoopRzBuffer will be NULL. You must still
+ * free hadoopRzBuffer instances containing NULL.
+ *
+ * On failure, we will return NULL plus an errno code.
+ * errno = EOPNOTSUPP indicates that we could not do a
+ * zero-copy read, and there was no ByteBufferPool
+ * supplied.
+ */
+ struct hadoopRzBuffer* hadoopReadZero(hdfsFile file,
+ struct hadoopRzOptions *opts, int32_t maxLength);
+
+ /**
+ * Determine the length of the buffer returned from readZero.
+ *
+ * @param buffer a buffer returned from readZero.
+ * @return the length of the buffer.
+ */
+ int32_t hadoopRzBufferLength(const struct hadoopRzBuffer *buffer);
+
+ /**
+ * Get a pointer to the raw buffer returned from readZero.
+ *
+ * To find out how many bytes this buffer contains, call
+ * hadoopRzBufferLength.
+ *
+ * @param buffer a buffer returned from readZero.
+ * @return a pointer to the start of the buffer. This will be
+ * NULL when end-of-file has been reached.
+ */
+ const void *hadoopRzBufferGet(const struct hadoopRzBuffer *buffer);
+
+ /**
+ * Release a buffer obtained through readZero.
+ *
+ * @param file The hdfs stream that created this buffer. This must be
+ * the same stream you called hadoopReadZero on.
+ * @param buffer The buffer to release.
+ */
+ void hadoopRzBufferFree(hdfsFile file, struct hadoopRzBuffer *buffer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(unix) || defined(__MACH__)
+#pragma GCC visibility pop
+#endif
+
+#endif /*LIBHDFS_HDFS_H*/
+
+/**
+ * vim: ts=4: sw=4: et
+ */
Added: hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/fs/hdfs_test.h
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/fs/hdfs_test.h?rev=1602280&view=auto
==============================================================================
--- hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/fs/hdfs_test.h (added)
+++ hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/fs/hdfs_test.h Thu Jun 12 19:56:23 2014
@@ -0,0 +1,55 @@
+/**
+ * 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 LIBHDFS_HDFS_TEST_H
+#define LIBHDFS_HDFS_TEST_H
+
+struct hdfsFile_internal;
+
+/**
+ * Some functions that are visible only for testing.
+ *
+ * This header is not meant to be exported or used outside of the libhdfs unit
+ * tests.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ /**
+ * Determine if a file is using the "direct read" optimization.
+ *
+ * @param file The HDFS file
+ * @return 1 if the file is using the direct read optimization,
+ * 0 otherwise.
+ */
+ int hdfsFileUsesDirectRead(struct hdfsFile_internal *file);
+
+ /**
+ * Disable the direct read optimization for a file.
+ *
+ * This is mainly provided for unit testing purposes.
+ *
+ * @param file The HDFS file
+ */
+ void hdfsFileDisableDirectRead(struct hdfsFile_internal *file);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Added: hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/exception.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/exception.c?rev=1602280&view=auto
==============================================================================
--- hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/exception.c (added)
+++ hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/exception.c Thu Jun 12 19:56:23 2014
@@ -0,0 +1,234 @@
+/**
+ * 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 "fs/hdfs.h"
+#include "jni/exception.h"
+#include "jni/jni_helper.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define EXCEPTION_INFO_LEN (sizeof(gExceptionInfo)/sizeof(gExceptionInfo[0]))
+
+struct ExceptionInfo {
+ const char * const name;
+ int noPrintFlag;
+ int excErrno;
+};
+
+static const struct ExceptionInfo gExceptionInfo[] = {
+ {
+ .name = "java.io.FileNotFoundException",
+ .noPrintFlag = NOPRINT_EXC_FILE_NOT_FOUND,
+ .excErrno = ENOENT,
+ },
+ {
+ .name = "org.apache.hadoop.security.AccessControlException",
+ .noPrintFlag = NOPRINT_EXC_ACCESS_CONTROL,
+ .excErrno = EACCES,
+ },
+ {
+ .name = "org.apache.hadoop.fs.UnresolvedLinkException",
+ .noPrintFlag = NOPRINT_EXC_UNRESOLVED_LINK,
+ .excErrno = ENOLINK,
+ },
+ {
+ .name = "org.apache.hadoop.fs.ParentNotDirectoryException",
+ .noPrintFlag = NOPRINT_EXC_PARENT_NOT_DIRECTORY,
+ .excErrno = ENOTDIR,
+ },
+ {
+ .name = "java.lang.IllegalArgumentException",
+ .noPrintFlag = NOPRINT_EXC_ILLEGAL_ARGUMENT,
+ .excErrno = EINVAL,
+ },
+ {
+ .name = "java.lang.OutOfMemoryError",
+ .noPrintFlag = 0,
+ .excErrno = ENOMEM,
+ },
+ {
+ .name = "org.apache.hadoop.hdfs.server.namenode.SafeModeException",
+ .noPrintFlag = 0,
+ .excErrno = EROFS,
+ },
+ {
+ .name = "org.apache.hadoop.fs.FileAlreadyExistsException",
+ .noPrintFlag = 0,
+ .excErrno = EEXIST,
+ },
+ {
+ .name = "org.apache.hadoop.hdfs.protocol.QuotaExceededException",
+ .noPrintFlag = 0,
+ .excErrno = EDQUOT,
+ },
+ {
+ .name = "org.apache.hadoop.hdfs.server.namenode.LeaseExpiredException",
+ .noPrintFlag = 0,
+ .excErrno = ESTALE,
+ },
+};
+
+void getExceptionInfo(const char *excName, int noPrintFlags,
+ int *excErrno, int *shouldPrint)
+{
+ size_t i;
+
+ for (i = 0; i < EXCEPTION_INFO_LEN; i++) {
+ if (strstr(gExceptionInfo[i].name, excName)) {
+ break;
+ }
+ }
+ if (i < EXCEPTION_INFO_LEN) {
+ *shouldPrint = !(gExceptionInfo[i].noPrintFlag & noPrintFlags);
+ *excErrno = gExceptionInfo[i].excErrno;
+ } else {
+ *shouldPrint = 1;
+ *excErrno = EINTERNAL;
+ }
+}
+
+int printExceptionAndFreeV(JNIEnv *env, jthrowable exc, int noPrintFlags,
+ const char *fmt, va_list ap)
+{
+ size_t i;
+ int noPrint, excErrno;
+ char *className = NULL;
+ jstring jStr = NULL;
+ jvalue jVal;
+ jthrowable jthr;
+
+ jthr = classNameOfObject(exc, env, &className);
+ if (jthr) {
+ fprintf(stderr, "PrintExceptionAndFree: error determining class name "
+ "of exception.\n");
+ className = strdup("(unknown)");
+ destroyLocalReference(env, jthr);
+ }
+ for (i = 0; i < EXCEPTION_INFO_LEN; i++) {
+ if (!strcmp(gExceptionInfo[i].name, className)) {
+ break;
+ }
+ }
+ if (i < EXCEPTION_INFO_LEN) {
+ noPrint = (gExceptionInfo[i].noPrintFlag & noPrintFlags);
+ excErrno = gExceptionInfo[i].excErrno;
+ } else {
+ noPrint = 0;
+ excErrno = EINTERNAL;
+ }
+ if (!noPrint) {
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, " error:\n");
+
+ // We don't want to use ExceptionDescribe here, because that requires a
+ // pending exception. Instead, use ExceptionUtils.
+ jthr = invokeMethod(env, &jVal, STATIC, NULL,
+ "org/apache/commons/lang/exception/ExceptionUtils",
+ "getStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;", exc);
+ if (jthr) {
+ fprintf(stderr, "(unable to get stack trace for %s exception: "
+ "ExceptionUtils::getStackTrace error.)\n", className);
+ destroyLocalReference(env, jthr);
+ } else {
+ jStr = jVal.l;
+ const char *stackTrace = (*env)->GetStringUTFChars(env, jStr, NULL);
+ if (!stackTrace) {
+ fprintf(stderr, "(unable to get stack trace for %s exception: "
+ "GetStringUTFChars error.)\n", className);
+ } else {
+ fprintf(stderr, "%s", stackTrace);
+ (*env)->ReleaseStringUTFChars(env, jStr, stackTrace);
+ }
+ }
+ }
+ destroyLocalReference(env, jStr);
+ destroyLocalReference(env, exc);
+ free(className);
+ return excErrno;
+}
+
+int printExceptionAndFree(JNIEnv *env, jthrowable exc, int noPrintFlags,
+ const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = printExceptionAndFreeV(env, exc, noPrintFlags, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+int printPendingExceptionAndFree(JNIEnv *env, int noPrintFlags,
+ const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+ jthrowable exc;
+
+ exc = (*env)->ExceptionOccurred(env);
+ if (!exc) {
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, " error: (no exception)");
+ ret = 0;
+ } else {
+ (*env)->ExceptionClear(env);
+ va_start(ap, fmt);
+ ret = printExceptionAndFreeV(env, exc, noPrintFlags, fmt, ap);
+ va_end(ap);
+ }
+ return ret;
+}
+
+jthrowable getPendingExceptionAndClear(JNIEnv *env)
+{
+ jthrowable jthr = (*env)->ExceptionOccurred(env);
+ if (!jthr)
+ return NULL;
+ (*env)->ExceptionClear(env);
+ return jthr;
+}
+
+jthrowable newRuntimeError(JNIEnv *env, const char *fmt, ...)
+{
+ char buf[512];
+ jobject out, exc;
+ jstring jstr;
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ jstr = (*env)->NewStringUTF(env, buf);
+ if (!jstr) {
+ // We got an out of memory exception rather than a RuntimeException.
+ // Too bad...
+ return getPendingExceptionAndClear(env);
+ }
+ exc = constructNewObjectOfClass(env, &out, "RuntimeException",
+ "(java/lang/String;)V", jstr);
+ (*env)->DeleteLocalRef(env, jstr);
+ // Again, we'll either get an out of memory exception or the
+ // RuntimeException we wanted.
+ return (exc) ? exc : out;
+}
Added: hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/exception.h
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/exception.h?rev=1602280&view=auto
==============================================================================
--- hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/exception.h (added)
+++ hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/exception.h Thu Jun 12 19:56:23 2014
@@ -0,0 +1,155 @@
+/**
+ * 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 LIBHDFS_EXCEPTION_H
+#define LIBHDFS_EXCEPTION_H
+
+/**
+ * Exception handling routines for libhdfs.
+ *
+ * The convention we follow here is to clear pending exceptions as soon as they
+ * are raised. Never assume that the caller of your function will clean up
+ * after you-- do it yourself. Unhandled exceptions can lead to memory leaks
+ * and other undefined behavior.
+ *
+ * If you encounter an exception, return a local reference to it. The caller is
+ * responsible for freeing the local reference, by calling a function like
+ * PrintExceptionAndFree. (You can also free exceptions directly by calling
+ * DeleteLocalRef. However, that would not produce an error message, so it's
+ * usually not what you want.)
+ */
+
+#include <jni.h>
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <search.h>
+#include <pthread.h>
+#include <errno.h>
+
+/**
+ * Exception noprint flags
+ *
+ * Theses flags determine which exceptions should NOT be printed to stderr by
+ * the exception printing routines. For example, if you expect to see
+ * FileNotFound, you might use NOPRINT_EXC_FILE_NOT_FOUND, to avoid filling the
+ * logs with messages about routine events.
+ *
+ * On the other hand, if you don't expect any failures, you might pass
+ * PRINT_EXC_ALL.
+ *
+ * You can OR these flags together to avoid printing multiple classes of
+ * exceptions.
+ */
+#define PRINT_EXC_ALL 0x00
+#define NOPRINT_EXC_FILE_NOT_FOUND 0x01
+#define NOPRINT_EXC_ACCESS_CONTROL 0x02
+#define NOPRINT_EXC_UNRESOLVED_LINK 0x04
+#define NOPRINT_EXC_PARENT_NOT_DIRECTORY 0x08
+#define NOPRINT_EXC_ILLEGAL_ARGUMENT 0x10
+
+/**
+ * Get information about an exception.
+ *
+ * @param excName The Exception name.
+ * This is a Java class name in JNI format.
+ * @param noPrintFlags Flags which determine which exceptions we should NOT
+ * print.
+ * @param excErrno (out param) The POSIX error number associated with the
+ * exception.
+ * @param shouldPrint (out param) Nonzero if we should print this exception,
+ * based on the noPrintFlags and its name.
+ */
+void getExceptionInfo(const char *excName, int noPrintFlags,
+ int *excErrno, int *shouldPrint);
+
+/**
+ * Print out information about an exception and free it.
+ *
+ * @param env The JNI environment
+ * @param exc The exception to print and free
+ * @param noPrintFlags Flags which determine which exceptions we should NOT
+ * print.
+ * @param fmt Printf-style format list
+ * @param ap Printf-style varargs
+ *
+ * @return The POSIX error number associated with the exception
+ * object.
+ */
+int printExceptionAndFreeV(JNIEnv *env, jthrowable exc, int noPrintFlags,
+ const char *fmt, va_list ap);
+
+/**
+ * Print out information about an exception and free it.
+ *
+ * @param env The JNI environment
+ * @param exc The exception to print and free
+ * @param noPrintFlags Flags which determine which exceptions we should NOT
+ * print.
+ * @param fmt Printf-style format list
+ * @param ... Printf-style varargs
+ *
+ * @return The POSIX error number associated with the exception
+ * object.
+ */
+int printExceptionAndFree(JNIEnv *env, jthrowable exc, int noPrintFlags,
+ const char *fmt, ...) __attribute__((format(printf, 4, 5)));
+
+/**
+ * Print out information about the pending exception and free it.
+ *
+ * @param env The JNI environment
+ * @param noPrintFlags Flags which determine which exceptions we should NOT
+ * print.
+ * @param fmt Printf-style format list
+ * @param ... Printf-style varargs
+ *
+ * @return The POSIX error number associated with the exception
+ * object.
+ */
+int printPendingExceptionAndFree(JNIEnv *env, int noPrintFlags,
+ const char *fmt, ...) __attribute__((format(printf, 3, 4)));
+
+/**
+ * Get a local reference to the pending exception and clear it.
+ *
+ * Once it is cleared, the exception will no longer be pending. The caller will
+ * have to decide what to do with the exception object.
+ *
+ * @param env The JNI environment
+ *
+ * @return The exception, or NULL if there was no exception
+ */
+jthrowable getPendingExceptionAndClear(JNIEnv *env);
+
+/**
+ * Create a new runtime error.
+ *
+ * This creates (but does not throw) a new RuntimeError.
+ *
+ * @param env The JNI environment
+ * @param fmt Printf-style format list
+ * @param ... Printf-style varargs
+ *
+ * @return A local reference to a RuntimeError
+ */
+jthrowable newRuntimeError(JNIEnv *env, const char *fmt, ...)
+ __attribute__((format(printf, 2, 3)));
+
+#endif
Added: hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/jni_helper.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/jni_helper.c?rev=1602280&view=auto
==============================================================================
--- hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/jni_helper.c (added)
+++ hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/jni_helper.c Thu Jun 12 19:56:23 2014
@@ -0,0 +1,739 @@
+/**
+ * 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 "common/htable.h"
+#include "config.h"
+#include "jni/exception.h"
+#include "jni/jni_helper.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <uv.h>
+
+/**
+ * JNI Helper functions.
+ *
+ * These are a bunch of functions to make using JNI more bearable.
+ * They should be portable, since we use libuv for most platform-specific
+ * things.
+ *
+ * Currently, once JNI is initialized, it cannot be uninitialized. This is
+ * fine for most apps, but at some point, we should implement a shutdown
+ * function.
+ */
+
+/**
+ * Non-zero if jni_helper.c is initialized.
+ */
+static int g_jni_init;
+
+/**
+ * Once structure initializing jni_helper.c.
+ */
+static uv_once_t g_jni_init_once = UV_ONCE_INIT;
+
+/**
+ * The JNI library.
+ */
+static uv_lib_t g_jni_lib;
+
+/**
+ * The JNI_GetCreatedJavaVMs function.
+ */
+jint (*GetCreatedJavaVMs)(JavaVM **vmBuf, jsize bufLen, jsize *nVMs);
+
+/**
+ * The JNI_CreateJavaVM function.
+ */
+jint (*CreateJavaVM)(JavaVM **p_vm, void **p_env, void *vm_args);
+
+/**
+ * A hash table mapping class names to jclass objects.
+ * The keys are strings, and the values are jclass objects.
+ * We do not ever delete entries from this table.
+ *
+ * This may only be accessed under g_name_to_classref_htable_lock.
+ */
+static struct htable *g_name_to_classref_htable;
+
+/**
+ * The lock protecting g_name_to_classref_htable.
+ */
+static uv_mutex_t g_name_to_classref_htable_lock;
+
+/**
+ * Key that allows us to retrieve thread-local storage
+ *
+ * TODO: use the libuv local storage wrappers, once they supports thread
+ * destructors. (See https://github.com/joyent/libuv/issues/1216)
+ **/
+static pthread_key_t g_tls_key;
+
+/** The Native return types that methods could return */
+#define VOID 'V'
+#define JOBJECT 'L'
+#define JARRAYOBJECT '['
+#define JBOOLEAN 'Z'
+#define JBYTE 'B'
+#define JCHAR 'C'
+#define JSHORT 'S'
+#define JINT 'I'
+#define JLONG 'J'
+#define JFLOAT 'F'
+#define JDOUBLE 'D'
+
+/** Pthreads thread-local storage for each library thread. */
+struct hdfsTls {
+ JNIEnv *env;
+};
+
+static void hdfsThreadDestructor(void *v);
+static JNIEnv* getGlobalJNIEnv(void);
+static uint32_t jni_helper_hash_string(const void *key, uint32_t capacity);
+static int jni_helper_compare_string(const void *a, const void *b);
+
+static void jni_helper_init(void)
+{
+ int ret;
+ JNIEnv *env;
+ jthrowable jthr;
+
+ if (uv_dlopen(JNI_LIBRARY_NAME, &g_jni_lib) < 0) {
+ fprintf(stderr, "jni_helper_init: failed to load " JNI_LIBRARY_NAME
+ ": %s\n", uv_dlerror(&g_jni_lib));
+ return;
+ }
+ if (uv_dlsym(&g_jni_lib, "JNI_GetCreatedJavaVMs",
+ (void**)&GetCreatedJavaVMs) < 0) {
+ fprintf(stderr, "jni_helper_init: failed to find "
+ "JNI_GetCreatedJavaVMs function in "
+ JNI_LIBRARY_NAME "\n");
+ return;
+ }
+ if (uv_dlsym(&g_jni_lib, "JNI_CreateJavaVM",
+ (void**)&CreateJavaVM) < 0) {
+ fprintf(stderr, "jni_helper_init: failed to find "
+ "JNI_CreateJavaVM function in "
+ JNI_LIBRARY_NAME "\n");
+ return;
+ }
+ env = getGlobalJNIEnv();
+ if (!env) {
+ fprintf(stderr, "jni_helper_init: getGlobalJNIENv failed.\n");
+ return;
+ }
+ g_name_to_classref_htable = htable_alloc(128,
+ jni_helper_hash_string, jni_helper_compare_string);
+ if (!g_name_to_classref_htable) {
+ fprintf(stderr, "jni_helper_init: failed to allocate "
+ "name-to-classref hash table.\n");
+ return;
+ }
+ if (uv_mutex_init(&g_name_to_classref_htable_lock) < 0) {
+ fprintf(stderr, "jni_helper_init: failed to init mutex for "
+ "name-to-classref hash table.\n");
+ return;
+ }
+ ret = pthread_key_create(&g_tls_key, hdfsThreadDestructor);
+ if (ret) {
+ fprintf(stderr, "jni_helper_init: pthread_key_create failed with "
+ "error %d\n", ret);
+ return;
+ }
+ jthr = invokeMethod(env, NULL, STATIC, NULL,
+ "org/apache/hadoop/fs/FileSystem",
+ "loadFileSystems", "()V");
+ if (jthr) {
+ printExceptionAndFree(env, jthr, PRINT_EXC_ALL, "loadFileSystems");
+ return;
+ }
+ g_jni_init = 1;
+}
+
+/**
+ * The function that is called whenever a thread with libhdfs thread local data
+ * is destroyed.
+ *
+ * @param v The thread-local data
+ */
+static void hdfsThreadDestructor(void *v)
+{
+ struct hdfsTls *tls = v;
+ JavaVM *vm;
+ JNIEnv *env = tls->env;
+ jint ret;
+
+ ret = (*env)->GetJavaVM(env, &vm);
+ if (ret) {
+ fprintf(stderr, "hdfsThreadDestructor: GetJavaVM failed with "
+ "error %d\n", ret);
+ (*env)->ExceptionDescribe(env);
+ } else {
+ (*vm)->DetachCurrentThread(vm);
+ }
+ free(tls);
+}
+
+void destroyLocalReference(JNIEnv *env, jobject jObject)
+{
+ if (jObject)
+ (*env)->DeleteLocalRef(env, jObject);
+}
+
+static jthrowable validateMethodType(JNIEnv *env, MethType methType)
+{
+ if (methType != STATIC && methType != INSTANCE) {
+ return newRuntimeError(env, "validateMethodType(methType=%d): "
+ "illegal method type.\n", methType);
+ }
+ return NULL;
+}
+
+jthrowable newJavaStr(JNIEnv *env, const char *str, jstring *out)
+{
+ jstring jstr;
+
+ if (!str) {
+ /* Can't pass NULL to NewStringUTF: the result would be
+ * implementation-defined. */
+ *out = NULL;
+ return NULL;
+ }
+ jstr = (*env)->NewStringUTF(env, str);
+ if (!jstr) {
+ /* If NewStringUTF returns NULL, an exception has been thrown,
+ * which we need to handle. Probaly an OOM. */
+ return getPendingExceptionAndClear(env);
+ }
+ *out = jstr;
+ return NULL;
+}
+
+jthrowable newCStr(JNIEnv *env, jstring jstr, char **out)
+{
+ const char *tmp;
+
+ if (!jstr) {
+ *out = NULL;
+ return NULL;
+ }
+ tmp = (*env)->GetStringUTFChars(env, jstr, NULL);
+ if (!tmp) {
+ return getPendingExceptionAndClear(env);
+ }
+ *out = strdup(tmp);
+ (*env)->ReleaseStringUTFChars(env, jstr, tmp);
+ return NULL;
+}
+
+static uint32_t jni_helper_hash_string(const void *key, uint32_t capacity)
+{
+ const char *str = key;
+ uint32_t hash = 0;
+
+ while (*str) {
+ hash = (hash * 31) + *str;
+ str++;
+ }
+ return hash % capacity;
+}
+
+static int jni_helper_compare_string(const void *a, const void *b)
+{
+ return strcmp(a, b) == 0;
+}
+
+jthrowable invokeMethod(JNIEnv *env, jvalue *retval, MethType methType,
+ jobject instObj, const char *className,
+ const char *methName, const char *methSignature, ...)
+{
+ va_list args;
+ jclass cls;
+ jmethodID mid;
+ jthrowable jthr;
+ const char *str;
+ char returnType;
+
+ jthr = validateMethodType(env, methType);
+ if (jthr)
+ return jthr;
+ jthr = globalClassReference(className, env, &cls);
+ if (jthr)
+ return jthr;
+ jthr = methodIdFromClass(className, methName, methSignature,
+ methType, env, &mid);
+ if (jthr)
+ return jthr;
+ str = methSignature;
+ while (*str != ')') str++;
+ str++;
+ returnType = *str;
+ va_start(args, methSignature);
+ if (returnType == JOBJECT || returnType == JARRAYOBJECT) {
+ jobject jobj = NULL;
+ if (methType == STATIC) {
+ jobj = (*env)->CallStaticObjectMethodV(env, cls, mid, args);
+ }
+ else if (methType == INSTANCE) {
+ jobj = (*env)->CallObjectMethodV(env, instObj, mid, args);
+ }
+ retval->l = jobj;
+ }
+ else if (returnType == VOID) {
+ if (methType == STATIC) {
+ (*env)->CallStaticVoidMethodV(env, cls, mid, args);
+ }
+ else if (methType == INSTANCE) {
+ (*env)->CallVoidMethodV(env, instObj, mid, args);
+ }
+ }
+ else if (returnType == JBOOLEAN) {
+ jboolean jbool = 0;
+ if (methType == STATIC) {
+ jbool = (*env)->CallStaticBooleanMethodV(env, cls, mid, args);
+ }
+ else if (methType == INSTANCE) {
+ jbool = (*env)->CallBooleanMethodV(env, instObj, mid, args);
+ }
+ retval->z = jbool;
+ }
+ else if (returnType == JSHORT) {
+ jshort js = 0;
+ if (methType == STATIC) {
+ js = (*env)->CallStaticShortMethodV(env, cls, mid, args);
+ }
+ else if (methType == INSTANCE) {
+ js = (*env)->CallShortMethodV(env, instObj, mid, args);
+ }
+ retval->s = js;
+ }
+ else if (returnType == JLONG) {
+ jlong jl = -1;
+ if (methType == STATIC) {
+ jl = (*env)->CallStaticLongMethodV(env, cls, mid, args);
+ }
+ else if (methType == INSTANCE) {
+ jl = (*env)->CallLongMethodV(env, instObj, mid, args);
+ }
+ retval->j = jl;
+ }
+ else if (returnType == JINT) {
+ jint ji = -1;
+ if (methType == STATIC) {
+ ji = (*env)->CallStaticIntMethodV(env, cls, mid, args);
+ }
+ else if (methType == INSTANCE) {
+ ji = (*env)->CallIntMethodV(env, instObj, mid, args);
+ }
+ retval->i = ji;
+ }
+ va_end(args);
+
+ jthr = (*env)->ExceptionOccurred(env);
+ if (jthr) {
+ (*env)->ExceptionClear(env);
+ return jthr;
+ }
+ return NULL;
+}
+
+jthrowable constructNewObjectOfClass(JNIEnv *env, jobject *out, const char *className,
+ const char *ctorSignature, ...)
+{
+ va_list args;
+ jclass cls;
+ jmethodID mid;
+ jobject jobj;
+ jthrowable jthr;
+
+ jthr = globalClassReference(className, env, &cls);
+ if (jthr)
+ return jthr;
+ jthr = methodIdFromClass(className, "<init>", ctorSignature,
+ INSTANCE, env, &mid);
+ if (jthr)
+ return jthr;
+ va_start(args, ctorSignature);
+ jobj = (*env)->NewObjectV(env, cls, mid, args);
+ va_end(args);
+ if (!jobj)
+ return getPendingExceptionAndClear(env);
+ *out = jobj;
+ return NULL;
+}
+
+
+jthrowable methodIdFromClass(const char *className, const char *methName,
+ const char *methSignature, MethType methType,
+ JNIEnv *env, jmethodID *out)
+{
+ jclass cls;
+ jthrowable jthr;
+
+ jthr = globalClassReference(className, env, &cls);
+ if (jthr)
+ return jthr;
+ jmethodID mid = 0;
+ jthr = validateMethodType(env, methType);
+ if (jthr)
+ return jthr;
+ if (methType == STATIC) {
+ mid = (*env)->GetStaticMethodID(env, cls, methName, methSignature);
+ }
+ else if (methType == INSTANCE) {
+ mid = (*env)->GetMethodID(env, cls, methName, methSignature);
+ }
+ if (mid == NULL) {
+ fprintf(stderr, "could not find method %s from class %s with "
+ "signature %s\n", methName, className, methSignature);
+ return getPendingExceptionAndClear(env);
+ }
+ *out = mid;
+ return NULL;
+}
+
+jthrowable globalClassReference(const char *className, JNIEnv *env, jclass *out)
+{
+ jthrowable jthr = NULL;
+ jclass local_clazz = NULL;
+ jclass clazz = NULL;
+ int ret;
+
+ uv_mutex_lock(&g_name_to_classref_htable_lock);
+ clazz = htable_get(g_name_to_classref_htable, className);
+ if (clazz) {
+ *out = clazz;
+ goto done;
+ }
+ local_clazz = (*env)->FindClass(env,className);
+ if (!local_clazz) {
+ jthr = getPendingExceptionAndClear(env);
+ goto done;
+ }
+ clazz = (*env)->NewGlobalRef(env, local_clazz);
+ if (!clazz) {
+ jthr = getPendingExceptionAndClear(env);
+ goto done;
+ }
+ ret = htable_put(g_name_to_classref_htable, (char*)className, clazz);
+ if (ret) {
+ jthr = newRuntimeError(env, "htable_put failed with error "
+ "code %d\n", ret);
+ goto done;
+ }
+ *out = clazz;
+ jthr = NULL;
+done:
+ uv_mutex_unlock(&g_name_to_classref_htable_lock);
+ (*env)->DeleteLocalRef(env, local_clazz);
+ if (jthr && clazz) {
+ (*env)->DeleteGlobalRef(env, clazz);
+ }
+ return jthr;
+}
+
+jthrowable classNameOfObject(jobject jobj, JNIEnv *env, char **name)
+{
+ jthrowable jthr;
+ jclass cls, clsClass = NULL;
+ jmethodID mid;
+ jstring str = NULL;
+ const char *cstr = NULL;
+ char *newstr;
+
+ cls = (*env)->GetObjectClass(env, jobj);
+ if (cls == NULL) {
+ jthr = getPendingExceptionAndClear(env);
+ goto done;
+ }
+ clsClass = (*env)->FindClass(env, "java/lang/Class");
+ if (clsClass == NULL) {
+ jthr = getPendingExceptionAndClear(env);
+ goto done;
+ }
+ mid = (*env)->GetMethodID(env, clsClass, "getName", "()Ljava/lang/String;");
+ if (mid == NULL) {
+ jthr = getPendingExceptionAndClear(env);
+ goto done;
+ }
+ str = (*env)->CallObjectMethod(env, cls, mid);
+ if (str == NULL) {
+ jthr = getPendingExceptionAndClear(env);
+ goto done;
+ }
+ cstr = (*env)->GetStringUTFChars(env, str, NULL);
+ if (!cstr) {
+ jthr = getPendingExceptionAndClear(env);
+ goto done;
+ }
+ newstr = strdup(cstr);
+ if (newstr == NULL) {
+ jthr = newRuntimeError(env, "classNameOfObject: out of memory");
+ goto done;
+ }
+ *name = newstr;
+ jthr = NULL;
+
+done:
+ destroyLocalReference(env, cls);
+ destroyLocalReference(env, clsClass);
+ if (str) {
+ if (cstr)
+ (*env)->ReleaseStringUTFChars(env, str, cstr);
+ (*env)->DeleteLocalRef(env, str);
+ }
+ return jthr;
+}
+
+/**
+ * Get the global JNI environemnt.
+ *
+ * We only have to create the JVM once. After that, we can use it in
+ * every thread. You must be holding the jvmMutex when you call this
+ * function.
+ *
+ * @return The JNIEnv on success; error code otherwise
+ */
+static JNIEnv* getGlobalJNIEnv(void)
+{
+ const jsize vmBufLength = 1;
+ char *classpath;
+ JavaVM* vmBuf[vmBufLength];
+ JNIEnv *env;
+ jint rv = 0;
+ jint noVMs = 0;
+
+ rv = GetCreatedJavaVMs(&(vmBuf[0]), vmBufLength, &noVMs);
+ if (rv != 0) {
+ fprintf(stderr, "getGlobalJNIEnv: JNI_GetCreatedJavaVMs failed "
+ "with error: %d\n", rv);
+ return NULL;
+ }
+ if (noVMs > 0) {
+ //Attach this thread to the VM
+ JavaVM* vm = vmBuf[0];
+ rv = (*vm)->AttachCurrentThread(vm, (void*)&env, 0);
+ if (rv != 0) {
+ fprintf(stderr, "getGlobalJNIEnv: Call to AttachCurrentThread "
+ "failed with error: %d\n", rv);
+ return NULL;
+ }
+ return env;
+ }
+ //Get the environment variables for initializing the JVM
+ classpath = getenv("CLASSPATH");
+ if (!classpath) {
+ fprintf(stderr, "getGlobalJNIEnv: The CLASSPATH environment "
+ "variable was not set.");
+ return NULL;
+ }
+ char *hadoopClassPathVMArg = "-Djava.class.path=";
+ size_t optHadoopClassPathLen = strlen(classpath) +
+ strlen(hadoopClassPathVMArg) + 1;
+ char *optHadoopClassPath = malloc(optHadoopClassPathLen);
+ snprintf(optHadoopClassPath, optHadoopClassPathLen,
+ "%s%s", hadoopClassPathVMArg, classpath);
+
+ // Determine the # of LIBHDFS_OPTS args
+ int noArgs = 1;
+ char *hadoopJvmArgs = getenv("LIBHDFS_OPTS");
+ char jvmArgDelims[] = " ";
+ char *str, *token, *savePtr;
+ if (hadoopJvmArgs != NULL) {
+ hadoopJvmArgs = strdup(hadoopJvmArgs);
+ for (noArgs = 1, str = hadoopJvmArgs; ; noArgs++, str = NULL) {
+ token = strtok_r(str, jvmArgDelims, &savePtr);
+ if (NULL == token) {
+ break;
+ }
+ }
+ free(hadoopJvmArgs);
+ }
+
+ // Now that we know the # args, populate the options array
+ JavaVMOption options[noArgs];
+ options[0].optionString = optHadoopClassPath;
+ hadoopJvmArgs = getenv("LIBHDFS_OPTS");
+ if (hadoopJvmArgs != NULL) {
+ hadoopJvmArgs = strdup(hadoopJvmArgs);
+ for (noArgs = 1, str = hadoopJvmArgs; ; noArgs++, str = NULL) {
+ token = strtok_r(str, jvmArgDelims, &savePtr);
+ if (NULL == token) {
+ break;
+ }
+ options[noArgs].optionString = token;
+ }
+ }
+
+ //Create the VM
+ JavaVMInitArgs vm_args;
+ JavaVM *vm;
+ vm_args.version = JNI_VERSION_1_2;
+ vm_args.options = options;
+ vm_args.nOptions = noArgs;
+ vm_args.ignoreUnrecognized = 1;
+
+ rv = CreateJavaVM(&vm, (void*)&env, &vm_args);
+
+ if (hadoopJvmArgs != NULL) {
+ free(hadoopJvmArgs);
+ }
+ free(optHadoopClassPath);
+ if (rv != 0) {
+ fprintf(stderr, "Call to JNI_CreateJavaVM failed "
+ "with error: %d\n", rv);
+ return NULL;
+ }
+ return env;
+}
+
+/**
+ * getJNIEnv: A helper function to get the JNIEnv* for the given thread.
+ * If no JVM exists, then one will be created. JVM command line arguments
+ * are obtained from the LIBHDFS_OPTS environment variable.
+ *
+ * Implementation note: we rely on POSIX thread-local storage (tls).
+ * This allows us to associate a destructor function with each thread, that
+ * will detach the thread from the Java VM when the thread terminates. If we
+ * failt to do this, it will cause a memory leak.
+ *
+ * However, POSIX TLS is not the most efficient way to do things. It requires a
+ * key to be initialized before it can be used. Since we don't know if this key
+ * is initialized at the start of this function, we have to lock a mutex first
+ * and check. Luckily, most operating systems support the more efficient
+ * __thread construct, which is initialized by the linker.
+ *
+ * @param: None.
+ * @return The JNIEnv* corresponding to the thread.
+ */
+JNIEnv* getJNIEnv(void)
+{
+ JNIEnv *env;
+ struct hdfsTls *tls;
+ int ret;
+
+#ifdef HAVE_BETTER_TLS
+ static __thread struct hdfsTls *quickTls = NULL;
+ if (quickTls)
+ return quickTls->env;
+#endif
+ uv_once(&g_jni_init_once, jni_helper_init);
+ if (!g_jni_init) {
+ fprintf(stderr, "getJNIEnv: failed to initialize jni.\n");
+ return NULL;
+ }
+ tls = pthread_getspecific(g_tls_key);
+ if (tls) {
+ return tls->env;
+ }
+ env = getGlobalJNIEnv();
+ if (!env) {
+ fprintf(stderr, "getJNIEnv: getGlobalJNIEnv failed\n");
+ return NULL;
+ }
+ tls = calloc(1, sizeof(struct hdfsTls));
+ if (!tls) {
+ fprintf(stderr, "getJNIEnv: OOM allocating %zd bytes\n",
+ sizeof(struct hdfsTls));
+ return NULL;
+ }
+ tls->env = env;
+ ret = pthread_setspecific(g_tls_key, tls);
+ if (ret) {
+ fprintf(stderr, "getJNIEnv: pthread_setspecific failed with "
+ "error code %d\n", ret);
+ hdfsThreadDestructor(tls);
+ return NULL;
+ }
+#ifdef HAVE_BETTER_TLS
+ quickTls = tls;
+#endif
+ return env;
+}
+
+int javaObjectIsOfClass(JNIEnv *env, jobject obj, const char *name)
+{
+ jclass clazz;
+ int ret;
+
+ clazz = (*env)->FindClass(env, name);
+ if (!clazz) {
+ printPendingExceptionAndFree(env, PRINT_EXC_ALL,
+ "javaObjectIsOfClass(%s)", name);
+ return -1;
+ }
+ ret = (*env)->IsInstanceOf(env, obj, clazz);
+ (*env)->DeleteLocalRef(env, clazz);
+ return ret == JNI_TRUE ? 1 : 0;
+}
+
+jthrowable hadoopConfSetStr(JNIEnv *env, jobject jConfiguration,
+ const char *key, const char *value)
+{
+ jthrowable jthr;
+ jstring jkey = NULL, jvalue = NULL;
+
+ jthr = newJavaStr(env, key, &jkey);
+ if (jthr)
+ goto done;
+ jthr = newJavaStr(env, value, &jvalue);
+ if (jthr)
+ goto done;
+ jthr = invokeMethod(env, NULL, INSTANCE, jConfiguration,
+ "org/apache/hadoop/conf/Configuration", "set",
+ "(Ljava/lang/String;Ljava/lang/String;)V",
+ jkey, jvalue);
+ if (jthr)
+ goto done;
+done:
+ (*env)->DeleteLocalRef(env, jkey);
+ (*env)->DeleteLocalRef(env, jvalue);
+ return jthr;
+}
+
+jthrowable fetchEnumInstance(JNIEnv *env, const char *className,
+ const char *valueName, jobject *out)
+{
+ jclass clazz;
+ jfieldID fieldId;
+ jobject jEnum;
+ char prettyClass[256];
+
+ clazz = (*env)->FindClass(env, className);
+ if (!clazz) {
+ return newRuntimeError(env, "fetchEnum(%s, %s): failed to find class.",
+ className, valueName);
+ }
+ if ((size_t)snprintf(prettyClass, sizeof(prettyClass), "L%s;", className)
+ >= sizeof(prettyClass)) {
+ return newRuntimeError(env, "fetchEnum(%s, %s): class name too long.",
+ className, valueName);
+ }
+ fieldId = (*env)->GetStaticFieldID(env, clazz, valueName, prettyClass);
+ if (!fieldId) {
+ return getPendingExceptionAndClear(env);
+ }
+ jEnum = (*env)->GetStaticObjectField(env, clazz, fieldId);
+ if (!jEnum) {
+ return getPendingExceptionAndClear(env);
+ }
+ *out = jEnum;
+ return NULL;
+}
+
+// vim: ts=4:sw=4:tw=79:et
Added: hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/jni_helper.h
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/jni_helper.h?rev=1602280&view=auto
==============================================================================
--- hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/jni_helper.h (added)
+++ hadoop/common/branches/HADOOP-10388/hadoop-native-core/src/main/native/jni/jni_helper.h Thu Jun 12 19:56:23 2014
@@ -0,0 +1,163 @@
+/**
+ * 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 LIBHDFS_JNI_HELPER_H
+#define LIBHDFS_JNI_HELPER_H
+
+#include <jni.h>
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <search.h>
+#include <pthread.h>
+#include <errno.h>
+
+#define PATH_SEPARATOR ':'
+
+
+/** Denote the method we want to invoke as STATIC or INSTANCE */
+typedef enum {
+ STATIC,
+ INSTANCE
+} MethType;
+
+/**
+ * Create a new malloc'ed C string from a Java string.
+ *
+ * @param env The JNI environment
+ * @param jstr The Java string
+ * @param out (out param) the malloc'ed C string
+ *
+ * @return NULL on success; the exception otherwise
+ */
+jthrowable newCStr(JNIEnv *env, jstring jstr, char **out);
+
+/**
+ * Create a new Java string from a C string.
+ *
+ * @param env The JNI environment
+ * @param str The C string
+ * @param out (out param) the java string
+ *
+ * @return NULL on success; the exception otherwise
+ */
+jthrowable newJavaStr(JNIEnv *env, const char *str, jstring *out);
+
+/**
+ * Helper function to destroy a local reference of java.lang.Object
+ * @param env: The JNIEnv pointer.
+ * @param jFile: The local reference of java.lang.Object object
+ * @return None.
+ */
+void destroyLocalReference(JNIEnv *env, jobject jObject);
+
+/** invokeMethod: Invoke a Static or Instance method.
+ * className: Name of the class where the method can be found
+ * methName: Name of the method
+ * methSignature: the signature of the method "(arg-types)ret-type"
+ * methType: The type of the method (STATIC or INSTANCE)
+ * instObj: Required if the methType is INSTANCE. The object to invoke
+ the method on.
+ * env: The JNIEnv pointer
+ * retval: The pointer to a union type which will contain the result of the
+ method invocation, e.g. if the method returns an Object, retval will be
+ set to that, if the method returns boolean, retval will be set to the
+ value (JNI_TRUE or JNI_FALSE), etc.
+ * exc: If the methods throws any exception, this will contain the reference
+ * Arguments (the method arguments) must be passed after methSignature
+ * RETURNS: -1 on error and 0 on success. If -1 is returned, exc will have
+ a valid exception reference, and the result stored at retval is undefined.
+ */
+jthrowable invokeMethod(JNIEnv *env, jvalue *retval, MethType methType,
+ jobject instObj, const char *className, const char *methName,
+ const char *methSignature, ...);
+
+jthrowable constructNewObjectOfClass(JNIEnv *env, jobject *out, const char *className,
+ const char *ctorSignature, ...);
+
+jthrowable methodIdFromClass(const char *className, const char *methName,
+ const char *methSignature, MethType methType,
+ JNIEnv *env, jmethodID *out);
+
+jthrowable globalClassReference(const char *className, JNIEnv *env, jclass *out);
+
+/** classNameOfObject: Get an object's class name.
+ * @param jobj: The object.
+ * @param env: The JNIEnv pointer.
+ * @param name: (out param) On success, will contain a string containing the
+ * class name. This string must be freed by the caller.
+ * @return NULL on success, or the exception
+ */
+jthrowable classNameOfObject(jobject jobj, JNIEnv *env, char **name);
+
+/** getJNIEnv: A helper function to get the JNIEnv* for the given thread.
+ * If no JVM exists, then one will be created. JVM command line arguments
+ * are obtained from the LIBHDFS_OPTS environment variable.
+ * @param: None.
+ * @return The JNIEnv* corresponding to the thread.
+ * */
+JNIEnv* getJNIEnv(void);
+
+/**
+ * Figure out if a Java object is an instance of a particular class.
+ *
+ * @param env The Java environment.
+ * @param obj The object to check.
+ * @param name The class name to check.
+ *
+ * @return -1 if we failed to find the referenced class name.
+ * 0 if the object is not of the given class.
+ * 1 if the object is of the given class.
+ */
+int javaObjectIsOfClass(JNIEnv *env, jobject obj, const char *name);
+
+/**
+ * Set a value in a configuration object.
+ *
+ * @param env The JNI environment
+ * @param jConfiguration The configuration object to modify
+ * @param key The key to modify
+ * @param value The value to set the key to
+ *
+ * @return NULL on success; exception otherwise
+ */
+jthrowable hadoopConfSetStr(JNIEnv *env, jobject jConfiguration,
+ const char *key, const char *value);
+
+/**
+ * Fetch an instance of an Enum.
+ *
+ * @param env The JNI environment.
+ * @param className The enum class name.
+ * @param valueName The name of the enum value
+ * @param out (out param) on success, a local reference to an
+ * instance of the enum object. (Since Java enums are
+ * singletones, this is also the only instance.)
+ *
+ * @return NULL on success; exception otherwise
+ */
+jthrowable fetchEnumInstance(JNIEnv *env, const char *className,
+ const char *valueName, jobject *out);
+
+#endif /*LIBHDFS_JNI_HELPER_H*/
+
+/**
+ * vim: ts=4: sw=4: et:
+ */
+