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!\n", 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\n", 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\n", $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


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


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值