Shivakar Vulli

Archive for October, 2009

Using Beagle to Speed Up Desktop Searches on Linux

leave a comment

About Beagle

Beagle is a desktop-indepedent search service for Linux that lets you search your user files. It has the capability to search and index all files including images, music, videos, documents (pdf, odt, odp, etc.), emails, web history, IM conversations, addressbook, calendar, source code, archives and much more. It is a complete desktop search service perfect for anyone using Linux.

Beagle indexes user data in real time with indexing done at the time of file creation, re-indexing on modification and purged from index on deletion. E-mail is indexed up on arrival and IM conversations are indexed in real time. Beagle searches not only the text contained in the document, but also all metadata such as ID3 Tags for music, header information from emails, etc.

I use GNOME on a Fedora 11 machine, therefore I will detail the procedure to get beagle search up and running in the same. The procedure would be all that different with a different desktop or Linux distribution.

Installing Beagle

On Fedora you can install Beagle using

yum install beagle

Using Beagle

Once the installation is completed, start Places > Search and select Search > Preferences. Select the options you need but do check the option for Start search & indexing services automatically in the Searching tab. In the Indexing tab, add any paths that you want to be indexed, and any application data sources (like Thunderbird and Pidgin) that you want beagle to index in the Data sources tab. I have not used indexing remote search-enabled hosts feature, but you can check it out in Network options. You can also enable a web-interface and allow external access to local search services in the same tab.

To check the installation, open a terminal and issue the following command

beagled --fg --debug

This should display the settings of beagled. You can kill the service by pressing Ctrl-C.

When you login the next time, beagle will be running and indexing your existing files and should index any new file created. However, if you want to speed things up and index all the existing files before you start using your system again, beagle has a solution.

You need to export the following variable to set accelerated indexing. Keep in mind this is going to use as much as your CPU as needed and will take time some time depending on the number of files you have in your included search directories.

 export BEAGLE_EXCERCISE_THE_DOG=1

Now run the following command to start beagle in the accelerated indexing mode.

beagled --indexing-test-mode

This will set beagled to exit after indexing all the files in the current search directories. Once this is done you can logout and log back in to start using beagle for your searches.

At any time if you want to check the current status of beagled, issue the following command

beagled-status

And to shut down beagled you can either do it from Service Options in the search window or by issuing the beagle-shutdown from a terminal.

For more information on beagle, visit the project homepage.

Written by Shivakar

October 30th, 2009

Posted in Fedora, Linux, OpenSource

Tagged with , , ,

RTAI on Arcom’s SBC-GXX533 Development Kit.

leave a comment

Note: This is an entry from my old website. This project was completed in 2007. I make no guaratee that this will work with newer versions of the software used for this project. Please use caution when using this information


About this guide

This guide outlines the procedure to install RTAI on Arcom’s SBC-GX533 Development Board. You will need the SBC-GX533 Development Kit and a Linux machine (running preferably Kernel 2.6) to complete this tutorial. I will be referring to the Linux machine as the host system and the SBC-GX533 as the target board. Access to the Internet from the host system is preferred. Also you need a way to copy files from the host system to the target board. I used ssh for this purpose. The board’s ethernet card 0 (eth0) is configured via DHCP so all I needed to do was to plug one of the spare ethernet cables from my router to eth0 and I was able to access the target board via eth0. If you don’t have Internet connection on either machine, all you need to do is configure both systems’ IP addresses manually and put them on a network. If for this you need to login to the target board, you can connect to the board using serial connection. The procedure to connect to the target board using serial connection can be found in the SBC-GX533 Technical Manual.

You need the following installed on the host system before proceeding.

  1. Perl – To install the AEL host environment.
  2. AEL host environment – You can install the AEL host environment from the CD provided with the kit. Installation instructions can be found in Arcom Embedded Linux Technical Manual.
  3. Minicom or other serial communications program like GtkTerm.

About Arcom

Arcom, a Eurotech company, is a leading supplier of standard, modified, and custom solutions for embedded communication and control technology. Founded in Cambridge in 1982, Arcom has developed a broad range of solutions for data processing, communications and control in industry and commercial applications. Arcom has engineering and support teams in Kansas City (US) and Cambridge (UK) which offer Design services to OEM customers.

More information about Arcom can be found at http://www.arcom.com.

About SBC-GX533

To put it into a single sentence, The Arcom SBC-GX533 Linux Development Kit provides the easiest way to develop a wide range of embedded devices in a Linux environment.

More elaborately, [from Arcom's Website] The SBC-GX533 is a low profile, fan-less, RoHS compliant EBX form factor board, based on the AMD Geodeā„¢ GX 533 @1.1W processor. It includes all the standard PC interfaces as well as a full range of multimedia features including onboard graphics which can drive a standard analog display or a TFT flat panel, dual 10/100baseTx Ethernet, onboard 32Mbyte Flash drive, CompactFlash port, four USB ports, four serial ports and an analog touchscreen interface.

The SBC-GX533 is ideal for fan-less embedded controllers which require PC compatibility with full solid-state operation.

Kernel 2.6 based Embedded linux is already installed, with GNC C library. Compressed Journalling Flash File System (JFFS2) offering high reliability and recovery from power interruptions. Secure Shell (openSSH) , Embedded Web Server. Embedded Linux Drivers for onboard I/O, network and audio.

For more information on the SBC-GX533 Development Kit, visit :


About RTAI

RTAI stands for Real-Time Application Interface for Linux. RTAI lets you write applications with strict timing constraints. RTAI consists mainly of two parts:

  1. A patch to the kernel which introduces a hardware abstraction layer. This adds to the kernel real-time capabilities allowing you to have a real-time OS within a non real-time Linux environment.
  2. A broad variety of services which make real-time programmers’ lives easier. The RTAI API provides you a wide variety of functions you can use to develop your embedded application faster.

For more information on RTAI, check out the project website.

Installing RTAI on Arcom’s SB-GX533

Step1: Setup the Sources

Download the latest stable RTAI Package from their project website. For this project I used the 3.4 closure version. The Kernel source for the target board can be found on the AEL Host environment on the host machine. On the machine used for this project, the path to the source was

/opt/arcom/src/linux-source-2.6.16.14-arcom1.tar.gz

Extract both, the kernel source and rtai source to /usr/src. Create symlink /usr/src/linux pointing to the kernel source using

ln -s /usr/src/linux-source-2.6.16.14-arcom1 /usr/src/linux

Now to apply the RTAI patch do the following.

1
2
cd /usr/src/linux
patch-p1 /usr/src/rtai-3.4-cv/base/arch/i386/patches/hal-linux-2.6.16.i386-1.3.08.patch

Now the sources are setup and we can proceed to configuring and compiling the kernel and RTAI.

Step 2: Configuring and Compiling the Kernel

First get the default configuration by running

make ARCH=i386 sbc-gx533_defconfig

Next you can tweak the options to suite your needs using

make ARCH=i386 xconfig

According to the RTAI installation guide, you need to turn off module versioning, ACPI support and APM support as these conflict with RTAI. I turned on support for Arcom SBC-GX533 and also made the kernel preemptible. Once this is done you can move on to compiling the kernel. You have to do this using the tool ael-kernel-build.

ael-kernel-build --ARCH=i386 image

This will compile the kernel, build the image and build three .deb packages at /usr/src/. Copy the linux-image .deb file to the target board and install using

dpkg -i linux-image-2.6.16.14-arcom1_10.0.Custom_i386.deb

Now connect to the target board using serial connection and enter the Redboot mode, by pressing Ctrl-C when prompted during the boot up. Once you are in the Redboot enter the following command to change the default kernel to the newly installed one.

alias kernel /boot/vmlinuz-

Now the board is ready for RTAI to be installed.

Step 3: Configuring and Compiling the RTAI

According to the RTAI manual you need to be running the kernel with which you are going to use RTAI. But the cross compilation did work for me with a few fixable problems. Change the working directory to /usr/src and create a new directory called build. This is preferred way of compiling RTAI. Change the working directory to build. Now enter the following to build and install RTAI.

make -f /usr/src/rtai-3.4-cv/makefile xconfig CC=i386-linux-gcc CXX=i386-linux-g++

Select all the features you need and then save the configuration and exit. Now compile RTAI.

make all

Now install RTAI to a folder so that you can transfer it to the target board.

make install DESTDIR=/tmp/rtai

Once the installation is completed you can transfer the installation to the target board by the following commands. The target board by default does not have bunzip compression installed on it, hence it is easier to use gunzip compression.

1
2
3
cd /tmp/rtai
tar cvzf ../rtai_install.tar.gz *
cd .. sftp root@<TargetBoard_Hostname_or_IPAddress>

now login to the target board and install RTAI.

cd / tar xvf /root/rtai_install.tar.gz

This concludes the installation of RTAI

Step 4: Testing the RTAI Installation

Change the working directory to /usr/realtime/testsuite/kern/latency and type the following

rtai-load latency

This should run the latency test and display the results. The default installation asks you to just run ./run in the current directory tos ee the latency results, but due to cross compilation (IMHO) it does not work like that any more. You have to call rtai manually passing it the test you want to run. There is a file named .runinfo in each of the testsuite directory. The first word inside the file is the argument you have to pass to rtai_load to run the test. Compare your results with the ones on this site – http://issaris.org/rtai/.

Now your Arcom SBC-GX533 is ready for running real-time applications.

Written by Shivakar

October 30th, 2009

Posted in Embedded, Linux

Tagged with , , , ,

Creating Matlab MEX Function for PostgreSQL Database Connectivity

leave a comment

Note: This is an entry from my old website. This is a piece of code that I have written in 2007. Although it is still being used in my research group, it is being used on systems with Matlab v7.0, Microsoft Visual Studio .NET 2003 and PostgreSQL v8.1.5. I have never tried to run the program using newer versions of any of these software and make no claim or provide any guarantee that it will work as provided or at all. Please use caution in using this code.


A few months ago I was assigned an interesting problem of providing connectivity between PostgreSQL and Matlab. After some research I found that the best way would be the Matlab Database Toolbox. The problem with that solution was that we need to provide the connectivity for about 10 computers and the toolbox was priced at about USD 125. So purchasing per seat or even 10 floating licenses would mean spending around USD 1000 (With any academic volume discounts available, I guess). So I set out to find alternatives and after some more searching around I found that writing a MEX function is the best way to include C (or Fortran for that matter) code into Matlab. I was already using libpq to connect to this database in my C/C++ programs, so I ventured to try if MEX function could be written to do the job.

The setup

The setup consisted of 10 systems. The database server is a Linux machine running Ubuntu Dapper Drake, and all the clients are Windows machines running Windows XP with Matlab 7.0 and Microsoft Visual Studio .NET 2003 installed on them.

Introduction to MEX files

MEX stands for Matlab EXecutable. MEX provides a way to call C or Fortran functions from within Matlab. A very good resource (probably the best) on MEX function is [1].

A MEX file has two main components:

  1. #include “mex.h”
    Every C/C++ MEX-file must include mex.h. This is necessary to use the mx* and mex* routines.
  2. mexFunction gateway
    C/C++ MEX functions do not have a main() function, instead the entry point is the mexFunction(). It’s syntax is always

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *phrs[]){ }

where,
mexFunction – Name of the entry point to the program (same for every MEX-file, like “main” in C/C++)
nlhs – Number of output mxArrays (Left Hand Side)
plhs – Array of poitns to expected output mxArrays
nrhs – Number of input mxArrays (Right Hand Side)
prhs – Array of pointers to input mxArrays. The input data is read-only and should not be altered by the mexFunction.

Apart from these two essential things you can use all the mx* and mex* functions and include all the normal include files from C/C++ or your special libraries. A more detailed discussion can be found at [1].

Introduction to libpq

libpq is the C API to PostgreSQL and consists of a set of library functions that allow client programs to pass queries to a PostgreSQL backend server and to receive the result of these queries.

An introduction to libpq can be found at [2].

Setting up the PostgreSQL Database Server

I setup a PostgreSQL server on Ubuntu Dapper Drake. The simplest way to install the database server is through apt-get.

sudo apt-get install postgresql-8.1

This would install PostgreSQL-8.1, creates a user ‘postgres’ and a database ‘postgres’. For this example, I would be using the default database user and database.

For more information on installing from source, creating new databases, creating and adding new users to the database visit [3].

C Program for checking libpq

To check the functionality offered by libpq and to check whether the database server and libpq are working as expected, I wrote a C program and used MSVS 2003 to compile it. For compiling the program you need ‘libpq-fe.h’, ‘libpq.dll’ and other associated dlls. For that I downloaded the binary version of PostgreSQL for windows from [4] and added the required directories to VC++ path.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <stdarg.h>
  #include "libpq-fe.h" /* This is required for using the goodies from libpq */
 
  PGconn *psql; /* The actual connection variable */
 
  int main (int argc, char **argv) {
    int i, j;
    PGresult *result; /*Variable to store the result from the database query */
   
    /* Initialize the connection */
    /* Makes connection to the host with specified IP address as user postgres and connects to the database postgres */
    psql = PQconnectdb("hostaddr='192.168.100.25' dbname='postgres' user = 'postgres'");
    if(!psql) { /* Check whether the connection went fine or not */
      fprintf(stderr, "libpq error: PQconnectdb returned NULL.\n\n");
      exit(1);
    }
    if(PQstatus(psql) != CONNECTION_OK) { /* Check the status of the connection */
      fprintf(stderr, "libpq error : PQstatus(psql) != CONNECTION_OK \n\n");
      exit(2);
    }
   
    result = PQexec (psql, "SELECT * FROM test;"); /* PQexec queries the server psql with the query that is passed to it */
    if(!result || !(j=PQntuples(result))) { /* Check if there is a result from the query. If yes then store the number of rows returned */
      fprintf(stderr, "libpq error: no rows returned or bad result set \n\n");
      PQfinish(psql); /* If no result was returned, close the connection */
      exit(3);
    }
   
    for(i=0; i< j; i++) {
      printf("Name: %s\n", PQgetvalue(result, i,0));
     
      /*PQgetvalue returns the value at the given index from the result */
      printf("ID: %s\n", PQgetvalue(result, i, 1));
    }
   
    PQclear(result); /* Clear the result - Always a good practise */
    PQfinish(psql); /* Close the connection */
  }

Now compile and execute this program. If everything was done right, you will see the contents of the table ‘test’ from the database ‘postgres’.

Since we now know that libpq setup is working properly, we can proceed to the mex function.

The MEX function

Programming MEX functions is actually easy one you are through with a few examples. You will realize that the time taken to setup the Matlab environment is much less than the time required to setup a Visual Studio project.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <stdarg.h>
  #include "libpq-fe.h" /* Include this for the goodies from libpq */
  #include "mex.h" /* Include this for MEX stuff */
  #include "matrix.h"
 
  #define MAXERROR 500 //Size of the maximum error string
  /*
  * There is no main function in the MEX files. The entry point is instead the mexFunction. The
  * mexFunction takes four parameters:
  * nlhs - An int variable which holds the number of left hand side variables (vararg_out) in the
  * MATLAB function call
  * plhs - A mxArray pointer which holds the left hand side output values (output_args) in the
  * MATLAB function call
  * nrhs - An int variable which holds the number of right hand side variables (vararg_in) in the
  * MATLAB function call
  * prhs - A mxArray pointer which holds the right hand side input values (input_args) in the
  * MATLAB function call
  */

 
  void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
    PGconn *psql; // The actual connection variable
    PGresult *result; // A Variable to hold the result
    char colBuffer[33];
    int i, j, tuples, fields, buflen, status;
    int *dims = mxCalloc(1, sizeof(int)); //Use mxCalloc to allocate memory in mex functions
    char *errMsg = mxCalloc(MAXERROR, sizeof(char));
    char *conn, *quer;
    int position = 1;
    mxArray *outArray; //An array to store the output values from pq_query function
   
    if(nrhs !=2) //Check for the number of inputs - This program requires two inputs - connectioninfo and query
      mexErrMsgTxt("Two Input Arguments Required.");
    else if(nlhs >1) //Check for the number of outputs - This program outputs only one output
      mexErrMsgTxt("Too many output arguments.");
   
    if((mxIsChar(prhs[0]) != 1) && (mxIsChar(prhs[1]) != 1)) //Check the type of the inputs
      mexErrMsgTxt("Inputs must be string."); // Inputs must be Strings
     
    //Calculates the length of the first rhs argument
    buflen = (mxGetM(prhs[0])*mxGetN(prhs[0])) + 1;
    conn = mxCalloc(buflen, sizeof(char)); // Allocate memory for char* conn
   
    status = mxGetString(prhs[0], conn, buflen); //Store the value of first rhs argument into conn   
    if(status !=0) //Check whether successful
      mexWarnMsgTxt("Not Enough memory. String 'conn' is truncated.");

    buflen = (mxGetM(prhs[1])* mxGetN(prhs[1])) + 1; //Calculates the length of the second rhs argument
    quer = mxCalloc(buflen, sizeof(char)); //Allocate memory for char *quer
   
    status = mxGetString(prhs[1], quer, buflen); //Store the value of the second rhs argument into quer
    if(status !=0) //Check whether successful
      mexWarnMsgTxt("Not Enough Memory. String 'quer' is truncated.");
     
    /* Initiate the connection */
    psql = PQconnectdb(conn);
    if(!psql){ //Check whether the connection went fine or not
      mexErrMsgTxt("libpq error: PQconnectdb returned null\n\n");
    }
   
    if(PQstatus(psql) != CONNECTION_OK){ //Check the connection status
      mexErrMsgTxt("libpq error: PQstatus(psql) != CONNECTION_OK\n\n");
    }
   
    result = PQexec (psql,quer); // Use PQexec to query the database
    /* check for null rows - if yes */
    if(!result || !(tuples = PQntuples(result)) || !(fields = PQnfields(result))){
      errMsg = PQerrorMessage(psql);
      PQfinish(psql);
      mexPrintf("%s", errMsg);
      mexErrMsgTxt("libpq error: No rows returned or bad result set\n\n");
    }
   
    dims[0] = tuples * fields + 1;
    outArray = mxCreateCellArray(1, dims);
    itoa(fields, colBuffer, 10);
    mxSetCell(outArray,0, mxCreateString(colBuffer));
    for(i=0; i < tuples; i++)
      for(j=0; j < fields; j++)
      /* copy the contents of Result in to mxArray outArray */
        mxSetCell(outArray, position++, mxCreateString(PQgetvalue(result, i, j)));
       
    plhs[0] = outArray;    /*Assign the outArray to the left hand side argument in the MATLABfunction call */
    return;
  }

Save this program as, say libpqmex.c

To compile the program at Matlab command prompt type

 mex libpqmex.c libpq.lib

If a C compiler is not already selected, you will be presented with the various compilers available on your system. I selected MS VC++ .net 2003. Select the compiler you want. This will compile your program and link it to libpq.lib and create libpqmex.mex32 (previous versions of Matlab used to create a dll, say libpqmex.dll). Now you can call the MEX function as you would all any other Matlab function

connInfo = ['hostaddr=''192.168.100.25'' dbname=''postgres'' user=''postgres'''];

In the above line all are single quotes. this will save the string into connInfo.

queryString = ['SELECT * FROM test'];

This will save your query into queryString. This can be modified into any query you want. Now call the function.

result = libpqmex(connInfo, queryString);

This should save the output from the database into the variable result.

Now the MEX function returns the result in one single vector so I wrote a .m file to convert this into a cell array containing the result in the form of a table. Although this can be done in the MEX function itself, I decided to keep things simple.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  function [queryResult] = getFromdb(hostname, database, username, query)
  % Sample Function call - result = querydb('192.168.100.25', 'postgres', 'postgres', 'SELECT * from test2');
  % hostname = '192.168.100.25';
  % database = 'postgres';
  % username = 'postgres';

  % Use the information provided by the user to create a connection string
  connInfo = ['host = ''' hostname '''' ' dbname = ''' database '''' ' user = ''' username ''''];  
 
  % Get the result. The result will be a single column array containing
  % all the values returned from the query.
  resultFromdb = getFromdbmex(connInfo, query);
  numResultCols = str2num(resultFromdb{1});
 
  queryResult = {};
  % Convert the result to an cell Matrix with rows and columns
  for i = 1:numResultCols
  queryResult(:,i) = resultFromdb(i+1:numResultCols:end);
  end

That concludes this article.

References

  1. MEX guide at Mathworks.com
  2. libpq documentation and API reference
  3. PostgreSQL documentation
  4. http://www.postgresql.org/ftp/binary/v8.1.5/win32/

Written by Shivakar

October 29th, 2009

Posted in C/C++, Matlab, Programming

Tagged with , , , ,