`
saiyaren
  • 浏览: 225693 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

hiphop 1.0 开发问题总结 原创-胡志广

阅读更多
我从去年搞hiphop总结的一些问题,其中有些是过程中的问题,有的是已经解决的问题,没有多做整理和总结,但是希望对大家有帮助:
 

1.  Hiphop安装

Hiphop 需要在centos 6.2以上支持可以,并且通过yum安装支持包比较好;

然后 cmake时,需要单独创建一个文件夹(如build),不要跟之前的文件混淆,否则编译好的内容会出现错误。

 

2.  动态加载

AllDynamic 在编译php 时,添加该属性就可以对动态内容进行加载,如require中用变量,默认是关闭的

-v “AllDynamic=true”

 

3.  守护进程日志不输出内容解决方法

Hiphop如果守护进程,进行日志配置,之前不输出内容,是由于使用了相对路径,hiphop在守护进程时,需要使用绝对路径才可以进行日志输出,如:

File =/export/hphp_project/xxxx.xxx.com_hphp_update_20120803/info.log

 

    #access log settings

   AccessLogDefaultFormat = %h %l %u %t \"%r\" %>s %b

   Access {

     * {

       File =/export/hphp_project/xxx.xxx.com_hphp_update_20120803/access.log

       Format = %h %l %u %t \"%r\" %>s %b

     }

 

}

 

File这里配置的都是绝对路径即可

 

4.  Hiphop 添加静态扩展

首先进入src/idl目录创建一个[extension name].idl.php文件

如:

hello.idl.php

:> hello.idl.php

src/idl目录中创建

然后再执行schema.php ,生成idl模板,如:

/export/server/php/bin/php schema.php hello>hello.idl.php

生成好后,我们编写idl文件模板,可以参照里面的内容写方法和类,如:

DefineFunction(

 array(

   'name'   =>"hello_world",

   'desc'   => "helloworld",

    'return' => array(

     'type'   => Int64,

     'desc'   => "11,out helloworld!",

   ),

  ));

编辑好hello.idl.php后,我们先备份一下

Src/system/ext.incsrc/runtime/ext/ext.h2个文件,因为在下面执行make后,这2个文件会被清空;

然后我们返回到src目录下,执行:

EXT=[existingextension name] make -C idl update命令,如:

EXT=hello make-C idl update

然后会生成ext_hello.cpp ext_hello.h hello.inc idl目录

src/runtime/ext/profile/目录下生成extprofile_hello.h

src/system目录下生成hello.inc文件

然后我们把ext_hello.cpp ext_hello.h2个文件拷贝到src/runtime/ext目录下,然后我们为ext_hello.cpp里面添加实现,如我们修改ext_hello.cpp内容:

int64f_hello_world() {

 

    printf("hello world");

    return 11;

}

然后保存,编译好后,该方法会返回11 ,可进行测试。

然后我们把刚才备份的src/system/ext.incsrc/runtime/ext/ext.h拷贝回来覆盖现有的这2个文件,然后我们编辑src/system/ext.inc文件,在下面增加上一行:

#include "hello.inc"

我们需要增加扩展的inc文件,保存;

然后我们再修改src/runtime/ext/ext.h文件,添加上一行:

#include<runtime/ext/profile/extprofile_hello.h>

添加上我们扩展的extprofile的头文件

修改完这2个文件后,我们返回到主目录,创建一个build1目录,进入到build1目录中执行 cmake ../

然后cmake 完毕后执行make 安装完hiphop后我们在编译php文件会发现我们新加扩展的方法可以用了

 

 

5.  Mongodb c++ client安装

下载mongodb-linux-x86_64-2.2.0-client.tgz,然后解压后后执行:

Scons

Scons需要预先安装

执行完scons后,打开build,下面有一个libmongoclient.a文件,这个文件cp $CMAKE_PREFIX_PATHlib

然后

cp -rmongo-cxx-driver-v2.2/src/mongo $CMAKE_PREFIX_PATH

 

如果执行g++编译:

g++ test_mongodb.cpp -I/export/dev/usr/include/ /export/dev/usr/lib/libmongoclient.a/usr/lib64/libboost_thread-mt.so /usr/lib64/libboost_filesystem.so/usr/lib64/libboost_program_options.so -o test_mongodb

 

 

 

6.  hiphop 类实现

CMakeFiles/program.dir/cpp/001.cpp.o: Infunction `HPHP::pm_php$test_php(bool, HPHP::LVariableTable*,HPHP::Globals*)':\n001.cpp:(.text+0xbf): undefined reference to`HPHP::coo_Mongo()'\n001.cpp:(.text+0xc7): undefined reference to`HPHP::c_Mongo::create()'\ncollect2: ld \xb7\xb5\xbb\xd8 1\nmake[2]: ***[program] \xb4\xed\xce\xf3 1\nmake[1]: *** [CMakeFiles/program.dir/all]\xb4\xed\xce\xf3 2\nmake: *** [all] \xb4\xed\xce\xf3 2\n

compiling and linking CPP files took0'50" (50022 ms) wall time

 

当编译php时报了如上错误,说明没有coo_Mongoc_Mongo::create() 的实现

 

2个是在src/system/gen/sys目录下的dynamic_table_class.cpp中实现的,然后在dynamic_table_class.cpp中还有一些类的函数等注册信息,具体内容如下:

 

//这里是注册扩展类声明的位置coo_[扩展类名],如Mongo

ObjectData *coo_Mongo() {

 return NEWOBJ(c_Mongo)();

}

//实现类注册

IMPLEMENT_CLASS(Mongo)

//接口表数组,必须

//第一参数是hash

//第二个参数是flag 0,1

//第三个参数是名字

//第四个参数是回调函数

//参照InstanceOfInfo 结构

extern const InstanceOfInfocw_Mongo$$instanceof_table[] = {

 {0x414077AFA9BA239FLL,1,"Mongo",&cw_Mongo},

};

//这个也是必要的,内容所有的都一致,只是名字为扩展名称,如cw_[扩展名称]

const int cw_Mongo$$instanceof_index[] = {

  1,

 -1,0,

};

//调用信息

//第一参数调用方法

//第二个参数是调用最少参数

//第三个参数是调用参数总数

//第四个参数引用flags(不太清楚)

//参数参照CallInfo结构

//名字构成ci_扩展类名$$方法名称,ci_Mongo$$__destruct,方法名称从生成的ext_扩展.h中的如果是普通方法把名字直接粘贴过来ci_Mongo$$函数名,如果是

extern const CallInfo ci_Mongo$$__destruct= { (void*)&c_Mongo::i___destruct, (void*)&c_Mongo::ifa___destruct, 0,4, 0x0000000000000000LL};

extern const CallInfo ci_Mongo$$__construct= { (void*)&c_Mongo::i___construct, (void*)&c_Mongo::ifa___construct,2, 4, 0x0000000000000000LL};

extern const CallInfo ci_Mongo$$___get = {(void*)&c_Mongo::i___get, (void*)&c_Mongo::ifa___get, 1, 4,0x0000000000000000LL};

 

//这里也是声明函数信息,所有内容几乎一致

//方法定义

Variant c_扩展类名称::i___函数名称(MethodCallPackage&mcp, CArrRef params) {

 return invoke_meth_few_handler(mcp, params, &ifa___函数名称);

}

Variant c_Mongo::i___construct(MethodCallPackage&mcp, CArrRef params) {

 return invoke_meth_few_handler(mcp, params, &ifa___construct);

}

Variantc_Mongo::i___destruct(MethodCallPackage &mcp, CArrRef params) {

 return invoke_meth_few_handler(mcp, params, &ifa___destruct);

}

Variant c_Mongo::i___get(MethodCallPackage&mcp, CArrRef params) {

 return invoke_meth_few_handler(mcp, params, &ifa___get);

}

 

Variantc_Mongo::ifa___construct(MethodCallPackage &mcp, int count,INVOKE_FEW_ARGS_IMPL_ARGS) {

  if(UNLIKELY(mcp.obj == 0)) {

   return ObjectData::ifa_dummy(mcp, count, INVOKE_FEW_ARGS_PASS_ARGS,ifa___construct, coo_Mongo);

  }

 c_Mongo *self ATTRIBUTE_UNUSED (static_cast<c_Mongo*>(mcp.obj));

 //if (UNLIKELY(count<1 || count > 2)) return throw_toomany_arguments("__construct",1,2, 1);

 CVarRef arg0(a0);

 //if (count <= 1) return (self->t___construct(arg0));

 CVarRef arg1(a1);

 return (self->t___construct(arg0,arg1),null);

}

Variantc_Mongo::ifa___destruct(MethodCallPackage &mcp, int count, INVOKE_FEW_ARGS_IMPL_ARGS){

  if(UNLIKELY(mcp.obj == 0)) {

   return ObjectData::ifa_dummy(mcp, count, INVOKE_FEW_ARGS_PASS_ARGS,ifa___destruct, coo_Mongo);

  }

 c_Mongo *self ATTRIBUTE_UNUSED (static_cast<c_Mongo*>(mcp.obj));

  if(UNLIKELY(count > 0)) return throw_toomany_arguments("__destruct",0, 1);

 return (self->t___destruct());

}

 

Variantc_Mongo::ifa___get(MethodCallPackage &mcp, int count,INVOKE_FEW_ARGS_IMPL_ARGS) {

  if(UNLIKELY(mcp.obj == 0)) {

   return ObjectData::ifa_dummy(mcp, count, INVOKE_FEW_ARGS_PASS_ARGS,ifa___get, coo_Mongo);

  }

 c_Mongo *self ATTRIBUTE_UNUSED (static_cast<c_Mongo*>(mcp.obj));

 //if (UNLIKELY(count != 1 )) returnthrow_toomany_arguments("___get", 1,1, 1);

 CVarRef arg0(a0);

 return (self->t___get(arg0));

}

 

extern const MethodCallInfoTablecw_Mongo$$call_info_table[] = {};

 // {0x0D31D0AC229C615FLL, 0, 11, "__construct",&ci_Mongo$$__construct },

 // {0x7F974836AACC1EF3LL, 1, 10, "__destruct", &ci_Mongo$$__destruct},

//};

//extern const intcw_Mongo$$call_info_index[] = {

// 3,

// -1,-1,-1,0,

//};

 

extern const intcw_Mongo$$call_info_index[] = {

  };

 

 

c_Mongo *c_Mongo::create(String a0,Varianta1) {

 CountableHelper h(this);

 init();

 t___construct(a0,a1);

 clearNoDestruct();

 return this;

}

extern const MethodCallInfoTablecw_Mongo$$call_info_table[];

extern const intcw_Mongo$$call_info_index[];

extern const InstanceOfInfocw_Mongo$$instanceof_table[];

extern const intcw_Mongo$$instanceof_index[];

const ObjectStaticCallbacks cw_Mongo = {

 (ObjectData*(*)(ObjectData*))coo_Mongo,

 cw_Mongo$$call_info_table,cw_Mongo$$call_info_index,

 cw_Mongo$$instanceof_table,cw_Mongo$$instanceof_index,

 &c_Mongo::s_class_name,

 0,&ci_Mongo$$__construct,0,0,0x0,

 &c_Mongo::s_cls

};

 

 

7.  Hiphop编译错误:

make[5]: *** write jobserver: Bad filedescriptor.  Stop.\nmake[5]: *** Waitingfor unfinished jobs....\nmake[5]: *** write jobserver: Bad filedescriptor.  Stop.\nmake[4]: *** [CMakeFiles/program.dir/all]Error 2\nmake[3]: *** [all] Error 2\n

hphp failed

 

在扩展中添加mongo的连接在类函数中就会出现上面的问题,但是第二次编译后就没问题了

DBClientConnection c;

 

 

8.  Hiphop编译错误

/export/dev/hiphop-php/src/system/gen/sys/dynamic_table_class.cpp:1309:error: prototype for 'HPHP::c_MongoCursor* HPHP::c_MongoCursor::create(HPHP::Variant,HPHP::String, HPHP::Array, HPHP::Array)' does not match any in class'HPHP::c_MongoCursor'

/export/dev/hiphop-php/src/runtime/ext/ext_mongo.h:55:error: candidate is: HPHP::c_MongoCursor*HPHP::c_MongoCursor::create(HPHP::Object, HPHP::String, HPHP::Array,HPHP::Array)

make[2]: ***[src/CMakeFiles/hphp_runtime_static.dir/system/gen/sys/dynamic_table_class.cpp.o]Error 1

make[1]: ***[src/CMakeFiles/hphp_runtime_static.dir/all] Error 2

make: *** [all] Error 2

当报这个错误时,是由于我们的dynamic_table_class.cpp文件的1309行的

c_MongoCursor::create…的类型错误了,所以参照

HPHP::c_MongoCursor*HPHP::c_MongoCursor::create(HPHP::Object, HPHP::String, HPHP::Array,HPHP::Array)提示把类型改过来就可以了

 

9.  Hiphop编译错误

../../../bin/libhphp_runtime.a(dynamic_table_class.cpp.o):(.rodata+0x1360):undefined reference to`HPHP::c_MongoCursor::i_rewind(HPHP::MethodCallPackage&, HPHP::Arrayconst&)'

collect2: ld returned 1 exit status

make[2]: *** [src/hphp/hphp] Error 1

make[1]: ***[src/hphp/CMakeFiles/hphp.dir/all] Error 2

make[1]: *** Waiting for unfinishedjobs....

../../../bin/libhphp_runtime.a(dynamic_table_class.cpp.o):(.rodata+0x1360):undefined reference to`HPHP::c_MongoCursor::i_rewind(HPHP::MethodCallPackage&, HPHP::Arrayconst&)'

collect2: ld returned 1 exit status

当报这个错误时,提示没有引用i_rewind,说明我们未对i_rewind进行定义

我们只需要添加:

Variantc_MongoCursor::i_rewind(MethodCallPackage &mcp, CArrRef params) {

 return invoke_meth_few_handler(mcp, params,&ifa_rewind);

 }

声明一下,就可以了

 

10.        Hiphop编译错误

HipHop Warning:  Missing argument 1 for key() in test1.php online 6

当报这个错误时,是因为调用key()函数的方式出现了问题,如:

$a=new Mongo();

$a.key();

这样就会报上面的错误,因为php调用函数是用->
所以把$a.key()改为$a->key()就没有问题了

 

11.        Hiphop创建对象指针

c_VectorIterator* it =NEWOBJ(c_VectorIterator)();

it->test();

 

 

12.        hiphop编译错误

当编译php使用hiphop时,报了如下错误:

Core dumped: Segmentation fault

这可能是由于类调用方法不存在引发的段错误,如:

$a=new Mongo();

$a->key();

但是Mongo中没有key,那么就会出现上面的错误,段错误发生很多,这只是其中一种情况

 

13.        Hiphop编译错误

error: 'c_Closure' was not declared in thisscope

当编译hiphop时,报了如上错误,是由于没有把c_Closure类的头文件引入进来,引入后就没问题了

 

14.        Hiphop call_info_tablecall_info_index

当使用hiphop 编译php时报出如下错误:

HipHop Fatal error: Unknown methodMongoCursor::rewind in test1.php on line 2

 

这里提示找不到方法rewind,是由于在dynamic_table_class.cpp这个类中定义MongoCursorrewind中没有对call_info_tablecall_info_index进行定义,这2个表都需要定义,否则会找不到函数;

call_info_index这个矩阵是有一定的规律的和call_info_table的数量是有关系的,和名字无关,所以当call_info_table数量相同时,所产生的call_info_index是一样的,现在找不到好的方法生成dynamic_table_class.cpp,所以可以借助一个php,在php中实现好类和函数,然后通过hiphop编译,然后在hiphop编译好的文件中找到cpp目录下的001.cpp(这里一个文件是由于在编译时定义cluster-count=1),然后找到相应的call_info_tablecall_info_index拷贝到dynamic_table_class.cpp文件即可。

 

如:

extern const MethodCallInfoTablecw_myIterator___call_info_table[] = {

  {0x7F974836AACC1EF3LL, 1, 10, "__destruct",&ci_myIterator_____destruct },

  {0x6413CB5154808C44LL, 1, 5, "valid", &ci_myIterator___valid },

  {0x337E695DE87C57C7LL, 1, 8, "key", &ci_myIterator___key },

  {0x3C6D50F3BB8102B8LL, 1, 4, "next", &ci_myIterator___next },

  {0x1670096FDE27AF6ALL, 1, 6, "rewind", &ci_myIterator___rewind },

  {0x5B3A4A72846B21DCLL, 1, 7, "current", &ci_myIterator___current},

  {0x0D31D0AC229C615FLL, 1, 11, "__construct",&ci_myIterator_____construct },

};

 

//这个和call_info_table的数量是有关系的

extern const intcw_myIterator___call_info_index[] = {

  15,

 -1,-1,-1,0,1,-1,-1,2,

 3,-1,4,-1,5,-1,-1,6,

 

};

 

所以call_info_tablecall_info_index是必要的

 

 

15.        Hiphop支持Iterator

extern const InstanceOfInfocw_MongoCursor$$instanceof_table[] = {

 {0x414077AFA9BA239FLL,1,"MongoCursor",&cw_MongoCursor},

{0x66679538C5E6F0A1LL,1,"Traversable",(constObjectStaticCallbacks*)2},

 {0x0636A5F84AF9D29ELL,1,"Iterator",(constObjectStaticCallbacks*)2}

  };

 

如果想让类支持Iterator,那么就在dynamic_table_class.cpp类中找到instanceof_table,然后加上{0x0636A5F84AF9D29ELL,1,"Iterator",(constObjectStaticCallbacks*)2}这句话就可以了

 

 

16.        Hiphop类返回类,调用方法

如果在hiphop中需要返回一个类,并且调用它的方法,那么被返回类的方法一定要在call_info_tablecall_info_index2个数据中出现否则会报:

HipHop Fatal error: Unknown methodMongoCursor::rewind in test1.php on line 2

call_info_tablecall_info_index是在dynamic_table_class.cpp类中添加

 

17.        hiphop编译好的php目录结构

这个是编译好hiphop的目录结构

cls  CMakeCache.txt CMakeFiles cmake_install.cmake CMakeLists.txt  cpp  Makefile php  program  sep_extensions.mk  sys

 

 

cls中是当前编译的类的头文件

cpp是编译好的实现内容

 

18.        hiphop编译错误

/export/hphp_project/test/php/test.cpp: Infunction 'HPHP::Variant HPHP::pm_php$test_php(bool, HPHP::LVariableTable*,HPHP::Globals*)':\n/export/hphp_project/test/php/test.cpp:21: error: 'classHPHP::GlobalVariables' has no member named'run_pm_php$test_php'\n/export/hphp_project/test/php/test.cpp:25: error: 'classHPHP::GlobalVariables' has no member named 'gvm_obj'\nmake[2]: ***[CMakeFiles/program.dir/php/test.cpp.o] Error 1\nmake[1]: ***[CMakeFiles/program.dir/all] Error 2\nmake: *** [all] Error 2\n

 

当报如上错误时,一般是编译文件出现冲突了,所以清理一遍编译目录,重新编译即可

 

 

19.        Hiphop实现Iterator

ext_mongo.h中:

#include <runtime/base/base_includes.h>

 

namespace HPHP {

///////////////////////////////////////////////////////////////////////////////

 

 

///////////////////////////////////////////////////////////////////////////////

// class MongoCursor

 

FORWARD_DECLARE_CLASS_BUILTIN(MongoCursor);

class c_MongoCursor : public ExtObjectData{

 public:

 DECLARE_CLASS(MongoCursor, MongoCursor, ObjectData)

 

  //这个是Iterator的游标

 int64 m_position;

  //这个是保存内容的集合

 Array m_array;

 

  //need to implement

 public: c_MongoCursor(const ObjectStaticCallbacks *cb =&cw_MongoCursor);

 public: ~c_MongoCursor();

 public: void t___construct(CObjRef connection, CStrRef ns, CArrRef query= null_array, CArrRef fields = null_array);

 DECLARE_METHOD_INVOKE_HELPERS(__construct);

 public: Variant t_current();

 DECLARE_METHOD_INVOKE_HELPERS(current);

 public: int64 t_key();

 DECLARE_METHOD_INVOKE_HELPERS(key);

 public: void t_next();

 DECLARE_METHOD_INVOKE_HELPERS(next);

 public: void t_rewind();

 DECLARE_METHOD_INVOKE_HELPERS(rewind);

 public: bool t_valid();

 DECLARE_METHOD_INVOKE_HELPERS(valid);

 public: Variant t___destruct();

 DECLARE_METHOD_INVOKE_HELPERS(__destruct);

 

  //implemented by HPHP

 public: c_MongoCursor *create(Object connection, String ns, Array query= null_array, Array fields = null_array);

 

};

}

 

ext_mongo.cpp中:

#include <runtime/ext/ext_mongo.h>

#include<runtime/ext/ext_continuation.h>

#include <iostream>

 

using namespace std;

 

namespace HPHP {

///////////////////////////////////////////////////////////////////////////////

c_MongoCursor:: c_MongoCursor(constObjectStaticCallbacks *cb):ExtObjectData(cb){

         cout<<"start"<<endl;     

         //在构造函数中初始化游标

         m_position= 0LL;

   m_array.append(new Variant("1"));

   m_array.append(new Variant("2"));

   m_array.append(new Variant("3"));

 

}

 c_MongoCursor:: ~c_MongoCursor(){

         cout<<"end"<<endl;

}

 void c_MongoCursor::t___construct(CObjRef connection, CStrRef ns,CArrRef query, CArrRef fields){

         //(php)构造函数中初始化游标

         m_position= 0LL;

   //m_array.append(new Variant("1"));

   //m_array.append(new Variant("2"));

   //m_array.append(new Variant("3"));

         cout<<"construct"<<endl;

         }

Variant c_MongoCursor::t_current(){

         cout<<"current"<<endl;

         //m_array.rvalAt(m_position, AccessFlags::Error);返回当前位置的array

         returnm_array.rvalAt(m_position, AccessFlags::Error);

}

int64 c_MongoCursor::t_key(){

         cout<<"key"<<endl;

         //返回当前位置

         returnm_position;

}

void c_MongoCursor::t_next(){

         cout<<"next"<<endl;

         //对游标进行累加

         ++m_position;

}

//初始化

void c_MongoCursor::t_rewind(){

   INSTANCE_METHOD_INJECTION_BUILTIN(MongoCursor,MongoCursor::rewind);

   m_position = 0LL;

         cout<<"rewind"<<endl;  

}

//判断是否是最后一个对象

bool c_MongoCursor:: t_valid(){

         cout<<"valid"<<endl;

         returnisset(m_array, m_position);

}

 Variant c_MongoCursor::t___destruct(){

                   cout<<"destruct"<<endl;

         returnnull;

}

}

 

定义idl:

DefineFunction(

 array(

   'name'   => 'current',

   'return' => array(

     'type'   => Variant,

   ),

  ));

 

DefineFunction(

 array(

   'name'   => 'key',

   'return' => array(

     'type'   => Int64,

   ),

  ));

 

DefineFunction(

 array(

   'name'   => 'next',

   'return' => array(

     'type'   => null,

   ),

  ));

 

DefineFunction(

 array(

   'name'   => 'rewind',

    'return' => array(

     'type'   => null,

   ),

  ));

 

DefineFunction(

 array(

   'name'   => 'valid',

   'return' => array(

     'type'   => Boolean,

   ),

  ));

 

20.        Hiphop编译失败

../../../bin/libhphp_runtime.a(ext_mongo.cpp.o):In function `HPHP::c_Mongo::c_Mongo(HPHP::ObjectStaticCallbacks const*)':

ext_mongo.cpp:(.text+0x2f): undefinedreference to `vtable for HPHP::c_Mongo'

../../../bin/libhphp_runtime.a(ext_mongo.cpp.o):In function `HPHP::c_MongoDB::c_MongoDB(HPHP::ObjectStaticCallbacks const*)':

ext_mongo.cpp:(.text+0xbf): undefinedreference to `vtable for HPHP::c_MongoDB'

collect2: ld returned 1 exit status

make[2]: *** [src/hphp/hphp] Error 1

make[1]: ***[src/hphp/CMakeFiles/hphp.dir/all] Error 2

make[1]: *** Waiting for unfinished jobs....

 

21.        hiphop编译php失败

CMakeFiles/program.dir/php/test1.cpp.o: Infunction `HPHP::pm_php$test1_php(bool, HPHP::LVariableTable*,HPHP::Globals*)':\ntest1.cpp:(.text+0x0): multiple definition of`HPHP::pm_php$test1_php(bool, HPHP::LVariableTable*, HPHP::Globals*)'\nCMakeFiles/program.dir/cpp/001.cpp.o:001.cpp:(.text+0x0):first defined here\ncollect2: ld \xb7\xb5\xbb\xd8 1\nmake[2]: *** [program]\xb4\xed\xce\xf3 1\nmake[1]: *** [CMakeFiles/program.dir/all] \xb4\xed\xce\xf32\nmake: *** [all] \xb4\xed\xce\xf3 2\n

compiling and linking CPP files took1'05" (65239 ms) wall time

 

如果报这个错误,那么把输出编译内容清空一下重新编译即可

 

 

22.        Hiphop编译错误

HipHop Fatal error: syntax error,unexpected T_OBJECT_OPERATOR in test_mongo.php on line 4

这个是因为php中定义的对象没有$

:

test=new Mongo();

正确的应该是:

$test=new Mongo();

 

23.        通过php用函数模板生成dynamic_table_class.cpp内容

首先在php中定义好类和方法

然后通过HPHP_HOME/build/src/hphp/hphp 编译该php,编译好后,去编译后的目录的cpp文件夹下找到001.cpp(注意我们这里只编译一个phpcluster-count=1,这样主要为了方便查询)

然后我们打开001.cpp

从这里开始:

//cw_扩展名称___instanceof

extern const InstanceOfInfocw_Mongo___instanceof_table[] = {

 {0x656B62D3A5CF04D9LL,1,"Mongo",&cw_Mongo},

 };

…………………

中间内容省略

const ObjectStaticCallbacks cw_Mongo = {

 (ObjectData*(*)(ObjectData*))coo_Mongo,

 cw_Mongo___call_info_table,cw_Mongo___call_info_index,

 cw_Mongo___instanceof_table,cw_Mongo___instanceof_index,

 &c_Mongo::s_class_name,

 0,&ci_Mongo_____construct,0,0,0x0,

 &c_Mongo::s_cls

 };

到这里结束拷贝到dynamic_table_class.cpp这个文件中,然后在上面加上:

ObjectData *coo_Mongo () {

 return NEWOBJ(c_Mongo)();

}

IMPLEMENT_CLASS(Mongo)

这些内容即可,这2块拼接好后就是我们需要的class内容了,这里的mongo是扩展的名称,根据定义不同,可进行更改。

注:

dynamic_table_class.cpp通过hphp生成的变量名称cicw打头的和原生的有些区别,但是不影响,原生的dynamic_table_class.cpp生成的 cicw连接是用$$hphp生成的是用____

如:

这个是hphp 生成的:

extern constInstanceOfInfo cw_Mongo___instanceof_table[] = {

 {0x656B62D3A5CF04D9LL,1,"Mongo",&cw_Mongo},

 };

这个是原生的:
extern const InstanceOfInfo cw_Mongo$$instanceof_table[] = {

 {0x656B62D3A5CF04D9LL,1,"Mongo",&cw_Mongo},

 };

 

24.        Array 的头文件是Type_array.h

Array a=Array::Create();

  Variant a1=Variant("1");

  a.add(Variant("a1"),Variant("aa"));

  a.add(Variant("a1"),Variant("ab"));

  a.add(Variant("a1"),Variant("ac"));

  for (ArrayIter iter(a); iter; ++iter) {

        Variant vKey = iter.second();

        cout<<vKey.toString().data()<<endl;

 }

 

  Array b=Array::Create();

  b.set(Variant("b1"),Variant("ba"));

  b.set(Variant("b1"),Variant("bb"));

  b.set(Variant("b1"),Variant("bc"));

  for (ArrayIter iter(b); iter; ++iter) {

        Variant vKey = iter.second();

        cout<<vKey.toString().data()<<endl;

 }

 

  Array c=Array::Create();

  String key("name");

  c.add(key,Variant("name1"));

  key=String("value");

  c.add(key,Variant(1));

  key=String("tag");

  c.add(key,Variant(0));

 

//  c.add(String("name"),Variant("name1"));

//  c.add(String("value"),Variant(1));

//  c.add(String("tag"),Variant(0));

  for (ArrayIter iter(c); iter; ++iter) {

          Variant vKey = iter.second();

          cout<<vKey.toString().data()<<endl;

  }

 

其中,addsetkey都需要用hhvm的类型,具体参考type_array.h;

addset的区别,addkey不保证唯一性,可以添加多条记录,set保证key唯一性,如果后面的再set同样key则覆盖keyvalue;

上面程序输出结果:

[huzg@BP-28-2-206192 hphp2]$ /export/dev_hphp2.0/hiphop-php_hzg/hphp/hhvm/hhvm test_hphp2.php

aa

ab

ac

bc

name1

1

0

3个是add值:

aa

ab

ac

这是set值:

 

bc

25.        Varint 的头文件Type_varint.h

26.        遍历hiphopvarint集合

for (ArrayIter iter(options); iter; ++iter){

        Variant vKey = iter.second();

       cout<<vKey.toString()<<endl;

 }

 

27.        CStrRef转换为char*

调用data方法

a.      data();

 

28.        hiphop新增扩展collection

#include<runtime/ext/profile/extprofile_collection.h>

 

 

29.        Hiphop重新编译后,对Iterator扩展需要重新编译

当更新新版本的hiphop后,之前的iterator  key 就无法应用,那么我们需要将之前编译好的php模板重新用hiphop新版的编译好,然后把内容复制到dynamic_table_class.cpp中,为什么要重新编译,因为instanceof_tablecall_info_tablehash值变了,这个值需要和变量表中的一致,所以更新后需要重新编译复制过来,就不会出现问题了。

extern const InstanceOfInfocw_MongoCursor$$instanceof_table[] = {

  {0x54E82965,1,"MongoCursor",&cw_MongoCursor},

 {0x45E6F0A1,1,"Traversable",(const ObjectStaticCallbacks*)2},

 {0x4AF9D29E,1,"Iterator",(const ObjectStaticCallbacks*)2},

 

};

 

extern const MethodCallInfoTablecw_MongoCursor$$call_info_table[] = {

  {0x54808C44, 1, 5, "valid", &ci_MongoCursor$$valid },

  {0x5373F906, 1, 5, "limit", &ci_MongoCursor$$limit },

  {0x5E27AF6A, 0, 6, "rewind", &ci_MongoCursor$$rewind },

  {0x0E1DBB2A, 1, 4, "sort", &ci_MongoCursor$$sort },

  {0x024E8C51, 1, 3, "key", &ci_MongoCursor$$key },

  {0x2ACC1EF3, 1, 10, "__destruct", &ci_MongoCursor$$__destruct },

  {0x594564B4, 1, 4, "skip", &ci_MongoCursor$$skip },

  {0x3B8102B8, 1, 4, "next", &ci_MongoCursor$$next },

  {0x046B21DC, 1, 7, "current", &ci_MongoCursor$$current },

  {0x229C615F, 1, 11, "__construct", &ci_MongoCursor$$__construct },

};

 

30.        Htmlspecialchars不支持gb2312

GB2312 is not implemented yet

 

解决方法:

1)修改$HPHP_HOME/src/runtime/base/server/transport.cpp文件

将 void Transport::prepareHeaders(boolcompressed, const void *data, int size)函数中的627行的:

   string contentType = "text/html;charset="

                         +RuntimeOption::DefaultCharsetName;

改为

     stringcontentType = "text/html" ;

(2)修改$HPHP_HOME/src/runtime/base/string_util.cpp

将String StringUtil::HtmlEncode(CStrRefinput, QuoteStyle quoteStyle,

                              const char*charset, bool nbsp)函数中的333行的:

if(strcasecmp(charset, "ISO-8859-1") == 0) {

      utf8 = false;

   } else if (strcasecmp(charset,"UTF-8")) {

      throw NotImplementedException(charset);

   }      

中的throwNotImplementedException(charset);注释掉,就不会抛HipHopFatal error: GB2312 is not implemented yet异常了。

31.        hiphop编译php失败

CMakeFiles/program.dir/sys/literal_strings_0.no.cpp.o:In function `HPHP::init_literal_varstrings()':\nliteral_strings_0.no.cpp:(.text+0x0):multiple definition of`HPHP::init_literal_varstrings()'\nCMakeFiles/program.dir/sys/literal_strings_1.no.cpp.o:literal_strings_1.no.cpp:(.text+0x0):first defined here\ncollect2: ld \xb7\xb5\xbb\xd8 1\nmake[2]: *** [program]\xb4\xed\xce\xf3 1\nmake[1]: *** [CMakeFiles/program.dir/all] \xb4\xed\xce\xf32\nmake: *** [all] \xb4\xed\xce\xf3 2\n

compiling and linking CPP files took0'58" (58735 ms) wall time

hphp failed

hiphop编译php失败报如上错误时,是由于编译的指定目录出现了冲突,所以把编译的指定目录清空后,重新编译就没有问题了。

编译路径如:

/export/dev/hiphop-php/build/src/hphp/hphptest_redis.php -k 1 --log=3 --cluster-count=1 -o /export/hphp_project/test

 

–o 后面的路径

 

32.        新版本的dynamic_table_class.cpphash值变小了

如果更新版本后,注意每次添加新扩展时,需要对HASH值进行重新编译,因为旧的值在新版本中可能造成越界的警告:

如:

/export/dev/hiphop-php/src/system/gen/sys/dynamic_table_class.cpp:171:warning: overflow in implicit constant conversion

这里提示的是171行越界了,因为新版本的hash值变短了,所以之前旧的长所以造成了越界,

 

这是旧的hash

extern const InstanceOfInfocw_MongoDB___instanceof_table[] = {

 {0x5999BDEDF7C49E1FLL,1,"MongoDB",&cw_MongoDB},

};

这是新的hash值:

extern const InstanceOfInfocw_Mongo___instanceof_table[] = {

 {0x5BD7C876,1,"Mongo",&cw_Mongo},

};

旧的(0x5999BDEDF7C49E1FLL)要比新的(0x5BD7C876)长,所以这里我们重新生成一遍,把就的hash值改了即可

需要改的变量为instanceof_tablecall_info_table两个,改后就不会出现如上警告了

 

 

33.        Hiphop类重复定义冲突错误

make[2]: *** No rule to make target`cls/Fake$0.h', needed by `CMakeFiles/program.dir/cpp/001.cpp.o'.  Stop.\nmake[1]: ***[CMakeFiles/program.dir/all] Error 2\nmake: *** [all] Error 2\n

如果报了如Fake$0.h这样的错误,是由于在PHP文件中重复定义了类造成的,将一个删除即可。

 

 

34.        Hiphop  debug

cmake -DCMAKE_BUILD_TYPE=Debug .
make

 

 

35.        编译的php不存在

hphp:/export/dev/hiphop-php/src/util/job_queue.h:321:HPHP::JobQueueDispatcher<TJob, TWorker>::JobQueueDispatcher(int, bool,int, int, bool, void*, bool) [with TJob = OutputJob*, TWorker = OutputWorker]:Assertion `threadCount >= 1' failed

当执行

/export/dev/hiphop-php/build/src/hphp/hphpRedis1.php -k 1 --log=3 --cluster-count=1 -o /export/hphp_project/test

语句时报了如上错误,是由于Redis1.php不存在,改为正确的php路径的名字即可

 

 

36.        Hiphop c++可以使用析构函数

hiphop的类中继承Sweepable类就可以使用析构函数了,如:

ext_redis.h中添加上Sweepable继承,

class c_Redis : public ExtObjectData,publicSweepable {

 public:

……………………………………..

 

继承Sweepable了他后,就可以用~c_redis这个函数了

 

 

37.        Php rawurlencode~不转换为%7E,hiphoprawurlencode~转换为%7E解决方法

src/runtime/base/zend/zend_url.cpp中的这个方法url_raw_encode是进行编码的

char *url_raw_encode(const char *s, int&len) {

 register int x, y;

 unsigned char *str;

 

  str= (unsigned char *)malloc(3 * len + 1);

  for(x = 0, y = 0; len--; x++, y++) {

   str[y] = (unsigned char) s[x];

   if ((str[y] < '0' && str[y] != '-' && str[y] != '.')||

     (str[y] < 'A' && str[y] > '9') ||

       (str[y] > 'Z' && str[y] < 'a' && str[y] != '_') ||

     (str[y] > 'z')) {

     str[y++] = '%';

     str[y++] = hexchars[(unsigned char) s[x] >> 4];

     str[y] = hexchars[(unsigned char) s[x] & 15];

    }

  }

 str[y] = '\0';

  len= y;

 return ((char *)str);

}

 

这里的str[y]是接受到的特殊字符是否进行编码,我们只需要在if最外层判断&&str[y]!=’~’即可,修改如下:

if (((str[y] < '0' && str[y] !='-' && str[y] != '.') ||

     (str[y] < 'A' && str[y] > '9') ||

       (str[y] > 'Z' && str[y] < 'a' && str[y] != '_') ||

     (str[y] > 'z'))&&str[y]!=’~’)

 

 

38.        添加hiphop动态链接库

CMake/HPHPFind.cmake

添加:

   target_link_libraries(${target} /export/dev_hphp/usr/lib/libhiredis.so)

   target_link_libraries(${target}/export/dev_hphp/usr/lib/libmongoclient.a)

   target_link_libraries(${target} /usr/lib64/libboost_thread-mt.so)

   target_link_libraries(${target} /usr/lib64/libboost_filesystem.so)

target_link_libraries(${target}/usr/lib64/libboost_program_options.so)

后面的就是动态链接库的地址

 

 

39.        Hiphop编译错误

../../../bin/libhphp_runtime.a(dynamic_table_class.cpp.o):In function `HPHP::c_MongoCursor::create(HPHP::Object, HPHP::String,HPHP::Array, HPHP::Array)':

dynamic_table_class.cpp:(.text+0x22455):undefined reference to `HPHP::c_MongoCursor::t___construct(HPHP::Objectconst&, HPHP::String const&, HPHP::Array const&, HPHP::Arrayconst&

 

报这个问题,如果存在t___construc但是编译找不到,那么清空编译目录重新编译

 

40.        Hiphop编译错误

runningexecutable /export/dev_hphp/hiphop-php_hzg/src/hhvm/hhvm-vRepo.Authoritative=true -vRepo.Commit=false -vRepo.Local.Mode=r--vRepo.Local.Path=/export/hphp_project/test//hhvm.hhbc --file test_mongo.php...

sh:/export/dev_hphp/hiphop-php_hzg/src/hhvm/hhvm: 没有那个文件或目录

如果报上述错误,那么在HPHP_HOME下执行

Cmake .

Make –j 16生成HHVM即可

 

41.        Hiphop编译php错误

当报如下错误时:

runningexecutable /export/dev/hiphop-php/src/hhvm/hhvm -vRepo.Authoritative=true-vRepo.Commit=false -vRepo.Local.Mode=r--vRepo.Local.Path=/export/hphp_project/test/hhvm.hhbc --file test_mongo.php...

sh:/export/dev/hiphop-php/src/hhvm/hhvm: No such file or directory

command failed:"/export/dev/hiphop-php/src/hhvm/hhvm -vRepo.Authoritative=true-vRepo.Commit=false -vRepo.Local.Mode=r--vRepo.Local.Path=/export/hphp_project/test/hhvm.hhbc --filetest_mongo.php"

all files savedin /export/hphp_project/test ...

running hphptook 0'00" (291 ms) wall time

 

这个是由于设置了USE_HHVM=1

这里把USE_HHVM=1环境变量清空,cmakemake 编译即可

 

 

42.        Hiphop添加析构函数

src\compiler\statement\Class_Statement.cpp文件下outputCPPImpl是生成头文件的代码

我们这个添加析构就是给类继承Sweepable,并且在c++的析构中调用t___destruct()即可;

我们在class_Statement.cpp文件的379行添加上:

public Sweepable

也就是如下代码:

cg_printf(" : public ObjectData,publicSweepable");

 

然后我们在592行下添加如下代码:

//add hiphop __destruct functoin

       std::set <string> ::iteratordestruct_fun=done.find("__destruct ");

       //__destrcut exists

       if(destruct_fun!=done.end()){

                cg_printf("public:~c_%s(){t___destruct();}\n",clsName);

       }

上面的代码就是当类中有__destruct函数时,那么我们则在类里面添加

~c_类名(){t___destruct();}

添加c++析构函数,并调用php的析构即可;

done中保存了所有的类的声明的函数

 

 

 

43.        hiphop undefinedreference to `HPHP::c_MongoDate::os_prop_table'错误

hiphop报如下错误时:

undefined reference to`HPHP::c_MongoDate::os_prop_table'

由于该类用了属性,但是未引用

dymanic_table_class.cpp最后加入:

const ClassPropTablec_MongoDate::os_prop_table = {

 7,1,-1,-1,-1,-1,9,0,

 cpt_hash_entries+0,0,cpt_table_entries+0,cpt_static_inits

};

这个就可以了

 

 

44.        Hiphop报段错误

hphp:/export/dev/hiphop-php/src/compiler/analysis/type.cpp:82: static HPHP::TypePtrHPHP::Type::GetType(HPHP::Type::KindOf, const std::string&): Assertion`kindOf' failed.

Core dumped: Aborted

hphp failed

当编译php时报了如上错误,可能是由于system/xxx.inc内容和扩展的内容不匹配所造成的,所以检查新增的扩展和inc文件内容是否匹配

 

 

45.        Hiphop最新版本支持包

Hiphop标准的gcc版本和boost

Gcc :4.6.1

Boost:1.50

2个是facebook正在使用的,而且编译不会出现问题

 

 

46.        Hiphop 支持namespace

修改/export/dev/hiphop-php/src/compiler/code_generator.cpp

364行的FormatLabel方法:

std::string CodeGenerator:: FormatLabel(const std::string &name) {

 //cout<<name<<"---------------------------------"<<endl;

 string ret;

 ret.reserve(name.size());

  for(size_t i = 0; i < name.size(); i++) {

   unsigned char ch = name[i];

   if ((ch >= 'a' && ch <= 'z') ||

       (ch >= 'A' && ch <= 'Z') ||

       (ch >= '0' && ch <= '9') || ch == '_') {

     ret += ch;

    }else {

     char buf[10];

     if(ch=='\\'){

       snprintf(buf, sizeof(buf), "%02X",(int)ch);

     }else{

     snprintf(buf, sizeof(buf), "%s%02X",Option::LabelEscape.c_str(),

               (int)ch);

     }

     ret += buf;

    }

  }

 return ret;

}

Option::LabelEscape.c_str()$

FormatLabel方法是把所有不包含在a-z,A-Z,0-9_外的所有内容前加上$并把后面的字符通过%02X转换为16进制的ASCII

我这里修改为:

if(ch=='\\'){

       snprintf(buf, sizeof(buf), "%02X",(int)ch);

     }else{

     snprintf(buf, sizeof(buf), "%s%02X", Option::LabelEscape.c_str(),

               (int)ch);

     }

 

当不在数字、字母、下划线外的,如果字符为\\(右斜杠),那么不在其前面增加$只对其进行转义为5C\\对应的ascii码是92

除此之外,还有在cpp中会添加上:

FORWARD_DECLARE_CLASS(类名)

所以这里也需要转义,否则找不到类:

生成FORWARD_DECLARE_CLASS的有3个地方:

(1)Src/compiler/code_generator.cpp中的

outputForwardDeclaration方法

是进行FORWARD_DECLARE_CLASS赋值的

 

(2) compiler/analysis/function_scope.cpp

outputCPPPreface该函数2184FORWARD_DECLARE_CLASS

 

 

3compiler/analysis/variable_table.cpp
outputCPPGlobalVariablesHeader函数的866FORWARD_DECLARE_CLASS

 

在生成代码后sys/ global_variables.cpp这个cpp文件中会生成FORWARD_DECLARE_CLASS代码

我们修改

compiler/analysis/variable_table.cpp的代码:

866行代码:

    cg_printf("FORWARD_DECLARE_CLASS(%s);\n",

                varType->getName().c_str());

修改为:

       string cls_name_new=CodeGenerator::FormatLabel(varType->getName());

       cg_printf("FORWARD_DECLARE_CLASS(%s);\n",

                  cls_name_new.c_str());

首先进行一次格式化操作

 

 

47.        Hiphop环境变量错误编译失败

hiphop编译php时,编译失败,报如下错误:

compiling andlinking CPP files...
/export/hphp_project/test/cpp/001.cpp: In function \xe2\x80\x98HPHP::VariantHPHP::pm_php$test_diff1_php(bool, HPHP::LVariableTable*,HPHP::Globals*)\xe2\x80\x99:\n/export/hphp_project/test/cpp/001.cpp:25: error:\xe2\x80\x98x_onlysee\xe2\x80\x99 was not declared in thisscope\n/export/hphp_project/test/cpp/001.cpp:28: error: expected initializerbefore \xe2\x80\x98&\xe2\x80\x99token\n/export/hphp_project/test/cpp/001.cpp:29: error:\xe2\x80\x98tmp0\xe2\x80\x99 was not declared in this scope\nmake[2]: ***[CMakeFiles/program.dir/cpp/001.cpp.o] Error 1\nmake[1]: ***[CMakeFiles/program.dir/all] Error 2\nmake: *** [all] Error 2\n

 

这是由于环境变量错误造成的,所以重新设定的HPHP_HOMEHPHP_LIB即可

 

48.        Hiphop 多核编译

bin/run.sh中的make 后面加入-j 16 ,16cpu数量

if [ -n "$HPHP_VERBOSE" ]; then

 make -j 16 $MAKEOPTS > /dev/tty || exit $?

else

 make -j 16 $MAKEOPTS || exit $?

Fi

 

 

49.        Hiphop 20121224版编译错误解决

当编译时抛出了如下错误:

/export/dev_hhvm/hiphop-php_hzg/src/util/asm-x64.h:360:20:error: uninitialized const 'HPHP::VM::Transl::reg::rip' [-fpermissive]

解决方法:

$HPHP/CMake/HPHPSetup.cmake 118行,添加-fpermissive在编译即可下面标红位置

set(CMAKE_CXX_FLAGS "-fno-gcse-fno-omit-frame-pointer -ftemplate-depth-60 -Wall -Woverloaded-virtual-Wno-deprecated -Wno-strict-aliasing -Wno-write-strings -W    no-invalid-offsetof -fno-operator-names-Wno-error=array-bounds -Wno-error=switch -std=gnu++0x -Werror=format-security -fpermissive"

 

 

50.        hphp 生成扩展(静态编译)

首先创建src/idl/xxx.idl.php,mongo.idl.php

然后返回到src 目录下,执行:

EXT=mongo make –C idl install|update

注:

如果按照原生写的makeFile会覆盖掉,system/ext.inc runtime/ext/ext.h文件的内容,所以我将src/idl/MakeFile的内容覆盖system/ext.incruntime/ext/ext.h的内容注释掉;

内容为:

21行的:

../system/ext.inc:idl_list.php $(IDL_PHPS)

 20    @echo 'Generating $@'

 21    #$(V)$(PHP) idl_list.php inc $@

 22    $(V)touch ../compiler/builtin_symbols.cpp

 

35行的:

33 ../runtime/ext/ext.h: idl_list.php$(IDL_PHPS)

 34    @echo 'Generating $@'

 35    #$(V)$(PHP) idl_list.php ext $@

 

然后生成好后,在system/ext.inc 中加入新添加好的xxx.inc ,如mongo.inc;

:

#include "mongo.inc"

然后runtime/ext/ext.h中添加:

#include<runtime/ext/profile/extprofile_mongo.h>

 

添加好后,然后去$HPHP/build目录下进行编译;

由于在ext.inc 中添加了mongo.inc,所以mongo.inc的内容即为系统的内容;

builtin_symbols.h 中即可把类,函数等信息初始化前加载在静态变量中,如:

 static const char *ExtensionFunctions[];

 static const char *ExtensionClasses[];

  static const char *ExtensionConsts[];

 static const char *ExtensionDeclaredDynamic[];

 static const char *SystemClasses[];

 static const char *HelperFunctions[];

 

编译好后,然后在system 目录下执行:

$HPHP --opts=none -t cpp -f sys -o ./gen t--input-dir . -i `find classes globals -name '*.php'`

 

即可将system/gen下的所有内容进行替换,如dymanic_table_class.cpp中的内容就会有mongo.inc中的类、变量等内容

 

然后在去$HPHP/build中进行make –j 16 编译,即可将扩展编译进去,这样扩展就编译成功和 hphp  成功耦合;

 

注意:

在生成好了system/gen下内容后,需要对ext_xxx.h对应的ext_xxx.cp中的内容进行实现,否则dymanic_table中是找不到实现的方法的,所以会报undefined reference 这样的错误

 

 

51.        Hiphop20121224版本编译扩展undefinedreference to 错误解决方法

./../../bin/libext_hhvm.a(ext_mongo.ext_hhvm.cpp.o):In function `HPHP::fg_test_hello(HPHP::VM::ActRec*)':

ext_mongo.ext_hhvm.cpp:(.text+0x1a):undefined reference to `HPHP::f_test_hello()'

../../../bin/libext_hhvm.a(ext_mongo.ext_hhvm.cpp.o):In function `HPHP::new_Mongo_Instance(HPHP::VM::Class*)':

ext_mongo.ext_hhvm.cpp:(.text+0x153):undefined reference to `HPHP::c_Mongo::c_Mongo(HPHP::ObjectStaticCallbacksconst*)'

../../../bin/libext_hhvm.a(ext_mongo.ext_hhvm.cpp.o):In function `HPHP::tg_5Mongo___construct(HPHP::VM::ActRec*)':

ext_mongo.ext_hhvm.cpp:(.text+0x211):undefined reference to `HPHP::c_Mongo::t___construct(HPHP::String const&,HPHP::Variant const&)'

../../../bin/libext_hhvm.a(ext_mongo.ext_hhvm.cpp.o):In function `HPHP::tg_5Mongo___get(HPHP::VM::ActRec*)':

ext_mongo.ext_hhvm.cpp:(.text+0x5ff):undefined reference to `HPHP::c_Mongo::t___get(HPHP::Variant)'

../../../bin/libext_hhvm.a(ext_mongo.ext_hhvm.cpp.o):In function `HPHP::tg_5Mongo___destruct(HPHP::VM::ActRec*)':

ext_mongo.ext_hhvm.cpp:(.text+0x770):undefined reference to `HPHP::c_Mongo::t___destruct()'

../../../bin/libext_hhvm.a(ext_mongo.ext_hhvm.cpp.o):In function `HPHP::tg1_5Mongo___construct(HPHP::TypedValue*, HPHP::VM::ActRec*,long long, HPHP::ObjectData*)':

ext_mongo.ext_hhvm.cpp:(.text.unlikely+0xfd):undefined reference to `HPHP::c_Mongo::t___construct(HPHP::String const&,HPHP::Variant const&)'

../../../bin/libext_hhvm.a(ext_hhvm_infotabs.cpp.o):(.rodata+0x91b8):undefined reference to `HPHP::f_test_hello()'

collect2: ld returned 1 exit status

 

生成ext 扩展后,会在runtime/ext目录下生成如:

ext_mongo.h ext_mongo.cpp2个文件,然后在ext_mongo.cpp中添加上实现;

 

然后我们在build目录下执行make –j 16 编译;编译完毕后,我们执行bin/generated_files.sh all

命令后,然后我们生成了hhvm hhvm_infotabs的内容;

但是编译后出现了为引用的信息,未引用的内容是ext_mongo.cpp的方法,由于在hiphop中是在dymanic_table中引用了这些内容,如果不对dymanic_table的内容进程生成,那么只有实现,没有引用就会产生这样的错误;

所以正常流程为:

(1)    先定义idl;

(2)    定义好idl后,去src 目录下执行EXT=mongo make –C idl install|update

(3)    src/system/mongo.inc添加到ext.inc中进行引用;

(4)    src/runtime/ext/extprofile_mongo.h 添加到ext.h中进行引用

(5)    build目录下执行make –j 16,添加好ext.inc后,mongo的内容就为系统的内容了,类、函数、变量、常量等均会捕获到

(6)    执行完毕后,在去执行bin/generated_files.sh all,生成hhvm.cpp,更新hhvm_infotabs.cpp

(7)    然后再去build目录重新build,这样扩展就加入到hhvm中了

 

 

52.        扩展模板生成类无构造函数错误解决方法

当通过idl生成扩展时报了如下错误;

PHP Fatal error:  Uncaught exception 'Exception' with message'No constructor defined for class s_class' in/export/dev_hhvm/hiphop-php_hzg/src/idl/base.php:243

Stack trace:

#0 /export/dev_hhvm/hiphop-php_hzg/src/idl/test.idl.php(88):EndClass()

#1/export/dev_hhvm/hiphop-php_hzg/src/idl/idl.php(31):require('/export/dev_hhv...')

#2 {main}

 thrown in /export/dev_hhvm/hiphop-php_hzg/src/idl/base.php on line 243

这是由于没有添加构造函数造成的问题;

DefineFunction(

 array(

   "name"   =>"__construct",

   "flags"  =>HasDocComment,

   "return" => array(

     "type"   => null,

   ),

  ));

加上这个就可以了

53.        生成扩展段错误,模板flags没加问题

idl.php

对于所有的class,function.defineProperty,defineConstant的声明flags是必须的,如果不加flags,那么编译好后,会抛出段错误,在compiler/builtin_symbols.cpp:189行,所以需要注意这一点,也就是最后在189行后的cname会是空指针

 

54.        undefined reference 错误解决方法

../../../bin/libext_hhvm.a(ext_hhvm_infotabs.cpp.o):(.rodata+0x11e70):undefined reference to `HPHP::fg_test_hello(HPHP::VM::ActRec*)'

这个问题需要清空build ,重新编译

 

 

55.        Idl模板实现接口

'ifaces' => array('Iterable','Countable'),

 

IsFinal用法,类定义(idl/collection.idl.php)

BeginClass(

 array(

   'name'   =>"VectorIterator",

   'ifaces' => array('Iterator'),

   'desc'   => "An iteratorimplementation for iterating over a Vector.",

   'flags'  =>  IsFinal | HasDocComment,

  ));

 

 

 

 

RefVariableArguments用法(idl/file.idl.php)

DefineFunction(

 array(

   'name'   => "fscanf",

   'desc'   => “”,

   'flags'  =>  HasDocComment | RefVariableArguments,

    …….

  ));

 

FunctionIsFoldable | NoEffect | NoInjection用法(idl/variable.idl.php)

DefineFunction(

 array(

   'name'   =>"is_bool",

   'desc'   => "Finds whetherthe given variable is a boolean.",

   'flags'  =>  HasDocComment | FunctionIsFoldable | NoEffect| NoInjection,

   …..

  ));

 

MixedVariableArguments | ContextSensitive用法(idl/function.idl.php)

DefineFunction(

 array(

   'name'   =>"call_user_func_async",

   'desc'   => ".",

   'flags'  =>  HasDocComment | HipHopSpecific |MixedVariableArguments | ContextSensitive,

….

}

 

AllowIntercept用法(idl/apc.idl.php):

DefineFunction(

 array(

   'name'   =>"apc_add",

   'desc'   => ".",

'flags'  => HasDocComment | AllowIntercept,

…………….

}

 

HipHopSpecific| VariableArguments | HasOptFunction | NoProfile 用法(idl/fb.idl.php)

DefineFunction(

  array(

    'name'  => "fb_call_user_func_safe",

    'desc'  => "",

    'flags' =>  HasDocComment |HipHopSpecific | VariableArguments | HasOptFunction | NoProfile |ContextSensitive,

    'opt'   => "hphp_opt_fb_call_user_func",

  …..

  ));

 

NoDefaultSweep用法(idl/domdocument.idl.php)

BeginClass(

  array(

    'name'  => "DOMDocument",

    'parent' => "DOMNode",

    'bases' => array('Sweepable'),

    'desc'  => "",

    'flags' =>  HasDocComment |NoDefaultSweep,

}

 

NeedsActRec用法(idl/error.idl.php):

DefineFunction(

  array(

    'name'  => "debug_backtrace",

    'desc'  => "debug_backtrace() generates a PHP backtrace.",

    'flags' =>  HasDocComment |NeedsActRec,

 ……..

    'taint_observer' => false,

  ));

 

56.        idl Flags 配置

functionflags:

HasDocComment

HasOptFunction      

MixedVariableArguments

RefVariableArguments

VariableArguments

NoEffect

FunctionIsFoldable

ContextSensitive

NeedsActRec

Classflags:

Class method:

IsAbstract

IsProtected

IsPrivate

IsStatic

Class properties:

IsProtected

IsPrivate

IsStatic

 

57.        Hiphop char 转换为Variant乱码

Char * a=malloc(sizeof(char));

的值为”aaaddd”

a转为hiphop variant

Variant(a)

但是这样转换后,有时候会产生乱码,所以我们需要先将char 指针等内容先转换为c++

String ,然后将string 的值转换为Variant这样就不会产生乱码了

如:

Char a[3]=”abc”;

String b=a;

Varaint c=Varaint(b);

 

58.        Hiphop ext扩展错误提示和异常

cpp扩展代码中写入:

raise_warning(“warning content”);

 

raise_error(“error content!”);

 

59.        设置编码

Server {
DefaultCharsetName = GBK
}

 

 

60.        Hiphop soap

Hiphop soap基本功能可支持,但是不支持no-wsdl模式,但是一般的情况下,一般都是使用wsdl模式;

SOAPFault php hiphop 抛出异常模式些许差异;但是都可以提示错误;

 

61.        执行generated_files.sh hhvm报错

当执行bin下的generated_files.sh hhvm报如下错误时

No object file to generate xxx.hhvm.cpp from,did you build first?

是因为新的扩展的.o文件不存在,所以需要重新编译可以找到该文件即可

这个内容是在generated_files.sh文件中这里实现的:

# $1 - Binary to pull symbols from

# $2 - .ext_hhvm.cpp file to build

make_hhvm()

{

 echo "$1===$2"

  [ !-f "$1" ] && check_err 1 "No object file to generate $2from, did you build first?"

  [$VERBOSE -eq 1 ] && echo "Generating $2"

 $HHVM gen_ext_hhvm.php $2 . /dev/null /dev/null "" $1

 check_err $? "Failed generating $2"

}

 

62.        Hiphop 扩展的函数名必须是小写

执行generated_files.sh hhvm

报了如下错误,因为function的名字有大写(这是有问题的)需要完善

Extension function name must be alllowercase: Ice_initialize

ext_hhvm generation failed

ERROR # 1 : Failed generating../ext/ext_ice.ext_hhvm.cpp

 

报这个错误的是:

是这个src/runtime/ext_hhvm/gen_lib.php文件中252

if ($this->name != strtolower($this->name)){

     echo "Extension function name must be all " .

         "lowercase: " . $this->name . "\n";

     echo "ext_hhvm generation failed\n";

    exit(1);

 

生成扩展时生成的函数名称也都变为了小写是在src/idl/base.php中进行转换的

不知道为何将方法的名称都转为了小写

 

经测试,idl中的函数的命名可以为小写,因为在编译好的hhvm中,对于方法的名称不区分大小写,最终都是识别到小写

 

63.        Hiphop Idl 设置默认值

在设置idl 的参数时,最多可以有2个不设置默认值;

如果你有4个参数,你都不设置默认值,那么第三个、第四个就会报如下错误:

default argument missing for parameter 4

所以最好设置idl时,给函数的参数都设置默认值

 

64.        HPHP::String 转换成std::String

HPHP::Stringhiphop 自定义的一个String类,它不能之间强转为std::String

需要通过将HPHP::String转换成char* 然后转换为std::String

例:

Varint a;//是一个hphp:string类型

Std::string b=a.toString().data();

这样既可

 

65.        CObjRef转成指定类型的指针

bool f_memcache_set_server_params(CObjRefmemcache, CStrRef host,) {

  //Object对象转换成指定类型

  c_Memcache *memcache_obj =memcache.getTyped<c_Memcache>();

 return memcache_obj->t_setserverparams(host, port, timeout,retry_interval,

                                        status, failure_callback);

}

 

66.        实例化hiphop 已有的hiphop类对象,并调用构造函数

如:

Php 中定义了一个类:

Class A {

         Public$a;

         Public$b;

         Publicfunction __construct($a,$b){

                   $this->a=$a;

                   $this->b=$b

         }

}

 

当通过hhvm转换后,这个A的类会生成一个hiphop的类为:c_A

 

Hiphop 实例化A并且通过构造函数对其进行成员变量的封装:

Object f_getObjectClass(CVarRefv) {

Object *obj = new Object();
//string aa = "c_" + v.toString();
HPHP::CStrRef ss = v.toCStrRef();
Array* params=new Array();
 params->append(Variant("aaaaaa"));
 params->append(Variant("bbbbbb"));

/*第一个参数是类的名称如:c_A

  第二个参数是构造函数的参数,这个必须得有带参的构造函数,否则值是设置不进去的,

  而且参数是按顺序进行遍历的;

  第三个参数是对对象进行构造函数初始化

*/
Object aa=create_object(ss,*params,true);
return aa; 
}

 

在头文件中需要引入

#include<runtime/base/externals.h>

这个头文件,create_object函数在这个文件中进行声明的

 

Create_Object实现是在bytecode.cpp文件中1365,这个是hhvm的实现

create_object在builtin_functions.cpp的1012行是对外的create_object接口函数,分支是走hhvm还是走hphp

 

67. 内存泄露问题

$str =time().'.'.rand(10000, 99999) ;
define('LOG_ID', $str ) ;

 

当一个变量调用2个函数进行连接时,然后用define方式定义为常量会造成内存泄露的问题;

将常量设置为全局变量就可以解决这个问题了

 

 

68. 获取对象的成员变量值和通过类名获取类的成员

Object f_icephp_defineproxy (CObjRefclassObj) {

  /*

         通过传入对象获取对象的成员集合

         Vars是以key value 保存的

  */

 Variant vars=f_get_object_vars(classObj);

  /*

         通过类名获取类下的所有成员名称

    classObj->o_getClassName()获取类名的方法返回值为CStrRefType_object.h

 */

 Array varNames=f_get_class_vars(classObj->o_getClassName());

  /*

         遍历类成员的名称

*/

  for(ArrayIter iter(varNames); iter; ++iter) {

                     /*

                            获取成员名称

                   */

         Variant vKey = iter.first();

                   /*

                            根据成员名称获取对象下该成员的值

                   */

         cout<<vKey.toString()<<":"<<vars[vKey].toString()<<endl;;

  }

   return NULL;

}

../runtime/ext/ext_class.h

/* 通过类名获取类下的成员名称的Array集合*/

Array f_get_class_vars(CStrRef class_name);

/*

         通过传入对象获取对象的成员列表

         保存内容为:keyvalue key是成员名称,value是成员值

         Variant是返回的集合

*/

Variant f_get_object_vars(CVarRef object);

 

Ext_class.hhiphop操作类的扩展;

 

Php 代码:

 

<?php

   class A{

       public $a;

       public $b;

       public $c;

       public function __construct($a,$b,$c){

           $this->a=$a;

           $this->b=$b;

           $this->c=$c;

       }

    }

 

   $a=new A("aaa222","bbb333","cccccc");

    $c=newA("aaa111","bbb222","cccccc333");

 

   //echo $a;

   //print_r($a);

   //var_dump($a);

   $b=get_object_vars($a);

   $count=count($b);

   echo $count;

   var_dump($b);

   echo $b["a"];

   echo $b["b"];

   icephp_defineproxy($a);

   icephp_defineproxy($c);

?>

 

后端输出内容如下,已获取到对象值

a:aaa222|

b:bbb333|

c:cccccc|

a:aaa111|

b:bbb222|

c:cccccc333|

 

 

69.        hiphop 抛出异常处理

(1)      简单的抛出异常处理

throw Exception(“Test throw Exception”);

Exception e=new Exception(“Test thorw Exception”);

调用抛出异常的方法后hiphop控制台输出:

HipHop Fatal error: Test thorw Exception

(2)      获取php中声明的异常类,抛出异常信息

Hiphop代码:

Objectf_icephp_defineproxy(CObjRef classname) {

Objectf_icephp_defineproxy(CObjRef classname)

Array*params=new Array();

 params->append(Variant(300));

 params->append(Variant("RpcExceptionerror msg!"));

/*

通过创建动态类根据类名构造一个异常类,但是这里需要注意的是:

一般用户类前会加上c_xxx,但是Exception的用户类没有c_,直接在php

中定义的是什么类名,那么这里在创建对象时也是用什么名称,这里需要

注意,否则会找不到类

*/

Objecte=create_object("com_xx_RpcException",*params,true);

       throwe;

return NULL;

}

 

PHP代码:

class com_xx_RpcExceptionextends Exception

{

        public function__construct($resultCode=0, $msg='')

        {

                $this->resultCode =$resultCode;

                $this->msg = $msg;

        }

 

        public function ice_name()

        {

                return 'com::xx::RpcException';

        }

 

        public function __toString()

        {

            return$this->msg."|".$this->resultCode;

        }

 

        public $resultCode;

        public $msg;

}

 

try{

    icephp_defineproxy($a);

   }catch(Exception $e){

        echo $e;

}

 

调用后在页面输出:

RpcException error msg!|300

 

 

70.        Hiphop idl常量定义问题

DefineConstant(

   array(

       'name'  =>"IcePHP__t_int",

       'type'  => Variant,

    )

);

 

这里的Type只支持如下几种类型:

 case Type::KindOfBoolean:

     case Type::KindOfInt64:

     case Type::KindOfDouble:

     case Type::KindOfString:

     case Type::KindOfArray:

     case Type::KindOfVariant:

       cg_printf("(const char *)&%s,\n", varName.c_str());

       break;

这个是在analyze_result.cpp 3341行,他们都会转换成char类型,但是不能是Object类型的,否则在执行generate_files.sh的时候会报错误,而错误的原因就出现在常量问题;

 

 

71.        Hiphop idl中不要用typeid做变量名

typeid做参数名称,在编译的时候会报错误,所以在idl中定义变量名称时不要用typeid做关键字

 

 

72.        Hiphop 通过变量名称获取变量对象

ext_variable.cpp中的f_get_defined_vars函数获取所有的变量,返回一个Array,Array中存放的是key是变量名,value是对象

例子:

 Array   dvs=f_get_defined_vars();

                Varianta=dvs["IcePHP__t_int"];

                Object  b=a.toObject();

                PrimitiveInfo*pi=b.getTyped<PrimitiveInfo>();

               cout<<"IcePHP__t_int:"<<pi->kind<<endl;

 

73.        hiphop 持久化对象

g_persistentObjectshiphop 定义的一个持久化对象的mapmap,是PersistentObjectStore类型,在execution_context.h

set(const char *type, const char *name,ResourceData *obj)

set方法

type是类型

name是第二层key

obj 是继承ResourceData的类

get函数:

ResourceData *get(const char *type, constchar *name);

Type是类型:

Namekey,获取resoucedata的类型

下面是具体的例子:

 

class Ice_Communicator : publicSweepableResourceData{

           public:Ice_Communicator(){

                cp=NULL;

           };

           public:~Ice_Communicator(){};

           public:Ice::CommunicatorPtr cp;

           public:std::set<std::string> factoryWrapperClassSet;

           public:IceObjectFactoryWrapperPtr ifwp;

 

       };

 

 

                pthread_t tid;

                tid = pthread_self();

               //获取tid

                                     Varianttidv=Variant((int64)tid);

                char *tidc=tidv.toString().data();

                Ice_Communicator*ic=dynamic_cast<Ice_Communicator*>(g_persistentObjects->get("ice_c",tidc));

                if(ic==NULL){

                   ic=new Ice_Communicator();

                   g_persistentObjects->set("ice_c",tidc, ic);

                   ic->cp=Ice::initialize();

 

                }

 

74.        Hiphop 性能问题须知

编译hiphop 如果需要debug

那么加上

cmake -DCMAKE_BUILD_TYPE=Debug .

 

但是如果加上debug后,hiphopcpu使用率会高一倍

所以在线上正式使用的时候,需要把debug去掉,这样性能可以提高一倍

cmake .

 

75.        编译好的二进制的hhvmsystemlib.php文件

当执行hhvm找不到systemlib.php文件时,是由于没有配置HPHP_LIB环境变量,

HPHP_LIB指向的是hphpbin目录,systemlib.php文件就在bin目录下

 

 

76.        Php中的unset是销毁对象函数

当在php代码中调用了unset函数会销毁当前对象触发析构函数;

如:

$a=new A();

Unset($a);

这样就触发了A的析构函数,销毁了该对象

$a=new A();

$a=null;

也会销毁对象

 

 

77.        Hiphop 内存泄露总结

当涉及到使用hiphop的扩展类时,需要实例化一个对象指针:

如:

Class Test:public ExtObjectData,publicSweepable{

 

}

 

那么当在代码中进行实例化,需要用hiphop内置的宏NEWOBJ

例:

Test *test=NEWOBJ(TEST)();

这样可以控制内存,如果用自己的new Test()这样实例化,一般delete需要考虑很多因素,但是用NEWOBJ时,需要在扩展类后面继承上Sweepable类才可以回收调用析构函数,这样就匹配了,不会造成内存泄露;

NEWOBJ用法:

NEWOBJ(扩展类类名)(参数)

 

当在hiphop 自己的创建的类,那么就需要用new delete 进行匹配,否则会造成内存泄露;

 

在使用map时,如果是把值放入到对象中,那么mapsecond是存的值,这时的地址不是你的对象地址,如:

Test *test=new Test();

Std::map<std::string,Test> map;

Map[“1”]=*test;

注意,这里的map[1]存的valuetest对象,而不是test这个对象的地址,当封装到map中后,map会给他分配一块独立的地址,所以再取时释放的也是map的地址,如果想用map存放上对象,并在后面释放,那么最好存对象指针

 

getTyped涉及内存泄露:

当使用getTyped进行类型转换时,getTyped中的类需要继承Sweapable,否则转换的对象不会被回收

p_cict = iceclassobj.getTyped<c_IcePHP_class>();

 

ArrayVaraint如果用new 来实例化,那么需要对其进行delete回收对象,所以一般建议去创建值,如果非要用指针,那么就要注意回收:

Array array=Array::Create();//创建Array对象

Variant v=Variant();//创建Variant对象

 

 

78.        编码问题到底hhvm 运行报unknown Exception

 

部署hiphop 的时候首先打印一下语言:

echo $LANG

 

输出为:

zh_CN.UTF-8

 

这个是正确的,如果编码为

Zh-CN.gbk

这个横线应该是下划线,否则hiphop访问时会报unknown exception错误,这个很难发现,一定要注意

 

 

79.        共享内存对象

Hiphop中的APC使用共享内存对象实现的,所以xcache也采用该模式,在hiphop中的

SharedStore类是共享存储,并且通过newConcurrentTableSharedStore(0)进行实例化的;

SharedStore定义在src\runtime\base\shared\shared_store_base.h

ConcurrentTableSharedStore 定义在src\runtime\base\shared\concurrent_shared_store.h

ConcurrentTableSharedStore(id)构造函数中是id 一般来说一个下标即可;

ConcurrentTableSharedStoreSharedStore的子类

例:

SharedStore m_store = newConcurrentTableSharedStore(0) ;

//存值:

m_store ->store( name, value, ttl, true)
//具体实现: 

/*

virtual bool store(CStrRef key, CVarRefval, int64 ttl,

                     bool overwrite = true

*/

//取值

m_store ->get(name, v);

 

详细可见源码;

 

 

80.        Memcached超时问题解决

安装libmecached需要在1.0.1以上,目前安装的是1.0.5

安装后,然后将包替换到/export/dev_hhvm/usr下包括头文件和so文件

然后重新编译

ldd build/src/hhvm/hhvm |grep memcached查看

libmemcached.so.9 =>/export/dev_hhvm/usr/lib/libmemcached.so.9

如果是9就对了,如果是7那么就是0.49版本的,老版本的不支持超时;

还有一点就是

$m->setOption(Memcached::OPT_RECV_TIMEOUT,1000);

$m->setOption(Memcached::OPT_SEND_TIMEOUT,1000);

$m->setOption(Memcached::OPT_RETRY_TIMEOUT,300);

$m->setOption(Memcached::OPT_CONNECT_TIMEOUT,1);

 

$m->addServer('10.1.2.3', 11211);

 

setOption 设置需要在addServer之前才可以生效,在addServer后不生效

 

81.        添加hhvm runtime option

runtime_option.cpp中定义静态变量,设定初值

  //第一层

  Hdfmysql = config["MySQL"];

  //第二层,MySQLReadOnly是静态变量,ReadOnlymysql下的值

  MySQLReadOnly =mysql["ReadOnly"].getBool();

 

调用时RuntimeOption:: MySQLReadOnly调用就可以获取了

 

Src/runtime/base/runtime_option.cpp

82.        Freetds查找etc配置问题

Hhvm应用freetds时,需要找到他的动态链接库libsybdb.so

libsybdb.so库可以放到任意位置,但是freetdsetc需要在一个已经安装的目录下,而etc也需要是这个目录下安装好的lib下的库才可以,所以有如下2种方式配置:

(1)      配置环境变量

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/freetds0.82/lib  

红色部分是freetds 的动态链接库位置(也就是已经安装的freetds位置)

(2)      设置动态链接库

echo “/usr/local/freetds0.82/lib  ” > /etc/ld.so.conf.d/hhvm.conf

ldconfig

 

这时候查看ldd hhvm|grep libsydbd.so就可以看到相应的路径了;

 

Freetds安装方法:

./configure--prefix=/usr/local/freetds0.82  --enable-msdblib --with-tdsver=5.0

 

 

83.    获取cpu核心数量

Process::GetCPUCount()

Src/util/process.h

 

 

MachineInfo类是机器信息在

Src/runtime/ext/ext_hotprofiler.cpp

 

修改默认的ThreadCount数量:

默认hhvmThreadCount数量为50,在runtime_option.cpp

//修改为默认cpu核数的一倍*2

int RuntimeOption::ServerThreadCount=50;//101 定义变量

int RuntimeOption::ServerThreadCount = Process::GetCPUCount()<<1

….

ServerThreadCount =server["ThreadCount"].getInt32(50);//717intcpucount=Process::GetCPUCount()<<1;

ServerThreadCount =server["ThreadCount"].getInt32(cpucount);//赋值操作

 

84.        HdfgetBool问题

如:

MySQL {

       ReadOnly = false

}

这里ReadOnly = false后面不要加分号,如果加了分号后,那么则会匹配为true

HiphopgetBool的逻辑是不是0,false,no,off就是true

boolHdf::getBool(bool defValue /* = false */) const {

  const char *v = get();

   //如果v是空指针,返回false

  if (v == nullptr) return defValue;

  //一般存在值即为true,因为不可能0false,no,off共存,并且v这里永远为true,              //因为strcmp不配置为非0,

  return *v && strcmp(v, "0")&&

    strcasecmp(v, "false") &&strcasecmp(v, "no") && strcasecmp(v, "off");

}

 

 

 

85.        获取网络传输对象

Transport *transport =g_context->getTransport();

transport->sendString (“test”,200);

第一个是内容,第二个是http_code

g_context是线程内部的上下文对象;

 

 

86.        ___autoload 传入的参数为小写解决方法

Test_static.php:

<?php

function __autoload($name)

{

       echo “className:”.$name."===\n";

       require $name.".php";

       //require "ConsultationConstract.php";

}

 $timeout = ConsultationConstract::$GETCONSULTATION['timeout'];

 echo  $timeout;

 

?>

 

ConsultationConstract.php

<?php

 class ConsultationConstract {

       public static $GETCONSULTATION = array (

                'timeout' => 3600

       );

   }

?>

 

默认的hhvm输出        echo “className:”.$name."===\n";

是小写的consultationconstract

但我们需要的是ConsultationConstract

 

目前解决方式是:

compiler\expression\static_class_name.cppupdateClassName()

 

  m_className= Util::toLower(className);

修改为:

   m_className =className;

 

默认情况下,类名转换为了小写,但是小写后,到了authLoad函数时:

/src/runtime/base/builtin_functions.cpp +1958实现的:

Array params(ArrayInit(1,ArrayInit::vectorInit).set(className).create());

传参数,这里就传入了小写的了,但是实际我们需要的是原始的,可是在hhvmClass ClassInfo类中都没有原始的类名了;

上面的m_className修改后,有几处还是有对m_className进行转小写操作的,我们可以来分析一下;

1)        这里起的是对比作用,所以无影响

类似这种的

Class_constant_expression.cpp204(src\compiler\expression):   hash_string(Util::toLower(m_className).c_str(), m_className.size());

2)        更新m_className

resolveStatic 函数:

voidStaticClassName::resolveStatic(const string &name) {

…..

  m_className =Util::toLower(name);

}

resolveClass函数:

ClassScopePtrStaticClassName::resolveClass() {

……..

  } else if (m_parent) {

    if (ClassScopePtr self =scope->getContainingClass()) {

      if (!self->getOriginalParent().empty()){

        m_className =Util::toLower(self->getOriginalParent());

   ……..

      }

    }

      ……

}

 

resolveStatic只有1个调用

resolveClass 是在存在基类时进行调用,但是即时更新了,也都是小写状态,对于查找什么的影响不大;

 

所以目前暂时用这种解决,以后有好的方法再进行研究;

 

 

87.        Nginx proxy+rewritehhvm request_uri问题

Php代码:

$uri = $_SERVER['REQUEST_URI'];

echo $uri;

 

php url重写规则(nginx):

rewrite ^([^\.]*)/testuri\.html$ $1/index.php?mod=Testhzg&action=test5last;

 

proxy配置:

proxy_pass      http://hhvms;

proxy_set_header Host $host;

proxy_set_header X-Forwarded-For$remote_addr;

 

正常情况下nginx + rewrite+fastcgi的输出结果:

testuri.html

 

而通过proxyhhvm上的输出结果为:

index.php?mod=Testhzg&action=test5

 

显然phprewrite后的结果,而hhvmrewrite前的结果(就是原始路径)

如果要是想要hhvm+proxy也有这样的效果,那么可以这么搞:

Nginx中不进行rewrite,只进行proxy,然后由hhvm进行rewrite,然后就可以实现hhvmrequest_uri也是rewrite后的结果了;

但是这样唯一的问题可能就是造成日志的问题了;

 

 

88.        Cmakegcc 版本问题解决

当使用cmake ..

-- The C compiler identification is GNU4.4.6

-- The CXX compiler identification is GNU4.4.6

-- The ASM compiler identification is GNU

-- Found assembler: /usr/bin/cc

-- Check for working C compiler:/usr/bin/cc

-- Check for working C compiler:/usr/bin/cc -- works

-- Detecting C compiler ABI info

-- Detecting C compiler ABI info - done

-- Check for working CXX compiler:/usr/bin/c++

-- Check for working CXX compiler:/usr/bin/c++ -- works

-- Detecting CXX compiler ABI info

-- Detecting CXX compiler ABI info - done

-- CMAKE_PREFIX_PATH was missing,proceeding anyway

-- Performing Test HAVE_GCC_46

-- Performing Test HAVE_GCC_46 – Failed

报了如上内容,是gcc版本低,这里提供了一条语句/usr/bin/cc

也就是这里判断版本是通过cc判断的,我安装了gcc 4.6.3然后在bin的目录下cp gcc cc

然后配置环境变量:

exportPATH=/export/files/gcc-4.6.3/bin:$PATH

就可以识别了,gcc-4.6.3/bin需要在前面,覆盖旧path中的cc路径

 

 

89.        Hiphop libevent打补丁失败解决

git clonegit://github.com/libevent/libevent.git

cd libevent

git checkoutrelease-1.4.14b-stable

checkout有些问题,需要这么改:

git checkout –b 1.4.14b release-1.4.14b-stable

git checkout –b <branch> <tag>

 

cat../hiphop-php/hphp/third_party/libevent-1.4.14.fb-changes.diff | patch -p1

 

如果这样打包后还是有错误,打补丁失败,请查看服务器是否可以连接外网,我之前的问题是服务器不可以连接外网造成的

 

然后在可以上外网的机器上打好补丁copy过去,就可以直接编译用了

 

90.        Libevent keepalive内存泄露问题解决

libevent下的http.c中:

位置为2319行下面加入一行:

         req->userdone= 1 ;

即可;

static void

evhttp_handle_request(struct evhttp_request*req, void *arg)

{

         structevhttp *http = arg;

         structevhttp_cb *cb = NULL;

 

         event_debug(("%s:req->uri=%s", __func__, req->uri));

         if(req->uri == NULL) {

                   event_debug(("%s:bad request", __func__));

                   if(req->evcon->state == EVCON_DISCONNECTED) {

                            /*liulei edit     

                                     solvekeepalive memery leak

                                     huzhiguangadd note

                            */

                            req->userdone = 1;

                           

                            evhttp_connection_fail(req->evcon,EVCON_HTTP_EOF);

                   }else {

                            event_debug(("%s:sending error", __func__));

                            evhttp_send_error(req,HTTP_BADREQUEST, "Bad Request");

                   }

                   return;

         }

 

91.        Pcre问题

<?php

$pattern = '/^\/$/u' ;

$case = '' ;

$pathInfo = '/' ;

if(preg_match($pattern.$case,$pathInfo,$matches)){

       echo "1111111111 $matches<br/>" ;

       var_dump($matches) ;

} else {

       echo "2222222222<br/>" ;

}

?>

 

当运行hhvm的时候,报了如下错误:

HipHop Warning: Compilation failed: thisversion of PCRE is compiled without UTF support at offset 0

 

这是由于编译pcre的时候没有添加支持utf-8的选项,在编译的时候加上该选项即可:

./configure --enable-utf

 

92.        直接应用bytecode

设置Authoritativetrue

Repo {

 Authoritative = true

 Central {

     Path = /export/servers/hhvm-1.1/repo/hhvm.hhbc.sq3

    }

}

 

 

93.        Libmemcached版本更新

更新hhvmlibmemcached版本:

默认的wiki版本是0.49

更新1.0.5:

includelib一起cpusr下,然后编译,编译好后,用:

Ldd hhvm|grep libmemcached

/export/dev_hhvm/usr/lib/libmemcached.so.9

.9其实更新每个包下的libmemcached.so这个包到usr/lib下就可以;

 

更新1.0.17

Include还是用1.0.5的,然后把1.0.17libmemcached.so拷贝到/usr/lib下编译即可;

然后:

Ldd hhvm|grep libmemcached

/export/dev_hhvm/usr/lib/libmemcached.so.11

.11就是1.0.17的包了

 

94.   Hhvm 1.0 删除扩展后扔会在ext_hhvm中的ext_hhvm_infotabs中生成解决方法

一般来说生成扩展需要执行以下几步:

sh generated_files.sh gen

sh generated_files.sh hhvm

sh generated_files.sh infotabs

 

当我们之前加过一个扩展,但是之后想删除,那么我删除了ext *.h*.cpp,包括inc等等,但是最终还是会在ext_hhvm_infotabs.cpp中生成这些信息是为什么呢?

因为ext_hhvm_infotabs.cpp中的扩展的类信息等都是从idl/*.idl.php中获取的,那么你不清除该idl文件,那么这个符号表中就永远会生成你的扩展信息;

因为在gen_lib.php中的parseIDLForMethods类似这样的方法等都是去查找的idl文件

那么我们如果要彻底清除一个扩展就需要做到如下几步:

(1)     删除ext下的ext_xxx.hext_xxx.cppext_xxx.ext_hhvm.cpp, ext_xxx.ext_hhvm.h

(2)     删除test下的内容test_ext_xxx.h test_ext_xxx.cpp

(3)     删除runtime/ext/profile下的extprofile_xxx.h

(4)     最后删除src/idl/xxx.idl.php

 

这样就完全删除该扩展了

 

 

 

 

95.   Hhvm使用split 函数coredump问题解决方法

Split函数的测试脚本:

 

<?php

$date = "04/30/1973";

list($month, $day, $year) = split ('[/.-]', $date);

echo "Month: $month; Day: $day; Year: $year<br />\n";

?>

 

当多线程(并发)测试时,出现了coredump问题:

Coredump报的信息:

#0  node_new () at regparse.c:1105

#1  0x00007f54572a18a9 in node_new_cclass () at regparse.c:1130

#2  0x00007f54572a59a5 in parse_char_class (np=0x7f5445ce6b48, tok=0x7f5445ce6bf0, src=0x7f5445ce6c28, end=0x7f544c2f5c29 "", env=0x7f5445ce6e30) at regparse.c:4208

#3  0x00007f54572a6ea5 in parse_exp (np=0x7f5445ce6b48, tok=0x7f5445ce6bf0, term=<value optimized out>, src=0x7f5445ce6c28, end=0x7f544c2f5c29 "", env=0x7f5445ce6e30) at regparse.c:5268

#4  0x00007f54572a8110 in parse_branch (top=0x7f5445ce6ba8, tok=0x7f5445ce6bf0, term=0, src=0x7f5445ce6c28, end=0x7f544c2f5c29 "", env=0x7f5445ce6e30) at regparse.c:5433

#5  0x00007f54572a8234 in parse_subexp (top=0x7f5445ce6f28, tok=0x7f5445ce6bf0, term=0, src=0x7f5445ce6c28, end=0x7f544c2f5c29 "", env=0x7f5445ce6e30) at regparse.c:5470

#6  0x00007f54572a847a in parse_regexp (root=0x7f5445ce6f28, pattern=0x7f544c2f5c24 "[/.-]", end=0x7f544c2f5c29 "", reg=0x7f540c05c5a0, env=0x7f5445ce6e30) at regparse.c:5514

#7  onig_parse_make_tree (root=0x7f5445ce6f28, pattern=0x7f544c2f5c24 "[/.-]", end=0x7f544c2f5c29 "", reg=0x7f540c05c5a0, env=0x7f5445ce6e30) at regparse.c:5541

#8  0x00007f54572af2ab in onig_compile (reg=0x7f540c05c5a0, pattern=0x7f544c2f5c24 "[/.-]", pattern_end=<value optimized out>, einfo=0x0) at regcomp.c:5301

#9  0x00007f54572afbe3 in onig_new (reg=0x7f5445ce7040, pattern=0x7f544c2f5c24 "[/.-]", pattern_end=0x7f544c2f5c29 "", option=0, enc=0x7f54574fe320, syntax=0x2e2d660, einfo=0x0) at regcomp.c:5546

#10 0x00007f54572b7fb7 in regcomp (reg=0x7f5445ce7040, pattern=0x7f544c2f5c24 "[/.-]", posix_options=<value optimized out>) at regposix.c:154

#11 0x00000000010d559d in HPHP::php_split (spliton=..., str=..., count=-1, icase=false) at /export/dev_hhvm/hiphop-php_hzg/src/runtime/base/preg.cpp:1400

#12 0x00000000017b350a in HPHP::f_split (pattern=..., str=..., limit=-1) at /export/dev_hhvm/hiphop-php_hzg/src/runtime/ext/ext_preg.cpp:106

………………………….

 

最终发现是f_split函数出的问题,然后是调用了Oniguruma(正则库的问题);

问题出在了regparse.c:1105这里,由于这里默认采用的方式的线程原子操作,也就是没有对多进程进行处理,这里有一个链表是FreeNodeList是一个静态的变量,所以操作的时候就出现了争抢销毁,最终该对象成为了野指针;

那么如何解决这个问题呢?这里有一个宏默认是进行线程原子操作的,我们只要把这个宏注释掉就可以进行多线程或者多进程的操作了。

我们找到regint.h文件中的69行:

//#define USE_PARSE_TREE_NODE_RECYCLE

注释掉这个宏即可,然后我们重新编译Oniguruma

由于最开始使用的是默认的yum 的库oniguruma-devel,这里我们需要去下载源码才可以;

安装完毕后,我们替换so即可;

该库的默认路径在:/usr/lib64/libonig.so.2

经过测试,改后无发现coredump问题;

 

Oniguruma 下载地址:

http://www.geocities.jp/kosako3/oniguruma/

我用的版本是5.9.4

Latest release version 5.9.4 (2013/04/04) Change Log

5.9.3 (2012/10/26)

 

这个版本;

 

Git问题位置:

 

https://github.com/facebook/hiphop-php/issues/1111

 

 

96.   hhvm  支持parse_str

测试脚本

<?php

 

//传入array

 parse_str("id=23&name=John%20Adams",$a);

 print_r($a);

 

 echo var_dump($id);

 echo "\n";

 echo var_dump($name);

 echo "\n";

//不传入array

 parse_str("id=23&name=John%20Adams");

 

 echo var_dump($id);

 echo "\n";

 echo var_dump($name);

 echo "\n";

//传入array并且有同名变量

$name = 'Smith';

parse_str("id=23&name=John%20Adams", $a);

echo $name . "\n";

 

 

 

 ?>

 

提问:

https://github.com/facebook/hiphop-php/issues/1146

 

第一版修复地址:

https://github.com/facebook/hiphop-php/commit/c2ec3da9e74ed6d3fac7cded6ad29dc5b3947786

 

9月份该问题已经修复一部分,就是不传入参数的也可以捕获到:

parse_str("id=23&name=John%20Adams");

输出:

string(2) "23"

string(10) "John Adams"

 

但是如果是如上面代码的状况就会输出:

Array

(

    [id] => 23

    [name] => John Adams

)

 

HipHop Notice:  Undefined variable: id in /export/data/www/test/test_ext/test_parse_str.php on line 7

NULL

 

HipHop Notice:  Undefined variable: name in /export/data/www/test/test_ext/test_parse_str.php on line 9

NULL

 

完全修复无diff的代码为ext_string.cpp中:

void f_parse_str(CStrRef str, VRefParam arr /* = null */) {

Variant result;

        HttpProtocol::DecodeParameters(result, str.data(), str.size());

        if(!arr.isReferenced()) {

                f_extract(result.toArray());

                return;

        }

///////////////////////////////防止出现Notice也就是变量未定义//////////////////////////

 Array vars=result.toArray();

        Array newVars=Array::Create();

                   Array allVars=f_get_defined_vars();

        for (ArrayIter iter(vars); iter; ++iter) {

                Variant key = iter.first();

                if(!allVars.exists(key)){

                        Variant value;

                        value.setNull();

                        newVars.set(key,Variant(value));

                }

        }

        f_extract(newVars);

 

        arr = result.toArray();

///////////////////////////////////////////////////////////////////////////////

}

这样修改后和phpdiff

 

如果是旧版本的,需要加入一个头:

#include "hphp/runtime/ext/ext_variable.h"

因为f_extract 是在该头文件中的函数

 ========================================================================

下面的是正确的修复,上面虽然内容一致,但是其实最终实现语法和zend不同了,主要是变量存在问题;

其实和php语法一致的还是后来官方修复后的内容:

我上面改的内容其实避免了notice,但是最终当传入$a后,这个变量应该是不存在的;

https://github.com/facebook/hiphop-php/issues/1146

见:

 

@huzhiguang, compare output of this script on PHP and your patched HHVM:

<?php
parse_str("id=23&name=John%20Adams",$a);
var_dump(isset($name));

PHP Output:

bool(false)

As I said before, this is because no variables should be extracted when second parameter of parse_str is given. Seehttps://github.com/php/php-src/blob/master/ext/standard/string.c#L4454-4460 for details.

 

php的代码实现中:

https://github.com/php/php-src/blob/master/ext/standard/string.c#L4454-4460

if (arrayArg == NULL) {

                 zval tmp;

 

                 if (!EG(active_symbol_table)) {

                          zend_rebuild_symbol_table(TSRMLS_C);

                 }

                 Z_ARRVAL(tmp) = EG(active_symbol_table);

                 sapi_module.treat_data(PARSE_STRING, res, &tmp TSRMLS_CC);

         } else   {

                 zval ret;

 

                 array_init(&ret);

                 sapi_module.treat_data(PARSE_STRING, res, &ret TSRMLS_CC);

                 /* Clear out the array that was passed in. */

                 zval_dtor(arrayArg);

                 ZVAL_COPY_VALUE(arrayArg, &ret);

         }

 

array存在的时候也就是else分支是不进行创建变量的;

所以官方提供的代码最终实现是正确的:

最终实现:

void f_parse_str(CStrRef str, VRefParam arr /* = null */) {

Variant result;

        HttpProtocol::DecodeParameters(result, str.data(), str.size());

        if(!arr.isReferenced()) {

                f_extract(result.toArray());

                return;

        }

        arr = result.toArray();

}

 

97.   将变量加入到符号表的函数f_extract

Phpextract函数是将一个array的内容添加到vm的变量中,让其变量能够找到;

如:

$a=array(“test”=>”1”,”test1”=>”2”);

extract($a);

echo $test;

 

 

输出是1,也就是这时候就注册了2个变量test,test1;

 

 

2
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics