Wednesday, February 28, 2007

Monday, February 19, 2007

Crontab

This is a useful program for scheduling routine tasks initiated by scripts. Developing on the search installation from last week, we will write a crontab entry to update the namazu index daily.

First of all check which jobs are currently scheduled:

user@compy:~> crontab -l
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.XXXX8NR6OC installed on Mon Feb 5 17:51:55 2007)
# (Cron version V5.0 -- $Id: crontab.c,v 1.12 2004/01/23 18:56:42 vixie Exp $)
0 5 * * * /home/user/.backup.sh


This is the rsync job from the other week. So, next we need to create a script to run the namazu index. This is a simple shell script with the following command in it:
#!/bin/bash
mknmz -O ~/.namazu/index/ ~/work/articles/

Save this file somewhere like in ~/.namazu/.index.sh. Append this to the crontab in the same way as the rsync script was added - i.e. type crontab -e and add the following line:
0 5 * * * /home/user/.namazu/.index.sh

Then, type crontab -l to check that it has been added. You should now have a namazu index that updates everyday at 5AM.

Wednesday, February 7, 2007

Namazu Config

Namazu is a search engine. Whilst its no replacement for find and grep in most cases, it is useful for searching a directory of pdf files, and this can be made available through a web interface - which is quite useful if you have a lot of pdfs.

Download and install the program - its available for most distributions. You will need to edit the config file namazurc and the index config file mknmzrc. I needed to change the max file size variable to accommodate my pdfs.

In the mknmzrc file I changed the following lines:
# The max file size for indexing. Files larger than this
# will be ignored.
# NOTE: This value is usually larger than TEXT_SIZE_MAX because
# binary-formated files such as PDF, Word are larger.
#
$FILE_SIZE_MAX = 10000000;

#
# The max text size for indexing. Files larger than this
# will be ignored.
#
$TEXT_SIZE_MAX = 6000000;



I then created an index directory in my home directory. If you are setting this up for a web server you may wish to keep the index files elsewhere. So then I ran the mknmz program:

mknmz -O ~/.namazu/index/ ~/work/articles/


This creates the index of the articles directory and stores it in the .namazu/index directory. From the command line you can now enter:
namazu "epitope not cell"


Not that that search makes any sense but you get the idea.

Friday, February 2, 2007

ssh bash completion in Ubuntu

SSH bash completion doesn't currently work in 6.10. This is because hostnames are now stored as hashes in ~/.ssh/known_hosts. To disable storing hostnames as hashes and allow ssh hostname completion to work correctly you need to edit: /etc/ssh/ssh_config and change HashKnownHosts to No.

Thanks to Ubuntu forums for the answer.

Thursday, February 1, 2007

Set up subversion

If you are comfortable with CVS - changing over to svn shouldn't be too hard. First make sure you download the latest version of svn from your package manager.

Then to create the new svn repository type:
svnadmin create /foo/bar/repo


Then to check it out, you need to create a working directory and know the url of the svnserve. In my case this is a local server running on just my machine so the following will work:
mkdir svndir

svn checkout file:///foo/bar/repo svndir


You can now move into the svndir and start working.

Its probably well worth reading up on the differences between cvs projects and svn directories. Its probably easiest to think of creating a new svn repository for what would have been a cvs project. Also its worth bearing in mind that changes in a svn repository tag the whole project rather than a single file.

Friday, January 26, 2007

vector can not hold reference to a pure virtual base class

I had three classes, a template pure virtual base class, a template
derived class and a third which I would like to use to store copies of
the derived class. The code looked like this:

#include <iostream>
#include <vector>

using namespace std;

template <class _prec> class Base {
public:
_prec i;

Base() {
i = 12;
}

virtual void f() = 0;

};

template <class _prec> class Derived : public Base<_prec> {
public:
void f() {
std::cout << this->i << std::endl;
}
};

template <class _prec> class Collect {
public:
vector <Base<_prec> *> vec;

Collect() {
}

void g(Base<_prec> &in) {
vec.push_back(&in);
vec[0]->f();
}
};

int main() {
Derived<int> *d = new Derived<int>;
Collect<int> c;

c.g(*d);

return 0;
}



And resulted in errors such as:

/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/vector.tcc:256: error: cannot allocate an object of abstract type ‘Base<int>’
base_vector_test.cpp:6: note: since type ‘Base<int>’ has pure virtual functions
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/vector.tcc:256: error: cannot declare variable ‘__x_copy’ to be of abstract type ‘Base<int>’
base_vector_test.cpp:6: note: since type ‘Base<int>’ has pure virtual functions



The problem is that vector creates a copy of the object you pass it. If you pass it a reference to an abstract base class it can't create a copy, just as you can't do: Base b; The solution in my case is to use pointers. This however means you'll have to manage their allocation and deallocation of the objects yourself. The fixed code looks like this:

#include <iostream>
#include <vector>

using namespace std;

template <class _prec> class Base {
public:
_prec i;

Base() {
i = 12;
}

virtual void f() = 0;

};

template <class _prec> class Derived : public Base<_prec> {
public:
void f() {
std::cout << this->i << std::endl;
}
};

template <class _prec> class Collect {
public:
vector <Base<_prec> *> vec;

Collect() {
}

void g(Base<_prec> &in) {
vec.push_back(&in);
vec[0]->f();
}
};

int main() {
Derived<int> *d = new Derived<int>;
Collect<int> c;

c.g(*d);

delete d;
return 0;
}



My original thread on comp.lang.c++ where I got help with this problem can be found here: http://groups.google.ie/group/comp.lang.c++/browse_thread/thread/c4cad258a9a94540

Thursday, January 25, 2007

Inheritance appears to break when deriving a template class

If you have a base template class from which you derive another template class inheritance can appear to break, i.e. you don't appear to be able to access the base classes variables and methods directly. For example take the following code:


#include <iostream>

template <class _prec> class Base {
public:
_prec i;

Base() {
i = 12;
}

virtual void f() {
std::cout << i << std::endl;
}

};

template <class _prec> class Derived : public Base<_prec> {
public:
void f() {
std::cout << i*2 << std::endl;
}
};

int main() {
Base<int> b;
Derived<int> d;

b.f();
d.f();

return 0;
}



On gcc 4.1.2 this gives the following error:

derive_test.cpp: In member function ‘void Derived<_prec>::f()’:
derive_test.cpp:20: error: ‘i’ was not declared in this scope



The problem is caused because the base class is not in scope, why I find unclear, and the work around a little messy. But basically if you change
std::cout << i*2 << std::endl;
to
std::cout << this->i*2 << std::endl;

All will be well.


More info at: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19 and
http://gcc.gnu.org/onlinedocs/gcc/Name-lookup.html