天天看点

移植opendaylight到powerpc平台

今天介绍一下将ODL移植到powerpc平台上遇到的一些问题。

1、启动karaf时提示找不到hostname,无法进行tcp连接。

可以通过hostname命令进行设置,例如hostname localhost

2、启动过程中出现异常,提示文件句柄不足。

一个进程打开文件句柄数目是有限制(也可以设置成无限),不同操作系统是不同的。我们可以通过ulimit进行设置,例如:ulimit -n 65535

3、启动过程出现异常,提示找不到类名(最恶心的问题),百度+谷歌都不好使。

[email protected]>Uncaught error from thread [opendaylight-cluster-data-
akka.persistence.dispatchers.default-plugin-dispatcher-18] shutting down JVM since 'akka.jvm-exit-on
-fatal-error' is enabled for ActorSystem[opendaylight-cluster-data]
java.lang.NoClassDefFoundError: org/iq80/leveldb/DBFactory
        at akka.persistence.journal.leveldb.LeveldbJournal.<init>(LeveldbJournal.scala:22)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at java.lang.Class.newInstance(Class.java:442)
        at akka.util.Reflect$.instantiate(Reflect.scala:44)
        at akka.actor.NoArgsReflectConstructor.produce(IndirectActorProducer.scala:105)
        at akka.actor.Props.newActor(Props.scala:213)
        at akka.actor.ActorCell.newActor(ActorCell.scala:562)
        at akka.actor.ActorCell.create(ActorCell.scala:588)
        at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:461)
        at akka.actor.ActorCell.systemInvoke(ActorCell.scala:483)
        at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:282)
        at akka.dispatch.Mailbox.run(Mailbox.scala:223)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassNotFoundException: org.iq80.leveldb.DBFactory
        at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501)
        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)
        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412)
        at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 18 more
#
#
           

【定位过程-第一阶段】

定位过程1:提示找不到类,那么就看一下类是否存在,经过确认类文件是存在且路径也是对的,类文件在leveldbjni-all-1.8-odl.jar包中。

定位过程2:查看leveldbjni-all-1.8-odl.jar中META-INF/MANIFEST.MF文件,其中有一段内容如下(整理格式后):

Bundle-NativeCode:
META-INF/native/windows32/leveldbjni.dll;osname=Win32;processor=x86,
META-INF/native/windows64/leveldbjni.dll;osname=Win32;processor=x86-64,
META-INF/native/osx/libleveldbjni.jnilib;osname=macosx;processor=x86,
META-INF/native/osx/libleveldbjni.jnilib;osname=macosx;processor=x86-64,
META-INF/native/linux32/libleveldbjni.so;osname=Linux;processor=x86,
META-INF/native/linux64/libleveldbjni.so;osname=Linux;processor=x86-64,
META-INF/native/sunos64/amd64/libleveldbjni.so;osname=SunOS;processor=x86-64,
META-INF/native/sunos64/sparcv9/libleveldbjni.so;osname=SunOS;processor=sparcv9
           

因为我们是linux系统(红色字段),然而我们是powerpc平台并非x86平台。基本可以确定so动态库以及processor这个地方是有问题的,那么就先解决这个问题。

【解决问题-第一阶段】

解决1:libleveldbjni.so必须是powerpc平台上,需要下载如下三个软件:

软件名称 下载方式 备注
snappy wget http://snappy.googlecode.com/files/snappy-1.0.5.tar.gz
leveldb git clone git://github.com/chirino/leveldb.git 非谷歌官方仓库地址
leveldbjni git clone git://github.com/fusesource/leveldbjni.git

具体编译方式可参考leveldbjni中readme.md文件,提醒一下必须是交叉编译啊!!将编译好的libleveldbjni.so替换到jar包中。

解决2:processor应该设置成什么呢?

通过走查代码,发现processor的获取是通过System.getProperty("os.arch"),在我们的环境中os.arch返回的是ppc64。因此我们对MANIFEST.MF文件修改,将对应的processor修改成ppc64。

【验证-第一阶段】

 替换so以及MANIFEST.MF文件之后,再次启动karaf,仍然报相同错误,没有任何进展。

【定位过程-第二阶段】

定位过程1:为了验证替换文件之后的jar是否正确,下载原生的karaf,并且手动安装这个jar包,发现bundle的状态一直都是Installed(正常应该Active状态)。说明jar包还是有问题。

定位过程2:针对这种问题,我们只能调试,调试方法有:日志、debug调试。对于一个不太了解软件,debug调试是最佳方式。针对这个问题,我们应该将断点设置在什么地方呢?由于我们是通过bundle:install -s bundle名称,那么好我们就设置在命令行入口的地方。

【解决问题-第二阶段】

通过上面debug过程中,最终发现命令行在安装bundle的时候,匹配arch名字是powerpc,而非是ppc64。因此我们可以得出我们需要将processor设置成powerpc。(这部分代码进行了适配,把ppc64是配成powerpc)

【验证-第二阶段】

通过上面将processor设置powerpc,将jar包放到原生的karaf中,发现安装这个bundle之后,状态是active。非常的兴奋!!!然后把该jar包放到odl中,启动karaf,不幸的事情发生了,还是报错且错误一样。简直是在做过山车一般,倍儿爽!!

【定位过程-第三阶段】

既然原生的karaf能运行起来,证明这样配置问题不大且so库应该也是正常的。那么就只能调试debug调试odl。

定位过程1:我们在调试odl的时候一般都是系统启动ok,调试我们业务逻辑,但是针对这种启动过程中抛出了异常,我们应该如何调试呢?我们面临的是必须在抛异常之前就把断点断住,我们应该怎么做呢?原来jvm提供了一个参数suspend,我们需要将这个参数设置.即可。这个参数含义是进程启动之后只分配基本资源,不执行任何业务逻辑,当客户端连上jvm之后,才开始执行业务逻辑。说白点大白话,就设置这个参数之后进行先挂起。

定位过程2:bundle:install  [bundle名称] 与 bundle:install -s [bundle名称] 区别是s表示start,安装并激活。通过分步调试,只调试install过程,发现install过程没有问题,processor校验过程对os.arch进行了适配,适配成powerpc。

 【解决问题-第三阶段】

解决方法1:修改start过程对processor校验。

解决方法2:修改配置MANIFEST.MF文件,增加对processor是ppc64。

【验证-第三阶段】

META-INF/native/linux64/libleveldbjni.so;osname=Linux;processor=ppc64,
META-INF/native/linux64/libleveldbjni.so;osname=Linux;processor=powerpc,
           

采用解决方法2,验证通过,karaf可以在powerpc平台正常启动。

【特别说明】

1、在解决过程还需要编一个libjansi.so,在jline-2.12.jar,因此需要单独再编译一下libjansi.so

2、我们的odl代码其实包含了两套osgi框架Apache Felix和Equinox(原生karaf只有Felix),由于存在两个osgi框架,才导致上面对于processor的处理出现不一致。       

继续阅读