Hadoop-2.6.0上的C的API訪问HDFS

在通过Hadoop-2.6.0的C的API訪问HDFS的时候,编译和执行出现了不少问题,花费了几天的时间,上网查了好多的资料,最终还是把问题给攻克了

 參考文献:http://m.blog.csdn.net/blog/Aquester/25242215

系统:CentOS 6.6,hadoop-2.6.0, 在hadoop集群的datanode机器上进行

例子代码来源官方文档中的CAPI libhdfs:

#include"hdfs.h"

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

 int main(int argc, char **argv) {

 

       hdfsFS fs =hdfsConnect("10.25.100.130", 9000); //在这里做了一点改动

        const char* writePath ="/tmp/testfile.txt";

        hdfsFile writeFile = hdfsOpenFile(fs,writePath, O_WRONLY|O_CREAT, 0, 0, 0);

        if(!writeFile) {

              fprintf(stderr, "Failed toopen %s for writing! ", writePath);

              exit(-1);

        }

        char* buffer = "Hello,World!";

        tSize num_written_bytes = hdfsWrite(fs,writeFile, (void*)buffer, strlen(buffer)+1);

        if (hdfsFlush(fs, writeFile)) {

               fprintf(stderr, "Failed to'flush' %s ", writePath);

              exit(-1);

        }

        hdfsCloseFile(fs, writeFile);

    }

接下来就是编译。依照官网上给出的:

How To Link With The Library

See the CMake filefor test_libhdfs_ops.c in the libhdfssource directory (hadoop-hdfs-project/hadoop-hdfs/src/CMakeLists.txt) or something like: gcc above_sample.c -I$HADOOP_HDFS_HOME/include -L$HADOOP_HDFS_HOME/lib/native-lhdfs -o above_sample

试用另外一种:

[root@node04 ~]# gcc above_sample.c -I/home/hadoop/hadoop-2.6.0/include/ -L /home/hadoop/hadoop-2.6.0/lib/native/-lhdfs -o above_sample

能够通过,查了好多资料。非常少有人使用这一种。怎样使用这一种有错误,也能够换用第二种。


我使用的是这一种编译方式:

[root@node04 ~]# gcc above_sample.c -I/home/hadoop/hadoop-2.6.0/include/ -L /home/hadoop/hadoop-2.6.0/lib/native/-lhdfs /usr/java/jdk1.7.0_75/jre/lib/amd64/server/libjvm.so -o above_sample

这两种方法都能够生成一个可运行的文件above_sample

编译通过,能够在执行的时候出现下面错误:

[root@node04 ~]# ./above_sample

./above_sample: error while loading sharedlibraries: libjvm.so: cannot open shared object file: No such file or directory

发生这样的报错的原因是,编译的程序执行期间须要依赖某个共享库,比方上面,write可执行程序须要依赖一个叫“libxxxx.so”的共享库。(动态链接库与静态链接库的差别。请百度相关文档)

/etc/ld.so.conf中加入路径,然后又一次载入共享库:

首先要找到缺失这个库的存在路径

[root@node04 ~]# find / -name libhdfs.so.0.0.0

/home/hadoop/hadoop-2.6.0/lib/native/libhdfs.so.0.0.0

[root@node04 ~]# find / -name libjvm.so

/usr/java/jdk1.7.0_75/jre/lib/amd64/server/libjvm.so

 [root@node04 ~]# vi /etc/ld.so.conf

 编辑后例如以下:

include ld.so.conf.d/*.conf

/home/hadoop/hadoop-2.6.0/lib/native/

/usr/java/jdk1.7.0_75/jre/lib/amd64/server/

分别加入了两个路径。每一个路径占一行。

编辑完后,又一次载入库:

[root@node04 ~]# /sbin/ldconfig –v

这一种方法是是针对整个系统,启动时就载入

 然后我们就继续运行可运行文件:

[root@node04 ~]# ./above_sample

loadFileSystems error:

(unable to get stack trace for java.lang.NoClassDefFoundError exception: ExceptionUtils::getStackTrace error.)

hdfsBuilderConnect(forceNewInstance=0, nn=172.25.40.171, port=9001, kerbTicketCachePath=(NULL), userName=(NULL)) error:

(unable to get stack trace for java.lang.NoClassDefFoundError exception: ExceptionUtils::getStackTrace error.)

经过查找资料发现:

上述信息中的关键项是“NoClassDefFoundError”和“ExceptionUtils”。也就是找不到ExceptionUtils,一般可判断是由于找不到对应的jar文件,Google搜索“ExceptionUtils  jar”,发现“ExceptionUtils”应当是在包apache-commons-lang.jar中。

进一步用Google去搜索“apache-commons-lang.jar”,找到下载网址:http://commons.apache.org/proper/commons-lang/download_lang.cgi,上面能够下载commons-lang3-3.3.2-bin.tar.gz,解压后就能够看到commons-lang3-3.3.2.jar。

hadoop的二进制安装包,应当自带了这个文件。通过努力。在hadoop安装文件夹下的share/hadoop/tools/lib子文件夹下发现了commons-lang-2.6.jar,应当就是它了

 然后改动我们的环境变量。在我们配置java环境变量之后加入hadoop的环境变量

[root@node04 ~]# vi /etc/profile

unset i

unset -f pathmunge

 export JAVA_HOME=/usr/java/jdk1.7.0_75

export JRE_HOME=$JAVA_HOME/jre

export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib/rt.jar

PATH=$PATH:$JAVA_HOME/bin

 HADOOP_HOME=/home/hadoop/hadoop-2.6.0

exportPATH=$HADOOP_HOME/bin:$PATH

exportCLASSPATH=.:$HADOOP_HOME/share/hadoop/common/lib/commons-lang-2.6.jar

又一次执行程序。ExceptionUtils错误消失了,但遇到新错误:

loadFileSystems error:

java.lang.NoClassDefFoundError: org/apache/hadoop/fs/FileSystem

Caused by: java.lang.ClassNotFoundException: org.apache.hadoop.fs.FileSystem

        at java.net.URLClassLoader$1.run(URLClassLoader.java:372)

        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)

        at java.security.AccessController.doPrivileged(Native Method)

        at java.net.URLClassLoader.findClass(URLClassLoader.java:360)

        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)

        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

hdfsBuilderConnect(forceNewInstance=0, nn=10.25.100.130, port=9000, kerbTicketCachePath=(NULL), userName=(NULL)) error:

java.lang.NoClassDefFoundError: org/apache/hadoop/conf/Configuration

Caused by: java.lang.ClassNotFoundException: org.apache.hadoop.conf.Configuration

        at java.net.URLClassLoader$1.run(URLClassLoader.java:372)

        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)

        at java.security.AccessController.doPrivileged(Native Method)

        at java.net.URLClassLoader.findClass(URLClassLoader.java:360)

        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)

        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

仍然是NoClassDefFoundError错误,原因应当是一样的:classpath中漏了哪个文件夹。这就要看FileSystemConfiguration在哪个jar中了。尝试将hadoop-common-2.6.0.jarcommons-configuration-1.6.jar直接增加到classpath

[root@node04~]# vi /etc/profile

export=CLASSPATH=.:$HADOOP_HOME/share/hadoop/common/lib/commons-lang-2.6.jar:/home/hadoop/hadoop-2.6.0/share/hadoop/common/hadoop-common-2.6.0.jar:/home/#hadoop/hadoop-2.6.0/share/hadoop/common/lib/commons-configuration-1.6.jar:/home/hadoop/hadoop-2.6.0/share/hadoop/common/lib/commons-logging-1.1.3.jar:/#home/hadoop/hadoop-2.6.0/share/hadoop/hdfs/hadoop-hdfs-2.6.0.jar

发现FileSystem和Configuration错误消失了,说明有效:

loadFileSystems error:

java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory

        at org.apache.hadoop.fs.FileSystem.<clinit>(FileSystem.java:95)

Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory

        at java.net.URLClassLoader$1.run(URLClassLoader.java:372)

。。。

。。。。

。。。。。。。

。。。

。。

。。

。。。

。。。。。。

。。

。。。。。。。。

。。。。

。。。。。。。。。。

。。。

。。

。。

经过查找资料发现,还是类似的错误,这样下会去搞死人。通过上述的一些操作。预计须要将全部的jar文件一个个的将入到classpath中。因为对java不熟悉,也仅仅有先这样做一做了

[root@node04 ~]# find /home/hadoop/hadoop-2.6.0/share/ -name *.jar|awk '{ printf("exportCLASSPATH=%s:$CLASSPATH ", $0); }'

将查找到的所有结果所有导入到环境变量中,,将刚才加入的环境变量凝视:

[root@node04 ~]#vi /etc/profile

unset i

unset -fpathmunge

 export JAVA_HOME=/usr/java/jdk1.7.0_75

export JRE_HOME=$JAVA_HOME/jre

export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib/rt.jar

PATH=$PATH:$JAVA_HOME/bin

 HADOOP_HOME=/home/hadoop/hadoop-2.6.0

export PATH=$HADOOP_HOME/bin:$PATH

 #export=CLASSPATH=.:$HADOOP_HOME/share/hadoop/common/lib/commons-lang-2.6.jar:/home/hadoop/hadoop-2.6.0/share/hadoop/common/hadoop-common-2.6.0.jar:/home/#hadoop/hadoop-2.6.0/share/hadoop/common/lib/commons-configuration-1.6.jar:/home/hadoop/hadoop-2.6.0/share/hadoop/common/lib/commons-logging-1.1.3.jar:/#home/hadoop/hadoop-2.6.0/share/hadoop/hdfs/hadoop-hdfs-2.6.0.jar

 exportCLASSPATH=/home/hadoop/hadoop-2.6.0/share/hadoop/mapreduce/lib-examples/hsqldb-2.0.0.jar:$CLASSPATH

export CLASSPATH=/home/hadoop/hadoop-2.6.0/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0.jar:$CLASSPATH

exportCLASSPATH=/home/hadoop/hadoop-2.6.0/share/hadoop/mapreduce/hadoop-mapreduce-client-common-2.6.0.jar:$CLASSPATH

export CLASSPATH=/home/hadoop/hadoop-2.6.0/share/hadoop/mapreduce/hadoop-mapreduce-client-hs-2.6.0.jar:$CLASSPATH

exportCLASSPATH=/home/hadoop/hadoop-2.6.0/share/hadoop/mapreduce/hadoop-mapreduce-client-shuffle-2.6.0.jar:$CLASSPATH

exportCLASSPATH=/home/hadoop/hadoop-2.6.0/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.6.0-tests.jar:$CLASSPATH

exportCLASSPATH=/home/hadoop/hadoop-2.6.0/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.6.0.jar:$CLASSPATH

exportCLASSPATH=/home/hadoop/hadoop-2.6.0/share/hadoop/mapreduce/lib/aopalliance-1.0.jar:$CLASSPATH

exportCLASSPATH=/home/hadoop/hadoop-2.6.0/share/hadoop/mapreduce/lib/javax.inject-1.jar:$CLASSPATH

exportCLASSPATH=/home/hadoop/hadoop-2.6.0/share/hadoop/mapreduce/lib/leveldbjni-all-1.8.jar:$CLASSPATH

export CLASSPATH=/home/hadoop/hadoop-2.6.0/share/hadoop/mapreduce/lib/guice-servlet-3.0.jar:$CLASSPATH

。。。。。。。

。。。。。。

。。。。

。。

。。。。。。。

。。。

。。。

。。。

。。。。。

。。。。

。。

。。。

。。。。

。。。

。。。。。。

。。

。。

。。

。。。。。

。。。。。。。。

。。。。。

。。。。。。。。。。。。。

。。

。。。。。。。。。。。

。。。。。

。。

。。。。

。。

。。。

。。。。。。。。

。。。

。。。。。。。。。。。

。。。。。

。。。。

。。。

。。

。。

。。。。。

。。。

。。。。。。。

。。

。。

。。。。。。

。。

。。。。

。。。。。

。。。

。。

。。。

 搞定之后,然后继续执行

[root@node04 ~]# ./above_sample

SLF4J: Class path contains multiple SLF4J bindings.

SLF4J: Found binding in[jar:file:/home/hadoop/hadoop-2.6.0/share/hadoop/kms/tomcat/webapps/kms/WEB-INF/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]

SLF4J: Found binding in[jar:file:/home/hadoop/hadoop-2.6.0/share/hadoop/httpfs/tomcat/webapps/webhdfs/WEB-INF/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]

SLF4J: Found binding in[jar:file:/home/hadoop/hadoop-2.6.0/share/hadoop/common/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]

SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for anexplanation.

SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]

2015-08-13 22:12:53,012 WARN [main] util.NativeCodeLoader (NativeCodeLoader.java:<clinit>(62))- Unable to load native-hadoop library for your platform... using builtin-javaclasses where applicable

2015-08-13 22:12:57,780 INFO [Thread-4] hdfs.DFSClient(DFSOutputStream.java:createBlockOutputStream(1471)) - Exception increateBlockOutputStream

java.io.IOException: Bad connect ack with firstBadLink as10.25.100.132:50010

                                                                                      atorg.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.createBlockOutputStream(DFSOutputStream.java:1460)

                                                                                      atorg.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.nextBlockOutputStream(DFSOutputStream.java:1361)

                                                                                      atorg.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:588)

2015-08-13 22:12:57,785 INFO [Thread-4] hdfs.DFSClient(DFSOutputStream.java:nextBlockOutputStream(1364)) - AbandoningBP-611125423-10.25.100.130-1439079666020:blk_1073741846_1022

2015-08-13 22:12:57,801 INFO [Thread-4] hdfs.DFSClient (DFSOutputStream.java:nextBlockOutputStream(1368))- Excluding datanode 10.25.100.132:50010

[root@node04 ~]#

 突然发现,成功了,先别高兴的太早,让我们先看看hadoop上有没有创建上传一个文本文档testfile.txt


经过查找,恭喜你,成功了!

!。


【推广】 免费学中医,健康全家人
原文地址:https://www.cnblogs.com/llguanli/p/8404522.html