<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" ><channel><title>LINUX For You &#187; Developers</title> <atom:link href="http://www.linuxforu.com/category/developers/feed/" rel="self" type="application/rss+xml" /><link>http://www.linuxforu.com</link> <description>The Complete Magazine on Open Source</description> <lastBuildDate>Tue, 31 Jan 2012 17:22:40 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=</generator> <xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /> <item><title>Device Drivers, Part 14: A Dive Inside the Hard Disk for Understanding Partitions</title><link>http://www.linuxforu.com/2012/01/device-drivers-partitions-hard-disk/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=device-drivers-partitions-hard-disk</link> <comments>http://www.linuxforu.com/2012/01/device-drivers-partitions-hard-disk/#comments</comments> <pubDate>Tue, 31 Jan 2012 10:47:17 +0000</pubDate> <dc:creator>Anil Kumar Pugalia</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[Developers]]></category> <category><![CDATA[BIOS]]></category> <category><![CDATA[boot]]></category> <category><![CDATA[device drivers]]></category> <category><![CDATA[DOS]]></category> <category><![CDATA[fdisk]]></category> <category><![CDATA[Hard disk drive]]></category> <category><![CDATA[hard disks]]></category> <category><![CDATA[kernel]]></category> <category><![CDATA[kernel programming]]></category> <category><![CDATA[LFY January 2012]]></category> <category><![CDATA[linked-list head]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[linux device drivers]]></category> <category><![CDATA[Linux Device Drivers Series]]></category> <category><![CDATA[MBR]]></category> <category><![CDATA[mechanical engineering]]></category> <category><![CDATA[Minix]]></category> <category><![CDATA[operating system]]></category> <category><![CDATA[Partition table]]></category> <category><![CDATA[partitions]]></category> <category><![CDATA[platters]]></category> <category><![CDATA[sectors]]></category> <category><![CDATA[storage systems]]></category><guid isPermaLink="false">http://www.linuxforu.com/?p=9439</guid> <description><![CDATA[This article, which is part of the series on Linux device drivers, takes you on a tour inside a hard disk. &#8220;Doesn&#8217;t it sound like a mechanical engineering subject: The design of the...]]></description> <content:encoded><![CDATA[<p><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/Hard-drive-opening-image.jpg?d9c344" alt="Inside the hard drive" title="Inside the hard drive" width="350" height="334" class="alignright size-full wp-image-9441" /><div class="introduction">This article, which is part of the <a href="http://www.linuxforu.com/tag/linux-device-drivers-series/">series on Linux device drivers</a>, takes you on a tour inside a hard disk.</div><p>&#8220;Doesn&#8217;t it sound like a mechanical engineering subject: The design of the hard disk?&#8221; questioned Shweta. &#8220;Yes, it does. But understanding it gives us an insight into its programming aspect,&#8221; reasoned Pugs, while waiting for the commencement of the seminar on storage systems.</p><p>The seminar started with a few hard disks in the presenter&#8217;s hand and then a dive into her system, showing the output of <code>fdisk -l</code> (Figure 1).</p><div id="attachment_9440" class="wp-caption aligncenter" style="width: 590px"><a href="http://cdn.linuxforu.com/wp-content/uploads/2012/01/figure_23_fdisk_listing.png?d9c344"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/figure_23_fdisk_listing-590x448.png?d9c344" alt="Partition listing by fdisk" title="Partition listing by fdisk" width="590" height="448" class="size-large wp-image-9440" /></a><p class="wp-caption-text">Figure 1: Partition listing by fdisk</p></div><p>The first line shows the hard disk size in human-friendly format and in bytes. The second line mentions the number of logical heads, logical sectors per track, and the actual number of cylinders on the disk &#8212; together known as the geometry of the disk.</p><p>The 255 heads indicate the number of platters or disks, as one read-write head is needed per disk. Let&#8217;s number them, say D1, D2,  D255. Now, each disk would have the same number of concentric circular tracks, starting from the outside to the inside. In the above case, there are 60,801 such tracks per disk. Let&#8217;s number them, say T1, T2,  T60801. And a particular track number from all the disks forms a cylinder of the same number. For example, tracks T2 from D1, D2,  D255 will together form the cylinder C2. Now, each track has the same number of logical sectors &#8212; 63 in our case, say S1, S2,  S63. And each sector is typically 512 bytes. Given this data, one can actually compute the total usable hard disk size, using the following formula:</p><pre class="brush: text; gutter: false; first-line: 1">Usable hard disk size in bytes = (Number of heads or disks) * (Number of tracks per disk) * (Number of sectors per track) * (Number of bytes per sector, i.e. sector size)</pre><p>For the disk under consideration, it would be: <code>255 * 60801 * 63 * 512 bytes = 500105249280 bytes</code>.</p><p>Note that this number may be slightly less than the actual hard disk (500107862016 bytes, in our case). The reason is that the formula doesn&#8217;t consider the bytes in the last partial or incomplete cylinder. The primary reason for that is the difference between today&#8217;s technology of organising the actual physical disk geometry and the traditional geometry representation using heads, cylinders and sectors.</p><p>Note that in the <code>fdisk</code> output, we referred to the heads and sectors per track as logical not physical. One may ask that if today&#8217;s disks don&#8217;t have such physical geometry concepts, then why still maintain them and represent them in a logical form? The main reason is to be able to continue with the same concepts of partitioning, and be able to maintain the same partition table formats, especially for the most prevalent DOS-type partition tables, which heavily depend on this simplistic geometry. Note the computation of cylinder size (<code>255 heads * 63 sectors / track * 512 bytes / sector = 8225280 bytes</code>) in the third line and then the demarcation of partitions in units of complete cylinders.</p><h2>DOS-type partition tables</h2><p>This brings us to the next important topic: understanding DOS-type partition tables. But first, what is a partition, and why should we partition? A hard disk can be divided into one or more logical disks, each of which is called a partition. This is useful for organising different types of data separately, for example, different operating system data, user data, temporary data, etc.</p><p>So, partitions are basically logical divisions and need to be maintained by metadata, which is the partition table. A DOS-type partition table contains four partition entries, each a 16-byte entry. Each of these entries can be depicted by the following &#8216;C&#8217; structure:</p><pre class="brush: c; gutter: false; first-line: 1">typedef struct
{
    unsigned char boot_type; // 0x00 - Inactive; 0x80 - Active (Bootable)
    unsigned char start_head;
    unsigned char start_sec:6;
    unsigned char start_cyl_hi:2;
    unsigned char start_cyl;
    unsigned char part_type;
    unsigned char end_head;
    unsigned char end_sec:6;
    unsigned char end_cyl_hi:2;
    unsigned char end_cyl;
    unsigned long abs_start_sec;
    unsigned long sec_in_part;
} PartEntry;</pre><p>This partition table, followed by the two-byte signature <code>0xAA55</code>, resides at the end of the disk&#8217;s first sector, commonly known as the Master Boot Record (MBR). Hence, the starting offset of this partition table within the MBR is <code>512 - (4 * 16 + 2) = 446</code>. Also, a 4-byte disk signature is placed at offset 440.</p><p>The remaining top 440 bytes of the MBR are typically used to place the first piece of boot code, that is loaded by the BIOS to boot the system from the disk. The <code>part_info.c</code> listing contains these various definitions, along with code for parsing and printing a formatted output of the partition table.</p><p>From the partition table entry structure, it could be noted that the start and end cylinder fields are only 10 bits long, thus allowing a maximum of 1023 cylinders only. However, for today&#8217;s huge hard disks, this is in no way sufficient. Hence, in overflow cases, the corresponding <code>&lt;head, cylinder, sector&gt;</code> triplet in the partition table entry is set to the maximum value, and the actual value is computed using the last two fields: the absolute start sector number (abs_start_sec) and the number of sectors in this partition (<code>sec_in_part</code>).</p><p>The code for this too is in <code>part_info.c</code>:</p><pre class="brush: c; gutter: true; first-line: 1">#include &lt;stdio.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;unistd.h&gt;

#define SECTOR_SIZE 512
#define MBR_SIZE SECTOR_SIZE
#define MBR_DISK_SIGNATURE_OFFSET 440
#define MBR_DISK_SIGNATURE_SIZE 4
#define PARTITION_TABLE_OFFSET 446
#define PARTITION_ENTRY_SIZE 16 // sizeof(PartEntry)
#define PARTITION_TABLE_SIZE 64 // sizeof(PartTable)
#define MBR_SIGNATURE_OFFSET 510
#define MBR_SIGNATURE_SIZE 2
#define MBR_SIGNATURE 0xAA55
#define BR_SIZE SECTOR_SIZE
#define BR_SIGNATURE_OFFSET 510
#define BR_SIGNATURE_SIZE 2
#define BR_SIGNATURE 0xAA55

typedef struct {
    unsigned char boot_type; // 0x00 - Inactive; 0x80 - Active (Bootable)
    unsigned char start_head;
    unsigned char start_sec:6;
    unsigned char start_cyl_hi:2;
    unsigned char start_cyl;
    unsigned char part_type;
    unsigned char end_head;
    unsigned char end_sec:6;
    unsigned char end_cyl_hi:2;
    unsigned char end_cyl;
    unsigned long abs_start_sec;
    unsigned long sec_in_part;
} PartEntry;

typedef struct {
    unsigned char boot_code[MBR_DISK_SIGNATURE_OFFSET];
    unsigned long disk_signature;
    unsigned short pad;
    unsigned char pt[PARTITION_TABLE_SIZE];
    unsigned short signature;
} MBR;

void print_computed(unsigned long sector) {
    unsigned long heads, cyls, tracks, sectors;

    sectors = sector % 63 + 1 /* As indexed from 1 */;
    tracks = sector / 63;
    cyls = tracks / 255 + 1 /* As indexed from 1 */;
    heads = tracks % 255;
    printf(&quot;(%3d/%5d/%1d)&quot;, heads, cyls, sectors);
}

int main(int argc, char *argv[]) {
    char *dev_file = &quot;/dev/sda&quot;;
    int fd, i, rd_val;
    MBR m;
    PartEntry *p = (PartEntry *)(m.pt);

    if (argc == 2) {
        dev_file = argv[1];
    }
    if ((fd = open(dev_file, O_RDONLY)) == -1) {
        fprintf(stderr, &quot;Failed opening %s: &quot;, dev_file);
        perror(&quot;&quot;);
        return 1;
    }
    if ((rd_val = read(fd, &amp;m, sizeof(m))) != sizeof(m)) {
        fprintf(stderr, &quot;Failed reading %s: &quot;, dev_file);
        perror(&quot;&quot;);
        close(fd);
        return 2;
    }
    close(fd);
    printf(&quot;\nDOS type Partition Table of %s:\n&quot;, dev_file);
    printf(&quot;  B Start (H/C/S)   End (H/C/S) Type  StartSec    TotSec\n&quot;);
    for (i = 0; i &lt; 4; i++) {
        printf(&quot;%d:%d (%3d/%4d/%2d) (%3d/%4d/%2d)  %02X %10d %9d\n&quot;,
            i + 1, !!(p[i].boot_type &amp; 0x80),
            p[i].start_head,
            1 + ((p[i].start_cyl_hi &lt;&lt; 8) | p[i].start_cyl),
            p[i].start_sec,
            p[i].end_head,
            1 + ((p[i].end_cyl_hi &lt;&lt; 8) | p[i].end_cyl),
            p[i].end_sec,
            p[i].part_type,
            p[i].abs_start_sec, p[i].sec_in_part);
    }
    printf(&quot;\nRe-computed Partition Table of %s:\n&quot;, dev_file);
    printf(&quot;  B Start (H/C/S)   End (H/C/S) Type  StartSec    TotSec\n&quot;);
    for (i = 0; i &lt; 4; i++) {
        printf(&quot;%d:%d &quot;, i + 1, !!(p[i].boot_type &amp; 0x80));
        print_computed(p[i].abs_start_sec);
        printf(&quot; &quot;);
        print_computed(p[i].abs_start_sec + p[i].sec_in_part - 1);
        printf(&quot; %02X %10d %9d\n&quot;, p[i].part_type,
            p[i].abs_start_sec, p[i].sec_in_part);
    }
    printf(&quot;\n&quot;);
    return 0;
}</pre><p>As the above is an application, compile it with <code>gcc part_info.c -o part_info</code>, and then run <code>./part_info /dev/sda</code> to check out your primary partitioning information on <code>/dev/sda</code>. Figure 2 shows the output of <code>./part_info</code> on the presenter&#8217;s system. Compare it with the <code>fdisk</code> output in Figure 1.</p><div id="attachment_9442" class="wp-caption aligncenter" style="width: 590px"><a href="http://cdn.linuxforu.com/wp-content/uploads/2012/01/figure_24_part_info_output.png?d9c344"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/figure_24_part_info_output-590x448.png?d9c344" alt="Output of ./part_info" title="Output of ./part_info" width="590" height="448" class="size-large wp-image-9442" /></a><p class="wp-caption-text">Figure 2: Output of ./part_info</p></div><h2>Partition types and boot records</h2><p>Now, as this partition table is hard-coded to have four entries, that&#8217;s the maximum number of partitions you can have. These are called primary partitions, each having an associated type in the corresponding partition table entry. These types are typically coined by various OS vendors, and hence sort of map to various OSs like DOS, Minix, Linux, Solaris, BSD, FreeBSD, QNX, W95, Novell Netware, etc., to be used for/with the particular OS. However, this is more a formality than a real requirement.</p><p>Besides this, one of the four primary partitions can be labelled as something called an extended partition, which has a special significance. As the name suggests, it is used to further extend hard disk division, i.e., to have more partitions. These are called logical partitions and are created within the extended partition. The metadata of these is maintained in a linked-list format, allowing an unlimited number of logical partitions (at least theoretically).</p><p>For that, the first sector of the extended partition, commonly called the Boot Record (BR), is used like the MBR to store (the linked-list head of) the partition table for the logical partitions. Subsequent linked-list nodes are stored in the first sector of the subsequent logical partitions, referred to as the Logical Boot Record (LBR). Each linked-list node is a complete 4-entry partition table, though only the first two entries are used &#8212; the first for the linked-list data, namely, information about the immediate logical partition, and the second as the linked list&#8217;s next pointer, pointing to the list of remaining logical partitions.</p><p>To compare and understand the primary partitioning details on your system&#8217;s hard disk, follow the steps (as the root user &#8212; hence with care) given below:</p><pre class="brush: text; gutter: false; first-line: 1">./part_info /dev/sda ## Displays the partition table on /dev/sda
fdisk -l /dev/sda ## To display and compare the partition table entries with the above</pre><p>In case you have multiple hard disks (<code>/dev/sdb</code>, &#8230;), hard disk device files with other names (<code>/dev/hda</code>, &#8230;), or an extended partition, you may try <code>./part_info &lt;device_file_name&gt;</code> on them as well. Trying on an extended partition would give you the information about the starting partition table of the logical partitions.</p><p>Right now, we have carefully and selectively played (read-only) with the system&#8217;s hard disk. Why carefully? Since otherwise, we may render our system non-bootable. But no learning is complete without a total exploration. Hence, in our next session, we will create a dummy disk in RAM and do destructive exploration on it.<div id="crp_related"><h5>Related Posts:</h5><ul><li><a href="http://www.linuxforu.com/2012/01/working-with-mtd-devices/" rel="bookmark" class="crp_title">Working with MTD Devices</a></li><li><a href="http://www.linuxforu.com/2012/01/joy-of-programming-understanding-bit-fields-c/" rel="bookmark" class="crp_title">Joy of Programming: Understanding Bit-fields in C</a></li><li><a href="http://www.linuxforu.com/2009/02/improve-multi-os-computer-performance-through-cross-swapping/" rel="bookmark" class="crp_title">Improve Multi-OS Computer Performance through Cross Swapping</a></li><li><a href="http://www.linuxforu.com/2009/03/install-linux-straight-from-an-iso/" rel="bookmark" class="crp_title">Stop Wasting CDs; Install Linux Straight from an ISO</a></li><li><a href="http://www.linuxforu.com/2011/04/getting-started-with-inotify/" rel="bookmark" class="crp_title">Getting Started with Inotify</a></li></ul></div>Tags: <a href="http://www.linuxforu.com/tag/bios/" title="BIOS" rel="tag">BIOS</a>, <a href="http://www.linuxforu.com/tag/boot/" title="boot" rel="tag">boot</a>, <a href="http://www.linuxforu.com/tag/device-drivers/" title="device drivers" rel="tag">device drivers</a>, <a href="http://www.linuxforu.com/tag/dos/" title="DOS" rel="tag">DOS</a>, <a href="http://www.linuxforu.com/tag/fdisk/" title="fdisk" rel="tag">fdisk</a>, <a href="http://www.linuxforu.com/tag/hard-disk-drive/" title="Hard disk drive" rel="tag">Hard disk drive</a>, <a href="http://www.linuxforu.com/tag/hard-disks/" title="hard disks" rel="tag">hard disks</a>, <a href="http://www.linuxforu.com/tag/kernel/" title="kernel" rel="tag">kernel</a>, <a href="http://www.linuxforu.com/tag/kernel-programming/" title="kernel programming" rel="tag">kernel programming</a>, <a href="http://www.linuxforu.com/tag/lfy-january-2012/" title="LFY January 2012" rel="tag">LFY January 2012</a>, <a href="http://www.linuxforu.com/tag/linked-list-head/" title="linked-list head" rel="tag">linked-list head</a>, <a href="http://www.linuxforu.com/tag/linux/" title="Linux" rel="tag">Linux</a>, <a href="http://www.linuxforu.com/tag/linux-device-drivers/" title="linux device drivers" rel="tag">linux device drivers</a>, <a href="http://www.linuxforu.com/tag/linux-device-drivers-series/" title="Linux Device Drivers Series" rel="tag">Linux Device Drivers Series</a>, <a href="http://www.linuxforu.com/tag/mbr/" title="MBR" rel="tag">MBR</a>, <a href="http://www.linuxforu.com/tag/mechanical-engineering/" title="mechanical engineering" rel="tag">mechanical engineering</a>, <a href="http://www.linuxforu.com/tag/minix/" title="Minix" rel="tag">Minix</a>, <a href="http://www.linuxforu.com/tag/operating-system/" title="operating system" rel="tag">operating system</a>, <a href="http://www.linuxforu.com/tag/partition-table/" title="Partition table" rel="tag">Partition table</a>, <a href="http://www.linuxforu.com/tag/partitions/" title="partitions" rel="tag">partitions</a>, <a href="http://www.linuxforu.com/tag/platters/" title="platters" rel="tag">platters</a>, <a href="http://www.linuxforu.com/tag/sectors/" title="sectors" rel="tag">sectors</a>, <a href="http://www.linuxforu.com/tag/storage-systems/" title="storage systems" rel="tag">storage systems</a><br /> ]]></content:encoded> <wfw:commentRss>http://www.linuxforu.com/2012/01/device-drivers-partitions-hard-disk/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Lisp: Tears of Joy, Part 8</title><link>http://www.linuxforu.com/2012/01/lisp-tears-of-joy-part-8/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=lisp-tears-of-joy-part-8</link> <comments>http://www.linuxforu.com/2012/01/lisp-tears-of-joy-part-8/#comments</comments> <pubDate>Tue, 31 Jan 2012 07:33:52 +0000</pubDate> <dc:creator>Vivek Shangari</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[Developers]]></category> <category><![CDATA[CLOS]]></category> <category><![CDATA[Common Lisp]]></category> <category><![CDATA[Common Lisp Object System]]></category> <category><![CDATA[Conard Barski]]></category> <category><![CDATA[control functions]]></category> <category><![CDATA[Daniel G. Bobrow]]></category> <category><![CDATA[Doug Hoyte]]></category> <category><![CDATA[flow control]]></category> <category><![CDATA[functional programming]]></category> <category><![CDATA[James Hague]]></category> <category><![CDATA[Jon L White]]></category> <category><![CDATA[LFY January 2012]]></category> <category><![CDATA[Lisp]]></category> <category><![CDATA[Lisp: Tears of Joy series]]></category> <category><![CDATA[Michael Feathers]]></category> <category><![CDATA[object interfaces]]></category> <category><![CDATA[object-oriented programming]]></category> <category><![CDATA[oo approach]]></category> <category><![CDATA[oo programming]]></category> <category><![CDATA[programming]]></category> <category><![CDATA[programming style]]></category> <category><![CDATA[recursion]]></category> <category><![CDATA[Richard P Gabriel]]></category><guid isPermaLink="false">http://www.linuxforu.com/?p=9429</guid> <description><![CDATA[Lisp has been hailed as the world&#8217;s most powerful programming language. But only the top percentile of programmers use it because of its cryptic syntax and academic reputation. This is rather unfortunate, since...]]></description> <content:encoded><![CDATA[<p><img class="aligncenter size-large wp-image-9431" title="Time to Lisp" src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/lisp-tear-of-joy-590x363.jpg?d9c344" alt="Time to Lisp" width="590" height="363" /><div class="introduction">Lisp has been hailed as the world&#8217;s most powerful programming language. But only the top percentile of programmers use it because of its cryptic syntax and academic reputation. This is rather unfortunate, since Lisp isn&#8217;t that hard to grasp. If you want to be among the crème de la crème, <a href="http://www.linuxforu.com/tag/lisp-tears-of-joy-series/" title="Series of articles on Lisp">this series</a> is for you. This is the eighth article in the series that began in <a href="http://www.linuxforu.com/2011/06/lisp-tears-of-joy-part-1/" title="Lisp: Tears of Joy, Part 1">June 2011</a>.</div><p>In rare moments of self-reflection, when I allow myself to doubt my skills as a Lisp evangelist, I sometimes wonder if I have left behind some of my fellow programmers who favour the object-oriented style of programming. Just because I have been focusing on Lisp as a functional programming paradigm, it doesn&#8217;t mean we don&#8217;t have a role for you in our plans of world domination. Read on to know where you fit in.</p><h2>Functional vs object-oriented (OO) programming</h2><p>With an OO approach, programmers write code that describes in exacting detail the steps that the computer must take to accomplish the goal. They focus on how to perform tasks, and how to track changes in state. They would use loops, conditions and method calls as their primary flow control, and instances of structures or classes as primary manipulation units. OO tries to control state behind object interfaces.</p><p>In contrast, functional programming (FP) involves composing the problem as a set of functions to be executed. FP programmers focus on what information is desired and what transformations are required, by carefully defining the input to each function and what each function returns. They would use function calls, including recursion, as their primary flow control, functions as first-class objects and data collections as primary manipulation units. FP tries to minimise state by using pure functions as much as possible.</p><p><a href="http://twitter.com/#!/mfeathers/status/29581296216">According to Michael Feathers</a>: &#8220;OO makes code understandable by encapsulating moving parts. FP makes code understandable by minimising moving parts.&#8221;</p><p>Conard Barski points out that the critics of the OO programming style may complain that object-oriented techniques force data to be hidden away in a lot of disparate places by requiring them to live inside many different objects. Having data located in disparate places can make programs difficult to understand, especially if that data changes over time.</p><p>Therefore, many Lispers prefer to use functional techniques over object-oriented techniques, though the two can often be used together &#8212; with some care. Nonetheless, there are still many domains in which object-oriented techniques are invaluable, such as in user interface programming or simulation programming.</p><p>On the other hand, James Hague, in his assessment of functional programming argues that, &#8220;100 per cent pure functional programming doesn&#8217;t work. Even 98 per cent pure functional programming doesn&#8217;t work. But if the slider between functional purity and 1980s BASIC-style imperative messiness is kicked down a few notches &#8212; say to 85 per cent &#8212; then it really does work. You get all the advantages of functional programming, but without the extreme mental effort and un-maintainability that increases as you get closer and closer to perfectly pure.&#8221;</p><h2>CLOS</h2><p>If OO is what gets you going, Common Lisp offers the most sophisticated object-oriented programming framework of any major programming language. It&#8217;s called Common Lisp Object System (CLOS). It is customisable at a fundamental level, using the Meta-Object Protocol (MOP). It has been claimed that there&#8217;s really nothing like it anywhere else in programming. It lets you control incredibly complex software without losing control over the code.</p><p>Let the tears of joy flow&#8230;</p><h2>Object-oriented programming in Common Lisp</h2><h3>What is CLOS?</h3><h4>#1: It is a layered system designed for flexibility.</h4><p>One of the design goals of CLOS is to provide a set of layers that separate different programming language concerns from one another. The first level of the Object System provides a programmatic interface to object-oriented programming. This level is designed to meet the needs of most serious users, and to provide a syntax that is crisp and understandable.</p><p>The second level provides a functional interface into the heart of the Object System. This level is intended for programmers who are writing very complex software or a programming environment. The first level is written in terms of this second level.</p><p>The third level provides the tools for programmers who are writing their own object-oriented language. It allows access to the primitive objects and operators of the Object System. It is this level at which the implementation of the Object System itself is based.</p><p>The layered design of CLOS is founded on the meta-object protocol, a protocol that is used to define the characteristics of an object-oriented system. Using the meta-object protocol, other functional or programmatic interfaces to the Object System, as well as other object systems, can be written.</p><h4>#2: It is based on the concept of generic functions rather than on message-passing.</h4><p>This choice is made for two reasons:</p><ol><li>there are some problems with message-passing in operations of more than one argument;</li><li>the concept of generic functions is a generalisation of the concept of ordinary Lisp functions.</li></ol><p>A key concept in object-oriented systems is that given an operation and a tuple of objects on which to apply the operation, the code that is most appropriate to perform the operation is selected, based on the classes of the objects.</p><p>In most message-passing systems, operations are essentially properties of classes, and this selection is made by packaging a message that specifies the operation and the objects to which it applies, before sending that message to a suitable object. That object then takes responsibility for selecting the appropriate piece of code. These pieces of code are called methods.</p><h4>#3: It is a multiple inheritance system.</h4><p>Another key concept in object-oriented programming is the definition of structure and behaviour on the basis of the class of an object. Classes thus impose a type system &#8212; the code that is used to execute operations on objects depends on the classes of the objects. The sub-class mechanism allows classes to be defined that share the structure and the behaviour of other classes. This sub-classing is a tool for modularisation of programs.</p><h4>#4: It provides a powerful method combination facility.</h4><p>Method combination is used to define how the methods that are applicable to a set of arguments can be combined to provide the values of a generic function. In many object-oriented systems, the most specific applicable method is invoked, and that method may invoke other, less specific methods.</p><p>When this happens, there is often a combination strategy at work, but that strategy is distributed throughout the methods as local control structure. Method combination brings the notion of a combination strategy to the surface, and provides a mechanism for expressing that strategy.</p><h4>#5: The primary entities of the system are all first-class objects.</h5><p>In the Common Lisp Object System, generic functions and classes are first-class objects with no intrinsic names. It is possible and useful to create and manipulate anonymous generic functions and classes. The concept of &#8220;first-class&#8221; is important in Lisp-like languages. A first-class object is one that can be explicitly made and manipulated; it can be stored in any location that can hold general objects.</p><h5>What CLOS is not</h3><p>It does not make for a great pickup conversation at the bar. I tried. It did not work!</p><p>It also does not attempt to solve problems of encapsulation. The inherited structure of a class depends on the names of the internal parts of the classes from which it inherits. CLOS does not support subtractive inheritance. Within Common Lisp, there is a primitive module system that can be used to help create separate internal namespaces.</p><h3>Classes</h3><p>The <code>defclass</code> macro is used to define a new class. The definition of a class consists of its name, a list of its direct super-classes, a set of slot specifiers and a set of class options. The direct super-classes of a class are those from which the new class inherits structure and behaviour. When a class is defined, the order in which its direct super-classes are mentioned in the <code>defclass</code> form defines a local precedence order on the class and those super-classes. The local precedence order is represented as a list consisting of the class, followed by its direct super-classes, in the order mentioned in the <code>defclass</code> form. The following two classes define a representation of a point in space. The <code>x-y-position</code> class is a sub-class of the <code>position</code> class:</p><pre class="brush: text; gutter: false; first-line: 1">&gt; (defclass position () ())

&gt; (defclass x-y-position (position)
      ((x :initform 0)
       (y :initform 0))
     (:accessor-prefix position-))</pre><p>The <code>position</code> class is useful if we want to create other sorts of representations for spatial positions. The <code>x</code> and <code>y</code> coordinates are initialised to 0 in all instances, unless explicit values are supplied for them. To refer to the x coordinate of an instance of <code>x-y-position</code>, you would write:</p><pre class="brush: text; gutter: false; first-line: 1">&gt; (position-x position)</pre><p>To alter the x coordinate of that instance, you would write:</p><pre class="brush: text; gutter: false; first-line: 1">(setf (position-x position) new-x)</pre><p>The macro <code>defclass</code> is part of the Object System programmatic interface and, as such, is on the first of the three levels of the Object System.</p><h3>Generic functions</h3><p>The class-specific operations of the Common Lisp Object System are provided by generic functions and methods. A generic function is one whose behaviour depends on the classes or identities of the arguments supplied to it. The methods associated with the generic function define the class-specific operations of the generic function.</p><p>Like an ordinary Lisp function, a generic function takes arguments, performs a series of operations and returns values. An ordinary function has a single body of code that is always executed when the function is called. A generic function is able to perform different series of operations and to combine the results of the operations in different ways, depending on the class or identity of one or more of its arguments.</p><p>Generic functions are defined by means of the <code>defgeneric-options</code> and <code>defmethod</code> macros. The <code>defgeneric-options</code> macro is designed to allow for the specification of properties that pertain to the generic function as a whole, and not just to individual methods. The <code>defmethod</code> form is used to define a method. If there is no generic function of the given name, however, it automatically creates a generic function with default values for the argument precedence order (left-to-right, as defined by the lambda-list), the generic function class (the class <code>standard-generic-function</code>), the method class (the class <code>standard-method</code>) and the method combination type (<code>standard-method combination</code>).</p><h3>Methods</h3><p>The class-specific operations provided by generic functions are themselves defined and implemented by methods. The class or identity of each argument to the generic function indicates which method or methods are eligible to be invoked.</p><p>A method object contains a method function, an ordered set of parameter specialisers that specify when the given method is applicable, and an ordered set of qualifiers that are used by the method combination facility to distinguish between methods.</p><p>The <code>defmethod</code> macro is used to create a method object. A <code>defmethod</code> form contains the code that is to be run when the arguments to the generic function cause the method that it defines, to be selected. If a <code>defmethod</code> form is evaluated, and a method object corresponding to the given generic function name, parameter specialisers and qualifiers already exists, then the new definition replaces the old.</p><p>Generic functions can be used to implement a layer of abstraction on top of a set of classes. For example, the <code>x-y-position</code> class can be viewed as containing information in polar coordinates.</p><p>Two methods have been defined &#8212; <code>position-rho</code> and <code>position-theta</code>, that calculate the &#961; and &#920; coordinates given an instance of <code>x-y-position</code>:</p><pre class="brush: text; gutter: false; first-line: 1">&gt; (defmethod position-rho ((pos x-y-position))
      (let ((x (position-x pos))
            (y (position-y pos)))
         (sqrt (+ (* x x) (* y y)))))

&gt; (defmethod position-theta ((pos x-y-position))
     (atan (position-y pos) (position-x pos)))</pre><p>It is also possible to write methods that update the &#8220;virtual slots&#8221; <code>position-rho</code> and <code>position-theta</code>:</p><pre class="brush: text; gutter: false; first-line: 1">&gt; (defmethod-setf position-rho ((pos x-y-position)) (rho)
      (let* ((r (position-rho pos))
           (ratio (/ rho r)))
        (setf (position-x pos) (* ratio (position-x pos)))
        (setf (position-y pos) (* ratio (position-y pos)))))

&gt; (defmethod-setf position-theta ((pos x-y-position)) (theta)
      (let ((rho (position-rho pos)))
       (setf (position-x pos) (* rho (cos theta)))
       (setf (position-y pos) (* rho (sin theta)))))</pre><p>To update the &#961;-coordinate you may write:</p><pre class="brush: text; gutter: false; first-line: 1">&gt; (setf (position-rho pos) new-rho)</pre><p>This is precisely the same syntax that would be used if the positions were explicitly stored as polar coordinates.</p><h3>Class redefinition</h3><p>The Common Lisp Object System provides a powerful class-redefinition facility.</p><p>When a <code>defclass</code> form is evaluated, and a class with the given name already exists, the existing class is redefined. Redefining a class modifies the existing class object to reflect the new class definition.</p><p>You may define methods on the generic function <code>class-changed</code> to control the class redefinition process. This generic function is invoked automatically by the system after <code>defclass</code> has been used to redefine an existing class; for example, suppose it becomes apparent that the application that requires representing positions uses polar coordinates more than it uses rectangular coordinates. It might make sense to define a sub-class of <code>position</code> that uses polar coordinates:</p><pre class="brush: text; gutter: false; first-line: 1">&gt; (defclass rho-theta-position (position)
      ((rho :initform 0)
      (theta :initform 0))
    (:accessor-prefix position-))</pre><p>The instances of <code>x-y-position</code> can be automatically updated by defining a class-changed method:</p><pre class="brush: text; gutter: false; first-line: 1">&gt; (defmethod class-changed ((old x-y-position)
                          (new rho-theta-position))
;; Copy the position information from old to new to make new
;; be a rho-theta-position at the same position as old.
     (let ((x (position-x old))
           (y (position-y old)))
        (setf (position-rho new) (sqrt (+ (* x x) (* y y)))
              (position-theta new) (atan y x))))</pre><p>At this point, we can change an instance of the class <code>x-y-position</code>, <code>p1</code>, to be an instance of <code>rho-theta-position</code> by using change-class:</p><pre class="brush: text; gutter: false; first-line: 1">&gt; (change-class p1 &#039;rho-theta-position)</pre><h3>Inheritance</h3><p>Inheritance is the key to program modularity within CLOS. A typical object-oriented program consists of several classes, each of which defines some aspect of behaviour. New classes are defined by including the appropriate classes as super-classes, thus gathering the desired aspects of behaviour into one class.</p><p>In general, slot descriptions are inherited by sub-classes. That is, slots defined by a class are usually slots implicitly defined by any sub-class of that class, unless the sub-class explicitly shadows the slot definition. A class can also shadow some of the slot options declared in the <code>defclass</code> form of one of its super-classes by providing its own description for that slot.</p><p>A sub-class inherits methods in the sense that any method applicable to an instance of a class is also applicable to instances of any sub-class of that class (all other arguments to the method being the same).</p><p>The inheritance of methods acts the same way regardless of whether the method was created by using <code>defmethod</code> or by using one of the <code>defclass</code> options that cause methods to be generated automatically.</p><p>I hope with this article I have managed to convince OO programmers that Lisp is generous enough to cater to your style of thinking. Stick with me, and I promise that you won&#8217;t be disappointed. So far we&#8217;ve seen how to fit the nuts and bolts into the engine. Next month, we&#8217;ll learn how to paint it a nice shiny red&#8230; I am referring to Graphical Programming in Lisp!</p><h5>References</h5><ul><li><em>Let Over Lambda</em>, Doug Hoyte</li><li><em>CLOS: Integrating Object-Oriented and Functional programming</em>, Richard P. Gabriel, Jon L White, Daniel G. Bobrow</li></ul><div id="crp_related"><h5>Related Posts:</h5><ul><li><a href="http://www.linuxforu.com/2011/09/lisp-tears-of-joy-part-4/" rel="bookmark" class="crp_title">Lisp: Tears of Joy, Part 4</a></li><li><a href="http://www.linuxforu.com/2011/12/lisp-tears-of-joy-part-7/" rel="bookmark" class="crp_title">Lisp: Tears of Joy, Part 7</a></li><li><a href="http://www.linuxforu.com/2011/10/lisp-tears-of-joy-part-5/" rel="bookmark" class="crp_title">Lisp: Tears of Joy, Part 5</a></li><li><a href="http://www.linuxforu.com/2011/12/loading-library-files-in-cpp/" rel="bookmark" class="crp_title">Loading Library Files in C++</a></li><li><a href="http://www.linuxforu.com/2011/11/lisp-tears-of-joy-part-6/" rel="bookmark" class="crp_title">Lisp: Tears of Joy, Part 6</a></li></ul></div>Tags: <a href="http://www.linuxforu.com/tag/clos/" title="CLOS" rel="tag">CLOS</a>, <a href="http://www.linuxforu.com/tag/common-lisp/" title="Common Lisp" rel="tag">Common Lisp</a>, <a href="http://www.linuxforu.com/tag/common-lisp-object-system/" title="Common Lisp Object System" rel="tag">Common Lisp Object System</a>, <a href="http://www.linuxforu.com/tag/conard-barski/" title="Conard Barski" rel="tag">Conard Barski</a>, <a href="http://www.linuxforu.com/tag/control-functions/" title="control functions" rel="tag">control functions</a>, <a href="http://www.linuxforu.com/tag/daniel-g-bobrow/" title="Daniel G. Bobrow" rel="tag">Daniel G. Bobrow</a>, <a href="http://www.linuxforu.com/tag/doug-hoyte/" title="Doug Hoyte" rel="tag">Doug Hoyte</a>, <a href="http://www.linuxforu.com/tag/flow-control/" title="flow control" rel="tag">flow control</a>, <a href="http://www.linuxforu.com/tag/functional-programming/" title="functional programming" rel="tag">functional programming</a>, <a href="http://www.linuxforu.com/tag/james-hague/" title="James Hague" rel="tag">James Hague</a>, <a href="http://www.linuxforu.com/tag/jon-l-white/" title="Jon L White" rel="tag">Jon L White</a>, <a href="http://www.linuxforu.com/tag/lfy-january-2012/" title="LFY January 2012" rel="tag">LFY January 2012</a>, <a href="http://www.linuxforu.com/tag/lisp/" title="Lisp" rel="tag">Lisp</a>, <a href="http://www.linuxforu.com/tag/lisp-tears-of-joy-series/" title="Lisp: Tears of Joy series" rel="tag">Lisp: Tears of Joy series</a>, <a href="http://www.linuxforu.com/tag/michael-feathers/" title="Michael Feathers" rel="tag">Michael Feathers</a>, <a href="http://www.linuxforu.com/tag/object-interfaces/" title="object interfaces" rel="tag">object interfaces</a>, <a href="http://www.linuxforu.com/tag/object-oriented-programming/" title="object-oriented programming" rel="tag">object-oriented programming</a>, <a href="http://www.linuxforu.com/tag/oo-approach/" title="oo approach" rel="tag">oo approach</a>, <a href="http://www.linuxforu.com/tag/oo-programming/" title="oo programming" rel="tag">oo programming</a>, <a href="http://www.linuxforu.com/tag/programming/" title="programming" rel="tag">programming</a>, <a href="http://www.linuxforu.com/tag/programming-style/" title="programming style" rel="tag">programming style</a>, <a href="http://www.linuxforu.com/tag/recursion/" title="recursion" rel="tag">recursion</a>, <a href="http://www.linuxforu.com/tag/richard-p-gabriel/" title="Richard P Gabriel" rel="tag">Richard P Gabriel</a><br /> ]]></content:encoded> <wfw:commentRss>http://www.linuxforu.com/2012/01/lisp-tears-of-joy-part-8/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Developing Applications on QT, Part 1</title><link>http://www.linuxforu.com/2012/01/developing-applications-qt-part-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=developing-applications-qt-part-1</link> <comments>http://www.linuxforu.com/2012/01/developing-applications-qt-part-1/#comments</comments> <pubDate>Tue, 31 Jan 2012 06:26:29 +0000</pubDate> <dc:creator>Manoj Kumar</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[Developers]]></category> <category><![CDATA[application development]]></category> <category><![CDATA[application performance]]></category> <category><![CDATA[C/C++]]></category> <category><![CDATA[cpp]]></category> <category><![CDATA[desktop applications]]></category> <category><![CDATA[GUI]]></category> <category><![CDATA[Java]]></category> <category><![CDATA[LFY January 2012]]></category> <category><![CDATA[Microsoft Windows]]></category> <category><![CDATA[POSIX]]></category> <category><![CDATA[Qt]]></category> <category><![CDATA[Qt applications]]></category> <category><![CDATA[Qt Creator]]></category> <category><![CDATA[Qt Designer]]></category> <category><![CDATA[Qt development]]></category> <category><![CDATA[Qt GUI applications]]></category> <category><![CDATA[Qt Linguist]]></category> <category><![CDATA[software frameworks]]></category> <category><![CDATA[Sun Microsystems]]></category> <category><![CDATA[Symbian]]></category> <category><![CDATA[Trolltech]]></category> <category><![CDATA[xml]]></category><guid isPermaLink="false">http://www.linuxforu.com/?p=9422</guid> <description><![CDATA[This article introduces application development using the Qt GUI framework. There was a time when all desktop applications were developed from scratch. Then came the concept of code reuse. Static and shared libraries...]]></description> <content:encoded><![CDATA[<p><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/qt-dev-open-590x393.jpg?d9c344" alt="It&#039;s Qt" title="It&#039;s Qt" width="590" height="393" class="aligncenter size-large wp-image-9426" /><div class="introduction">This article introduces application development using the Qt GUI framework.</div><p>There was a time when all desktop applications were developed from scratch. Then came the concept of code reuse. Static and shared libraries were created for use in application development, but developers didn&#8217;t stop at that; they came up with software frameworks. Though libraries and frameworks seem to functionally be the same, there are some major differences between them, which should be understood:</p><ul><li>Libraries offer reusability of functionality, whereas frameworks offer reusability of behaviour. For example, a library may provide classes for TCP and UDP sockets, while a framework will provide a class for an abstract socket.</li><li>A library may provide functions used for signals/events, but the framework function is how they interact with the system and other components.</li><li>Libraries are called from application code, but the framework calls application code &#8212; or, you can say, provides services to the code.</li></ul><h2>Desktop applications</h2><p>Desktop applications are very platform-specific. An application compiled for Linux cannot be directly executed on another OS without some sort of emulation, due to differences in system calls and libraries between OSs. A big question was how to write platform-independent applications.</p><p>One method was to develop libraries for each platform, keeping application code the same and recompiling for each target platform. This does make life easier for developers &#8212; but then everything changed with the revolutionary concept of virtual machines from Sun Microsystems, which gave the world the platform-independent Java programming language. Java applications run on the Java Virtual Machine (JVM). Code developed once can be deployed to every platform that has a JVM for it.</p><p>But everything comes with a price. In Java&#8217;s case, the price was application performance. The performance of Java applications is not as good as of C/C++ applications compiled to platform-native code. Another problem is the large memory footprint. No doubt Java is still a leading language, but these days we have some really big data applications (for example, in biotech) with very high performance requirements. So again, the need is to develop applications compilable to native code. Application development using C is time-consuming, while C++ is a better option. We have some frameworks that support C++ for application development. The Qt framework is one of them.</p><h2>Introducing Qt</h2><p><a href="http://qt.nokia.com/">Qt</a> is a cross-platform application framework developed by Trolltech and presently owned by Nokia. Its APIs are for C++. Qt has been extensively used by application developers to develop cross-platform applications.</p><p>Qt can help with graphical application development, network applications, database and multimedia applications, handling XML and 3D, painting, drawing and Web access. As far as platform support is concerned, it supports Linux, Mac OS, Windows, Meego, Embedded Linux and Symbian.</p><h2>Qt architecture</h2><p>In Figure 1, you can see a minimal architecture diagram.</p><div id="attachment_9424" class="wp-caption aligncenter" style="width: 590px"><a href="http://cdn.linuxforu.com/wp-content/uploads/2012/01/fig-1.png?d9c344"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/fig-1-590x179.png?d9c344" alt="Qt architecture" title="Qt architecture" width="590" height="179" class="size-large wp-image-9424" /></a><p class="wp-caption-text">Figure 1: Qt architecture</p></div><p>The top layer is C++ program code. Below that are Qt classes for GUI, WebKit, databases, etc., and then an OS-specific support layer. Earlier, Qt also supported Java; its Java-based version was called Jambie. As Qt development progressed, it was getting difficult to support both C++ and Java, so the decision was made to support only C++.</p><h2>Qt installation</h2><p>Installation methods differ by OS. On Ubuntu 10.04 LTS, I installed Qt via the Synaptic package manager &#8212; install the <code>qtcreator</code> package; dependency resolution will install Qt Assistant, Qt Designer, Qt Linguist and Qt Creator.</p><p>If you want to try out the latest Qt release, you can download the offline installer from their <a href="http://qt.nokia.com/downloads">official  website</a> and install it. Just <code>chmod</code> the installer file to make it executable and run it, and then follow the prompts.</p><h2>A &#8216;Hello World&#8217; program (non-GUI)</h2><p>Open a terminal. Create a directory (first) and create a simple &#8220;Hello World&#8221; program with the following code:</p><pre class="brush: cpp; gutter: false; first-line: 1">#include&lt;QtCore&gt;
int main(){
    qDebug() &lt;&lt; &quot;Hello world\n&quot;;
}</pre><p>The included header file QtCore contains declarations for classes that do not use a GUI. We will look at these in detail in later articles. For now, just use the <code>qDebug</code> class, which outputs debugging messages to the console and is equivalent to <code>cout</code> in traditional C++ programming.</p><p>So how does one compile it? The Trolltech people came out with an easy solution to support cross-platform compilation. First, a project file should be created, and then a <code>Makefile</code> is created using it. Then, just run <code>make</code> to compile the program. When you install QT Creator, a utility called <code>qmake</code> is also installed. This is a cross-platform <code>Makefile</code> generator for Qt. Check out its man pages for more. Run <code>qmake -project</code> to create a project file (<code>.pro</code> extension, with its name that of the containing directory, i.e., first).</p><pre class="brush: text; gutter: false; first-line: 1">$ cat first.pro
######################################################################
# Automatically generated by qmake (2.01a) Mon Nov 28 05:49:29 2011
######################################################################

TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .

# Input
SOURCES += main.cpp</pre><p>You can create both applications and libraries; the value of <code>TEMPLATE</code> is <code>app</code>, indicating this is an application. I will cover library development in later articles. The <code>SOURCES</code> entry lists source files in the project, about which  more details appear later in this article series.</p><p>Now, let us generate the <code>Makefile</code> with <code>qmake</code>. It&#8217;s a long file &#8212; it may contain up to 200 lines. Run <code>make</code> to create the executable file:</p><pre class="brush: text; gutter: false; first-line: 1">$ make
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -o main.o main.cpp
make: Circular all &lt;- first dependency dropped.
g++ -Wl,-O1 -o first main.o    -L/usr/lib -lQtGui -lQtCore -lpthread</pre><p>In the last line, you can see that our sample program uses the POSIX thread library too. Run the file with <code>./first</code> to see the output &#8220;Hello world&#8221;. It&#8217;s done! We have successfully compiled our first program.</p><h2>Sample GUI program</h2><p>Qt has an option to create UI files using a drag-and-drop method, which we will explore in the next article. For now, let us hand-code a sample simple GUI program:</p><pre class="brush: cpp; gutter: false; first-line: 1">

#include&lt;QApplication&gt;
#include&lt;QLabel&gt;

int main(int argc, char *argv[]){
    QApplication a(argc, argv);
    QLabel    label;
    label.setText(&quot;Hello World&quot;);
    label.show();
    a.exec();
}</pre><p>In the first example, there was no GUI. The program terminates when main returns. However, in GUI programs, we can&#8217;t do that, or the application will not be usable. We want the GUI to run until the user closes the window. To achieve this, run your program in a loop till this happens, so you use the event-loop-based class <code>QApplication</code>. When you create an object of this class and call its <code>exec()</code> function, main never returns. The application keeps on waiting for user input events.</p><p>The second header file contains the class <code>QLabel</code>, a simple widget used to display text. Instantiate it and set its text to &#8220;Hello World&#8221;. When a widget&#8217;s <code>show()</code> function is called, then it becomes a window. So the widget label will be seen like a window. In Figure 2, you can see the resultant label window with title bar. You can resize the output window simply with the help of the mouse.</p><div id="attachment_9423" class="wp-caption aligncenter" style="width: 422px"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/fig2.png?d9c344" alt="Widget label" title="Widget label" width="422" height="256" class="size-full wp-image-9423" /><p class="wp-caption-text">Figure 2: Widget label</p></div><p>In the next articles, we will cover the core classes of Qt. In the meanwhile, I suggest you go through the <a href="http://doc.qt.nokia.com/">official documentation</a>.</p><div class="imagecredit">Feature image courtesy: <a href="http://www.flickr.com/photos/nokia_fan/5072435170/">nokia_fan</a>. Reused under the terms of CC-BY-NC 2.0 License.</div><div id="crp_related"><h5>Related Posts:</h5><ul><li><a href="http://www.linuxforu.com/2011/12/loading-library-files-in-cpp/" rel="bookmark" class="crp_title">Loading Library Files in C++</a></li><li><a href="http://www.linuxforu.com/2011/06/qemu-for-embedded-systems-development-part-1/" rel="bookmark" class="crp_title">Using QEMU for Embedded Systems Development, Part 1</a></li><li><a href="http://www.linuxforu.com/2011/08/integrating-google-app-engine-and-eclipse/" rel="bookmark" class="crp_title">Integrating Google App Engine and Eclipse</a></li><li><a href="http://www.linuxforu.com/2011/08/joy-of-programming-calling-virtual-functions-from-constructors/" rel="bookmark" class="crp_title">Joy of Programming: Calling Virtual Functions from Constructors</a></li><li><a href="http://www.linuxforu.com/2011/10/lets-play-with-codeigniter/" rel="bookmark" class="crp_title">Let&#8217;s Play with CodeIgniter</a></li></ul></div>Tags: <a href="http://www.linuxforu.com/tag/application-development/" title="application development" rel="tag">application development</a>, <a href="http://www.linuxforu.com/tag/application-performance/" title="application performance" rel="tag">application performance</a>, <a href="http://www.linuxforu.com/tag/cc/" title="C/C++" rel="tag">C/C++</a>, <a href="http://www.linuxforu.com/tag/cpp/" title="cpp" rel="tag">cpp</a>, <a href="http://www.linuxforu.com/tag/desktop-applications/" title="desktop applications" rel="tag">desktop applications</a>, <a href="http://www.linuxforu.com/tag/gui/" title="GUI" rel="tag">GUI</a>, <a href="http://www.linuxforu.com/tag/java/" title="Java" rel="tag">Java</a>, <a href="http://www.linuxforu.com/tag/lfy-january-2012/" title="LFY January 2012" rel="tag">LFY January 2012</a>, <a href="http://www.linuxforu.com/tag/microsoft-windows/" title="Microsoft Windows" rel="tag">Microsoft Windows</a>, <a href="http://www.linuxforu.com/tag/posix/" title="POSIX" rel="tag">POSIX</a>, <a href="http://www.linuxforu.com/tag/qt/" title="Qt" rel="tag">Qt</a>, <a href="http://www.linuxforu.com/tag/qt-applications/" title="Qt applications" rel="tag">Qt applications</a>, <a href="http://www.linuxforu.com/tag/qt-creator/" title="Qt Creator" rel="tag">Qt Creator</a>, <a href="http://www.linuxforu.com/tag/qt-designer/" title="Qt Designer" rel="tag">Qt Designer</a>, <a href="http://www.linuxforu.com/tag/qt-development/" title="Qt development" rel="tag">Qt development</a>, <a href="http://www.linuxforu.com/tag/qt-gui-applications/" title="Qt GUI applications" rel="tag">Qt GUI applications</a>, <a href="http://www.linuxforu.com/tag/qt-linguist/" title="Qt Linguist" rel="tag">Qt Linguist</a>, <a href="http://www.linuxforu.com/tag/software-frameworks/" title="software frameworks" rel="tag">software frameworks</a>, <a href="http://www.linuxforu.com/tag/sun-microsystems/" title="Sun Microsystems" rel="tag">Sun Microsystems</a>, <a href="http://www.linuxforu.com/tag/symbian/" title="Symbian" rel="tag">Symbian</a>, <a href="http://www.linuxforu.com/tag/trolltech/" title="Trolltech" rel="tag">Trolltech</a>, <a href="http://www.linuxforu.com/tag/xml/" title="xml" rel="tag">xml</a><br /> ]]></content:encoded> <wfw:commentRss>http://www.linuxforu.com/2012/01/developing-applications-qt-part-1/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Working with MTD Devices</title><link>http://www.linuxforu.com/2012/01/working-with-mtd-devices/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=working-with-mtd-devices</link> <comments>http://www.linuxforu.com/2012/01/working-with-mtd-devices/#comments</comments> <pubDate>Tue, 31 Jan 2012 05:28:39 +0000</pubDate> <dc:creator>Mohan Lal Jangir</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[Developers]]></category> <category><![CDATA[application developers]]></category> <category><![CDATA[bad blocks]]></category> <category><![CDATA[C]]></category> <category><![CDATA[Data storage device]]></category> <category><![CDATA[Disk sector]]></category> <category><![CDATA[driver]]></category> <category><![CDATA[file systems]]></category> <category><![CDATA[flash devices]]></category> <category><![CDATA[flash memory]]></category> <category><![CDATA[flash memory chips]]></category> <category><![CDATA[Hard disk drive]]></category> <category><![CDATA[kernel]]></category> <category><![CDATA[kernel programmer]]></category> <category><![CDATA[LFY January 2012]]></category> <category><![CDATA[Memory Technology]]></category> <category><![CDATA[MTD]]></category> <category><![CDATA[MTD Devices]]></category> <category><![CDATA[NAND/NOR-based flash]]></category> <category><![CDATA[partitions]]></category> <category><![CDATA[removable media]]></category> <category><![CDATA[scheduler]]></category> <category><![CDATA[sd cards]]></category> <category><![CDATA[USB flash drive]]></category> <category><![CDATA[volatile data]]></category><guid isPermaLink="false">http://www.linuxforu.com/?p=9415</guid> <description><![CDATA[This article shows how kernel and application developers (in C) can make use of MTD in Linux. MTD (Memory Technology Devices) are NAND/NOR-based flash memory chips used for storing non-volatile data like boot...]]></description> <content:encoded><![CDATA[<p><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/mtd-590x315.png?d9c344" alt="Memory Technology Devices" title="Memory Technology Devices" width="590" height="315" class="aligncenter size-large wp-image-9418" /><div class="introduction">This article shows how kernel and application developers (in C) can make use of MTD in Linux.</div><p>MTD (Memory Technology Devices) are NAND/NOR-based flash memory chips used for storing non-volatile data like boot images and configurations. Readers are cautioned not to get confused with USB sticks, SD cards, etc., which are also called flash devices, but are not MTD devices. The latter are generally found on development boards, used to store boot loaders, an OS, etc.</p><p>Even though MTD devices are for data storage, they differ from hard disks and RAM in several aspects. The biggest difference is that while hard disk sectors are rewritable, MTD device sectors must be erased before rewriting &#8212; which is why they are more commonly called erase-blocks. Second, hard disk sectors can be rewritten several times without wearing out the hardware, but MTD device sectors have a limited life and are not usable after about 10^3-10^5 erase operations. The worn out erase-blocks are called bad blocks and the software must take care not to use such blocks.</p><p>Like hard disks, MTD devices can be partitioned and can therefore act as independent devices. On a system with one or more MTD devices, device and partition information can be obtained from the <code>/proc/mtd</code> file. A typical <code>/proc/mtd</code> file is as follows:</p><pre class="brush: text; gutter: false; first-line: 1">cat /proc/mtd
dev:  size    erasesize name
mtd0: 000a0000 00020000 &quot;misc&quot;
mtd1: 00420000 00020000 &quot;recovery&quot;
mtd2: 002c0000 00020000 &quot;boot&quot;
mtd3: 0fa00000 00020000 &quot;system&quot;
mtd4: 02800000 00020000 &quot;cache&quot;
mtd5: 0af20000 00020000 &quot;userdata&quot;</pre><p>A partitioned MTD device can be depicted as in Figure 1, which shows the relation between an MTD device, a partition and a sector.</p><div id="attachment_9416" class="wp-caption aligncenter" style="width: 450px"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/figure-1-an-MTD-Device.jpg?d9c344" alt="An MTD device" title="An MTD device" width="450" height="477" class="size-full wp-image-9416" /><p class="wp-caption-text">Figure 1: An MTD device</p></div><p>As already said, MTD write operations are different from usual storage devices. Therefore, before we move further, let&#8217;s understand how write operations take place on MTD devices. Figure 2 shows a typical write case.</p><div id="attachment_9417" class="wp-caption aligncenter" style="width: 590px"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/figure-2-590x172.jpg?d9c344" alt="An MTD write operation" title="An MTD write operation" width="590" height="172" class="size-large wp-image-9417" /><p class="wp-caption-text">Figure 2: An MTD write operation</p></div><p>The left-most part shows a sector that has some data at the end. The rest of the sector has not been written since the last erase. A user wants to write &#8220;new data 1&#8243; to this sector at offset 0. Since this part of the sector has already been erased, it is ready to be written and so &#8220;new data 1&#8243; can be directly written to the sector. Later, the user may want to write &#8220;new data 2&#8243;, again at offset 0. To do this, the sector must be erased. Since the sector needs to be erased in entirety, the &#8220;old data&#8221; must be backed up in a temporary buffer. After erasing the complete sector, the &#8220;new data 2&#8243; and &#8220;old data&#8221; must be written at appropriate offsets.</p><p>This procedure is the reason there are specific file systems for MTD devices, like JFFS2 and YAFFFS, and flash translation layers (FTL) like NFTL, INFTL, etc. These FTLs and file systems take special care of MTD device properties to hide complexity from the user.</p><p>In the first section that follows, we will look at how to access, read/write and erase MTD devices from Linux applications. The second section describes the same things in kernel space, so that this article can be useful to both application as well as kernel developers.</p><h2>Accessing MTDs from applications</h2><p>The user must know the device partition to work upon, which can be found from <code>/proc/mtd</code> as shown earlier. Assuming users want to work on the &#8220;userdata&#8221; partition, they must use the <code>/dev/mtd5</code> device.</p><p>The first thing to do is to get information about the MTD device. Use the <code>MEMGETINFO ioctl</code> command, as follows:</p><pre class="brush: c; gutter: true; first-line: 1">#include &lt;stdio.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;sys/ioctl.h&gt;
#include &lt;mtd/mtd-user.h&gt;

int main()
{
    mtd_info_t mtd_info;
    int fd = open(&quot;/dev/mtd5&quot;, O_RDWR);
ioctl(fd, MEMGETINFO, &amp;mtd_info);

    printf(&quot;MTD type: %u\n&quot;, mtd_info.type);
    printf(&quot;MTD total size : %u bytes\n&quot;, mtd_info.size);
    printf(&quot;MTD erase size : %u bytes\n&quot;, mtd_info.erasesize);

    return 0;
}</pre><p>Error handling has been omitted for brevity. The <code>mtd_info_t</code> structure is used with the <code>MEMGETINFO</code> command. The MTD type can be <code>MTD_ABSENT</code>, <code>MTD_RAM</code>, <code>MTD_ROM</code>, <code>MTD_NAND</code>, <code>MTD_NOR</code>, etc., which are defined in the <code>mtd/mtd-abi.h</code> header file. The <code>mtd_info.size</code> indicates the size of the whole device (i.e., the partition, in this case). Finally, <code>mtd_info.erasesize</code> indicates the sector size. During an erase operation, this is the minimum size that can be erased, as we&#8217;ll see later.</p><p>Reading MTD devices is similar to ordinary devices:</p><pre class="brush: c; gutter: false; first-line: 1">/* read something from last sector */
unsigned char buf[64];
lseek(fd, -mtd_info.erasesize, SEEK_END);
read(fd, buf, sizeof(buf));</pre><p>A write operation can be performed in the same way, provided the sector has been erased previously. Finally, we come to the erase operation. Here is an example of erasing a partition, sector by sector:</p><pre class="brush: c; gutter: false; first-line: 1">void erase_partition(mtd_info_t *mtd_info, int fd) {
    erase_info_t ei;
    ei.length = mtd_info-&gt;erasesize;
 
    for(ei.start = 0; ei.start &lt; mtd_info-&gt;size; ei.start += mtd_info-&gt;erasesize) {
        ioctl(fd, MEMUNLOCK, &amp;ei);
        ioctl(fd, MEMERASE, &amp;ei);
    }
}</pre><p>All sectors of the device are writeable after this erase operation. Notice the use of <code>MEMUNLOCK</code> before <code>MEMERASE</code>, which is essential to allow the erase operation.</p><h2>Accessing MTDs from kernel space</h2><p>This section will repeat the functions explained in the previous section, but in kernel space. This needs a separate section since the erase operation is more complex here  &#8211;  the erase operation may sleep and therefore the kernel programmer has to wait until the operation is completed. This is the case for applications too, but the sleep is transparently taken care of by the scheduler.</p><p>As explained earlier, the first MTD information is the <code>mtd_info</code> structure. This is retrieved by iterating through all registered MTD devices:</p><pre class="brush: c; gutter: true; first-line: 1">#include &lt;linux/kernel.h&gt;
#include &lt;linux/mtd/mtd.h&gt;
#include &lt;linux/err.h&gt;

static struct mtd_info *mtd_info = NULL;
 
int init_module(void) {
    int num;
    for(num = 0; num &lt; 64; num++) {
        mtd_info = get_mtd_device(NULL, num);
        if(IS_ERR(mtd_info)) {
            printk(&quot;No device for num %d\n&quot;, num);
            continue;
        }
        if(mtd_info-&gt;type == MTD_ABSENT) {
            put_mtd_device(mtd_info);
            continue;
        }
        if(strcmp(mtd_info-&gt;name, &quot;userdata&quot;)) {
            put_mtd_device(mtd_info);
            continue;
        }
        printk(&quot;MTD type: %u\n&quot;, mtd_info-&gt;type);
        printk(&quot;MTD total size : %u bytes\n&quot;, mtd_info-&gt;size);
        printk(&quot;MTD erase size : %u bytes\n&quot;, mtd_info-&gt;erasesize);
        return 0;
    }
    mtd_info = NULL;
    return 0;
}
 
void cleanup_module(void)

{

if(mtd_info)
        put_mtd_device(mtd_info);
}</pre><p>The above kernel module searches for the &#8220;userdata&#8221; partition. The function <code>get_mtd_device()</code>, when invoked with the first argument <code>NULL</code>, returns the MTD device associated with the minor number specified in the second argument. On a successful search, it increments the reference count of the device. That&#8217;s why, before exiting, a call to <code>put_mtd_device()</code> must be made to release (decrement) the reference count.</p><p>Additionally, the module uses the <code>flag MTD_ABSENT</code> (which is available to applications too). This check is required to function correctly with some probing device drivers used to allocate placeholder MTD devices on systems that have socketed or removable media.</p><p>Having retrieved the <code>mtd_info</code> structure, reading is relatively simple:</p><pre class="brush: c; gutter: false; first-line: 1">/* read something from last sector */
u_char buf[64];

mtd_info-&gt;read(mtd_info, mtd_info.size-mtd_info.erasesize, sizeof(buf), buf);</pre><p>The second argument of the read function specifies the read offset, and the third the length to read. Note that the read operation too may sleep and, therefore, it must not be performed in an interrupt context. The write operation can be performed as follows (assuming the sector has been previously erased):</p><pre class="brush: c; gutter: false; first-line: 1">/* write something to last sector */
mtd_info-&gt;write(mtd_info, mtd_info.size-mtd_info.erasesize, sizeof(buf), buf);</pre><p>As mentioned before, the read, write and erase operations may sleep. Therefore, kernel code must wait for the operation to finish. Here is an example of erasing the partition and waiting to finish the operation:</p><pre class="brush: c; gutter: false; first-line: 1">#include &lt;linux/sched.h&gt;

void erase_partition(struct mtd_info *mtd_info) {
    unsigned int start;
    for(start = 0; start &lt; mtd_info-&gt;size; start += mtd_info-&gt;erasesize)
        erase_sector(mtd_info, start, mtd_info-&gt;erasesize);
}
 
void erase_sector(struct mtd_info *mtd_info, unsigned int start, unsigned int len) 

{
    int ret;
    struct erase_info ei = {0};
    wait_queue_head_t waitq;
    DECLARE_WAITQUEUE(wait, current);
    
    init_waitqueue_head(&amp;waitq);
    ei.addr = start;
    ei.len = mtd_info-&gt;erasesize;
    ei.mtd = mtd_info;
    ei.callback = erase_callback;
    ei.priv = (unsigned long)&amp;waitq;
    ret = mtd_info-&gt;erase(mtd_info, &amp;ei);
    if(!ret)     {
        set_current_state(TASK_UNINTERRUPTIBLE);
        add_wait_queue(&amp;waitq, &amp;wait);
        if (ei.state != MTD_ERASE_DONE &amp;&amp; ei.state != MTD_ERASE_FAILED)
            schedule();
        remove_wait_queue(&amp;waitq, &amp;wait);
        set_current_state(TASK_RUNNING);
 
        ret = (ei.state == MTD_ERASE_FAILED)?-EIO:0;
    }
}
 
void erase_callback (struct erase_info *instr) {
    wake_up((wait_queue_head_t *)instr-&gt;priv);
}</pre><p>The <code>erase_partition()</code> function iterates over all sectors, and erases them with <code>erase_sector()</code>. At the core of <code>erase_sector()</code> is the <code>mtd_info-&gt;erase</code> call, which (as mentioned previously) may sleep. Therefore, <code>erase_sector()</code> prepares a wait queue and a wait queue head.</p><p>After a call to <code>mtd_info-&gt;erase</code>, the function prepares itself to relinquish the CPU (presuming that <code>mtd_info-&gt;erase</code> will sleep) by changing task state to <code>TASK_UNINTERRUPTIBLE</code> and adding itself to the wait queue head. Before relinquishing the CPU, it checks if erase is done, through the <code>ei.state</code> flag. If erase is done successfully, this flag will be set to <code>MTD_ERASE_DONE</code>.</p><p>If the erase operation is not complete, the task relinquishes the CPU by calling <code>schedule()</code>. Later, when the erase operation is complete, the driver calls the callback function provided in <code>ei.callback</code>. Here the task wakes up to itself, then removes itself from the wait queue, changes the task state to <code>TASK_RUNNING</code> and finally, the <code>erase_sector()</code> function returns.</p><p>MTD devices have many more features that can be used by application programmers. ECC (error correction codes) and OOB (out of band) data are some of them. The MTD framework is integrated into the Linux kernel &#8212; therefore it makes working with MTD devices very simple, as we have seen in this article.<div id="crp_related"><h5>Related Posts:</h5><ul><li><a href="http://www.linuxforu.com/2012/01/device-drivers-partitions-hard-disk/" rel="bookmark" class="crp_title">Device Drivers, Part 14: A Dive Inside the Hard Disk for Understanding Partitions</a></li><li><a href="http://www.linuxforu.com/2011/12/loading-library-files-in-cpp/" rel="bookmark" class="crp_title">Loading Library Files in C++</a></li><li><a href="http://www.linuxforu.com/2011/05/decoding-character-device-file-operations/" rel="bookmark" class="crp_title">Device Drivers, Part 6: Decoding Character Device File Operations</a></li><li><a href="http://www.linuxforu.com/2011/12/data-transfers-to-from-usb-devices/" rel="bookmark" class="crp_title">Device Drivers, Part 13: Data Transfer to and from USB Devices</a></li><li><a href="http://www.linuxforu.com/2011/11/socket-api-part-4-datagrams/" rel="bookmark" class="crp_title">The Socket API, Part 4: Datagrams</a></li></ul></div>Tags: <a href="http://www.linuxforu.com/tag/application-developers/" title="application developers" rel="tag">application developers</a>, <a href="http://www.linuxforu.com/tag/bad-blocks/" title="bad blocks" rel="tag">bad blocks</a>, <a href="http://www.linuxforu.com/tag/c/" title="C" rel="tag">C</a>, <a href="http://www.linuxforu.com/tag/data-storage-device/" title="Data storage device" rel="tag">Data storage device</a>, <a href="http://www.linuxforu.com/tag/disk-sector/" title="Disk sector" rel="tag">Disk sector</a>, <a href="http://www.linuxforu.com/tag/driver/" title="driver" rel="tag">driver</a>, <a href="http://www.linuxforu.com/tag/file-systems/" title="file systems" rel="tag">file systems</a>, <a href="http://www.linuxforu.com/tag/flash-devices/" title="flash devices" rel="tag">flash devices</a>, <a href="http://www.linuxforu.com/tag/flash-memory/" title="flash memory" rel="tag">flash memory</a>, <a href="http://www.linuxforu.com/tag/flash-memory-chips/" title="flash memory chips" rel="tag">flash memory chips</a>, <a href="http://www.linuxforu.com/tag/hard-disk-drive/" title="Hard disk drive" rel="tag">Hard disk drive</a>, <a href="http://www.linuxforu.com/tag/kernel/" title="kernel" rel="tag">kernel</a>, <a href="http://www.linuxforu.com/tag/kernel-programmer/" title="kernel programmer" rel="tag">kernel programmer</a>, <a href="http://www.linuxforu.com/tag/lfy-january-2012/" title="LFY January 2012" rel="tag">LFY January 2012</a>, <a href="http://www.linuxforu.com/tag/memory-technology/" title="Memory Technology" rel="tag">Memory Technology</a>, <a href="http://www.linuxforu.com/tag/mtd/" title="MTD" rel="tag">MTD</a>, <a href="http://www.linuxforu.com/tag/mtd-devices/" title="MTD Devices" rel="tag">MTD Devices</a>, <a href="http://www.linuxforu.com/tag/nandnor-based-flash/" title="NAND/NOR-based flash" rel="tag">NAND/NOR-based flash</a>, <a href="http://www.linuxforu.com/tag/partitions/" title="partitions" rel="tag">partitions</a>, <a href="http://www.linuxforu.com/tag/removable-media/" title="removable media" rel="tag">removable media</a>, <a href="http://www.linuxforu.com/tag/scheduler/" title="scheduler" rel="tag">scheduler</a>, <a href="http://www.linuxforu.com/tag/sd-cards/" title="sd cards" rel="tag">sd cards</a>, <a href="http://www.linuxforu.com/tag/usb-flash-drive/" title="USB flash drive" rel="tag">USB flash drive</a>, <a href="http://www.linuxforu.com/tag/volatile-data/" title="volatile data" rel="tag">volatile data</a><br /> ]]></content:encoded> <wfw:commentRss>http://www.linuxforu.com/2012/01/working-with-mtd-devices/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Building Image Processing Embedded Systems using Python, Part 1</title><link>http://www.linuxforu.com/2012/01/building-image-processing-embedded-systems-using-python-part-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=building-image-processing-embedded-systems-using-python-part-1</link> <comments>http://www.linuxforu.com/2012/01/building-image-processing-embedded-systems-using-python-part-1/#comments</comments> <pubDate>Mon, 30 Jan 2012 17:48:27 +0000</pubDate> <dc:creator>Jayneil Dalal</dc:creator> <category><![CDATA[Developers]]></category> <category><![CDATA[Home / Quick Tips]]></category> <category><![CDATA[How-Tos]]></category> <category><![CDATA[Android]]></category> <category><![CDATA[Arduino]]></category> <category><![CDATA[C]]></category> <category><![CDATA[embedded systems]]></category> <category><![CDATA[embedded vision]]></category> <category><![CDATA[Image processing]]></category> <category><![CDATA[LFY January 2012]]></category> <category><![CDATA[matlab]]></category> <category><![CDATA[OMAP4430]]></category> <category><![CDATA[OpenCV]]></category> <category><![CDATA[PandaBoard]]></category> <category><![CDATA[portable solution]]></category> <category><![CDATA[Pyserial]]></category> <category><![CDATA[python]]></category> <category><![CDATA[signal processing]]></category><guid isPermaLink="false">http://www.linuxforu.com/?p=9402</guid> <description><![CDATA[The first part of this three-part series gives a brief overview of the embedded vision and the various components required to make it work. It also covers the installation procedure for the OpenCV...]]></description> <content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-9408" title="Python" src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/python.jpg?d9c344" alt="Python" width="300" height="272" /></p><div class="introduction">The first part of this three-part series gives a brief overview of the embedded vision and the various components required to make it work. It also covers the installation procedure for the OpenCV library.</div><p>Modern life is incomplete without gadgets, smartphones, automated appliances, et al. These electronic devices aide us in our daily grind, making our otherwise mundane/hectic life a bit easier. So what controls these devices? In layman&#8217;s language, it&#8217;s a small circuit with preprogrammed human logic, called an embedded system. Listed below are some useful definitions.</p><ul><li><strong>Embedded system (ES):</strong> An embedded system is some combination of computer hardware and software, either fixed in capability or programmable, that is specifically designed for a particular function. Industrial machines, automobiles, medical equipment, cameras, household appliances, air-planes, vending machines and toys (as well as the more obvious cellular phone and PDA) are among the myriad possible hosts of an embedded system.</li><li><strong>Image processing:</strong> In electrical engineering and computer science, image processing is any form of signal processing for which the input is an image, such as a photograph or video frame. The output of image processing may be either an image, or a set of characteristics or parameters related to the image. Most image-processing techniques involve treating the image as a two-dimensional signal, and applying standard signal-processing techniques to it. In other words, it is basically the transformation of data from a still or video camera into either a decision or a new representation. All such transformations are done to achieve some particular goal. The input data may be a live video feed, the decision may be that a face has been detected, and a new representation may be conversion of a colour image into a greyscale image.</li><li><strong>Embedded vision:</strong> Embedded vision is the merging of two technologies &#8212; embedded systems and image-processing/computer vision (also sometimes referred to as machine vision). Due to the emergence of very powerful, low-cost and energy-efficient processors, it has become possible to incorporate vision capabilities into a wide range of embedded systems. One successful example is the Microsoft Kinect video game controller, which uses embedded vision to track the movements of Xbox 360 users, avoiding the need for handheld controllers. Microsoft sold eight million Kinect units in the first two months after its introduction.</li></ul><p>Moving on, the five basic components required to build an embedded system using Python are discussed below, in brief.</p><h2>The operating system (OS)</h2><p>The OS is the heart of an embedded vision system. Many different dependencies that are required to run software are provided by the OS, which is the interface between the hardware and the software. Of the many OSs in the market (such as Windows, Linux, etc.) there are reasons why Linux is preferable:</p><ul><li>It is open source, i.e., it is free of cost and free, as in &#8220;freedom&#8221;.</li><li>It is virtually virus-free.</li><li>It has pretty good support &#8212; bug trackers, documentation, forums, mailing lists, IRC, etc.</li><li>It is easy on systems resources &#8212; that is, more resources can be dedicated to applications.</li></ul><p>There are various Linux distributions like Ubuntu, Fedora, etc., to choose from. I personally prefer Ubuntu, because of its easy learning curve. Now, size is the main constraint for an embedded system. Using a PC OS won&#8217;t do. A much more portable solution is required, such as the <a href="http://pandaboard.org/">PandaBoard</a>shown in Figure 1.</p><div id="attachment_9405" class="wp-caption aligncenter" style="width: 590px"><a href="http://cdn.linuxforu.com/wp-content/uploads/2012/01/Fig11.jpg?d9c344"><img class="size-large wp-image-9405" title="PandaBoard" src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/Fig11-590x419.jpg?d9c344" alt="PandaBoard" width="590" height="419" /></a><p class="wp-caption-text">Figure 1: PandaBoard</p></div><p>Check out its specs:</p><ul><li>OMAP4 (Cortex-A9) CPU-based open development platform</li><li>OMAP4430 Application processor</li><li>1 GB low-power DDR2 RAM</li><li>Display HDMI v1.3 Connector (Type A) to drive HD displays, DVI-D Connector</li><li>8.89cm audio in/out and HDMI Audio out</li><li>Full-size SD/MMC card</li><li>Built-in 802.11 and Bluetooth v2.1+EDR</li><li>Onboard 10/100 Ethernet</li><li>Expansion: 1xUSB OTG, 2xUSB HS host ports, general-purpose expansion header</li></ul><p>PandaBoard is such a powerful mobile computing platform that one can port various OSs like Android and Ubuntu 10.04 to it!</p><h2>Image-Processing (IP) software</h2><p>There are many software and libraries available for image processing, like MATLAB, OpenCV, etc. Licensing costs for MATLAB are very high, but OpenCV is preferable since:</p><ul><li>It is free.</li><li>It is fast.</li><li>Has good documentation, tutorials, user groups, forums, etc.</li><li>There are a lot of prebuilt functions and algorithms to get a head start.</li><li>There is active development on interfaces for other languages like Ruby, Python, MATLAB, etc.</li></ul><p>OpenCV grew out of an Intel Research initiative to advance CPU-intensive applications. The intent behind OpenCV was to provide a platform that a student could readily use for developing applications, instead of reinventing basic functions from scratch. Figure 2 is a block diagram showing the different modules in OpenCV. Check out the documentation <a href="http://opencv.itseez.com/">here</a>.</p><div id="attachment_9406" class="wp-caption aligncenter" style="width: 590px"><img class="size-large wp-image-9406" title="OpenCV modules" src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/Fig2-OpenCV_modules-590x319.jpg?d9c344" alt="OpenCV modules" width="590" height="319" /><p class="wp-caption-text">Figure 2: OpenCV modules</p></div><h2>Arduino</h2><p>To make any changes in the external environment, we need a hardware circuit with a &#8220;brain&#8221;. This role can be filled by any microcontroller or microprocessor. Various companies such as Texas Instruments, NXP, Maxim, Atmel, etc., make microcontrollers.</p><p>A microcontroller cannot be directly used in a circuit, as is. A full development circuit board has to be made, providing access to different pins of the microcontroller. This process is not easy, as it involves designing the circuit, soldering, etc. All changes are permanent. Also, a program loader has to be made to load the code from the computer into the microcontroller. This can be quite cumbersome, so <a href="http://www.arduino.cc/">Arduino</a> is used, due to the following reasons:</p><ul><li>It is open source, so all schematics are available and you can design the same board on your own.</li><li>It is based on the concept of breadboard prototyping, which encourages the use of hook-up wires and breadboard, to make a circuit which can be easily modified later. This avoids the hassles of soldering.</li><li>There are a number of tutorials, tons of code, forums, etc., to help beginners.</li><li>The design of the board and IDE is so simple that one does not have to be an engineer to use it. Even a middle school student can use it.</li><li>It is pretty cheap compared to other available development boards.</li></ul><p>There are various versions of Arduino to choose from, such as Uno, Mega, Lilypad, etc. I personally prefer the Arduino Mega (Figure 3), which is a microcontroller board based on the ATmega1280.</p><div id="attachment_9407" class="wp-caption aligncenter" style="width: 590px"><a href="http://cdn.linuxforu.com/wp-content/uploads/2012/01/Fig3.jpg?d9c344"><img class="size-large wp-image-9407" title="Arduino Mega" src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/Fig3-590x302.jpg?d9c344" alt="Arduino Mega" width="590" height="302" /></a><p class="wp-caption-text">Figure 3: Arduino Mega</p></div><p>It has 54 digital input/output pins, of which 14 can be used as PWM (Pulse-width modulation) outputs, 16 analogue inputs, 4 UARTs (hardware serial ports), a 16 MHz crystal oscillator, a USB connection, a power jack, an ICSP header, and a reset button. It contains everything needed to support the microcontroller; simply connect it to a computer with a USB cable, or power it with an AC-to-DC adaptor or battery to get started.</p><h2>Pyserial</h2><p>This is a <a href="http://pyserial.sourceforge.net/">library</a> that provides Python support for serial connections (RS-232) over a variety of different devices: old-style serial ports, Bluetooth dongles, infra-red ports, and so on. It also supports remote serial ports via RFC 2217 (since V2.5). We use this for communication with the external hardware (Arduino). This library is easy to use, and has good documentation.</p><h2>Python</h2><p>Python is a general-purpose, high-level programming language whose design philosophy emphasises code readability. Python claims to combine remarkable power with very clear syntax, and its standard library is large and comprehensive.</p><h2>OpenCV installation</h2><p>Let us now proceed to OpenCV installation. All commands are meant to be run in a terminal.</p><ol><li>Install all prerequisites as shown below:<pre class="brush: text; gutter: false; first-line: 1">sudo apt-get install build-essential
sudo apt-get install cmake
sudo apt-get install pkg-config
sudo apt-get install libpng12-0 libpng12-dev libpng++-dev libpng3
sudo apt-get install libpnglite-dev libpngwriter0-dev libpngwriter0c2
sudo apt-get install zlib1g-dbg zlib1g zlib1g-dev
sudo apt-get install libjasper-dev libjasper-runtime libjasper1
sudo apt-get install pngtools libtiff4-dev libtiff4 libtiffxx0c2 libtiff-tools
sudo apt-get install libjpeg8 libjpeg8-dev libjpeg8-dbg libjpeg-prog
sudo apt-get install ffmpeg libavcodec-dev libavcodec52 libavformat52 libavformat-dev
sudo apt-get install libgstreamer0.10-0-dbg libgstreamer0.10-0 libgstreamer0.10-dev
sudo apt-get install libxine1-ffmpeg libxine-dev libxine1-bin
sudo apt-get install libunicap2 libunicap2-dev
sudo apt-get install libdc1394-22-dev libdc1394-22 libdc1394-utils
sudo apt-get install swig
sudo apt-get install libv4l-0 libv4l-dev
sudo apt-get install python-numpy
sudo apt-get install build-essential libgtk2.0-dev libjpeg62-dev libtiff4-dev libjasper-dev \
libopenexr-dev cmake python-dev python-numpy libtbb-dev libeigen2-dev yasm libfaac-dev \
libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev</pre></li><li>Install Python development headers with <code>sudo apt-get install python-dev</code>.</li><li>Download the <a href="http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/2.3/">OpenCV source code</a>. It is recommended that you move the downloaded OpenCV package to your <code>/home/&lt;user&gt;</code> directory. With that as your current directory, extract the archive, as follows:<pre class="brush: text; gutter: false; first-line: 1">tar -xvf OpenCV-2.3.1a.tar.bz2
cd OpenCV-2.3.1/</pre></li><li>Make a new directory called build and cd into it (mkdir build; cd build).</li><li>Run Cmake:<pre class="brush: text; gutter: false; first-line: 1">cmake -D WITH_TBB=ON -D BUILD_NEW_PYTHON_SUPPORT=ON -D WITH_V4L=OFF-D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D BUILD_EXAMPLES=ON ..</pre></li><li>Follow this with <code>make</code> and <code>sudo make install</code> (to install the library).</li><li>Next, configure the system to use the new OpenCV shared libraries. Edit a configuration file with <code>sudo gedit /etc/ld.so.conf.d/opencv.conf</code>. Add the following line at the end of the file (it may be an empty file, which is okay) and then save it:<pre class="brush: text; gutter: false; first-line: 1">/usr/local/lib</pre></li><li>Close the file and run <code>sudo ldconfig</code>.</li><li>Open your system <code>bashrc</code> file (for me, that is <code>sudo gedit /etc/bash.bashrc</code>) and add the following code at the end of the file:<pre class="brush: text; gutter: false; first-line: 1">PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
export PKG_CONFIG_PATH</pre></li><li>Save and close the file, then log out and log in again, or reboot the system.</li></ol><p>In the second part of this series, I plan to cover the basics and functions of OpenCV, and then how to develop image-processing programs based on it. In the third (and final) part, I will cover Arduino and Pyserial programming, as well as how to integrate all five components to finally build an embedded system for image processing.</p><div class="note">Acknowledgement: I would really like to thank my colleagues Sohil Patel and Samarth Shah for their help and support. I would also like to thank Prof N.P Gajjar and Prof Dhaval Shah for their guidance.</div><div class="imagecredit">Feature image courtesy: <a href="http://www.flickr.com/photos/mrtopf/2050489689/">Christian Scholz</a>. Reused under the terms of CC-BY-NC 2.0 License.</div><div id="crp_related"><h5>Related Posts:</h5><ul><li><a href="http://www.linuxforu.com/2011/09/recover-deleted-files-in-linux/" rel="bookmark" class="crp_title">Recover Deleted Files in Linux</a></li><li><a href="http://www.linuxforu.com/2011/05/quick-quide-to-qemu-setup/" rel="bookmark" class="crp_title">The Quick Guide to QEMU Setup</a></li><li><a href="http://www.linuxforu.com/2011/05/how-to-remaster-ubuntu-to-get-a-customised-distribution/" rel="bookmark" class="crp_title">How to Remaster Ubuntu to Get a Customised Distribution</a></li><li><a href="http://www.linuxforu.com/2012/01/developing-applications-qt-part-1/" rel="bookmark" class="crp_title">Developing Applications on QT, Part 1</a></li><li><a href="http://www.linuxforu.com/2011/11/exploring-software-new-look-plone-4/" rel="bookmark" class="crp_title">Exploring Software: The New-Look Plone 4</a></li></ul></div>Tags: <a href="http://www.linuxforu.com/tag/android/" title="Android" rel="tag">Android</a>, <a href="http://www.linuxforu.com/tag/arduino/" title="Arduino" rel="tag">Arduino</a>, <a href="http://www.linuxforu.com/tag/c/" title="C" rel="tag">C</a>, <a href="http://www.linuxforu.com/tag/embedded-systems/" title="embedded systems" rel="tag">embedded systems</a>, <a href="http://www.linuxforu.com/tag/embedded-vision/" title="embedded vision" rel="tag">embedded vision</a>, <a href="http://www.linuxforu.com/tag/image-processing/" title="Image processing" rel="tag">Image processing</a>, <a href="http://www.linuxforu.com/tag/lfy-january-2012/" title="LFY January 2012" rel="tag">LFY January 2012</a>, <a href="http://www.linuxforu.com/tag/matlab/" title="matlab" rel="tag">matlab</a>, <a href="http://www.linuxforu.com/tag/omap4430/" title="OMAP4430" rel="tag">OMAP4430</a>, <a href="http://www.linuxforu.com/tag/opencv/" title="OpenCV" rel="tag">OpenCV</a>, <a href="http://www.linuxforu.com/tag/pandaboard/" title="PandaBoard" rel="tag">PandaBoard</a>, <a href="http://www.linuxforu.com/tag/portable-solution/" title="portable solution" rel="tag">portable solution</a>, <a href="http://www.linuxforu.com/tag/pyserial/" title="Pyserial" rel="tag">Pyserial</a>, <a href="http://www.linuxforu.com/tag/python/" title="python" rel="tag">python</a>, <a href="http://www.linuxforu.com/tag/signal-processing/" title="signal processing" rel="tag">signal processing</a><br /> ]]></content:encoded> <wfw:commentRss>http://www.linuxforu.com/2012/01/building-image-processing-embedded-systems-using-python-part-1/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>NewSQL &#8212; The New Way to Handle Big Data</title><link>http://www.linuxforu.com/2012/01/newsql-handle-big-data/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=newsql-handle-big-data</link> <comments>http://www.linuxforu.com/2012/01/newsql-handle-big-data/#comments</comments> <pubDate>Mon, 30 Jan 2012 07:38:19 +0000</pubDate> <dc:creator>Prasanna Venkatesh</dc:creator> <category><![CDATA[Developers]]></category> <category><![CDATA[Overview]]></category> <category><![CDATA[Sysadmins]]></category> <category><![CDATA[Technology]]></category> <category><![CDATA[451 Group]]></category> <category><![CDATA[acid]]></category> <category><![CDATA[analytics systems]]></category> <category><![CDATA[big data]]></category> <category><![CDATA[CouchDB]]></category> <category><![CDATA[data availability]]></category> <category><![CDATA[data management]]></category> <category><![CDATA[data management solutions]]></category> <category><![CDATA[data processing]]></category> <category><![CDATA[data storage]]></category> <category><![CDATA[database systems]]></category> <category><![CDATA[database technology]]></category> <category><![CDATA[databases]]></category> <category><![CDATA[enterprise applications]]></category> <category><![CDATA[exabytes]]></category> <category><![CDATA[Facebook]]></category> <category><![CDATA[Google]]></category> <category><![CDATA[high availability]]></category> <category><![CDATA[information management systems]]></category> <category><![CDATA[LFY January 2012]]></category> <category><![CDATA[LinkedIn]]></category> <category><![CDATA[Matthew Aslett]]></category> <category><![CDATA[MySQL]]></category> <category><![CDATA[NewSQL]]></category> <category><![CDATA[NoSQL]]></category> <category><![CDATA[NoSQL solutions]]></category> <category><![CDATA[OLTP]]></category> <category><![CDATA[performance requirements]]></category> <category><![CDATA[processing power]]></category> <category><![CDATA[RDBMS]]></category> <category><![CDATA[real-time transactions]]></category> <category><![CDATA[Relational Database]]></category> <category><![CDATA[Twitter]]></category> <category><![CDATA[web applications]]></category><guid isPermaLink="false">http://www.linuxforu.com/?p=9359</guid> <description><![CDATA[Big data, big data, big data! This term has been dominating information management for a while, leading to enhancements in systems, primarily databases, to handle this revolution. Though there are many alternative information...]]></description> <content:encoded><![CDATA[<p><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/NewSQL-Distribution.jpg?d9c344" alt="NewSQL Distribution" title="NewSQL Distribution" width="300" height="313" class="alignright size-full wp-image-9366" /><div class="introduction">Big data, big data, big data! This term has been dominating information management for a while, leading to enhancements in systems, primarily databases, to handle this revolution. Though there are many alternative information management systems available for users, in this article, we share our perspective on a new type, termed NewSQL, which caters to the growing data in OLTP systems.</div><p>Everywhere we look in today&#8217;s data management landscape, the volume of information is soaring. According to one estimate, the data created in 2010 is about 1,200 exabytes, and will grow to nearly 8,000 exabytes by 2015, with the Internet/Web being the primary data driver and consumer.</p><p>This growth is outpacing the growth of storage capacity, leading to the emergence of information management systems where data is stored in a distributed way, but accessed and analysed as if it resides on a single machine (Figure 1).</p><div id="attachment_9363" class="wp-caption aligncenter" style="width: 500px"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/NewSQL-Distribution-Fig.1.jpg?d9c344" alt="Distributed data storage" title="Distributed data storage" width="500" height="310" class="size-full wp-image-9363" /><p class="wp-caption-text">Figure 1: Distributed data storage</p></div><p>Besides resolving the data size problem, these solutions also need to cater to massive performance requirements to ensure timeliness of data processing. Unfortunately, an increase in processing power does not directly translate to faster data access, triggering a rethink on existing database systems.</p><p>To understand the enormity of data volumes, let&#8217;s look at a couple of figures:  Facebook needs to store 135 billion messages a month. Twitter has the problem of storing 7 TB of data per day, with the prospect of this requirement doubling multiple times per year. Criticality of data and continuity in data availability has become more important than ever. We expect data to be available 24&#215;7 and from everywhere.</p><p>This brings in the third dimension of high availability and durability. So we have to factor in high availability without any single point of failure, which has traditionally been a telecom forte. These challenges have created a new wave in database processing solutions, which manage data in both structured<br /> and unstructured ways.</p><p>Legacy information management systems are characterised by monolithic relational databases, disk/tape-based stores (as memory in huge quantities is scarce or expensive), vendor lock-in and limited enterprise-level scalability. With the advent of the cloud, new data management solutions are emerging to handle distributed (relational/non-relational) content on open platforms at the speed of a mouse-click.</p><h2>NoSQL</h2><p>One of the key advances in resolving the &#8220;big-data&#8221; problem has been the emergence of NoSQL as an alternative database technology. NoSQL (sometimes expanded to &#8220;not only SQL&#8221;) is a broad class of DBMS that differ significantly from the classic RDBMS model. These data stores may not require fixed table schemas, usually avoid join operations and typically scale horizontally.</p><p>NoSQL solutions have carved a niche market for themselves as key-value stores, document databases, graph databases and big-tables. Use cases for these solutions in Web applications are a dime a dozen. They are used everywhere &#8212; whether it is in Web-based social interactions like online gaming/networking, or revenue maximising decisions like ad offerings, and not to mention basic operations like searching the Internet. Figure 2 shows the architecture of a famous NoSQL database (CouchDB) written in Erlang.</p><div id="attachment_9365" class="wp-caption aligncenter" style="width: 464px"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/NewSQL-Cassandra-Fig.2.jpg?d9c344" alt="CouchDB architecture" title="CouchDB architecture" width="464" height="505" class="size-full wp-image-9365" /><p class="wp-caption-text">Figure 2: CouchDB architecture</p></div><p>But, is NoSQL the answer to all problems? In spite of the technological acumen provided by NoSQL solutions, the RDBMS users in enterprises are reluctant to switch to it. Why?</p><p>The greatest deployment of traditional RDBMS is primarily in enterprises, for everything the enterprise does, whether storing customer information, internal financials, employee information or anything else. Is such data growing? Yes, so big-data issues are relevant to them. So why not NoSQL?</p><p>Even though there are varieties of NoSQL offerings, they are typically characterised by lack of SQL support, and non-adherence to ACID (Atomicity, Consistency, Isolation and Durability) properties. (Here, we will not go into the technical reasons for this.)</p><p>So while NoSQL could help enterprises manage large distributed data, enterprises cannot afford to lose the ACID properties &#8212; which were the key reasons for choosing an RDBMS in the first place. Also, since NoSQL solutions don&#8217;t provide SQL support, which most current enterprise applications require, this pushes enterprises away from NoSQL.</p><p>Hence, a new set of data-management solutions are emerging to address large data OLTP concerns, without sacrificing ACID and SQL interfaces.</p><h2>Why is traditional OLTP insufficient?</h2><p>We have already discussed the fact that there is an explosion in the OLTP data space. For example, more widely used social network sites (like Facebook and Linkedin) lead to larger OLTP requirements. Each user of such sites requires credentials and user profile information to be stored, generally in some OLTP database, even though the actual user data is stored in a NoSQL data-store. Facebook&#8217;s 750 million users require a very large OLTP database.</p><p>While growing OLTP data is a direct contributor, business requirements also force non-OLTP data to be managed as OLTP. Let&#8217;s look at the example of how analytics (which is the quintessential OLAP application) has led to the scalability requirements of OLTP.</p><h2>Case study: Real-time analytics</h2><p>In the earlier days, analytics were performed on historic data with specialised data warehouse solutions, mostly using an ETL (Extract, Transform and Load) approach. Data extracted from OLTP systems was fed to data warehouse systems capable of handling voluminous data. Real-time analytics is an approach that enables business users to get up-to-the-minute data by directly accessing business operational systems or feeding real-time transactions to analytics systems.</p><p>For example, previously Google Analytics analysed past performance &#8212; but recently, Google launched <em>Google Analytics: Real Time</em>, which shows a set of new reports on what&#8217;s happening on their site, as it happens.</p><p>Even though traditional OLTP systems provide ACID, they are not well equipped to handle the volume of data seen because of new innovative business scenarios like real-time analytics. A combination of traditional OLTP systems and analytics systems might under-utilise the analytics systems, due to scalability limitations and the performance of traditional OLTP systems.</p><h2>Welcome NewSQL</h2><p>To address big-data OLTP business scenarios that neither traditional OLTP systems nor NoSQL systems address, alternative database systems have evolved, collectively named NewSQL systems. This term was coined by the 451 Group, in their <a href="https://www.451research.com/report-long?icid=1651">now famous report, &#8220;NoSQL, NewSQL and Beyond&#8221;</a>.</p><p>The term NewSQL was used to categorise these new alternative database systems. 451 Group&#8217;s senior analyst, Matthew Aslett, clarified the meaning of the term NewSQL (in his blog) as follows: &#8220;NewSQL is our shorthand for the various new scalable/high-performance SQL database vendors. We have previously referred to these products as &#8220;ScalableSQL&#8221; to differentiate them from the incumbent relational database products. Since this implies horizontal scalability, which is not necessarily a feature of all products, we adopted the term NewSQL in the new report. And to clarify, like NoSQL, NewSQL is not to be taken too literally: the new thing about the NewSQL vendors is the vendor, not the SQL. NewSQL is a set of various new scalable/high-performance SQL database vendors (or databases). These vendors have designed solutions to bring the benefits of the relational model to the distributed architecture, and improve the performance of relational databases to an extent that the scalability is no longer an issue.&#8221;</p><p>Figure 3 is an architectural example of one of the NewSQL solutions (dbShards).</p><div id="attachment_9364" class="wp-caption aligncenter" style="width: 590px"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/NewSQL-dbshards-overview-Fig.3-590x354.jpg?d9c344" alt="dbShards" title="dbShards" width="590" height="354" class="size-large wp-image-9364" /><p class="wp-caption-text">Figure 3: dbShards</p></div><h2>Technical characteristics of NewSQL solutions</h2><ol><li>SQL as the primary mechanism for application interaction.</li><li>ACID support for transactions.</li><li>A non-locking concurrency control mechanism so real-time reads will not conflict with writes, and thus cause them to stall.</li><li>An architecture providing much higher per-node performance than available from traditional RDBMS solutions.</li><li>A scale-out, shared-nothing architecture, capable of running on a large number of nodes without suffering bottlenecks.</li></ol><p>The expectation is that NewSQL systems are about 50 times faster than traditional OLTP RDBMS.</p><p>Similar to NoSQL, there are many categories of NewSQL solutions. Now we can look at these categorisations and their characteristics.</p><h2>NewSQL categorisation</h2><p>Categorisation is based on the different approaches adopted by vendors to preserve the SQL interface, and address the scalability and performance concerns of traditional OLTP solutions.</p><ol><li><strong>New databases:</strong> These NewSQL systems are newly designed from scratch to achieve scalability and performance. Of course, some (hopefully minor) changes to the code will be required and data migration is still needed. One of the key considerations in improving the performance is making non-disk (memory) or new kinds of disks (flash/SSD) the primary data store. Solutions can be software-only (VoltDB, NuoDB and Drizzle) or supported as an appliance (Clustrix, Translattice). Examples of offerings are Clustrix, NuoDB and Translattice (commercial); and VoltDB, Drizzle, etc., (open source).</li><li><strong>New MySQL storage engines:</strong> MySQL is part of the LAMP stack and is used extensively in OLTP. To overcome MySQL&#8217;s scalability problems, a set of storage engines are developed, which include Xeround, Akiban, MySQL NDB cluster, GenieDB, Tokutek, etc. The good part is the usage of the MySQL interface, but the downside is data migration from other databases (including old MySQL) is not supported. Examples of offerings are Xeround, GenieDB and TokuTek (commercial); and Akiban, MySQL NDB Cluster and others in open source.</li><li><strong>Transparent clustering:</strong> These solutions retain the OLTP databases in their original format, but provide a pluggable feature to cluster transparently, to ensure scalability. Another approach is to provide transparent sharding to improve scalability. Schooner MySQL, Continuent Tungsten and ScalArc follow the former approach, whereas ScaleBase and dbShards follow the latter approach. Both approaches allow reuse of existing skillsets and ecosystem, and avoid the need to rewrite code or perform any data migration. Examples of offerings are  ScalArc, Schooner MySQL, dbShards and ScaleBase (commercial); and Continuent Tungsten (open source).</li></ol><h2>Summing up</h2><p>Given the continuing trend of data growth in OLTP systems, a new generation of solutions is required to cater to them. DBMSs have to be rearchitected from scratch to meet this demand. However, unlike NoSQL, these DBMSs have to cater for applications already written for an earlier generation of RDBMS. Hence, drastic interface changes like throwing out SQL or extensive changes to data schema is out of the question.</p><p>A new generation of information management systems, termed NewSQL systems, caters to this trend and these constraints. NewSQL is apt for businesses that are planning to:</p><ol><li>migrate existing applications to adapt to new trends of data growth,</li><li>develop new applications on highly scalable OLTP systems, and</li><li>rely on existing knowledge of OLTP usage.</li></ol><p>We look forward to your comments on this introductory article, and we will also plan for a series of expert in-depth articles on the NewSQL database technology.<div id="crp_related"><h5>Related Posts:</h5><ul><li><a href="http://www.linuxforu.com/2011/07/database-demands-of-peta-scale-computing/" rel="bookmark" class="crp_title">The Database Demands of Peta-scale Computing</a></li><li><a href="http://www.linuxforu.com/2011/02/up-close-and-personal-with-nosql/" rel="bookmark" class="crp_title">Up Close and Personal with NoSQL</a></li><li><a href="http://www.linuxforu.com/2012/01/importance-of-in-memory-databases/" rel="bookmark" class="crp_title">The Importance of In-memory Databases</a></li><li><a href="http://www.linuxforu.com/2011/05/databases-in-era-of-cloud-computing-and-big-data/" rel="bookmark" class="crp_title">Databases in the Era of Cloud Computing and Big Data</a></li><li><a href="http://www.linuxforu.com/2010/02/enterprise-db-score-a-goal-with-postgres/" rel="bookmark" class="crp_title">Score a Goal With Postgres!</a></li></ul></div>Tags: <a href="http://www.linuxforu.com/tag/451-group/" title="451 Group" rel="tag">451 Group</a>, <a href="http://www.linuxforu.com/tag/acid/" title="acid" rel="tag">acid</a>, <a href="http://www.linuxforu.com/tag/analytics-systems/" title="analytics systems" rel="tag">analytics systems</a>, <a href="http://www.linuxforu.com/tag/big-data/" title="big data" rel="tag">big data</a>, <a href="http://www.linuxforu.com/tag/couchdb/" title="CouchDB" rel="tag">CouchDB</a>, <a href="http://www.linuxforu.com/tag/data-availability/" title="data availability" rel="tag">data availability</a>, <a href="http://www.linuxforu.com/tag/data-management/" title="data management" rel="tag">data management</a>, <a href="http://www.linuxforu.com/tag/data-management-solutions/" title="data management solutions" rel="tag">data management solutions</a>, <a href="http://www.linuxforu.com/tag/data-processing/" title="data processing" rel="tag">data processing</a>, <a href="http://www.linuxforu.com/tag/data-storage/" title="data storage" rel="tag">data storage</a>, <a href="http://www.linuxforu.com/tag/database-systems/" title="database systems" rel="tag">database systems</a>, <a href="http://www.linuxforu.com/tag/database-technology/" title="database technology" rel="tag">database technology</a>, <a href="http://www.linuxforu.com/tag/databases/" title="databases" rel="tag">databases</a>, <a href="http://www.linuxforu.com/tag/enterprise-applications/" title="enterprise applications" rel="tag">enterprise applications</a>, <a href="http://www.linuxforu.com/tag/exabytes/" title="exabytes" rel="tag">exabytes</a>, <a href="http://www.linuxforu.com/tag/facebook/" title="Facebook" rel="tag">Facebook</a>, <a href="http://www.linuxforu.com/tag/google/" title="Google" rel="tag">Google</a>, <a href="http://www.linuxforu.com/tag/high-availability/" title="high availability" rel="tag">high availability</a>, <a href="http://www.linuxforu.com/tag/information-management-systems/" title="information management systems" rel="tag">information management systems</a>, <a href="http://www.linuxforu.com/tag/lfy-january-2012/" title="LFY January 2012" rel="tag">LFY January 2012</a>, <a href="http://www.linuxforu.com/tag/linkedin/" title="LinkedIn" rel="tag">LinkedIn</a>, <a href="http://www.linuxforu.com/tag/matthew-aslett/" title="Matthew Aslett" rel="tag">Matthew Aslett</a>, <a href="http://www.linuxforu.com/tag/mysql/" title="MySQL" rel="tag">MySQL</a>, <a href="http://www.linuxforu.com/tag/newsql/" title="NewSQL" rel="tag">NewSQL</a>, <a href="http://www.linuxforu.com/tag/nosql/" title="NoSQL" rel="tag">NoSQL</a>, <a href="http://www.linuxforu.com/tag/nosql-solutions/" title="NoSQL solutions" rel="tag">NoSQL solutions</a>, <a href="http://www.linuxforu.com/tag/oltp/" title="OLTP" rel="tag">OLTP</a>, <a href="http://www.linuxforu.com/tag/performance-requirements/" title="performance requirements" rel="tag">performance requirements</a>, <a href="http://www.linuxforu.com/tag/processing-power/" title="processing power" rel="tag">processing power</a>, <a href="http://www.linuxforu.com/tag/rdbms/" title="RDBMS" rel="tag">RDBMS</a>, <a href="http://www.linuxforu.com/tag/real-time-transactions/" title="real-time transactions" rel="tag">real-time transactions</a>, <a href="http://www.linuxforu.com/tag/relational-database/" title="Relational Database" rel="tag">Relational Database</a>, <a href="http://www.linuxforu.com/tag/twitter/" title="Twitter" rel="tag">Twitter</a>, <a href="http://www.linuxforu.com/tag/web-applications/" title="web applications" rel="tag">web applications</a><br /> ]]></content:encoded> <wfw:commentRss>http://www.linuxforu.com/2012/01/newsql-handle-big-data/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>The Importance of In-memory Databases</title><link>http://www.linuxforu.com/2012/01/importance-of-in-memory-databases/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=importance-of-in-memory-databases</link> <comments>http://www.linuxforu.com/2012/01/importance-of-in-memory-databases/#comments</comments> <pubDate>Mon, 30 Jan 2012 04:48:42 +0000</pubDate> <dc:creator>Prasanna Venkatesh</dc:creator> <category><![CDATA[Developers]]></category> <category><![CDATA[Overview]]></category> <category><![CDATA[Sysadmins]]></category> <category><![CDATA[Technology]]></category> <category><![CDATA[CSQL]]></category> <category><![CDATA[data management]]></category> <category><![CDATA[data mining]]></category> <category><![CDATA[data structure/algorithm]]></category> <category><![CDATA[database management systems]]></category> <category><![CDATA[database systems]]></category> <category><![CDATA[IBM]]></category> <category><![CDATA[IMDB]]></category> <category><![CDATA[in-memory computing]]></category> <category><![CDATA[in-memory databases]]></category> <category><![CDATA[in-memory technology]]></category> <category><![CDATA[India]]></category> <category><![CDATA[LFY January 2012]]></category> <category><![CDATA[MonetDB]]></category> <category><![CDATA[National Research Institute]]></category> <category><![CDATA[Oracle]]></category> <category><![CDATA[RDBMS]]></category> <category><![CDATA[Real-time analytics]]></category> <category><![CDATA[real-time applications]]></category> <category><![CDATA[real-time performance]]></category> <category><![CDATA[simplified storage algorithms]]></category> <category><![CDATA[web applications]]></category><guid isPermaLink="false">http://www.linuxforu.com/?p=9341</guid> <description><![CDATA[It has been predicted that in-memory computing will be one of the Top 10 technologies of 2012. In-memory databases (IMDBs) are a critical part of this paradigm. Through this introductory article, let&#8217;s get...]]></description> <content:encoded><![CDATA[<p><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/IN-Memory-DB.jpg?d9c344" alt="In-memory database" title="In-memory database" width="300" height="300" class="alignright size-full wp-image-9346" /><div class="introduction">It has been predicted that in-memory computing will be one of the Top 10 technologies of 2012. In-memory databases (IMDBs) are a critical part of this paradigm. Through this introductory article, let&#8217;s get acquainted with the basics of IMDBs. We will look at what they are, why they are developed, and the key differences between IMDB and traditional disk DBs.</div><p>Gartner has predicted in-memory computing to be one of the top 10 strategic technologies of 2012. In-memory computing is expected to have a disruptive impact on the data warehousing domain in the coming two years. There have been a series of such products released in the last two years, one of the most famous being SAP&#8217;s HANA. Real-time analytics and sub-second response times for enterprise applications require high-performance data management systems. This, in turn, has led to a surge in the importance of IMDBs.</p><p>Network bandwidth has increased dramatically and multi-core processors are available even in mobile phones. However, disk I/O speed has not been increasing at the same rate, which has crippled traditional databases. The first step towards high-performance databases is IMDBs. With ever-growing RAM size and the ability to address more RAM (with 64-bit address spaces), IMDBs are in vogue.</p><h2>What is an in-memory database?</h2><p>Wikipedia defines an in-memory database as, &#8220;An in-memory database (IMDB; also, main memory database system or MMDB) is a database management system that primarily relies on main memory for computer data storage. It is contrasted with database management systems that employ a disk storage mechanism.&#8221;</p><p>Margaret H Eich has given a very simple definition of an IMDB/MMDB: a database whose primary data store is main memory.</p><p>IMDBs are architected and designed differently from traditional RDBMSs. They have simplified algorithms and mechanisms, which are built with the awareness that all data is going to be in RAM. Figure 1 is a simple illustration of the differences.</p><div id="attachment_9345" class="wp-caption aligncenter" style="width: 590px"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/IMDB-vs-Disk-DB-Fig.1-590x296.png?d9c344" alt="IMDB vs Disk DB" title="IMDB vs Disk DB" width="590" height="296" class="size-large wp-image-9345" /><p class="wp-caption-text">Figure 1: IMDB vs Disk DB</p></div><p>IMDBs are also different from simplified storage algorithms like hash-tables or trees, in that IMDBs are &#8220;databases&#8221; or RDBMSs. Most IMDBs are ACID-compliant relational databases offering SQL. They have all the properties of a traditional RDBMS, but are tuned for data to be in-memory.</p><h2>Getting deeper into the IMDB</h2><p>IMDBs are not a new phenomenon. The great DB scientist Jim Gray conceptualised this technology 30 years ago and also predicted that in the 2000s these technologies would become widely accepted. Almost from the early 1980s, IMDBs have existed in the telecom and defense domains. However, these were built and maintained as internal components. IBM built one of the first in-memory engines (IMS/VS FastPath) way back in 1978.</p><p>The first significant commercial IMDB offering was TimesTen (later acquired by Oracle). Since then, almost all top DB vendors boast an IMDB product &#8212; like IBM&#8217;s SolidDB, Sybase&#8217;s ASE, etc.</p><h2>Myths about IMDBs</h2><p>Consider the following assertions:</p><ul><li>Given the same amount of RAM, disk DBs can perform at the same speed as IMDBs (by using caching technology).</li><li>If a RAM disk is created and a traditional disk DB is deployed on it, it delivers the same performance as an in-memory database.</li><li>If the system crashes, all the data stored in IMDBs will be lost.</li><li>SSDs and flash storage are getting better and better. Using these technologies along with traditional disk DBs yields the same performance as an in-memory database.</li><li>Since RAM size is limited, sizes of IMDBs are also limited.</li><li>Finally, IMDBs are not special; they are traditional disk DBs made to run on RAM.</li></ul><p>Naturally, all of these are myths. It is close to impossible to create an in-memory DB from a traditional disk database by just changing the OS or hardware environment.</p><p>So, internally, how different is an IMDB from a traditional disk DB?</p><p>IMDBs are architected and designed keeping in mind the fact that all data is in memory. This actually leads to much simpler design as compared to disk DBs. There are six areas of difference:</p><ol><li><em>Query optimisation:</em> In disk DBs, the I/O cost factor dominates the optimisation. However, in IMDBs there is no such clear factor, which makes query optimisation very tricky. This is generally solved by taking constants and falling back on rule-based optimisation.</li><li><em>Indexing:</em> More memory-friendly data structures and algorithms are used for indexing. While most disk DBs use B-Tree as a primary indexing data structure/algorithm, IMDBs tend to use T-Tree as a primary indexing data structure/algorithm.</li><li><em>Internal data representation:</em> Compactness of representation dominates concerns for IMDBs. With all data being in memory, IMDBs tend to use direct memory pointers heavily. This is very typical of the IMDB memory page, index data or relation representations.</li><li><em>Durability and recovery:</em> Contrary to popular belief, IMDBs are durable. They use algorithms similar to disk DBs for persistence. However, the buffer management, which is the biggest performance bottleneck for disk DBs, is eliminated. During database loading, IMDBs tend to take a bit more time as they have to load the complete data into memory. Hence, recovery is a bit slower.</li><li><em>Access methodology:</em> Generally, disk DBs offer client server over sockets as a primary access method. However, with no disk I/O, if IMDBs only offer sockets for access, this will become a bottleneck. Hence, most IMDBs tend to offer shared-memory access as a primary method. In a few cases, JDBC/ODBC interfaces are also supported.</li><li><em>Concurrency control:</em> Due to inherent speed in processing, IMDBs can take coarser locks and also do less to persist them. However, disk DBs take finer locks and take elaborate measures to persist them.</li></ol><p>Figure 2 is a typical architecture for an in-memory database.</p><div id="attachment_9342" class="wp-caption aligncenter" style="width: 590px"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/IMDB-Architecture-Fig.2-590x417.png?d9c344" alt="IMDB architecture" title="IMDB architecture" width="590" height="417" class="size-large wp-image-9342" /><p class="wp-caption-text">Figure 2: IMDB architecture</p></div><h2>Typical applications of IMDBs</h2><p>IMDBs are applicable in all domains that require real-time performance and very low latency. Four domains typically use IMDBs: telecom, financial segments, enterprises, and e-commerce and Web applications. In these spaces, IMDBs are used in a variety of applications (refer to Figure 3).</p><div id="attachment_9344" class="wp-caption aligncenter" style="width: 590px"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/IMDB-Usecases-Fig.3-590x298.png?d9c344" alt="IMDB usecases" title="IMDB usecases" width="590" height="298" class="size-large wp-image-9344" /><p class="wp-caption-text">Figure 3: IMDB usecases</p></div><h2>Key offerings in the IMDB space</h2><p>The IMDB space is dominated by a lot of commercial players. Some of the most important ones are Oracle TimesTen, IBM SolidDB, Sybase ASE, ENEA Polyhedra and McObject ExtremeDB. There are also some typical open source solutions. Let us take a look at two of the FOSS IMDBs &#8212; CSQL and MonetDB.</p><h3>CSQ</h3><p>CSQL is an open source main-memory high-performance RDBMS developed in India. It is one of the fastest open source IMDBs. It is designed to provide high performance on simple SQL queries and DML statements that involve only one table. It supports only limited features, which are used by most real-time applications, like <code>INSERT</code>, <code>UPDATE</code>, <code>DELETE</code> on a single table, and <code>SELECT</code> with local predicates on a single table.</p><p>It provides multiple interfaces such as JDBC, ODBC and other SQL APIs. CSQL offers atomicity, consistency and isolation. It is typically recommended for use as a cache for existing disk-based commercial databases.</p><h3>MonetDB</h3><p>MonetDB is an open source high-performance DBMS developed at the National Research Institute for Mathematics and Computer Science in the Netherlands. It was designed to provide high performance on complex queries against large databases, e.g., combining tables with hundreds of columns and multi-million rows.</p><p>MonetDB is one of the first database systems to focus its query optimisation effort on exploiting CPU caches. Development of MonetDB started in 1979 and it became an open source project in 2003. MonetDB has been successfully applied in high-performance applications for data mining, OLAP, GIS, XML Query, and text and multimedia retrieval.</p><p>How do IMDBs change the rules of the game? While existing applications and schemas can directly benefit from IMDB due to performance improvement, if some things are not carefully handled, the full benefit of IMDB is not achieved. Areas that require significant changes at both the conceptual as well as implementation levels are application design, database schema design and data design (partitioning of data).</p><h2>Application design</h2><p>Taking advantage of performance benefits offered by an IMDB means redesigning applications to take advantage of the specific strengths of in-memory technology. The main way to achieve this is to push work that is currently done in the application layer down to the database.</p><p>This not only allows developers to take advantage of special operations offered by the DBMS, but also reduces the amount of data that must be transferred between application layers. This can lead to substantial performance improvements and can open up new application areas.</p><h2>Database schema design</h2><p>IMDB is beneficial if the data fits into a single database. This requires efforts to conserve space, so more elaborate normalisation procedures are not suitable. Also, using very precise and apt data types enhances storage space. Reduced redundancy, carefully formed columns, precise index creation and efficient data management will help IMDB yield better performance.</p><h2>Data design</h2><p>One of the key changes when moving from traditional disk DBs to in-memory DBs is the space available, so data partitioning and storage assumes great significance. IMDB requires as much related data as possible in a single process space. Too much distribution will introduce network I/O in the processing, thereby degrading performance.</p><h2>Summing up</h2><p>IMDBs, combined with various current hardware trends, have the ability to change the performance of enterprise and other applications drastically. This, in turn, will result in tremendous value generation to businesses. Such enhanced performance will also foster the evolution of innovative applications and services.</p><p>Do send in your feedback and queries, which can be addressed in our forthcoming articles in the IMDB series.<div id="crp_related"><h5>Related Posts:</h5><ul><li><a href="http://www.linuxforu.com/2012/01/newsql-handle-big-data/" rel="bookmark" class="crp_title">NewSQL &#8212; The New Way to Handle Big Data</a></li><li><a href="http://www.linuxforu.com/2011/07/database-demands-of-peta-scale-computing/" rel="bookmark" class="crp_title">The Database Demands of Peta-scale Computing</a></li><li><a href="http://www.linuxforu.com/2009/02/improve-multi-os-computer-performance-through-cross-swapping/" rel="bookmark" class="crp_title">Improve Multi-OS Computer Performance through Cross Swapping</a></li><li><a href="http://www.linuxforu.com/2012/01/postgres-xc-database-clustering-solution/" rel="bookmark" class="crp_title">Postgres-XC &#8212; A PostgreSQL Clustering Solution</a></li><li><a href="http://www.linuxforu.com/2011/08/comprehensive-lamp-guide-part-2-mysql/" rel="bookmark" class="crp_title">The Comprehensive LAMP Guide &#8212; Part 2 (MySQL)</a></li></ul></div>Tags: <a href="http://www.linuxforu.com/tag/csql/" title="CSQL" rel="tag">CSQL</a>, <a href="http://www.linuxforu.com/tag/data-management/" title="data management" rel="tag">data management</a>, <a href="http://www.linuxforu.com/tag/data-mining/" title="data mining" rel="tag">data mining</a>, <a href="http://www.linuxforu.com/tag/data-structurealgorithm/" title="data structure/algorithm" rel="tag">data structure/algorithm</a>, <a href="http://www.linuxforu.com/tag/database-management-systems/" title="database management systems" rel="tag">database management systems</a>, <a href="http://www.linuxforu.com/tag/database-systems/" title="database systems" rel="tag">database systems</a>, <a href="http://www.linuxforu.com/tag/ibm/" title="IBM" rel="tag">IBM</a>, <a href="http://www.linuxforu.com/tag/imdb/" title="IMDB" rel="tag">IMDB</a>, <a href="http://www.linuxforu.com/tag/in-memory-computing/" title="in-memory computing" rel="tag">in-memory computing</a>, <a href="http://www.linuxforu.com/tag/in-memory-databases/" title="in-memory databases" rel="tag">in-memory databases</a>, <a href="http://www.linuxforu.com/tag/in-memory-technology/" title="in-memory technology" rel="tag">in-memory technology</a>, <a href="http://www.linuxforu.com/tag/india/" title="India" rel="tag">India</a>, <a href="http://www.linuxforu.com/tag/lfy-january-2012/" title="LFY January 2012" rel="tag">LFY January 2012</a>, <a href="http://www.linuxforu.com/tag/monetdb/" title="MonetDB" rel="tag">MonetDB</a>, <a href="http://www.linuxforu.com/tag/national-research-institute/" title="National Research Institute" rel="tag">National Research Institute</a>, <a href="http://www.linuxforu.com/tag/oracle/" title="Oracle" rel="tag">Oracle</a>, <a href="http://www.linuxforu.com/tag/rdbms/" title="RDBMS" rel="tag">RDBMS</a>, <a href="http://www.linuxforu.com/tag/real-time-analytics/" title="Real-time analytics" rel="tag">Real-time analytics</a>, <a href="http://www.linuxforu.com/tag/real-time-applications/" title="real-time applications" rel="tag">real-time applications</a>, <a href="http://www.linuxforu.com/tag/real-time-performance/" title="real-time performance" rel="tag">real-time performance</a>, <a href="http://www.linuxforu.com/tag/simplified-storage-algorithms/" title="simplified storage algorithms" rel="tag">simplified storage algorithms</a>, <a href="http://www.linuxforu.com/tag/web-applications/" title="web applications" rel="tag">web applications</a><br /> ]]></content:encoded> <wfw:commentRss>http://www.linuxforu.com/2012/01/importance-of-in-memory-databases/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Postgres-XC &#8212; A PostgreSQL Clustering Solution</title><link>http://www.linuxforu.com/2012/01/postgres-xc-database-clustering-solution/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=postgres-xc-database-clustering-solution</link> <comments>http://www.linuxforu.com/2012/01/postgres-xc-database-clustering-solution/#comments</comments> <pubDate>Fri, 27 Jan 2012 13:09:40 +0000</pubDate> <dc:creator>Ashutosh Bapat</dc:creator> <category><![CDATA[Developers]]></category> <category><![CDATA[Overview]]></category> <category><![CDATA[Sysadmins]]></category> <category><![CDATA[Technology]]></category> <category><![CDATA[cluster system]]></category> <category><![CDATA[clustering solution]]></category> <category><![CDATA[data storage]]></category> <category><![CDATA[database]]></category> <category><![CDATA[database clusters]]></category> <category><![CDATA[database servers]]></category> <category><![CDATA[disk cache]]></category> <category><![CDATA[EnterpriseDB]]></category> <category><![CDATA[high availability]]></category> <category><![CDATA[LFY January 2012]]></category> <category><![CDATA[Postgres-XC]]></category> <category><![CDATA[PostgreSQL]]></category> <category><![CDATA[relational database system]]></category> <category><![CDATA[scalability]]></category> <category><![CDATA[scalability problems]]></category> <category><![CDATA[SQL]]></category><guid isPermaLink="false">http://www.linuxforu.com/?p=9308</guid> <description><![CDATA[What started with a simple relational database system, is expanding its horizons by developing new technology that satiates the ever-increasing need for more data storage, greater transaction throughput and higher availability. Using a...]]></description> <content:encoded><![CDATA[<p><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/postgre-xc-ist-image-590x267.jpg?d9c344" alt="PostgreSQL Clustering" title="PostgreSQL Clustering" width="590" height="267" class="aligncenter size-large wp-image-9314" /><div class="introduction">What started with a simple relational database system, is expanding its horizons by developing new technology that satiates the ever-increasing need for more data storage, greater transaction throughput and higher availability. Using a cluster to solve these scalability problems is a present trend. This article talks about Postgres-XC, a clustering solution based on the popular PostgreSQL RDBMS.</div><p>A cluster is a collection of commodity components that provide scalability and availability at a low cost to the consumer. A database cluster is a collection of database servers that store and process data using commodity hardware, satisfying the need for more data storage, higher throughput and providing high availability. Postgres-XC is such a database cluster system; it is based on PostgreSQL, and follows the same open source model.</p><p>The Postgres-XC project began in 2009, through a collaboration between NTT and EnterpriseDB. The goal was to build an open source clustering solution based on PostgreSQL with 100 per cent compatible client APIs. Having PostgreSQL-compatible APIs allows existing PostgreSQL applications to use Postgres-XC with little (or no) change. The licensing terms of this project are the same as that of PostgreSQL.</p><h2>Postgres-XC architecture</h2><p>Postgres-XC is a write-scalable, synchronous multi-master, transparent PostgreSQL clustering solution based on shared-nothing architecture. It is a collection of tightly coupled database components, which can be installed on one or more physical or virtual machines. The components do not share any resources such as disk, cache or memory.</p><ul><li><em>Write-scalability</em> means that Postgres-XC can be configured with as many database servers as needed; Postgres-XC is able to handle more writes than a single PostgreSQL server.</li><li><em>Multi-master</em> implies that clients can connect to multiple database servers, and that each database server provides a single, consistent, cluster-wide view of the database.</li><li><em>Synchronous</em> means that a write from any of the masters is immediately visible to other transactions running on other masters.</li><li><em>Transparent</em> means that applications do not have to worry about how the data is stored in multiple database servers, internally.</li></ul><div id="attachment_9310" class="wp-caption aligncenter" style="width: 590px"><a href="http://cdn.linuxforu.com/wp-content/uploads/2012/01/postgres-xc-01.png?d9c344"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/postgres-xc-01-590x479.png?d9c344" alt="Postgres-XC architecture" title="Postgres-XC architecture" width="590" height="479" class="size-large wp-image-9310" /></a><p class="wp-caption-text">Figure 1: Postgres-XC architecture</p></div><p>Figure 1 gives the architectural overview of Postgres-XC with its three main components:</p><ol><li><em>Global Transaction Manager (GTM)</em> gathers and manages information about transactional activities in Postgres-XC, issues global transaction identifiers to transactions (to maintain a consistent view of the database on all nodes), and  provides ACID properties. It provides support for other global data, such as sequences and timestamps. It stores no user data, except control information.</li><li><em>Coordinators</em> (masters) provide a point of contact for the application/client. They are responsible for parsing and executing queries from the clients, and returning the results (if needed). They do not store any user data themselves, but gather the data from datanodes, with the help of SQL queries fired through a PostgreSQL-native interface. The coordinators also process the data if required and even manage the two-phase commit. Although coordinators do not store user data, they use the catalogue data to parse queries, resolve symbols, plan queries, locate data, etc.</li><li><em>Datanodes</em> store user data and catalogues. The datanodes execute the queries received from the coordinator and return results to the coordinator.</li></ol><h2>Distribution of data and scalability</h2><p>Postgres-XC allows two ways of storing the tables on the datanodes:</p><ol><li><strong>Distributed tables:</strong> A table is distributed on a given set of datanodes using strategies like hash, round-robin, or modulo partitioning. Every row of a distributed table resides on a single datanode. Multiple rows can be modified or written in parallel to various datanodes; we can also read the rows from various datanodes in parallel. Performance is greatly improved by parallel writes and reads from different datanodes.</li><li><strong>Replicated tables:</strong> A table is replicated on a given set of datanodes using statement-level replication, which performs better than log-based replication, since the size of the logs that must be shipped is much greater than the size of the statement. In the case of a replicated table, a row in the table resides on each datanode on which the table is replicated. Any modifications to the row must be duplicated to each replicated copy. Since all the data in the table is available on a single datanode, the coordinator can gather all the data from a single node and in some cases, act as a proxy between the client application and the datanode. This allows multiple queries on the same table to be directed to different datanodes, thus balancing the load and increasing the read throughput.</li></ol><p>Figures 2 and 3 depict the read and write concepts for distributed and replicated tables, respectively.</p><div id="attachment_9311" class="wp-caption aligncenter" style="width: 590px"><a href="http://cdn.linuxforu.com/wp-content/uploads/2012/01/postgres-xc-02.png?d9c344"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/postgres-xc-02-590x265.png?d9c344" alt="Distributed tables" title="Distributed tables" width="590" height="265" class="size-large wp-image-9311" /></a><p class="wp-caption-text">Figure 2: Distributed tables</p></div><div id="attachment_9312" class="wp-caption aligncenter" style="width: 590px"><a href="http://cdn.linuxforu.com/wp-content/uploads/2012/01/postgres-xc-03.png?d9c344"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/postgres-xc-03-590x239.png?d9c344" alt="Replicated tables" title="Replicated tables" width="590" height="239" class="size-large wp-image-9312" /></a><p class="wp-caption-text">Figure 3: Replicated tables</p></div><h2>High availability</h2><p>To achieve high availability, one needs data redundancy, component redundancy and automatic failover. In Postgres-XC, data redundancy can be achieved by using the PostgreSQL native replication with Hot Standby for datanodes. Since each coordinator is a master (capable of writing data) and is capable of reading writes performed by any other coordinator instantaneously, every coordinator is capable of replacing any other, should that coordinator fail. GTM-standby acts as a redundant component for GTM. However, third-party tools are required for automatic failover of all the three types of components.</p><h2>Performance evaluation</h2><p>Initial transaction throughput measurements carried out using the DBT-1 benchmark have shown significant throughput scalability, as shown in Figure 4.</p><div id="attachment_9313" class="wp-caption aligncenter" style="width: 590px"><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/postgres-xc-04-590x405.jpg?d9c344" alt="Performance evaluation" title="Performance evaluation" width="590" height="405" class="size-large wp-image-9313" /><p class="wp-caption-text">Figure 4: Performance evaluation</p></div><p>The figure plots the Scaling Factor versus the Number of Servers in Postgres-XC. The Scaling Factor is the ratio of the number of transactions completed per unit time by Postgres-XC, to that completed by PostgreSQL. A Server comprised of a coordinator and a datanode run on single machine. This benchmark demonstrated an improvement in throughput of approximately 6 times, when using 10 servers.</p><h2>Release management &#038; development processes</h2><p>The Postgres-XC project is hosted on <a href="http://postgres-xc.sourceforge.net/">SourceForge</a>. The Postgres-XC team tries to release a minor version of Postgres-XC every three to four months to ensure that the latest Postgres-XC features are available to users. The team also tries to make the latest PostgreSQL features available in Postgres-XC by doing frequent merges with the latest stable release of PostgreSQL.</p><p>The last release (0.9.6) of Postgres-XC supports most of the SQL syntax and features of PostgreSQL 9.1. The team is currently working on the first major release of Postgres-XC 1.0, due in 2012, with maximum PostgreSQL compliance. Some of the other features like the dynamic addition and removal of components, global deadlock detection, global constraint support, etc, will be targeted for major release after 1.0.</p><p>The development team follows the open source development model, where the issues, features or any other development related items are discussed on the public mailing list: <code>postgres-xc-developers@lists.sourceforge.net</code>. The <code>postgres-xc-general@lists.sourceforge.net</code> mailing list is used to discuss other Postgres-XC matters and to solicit help about Postgres-XC.</p><h3>Wish to contribute?</h3><p>The Postgres-XC team needs help with feature development, bug fixing, creating installers and distribution packages, testing, and evaluation of Postgres-XC on real applications. To be part of the Postgres-XC community, feel free to contact the Postgres-XC team at the appropriate mailing list.<div id="crp_related"><h5>Related Posts:</h5><ul><li><a href="http://www.linuxforu.com/2010/02/enterprise-db-score-a-goal-with-postgres/" rel="bookmark" class="crp_title">Score a Goal With Postgres!</a></li><li><a href="http://www.linuxforu.com/2011/06/telecom-service-provider-handles-huge-volumes-of-data-using-postgresql/" rel="bookmark" class="crp_title">A Telecom Service Provider Handles Huge Volumes of Data Using PostgreSQL</a></li><li><a href="http://www.linuxforu.com/2010/06/open-source-tools-in-gis/" rel="bookmark" class="crp_title">Open Source Tools in GIS</a></li><li><a href="http://www.linuxforu.com/2011/08/it-service-provider-turns-to-postgresql-for-scalability/" rel="bookmark" class="crp_title">IT Service Provider Turns to PostgreSQL for Scalability</a></li><li><a href="http://www.linuxforu.com/2011/03/a-foss-lovers-tryst-with-postgresql/" rel="bookmark" class="crp_title">A FOSS Lover&#8217;s Tryst With PostgreSQL</a></li></ul></div>Tags: <a href="http://www.linuxforu.com/tag/cluster-system/" title="cluster system" rel="tag">cluster system</a>, <a href="http://www.linuxforu.com/tag/clustering-solution/" title="clustering solution" rel="tag">clustering solution</a>, <a href="http://www.linuxforu.com/tag/data-storage/" title="data storage" rel="tag">data storage</a>, <a href="http://www.linuxforu.com/tag/database/" title="database" rel="tag">database</a>, <a href="http://www.linuxforu.com/tag/database-clusters/" title="database clusters" rel="tag">database clusters</a>, <a href="http://www.linuxforu.com/tag/database-servers/" title="database servers" rel="tag">database servers</a>, <a href="http://www.linuxforu.com/tag/disk-cache/" title="disk cache" rel="tag">disk cache</a>, <a href="http://www.linuxforu.com/tag/enterprisedb/" title="EnterpriseDB" rel="tag">EnterpriseDB</a>, <a href="http://www.linuxforu.com/tag/high-availability/" title="high availability" rel="tag">high availability</a>, <a href="http://www.linuxforu.com/tag/lfy-january-2012/" title="LFY January 2012" rel="tag">LFY January 2012</a>, <a href="http://www.linuxforu.com/tag/postgres-xc/" title="Postgres-XC" rel="tag">Postgres-XC</a>, <a href="http://www.linuxforu.com/tag/postgresql/" title="PostgreSQL" rel="tag">PostgreSQL</a>, <a href="http://www.linuxforu.com/tag/relational-database-system/" title="relational database system" rel="tag">relational database system</a>, <a href="http://www.linuxforu.com/tag/scalability/" title="scalability" rel="tag">scalability</a>, <a href="http://www.linuxforu.com/tag/scalability-problems/" title="scalability problems" rel="tag">scalability problems</a>, <a href="http://www.linuxforu.com/tag/sql/" title="SQL" rel="tag">SQL</a><br /> ]]></content:encoded> <wfw:commentRss>http://www.linuxforu.com/2012/01/postgres-xc-database-clustering-solution/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Partitioning in PostgreSQL</title><link>http://www.linuxforu.com/2012/01/partitioning-in-postgresql/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=partitioning-in-postgresql</link> <comments>http://www.linuxforu.com/2012/01/partitioning-in-postgresql/#comments</comments> <pubDate>Fri, 27 Jan 2012 10:07:24 +0000</pubDate> <dc:creator>Chetan Suttraway</dc:creator> <category><![CDATA[Developers]]></category> <category><![CDATA[How-Tos]]></category> <category><![CDATA[Sysadmins]]></category> <category><![CDATA[Tools / Apps]]></category> <category><![CDATA[constraints]]></category> <category><![CDATA[database partition]]></category> <category><![CDATA[database trigger]]></category> <category><![CDATA[design decision]]></category> <category><![CDATA[inheritance]]></category> <category><![CDATA[LFY January 2012]]></category> <category><![CDATA[partition maintenance]]></category> <category><![CDATA[partitions]]></category> <category><![CDATA[PostgreSQL]]></category> <category><![CDATA[Tables]]></category> <category><![CDATA[timestamp values]]></category><guid isPermaLink="false">http://www.linuxforu.com/?p=9305</guid> <description><![CDATA[Partitioning refers to splitting a large table into smaller pieces. This article covers the basics of partitioning in PostgreSQL. Currently, PostgreSQL supports range and list partitioning via table inheritance. Basically, you have to...]]></description> <content:encoded><![CDATA[<p><img src="http://cdn.linuxforu.com/wp-content/uploads/2012/01/partitioning-in-podtgre-590x314.jpg?d9c344" alt="Partitioning in PostgreSQL" title="Partitioning in PostgreSQL" width="590" height="314" class="aligncenter size-large wp-image-9306" /><div class="introduction">Partitioning refers to splitting a large table into smaller pieces. This article covers the basics of partitioning in PostgreSQL.</div><p>Currently, PostgreSQL supports range and list partitioning via table inheritance. Basically, you have to create each partition as a child table of the master table. Generally, if you want to split data into specific ranges, then use range partitioning.</p><p>Date and timestamp values are good examples for this. For example, you may want to split yearly data into quarterly partitions. Similarly, if you want to split data based on a specific list of values, then use list partitioning. For this, you can consider creating partitions for each state of a country. Generally, in range partitioning, you would be adding more partitions over time, whereas in list partitioning the data will be continuously growing within each partition. This design decision is very important from the partition maintenance point of view, which most people ignore.</p><p>Although the syntax for creating partitioned tables (just like the one in a commercial RDBMS) is not available in PostgreSQL, you may wonder exactly how to set up partitioning in PostgreSQL. You will be glad to know that PostgreSQL uses the concept of inheritance, triggers and constraint exclusion to support partitioning. Additionally, you can also use rules instead of triggers.</p><p>Now, inheritance and constraint exclusion come with their own pros and cons. There are various scenarios that you need to take care of. Sharing details on them is the main goal of this article. Further, once that has been addressed, the next goal should be to automate partition maintenance because you would most certainly like to automate the creation and maintenance part of partitioning. As you will realise by the end of this article, partition maintenance is another important task, apart from setting up the partitions.</p><h2>Partitioning using inheritance</h2><p>Before we begin, you should note that there are various ways to set up partitioning. The scheme that I am going to show here is just one of many. You would need to tweak it as per the actual requirements.</p><p>Before we start, make sure that the <code>constraint_exclusion</code> configuration option is set to either <code>ON</code> or <code>PARTITION</code> in the <code>postgresql.conf</code> file. This is absolutely necessary to get the partitioning scheme working.</p><p>First, let us create an empty master table without any primary key. If you are wondering about the missing primary key, then you should know that this is an empty master table, and that we need to set up a primary key on each of the partitions separately (more on this in the latter part of the article):</p><pre class="brush: sql; gutter: false; first-line: 1">CREATE TABLE orders (
     id            INT NOT NULL,
     address       TEXT NOT NULL,
     order_date    TIMESTAMP NOT NULL
);</pre><p>Now, create some partitions using non-overlapping CHECK constraints:</p><pre class="brush: sql; gutter: false; first-line: 1">CREATE TABLE orders_part_2011 (
    CHECK (order_date &gt;= DATE &#039;2011-01-01&#039;
                    AND order_date &lt; DATE &#039;2012-01-01&#039;)

) INHERITS (orders);

CREATE TABLE orders_part_2010 (
    CHECK (order_date &lt; DATE &#039;2011-01-01&#039;)
) INHERITS (orders);</pre><p>Here, the partition <code>orders_part_2011</code> will hold all data from 2011 onwards, whereas <code>orders_part_2010</code> will hold all previous data. Note that I am not using any primary key clause, as <code>order_date</code> cannot be a primary key in this particular setup. Further, always make sure that you match the data-type of values used with that of the column referred to in the <code>CHECK</code> constraints.</p><p>Optionally, you may create indexes on the partitioning key columns for each of the partitions:</p><pre class="brush: sql; gutter: false; first-line: 1">CREATE INDEX orders_part_2011_idx ON orders_part_2011(order_date);
CREATE INDEX orders_part_2010_idx ON orders_part_2010(order_date);</pre><p>The partitioning scheme is not yet ready. What I really want is that the data inserted into the master table should be redirected to the appropriate partition. This is where I need a trigger or rule. Triggers and rules have their own pros and cons. Here I use triggers, with trigger functions.</p><p>Again, a trigger function can be written in many ways, depending on the requirements. I will show two ways of writing one, along with their advantages and disadvantages. Let&#8217;s create a trigger function as shown below:</p><pre class="brush: sql; gutter: false; first-line: 1">CREATE OR REPLACE FUNCTION orders_insert_simple() RETURNS TRIGGER AS $$
DECLARE
vsql Text;
BEGIN
   vsql :=   &#039;INSERT INTO orders_part_&#039;|| to_char(NEW.order_date, &#039;YYYY&#039; )||
   &#039; VALUES (&#039;||NEW.id||&#039;,&#039;||quote_litera(NEW.address)||&#039;,&#039;||quote_literal(NEW.order_date)||&#039;)&#039;;
   RETURN NULL;
END;
$$ LANGUAGE plpgsql;</pre><p>Now we need to attach this trigger function to a trigger, to handle the <code>INSERT</code> on the master table:</p><pre class="brush: sql; gutter: false; first-line: 1">CREATE TRIGGER orders_insert_trigger
BEFORE INSERT ON orders
FOR EACH ROW EXECUTE PROCEDURE orders_insert_simple();</pre><p>There are quite a few interesting things used in the trigger function that you need to closely look at. It is important to note that the partition name is computed on the fly. This works for our particular case, as all the required partitions were created beforehand. This function would not require any updates, even if you add new partitions for the next year, and so on.</p><p>Looks easy? Then take a close look again, at the part where I have used <code>quote_literal</code> to quote the input values. Essentially, you need to quote each and every possible value that is going to be inserted into the partitions.</p><p>Similarly, you would need to take care of NULL values. This is the most cumbersome part of using this easy-to-write trigger function, so let&#8217;s try out another way of writing the trigger function:</p><pre class="brush: sql; gutter: false; first-line: 1">CREATE OR REPLACE FUNCTION orders_insert() RETURNS TRIGGER AS
$$
BEGIN
    IF (NEW.order_date &gt;= DATE &#039;2011-01-01&#039; AND NEW.order_date &lt; DATE &#039;2012-01-01&#039;) THEN
       INSERT INTO orders_part_2011 VALUES (NEW.*);
   ELSIF (NEW.order_date &lt; DATE &#039;2011-01-01&#039;) THEN
       INSERT INTO orders_part_2010 VALUES (NEW.*);
   ELSE
       RAISE EXCEPTION &#039;Date out of range. check orders_insert() function!&#039;;
   END IF;
   RETURN NULL;
END;
$$
LANGUAGE plpgsql;

CREATE TRIGGER orders_insert_trigger
BEFORE INSERT ON orders
FOR EACH ROW EXECUTE PROCEDURE orders_insert();</pre><p>As you can see, we are now explicitly checking <code>order_date</code> to redirect data into the appropriate partitions. This doesn&#8217;t need handling of quote or NULL values &#8212; at least, for non-partition-key values. I have simply used <code>NEW.*</code> instead of referring to individual column values.</p><p>In case you are not able to create all partitions beforehand, you would need to update the above trigger function with the logic to create partitions on-the-fly. Generally, we use separate triggers for partition creation and data redirection. Obviously, the partition creation trigger should always be fired before the redirection trigger. You should take care to avoid race conditions between those two triggers.</p><p>Now that the trigger is in place, let&#8217;s insert some records and verify the setup:</p><pre class="brush: sql; gutter: false; first-line: 1">pg=# INSERT INTO orders VALUES(1, &#039;pune&#039;, &#039;2011-08-22&#039;);
INSERT 0 0
pg=# INSERT INTO orders VALUES(2, &#039;pune&#039;, &#039;2010-02-22&#039;);
INSERT 0 0
pg=# UPDATE orders SET address = &#039;bengaluru&#039; WHERE id = 2;
UPDATE 1</pre><p>Do not panic on seeing the <code>INSERT</code> statement messages &#8212; they simply convey that zero records were inserted in the base (master) table. Actually, the records were transparently inserted into the related partitions.</p><p>Another thing to note about the <code>UPDATE</code> statement is that you are not supposed to update the partitioning key. Basically, any change to the partitioning key value might result in the movement of that record to another partition, which is termed as the row movement.</p><p>A simple way to handle queries that do update the partitioning key is to capture the <code>UPDATE</code> query, delete the related record from the partition, and then fire an <code>INSERT</code> on the base table. Then the partitioning mechanism will kick in and redirect the record to the appropriate partition. This is not handled in the current setup, as I am updating the address value, which is a non-partition-key column.</p><p>Let&#8217;s now check where the records are stored:</p><pre class="brush: sql; gutter: false; first-line: 1">SELECT * FROM orders;
 id |  address   |     order_date
----+--------------+---------------------------
  1 | pune         | 22-AUG-11 00:00:00
  2 | bengaluru | 22-FEB-10 00:00:00
(2 rows)</pre><p>PostgreSQL knows about the child tables of the orders table, so it assumes that the user wants all the data, from the parent as well as all the children. The partitions are normal tables, and you can query them as usual:</p><pre class="brush: sql; gutter: false; first-line: 1">SELECT * FROM orders_part_2011;
 id | address |     order_date
----+---------+------------------------
  1 | pune     | 22-AUG-11 00:00:00
(1 row)

SELECT * FROM orders_part_2010;
 id |  address  |     order_date
----+-----------+--------------------
  2 | bengaluru | 22-FEB-10 00:00:00
(1 row)</pre><p>You can also check if the master table is really empty, by using the <code>ONLY</code> clause, which restricts the lookup to only the table specified in the statement:</p><pre class="brush: sql; gutter: false; first-line: 1">SELECT * FROM ONLY orders;
 id | address | order_date
----+---------+------------
(0 rows)</pre><p>Querying over partitions<br /> Use the <code>EXPLAIN</code> feature to check the plan for querying over partitions:</p><pre class="brush: sql; gutter: false; first-line: 1">EXPLAIN SELECT * FROM orders WHERE order_date = &#039;02-JAN-11&#039;;
                                       QUERY PLAN
-----------------------------------------------------------------
 Result  (cost=0.00..26.01 rows=7 width=40)
   -&gt;  Append  (cost=0.00..26.01 rows=7 width=40)
         -&gt;  Seq Scan on orders  (cost=0.00..23.75 rows=6 width=44)
               Filter: (order_date = &#039;02-JAN-11 00:00:00&#039;::timestamp without time zone)
         -&gt;  Seq Scan on orders_part_2011 orders  (cost=0.00..2.26 rows=1 width=18)
               Filter: (order_date = &#039;02-JAN-11 00:00:00&#039;::timestamp without time zone)
(6 rows)</pre><p>In the above output, you see that only one partition was scanned, based on the <code>WHERE</code> clause conditions. Let&#8217;s look at another example:</p><pre class="brush: sql; gutter: false; first-line: 1">EXPLAIN SELECT * FROM orders WHERE order_date = now();
                                     QUERY PLAN
-----------------------------------------------------------------
 Result  (cost=0.00..30.03 rows=8 width=41)
   -&gt;  Append  (cost=0.00..30.03 rows=8 width=41)
         -&gt;  Seq Scan on orders  (cost=0.00..26.50 rows=6 width=44)
               Filter: (order_date = now())
         -&gt;  Seq Scan on orders_part_2011 orders  (cost=0.00..2.51 rows=1 width=18)
               Filter: (order_date = now())
         -&gt;  Seq Scan on orders_part_2010 orders  (cost=0.00..1.01 rows=1 width=44)
               Filter: (order_date = now())
(8 rows)</pre><p>Here all the partitions are scanned &#8212; definitely not what we wanted! You should be aware of the fact that the planner analyses the query before the values from the parameters or stored procedures are substituted. As the planner does not know the exact value of <code>now()</code> during the planning phase, it cannot prune partitions, and so scans all the partitions. You need to look out for such cases where constant values are expected. In case you are planning to use functions in the <code>WHERE</code> clause, do make sure to understand the various types of functions that can be created in PostgreSQL.</p><p>Let us now go through the finer details of the three features used in PostgreSQL partitioning.</p><h2>Constraint exclusion</h2><p>Constraint exclusion works with only range or equality check constraints. It might not work for constraints like the following:</p><pre class="brush: sql; gutter: false; first-line: 1">ALTER TABLE product_items_j ADD CONSTRAINT chk_item_name CHECK (item_name LIKE &#039;P%&#039;);</pre><p>More importantly, the <code>WHERE</code> condition should be similar to the <code>CHECK</code> constraints. For example, if you have the following <code>CHECK</code> constraint:</p><pre class="brush: sql; gutter: false; first-line: 1">ALTER TABLE product_items_j ADD CONSTRAINT chk_item_name CHECK (item_name BETWEEN &#039;P&#039; AND &#039;PB&#039;&#039;);</pre><p>Then constraint exclusion would not help for the following query, since the <code>WHERE</code> condition is not similar to the <code>CHECK</code> constraint:</p><pre class="brush: sql; gutter: false; first-line: 1">SELECT item_name FROM product_items WHERE item_name LIKE &#039;Q%&#039; ;</pre><p>To get the constraint exclusion working, you need this form of query:</p><pre class="brush: sql; gutter: false; first-line: 1">SELECT item_name FROM product_items WHERE item_name = &#039;Pen&#039;;</pre><p>From the above examples, it should be clear that the user needs to take extra effort while handling the <code>WHERE</code> clause predicates, in order to hit the <code>CHECK</code> constraints. The other major problem with this setup is that there is no automatic way to verify if all the <code>CHECK</code> constraints are mutually exclusive. You need to be extra careful while setting them up.</p><p>The <code>EXPLAIN</code> feature comes in very handy to tackle these issues. Basically, any change to the query or table, even the slightest one, should be rigorously followed by looking at the <code>EXPLAIN</code> output. If you do not see the expected plan, then either the <code>WHERE</code> clause or the <code>CHECK</code> constraints need to be looked into.</p><h2>Inheritance</h2><p>The important rule that you should always be aware of is that child tables inherit column <code>DEFAULT</code> values, not <code>NULL</code> and <code>CHECK</code> constraints only. Any other constraints, like <code>UNIQUE</code>, <code>PRIMARY</code> and <code>FOREIGN</code> key, will not be inherited. Also, indexes, ownership and permissions will not be inherited.</p><p>One has to set up the non-inherited constraints on all the child tables. However, there are various ways of setting up these constraints, which we will discuss in the very next section. The child tables cannot rename inherited columns, but can add new columns &#8212; this is the biggest advantage of using inheritance.</p><p>You should also note that one can enable or disable inheritance on child tables by using the <code>ALTER TABLE</code> command. This is, in fact, very useful when you want to remove or move partitions from the base table.</p><p>Using inheritance, you can have multiple levels of partitioning. You can always create a great-great-grandchild of a partition, but you might experience a performance loss with this kind of setup, since more base tables are involved, directly or indirectly. So generally, 1 or 2 levels for partitions and sub-partitions should be good. If you are going any deeper, then most probably you need to rethink the partitioning scheme employed.</p><h2>Uniqueness</h2><p>PostgreSQL uses indexes for supporting uniqueness. However, there are no multi-table indexes, which means that an index cannot span over more than one table. This is the reason for not having any primary key in our setup. In general, you might want to concentrate on indexing the partitioning key columns. For this, create non-overlapping <code>CHECK</code> constraints and then create a unique index on partitioning key columns over each partition. This is almost like having unique values over all partitions.</p><p>For indexing the non-partitioning-key columns, you create unique indexes over each partition. However, for verifying uniqueness, you need custom functions to scan all partitions, which would hopefully use the related indexes.</p><p>As you must have realised, this scanning of all partitions was not what we wanted, to begin with. Also, due to the lack of multi-table indexes, maintaining a primary key or a foreign key is technically not possible.</p><p>Consider that you created a primary key on each of the order_id columns of all child tables. Now it may happen that both <code>orders_part_2011</code> and <code>order_part_2010</code> have an <code>order_id</code> value of 1. Even though the uniqueness constraint within each child table is upheld, the base table orders now has duplicate <code>order_id</code> values.</p><p>To overcome this, you can create an additional lookup table, with primary keys from the base as well as child tables. Basically, you need to use triggers to keep the lookup table updated as you insert, update or delete records from the related partitioned table. Now all the primary and foreign key constraints can be mapped to this lookup table.</p><p>That&#8217;s it! These are basic setup issues that you must be able to get through now. You should now be ready to face the next challenge &#8212; performance tuning for partitions.</p><h2>What&#8217;s around the corner?</h2><p>The PostgreSQL community does have several discussions on this feature. For more details, you can visit <a href="http://wiki.postgresql.org/wiki/Table_partitioning">this wiki entry on partitioning</a>.<div id="crp_related"><h5>Related Posts:</h5><ul><li><a href="http://www.linuxforu.com/2011/08/connecting-to-mysql-with-python-and-php/" rel="bookmark" class="crp_title">Connecting to MySQL With Python and PHP</a></li><li><a href="http://www.linuxforu.com/2012/01/device-drivers-partitions-hard-disk/" rel="bookmark" class="crp_title">Device Drivers, Part 14: A Dive Inside the Hard Disk for Understanding Partitions</a></li><li><a href="http://www.linuxforu.com/2011/10/lets-play-with-codeigniter/" rel="bookmark" class="crp_title">Let&#8217;s Play with CodeIgniter</a></li><li><a href="http://www.linuxforu.com/2011/06/advanced-awk-for-sysadmins/" rel="bookmark" class="crp_title">Advanced Awk for Sysadmins</a></li><li><a href="http://www.linuxforu.com/2009/05/database-programming-in-python/" rel="bookmark" class="crp_title">Database Programming in Python</a></li></ul></div>Tags: <a href="http://www.linuxforu.com/tag/constraints/" title="constraints" rel="tag">constraints</a>, <a href="http://www.linuxforu.com/tag/database-partition/" title="database partition" rel="tag">database partition</a>, <a href="http://www.linuxforu.com/tag/database-trigger/" title="database trigger" rel="tag">database trigger</a>, <a href="http://www.linuxforu.com/tag/design-decision/" title="design decision" rel="tag">design decision</a>, <a href="http://www.linuxforu.com/tag/inheritance/" title="inheritance" rel="tag">inheritance</a>, <a href="http://www.linuxforu.com/tag/lfy-january-2012/" title="LFY January 2012" rel="tag">LFY January 2012</a>, <a href="http://www.linuxforu.com/tag/partition-maintenance/" title="partition maintenance" rel="tag">partition maintenance</a>, <a href="http://www.linuxforu.com/tag/partitions/" title="partitions" rel="tag">partitions</a>, <a href="http://www.linuxforu.com/tag/postgresql/" title="PostgreSQL" rel="tag">PostgreSQL</a>, <a href="http://www.linuxforu.com/tag/tables/" title="Tables" rel="tag">Tables</a>, <a href="http://www.linuxforu.com/tag/timestamp-values/" title="timestamp values" rel="tag">timestamp values</a><br /> ]]></content:encoded> <wfw:commentRss>http://www.linuxforu.com/2012/01/partitioning-in-postgresql/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Lisp: Tears of Joy, Part 7</title><link>http://www.linuxforu.com/2011/12/lisp-tears-of-joy-part-7/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=lisp-tears-of-joy-part-7</link> <comments>http://www.linuxforu.com/2011/12/lisp-tears-of-joy-part-7/#comments</comments> <pubDate>Fri, 30 Dec 2011 10:37:37 +0000</pubDate> <dc:creator>Vivek Shangari</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[Developers]]></category> <category><![CDATA[AREF]]></category> <category><![CDATA[CLOS]]></category> <category><![CDATA[Common Lisp]]></category> <category><![CDATA[Languages]]></category> <category><![CDATA[LFY December 2011]]></category> <category><![CDATA[Lisp]]></category> <category><![CDATA[lisp code]]></category> <category><![CDATA[lisp programs]]></category> <category><![CDATA[Lisp: Tears of Joy series]]></category> <category><![CDATA[macro definition]]></category> <category><![CDATA[Macros]]></category> <category><![CDATA[object-based systems]]></category> <category><![CDATA[Paul Graham]]></category> <category><![CDATA[programming]]></category> <category><![CDATA[syntax]]></category><guid isPermaLink="false">http://www.linuxforu.com/?p=8580</guid> <description><![CDATA[Lisp has been hailed as the world&#8217;s most powerful programming language. But only the top percentile of programmers use it because of its cryptic syntax and academic reputation. This is rather unfortunate, since...]]></description> <content:encoded><![CDATA[<p><img class="aligncenter size-large wp-image-8581" title="Time to Lisp" src="http://cdn.linuxforu.com/wp-content/uploads/2011/12/Open-Image-LISP-7-590x391.jpg?d9c344" alt="Time to Lisp" width="590" height="391" /></p><div class="introduction">Lisp has been hailed as the world&#8217;s most powerful programming language. But only the top percentile of programmers use it because of its cryptic syntax and academic reputation. This is rather unfortunate, since Lisp isn&#8217;t that hard to grasp. If you want to be among the crème de la crème, <a href="http://www.linuxforu.com/tag/lisp-tears-of-joy-series/">this series</a> is for you. This is the seventh article in the series, which began in <a title="Lisp: Tears of Joy, Part 1" href="http://www.linuxforu.com/2011/06/lisp-tears-of-joy-part-1/">June 2011</a>.</div><h2>Macros &#8212; can&#8217;t get enough of them!</h2><p>You already know from my <a href="http://www.linuxforu.com/tag/lisp-tears-of-joy-series/">previous articles</a> that macros are Lisp programs that generate other Lisp programs. The generated Lisp code has fully parenthesised notation, and so does the macro that generates the code. In the simplest case, a macro substitutes forms within a template, clearly establishing a visual correspondence between the generating code and the generated code.</p><p>Complex macros can use the full power of the Lisp language to generate code according to the macro parameters; often, a template form is wrapped in code that constructs appropriate sub-forms, but even this approach is just a typical pattern of use, and not a requirement (or restriction) of the Lisp macro facility.</p><p>To refresh our memories, let&#8217;s examine the mechanism by which the Lisp system translates code generated by a macro. You define a macro with a <code>defmacro</code> form; <code>defmacro</code> is like <code>defun</code>, but instead of returning values, the body of the <code>defmacro</code> returns a Lisp form. Your program &#8216;calls&#8217; a macro the same way it calls a function, but the behaviour is quite different.</p><p>First, none of the macro&#8217;s parameters are evaluatedever. Macro parameters are bound literally to the corresponding arguments in the macro definition. If you pass <code>(* 7 (+ 3 2))</code> to a macro, the argument in the body of the macro definition is bound to the literal list <code>(* 7 (+ 3 2))</code> and not the value 35.</p><p>Next, the macro expander is invoked, receiving all of the actual parameters bound to their corresponding arguments as named by the <code>defmacro</code> form. The macro expander is merely the body of the <code>defmacro</code> form, which is just Lisp code; the only catch is that the Lisp system expects the macro expander to return a Lisp form. The Lisp system then evaluates whatever form the macro expander returns.</p><p>A Lisp implementation may expand macros at different times. A macro could be expanded just once, when your program is compiled. Or it could be expanded on first use as your program runs, and the expansion could be cached for subsequent reuse. A properly written macro will behave the same under all of these implementations.</p><p>Let&#8217;s explore a real-world example of using a macro to extend Lisp into the problem domain. In addition to providing a macro expander, our new macro will automatically generate an environment that will be referenced by the expander. Our example will show how to move computations from run-time to compile-time, and how to share information computed at compile-time.</p><p>Let&#8217;s say you&#8217;re working on an interactive game that makes heavy use of the trigonometric function sin r in computing player motion and interaction. You&#8217;ve already determined that calling the Lisp function sin is too time-consuming; you also know that your program will work just fine with approximate results for the computation of sin r. You&#8217;d like to define a lookup-sin macro to do the table lookup at runtime and also hide the details of table generation, which would just clutter your program&#8217;s source code.</p><p>Your macro will be invoked as (lookup-sin radians divisions), where radians is always in the range of zero to one-half pi, and divisions is the number of discrete values available as the result of lookup-sin. At runtime, the macro expander will just compute the index into a lookup table, and return the value from the table. The table will be generated at compile-time (on most Lisp systems). Furthermore, only one table will ever be generated for a given value of divisions in the macro call.</p><pre class="brush: text; gutter: false; first-line: 1">;; This is where we cache all of the sine tables generated during compilation.
;; The tables stay around at runtime so they can be used for lookups.
(defvar *sin-tables* (make-hash-table)
    &quot;A has table of tables of sine values. The hash is keyed by the number of entries in each sine table.&quot;)

;; This is a helper function for the lookup-sin macro. It is used only at compile
;; time.
(defun get-sin-table-and-increment (divisions)
    &quot;Returns a sine lookup table and the number of radians quantised by each entry in the table. Tables of a given size are reused. A table covers angles from zero to pi/2 radians.&quot;
(let ((table (gethash divisions *sin-tables* :none))
      (increment (/ pi 2 divisions)))
    (when (eq table :none)
        ;; Uncomment the next line to see when a table gets created.

        ;; (print `|Making new table|)
        (setq table
            (setf (gethash divisions *sin-tables*)
                  (make-array
                    (1+ divisions)
                    :initial-element 1.0)))
        (dotimes (i divisions)
            (setf (aref table i)
                  (sin (* increment i)))))
     (values table increment)))

;; Macro calls the helper at compile time, and returns an AREF form to do the
;; lookup at runtime.
(defmacro lookup-sin (radians divisions)
    &quot;Return a sine value via table lookup.&quot;
    (multiple-value-bind (table increment)
                         (get-sin-table-and-increment divisions)
        `(aref, table (round, radians, increment))))</pre><p>Let us examine what is happening here. When this program runs, it executes just <code>aref</code>  (and associated round) to look up the sin r value.</p><pre class="brush: text; gutter: false; first-line: 1">&gt; (pprint (macroexpand-1 `(lookup-sin (/ pi 4) 50)))

(AREF #(0.0D0 0.03141075907812829D0 0.06279051952931338D0 0.09410831331851433D0 0.12533323356430426D0 0.15643446504023087D0 0.18738131458572463D0 0.21814324139654257D0 0.2486898871648548D0 0.2789911060392293D0
        0.3090169943749474D0 0.3387379202452914D0 0.368124552684678D0 0.3971478906347806D0 0.4257792915650727D0 0.4539904997395468D0 0.4817536741017153D0 0.5090414157503713D0 0.5358267949789967D0 0.5620833778521306D0
        0.5877852522924731D0 0.6129070536529765D0 0.6374239897486898D0 0.6613118653236518D0 0.6845471059286887D0 0.7071067811865476D0 0.7289686274214116D0 0.7501110696304596D0 0.7705132427757893D0 0.7901550123756904D0
        0.8090169943749475D0 0.8270805742745618D0 0.8443279255020151D0 0.8607420270039436D0 0.8763066800438637D0 0.8910065241883678D0 0.9048270524660196D0 0.9177546256839811D0 0.9297764858882515D0 0.9408807689542256D0
        ...)
      (ROUND (/ PI 4) 0.031415926535897934D0))</pre><p>Note that the macro call makes no mention of a lookup table. Tables are generated as needed by (and for) the compiler.</p><pre class="brush: text; gutter: false; first-line: 1">&gt; (lookup-sin (/ pi 4) 50)
0.7071067811865476D0</pre><p>In the macro expansion, the <code>#(...)</code> is the printed representation of the lookup table for 50 divisions of the quarter circle. This table is stored in the <code>*sin-tables*</code> hash table, where it is shared by every macro call to <code>(lookup-sin angle 50)</code>. We don&#8217;t even have to do a hash lookup at runtime, because the macro expander has captured the free variable table from the multiple-value-bind form in <code>lookup-sin</code>.</p><h2>Macros that define macros</h2><p>Macros that define macros are used infrequently, partly because it&#8217;s hard to think of a good use for this technique, and partly because it&#8217;s difficult to get right. The following macro, based on an example in Paul Graham&#8217;s book <em>On Lisp</em>, can be used to define synonyms for the names of Lisp functions, macros, and special forms.</p><pre class="brush: text; gutter: false; first-line: 1">&gt; (defmacro defsynonym (old-name new name)
&quot;Define OLD-NAME to be equivalent to NEW-NAME when used in the first position of a Lisp form.&quot;
 `(defmacro, new-name (&amp;rest args)
                    `(,`,old-name, @args)))
DEFSYNONYM

&gt; (defsynonym make-pair cons)
MAKE-PAIR

&gt; (make-pair `a `b)
(A . B)</pre><p>Macros are always a little bit dangerous because code containing a macro call does not automatically get updated if you change the definition of the macro. You can always establish your own convention to help you remember that you need to recompile certain code after you change a macro definition. But there&#8217;s always the possibility that you&#8217;ll forget, or make a mistake.</p><p>Ultimately, the likelihood that you&#8217;ll inadvertently end up with code that was compiled with an old version of a macro is directly proportional to how often you&#8217;re likely to change the macro. A macro like <code>defsynonym</code> practically begs to be used again and again as you generate new code. If you change your mind about the old name to associate with a given new name, all of your previously compiled code will still refer to the old name that you had decided upon earlier.</p><p>I&#8217;ll leave you here to have fun with your macros.</p><p>In the next article, we&#8217;ll take a peek into Common Lisp Object System (CLOS) which allows you to build very sophisticated object-based systems. If you care to code with a strongly object-oriented mindset, you will probably find all the OOP language functionality you need in Common Lisp. CLOS has many advanced object-oriented features that you won&#8217;t find in many other places. Because of this, CLOS has often been used as a research tool for studying OOP ideas.<div id="crp_related"><h5>Related Posts:</h5><ul><li><a href="http://www.linuxforu.com/2011/10/lisp-tears-of-joy-part-5/" rel="bookmark" class="crp_title">Lisp: Tears of Joy, Part 5</a></li><li><a href="http://www.linuxforu.com/2011/11/lisp-tears-of-joy-part-6/" rel="bookmark" class="crp_title">Lisp: Tears of Joy, Part 6</a></li><li><a href="http://www.linuxforu.com/2011/08/lisp-tears-of-joy-part-3/" rel="bookmark" class="crp_title">Lisp: Tears of Joy, Part 3</a></li><li><a href="http://www.linuxforu.com/2012/01/lisp-tears-of-joy-part-8/" rel="bookmark" class="crp_title">Lisp: Tears of Joy, Part 8</a></li><li><a href="http://www.linuxforu.com/2011/09/lisp-tears-of-joy-part-4/" rel="bookmark" class="crp_title">Lisp: Tears of Joy, Part 4</a></li></ul></div>Tags: <a href="http://www.linuxforu.com/tag/aref/" title="AREF" rel="tag">AREF</a>, <a href="http://www.linuxforu.com/tag/clos/" title="CLOS" rel="tag">CLOS</a>, <a href="http://www.linuxforu.com/tag/common-lisp/" title="Common Lisp" rel="tag">Common Lisp</a>, <a href="http://www.linuxforu.com/tag/languages/" title="Languages" rel="tag">Languages</a>, <a href="http://www.linuxforu.com/tag/lfy-december-2011/" title="LFY December 2011" rel="tag">LFY December 2011</a>, <a href="http://www.linuxforu.com/tag/lisp/" title="Lisp" rel="tag">Lisp</a>, <a href="http://www.linuxforu.com/tag/lisp-code/" title="lisp code" rel="tag">lisp code</a>, <a href="http://www.linuxforu.com/tag/lisp-programs/" title="lisp programs" rel="tag">lisp programs</a>, <a href="http://www.linuxforu.com/tag/lisp-tears-of-joy-series/" title="Lisp: Tears of Joy series" rel="tag">Lisp: Tears of Joy series</a>, <a href="http://www.linuxforu.com/tag/macro-definition/" title="macro definition" rel="tag">macro definition</a>, <a href="http://www.linuxforu.com/tag/macros/" title="Macros" rel="tag">Macros</a>, <a href="http://www.linuxforu.com/tag/object-based-systems/" title="object-based systems" rel="tag">object-based systems</a>, <a href="http://www.linuxforu.com/tag/paul-graham/" title="Paul Graham" rel="tag">Paul Graham</a>, <a href="http://www.linuxforu.com/tag/programming/" title="programming" rel="tag">programming</a>, <a href="http://www.linuxforu.com/tag/syntax/" title="syntax" rel="tag">syntax</a><br /> ]]></content:encoded> <wfw:commentRss>http://www.linuxforu.com/2011/12/lisp-tears-of-joy-part-7/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Content Delivery Network via cdn.linuxforu.com

Served from: www.linuxforu.com @ 2012-02-04 12:22:02 -->
