Axis2/C with pthreads

After writing Axis2/C with cbthead post , I was so curious to test same code with pthreads. As a result I came up with this modified echo sample which uses same svc client and environment among all threads. One thing to note is with cbthread, program worked well with 100,000 threads whereas with pthreads, it went out of memory around 370 threads.  However pthreads is more portable, well tested and widespread thread library therefore it is more likely to use Axis2/C with pthreads. echo.c and Makefile can be obtained from here [1].

1. http://www.cs.utk.edu/~dpremala/pthread/

echo.c

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <axiom.h>
#include <axis2_util.h>
#include <axiom_soap.h>
#include <axis2_client.h>
#include <pthread.h>
 
#define NTHREADS 10
 
axiom_node_t *
build_om_payload_for_echo_svc(const axutil_env_t * env);
 
typedef struct _ginfo{
    pthread_mutex_t *lock;
}ginfo_t;
 
typedef struct _svcinfo {
    pthread_t pid;
    const axutil_env_t *env;
    axis2_svc_client_t *svc_client;
}svc_info_t;
 
svc_info_t **pthreads;
ginfo_t *ginfo;
static void svc_client_send_request (void *v);
static void svc_client_finish_request (void *v);
 
int
main(int argc, char **argv)
{
    const axutil_env_t *env = NULL;
    const axis2_char_t *address = NULL;
    axis2_endpoint_ref_t *endpoint_ref = NULL;
    axis2_options_t *options = NULL;
    const axis2_char_t *client_home = NULL;
    axis2_svc_client_t *svc_client = NULL;
    int i = 0;
 
 
    /* Set up the environment */
    env = axutil_env_create_all("echo.log", AXIS2_LOG_LEVEL_TRACE);
 
    /* Set end point reference of echo service */
    address = "http://localhost:9090/axis2/services/echo";
    if (argc > 1)
    {
        if (axutil_strcmp(argv[1], "-h") == 0)
        {
            printf("Usage : %s [endpoint_url]\n",
                   argv[0]);
            printf("use -h for help\n");
            return 0;
        }
        else
        {
            address = argv[1];
        }
    }
    printf("Using endpoint : %s\n", address);
 
    /* Create EPR with given address */
    endpoint_ref = axis2_endpoint_ref_create(env, address);
 
    /* Setup options */
    options = axis2_options_create(env);
    axis2_options_set_to(options, env, endpoint_ref);
    axis2_options_set_action(options, env,
                             "http://ws.apache.org/axis2/c/samples/echoString");
 
    /* Set up deploy folder. It is from the deploy folder, the configuration is picked up
     * using the axis2.xml file.
     * In this sample client_home points to the Axis2/C default deploy folder. The client_home can 
     * be different from this folder on your system. For example, you may have a different folder 
     * (say, my_client_folder) with its own axis2.xml file. my_client_folder/modules will have the 
     * modules that the client uses
     */
    client_home = AXIS2_GETENV("AXIS2C_HOME");
    if (!client_home || !strcmp(client_home, ""))
        client_home = "../..";
 
    /* Create service client */
    svc_client = axis2_svc_client_create(env, client_home);
    if (!svc_client)
    {
        printf
            ("Error creating service client, Please check AXIS2C_HOME again\n");
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                        "Stub invoke FAILED: Error code:" " %d :: %s",
                        env->error->error_number,
                        AXIS2_ERROR_GET_MESSAGE(env->error));
        return -1;
    }
 
    /* Set service client options */
    axis2_svc_client_set_options(svc_client, env, options);
 
    /* Engage addressing module */
    axis2_svc_client_engage_module(svc_client, env, AXIS2_MODULE_ADDRESSING);
 
    pthreads = (svc_info_t **) malloc (sizeof (svc_info_t *) * NTHREADS);
    ginfo = (ginfo_t *) malloc (sizeof (ginfo_t));
    if (!ginfo)
    {
        fprintf (stderr, "no enough memory\n");
        exit (1);
    }
 
    ginfo->lock = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t));
    if (!ginfo->lock)
    {
        fprintf (stderr, "no enough memory\n");
        exit (1);
    }
    pthread_mutex_init (ginfo->lock, NULL);
 
    for (i = 0; i < NTHREADS; i++)
    {
        pthreads[i] = (svc_info_t *) malloc (sizeof (svc_info_t));
        if (!pthreads[i])
        {
            fprintf (stderr, "no enough memory\n");
            exit (1);
        }
        pthreads[i]->env = env;
        pthreads[i]->svc_client = svc_client;
        if (pthread_create (&(pthreads[i]->pid), NULL, (void *)svc_client_send_request, (void *)pthreads[i]))
        {
            perror ("pthread creation");
            exit (1);
        }
    }
 
    for (i = 0; i < NTHREADS; i++)
    {
        pthread_join (pthreads[i]->pid, NULL);
    }
 
    svc_client_finish_request ((void *)pthreads[0]);
    return 0;
}
 
/* build SOAP request message content using OM */
axiom_node_t *
build_om_payload_for_echo_svc(
    const axutil_env_t * env)
{
    axiom_node_t *echo_om_node = NULL;
    axiom_element_t *echo_om_ele = NULL;
    axiom_node_t *text_om_node = NULL;
    axiom_element_t *text_om_ele = NULL;
    axiom_namespace_t *ns1 = NULL;
    axis2_char_t *om_str = NULL;
 
    ns1 =
        axiom_namespace_create(env, "http://ws.apache.org/axis2/services/echo",
                               "ns1");
    echo_om_ele =
        axiom_element_create(env, NULL, "echoString", ns1, &echo_om_node);
    text_om_ele =
        axiom_element_create(env, echo_om_node, "text", NULL, &text_om_node);
    axiom_element_set_text(text_om_ele, env, "Hello World!", text_om_node);
    om_str = axiom_node_to_string(echo_om_node, env);
 
    if (om_str)
    {
        printf("\nSending OM : %s\n", om_str);
        AXIS2_FREE(env->allocator, om_str);
        om_str = NULL;
    }
    return echo_om_node;
}
 
 
static void
svc_client_send_request (void *v)
{
    svc_info_t *svcinfo;
    const axutil_env_t *env;
    axis2_svc_client_t *svc_client;
    axiom_node_t *payload = NULL;
    axiom_node_t *ret_node;
 
 
    svcinfo = (svc_info_t *)v;
 
    pthread_mutex_lock (ginfo->lock);
    env = svcinfo->env;
    svc_client = svcinfo->svc_client;
 
 
    /* Build the SOAP request message payload using OM API. */
    payload = build_om_payload_for_echo_svc(env);
 
    /* Send request */
    ret_node = axis2_svc_client_send_receive(svc_client, env, payload);
 
    if (ret_node)
    {
        axis2_char_t *om_str = NULL;
        om_str = axiom_node_to_string(ret_node, env);
        if (om_str)
            printf("\nReceived OM : %s\n", om_str);
        printf("\necho client invoke SUCCESSFUL!\n");
 
        AXIS2_FREE(env->allocator, om_str);
        ret_node = NULL;
    }
    else
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                        "Stub invoke FAILED: Error code:" " %d :: %s",
                        env->error->error_number,
                        AXIS2_ERROR_GET_MESSAGE(env->error));
        printf("echo client invoke FAILED!\n");
    }
    pthread_mutex_unlock (ginfo->lock);
}
 
static void 
svc_client_finish_request (void *v)
{
 
    svc_info_t *svcinfo;
    int i = 0;
    svcinfo = pthreads[0];
 
    if (svcinfo->svc_client)
    {
        axis2_svc_client_free(svcinfo->svc_client, svcinfo->env);
        svcinfo->svc_client = NULL;
    }
 
    if (svcinfo->env)
    {
        axutil_env_free((axutil_env_t *) svcinfo->env);
        svcinfo->env = NULL;
    }
 
    for (i = 0; i < NTHREADS; i++)
    {
        free (pthreads[i]);
    }
    free (pthreads);
 
    pthread_mutex_destroy (ginfo->lock);
    free (ginfo);
    printf ("All threads finished \n");
}

Technorati Tags: , , , ,

Posted in axis2c | Tagged , , , , | 5 Comments

Axis2/C with cbthread

Many users asked questions about using Axis2/C in multi threaded environment. Here Axis2/C client side used with cbthread library. cbthread library is a small lightweight non-preemptive thread library which was developed by Dr. Plank. Good thing about  cbthread library is , it doesn’t use much memory to keep information of threads. Unlike pthread, one can run thousands of threads without running out of memory. This example was tested with 100,000 of threads successfully and all requests were sent using same svc_client.Here [1] are some materials to to learn about cbthread

echo.c client side

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
#include <stdio.h>
#include <axiom.h>
#include <axis2_util.h>
#include <axiom_soap.h>
#include <axis2_client.h>
#include <cbthread.h>
 
/* Number of theads */
#define NTHREADS 10
 
typedef struct _svcinfo {
    const axutil_env_t *env;
    axis2_svc_client_t *svc_client;
}svc_info_t;
 
svc_info_t **cthreads;
static void svc_client_send_request (void *v);
static void svc_client_finish_request (void *v);
 
axiom_node_t *
build_om_payload_for_echo_svc(const axutil_env_t * env);
 
int
main(int argc, char **argv)
{
    const axutil_env_t *env = NULL;
    const axis2_char_t *address = NULL;
    axis2_endpoint_ref_t *endpoint_ref = NULL;
    axis2_options_t *options = NULL;
    const axis2_char_t *client_home = NULL;
    axis2_svc_client_t *svc_client = NULL;
    int i = 0;
 
    /* Set up the environment */
    env = axutil_env_create_all("echo.log", AXIS2_LOG_LEVEL_TRACE);
 
    /* Set end point reference of echo service */
    address = "http://localhost:9090/axis2/services/echo";
    if (argc > 1)
    {
        if (axutil_strcmp(argv[1], "-h") == 0)
        {
            printf("Usage : %s [endpoint_url]\n",
                   argv[0]);
            printf("use -h for help\n");
            return 0;
        }
        else
        {
            address = argv[1];
        }
    }
    printf("Using endpoint : %s\n", address);
 
    /* Create EPR with given address */
    endpoint_ref = axis2_endpoint_ref_create(env, address);
 
    /* Setup options */
    options = axis2_options_create(env);
    axis2_options_set_to(options, env, endpoint_ref);
    axis2_options_set_action(options, env,
                             "http://ws.apache.org/axis2/c/samples/echoString");
 
    /* Set up deploy folder. It is from the deploy folder, the configuration is picked up
     * using the axis2.xml file.
     * In this sample client_home points to the Axis2/C default deploy folder. The client_home can
     * be different from this folder on your system. For example, you may have a different folder
     * (say, my_client_folder) with its own axis2.xml file. my_client_folder/modules will have the
     * modules that the client uses
     */
    client_home = AXIS2_GETENV("AXIS2C_HOME");
    if (!client_home || !strcmp(client_home, ""))
        client_home = "../..";
 
    /* Create service client */
    svc_client = axis2_svc_client_create(env, client_home);
    if (!svc_client)
    {
        printf
            ("Error creating service client, Please check AXIS2C_HOME again\n");
        AXIS2_LOG_ERROR(env-&gt;log, AXIS2_LOG_SI,
                        "Stub invoke FAILED: Error code:" " %d :: %s",
                        env->;error->;error_number,
                        AXIS2_ERROR_GET_MESSAGE(env->error));
        return -1;
    }
 
    /* Set service client options */
    axis2_svc_client_set_options(svc_client, env, options);
 
    /* Engage addressing module */
    axis2_svc_client_engage_module(svc_client, env, AXIS2_MODULE_ADDRESSING);
 
    cthreads = (svc_info_t **) malloc (sizeof (svc_info_t *) * NTHREADS);
    for (i = 0; i < NTHREADS; i++)
    {
        cthreads[i] = (svc_info_t *) malloc (sizeof (svc_info_t));
        if (!cthreads[i])
        {
            fprintf (stderr, "no enough memory\n");
            exit (1);
        }
        cthreads[i]->env = env;
        cthreads[i]->svc_client = svc_client;
        cbthread_fork (svc_client_send_request, (void *)cthreads[i]);
    }
 
    cbthread_joinall(svc_client_finish_request, NULL);
    return 0;
}
 
/* build SOAP request message content using OM */
axiom_node_t *
build_om_payload_for_echo_svc(
    const axutil_env_t * env)
{
    axiom_node_t *echo_om_node = NULL;
    axiom_element_t *echo_om_ele = NULL;
    axiom_node_t *text_om_node = NULL;
    axiom_element_t *text_om_ele = NULL;
    axiom_namespace_t *ns1 = NULL;
    axis2_char_t *om_str = NULL;
 
    ns1 =
        axiom_namespace_create(env, "http://ws.apache.org/axis2/services/echo",
                               "ns1");
    echo_om_ele =
        axiom_element_create(env, NULL, "echoString", ns1, &echo_om_node);
    text_om_ele =
        axiom_element_create(env, echo_om_node, "text", NULL, &text_om_node);
    axiom_element_set_text(text_om_ele, env, "Hello World!", text_om_node);
    om_str = axiom_node_to_string(echo_om_node, env);
 
    if (om_str)
    {
        printf("\nSending OM : %s\n", om_str);
        AXIS2_FREE(env->allocator, om_str);
        om_str = NULL;
    }
    return echo_om_node;
}
 
static void
svc_client_send_request (void *v)
{
    svc_info_t *svcinfo;
    const axutil_env_t *env;
    axis2_svc_client_t *svc_client;
    axiom_node_t *payload = NULL;
    axiom_node_t *ret_node;
 
    svcinfo = (svc_info_t *)v;
    env = svcinfo->env;
    svc_client = svcinfo->svc_client;
 
    /* Build the SOAP request message payload using OM API. */
    payload = build_om_payload_for_echo_svc(env);
 
    /* Send request */
    ret_node = axis2_svc_client_send_receive(svc_client, env, payload);
 
    if (ret_node)
    {
        axis2_char_t *om_str = NULL;
        om_str = axiom_node_to_string(ret_node, env);
        if (om_str)
            printf("\nReceived OM : %s\n", om_str);
        printf("\necho client invoke SUCCESSFUL!\n");
 
        AXIS2_FREE(env->allocator, om_str);
        ret_node = NULL;
    }
    else
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                        "Stub invoke FAILED: Error code:" " %d :: %s",
                        env->error->error_number,
                        AXIS2_ERROR_GET_MESSAGE(env->error));
        printf("echo client invoke FAILED!\n");
    }
 
}
 
static void
svc_client_finish_request (void *v)
{
 
    svc_info_t *svcinfo;
    int i = 0;
    svcinfo = cthreads[0];
 
    if (svcinfo->svc_client)
    {
        axis2_svc_client_free(svcinfo->svc_client, svcinfo->env);
        svcinfo->svc_client = NULL;
    }
 
    if (svcinfo->env)
    {
        axutil_env_free((axutil_env_t *) svcinfo->env);
        svcinfo->env = NULL;
    }
 
    for (i = 0; i < NTHREADS; i++)
    {
        free (cthreads[i]);
    }
    free (cthreads);
    printf ("All threads finished \n");
}

Makefile

CC = gcc
CFLAGS = -O3 -Wall
LIB = -L/home/dinesh/lib -lcbthread -lm -L /home/dinesh/axis2c/deploy/lib -laxis2_engine -laxutil -laxis2_axiom
INCLUDE = -I. -I/home/dinesh/axis2c/deploy/include/axis2-1.5.0/ -I/home/dinesh/include
EXECUTABLES = echo
all : $(EXECUTABLES) 
 
echo: echo.c
        $(CC) $(CFLAGS)  $(INCLUDE) -o echo echo.c $(LIB)
clean:
        rm -f $(EXECUTABLES) *~ \#*

You can download echo.c and Makefile from here [2].
1. http://www.cs.utk.edu/~plank/plank/cbthread/
2. http://www.cs.utk.edu/~dpremala/cbthread/

Technorati Tags: , , , ,

Posted in axis2c | Tagged , , , , | 6 Comments

Drawings on a text file ?

If you ever need to draw a table, diagram on a text file this screen cast might be useful. It gives a nice example of drawing linked list structure on a text file.

Posted in emacs | Leave a comment

Install R, BioConductor in Debian

R is a free and open source package which use for statistical analysis. In this post main focus is going towards installing and configuring the BioConductor, which is also a free and open source project (a package in R) widely use for analyzing genome data. Tried to install and configure BioConductor in debian after a demonstration  of research group mates. Even though installing R was pretty much straight forward, BioConductor needed some effort.

Installing R

# apt-get install r-base  r-recommended r-base-dev

Installing BioConductor

#R
R version 2.7.1 (2008-06-23)
Copyright (C) 2008 The R Foundation for Statistical Computing
ISBN 3-900051-07-0

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type ‘license()’ or ‘licence()’ for distribution details.

Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type ‘contributors()’ for more information and
‘citation()’ on how to cite R or R packages in publications.

Type ‘demo()’ for some demos, ‘help()’ for on-line help, or
‘help.start()’ for an HTML browser interface to help.
Type ‘q()’ to quit R

>source(”http://bioconductor.org/biocLite.R”)

>biocLite()

It downloaded several packages on the fly and instaledl into R. For analytical purposes we use package called ‘affy’ however it did not install in my first attempt. After further investigation noticed that compilation of affy package gave an warning on my machine.Normally I enable -Werror flag therefore compilation aborted. Then exited from R environment and disabled -Werror flag.
read_pgf.c: In function ‘pgf_count_probeset_types’:
read_pgf.c:1265: warning: assignment from incompatible pointer type
gcc -std=gnu99 -shared  -o affyio.so fread_functions.o read_abatch.o read_bpmap.o read_cdffile2.o read_cdf_xda.o read_celfile_generic.o read_clf.o read_generic.o read_pgf.o -lpthread -lz  -lpthread  -L/usr/lib/R/lib -lR
** R
** preparing package for lazy loading
** help

#export CFLAGS=”"

#R

>source(”http://bioconductor.org/biocLite.R”)

>biocLite(”affy”)

> library(affy)
Loading required package: Biobase
Loading required package: tools

Welcome to Bioconductor

Vignettes contain introductory material. To view, type
‘openVignette()’. To cite Bioconductor, see
‘citation(”Biobase”)’ and for packages ‘citation(pkgname)’.

Loading required package: affyio
Loading required package: preprocessCore

Technorati Tags: , , ,

Posted in linux | Tagged , , , | 2 Comments

Install Sinhala In Debian

Some of my friends started tweet and sending emails in Sinhala. Problem I had was, I couldn’t read them since I dind’t install Sinhala in my laptop (Which runs Debian lenny of course). I found some really helpful websites which helped me to install Sinhala.

To install Sinhala, following line added to the /etc/apt/source.list [1]

deb http://sinhala.sourceforge.net/debian/i386/lenny/ ./

Then ran apt-update and installed packages [2].

#apt-get update
#apt-get install ttf-sinhala-lklug scim scim-gtk2-immodule im-switch scim-m17n m17n-db m17n-contrib

Interestingly, In order to make an effect on these changes session should be logged out. Sinhala will be enabled from next session.

Even though, This online tool [3] is easy to use, it is kind of burden to go there every time to type
some Sinhala. Deep and Mohanjith suggested that to try out SCIM.

Enable SCIM in XFCE [4]

Following lines added to ~/.Xsession file

LANG=en_US.UTF-8
export LANG
XMODIFIERS="@im=SCIM"
export XMODIFIERS
GTK_IM_MODULE="scim"
export GTK_IM_MODULE
scim -d&

startxfce4

After logged out and logged in again, SCIM was enabled.
Sinhala Input

Sinhala Input



Sinhala Wijesekara Keyboard Layout

Sinhala Wijesekara Keyboard Layout


Enjoy ! ජය !

Referances

1. http://www.siyabas.lk/sinhala_how_to_install.html#lin

2. http://www.nongnu.org/sinhala/doc/howto/sinhala-howto.html#SEC.ENABLING-SINHALA-LONG-2

3. http://www.ucsc.cmb.ac.lk/ltrl/services/feconverter/t2.html

4. http://wiki.xfce.org/howto/scim

Technorati Tags: , ,

Posted in linux | Tagged , , | Leave a comment

Axis2/C Vs gSoap

One of the Axis2/C key contributor Damitha Kumarage compares Axis2/C feature list against gSoap. This comparison spread over the areas of services, clients, WS-* support , MTOM , REST and many more. gSoap and Axis2/C are the main stacks in open source webservices stacks that are implemented in C, moreover this feature list comparison would be helpful for selecting one webservices framework. Since Damitha is Axis2/C contributor, this comparison might be little biased towards the Axis2/C; however, this article provides a good ground to compare these two stacks.

References

[1] “Feature Comparison of WSF/C and gSoap”

October 2008, http://wso2.org/library/articles/feature-comparrision-wsf-c-gsoap

Technorati Tags: ,

Posted in WSO2 WSF/C, axis2c, c, soap, wsfc | Tagged , | Leave a comment

Installing Matlab on Debian (lenny)

This blog post mainly target for UT students who need to install matlab on linux. However there are some possible problems that any one could come across while installing matlab. and fixes for those problems discussed in this post.

One of big news for UT about matlab is , University of Tennessee now has a system-wide license agreement with The MathWorks that makes MATLAB, Simulink and 54 other products available for free to all University of Tennessee faculty, staff, and students. Matlab download procedure with academic license can be obtained from OIT website. Downloading and installing involves following four steps.

  1. Create a Mathworks Account.
  2. Associate your MathWorks account with the TAH license using the appropriate Activation Key.
  3. Download MATLAB products from MathWorks.com and install MATLAB software.
  4. Activate the MATLAB software.

Even though installing on windows is quite easy, need some work around for installing on linux, specifically Debian Testing x86 distribution. Here x86 is emphasized because installing on x86_64 didn’t work for me.

After creating mathworks account, can be logged into mathworks website and cab be downloaded R2008a release. In order to download, system should have java installed  because mathworks has a download agent which uses javaws.

  • Select suitable distribution

  • Download Agent
Download Prompt
  • Point to Javaws

  • Download with Javaws

  • Starts Download

as it shown, matlab and it’s 54 modules are downloaded into /tmp/mathworks_downloads directory.

Installation.

To begin installation, as a super user

# cd /tmp/mathworks_downloas

# tar -xf boot.ftp

#./install

Extracting ftp files . . . [please wait]
Extracting matlab.common
Extracting matlab.glnx86
….

Read More »

Technorati Tags: ,

Posted in linux, matlab | Tagged , | Leave a comment

Apache Axis2/C 1.4.0 Released.

On 6th May 2008, Apache Axis2/C Team announced the release of Apache Axis2/C 1.4.0 . In this release , Guththila parser was used as the default parser. In mailing list we discussed this matter for some time and this is the first time we released with Guththila as the default parser.

Technorati Tags: , , ,

Posted in axis2c | Tagged , , , | Leave a comment

University of Moratuwa on TOP of the GSoc list.

Though this a bit old news, It is my pleasure to see University of Moratuwa on top of the Gsoc list. That was appeared in Google open source blog last week. My good friend Thilna has said almost everything I need to say in his blog post. Three cheers for Mora !!!

Technorati Tags: , ,

Posted in general | Tagged , , | Leave a comment

Quite an achievement!

After started blogging on this blog from 4th January 2008, today I noticed that this blog got: 5 in Google page ranking. I started this blog , in a way as an experiment on achieving good page ranking. Though total page views are little more than 1500, ranking is quite an achievement for me.

Technorati Tags: , ,

Posted in general | Tagged , , | Leave a comment