Wednesday, August 22, 2007

Having Fun with Trac: Tracd + Digest Authentication


Tracd
is a lightweight standalone Trac web server, which was added to Trac framework since version 0.7. Running Trac on Tracd is very simple, while needs a bit more work with authentication. Tracd supports both Basic and Digest authentication. The default is to use Digest authentication. In certain situations, I found out that Digest authentication is an easy and quick way to provide access controls to Trac web application. Here are the steps to create Digest authentication for tracd web server:


1. Creating a Password File


We used the htdigest tool which Apache provides to create a digest password file. The following command creates a digest password file users.mytest with realm name mytest and also adds user tom to the file:


htdigest -c tractest/users.mytest mytest tom


If file users.mytest exits, then we should remove option –c in the command above. We will be promoted for a password to enter for each user that we create.


2. Creating Trac Permissions


We also need to add Trac permissions for each user created in step 1. Permission privileges are managed using the trac-admin tool. For example, the following command will grant all privileges to user tom to project tractest:


trac-admin tractest/ permission add tom TRAC_ADMIN


3. Using Digest Authentication


The following command will force Tracd to trace users' activities with project tractest using Digest authentication:

tracd -p 1234 -a tractest, tractest/users.mytest, mytest tractest

When launching Trac from http://localhost:1234/tractest/login, a log-in form pops up and asks for user's name and password. Tracd also allows sharing a password file among multiple projects on one instance of Trac.

Reference:


Tracd : http://trac.edgewall.org/wiki/TracStandalone
Trac Permission: http://trac.edgewall.org/wiki/TracPermissions




Tuesday, August 7, 2007

Comparison of C++ and Java (VIII): Vtable vs. Method Invocation Table and Binary Compatibility (1)

Both Java and C++ have mechanisms to support dynamic polymorphism via run-time method binding, C++ uses vtable to achieve this goal while Java is by method invocation table. The difference of these two mechanisms leads to the different behaviours regarding to binary compatibility.

A vtable exmple

in C++, a vtable contains the addresses of the object's dynamically bound methods. Method calls are performed by fetching the method's address from the object's vtable. The vtable is the same for all objects belonging to the same class, and is therefore typically shared between them.

Considering the following example. Class A defines one virtual function methodA which just prints out a silly message:


A.h

class A{

public:
A(){}
virtual void methodB();
};

A.cc

void A::methodA(){
cout<<"print from method A "<<endl;
};

The vtable of A looks like:

vtable layout of class A:

A::_ZTV1A: 3u entries
0 0u
8 (int (*)(...))(&_ZTI1A)
16 A::methodA

The offset of A::methodA is 16.

Here is a test class to reference class A:

test.cc

int main (int argc, char *argv[]){
A* a = new A();
a->methodA();
}


We compile and link program by the following three steps:

>>g++ -c A.cc
>>g++ -c test.cc
>>g++ A.o test.o –o test

and run test program
>>./test

and get output:
>>Print from method A

In the example above, method call a->methodA fetches methodA from a address with offset 16.

Adding a virtual method breaks binary compatibility in C++

To show this, we add a virtual function methodB to class A right BEFORE methodA :

A.h

class A{
public:
A(){}
virtual void methodB(); // a new added function
virtual void methodA();
};

A.cc

void A::methodA(){
cout<<"print from method A "<<endl;
}

void A::methodB(){
cout<<"print from method B "<<endl;
}

Then we recompile class A BUT NOT class test, and link them again:

>>g++ -c A.cc
>>g++ A.o test.o –o test

Then we run test program:
>>./test

and get out put:
>>Print from method B

Why not " Print from method A" as I would expect? Let's take a look at the vtable of the revised class A:

vtable of revised class A

A::_ZTV1A: 4u entries
0 0u
8 (int (*)(...))(&_ZTI1A)
16 A::methodB
24 A::methodA

Note the address of methodA is now with offset 24, while the address of 16 is occupied by methodB. If we execute test program without recompilation, the address with offset 16 is still referenced and thus methodB gets called.

This problem shown above is known as "constant recompilation problem" and is usually considered as a side effect of C++: because C++ compiler references methods or variables by numeric offset at compilation time, sometimes we add a new method or a new instance variable to a class, any and all classes that reference that class will require a recompilation, or they break.