Sunday, June 4, 2017

Boost Intrusive container must be clear before exits

A few weeks ago when I was working on a problem involving linked list, I was stuck in an interesting test case on Boost Intrusive. The error I'm getting is coming from the comment of a source code as seen below:
void destructor_impl(Hook &hook, detail::link_dispatch<safe_link>)
{  //If this assertion raises, you might have destroyed an object
   //while it was still inserted in a container that is alive.
   //If so, remove the object from the container before destroying it.
   (void)hook; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!hook.is_linked());
}
I was in debug mode, and the program was stopped right there. At first I had overlooked into this important piece, but then later only I got to realize that the comment is giving some clue over there. The comment has clearly stated that I must have the container to be clear before destroying it. So what I did in my class was I extend the list_base_hook:
class FileNode : public list_base_hook<> {
public:
    string name;
    char type;

public:
    FileNode() {}

    void setName(string name) { this->name = name; }
    void setType(char type) { this->type= type; }
};

typedef boost::intrusive::list<FileNode> FileNodeList;
And this is my test case that causes the error:
BOOST_AUTO_TEST_CASE(TL_2)
{
    FileNodeList fnl;

    FileNode fn1;
    fn1.name = "path_A";

    assert(fn1.is_linked() == false);

    FileNode fn2;
    fn2.name = "fileA";

    fnl.push_front(fn1);

    fnl.clear(); // error will be thrown if this code is removed!
}
Do take note the above class FileNode does not take any template argument. There is another version using auto_unlink as template argument, just like below:
class FileNode : public list_base_hook<link_mode<auto_unlink> > { 
    ...
    ...
}; 
 
typedef boost::intrusive::list<FileNode, constant_time_size<false> > FileNodeList;
This feature does not require me to clear the container when the container's destructor is invoked, which happened when the function is exited.

Friday, March 17, 2017

Make path-to-string utility as static function

I have a string utility that converts the boost::filesystem::path into a string. The current implementation was done in the following way.
/** header file **/

using convert_typeX = std::codecvt_utf8<wchar_t>;

class Path {

   ...
   ...

private:
   wstring_convert<convert_typeX, wchar_t> converterX;

};


/** implementation file **/

Path::Path(path thePath)
    : rootPath(thePath), searchDone(false)
{
    string filename = converterX.to_bytes(thePath.wstring());
    string rootPath = converterX.to_bytes(this->rootPath.wstring());

    ...
}
This utility is spread across in every class that require path-to-string conversion. After some time when I look back on this code I felt that the design approach is very unpractical and quite troublesome too. Since this utility is used in everywhere, I just wonder, would it be better if I make it static. I'm just trying to simplify things, complex thing is tiring me.
/** header file **/

using convert_typeX = std::codecvt_utf8<wchar_t>;

class FileHelper {

   ...
   ...

public:
   static string convertPathToString(boost::filesystem::path thePath) {
      wstring_convert<convert_typeX, wchar_t> converterX;
      return converterX.to_bytes(thePath.wstring());
   }


private:
   wstring_convert<convert_typeX, wchar_t> converterX;

};


/** implementation file **/

Path::Path(path thePath)
    : rootPath(thePath), searchDone(false)
{
    string filename = FileHelper::convertPathToString(thePath);
    string rootPath = FileHelper::convertPathToString(this->rootPath);

    ...
}
With the new approach, I centralize that piece into FileHelper (a utility class specializes in file). When Path objects need it, just direct call on convertPathToString() from the class.

Thursday, March 2, 2017

Constructor pattern or code design error?

There is a minor defect happened in my program where the program only able to capture the files in the last recursive loop. Below is the code snippet of the code:
void FilePath::captureFiles(path searchPath) {

            ...
            ...

            // it is a directory
            if( is_directory(status(*it)) ) {
                BOOST_LOG_TRIVIAL(info) << "The file is a directory";

                captureFiles(*it);
            }
            // it is a file
            else {
                ...
                ...

                if( bPlus ) {
                    bPlus = false;
                    indexFile << "+" << filename << endl;

                    BOOST_LOG_TRIVIAL(info) << "FilePath::captureFiles : The file is capture into index file with '+' sign";
                }
                else if( !bMinus ) {
                    bMinus = false;
                    indexFile << filename << endl;

                    BOOST_LOG_TRIVIAL(info) << "FilePath::captureFiles : The file is capture into index file";
                }
            }

    indexFile.close();

    ...
    ...
}
The root cause happened when there is no more directory were found in the path and the program will flow into the else section. Once the file name was captured into indexFile, the indexFile were close!

Then where does this variable get initialized?
FilePath::FilePath(path thePath)
    : rootPath(thePath), searchDone(false)
{
    ...
    ...

    // capture the index file content into memory
    indexFilePath = rootPath + string(1, path::preferred_separator) + filename + ".i";

    if( exists(indexFilePath) ) {
        captureExistingFile();
        bFileExist = true;
    }

    indexFile.open(indexFilePath, ios_base::in | ios_base::out | ios_base::app);
}
Notice that the indexFile only got initialize once in the constructor, and its memory was free in the last loop of the recursive function, I have no way to reopen it inside the recursive loop.

A good programming practice for this case is that close it in the destructor since it got initialize in the constructor, then the problem will fix automatically.
FilePath::~FilePath()
{
    ...

    if( indexFile.is_open() )
        indexFile.close();
}

Monday, February 20, 2017

Using Boost.Log in the project

Boost.Log, just like other module, it must be built first before it can be used. But most of the time I will just go for the default compilation, just like below

> ./b2 --with-log 

According to this documentation, I can have a lot more option to the build. Say for example -DBOOST_LOG_DYN_LINK, below is the definition of the macro:

BOOST_LOG_DYN_LINK If defined in user code, the library will assume the binary is built as a dynamically loaded library ("dll" or "so"). Otherwise it is assumed that the library is built in static mode. This macro must be either defined or not defined for all translation units of user application that uses logging. This macro can help with auto-linking on platforms that support it.

When I build with -DBOOST_LOG_DYN_LINK just like the sample below:

> ./b2 --with-log define=BOOST_LOG_DYN_LINK

I must have the following statement in the .pro file:

DEFINES += BOOST_LOG_DYN_LINK

Take a closer look into the console output. Notice that BOOST_LOG_DYN_LINK option is added into g++ build command:
g++ -c -pipe -g -std=gnu++0x -Wall -W -D_REENTRANT -fPIC -DBOOST_LOG_DYN_LINK -DQT_QML_DEBUG 
-DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I../../backupUtil -I. -I../../../tool/boost_1_61_0 -I../../backupUtil 
-I../../../tool/Qt5.6.0/5.6/gcc_64/include -I../../../tool/Qt5.6.0/5.6/gcc_64/include/QtWidgets 
-I../../../tool/Qt5.6.0/5.6/gcc_64/include/QtGui -I../../../tool/Qt5.6.0/5.6/gcc_64/include/QtCore -I. -I. 
-I../../../tool/Qt5.6.0/5.6/gcc_64/mkspecs/linux-g++ -o main.o ../main.cpp
If the above define statement is missing from the .pro file, the compiler will throw out the link error. Tracing that error could lead to a wrong way fixing the problem because the root cause wasn't there. This documentation would give some hints on how this thing could be fixed. Below is the important text from that documentation:
<version><linkage>_<threading>_<system>
  • The <version> component describes the library major version. It is currently v2.
  • The <linkage> component tells whether the library is linked statically or dynamically. It is s if the library is linked statically and empty otherwise.
  • The <threading> component is st for single-threaded builds and mt for multi-threaded ones.
  • The <system> component describes the underlying OS API used by the library. Currently, it is only specified for multi-threaded builds. Depending on the target platform and configuration, it can be posix, nt5 or nt6.
Same to the default Boost.Log build without BOOST_LOG_LINK, link error will be throw if the define statement was declared in the .pro file.

Saturday, January 21, 2017

replace multiple character in a string

As mention before, unit test is just a way to gauge my code doing the right thing. But I still miss the functional test. Take the following piece as an example:
    int seperatorPos = filename.find("/");
    if(seperatorPos > 0) {
        filename.replace(seperatorPos, 1, "_");
    }
This piece supposes to construct the index file name from the given path. For example, if the given path is path_A/path_B, then the index file name should be path_A_path_B. The unit test has done a pretty good job, but in a real world environment, the path could be path_A/path_B/path_C, in such a situation, that piece could fail. This is the drawback of unit test, it can't simulate the actual use case. To fix the defects, that piece needs to identify when it has searched through the entire string. As you guess it, I need a while loop to do this, here is the solution:
    int seperatorPos = filename.find("/");
    while( seperatorPos != string::npos ) {
        filename.replace(seperatorPos, 1, "_");
        seperatorPos = filename.find("/");
    }
Then this is the final piece that meets my requirement.

Wednesday, December 28, 2016

Unit test my code

Now is the time for serious thing - unit testing. To make sure I'm doing the right thing with my code. Frankly speaking, implementing unit test in C++ is my first time. Not even heard of it in the past. Wasting a lot of my time discovering C++ unit test framework, surprisingly, Boost's test framework was quite user friendly.

To adopt this thing into my project, I've come an idea that is suited for my test case. The idea like this, for each test case, 2 folders will be created to mimic the source location and destination location. Thus I have a class named PrepareFile for this purpose, the constructor will invoke when each test case begins, and the destructor will invoke when the test case has ended:
class PrepareFile
{
public:
    PrepareFile() {
        create_directory("path_A");
        create_directory("path_B");

        BOOST_TEST_MESSAGE("Creating test folder");
    }
    ~PrepareFile() {
        remove_all("path_A");
        remove_all("path_B");

        BOOST_TEST_MESSAGE("Removing test folder");
    }
};

/*  Test case: Cap_T1
 *  Test scenario: path_A has one file
 *  Test result: one file is captured in index file
 */
BOOST_FIXTURE_TEST_CASE(Cap_T1, PrepareFile)
{
    ...
}

/*  Test case: Cap_T2
 *  Test scenario: path_A has one file, path_B has one file.
 *  Test result: files in both paths has captured in index file.
 */
BOOST_FIXTURE_TEST_CASE(Cap_T2, PrepareFile)
{
    ...
}
I like this test framework structure because it could provide me a clean test environment. Anyhow, this is just a tiny test in my code, SIT effort is still required.

Saturday, December 24, 2016

Generate WSDL file with wsgen

Today I'm running a Web Service experiment again. But I just feel that I'm making a tutorial right now. No way, this is just a finding on my silly mistake though. Assuming I have the following code setup:
package org.huahsin.main.bo;

...

@WebService(targetNamespace = "http://main.huahsin.org/")
public interface IPersonService {

 @WebMethod
 public String getPerson(String name);
}


package org.huahsin.main;

...

@WebService(serviceName = "PersonService", 
   endpointInterface = "org.huahsin.main.bo.IPersonService",
   portName = "PersonServicePort")
public class PersonService implements IPersonService {

 @Override
 public String getPerson(String name) {
  return "Hello World " + name;
 }

}
Take good care of the endpointInterface, I mess up this name with the implementation class name, that suppose belong to an Interface. Next is to fire up the WSDL through HTTP. Previously I was using this trick to make a WSDL file:
public class PersonClient {

 public static void main(String[] args) {
  Endpoint.publish("http://localhost:8080/ws", new PersonService());
 }
}
And then hit the URL http://localhost:8080/ws?wsdl in the browser, copy the content in the WSDL file. Actually wsgen has already covered the WSDL file generation with -wsdl as shown following command:

wsgen -keep -wsdl -cp ./WebContent/WEB-INF/classes org.huahsin.main.PersonService

There will be some minor modification on the REPLACE_WITH_ACTUAL_URL after WSDL file is generated:
  <service name="PersonService">
    <port binding="tns:PersonServicePortBinding" name="PersonServicePort">
      <soap:address location="REPLACE_WITH_ACTUAL_URL"/>
    </port>
  </service>
Just replace any URL as you like, make sure the IP and port are accessible, it is very useful to determine what are the service available currently deployed.

* Do take note that when I deploy this code into WebSphere Liberty Profile (v8.5.5.8 as of this writing) with CXF runtime bundle with my code, it causes conflict error. According to the documentation, I should not enable jaxws-2.2 feature.
If you application provides its own copy of CXF JAR files as the application libraries, for example, in the WEB-INF/lib directory of a web application, you cannot enable the jaxws-2.2 feature in the server.xml file.