<?xml version="1.0" encoding="UTF-8"?>

<rdf:RDF
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
  xmlns:sync="http://purl.org/rss/1.0/modules/syndication/"
  xmlns="http://purl.org/rss/1.0/">

<channel rdf:about="http://linuxgazette.net/lg.rdf">
<title>Linux Gazette</title>
<link>http://linuxgazette.net</link>
<description>An e-zine dedicated to making Linux just a little bit more fun.  
Published the first day of every month.
&lt;br&gt;
Issue 164: July, 2009
</description>
<language>en</language>
<managingEditor>gazette@linuxgazette.net</managingEditor>
<webMaster>gazette@linuxgazette.net</webMaster>
<copyright>Copyright (c) 1996-2009 the Editors of Linux Gazette</copyright>

<sync:updatePeriod>monthly</sync:updatePeriod>
<sync:updateFrequency>1</sync:updateFrequency>
<sync:updateBase>2000-01-01T12:00+00:00</sync:updateBase>

<image rdf:resource="http://linuxgazette.net/gx/2004/newlogo-blank-100-gold2.jpg"/>

<items>
<rdf:Seq>
<rdf:li rdf:resource="http://linuxgazette.net/164/lg_mail.html"></rdf:li>
<rdf:li rdf:resource="http://linuxgazette.net/164/lg_talkback.html"></rdf:li>
<rdf:li rdf:resource="http://linuxgazette.net/164/lg_tips.html"></rdf:li>
<rdf:li rdf:resource="http://linuxgazette.net/164/lg_bytes.html"></rdf:li>
<rdf:li rdf:resource="http://linuxgazette.net/164/kachold.html"></rdf:li>
<rdf:li rdf:resource="http://linuxgazette.net/164/laycock.html"></rdf:li>
<rdf:li rdf:resource="http://linuxgazette.net/164/prestia.html"></rdf:li>
<rdf:li rdf:resource="http://linuxgazette.net/164/sephton.html"></rdf:li>
<rdf:li rdf:resource="http://linuxgazette.net/164/silva.html"></rdf:li>
<rdf:li rdf:resource="http://linuxgazette.net/164/tomar.html"></rdf:li>
<rdf:li rdf:resource="http://linuxgazette.net/164/ecol.html"></rdf:li>
<rdf:li rdf:resource="http://linuxgazette.net/164/xkcd.html"></rdf:li>
<rdf:li rdf:resource="http://linuxgazette.net/164/lg_launderette.html"></rdf:li>
</rdf:Seq>
</items>
</channel>

<image rdf:about="http://linuxgazette.net/gx/2004/newlogo-blank-100-gold2.jpg">
<title>Linux Gazette RSS</title>
<url>http://linuxgazette.net/gx/2004/newlogo-blank-100-gold2.jpg</url>
<link>http://www.linuxgazette.net/</link>
<height>42</height>
<width>99</width>
</image>

<item rdf:about="http://linuxgazette.net/164/lg_mail.html">
<title>Mailbag</title>
<link>http://linuxgazette.net/164/lg_mail.html</link>
<dc:creator>LG Staff</dc:creator>
<dc:date>Wed, 01 Jul 2009 22:07:56 -0500</dc:date>
<description>By &lt;strong&gt;LG Staff&lt;/strong&gt;
&lt;br&gt;
&lt;br&gt;&lt;strong&gt;Still Searching&lt;/strong&gt;&lt;br&gt;
icewm question. maximized windows stick to top of screen can this be changed?&lt;br&gt;
&lt;strong&gt;Our Mailbag&lt;/strong&gt;&lt;br&gt;
file system related question&lt;br&gt;
linux command to read .odt ?&lt;br&gt;
Laptop installation problem&lt;br&gt;
[Mailman-Users] Virtual domain not quite working on HTTP (but fine on SMTP)&lt;br&gt;
Quoting question&lt;br&gt;
Fixed. Was: Virtual domain not quite working on HTTP (but fine on SMTP)&lt;br&gt;
Jim, HELP needed, 5-minute solution needed by computer industry&lt;br&gt;
</description>
</item>
<item rdf:about="http://linuxgazette.net/164/lg_talkback.html">
<title>Talkback</title>
<link>http://linuxgazette.net/164/lg_talkback.html</link>
<dc:creator>LG Staff</dc:creator>
<dc:date>Wed, 01 Jul 2009 22:07:56 -0500</dc:date>
<description>By &lt;strong&gt;LG Staff&lt;/strong&gt;
&lt;br&gt;
&lt;br&gt;Talkback:141/brownss.html&lt;br&gt;
157/lg_mail.html&lt;br&gt;
Talkback:133/cherian.html&lt;br&gt;
Talkback:141/lazar.html&lt;br&gt;
</description>
</item>
<item rdf:about="http://linuxgazette.net/164/lg_tips.html">
<title>2-Cent Tips</title>
<link>http://linuxgazette.net/164/lg_tips.html</link>
<dc:creator>LG Staff</dc:creator>
<dc:date>Wed, 01 Jul 2009 22:07:56 -0500</dc:date>
<description>By &lt;strong&gt;LG Staff&lt;/strong&gt;
&lt;br&gt;
&lt;br&gt;2-cent Tip: Wrapping a script in a timeout shell&lt;br&gt;
2-cent Tip - Poor Man's Computer Books&lt;br&gt;
2-cent Tip: Checking the amount of swapped out memory owned by a process&lt;br&gt;
2-cent Tip: ext2 fragmentation&lt;br&gt;
</description>
</item>
<item rdf:about="http://linuxgazette.net/164/lg_bytes.html">
<title>News Bytes</title>
<link>http://linuxgazette.net/164/lg_bytes.html</link>
<dc:creator>Deividson Luiz Okopnik and Howard Dyckoff</dc:creator>
<dc:date>Wed, 01 Jul 2009 22:07:56 -0500</dc:date>
<description>By &lt;strong&gt;Deividson Luiz Okopnik and Howard Dyckoff&lt;/strong&gt;
&lt;br&gt;
&lt;br&gt;Contents:&lt;br&gt;
&lt;strong&gt;News in General&lt;/strong&gt;&lt;br&gt;
Power IT Down Day - August 27, 2009 &lt;br&gt;
Ubuntu Remix to power Intel Classmate Netbooks&lt;br&gt;
Citrix Contributes Code for Virtual Network Switch&lt;br&gt;
New Community Website for Growing XenServer Customer Base&lt;br&gt;
Dell and Goodwill Expand Free Computer Recycling Program&lt;br&gt;
&lt;strong&gt;Conferences and Events&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Distro News&lt;/strong&gt;&lt;br&gt;
New Features listed for Forthcoming Ubuntu 9.10&lt;br&gt;
A naming contest for Ubuntu 10.04 and the South African Linux community&lt;br&gt;
Fedora 11: Many Virtualization Enhancements&lt;br&gt;
&lt;strong&gt;Software and Product News&lt;/strong&gt;&lt;br&gt;
Opera 10 beta: new features, new speed&lt;br&gt;
Oracle 11g Sets New Price/Performance Record with TPC-C Benchmark&lt;br&gt;
</description>
</item>
<item rdf:about="http://linuxgazette.net/164/kachold.html">
<title>Layer 8 Linux Security: OPSEC for Linux Common Users, Developers and Systems Administrators</title>
<link>http://linuxgazette.net/164/kachold.html</link>
<dc:creator>Lisa Kachold</dc:creator>
<dc:date>Wed, 01 Jul 2009 22:07:56 -0500</dc:date>
<description>By &lt;strong&gt;Lisa Kachold&lt;/strong&gt;
&lt;br&gt;
&lt;p&gt; As users of Linux each of us is in a unique position with a powerful tool.   Use of any tool without regard for security is dangerous.  Developers  likewise carry a great responsibility to the community to maintain systems  in a secure way.  Systems Administrators are often placed in the  uncomfortable role of holding a bastion between insecurity or pwnership and  uptime. &lt;/p&gt; 
</description>
</item>
<item rdf:about="http://linuxgazette.net/164/laycock.html">
<title>Building the GNOME Desktop from Source</title>
<link>http://linuxgazette.net/164/laycock.html</link>
<dc:creator>Oscar Laycock</dc:creator>
<dc:date>Wed, 01 Jul 2009 22:07:56 -0500</dc:date>
<description>By &lt;strong&gt;Oscar Laycock&lt;/strong&gt;
&lt;br&gt;
&lt;P&gt;First, I must say that the &lt;A HREF="http://www.gnome.org/"&gt;GNOME&lt;/A&gt; documentation &amp;quot;strongly recommends&amp;quot; against building from source files. If you do, it suggests using the GARNOME scripted system. Even GARNOME it says, is only for the &amp;quot;brave and patient&amp;quot;.  &lt;/P&gt; &lt;P&gt;I started building programs from source as I wanted to upgrade a very old distribution and did not have enough disk space to install a Fedora or Ubuntu. The memory on my old PC is probably a bit low too, at 128 Meg Also, it is fun to run the latest versions, be on the leading edge, and get ahead of the major distributions. You could not run Windows Vista (tm) on my old PC!  &lt;/P&gt; &lt;P&gt;I took the files from the latest GNOME release I could find, being version 2.25. This was probably a mistake. I later found out that odd numbered minor releases like 25 are development releases and may be unstable. The stable 2.26 series should have come out in March. In fact, when I built the file manager &amp;quot;Nautilus&amp;quot;, I could not find a dependency, &amp;quot;libunique&amp;quot;, so I went back to version 2.24. The GNOME sources are at  &lt;A HREF="http://ftp.gnome.org/pub/gnome"&gt;http://ftp.gnome.org/pub/gnome&lt;/A&gt;. &lt;/P&gt; &lt;P&gt;I used the Beyond Linux from Scratch (BLFS) guide to know where to find packages and in what order to build them. You can find it at &lt;A HREF="http://www.linuxfromscratch.org/"&gt;http://www.linuxfromscratch.org&lt;/A&gt; (LFS). Unfortunately the BLFS guide uses versions from the summer of 2007, GNOME version 2.18. Also, I installed the libraries and programs in the default location /usr/local, but looking back it would have been better to have put them in their own directory and give a --prefix option to &amp;quot;configure&amp;quot;, as the BLFS project recommends.  &lt;/P&gt; &lt;P&gt;It took me about a month to build a basic GNOME desktop in my spare time. Disappointingly, you don't see anything until the last piece, &amp;quot;gnome-session&amp;quot;, is in place.  &lt;/P&gt; &lt;P&gt;When I ran my first applications like the image-viewer &amp;quot;eye-of-gnome&amp;quot;, some appeared on the desktop and then core-dumped. The core file said the last function called was in GTK, in the libgtk-x11 library. I had had to upgrade my GTK when building gnome-panel. I had chosen the latest version 2.15.2. This is probably a development releases too. When I switched back to my year-old GTK, everything was fine. I finally settled for the stable version recommended by GARNOME. It took me a few days to sort this out!  &lt;/P&gt; &lt;P&gt;There is a free book on programming GNOME, &amp;quot;GTK+ / Gnome Application Development&amp;quot; by Havoc Pennington available at &lt;A HREF="http://developer.gnome.org/doc/GGAD"&gt;http://developer.gnome.org/doc/GGAD&lt;/A&gt;. This is somewhat old.  &lt;/P&gt; &lt;P&gt;Overall, I like GNOME because it is truly free and lighter than KDE.  &lt;/P&gt; &lt;H3 CLASS="western"&gt;GNOME versus KDE&lt;/H3&gt; &lt;P&gt;Last year (2008), I built the 4.0 release of &lt;A HREF="http://www.kde.org/"&gt;KDE&lt;/A&gt; from the source files. GNOME is made up of around sixty packages, KDE about twenty. &lt;A HREF="http://www.qtsoftware.com/"&gt;Qt&lt;/A&gt; (the user interface framework) and KDE are much larger than GNOME. The compressed source of Qt is about three times the size of the equivalent GTK+, GLib, Cairo and Pango put together. But, of course, KDE includes the web browser Konqueror. GNOME needs the Gecko layout engine from Mozilla.org that you see in Firefox.  &lt;/P&gt; &lt;P&gt;Qt and KDE's C++ code is slower to compile than GNOME's C, at least on my old laptop - a Pentium III with only 128 Meg RAM! KDE uses &lt;A HREF="http://www.cmake.org/"&gt;CMake&lt;/A&gt; rather than &amp;quot;configure&amp;quot; to generate the makefiles. It took a while to learn how to use CMake, but its files are much clearer.  &lt;/P&gt; &lt;P&gt;The BLFS instructions only covered KDE 3.5, so I had to adjust things for KDE 4.0. In GNOME, if you wanted to find out where to find some unusual packages, you could look at the makefiles of the GARNOME project. Its website is at  &lt;A HREF="http://projects.gnome.org/garnome"&gt;http://projects.gnome.org/garnome&lt;/A&gt;. GARNOME automatically fetches and builds a given GNOME release.  &lt;/P&gt; &lt;P&gt;For KDE, I had to change a little code when building the  &lt;A HREF="http://en.wikipedia.org/wiki/Strigi_(KDE)"&gt;&amp;quot;strigi&amp;quot;&lt;/A&gt; library. (It searches through files for the semantic desktop). To be exact, I had to add definitions for &amp;quot;__ctype_b&amp;quot; and &amp;quot;wstring&amp;quot;. For GNOME, it was easier. I mostly had to go off and find required libraries that were not in the BLFS notes.  &lt;/P&gt; &lt;P&gt;KDE has trouble starting up on my laptop, although it is all right on my PC. There is a lot of swapping in and out and thrashing with my low memory. In fact, both computers have 128 Megabytes. The laptop even has a faster processor. It has a Pentium III processor whereas than the PC has a Pentium II. The disks even seem about the same speed in simple tests. It is a puzzle. Anyway, KDE takes over ten minutes to start on my laptop! GNOME takes one minute. (KDE takes just over a minute on my PC.)  &lt;/P&gt; &lt;H3 CLASS="western"&gt;Browsers&lt;/H3&gt; &lt;P&gt;On KDE, I could get the Konqueror browser running fairly easily. But I had to add about 250 Meg of swap space to get the WebKit library to link with the low memory on my PC. WebKit is the rendering engine. I like the way Konqueror uses many of the same libraries as other parts of KDE. It makes Konqueror a bit lighter when running inside of KDE. (I have put the commands I use to add swap at the &lt;A HREF="#scmds"&gt;end&lt;/A&gt;).  &lt;/P&gt; &lt;P&gt;With &lt;A HREF="http://www.mozilla.com/firefox"&gt;Firefox 3&lt;/A&gt;, I had to turn the compiler optimization off with the &amp;quot;-O0&amp;quot; switch to avoid thrashing with the small memory on my old laptop. I also had to leave out a lot of the components in &amp;quot;libxul&amp;quot;. Otherwise the link of libxul ends up just swapping in and out as well. (I understand XUL is the toolkit used to build the user interface of Mozilla). Firefox does not work without a real libxul though.  &lt;/P&gt; &lt;P&gt;I thought I would try building GNOME's own browser -  &lt;A HREF="http://projects.gnome.org/epiphany"&gt;Epiphany&lt;/A&gt;. But I had trouble configuring it to use the Gecko rendering libraries in the Mozilla Firefox 3 browser I had just built. Epiphany offers a simpler interface than Firefox and concentrates just on web browsing, taking features like mail from other GNOME applications. Unfortunately Epiphany seems to expect &amp;quot;pkg-config&amp;quot; entries for Gecko, which Firefox 3 had not generated. (When you install a library, a file in /usr/lib/pkgconfig is created, listing the compiler flags (-L, -l and -I) needed by a program using the library.)  I manually added in all the Firefox shared libraries I could find. But there seemed to be some core Firefox functions that Epiphany still could not access. However, Epiphany does really recommend Firefox 2. But Firefox 2 uses a lot of deprecated functions in my more modern version of Cairo. I got lost in all the errors.  &lt;/P&gt; &lt;P&gt;Then I noticed that Epiphany's web page mentions an  &lt;A HREF="http://live.gnome.org/WebKitGtk"&gt;experimental version&lt;/A&gt; using &lt;A HREF="http://www.webkit.org/"&gt;WebKit&lt;/A&gt; as the browser engine. But the configuration seemed to have incomplete autoconf/automake files and use the Apple xcodebuild tool. It was too difficult for me. You can begin to see there is some skill required to build a complete distribution!  &lt;/P&gt; &lt;P&gt;I later learnt from a GNOME  &lt;A HREF="http://blogs.gnome.org/otte/2009/03/03/browsing-in-gnome"&gt;blog&lt;/A&gt; that the Mozilla version of Epiphany is not actively developed any more, because about a year ago GNOME started to switch to WebKit. But the switch has not been completed. It was originally scheduled to be delivered with GNOME 2.26, but has been postponed to GNOME 2.28. I remembered that WebKit is a fork of KDE's KHTML browser engine used by Konqueror. It was made by Apple for their Safari browser, and more recently used by Google in its Chrome browser.  &lt;/P&gt; &lt;P&gt;In the end, I built the &lt;A HREF="http://www.dillo.org/"&gt;Dillo&lt;/A&gt; browser. It used to use GTK and Glib. But it now uses the  &lt;A HREF="http://www.fltk.org/"&gt;FLTK&lt;/A&gt; (Fast Light Tool Kit) - a C++ GUI toolkit. Of course, it does not support Javascript or Java.  &lt;/P&gt; &lt;P&gt;Strangely enough, Konqueror runs quite well within GNOME! I think I will use it when developing complicated web pages which use Javascript and AJAX.  &lt;/P&gt; &lt;H3 CLASS="western"&gt;Problems compiling packages&lt;/H3&gt; &lt;P&gt;Would you enjoy building programs from the source tarballs?  I think you probably need some knowledge of C.  Not too much, as I didn't know a lot about C++ when I built KDE.  There always seem to be a few problem with compiling packages.  Here are a few to give you an idea.  &lt;/P&gt; &lt;P&gt;A simple problem occurred when I was building the &amp;quot;dbus-glib-bindings&amp;quot; package:  &lt;/P&gt; &lt;PRE class="code"&gt;DBUS_TOP_BUILDDIR=.. dbus-send --system --print-reply=literal --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.Introspectable.Introspect &amp;gt; dbus-bus-introspect.xml.tmp &amp;amp;&amp;amp; mv dbus-bus-introspect.xml.tmp dbus-bus-introspect.xml Failed to open connection to system message bus: Failed to connect to socket /usr/local/var/run/dbus/system_bus_socket: Connection refused&lt;/PRE&gt;&lt;P&gt; I guessed it wanted the dbus system bus running. I remembered something from building D-Bus last year, had a look around, and ran &amp;quot;dbus-daemon --system&amp;quot;.  &lt;/P&gt; &lt;P&gt;A typical problem was with gnome-terminal. It included the &amp;quot;dbus-glib-bindings.h&amp;quot; header file which itself included the glib header &amp;quot;glib-2.0/glib/gtypes.h&amp;quot;. But glib did not want its header file directly included and had put a &amp;quot;#error&amp;quot; statement in to give a warning. I solved this by crudely commenting out the #error.  &lt;/P&gt; &lt;P&gt;The strangest problem I got was when running GStreamer's configure script:  &lt;/P&gt; &lt;PRE class="code"&gt;    ./configure: line 32275: syntax error near unexpected token `('     ./configure: line 32275: `  for ac_var in `(set) 2&amp;gt;&amp;amp;1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do'&lt;/PRE&gt;&lt;P&gt; I tried narrowing it down by putting in some simple echo statements and then I changed some back ticks to the more modern &amp;quot;$()&amp;quot;. But, I had the same problem with the GStreamer Plugins package. So I decided to upgrade my version of Bash, which was a year old. The LFS project suggests using the &amp;quot;malloc&amp;quot; (memory allocation) from the libc library rather than that bundled with Bash, so I also ran configure with the option &amp;quot;--without-bash-malloc&amp;quot;. All this luckily fixed the problem.  &lt;/P&gt; &lt;P&gt;Out of interest, I have added the commands I typed (over sixty times) to build the packages, at the &lt;A HREF="#bcmds"&gt;end&lt;/A&gt; of this article.  &lt;/P&gt; &lt;H3 CLASS="western"&gt;GNOME libraries&lt;/H3&gt; &lt;P&gt;I enjoy reading about the libraries as I build them. I also wanted to draw a diagram showing which packages needed to be built first.  &lt;/P&gt; &lt;P&gt;The libraries are, in fact, described very well in the GNOME documentation at  &lt;A HREF="http://library.gnome.org/devel/platform-overview"&gt;http://library.gnome.org/devel/platform-overview&lt;/A&gt;. &lt;/P&gt; &lt;P&gt;The libraries shown below are used in various combinations by the GNOME applications you see on the desktop.  &lt;/P&gt; &lt;P&gt;My diagrams show the dependencies between packages. For example GTK requires Pango and Cairo. A package usually generates many libraries, so it is nice to think at the package level. I believe you can generate graphs of dependencies automatically from the GNOME build systems.  &lt;/P&gt; &lt;P&gt;I have included some notes that I found in the README file or documentation that came with the packages.  &lt;/P&gt; &lt;P&gt;I did not build most of the audio or video libraries, as I don't play music or watch videos on my laptop! It also keeps things simple. &lt;/P&gt; &lt;H4 CLASS="western"&gt;Base libraries&lt;/H4&gt; &lt;PRE&gt;       /|\                 /|\         +-------------------+         |       pygtk       |         |      pycairo      |         |     pygobject     |                        /|\            /| |\         | (python bindings) |          +---- gail ----+  +-----------+ +------+         +-------------------+          |    (GNOME    |  | dbus-glib | |libxml| /|\                                    |accessibility)|  | bindings  | |      |  +----------------------- gtk+ -----------------------+  +-----------+ +------+  |     (GIMP Tool Kit - graphical user interfaces)    |  |   D-Bus   |  |-- pango --+--------+                +---- atk -----+  | (message  |  |(rendering)| libpng |      +---------+(accessibility|  |  passing  |  | of text)  | libjpeg|      | libtiff |  interfaces) |  |  system)  |  +----------------------- cairo ----------------------+  +-----------+  |  (2D graphics library for multiple output devices) |  +------------------+------------ pixman -------------+                     |         (low level pixel        |                     | manipulation, e.g. compositing) |                     +----------------------------------                                                      /|\                               +-------- gvfs ---------+                                |   (backends include   | /|\                           | sftp, smb, http, dav) |   +----------------------- glib -----------------------+   |(data structures, portability wrappers, event loop, |  |threads, dynamic loading, algorithms, object system,|  |GIO - the virtual file system replacing gnome-vfs)  |  +----------------------------------------------------+     &lt;/PRE&gt;&lt;H5 CLASS="western"&gt; Notes&lt;/H5&gt; &lt;P&gt;The GIO library in &lt;A HREF="http://library.gnome.org/devel/glib/stable"&gt;GLib&lt;/A&gt; tries not to clone the POSIX API like the older gnome-vfs package, but instead provides higher-level, document-centric interfaces. The GVFS backends for GIO are run in separate processes, which minimizes dependencies and makes the system more robust. The GVFS package contains the GVFS daemon, which spawns further mount daemons for each individual connection.  &lt;/P&gt; &lt;P&gt;The core &lt;A HREF="http://www.pango.org/"&gt;Pango&lt;/A&gt; layout engine can be used with different font and drawing backends. GNOME uses FreeType, fontconfig, and Cairo. But on Microsoft Windows, Pango can use the native Uniscribe fonts and render with the Win32 API.  &lt;/P&gt; &lt;P&gt;The &lt;A HREF="http://cairographics.org/"&gt;Cairo&lt;/A&gt; documentation says it is &amp;quot;&lt;I&gt;designed to produce consistent output on all output media while taking advantage of display hardware acceleration when available (for example, through the X Render Extension) ... The cairo API provides operations similar to the drawing operators of PostScript and PDF. Operations in cairo include stroking and filling cubic Bezier splines, transforming and compositing translucent images, and antialiased text rendering. All drawing operations can be transformed by any affine transformation (scale, rotation, shear, etc.&lt;/I&gt;&amp;quot;  &lt;/P&gt; &lt;P&gt;&lt;A HREF="http://www.gtk.org/"&gt;GTK+&lt;/A&gt; was first developed as a widget set for the GIMP (GNU Image Manipulation Program). The FAQ mentions one of the original authors, Peter Mattis, saying &amp;quot;&lt;I&gt;I originally wrote GTK which included the three libraries, libglib, libgdk and libgtk. It featured a flat widget hierarchy. That is, you couldn't derive a new widget from an existing one. And it contained a more standard callback mechanism instead of the signal mechanism now present in GTK+. The + was added to distinguish between the original version of GTK and the new version. You can think of it as being an enhancement to the original GTK that adds object oriented features.&lt;/I&gt;&amp;quot; The GTK+ package contains GDK, the GTK+ Drawing Kit, an easy to use wrapper around the standard Xlib function calls for graphics and input devices. GDK provides the same API on MS Windows.  &lt;/P&gt; &lt;P&gt;The &lt;A HREF="http://projects.gnome.org/accessibility"&gt;GAIL&lt;/A&gt; documentation says &amp;quot;&lt;I&gt;GAIL provides an implementation of the ATK interfaces for GTK+ and GNOME libraries, allowing accessibility tools to interact with applications written using these libraries ... ATK provides the set of accessibility interfaces that are implemented by other toolkits and applications. Using the ATK interfaces, accessibility tools have full access to view and control running applications.&lt;/I&gt;&amp;quot; GAIL stands for GNOME Accessibility Implementation Layer. It has just been moved into GTK.  &lt;/P&gt; &lt;P&gt;&lt;A HREF="http://dbus.freedesktop.org/"&gt;D-BUS&lt;/A&gt; is a simple inter process communication (IPC) library based on messages. The documentation says &amp;quot;&lt;I&gt;a core concept of the D-BUS implementation is that 'libdbus' is intended to be a low-level API, similar to Xlib. Most programmers are intended to use the bindings to GLib, Qt, Python, Mono, Java, or whatever. These bindings have varying levels of completeness.&lt;/I&gt;&amp;quot;  &lt;/P&gt; &lt;P&gt;PyGObject allows you to use GLib, GObject and GIO from Python programs.  &lt;/P&gt; &lt;H4 CLASS="western"&gt;Platform libraries&lt;/H4&gt; &lt;PRE&gt;                                                      gnome-icon-theme                                                             /|\                                                       icon-naming-utils                                                (xml to translate old icon names)                   libgnomeui*      (a few extra gui widgets, many now in gtk)                       /|\                        +---------------------------+                        |                           |                   libbonoboui*                gnome-keyring            (user interface controls     (password and secrets daemon              for component framework)     and library interface)                       /|\                          |                        |                        libtasn1                        |               (Abstract Syntax Notation One)                        |                        +--------------------------------------+                        |                                      |                     libgnome*                          libgnomecanvas*     (initialising applications, starting programs,    (structured graphics:      accessing configuration parameters, activating  polygons, beziers, text      files and URI's, displaying help)               pixbufs, etc. Rendered                       /|\                             by Xlib or libart)   +--------------------+----------+                           |   |                               |                          /|\   |  gnome-vfs monikers           |                           |   |   /|\       /|\               |                           |   |    |         +-------- gnome-vfs* (virtual file system)   +----------+   |    |                 (consistent API for local and        |          |   |    |               remote files, cameras, WebDAV, etc)    |          |   |    |                         /|\                          |          |   |    |             +------------+--------+               libglade    libart*   |    |             |                     |            (dynamically   (fast 2d   |    |          Gconf             gnome-mime-data      load glade    graphic   |    |      (configuration           (classify         user        primitives)  libbonobo*     database -            file contents)     interface   (component      daemon &amp;amp;                                description  system, e.g.    library)                                files)  multimedia         /|\  in word processor)  |   /|\                 |   +------------------+    |  ORBit2+ * (fast and light CORBA object broker)    +--- libIDL (parses interface definitions for CORBA)            Note: * indicates library is depreciated&lt;/PRE&gt;&lt;H5 CLASS="western"&gt; Notes&lt;/H5&gt; &lt;P&gt;Many of the libraries on the left hand side of the diagram are not used in newly written code and references to them have been removed in some old code. But the API's are still supported, at least for the current GNOME 2.x series. GNOME is moving to using D-Bus for communication between processes. GNOME Panel applets use Bonobo to communicate with the panel. GnomeVFS has been replaced by GIO, and the GVFS library which supplies the network and local protocols.  &lt;/P&gt; &lt;P&gt;According to the documentation, &amp;quot; &lt;A HREF="http://library.gnome.org/devel/libglade/stable"&gt;&lt;I&gt;Libglade&lt;/I&gt;&lt;/A&gt;&lt;I&gt; is an alternative to using &lt;/I&gt;&lt;A HREF="http://glade.gnome.org/"&gt;&lt;I&gt;Glade's&lt;/I&gt;&lt;/A&gt;&lt;I&gt; code generation. Instead of generating code from the XML interface description, libglade loads and parses the description at runtime. It also provides functions that can be used to connect signal handlers to parts of the interface.&lt;/I&gt;&amp;quot;  &lt;/P&gt; &lt;P&gt;&lt;A HREF="http://www.gnome.org/~mathieu/libart/libart.html"&gt;Libart&lt;/A&gt; is, in its own words, a &amp;quot;sophisticated, antialiased, alpha-compositing engine.&amp;quot;  &lt;/P&gt; &lt;P&gt;The &amp;quot;gnome-keyring&amp;quot; README says it can &amp;quot;&lt;I&gt;manage several keyrings, each with its own master password, and there is also a session keyring which is never stored to disk, but forgotten when the session ends.&lt;/I&gt;&amp;quot;  &lt;/P&gt; &lt;P&gt;According to the Wikipedia,  &lt;A HREF="http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One"&gt;Abstract Syntax Notation One&lt;/A&gt; (ASN.1), is used &amp;quot;&lt;I&gt;in telecoms and computer networking... [and] is a standard and flexible notation that describes data structures for representing, encoding, transmitting and decoding data&lt;/I&gt;&amp;quot;.  &lt;/P&gt; &lt;P&gt;You can read the reference documentation for libbonobo at &lt;A HREF="http://library.gnome.org/devel/libbonobo/stable"&gt;http://library.gnome.org/devel/libbonobo/stable&lt;/A&gt;. Maybe it is worth a skim through to get an overview. There are similar API references for &lt;A HREF="http://library.gnome.org/devel/gconf/stable"&gt;GConf&lt;/A&gt;, &lt;A HREF="http://library.gnome.org/devel/gnome-vfs/stable"&gt;gnome-vfs&lt;/A&gt;, &lt;A HREF="http://library.gnome.org/devel/libgnome/stable"&gt;libgnome&lt;/A&gt;, &lt;A HREF="http://library.gnome.org/devel/libgnomecanvas/stable"&gt;libgnomecanvas&lt;/A&gt;, &lt;A HREF="http://library.gnome.org/devel/libbonoboui/stable"&gt;libbonoboui&lt;/A&gt; and &lt;A HREF="http://library.gnome.org/devel/libgnomeui/stable"&gt;libgnomeui&lt;/A&gt;. &lt;/P&gt; &lt;H4 CLASS="western"&gt;Desktop libraries&lt;/H4&gt; &lt;PRE&gt;gnome-themes   gnome-user-docs   gnome-backgrounds   gnome-terminal      |          (user, admin                        (just the shell:        /|\            guides)                           menubar, prefs dialog)      |               |                                     /|\ gtk-engines    gnome-doc-utils                              |    (themes)     (xslt for Docbook                            vte                 and translations)                    (terminal emulator                                                  widget implemented in GTK)                                     gnome-session                                          |                                     control-center                                         /|\  +----+----------------+-----------------+------------+------------+   |    |                |                 |            |            |  | gnome-applets  metacity  nautilus (file manager)   |        gstreamer  |   (for panel)  (window         |      |       |    |         plugins   |    |     |     manager)       /|\  libexif librsvg |            |  |   /|\ libgtop       |          |  (digital  (fast  |     +------+------+       |    |  (portable     zenity     |   cameras)  SVG)  |     |             |   |    | performance   (dialogs    |              |    |    gstreamer   liboil   |    |  statistics    in         |      +-------+   /|\  (sound &amp;amp;    (optimized  |    |  library       scripts)   | libcroco  libgsf  |    video)    inner loops /|\   |  and server)              | (CSS2     (structured                  using  |    |                           | parser)    files) |                 assembly  |    |                           |                   +--+-------+     MMX, SSE)  |    |                           |                      |       |  | gnome-panel        eel (nautilus widgets, extensions) |  libgnomekdb  |    |     |           /|\                        |     |      /|\  |    |     +-------+----+                      gnome-menus      |  |    |             |                           (engine)    libxklavier  | libwnck          |                                   (accessing &amp;amp; setting  | (library for window management e.g. workspace          keyboard layouts)       |                  |       pagers and tasklists)               /|\  +--------+---------+                                            |            |                                                   isocodes      gnome-desktop                                     (list of country, language (functions for background, monitor, thumbnails,           and currency names)  desktop items, and gnome-about. Icon files)&lt;/PRE&gt;&lt;H5 CLASS="western"&gt; Notes&lt;/H5&gt; &lt;P&gt;Remember the diagram shows the dependencies. For example, some of the features in the GNOME control panel are implemented in Metacity, such as changing the window border theme, or window navigation shortcuts.  &lt;/P&gt; &lt;P&gt;Libgnome-desktop contains APIs that really belong in libgnome(ui) or GTK+ but are limited in their use. It provides support for desktop backgrounds, monitor configuration, thumbnails, and desktop items.  &lt;/P&gt; &lt;P&gt;&lt;A HREF="http://live.gnome.org/RoadMap/Libwnck"&gt;Libwnck&lt;/A&gt; is the Window Navigator Construction Kit. It uses the Extended Window Manager Hints specification (EWMH).  &lt;/P&gt; &lt;P&gt;The documentation for &amp;quot;eel&amp;quot; says &amp;quot;&lt;I&gt;The Eazel Extensions Library is a collection of widgets and extensions to many modules of the GNOME platform. These widgets and extensions were developed by hackers working on Nautilus.&lt;/I&gt;&amp;quot;  &lt;/P&gt; &lt;P&gt;The &amp;quot;gnome-menus&amp;quot; package contains an implementation of the draft &amp;quot;Desktop Menu Specification&amp;quot; from freedesktop.org.  &lt;/P&gt; &lt;P&gt;The README for &lt;A HREF="http://sourceforge.net/projects/libexif"&gt;&amp;quot;libexif&amp;quot;&lt;/A&gt; says it &amp;quot;contains a library for parsing, editing, and saving EXIF data. Most digital cameras produce EXIF files, which are JPEG files with extra tags that contain information about the image ... It is intended to replace lots of redundant implementations in command-line utilities and programs with GUIs.&amp;quot;  &lt;/P&gt; &lt;P&gt;&lt;A HREF="http://librsvg.sourceforge.net/"&gt;Librsvg&lt;/A&gt; is a high performance SVG rendering. It can draw a SVG to a Cairo surface or render SVGs into GDK pixbufs for easy use in GTK+ applications. Librsvg is not used by the very latest Nautilus code, but is part of other GNOME applications.  &lt;/P&gt; &lt;P&gt;The README file for  &lt;A HREF="http://www.freespiders.org/projects/libcroco"&gt;&amp;quot;libcroco&amp;quot;&lt;/A&gt; says it is a &amp;quot;&lt;I&gt;standalone css2 parsing and manipulation library. The parser provides a low level event driven SAC (Simple Api for CSS) like api and a css object model like api. Libcroco provides a CSS2 selection engine and an experimental xml/css rendering engine.&lt;/I&gt;&amp;quot;  &lt;/P&gt; &lt;P&gt;The documentation for &lt;A HREF="http://directory.fsf.org/project/libgsf"&gt;&amp;quot;libgsf&amp;quot;&lt;/A&gt; says the &amp;quot;&lt;I&gt;GNOME Structured File Library (GSF) is an I/O abstraction for reading/writing compound files... GSF was written as part of the Gnumeric project. It started in 2002 as a replacement for libole2 which Gnumeric was using to handle the Microsoft Excel&lt;/I&gt;&amp;quot;. It reads gzip, bz2, zip, XML and OASIS Open Document formats amongst others.  &lt;/P&gt; &lt;P&gt;According to its home page, &lt;A HREF="http://www.schleef.org/liboil"&gt;&amp;quot;Liboil&amp;quot;&lt;/A&gt; “&lt;I&gt;is a library of simple functions that are optimized for various CPUs. These functions are generally loops implementing simple algorithms, such as converting an array of N integers to floating-point numbers or multiplying and summing an array of N numbers ... The goal of this project is to consolidate some of the code used by various multimedia projects, and also make optimizations easier to use by a broader range of applications.&lt;/I&gt;&amp;quot;  &lt;/P&gt; &lt;P&gt;The &amp;quot;gnome-applets&amp;quot; package includes the libpanel-applet library which allows you to develop small applications which can be embedded in the panel.  &lt;/P&gt; &lt;P&gt;On systems like BSD and Solaris,  &lt;A HREF="http://library.gnome.org/devel/libgtop/stable"&gt;&amp;quot;libgtop&amp;quot;&lt;/A&gt; provides a setgid/setuid server for graphical tools. On Linux, libgtop has a library that gives performance information in a generic way to the differents tools that use it such as &amp;quot;gtop&amp;quot; and panel applets.  &lt;/P&gt; &lt;P&gt;In the &lt;A HREF="http://projects.gnome.org/nautilus"&gt;Nautilus&lt;/A&gt; architecture document it says &amp;quot;&lt;I&gt;Nautilus is a general-purpose shell application for browsing arbitrary content. It is implemented as `nautilus', a container application which exercises overall control and provides chrome, and a number of nautilus view components. These view components may use the `libnautilus' library to ease implementation.&lt;/I&gt;&amp;quot;  &lt;/P&gt; &lt;P&gt;&lt;A HREF="http://gstreamer.freedesktop.org/"&gt;Gstreamer&lt;/A&gt;, of course, is a framework for streaming media. According to the documentation, &amp;quot;&lt;I&gt; It's based on plug-ins that will provide the various codec and other functionality ... Is GStreamer a media player ? No, GStreamer is a development framework for creating applications like media players, video editors, streaming media broadcasters and so on. That said, very good media players can easily be built on top of GStreamer&lt;/I&gt;&amp;quot;.  &lt;/P&gt; &lt;P&gt;&lt;A HREF="http://library.gnome.org/devel/vte/stable"&gt;VTE&lt;/A&gt; can also be used to embed a console/terminal in games, editors, IDEs, etc. VTE supports Unicode and character set conversion, as well as emulating any terminal known to the system's terminfo database.  &lt;/P&gt; &lt;P&gt;The author of &lt;A HREF="http://en.wikipedia.org/wiki/Metacity"&gt;Metacity&lt;/A&gt; says it is a &amp;quot;&lt;I&gt;boring window manager for the adult in you. Many window managers are like Marshmallow Froot Loops; Metacity is like Cheerios ... includes only the window manager; does not try to be a desktop environment. The pager, configuration, etc. are all separate and modular.&lt;/I&gt;&amp;quot; According to Wikipedia, GNOME used the Enlightenment window manager and then Sawfish before choosing Metacity. Apparently, it is aimed at new computer users that do not need the extreme configurability offered by its predecessors.  &lt;/P&gt; &lt;H3 CLASS="western"&gt;&lt;A NAME="bcmds"&gt;&lt;/A&gt;Build commands&lt;/H3&gt; &lt;P&gt;First I look at the README file in the package directory. Then I check if the INSTALL file is anything but the standard one, using &amp;quot;head&amp;quot;.  &lt;/P&gt; &lt;PRE class="code"&gt;set -b     # so bash tells me when jobs finish  configure --help=short 2&amp;gt;&amp;amp;1 | less    # shows options specific to package  configure &amp;gt;myconf01.lst 2&amp;gt;&amp;amp;1 &amp;amp;        # usually installs into /usr/local -                                       # unless you add a --prefix=/mydir option # have a look at the log file, - # especially the end  make &amp;gt;mymake01.lst 2&amp;gt;&amp;amp;1 &amp;amp; # at the start, &amp;quot;tail -f&amp;quot; the log file - # to make sure the compiler options are OK  make install &amp;gt;mymakeinst01.lst 2&amp;gt;&amp;amp;1 &amp;amp; # you may need to be root, of course. # look at the log file to see where the binaries are put, what are the actual # names of the libraries installed, and where to find the documentation&lt;/PRE&gt;&lt;H3 CLASS="western"&gt; &lt;A NAME="scmds"&gt;&lt;/A&gt;Commands to add swap&lt;/H3&gt; &lt;P&gt;Adding swap lets you pretend you have more memory. I did not know how to do this when I started!  &lt;/P&gt; &lt;PRE class="code"&gt;# run as root dd if=/dev/zero of=swap1 bs=1024 count=100k   # 100 Meg mkswap swap1 swapon swap1&lt;/PRE&gt;&lt;P&gt; Sometimes the program really is too big and the PC will just swap files in and out all the time. I can see the laptop is &amp;quot;thrashing&amp;quot; simply by the hard-disk light staying on! I also use the &amp;quot;&lt;CODE&gt;vmstat 5&lt;/CODE&gt;&amp;quot; command. It reports every five seconds. The CPU will be waiting for IO to finish most of the time. The &amp;quot;cpu wa&amp;quot; column will be high, say 97%. The program will not have much time to run, with a low &amp;quot;user time&amp;quot; for my non-kernel code. The &amp;quot;cpu us&amp;quot; column might say 3%. You can see the amount of blocks read and written rising in the &amp;quot;IO bi bo&amp;quot; columns. (The first line produced by &lt;CODE&gt;vmstat&lt;/CODE&gt; gives averages since the system booted.)  &lt;/P&gt; &lt;P&gt;Good luck!  &lt;/P&gt;  &lt;br clear="all" /&gt;  &lt;script type='text/javascript'&gt; digg_url = 'http://linuxgazette.net/164/laycock.html'; digg_title = 'Building the GNOME Desktop from Source'; digg_bodytext = '&lt;P&gt;First, I must say that the &lt;A HREF="http://www.gnome.org/"&gt;GNOME&lt;/A&gt; documentation &amp;quot;strongly recommends&amp;quot; against building from source files. If you do, it suggests using the GARNOME scripted system. Even GARNOME it says, is only for the &amp;quot;brave and patient&amp;quot;.  &lt;/P&gt; '; digg_topic = 'linux_unix'; &lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt; 
</description>
</item>
<item rdf:about="http://linuxgazette.net/164/prestia.html">
<title>Joey's Notes: VSFTP FTP server on RHEL 5.x</title>
<link>http://linuxgazette.net/164/prestia.html</link>
<dc:creator>Joey Prestia</dc:creator>
<dc:date>Wed, 01 Jul 2009 22:07:56 -0500</dc:date>
<description>By &lt;strong&gt;Joey Prestia&lt;/strong&gt;
&lt;br&gt;
&lt;p&gt; File Transfer Protocol (FTP) utilizes Transmission Connection Protocol (TCP)  communication and listens on port 21 for incoming client connections by  default. The connection to this port from the FTP client will form the control  stream from which commands are passed from the FTP client to the FTP server  and on occasion from the FTP server to the FTP client. FTP uses a separate  connection for control and data. So for the actual file transfer to take place,  a different connection is required which is called the data stream. Depending  on the transfer mode, the process of setting up the data stream is different.  Port 21 for control, port 20 for data. &lt;/p&gt; 
</description>
</item>
<item rdf:about="http://linuxgazette.net/164/sephton.html">
<title>Understanding Full Text Search in PostgreSQL</title>
<link>http://linuxgazette.net/164/sephton.html</link>
<dc:creator>Paul Sephton</dc:creator>
<dc:date>Wed, 01 Jul 2009 22:07:56 -0500</dc:date>
<description>By &lt;strong&gt;Paul Sephton&lt;/strong&gt;
&lt;br&gt;
&lt;P&gt;Those who have yet to enter their first search query in Google, Yahoo, or any of the myriad of other search engines available to the web, or have no interest in the use of PostgreSQL as a database engine to implement their own text search facility will find little use in reading further.&lt;/P&gt; &lt;P&gt;Although PostgreSQL coverage on the topic of Free Text Search is as good as the rest of their excellent documentation, the following might serve as an introduction to those who would further persue the topic.  In the interest of conciseness, this article skips quite a lot of detail and depends on the ability of the reader to infer what is not explicitly stated.&lt;/P&gt; &lt;h3&gt;Introduction&lt;/h3&gt; &lt;P&gt;Full Text Search (or FTS) is not a new technology. The earliest recorded patents related to the search for documents about a given topic were filed in the year 1963, more than forty-five years ago. These patents include &amp;quot;&lt;I&gt;CONTENT ADDRESSABLE MEMORY APPARATUS&lt;/I&gt;&amp;quot; (US Pat. 3290659 - Filed Dec 30, 1963), &amp;quot;&lt;I&gt;SCAN CONTROL, AND NORMALIZATION FOR A CHARACTER RECOGNITION SYSTEM&lt;/I&gt;&amp;quot; (US Pat. 3295105 - Filed Aug 27, 1964) and &amp;quot;&lt;I&gt;INFORMATION RETRIEVAL SYSTEM AND METHOD&lt;/I&gt;&amp;quot; (US Pat. RE26429 - Filed Dec 8, 1964).&lt;/P&gt; &lt;P&gt;To this day, the ability to impose structure upon the dearth of what is known as &amp;quot;Unstructured Data&amp;quot;, in order to turn this haystack into an information system, continues to challenge the finest minds.&lt;/P&gt; &lt;P&gt;The long list of granted patents persists through 2006 and 2007, namely &amp;quot;&lt;I&gt;Device and system for information management&lt;/I&gt;&amp;quot; (US Pat. 7376273 - Filed Jun 1, 2007 - Silverbrook Research Pty Ltd), &amp;quot;&lt;I&gt;Metasearching by sending a plurality of queries to a plurality of servers&lt;/I&gt;&amp;quot; (US Pat. 7277918 - Filed Jan 16, 2007) and &amp;quot;&lt;I&gt;Distributed internet based speech recognition system with natural language ...&lt;/I&gt;&amp;quot; (US Pat. 7203646 - Filed May 22, 2006 - Phoenix Solutions, Inc.)&lt;/P&gt; &lt;P&gt;Of course, we know today that &amp;quot;Full Text Search&amp;quot; is far from the only way to organise documents. A close runner up, though unable to reproduce the exact features of FTS, is the Bayesean search; a statistical means of indexing documents which determines the probabability that two documents are similar. Bayesean search has an almost uncanny knack of deriving the essence of documents rather than depending on a literal text match. The most common use of Bayesean search technology today is in spam filters, although engines such as &lt;A HREF="http://www.altsearchengines.com/2009/05/06/hope-dyves-deep-in-her-review-of-deepdyve/"&gt;DeepDyve&lt;/A&gt; demonstrates a more ambitious use.&lt;/P&gt; &lt;P&gt;Several SQL databases already have a built-in implementation of FTS, notably servers such as Oracle, SQL Server, and the free MySQL and PostgreSQL servers.  &lt;/P&gt; &lt;P&gt;MySQL native FTS is currently only available against the MyISAM database back-end, and is not yet available for the more popular InnoDB back-end. For Postgres, the earliest implementation of FTS was the TSearch module, replaced in version 7.4 with Tsearch2, and finally included in the core PostgreSQL engine in version 8.3.  &lt;/P&gt; &lt;P&gt;There are many implementations of external FTS engines which may be used in conjunction with SQL database engines, or individually. These include &lt;A HREF="http://lucene.apache.org/"&gt;Lucene&lt;/A&gt;, which is a very powerful and popular engine implemented as part of the Apache project, &lt;A HREF="http://swish-e.org/"&gt;Swish-E&lt;/A&gt;, and the &lt;A HREF="http://sphinxsearch.com/"&gt;Sphynx&lt;/A&gt; search engine, which has been steadily gaining in popularity.&lt;/P&gt; &lt;P&gt;Lucene is really a library against which programmers may develop search products. Their site has many links to generic products already developed against the library, including interfaces for Java (the original interface), PHP and DotNet. Sphynx is particularly popular amongst MySQL developers, as this engine supports both MyISAM as well as InnoDB database back-ends.&lt;/P&gt; &lt;h3&gt;PostgreSQL Full Text Search&lt;/h3&gt; &lt;P&gt;In a nutshell, Full Text Search is implemented by indexing the words contained in a document, and associated the indexed words with a reference to the document. Subsequently, searches for a  &lt;A HREF="http://www.iqlue.com/prosearch/topics/Boolean Phrase.htm"&gt;&lt;I&gt;boolean phrase&lt;/I&gt;&lt;/A&gt; using operators &lt;I&gt;and&lt;/I&gt;, &lt;I&gt;or&lt;/I&gt;, &lt;I&gt;not&lt;/I&gt; and braces may be matched against the index to locate documents containing the words in the phrase.  PostgreSQL does not currently support the fuzzy logic operators &lt;I&gt;near&lt;/I&gt;, &lt;I&gt;far&lt;/I&gt; or &lt;I&gt;strip&lt;/I&gt;.&lt;/P&gt; &lt;H3&gt;Eliminating redundancy&lt;/H3&gt; &lt;P&gt;Clearly, indexing every single word in a document would result in a very large index. This is neither required, nor is it particularly useful. For example, one might convert all text to lower case prior to indexing the words, making your searches insensitive to case, and simultaneously achieving a smaller index. Then one might eliminate words from the text which carry no real meaning (like 'and', 'or', 'the', 'for', etc.) as these words would be likely found in most documents already. The first approach is called &lt;I&gt;normalisation&lt;/I&gt;, and the second process is called &lt;I&gt;stop word elimination&lt;/I&gt;.&lt;/P&gt; &lt;P&gt;Finally, one might further reduce the size of the index by replacing words with others which have an identical or similar meaning. Thus one may replace instances of 'hungrily' and 'hungry' with 'hunger'. This process is called &lt;I&gt;dictionary substitution&lt;/I&gt;. &lt;/P&gt; &lt;P&gt;Further algorithmic measures (see &lt;A HREF="http://snowball.tartarus.org/"&gt;Snoball&lt;/A&gt;)[Ref. 4] may be performed to further reduce words to their essential meaning prior to the article being indexed. The replacement of colour names with their hexadecimal equivalents and the reduction of numeric values by reducing precision are other ways of &lt;I&gt;normalising&lt;/I&gt; the text.&lt;/P&gt; &lt;P&gt;All of these measures are to eliminate &lt;I&gt;redundancy&lt;/I&gt; from the indexed text, thereby reducing index size and resulting in less storage requirement, less disk I/O, faster indexing and a consequently faster search.&lt;/P&gt; &lt;H3&gt;PostgreSQL Dictionaries&lt;/H3&gt; &lt;P&gt;To aid in the process of normalisation and elimination of redundancy from text, PostgreSQL provides templates for several types of dictionary for use in a text search configuration. These are the Simple Dictionary, the Synonym Dictionary, the Thesaurus Dictionary, the iSpell Dictionary and the Snoball [Ref.4] Dictionary.&lt;/P&gt; &lt;P&gt;The Simple Dictionary eliminates stop words, and performs case normalisation. The Synonym Dictionary replaces one word with another, Thesaurus Dictionaries provide for industry specific phrase recognition, and the iSpell template may be used to embed any of the standard iSpell dictionaries available from &lt;A HREF="http://www.openoffice.org/"&gt;OpenOffice.Org&lt;/A&gt;. The Snoball[Ref.4] dictionaries, which perform algorithmic stemming and stop word elimination are included by default for a variety of languages in the PostgreSQL installation.&lt;/P&gt; &lt;P&gt;With PostgreSQL, all dictionaries are functionally equivalent, with the possible exception of the thesaurus type. Effectively, they consume a word (or token), and return an array of &lt;I&gt;lexemes&lt;/I&gt;, or NULL. When a dictionary returns NULL, the token is considered to be unrecognised. This allows dictionaries to be strung together, with the most general dictionary at the end of the list. Thus, if a dictionary earlier in the list returns a word, further dictionaries in the list are ignored. However, where an earlier dictionary returns NULL, the token is processed by subsequent dictionaries in the list.&lt;/P&gt; &lt;P&gt;A &lt;I&gt;lexeme&lt;/I&gt; is the equivalent of a token which has been converted to it's base form. Before being passed to the dictionary, PostgreSQL converts the &lt;I&gt;document text&lt;/I&gt; into an array of tokens through means of a simple parser. The parser is able to identify various types of tokens from the text, such as XML or HTML tags, integer or floating point numbers, version numbers, URL's, host names and so forth. PostgreSQL provides the ability to process different token types specifically, by mapping a given token type to different dictionary lists.&lt;/P&gt; &lt;H3&gt;Text Search Configuration&lt;/H3&gt; &lt;P&gt;Note that although PostgreSQL provides a lot of configurability, the base installation already provides a workable configuration. Unless there is a specific reason, it is probably not necessary to mess with it. Even so, an example text search configuration would be the following:&lt;/P&gt; &lt;PRE STYLE="margin-bottom: 0.5cm"&gt;CREATE TEXT SEARCH CONFIGURATION public.my_config (COPY=pg_catalog.english );&lt;/PRE&gt;&lt;P&gt; Now, having a new text search configuration, we can create a new dictionary:&lt;/P&gt; &lt;PRE&gt;CREATE TEXT SEARCH DICTIONARY english_ispell (     TEMPLATE = ispell,     DictFile = english,     AffFile = english,     StopWords = english );&lt;/PRE&gt;&lt;P&gt; In the above, we created a dictionary based on the iSpell template, where DictFile, AffFile and StopWords refer to files in the &lt;I&gt;`pg_config –share`\tsearch_data\&lt;/I&gt; directory, called &lt;I&gt;english.dict&lt;/I&gt;, &lt;I&gt;english.affix&lt;/I&gt;, and &lt;I&gt;english.stop&lt;/I&gt; respectively.&lt;/P&gt; &lt;P&gt;We can then add this dictionary into a configuration like this:&lt;/P&gt; &lt;PRE&gt;ALTER TEXT SEARCH CONFIGURATION my_config     ALTER MAPPING FOR asciiword, asciihword, hword_asciipart,                       word, hword, hword_part     WITH english_ispell, english_stem;&lt;/PRE&gt;&lt;P&gt; This adds our new dictionary to our new text search configuration, overriding the default &lt;I&gt;lexeme&lt;/I&gt; types (asciiword etc.) to ensure that they are processed through both the &lt;I&gt;english_ispell&lt;/I&gt; and &lt;I&gt;english_stem&lt;/I&gt; dictionaries. We can then start using our new text search configuration by changing the global parameter &lt;I&gt;default_text_search_config&lt;/I&gt;:&lt;/P&gt; &lt;PRE STYLE="margin-bottom: 0.5cm"&gt;SET default_text_search_config = 'public.my_config';&lt;/PRE&gt;&lt;P&gt; The above parameter will apply for the duration of the session, or until it is changed. To make the configuration permanent, one would need to set it in the &lt;I&gt;data/postgresql.conf&lt;/I&gt; file.&lt;/P&gt; &lt;H3&gt;Search Vectors&lt;/H3&gt; &lt;P&gt;All of this is very impressive, but how does one turn document content into an array of lexemes using the parser and dictionaries? How does one match a search criterion ti body text?  PostgreSQL provides a number of functions to do this. The first one we will look at is &lt;I&gt;to_tsvector()&lt;/I&gt;.&lt;/P&gt; &lt;P&gt;A &lt;I&gt;tsvector&lt;/I&gt; is an internal data type containing an array of lexemes with position information. The lexeme positions are used when searching, to &lt;I&gt;rank&lt;/I&gt; the search result based on proximity and other information. One may control the ranking by labelling the different portions which make up the search document content, for example the title, body and abstract may be weighted differently during search by labelling these sections differently. The section labels, quite simply A,B,C &amp;amp; D, are associated with the &lt;I&gt;tsvector&lt;/I&gt; at the time it is created, but the weight modifiers associated with those labels may be controlled after the fact.&lt;/P&gt; &lt;P&gt;We can create a tsvector for text like this:&lt;/P&gt; &lt;PRE&gt;bob=# select to_tsvector('Free text seaRCh is a wonderful Thing');                      to_tsvector                       ------------------------------------------------------  'free':1 'text':2 'thing':7 'search':3 'wonderful':6 (1 row)&lt;/PRE&gt;&lt;H3&gt; Assigning Weight Labels&lt;/H3&gt; &lt;P&gt;As may be seen, the tsvector is just a list of &lt;I&gt;lexemes&lt;/I&gt; with associated positions. The stop words such as 'a' and 'is' have been eliminated, and we have everything in lower case. Another example, adding labels:&lt;/P&gt; &lt;PRE&gt;bob=# select setweight(to_tsvector('Free text seaRCh is a wonderful Thing'),'A');                          setweight                          -----------------------------------------------------------  'free':1A 'text':2A 'thing':7A 'search':3A 'wonderful':6A (1 row)&lt;/PRE&gt;&lt;P&gt; &lt;BR&gt;&lt;BR&gt; &lt;/P&gt; &lt;P&gt;In essence, one may create a new tsvector with lexemes labeled for different sections of the text using setweight for the various sections:&lt;/P&gt; &lt;PRE&gt;bob=# select                                                                   bob-# setweight(to_tsvector('All about search'), 'B') || bob-# setweight(to_tsvector('Free text seaRCh is a wonderful Thing'),'A');                            ?column?                             ---------------------------------------------------------------  'free':4A 'text':5A 'thing':10A 'search':3B,6A 'wonderful':9A (1 row)&lt;/PRE&gt;&lt;P&gt; Assuming &amp;quot;All about search&amp;quot; was the title, and &amp;quot;Free text seaRCh is a wonderful Thing&amp;quot; was the body, we have now labelled the lexemes from the title, together with those from the body. Note that the word 'All' and 'About' in the title were both considered to be stop words. Subsequently, one may use the labels to rank the results depending on weight labelss associated with the title and body. We will visit this in more detail later.&lt;/P&gt; &lt;H3&gt;Matching Boolean Search Phrases&lt;/H3&gt; &lt;P&gt;But first, how does one go about matching a boolean search phrase to the tsvector? This is done using the @@ operator. For example:&lt;/P&gt; &lt;PRE&gt;bob=# select to_tsvector('Free text seaRCh is a wonderful Thing') @@ 'wonderful';  ?column?  ----------  t (1 row)&lt;/PRE&gt;&lt;P&gt; On the other hand 'wonderful' is not exactly a &lt;I&gt;wonderful&lt;/I&gt; example of a boolean phrase, now is it? Nope. It's just ordinary text. If that text is in the wrong format, for example contains other words, the query will in fact fail. PostgreSQL provides two functions which may be used to turn text into a query, represented as the built in &lt;I&gt;tsquery&lt;/I&gt; data type, for subsequent matching against &lt;I&gt;tsvectors&lt;/I&gt;. These are the &lt;I&gt;plainto_tsquery()&lt;/I&gt; and &lt;I&gt;to_tsquery()&lt;/I&gt; functions.&lt;/P&gt; &lt;P&gt;The rather limited &lt;I&gt;plainto_tsquery() &lt;/I&gt;function simply turns the text into a &lt;I&gt;tsquery&lt;/I&gt; with all the &lt;I&gt;lexemes&lt;/I&gt; in that text qualified by the '&amp;amp;' (or &lt;I&gt;AND&lt;/I&gt;) operator:&lt;/P&gt; &lt;PRE&gt;bob=# select plainto_tsquery('wonderful text');   plainto_tsquery     ----------------------  'wonderful' &amp;amp; 'text' bob=# select to_tsvector('Free text seaRCh is a wonderful Thing') @@ plainto_tsquery('wonderful text');  ?column?  ----------  t (1 row)&lt;/PRE&gt;&lt;P&gt; Where this might be useful, &lt;I&gt;plainto_tsquery()&lt;/I&gt; does not provide for boolean operators other than '&amp;amp;'. &lt;I&gt;to_tsquery()&lt;/I&gt; goes a lot further toward providing a decent boolean phrase. Unfortunately, it is also rather finicky about the text you throw at it. It will not accept text which is not separated by '&amp;amp;', '|' or '!'. It does accept braces, which are used to indicate operator precidence, but two tokens which translate to different lexemes directly after one another will cause &lt;I&gt;to_tsquery()&lt;/I&gt; to fail.&lt;/P&gt; &lt;PRE&gt;bob=# select to_tsquery('wonderful text'); ERROR:  syntax error in tsquery: &amp;quot;wonderful text&amp;quot; bob=# select to_tsquery('wonderful | text');       to_tsquery       ----------------------  'wonderful' | 'text'&lt;/PRE&gt;&lt;H3&gt; Ranking Search Results&lt;/H3&gt; &lt;P&gt;Nevertheless, we may use a &lt;I&gt;tsquery&lt;/I&gt; boolean search phrase to match against any &lt;I&gt;tsvector&lt;/I&gt;, or use a &lt;I&gt;tsquery&lt;/I&gt; and a &lt;I&gt;tsvector&lt;/I&gt; to produce a ranking by use of either the &lt;I&gt;ts_rank()&lt;/I&gt; or &lt;I&gt;ts_rank_cd()&lt;/I&gt; functions. These two functions behave slightly differently. &lt;I&gt;ts_rank()&lt;/I&gt; is considered the 'standard' ranking function, whilst &lt;I&gt;ts_rank_cd()&lt;/I&gt; uses the &lt;I&gt;Cover Density Ranking&lt;/I&gt; algorithm[ref.6], which is more interested in phrases than in the actual terms of the query itself.&lt;/P&gt; &lt;P&gt;To rank a match, one would use:&lt;/P&gt; &lt;PRE&gt;bob=# select ts_rank(to_tsvector('Free text seaRCh is a wonderful Thing'), to_tsquery('wonderful | thing'));   ts_rank   -----------  0.0607927 (1 row)  bob=# select ts_rank(to_tsvector('Free text seaRCh is a wonderful Thing'), to_tsquery('wonderful &amp;amp; thing'));   ts_rank   -----------  0.0991032 (1 row)  bob=# select ts_rank_cd(to_tsvector('Free text seaRCh is a wonderful Thing'), to_tsquery('wonderful &amp;amp; thing'));  ts_rank_cd  ------------         0.1 (1 row)&lt;/PRE&gt;&lt;P&gt; Relating this ranking ability back to the subject of tsvector weights, you will recall&lt;/P&gt; &lt;PRE&gt;bob=# select                                                                   bob-# setweight(to_tsvector('All about search'), 'B') || bob-# setweight(to_tsvector('Free text seaRCh is a wonderful Thing'),'A');                            ?column?                             ---------------------------------------------------------------  'free':4A 'text':5A 'thing':10A 'search':3B,6A 'wonderful':9A (1 row)&lt;/PRE&gt;&lt;P&gt; where we labelled the text sections of our document? Now we can do the following:&lt;/P&gt; &lt;PRE&gt;bob=# select ts_rank( bob-#  array[0.1,0.1,0.9,0.1], bob-#  setweight(to_tsvector('All about search'), 'B') ||  bob-#  setweight(to_tsvector('Free text seaRCh is a wonderful Thing'),'A'), bob-#  to_tsquery('wonderful &amp;amp; search'));  ts_rank   ----------  0.328337 (1 row)  bob=# select ts_rank( bob-#  array[0.1,0.1,0.1,0.9], bob-#  setweight(to_tsvector('All about search'), 'B') || bob-#  setweight(to_tsvector('Free text seaRCh is a wonderful Thing'),'A'), bob-#  to_tsquery('wonderful &amp;amp; search'));  ts_rank   ----------  0.907899 (1 row)&lt;/PRE&gt;&lt;P&gt; The &lt;I&gt;array[0.1,0.1,0.9,0.1]&lt;/I&gt; which is passed as the initial argument to ts_rank() takes arguments in order {D,C,B,A}. Since we labelled our sections A (for the body) and B (for the title), we first assigned B=0.9, A=0.1 and later B=0.1,A=0.9 in the statements above. Results of the ranking function differ accordingly.  If not specified, the optional weights array defaults to {0.1, 0.2, 0.4, 1.0}.&lt;/P&gt; &lt;H3&gt;Indexing TSVectors: The GIST &amp;amp; Gin&lt;/H3&gt; &lt;P&gt;Until now, we have used only the &lt;I&gt;select&lt;/I&gt; statement in our examples to demonstrate the matching between &lt;I&gt;tsvector&lt;/I&gt; and &lt;I&gt;tsquery&lt;/I&gt;, and subsequent ranking capabilities of PostgreSQL. Moving forward we will consider the use of &lt;I&gt;indexes&lt;/I&gt; to speed up searches, and later tackle the real showstopper which we have glossed over until now: why is &lt;I&gt;to_tsquery&lt;/I&gt; so pedantic, and how do we deal with that?&lt;/P&gt; &lt;P&gt;The two index types supported by PostgreSQL for full text search, are the &lt;I&gt;GIST&lt;/I&gt; index, which is based on hash tables, and the &lt;I&gt;Gin&lt;/I&gt; index which is based upon the Btree.&lt;/P&gt; &lt;P&gt;GIST is really fast in creating indexes. It really stores a hash table of the terms in the tsvector, and uses a hash of the terms in the tsquery to find the associated documents. Unfortunately, since the hash search result is non-deterministic, PostgreSQL has to check the results of the search, reading all of the articles located and double check the match before returning the result. For smaller sets of lexemes, and smaller databases, this works quite well. However, for really large datasets, the overheads in re-reading the data (or index) tend to make this approach quite slow.&lt;/P&gt; &lt;P&gt;Gin indexes are deterministic, and there is no implied overhead after a search using the index, but the downside to Gin is that index creation slows down logarithmically (thankfully not exponentially) as the number of entries grows. Whichever index method is chosen should therefore take the nature of the database and it's size into account.&lt;/P&gt; &lt;P&gt;There are two approaches to using an index. The first of these creates an index against a function of the data field, and the second approach is to store a tsvector in an additional field in the table; this tsvector field is then indexed. For example,&lt;/P&gt; &lt;PRE&gt;CREATE INDEX pgweb_idx ON pgweb    USING gin(to_tsvector('english', title || ' ' || body));&lt;/PRE&gt;&lt;P&gt; would create a Gin index using the combination of the title and body fields. This method is simple, but has an implied overhead: Index creation has to do additional work, and your search is more complex. The second approach uses a trigger to populate the dedicated tsvector field whenever a record is added or deleted from the table:&lt;/P&gt; &lt;PRE&gt;ALTER TABLE pgweb ADD COLUMN tsv tsvector; UPDATE pgweb SET tsv =      to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,'')); CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE   ON pgweb FOR EACH ROW EXECUTE PROCEDURE   tsvector_update_trigger(tsv, 'pg_catalog.english', title, body);&lt;/PRE&gt;&lt;P&gt; Now we simply add, update or remove table rows as normal, and the trigger populates the &lt;I&gt;tsvector&lt;/I&gt; field in the table row, which in turn updates the index appropriately. Subsequent queries may be against the &lt;I&gt;tsvector&lt;/I&gt; field, and that simplifies the query.&lt;/P&gt; &lt;H3&gt;Search result Markup&lt;/H3&gt; &lt;P&gt;We should mention at this point, before proceeding any further, a rather useful feature related to text search. PostgreSQL provides the ability to mark up text based upon the result of a text search. The function here, is &lt;I&gt;pg_headline()&lt;/I&gt;. This function returns text as a result, with all matching words in the text enclosed in &lt;I&gt;&amp;lt;b&amp;gt;&amp;lt;/b&amp;gt;&lt;/I&gt; HTML tags. It is really easy to use:&lt;/P&gt; &lt;PRE&gt;bob=# select ts_headline('Free text seaRCh is a wonderful Thing',         to_tsquery('wonderful &amp;amp; thing'));                  ts_headline                      -----------------------------------------------------  Free text seaRCh is a &amp;lt;b&amp;gt;wonderful&amp;lt;/b&amp;gt; &amp;lt;b&amp;gt;Thing&amp;lt;/b&amp;gt; (1 row)&lt;/PRE&gt;&lt;P&gt; To apply highlights to a matching abstract, one might issue the command:&lt;/P&gt; &lt;PRE&gt;select ts_headline(abstract, query)   from pgweb, to_tsquery('wonderful &amp;amp; thing') query,    where query @@ tsv;&lt;/PRE&gt;&lt;H3&gt; Phrase Search&lt;/H3&gt; &lt;P&gt;Speaking of features, one allegedly missing feature which some people, particularly users of external text engines continuously complain about PostgreSQL not having, is &lt;I&gt;phrase search&lt;/I&gt;. Here we refer to the apparent non-existent ability of PostgreSQL's full text search engine to support the match of indexed &lt;I&gt;literal&lt;/I&gt; phrases in the text.&lt;/P&gt; &lt;P&gt;Just stop to think about it for a moment. What exactly are we expecting here? How many &lt;I&gt;literal phrases&lt;/I&gt; are there in a document of say 10 words? Let's assume for the moment that the words are single character words: a,b,c...j. All the possible phrases in this document are:&lt;/P&gt; &lt;P STYLE="margin-left: 2cm; margin-bottom: 0cm"&gt;a,ab,abc,abcd...  (10 phrases)&lt;/P&gt; &lt;P STYLE="margin-left: 2cm; margin-bottom: 0cm"&gt;b,bc,bcd,bcde... (  9 phrases)&lt;/P&gt; &lt;P STYLE="margin-left: 2cm; margin-bottom: 0cm"&gt;etc...&lt;/P&gt; &lt;P STYLE="margin-bottom: 0cm"&gt;&lt;BR&gt; &lt;/P&gt; &lt;P&gt;Put differently, for a document consisting of (n) words, there are (n) phrases starting with the first word, n-1 starting with the second word, n-3 starting with the third word, etc. This translates to  &lt;/P&gt; &lt;P STYLE="margin-left: 2cm"&gt;&lt;I&gt;number of phrases = n/2 * (n+1) = 10/2*(10+1) = 55&lt;/I&gt;  &lt;/P&gt; &lt;P&gt;phrases in a document with just 10 words. For a document of 100 words, we have 5050 phrases! Are we seriously suggesting a literal phrase index is a good thing? Remember, such an index would have to contain all words, and could not afford to eliminate redundancy from the text (eg. Stop words). Not really a practical approach.&lt;/P&gt; &lt;P&gt;How then, do external text search engines support index assisted literal phrase search? Why, in exactly the same way PostgreSQL does it! Quite simply, the algorithm goes:&lt;/P&gt; &lt;OL&gt; 	&lt;LI&gt;&lt;P&gt;Turn the text phrase into a boolean search phrase, using the 	'&amp;amp;' operator&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;Use the full text search engine to locate the matching 	documents&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;For only those documents found, and using the &lt;I&gt;original&lt;/I&gt; 	text phrase do a case insensitive text match, eliminating false 	positives&lt;/P&gt; &lt;/OL&gt; &lt;P&gt;For PostgreSQL, case sensitive phrase matching is supported using the LIKE operator, and case insensitive matching through the ILIKE operator. Searching for the text  &lt;/P&gt; &lt;P STYLE="margin-left: 2cm"&gt;&lt;BR&gt;&lt;SPAN STYLE="text-decoration: none"&gt;&lt;I&gt;free text and 'Postgres text search'&lt;/I&gt;&lt;/SPAN&gt;&lt;/P&gt; &lt;P&gt;&lt;BR&gt;the query would go something like this:&lt;/P&gt; &lt;PRE&gt;select headline, ts_rank(tsv, query)    from pgweb, to_tsquery('free &amp;amp; text &amp;amp; postgres &amp;amp; search') query     where tsv @@ query and body ilike '%Postgres text search%';&lt;/PRE&gt;&lt;P&gt; ... which uses the FTS index to find articles with body text matching a query, and then for those items finds the intersection matching the literal text.&lt;/P&gt; &lt;P&gt;Simple, eh?&lt;/P&gt; &lt;H3&gt;Parsing Human Query Strings&lt;/H3&gt; &lt;P&gt;Not quite so simple. How, pray, is a poor developer supposed to turn the 'human' phrase above into the SQL statement below? This is a non-trivial task and mores the pity, well beyond the abilities of some developers. Indeed, this is considered to be a 'show-stopper' for many people. It involves building a pre-parser to parse the entered search phrase, the execution of which translates the natural language search phrase into a SQL statement formatted similarly to the above.&lt;/P&gt; &lt;P&gt;To end off this article, we include with apologies to YACCers, the listing of a &lt;a href="misc/sephton/parser.cpp"&gt;pre-parser which does precisely that&lt;/a&gt;. The general logic is generic enough to be translated to almost any language, but the listing shown here is in standard C++. This is a priority biassed recursive descent parser with no external dependencies. Feel free to use the code in any way you wish (hereby BSD license).&lt;/P&gt;  &lt;br&gt;  &lt;h2&gt;Other Linux Gazette Articles about PostgreSQL&lt;/h3&gt; &lt;UL&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="/../139/peterson.html"&gt;Writing PostgreSQL Functions 	in C&lt;/A&gt;&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="/../142/peterson.html"&gt;Writing PostgreSQL Functions 	in C, Part Two&lt;/A&gt;&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="/../067/nielsen.html"&gt;Combining Perl and PostgreSQL&lt;/A&gt;&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="/../FTS-Doc.odt/.../068/mitchell.html"&gt;The Opening 	of the Field: PostgreSQL's Multi-Version Concurrency Control&lt;/A&gt;&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="/../069/nielsen.html"&gt;Combining Perl and PostgreSQL, 	Part 2: Procedures with PL/pgSQL&lt;/A&gt;&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="/../070/williams.html"&gt;Using Aggregate Functions and 	Operators in PostgreSQL&lt;/A&gt;&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="/../072/nielsen.html"&gt;Standard Database Setup with 	Perl and PostgreSQL: Part 3&lt;/A&gt;&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="/../080/nielsen.html"&gt;Pl/Python and Cursors in 	Pl/Pgsql for PostgreSQL&lt;/A&gt;&lt;/P&gt; &lt;/UL&gt; &lt;h3&gt;References&lt;/h3&gt; &lt;OL&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="http://en.wikipedia.org/wiki/Full_text_search"&gt;http://en.wikipedia.org/wiki/Full_text_search&lt;/A&gt;&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="http://en.wikipedia.org/wiki/Search_engines"&gt;http://en.wikipedia.org/wiki/Search_engines&lt;/A&gt;&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="http://www.postgresql.org/docs/8.4/static/textsearch.html"&gt;http://www.postgresql.org/docs/8.4/static/textsearch.html&lt;/A&gt;&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="http://snowball.tartarus.org/"&gt;http://snowball.tartarus.org/&lt;/A&gt;&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="http://www.google.com/patents"&gt;http://www.google.com/patents&lt;/A&gt;&lt;/P&gt; 	&lt;LI&gt;&lt;P&gt;&lt;A HREF="http://books.google.co.za/books?id=9s-xuraeZCkC&amp;amp;pg=PA29&amp;amp;lpg=PA29&amp;amp;dq=cover+density+ranking&amp;amp;source=bl&amp;amp;ots=aThCVT5Yee&amp;amp;sig=WUFk-lNJY1PgPuXty18JA91mLAE&amp;amp;hl=en&amp;amp;ei=GV0qSpXED4_4MZvC4d8J&amp;amp;sa=X&amp;amp;oi=book_result&amp;amp;ct=result&amp;amp;resnum=4#PPA29,M1"&gt;Web 	Communities By Yanchun Zhang, Jeffrey Xu Yu, Jingyu Hou&lt;/A&gt;&lt;/P&gt; &lt;/OL&gt; &lt;P&gt;&lt;BR&gt;&lt;BR&gt; &lt;/P&gt;  &lt;br clear="all" /&gt;  &lt;script type='text/javascript'&gt; digg_url = 'http://linuxgazette.net/164/sephton.html'; digg_title = 'Understanding Full Text Search in PostgreSQL'; digg_bodytext = '&lt;P&gt;Those who have yet to enter their first search query in Google, Yahoo, or any of the myriad of other search engines available to the web, or have no interest in the use of PostgreSQL as a database engine to implement their own text search facility will find little use in reading further.&lt;/P&gt; '; digg_topic = 'linux_unix'; &lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt; 
</description>
</item>
<item rdf:about="http://linuxgazette.net/164/silva.html">
<title>Fedora 11 on the Eee PC 1000</title>
<link>http://linuxgazette.net/164/silva.html</link>
<dc:creator>Anderson Silva</dc:creator>
<dc:date>Wed, 01 Jul 2009 22:07:56 -0500</dc:date>
<description>By &lt;strong&gt;Anderson Silva&lt;/strong&gt;
&lt;br&gt;
&lt;p&gt;&lt;img src="misc/silva/fedora11-Eee.jpg" align="right"&gt; Red Hat's sponsored &lt;a href="http://www.fedoraproject.org/"&gt;Fedora Project&lt;/a&gt; just released its 11&lt;sup&gt;th&lt;/sup&gt; version of the RPM based distribution this month, and as a long time user, I thought I'd share a few things I had to do to get Fedora 11 running smoothly on my Eee PC 1000.&lt;/p&gt; 
</description>
</item>
<item rdf:about="http://linuxgazette.net/164/tomar.html">
<title>Sending and Receiving SMS from your Linux Computer</title>
<link>http://linuxgazette.net/164/tomar.html</link>
<dc:creator>Suramya Tomar</dc:creator>
<dc:date>Wed, 01 Jul 2009 22:07:56 -0500</dc:date>
<description>By &lt;strong&gt;Suramya Tomar&lt;/strong&gt;
&lt;br&gt;
&lt;p&gt;What is SMS? SMS stands for Short Message Service and is used to send text messages from one GSM enabled cell phone to another. But sometimes you might want to send an SMS message using your computer. Now there are three ways that you can send an SMS from a computer:   &lt;OL&gt; 	&lt;LI&gt;Use 	a SMS gateway service that allows your computer to connect to it 	using an API and send messages. There are a lot of these services 	available on the web but most are not free and require subscriptions&lt;/li&gt; 	&lt;LI&gt;Use 	a cell-phone/GPRS Modem connected to the computer.&lt;/li&gt; 	 	&lt;LI&gt;Some service providers allow you to send SMS to a number by sending an 	email to a specifically formated email address. &lt;/li&gt; 	 &lt;/OL&gt;   &lt;p&gt;I choose to use the second option because my provider doesn't support the last option and I think its cheaper than option one. All you need for this to work is an extra phone and a cheap phone plan that allows you to send and receive SMS's. In my case I had an old Sony Ericsson T610 lying in my desk gathering dust so I got a pre-paid SIM card and I was ready to proceed.   &lt;/p&gt;&lt;h3&gt;Pre-Installation 
</description>
</item>
<item rdf:about="http://linuxgazette.net/164/ecol.html">
<title>Ecol</title>
<link>http://linuxgazette.net/164/ecol.html</link>
<dc:creator>Javier Malonda</dc:creator>
<dc:date>Wed, 01 Jul 2009 22:07:56 -0500</dc:date>
<description>By &lt;strong&gt;Javier Malonda&lt;/strong&gt;
&lt;br&gt;
&lt;p&gt; &lt;em&gt;These images are scaled down to minimize horizontal scrolling.&lt;/em&gt; &lt;/p&gt; 
</description>
</item>
<item rdf:about="http://linuxgazette.net/164/xkcd.html">
<title>XKCD</title>
<link>http://linuxgazette.net/164/xkcd.html</link>
<dc:creator>Randall Munroe</dc:creator>
<dc:date>Wed, 01 Jul 2009 22:07:56 -0500</dc:date>
<description>By &lt;strong&gt;Randall Munroe&lt;/strong&gt;
&lt;br&gt;
&lt;p&gt;  &lt;div class="cartoon1"&gt; &lt;a href="misc/xkcd/cnr.png"&gt; &lt;img alt="[cartoon]" title="Can't and shouldn't. " src="misc/xkcd/cnr.png"&gt;&lt;p&gt;Click here to see the full-sized image&lt;/a&gt; &lt;/div&gt;  More XKCD cartoons can be found &lt;a href="http://xkcd.com"&gt;here&lt;/a&gt;.   &lt;script src="http://www.google-analytics.com/urchin.js" type="text/javascript"&gt; &lt;/script&gt; &lt;script type="text/javascript"&gt; _uacct = "UA-1204316-1"; urchinTracker(); &lt;/script&gt;  
</description>
</item>
<item rdf:about="http://linuxgazette.net/164/lg_launderette.html">
<title>The Linux Launderette</title>
<link>http://linuxgazette.net/164/lg_launderette.html</link>
<dc:creator>LG Staff</dc:creator>
<dc:date>Wed, 01 Jul 2009 22:07:56 -0500</dc:date>
<description>By &lt;strong&gt;LG Staff&lt;/strong&gt;
&lt;br&gt;
&lt;br&gt;Find me good clinic, plz&lt;br&gt;
I came across this to today&lt;br&gt;
</description>
</item>

</rdf:RDF>
