Tuscany SDO 中的Bug

阅读更多

Tuscany SDO 中的Bug

作者:ling091 时间:2008-12-16

 

我正在参与的ESB(企业服务总线)项目使用Tuscany的开源组件SDO(C++),在使用过程中,我和其他项目组员发现了SDO存在的几个bug,这些bug我已经通过Apache网站的JIRA

http://issues.apache.org/jira/browse/Tuscany

进行了发布,从该网站可以看到C++ SDO的所有使用者发布的bug和新特性,有些bug已经由该bug的发布者或其他用户提供了补丁。

以下是我在ApacheJIRA上发布的四个bug:

1Bug1

1.1 概要:

SDO的几个与序列化相关的方法不支持多线程

1.2 运行环境:

Windows XP

Visual C++6.0

cpp_tuscany_sdo-M3

libxml2-2.7.2

iconv-1.7.2

zlib-1.2.3

boost-1.33.1

1.3 描述:

在多线程环境中对SDO对象进行序列化和反序列化时,只有第一个线程的运行是好的,从第二个线程开始SDO对象的序列化和反序列化都失败了(多线程环境是通过开源库boost_1_33_1实现的)。这些在多线程中运行失败的方法包括:

//used when antiserializing a SDO object from a character string

const char*  XSDHelperImpl::define(

const char* schema,

bool loadImportNamespace= "")

 

//used when serializing a SDO object into a character string

char* XMLHelperImpl::save(

            DataObjectPtr dataObject,

            const char* rootElementURI,

            const char* rootElementName,

            int indent= -1)

 

// used when serializing a SDO object into a xml file

void XMLHelperImpl::save(

            DataObjectPtr dataObject,

            const char* rootElementURI,

            const char* rootElementName,

            const char* xmlFile,

            int indent = -1)

 

//used when getting a SOD object's shcema character string

char* XSDHelperImpl::generate(

            const TypeList& types,

            const char* targetNamespaceURI = "",

            int indent = -1)

 

//used when getting a SDO object's schema file

void XSDHelperImpl::generateFile(

            const TypeList& types,

            const char* fileName,

            const char* targetNamespaceURI = "",

            int indent = -1)

但是与对象序列化或反序列化相关的方法中,通过文件来反序列化创建SDO对象的方法都是线程安全的:

const char* XSDHelperImpl::defineFile(

const char* schema,

bool loadImportNamespace = false)

1.4 解决方案:

通过比较defineFiledefine方法的实现,我查找到原因是SDO涉及序列化和反序列化的方法都依赖开源的C++xml解析器libxml2,而libxml2的一些方法并不是线程安全的,尽管网上的资料声称libxml22.4.7版已经做到线程安全了。通过将define方法依赖的解析函数替换为libxml2中的其他线程安全的解析函数,补丁程序的define方法已经不存在线程不安全问题。

defineFile方法依赖的libxml2中的方法是:

XMLPUBFUN int XMLCALL           xmlSAXUserParseFile      (

xmlSAXHandlerPtr sax,

                                   void *user_data,

                                   const char *filename);

对该方法的调用位于SAX2Parser类的parse_twice方法

 

define方法依赖的libxml2中的方法是:

XMLPUBFUN int XMLCALL           xmlParseChunk          (

xmlParserCtxtPtr ctxt,                               

const char *chunk,

                                   int size,

                                   int terminate);

对该方法的调用位于SAX2Parser类的stream_twice方法,在补丁程序中,将xmlParserChunk方法替换为与xmlSAXUserParseFile对应的下列方法:

XMLPUBFUN int XMLCALL           xmlSAXUserParseMemory     (

xmlSAXHandlerPtr sax,

                                   void *user_data,

                                   const char *buffer,

                                   int size); 

补丁程序只修改了SAX2Parser类的stream_twice,修改后的实现为:

void SAX2Parser::stream_twice(std::istream& input)

        {

                    //begin input流读到char*

 

                    input.seekg(0, std::ios_base::end);

                    int size = input.tellg();

 

                    char* buffer = new char[size];

                    input.seekg(std::ios_base::beg);

 

                    input.read(buffer, size);

                   

                    //end

 

                    parserError = false;

            xmlSAXHandlerPtr handler = &SDOSAX2HandlerStruct;

 

                    //int rc = xmlSAXUserParseFile(handler, this, filename);

                    int rc = xmlSAXUserParseMemory(handler, this, buffer, size);

            if (rc == -1)

            {

                sdo_error(this, "xmlSAXUserParseFile returned an error %d", rc);

                SDO_THROW_EXCEPTION("parse", SDOFileNotFoundException,messageBuffer);

            }

                   

            // parse twice - first was for groups

                   

            if (setter)setter->clearErrors();

                   

            //rc = xmlSAXUserParseFile(handler, this, filename);

                    rc = xmlSAXUserParseMemory(handler, this, buffer, size);

            if (rc == -1)

            {

                sdo_error(this, "xmlSAXUserParseFile returned an error %d", rc);

                SDO_THROW_EXCEPTION("parse", SDOFileNotFoundException,messageBuffer);

            }

 

                    delete buffer;

 

             }

对于上面提到的其他的不支持多线程的方法,由于没有在libxml2中找到与之对应的线程安全的解析函数进行替换,所以这些函数仍然不支持多线程环境。

2Bug2

2.1 概要:

有些反序列化方法不支持中文,或者不可用,或者中文变为乱码。

2.2 运行环境:

Windows XP

Visual C++6.0

cpp_tuscany_sdo-M3

libxml2-2.7.2

iconv-1.7.2

zlib-1.2.3

 

2.3 描述:

从一个字符串反序列化成一个SDO对象时,如果字符串中存在中文字符,则反序列化为SDO对象存在问题,不同的使用方式或者不可用、或者中文变为乱码。

下面的方法是对SDO进行封装后的从字符串反序列化为SDO对象:

DataObjectPtr generateSDOFromStr(

const char* xsdStr, const char* xmlStr,

const char* nameSpace = "")

{

      DataObjectPtr root=NULL;

      try

      {

             DataFactoryPtr mdg=DataFactory::getDataFactory();

             XSDHelperPtr xsdHelper=HelperProvider::getXSDHelper(mdg);

             xsdHelper->define(xsdStr);

             XMLHelperPtr xmlHelper = HelperProvider::getXMLHelper(mdg);

             XMLDocumentPtr xmlDoc = xmlHelper->load(xmlStr,nameSpace);

             root = xmlDoc->getRootDataObject();

      }

      catch(SDORuntimeException e)

      {

             cout << "Exception in generateSDOFromStr"<< endl;

             cout<< e<            

      }    

      catch(...)

      {

             cout<<"Exception not SDORuntimeException"<

      }

 

      return root;

}

 

这是对该方法的两种调用方式:

 

void testGenerateSDOFromStr()
{
	
	//直接使用字符串

	string xsdStr = "";
	xsdStr += "";
	string xmlStr = "";
	
//--------------第一种调用方式-------------
//xmlStr写为GB2312或UTF-8结果都是乱码 但是创建sdo对象都是正确的
	//DataObjectPtr dob = generateSDOFromStr(xsdStr.c_str(), xmlStr.c_str() );

	//--------------第二种调用方式----------
	//只要第二个参数中有中文,构造的sdo对象就是null
	DataObjectPtr dob = generateSDOFromStr(xsdStr.c_str(), 
  		"");

	if(dob != NULL)
	{
		cout<getCString("name")< 
 

 

 

 

 

 

2.4 解决方案:

造成乱码的原因是SDO使用的libxml2对中文的支持很差,经过libxml2解析后,SDO得到的内容已经是乱码。解决方法是可以使用iconv提供的编码转换函数进行编码转换,在遇到带中文的字符串需要显示时,将其转换为GB2312编码即可。

3Bug3

3.1 概要:

反序列化为SDO对象的schema文件与从该SDO对象生成的schema文件不一致。

3.2 运行环境:

Windows XP

Visual C++6.0

cpp_tuscany_sdo-M3

libxml2-2.7.2

iconv-1.7.2

zlib-1.2.3

3.3 描述:

schema文件和xml文件反序列化成一个SDO对象,然后再从这个对象生成schema文件,前后两个schema文件的定义不一致,在后面的schema文件中,属性attribute变成了元素element

下面是测试用例:

 

 

Tuscany SDO中的Bug续: http://ling091.iteye.com/admin/blogs/295580

你可能感兴趣的:(多线程,iOS,XP,C,C++)