<?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>Aptivate &#124; A Blog for ICT4D &#187; Open Source</title>
	<atom:link href="http://blog.aptivate.org/category/open-source/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.aptivate.org</link>
	<description>International I.T. Development</description>
	<lastBuildDate>Thu, 02 Sep 2010 08:18:20 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Digital Photography on Linux</title>
		<link>http://blog.aptivate.org/2010/09/02/digital-photography-on-linux/</link>
		<comments>http://blog.aptivate.org/2010/09/02/digital-photography-on-linux/#comments</comments>
		<pubDate>Thu, 02 Sep 2010 08:12:39 +0000</pubDate>
		<dc:creator>chrisw</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Photography]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blog.aptivate.org/?p=623</guid>
		<description><![CDATA[Many people think that digital photography on Linux is much harder than on Windows or Macintosh. This is a typical comment:
As a hobby I&#8217;m a photographer, so I do lots of graphic work as editing for invites, posters, mag covers etc. does any one know of a software that will be as great as photoshop [...]]]></description>
			<content:encoded><![CDATA[<p>Many people think that digital photography on Linux is much harder than on Windows or Macintosh. This is a typical comment:</p>
<blockquote><p>As a hobby I&#8217;m a photographer, so I do lots of graphic work as editing for invites, posters, mag covers etc. does any one know of a software that will be as great as photoshop for linux (Ubuntu), not Gimp, Gimp is very limited. I tried using WINE but it doesnt work well, very slow.</p></blockquote>
<p>It was true for a long time that working with digital photos on Linux was difficult. The main problem was that the most popular software that users are familiar with, Photoshop and Lightroom, is simply not available for Linux (due to unfortunate business decisions by Adobe).</p>
<p>There have been open source alternatives to Photoshop for a while, notably Gimp, but Gimp is difficult to use and the interface is quite annoying:</p>
<blockquote><p>
I&#8217;d say the major limiting factor is the desire to slit your wrists while arguing with the unwieldy interface layout.</p></blockquote>
<p>Luckily today I came across (thanks to Alastair Otter of GLUG) this excellent article:</p>
<p><a href="http://blog.worldlabel.com/2010/photography-with-open-source-linux.html">Photography with Open Source / Linux</a></p>
<p>This includes detailed descriptions of the many applications available, most of which I hadn&#8217;t heard of before, and look forward to trying. I&#8217;ve been particularly impressed by Adobe Lightroom&#8217;s ease of use and powerful histogram correction features, and I was considering buying a copy even though it doesn&#8217;t run on Linux, but I will definitely try Darktable now.</p>
<p>For users who really, really have to have a Photoshop user interface, <a href="http://www.gimpshop.com/">GimpShop</a> may help.</p>
<p>And before you say &#8220;this is not work related&#8221;, I&#8217;ve often needed to edit photographs to prepare brochures, promotional materials and for website work <img src='http://blog.aptivate.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>It seems that digital photography on Linux has made excellent progress in the last year, and I&#8217;m very happy to see it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aptivate.org/2010/09/02/digital-photography-on-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>System Imaging for Free using G4L</title>
		<link>http://blog.aptivate.org/2010/07/22/free-system-imaging-using-g4l/</link>
		<comments>http://blog.aptivate.org/2010/07/22/free-system-imaging-using-g4l/#comments</comments>
		<pubDate>Thu, 22 Jul 2010 13:05:34 +0000</pubDate>
		<dc:creator>chrisw</dc:creator>
				<category><![CDATA[Engineer's Log]]></category>
		<category><![CDATA[Infrastructure]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[System Administration]]></category>

		<guid isPermaLink="false">http://blog.aptivate.org/?p=594</guid>
		<description><![CDATA[This is a copy of the notes that I wrote at AfNOG 2010 as a guide to using system imaging at future workshops. Unfortunately that wiki is not accessible without signing up for an account, so I&#8217;m posting the information here too.
How to Install Computer Labs
If you ever need to set up a large number [...]]]></description>
			<content:encoded><![CDATA[<p>This is a copy of the <a href="http://nsrc.org/workshops/2010/afnog/wiki/SystemImaging">notes</a> that I wrote at AfNOG 2010 as a guide to using system imaging at future workshops. Unfortunately that wiki is not accessible without signing up for an account, so I&#8217;m posting the information here too.</p>
<h3>How to Install Computer Labs</h3>
<p>If you ever need to set up a large number of computers in identical configurations, you have a few options:</p>
<ul>
<li>Install each one individually by hand</li>
<li>Automate the standard install process, for example using:
<ul>
<li><a href="http://en.wikipedia.org/wiki/Windows_Automated_Installation_Kit">AIK</a> for Windows;</li>
<li><a href="https://help.ubuntu.com/7.04/installation-guide/i386/automatic-install.html">Kickstart</a> for Red Hat Linux, CentOS and Ubuntu; or</li>
<li><a href="http://people.freebsd.org/~dwhite/bsdconpaper.html">sysinstall and mfsroot</a> for FreeBSD.</li>
</ul>
</li>
<li>Configure one machine exactly how you like it, and then exactly duplicate the hard disk to the others (disk imaging)</li>
</ul>
<p>The first option (manual installation) is extremely slow, tedious, error-prone, unlikely to result in identical machines, and does not speed up future installations or reinstallations.</p>
<p>The second option requires using rarely-used and less tested parts of the installer, scales poorly in performance for simultaneous installations, and places limits on what you can customise. For example, it could be impossible to customise <code>/etc/rc.conf</code> using the installer on FreeBSD, and pre-installing SSH keys is tricky. I also spent days writing a sysinstall script to automate a process that I could have done in half an hour by configuring a single machine manually.</p>
<p>Therefore I prefer the third option, system imaging.</p>
<h3>What is System Imaging</h3>
<p>Imaging is the process of making exact copies of one machine&#8217;s hard disk, including all partitions, onto another. This only works when the second hard disk is at least as large as the first. It works best when all the PCs are identical.</p>
<p>Imaging is independent of the operating system. You can image Windows, FreeBSD, any version of Linux, dual-boot and triple-boot installations, whatever you like.</p>
<p>We successfully used imaging to set up the PCs for these workshops:</p>
<ul>
<li><a href="http://www.ws.afnog.org/afnog2009/">AfNOG 2009</a>, Cairo, all tracks</li>
<li><a href="http://oer.aptivate.org/wiki/KBT/BMO_Training_KENET">KENET BMO Training</a>, Nairobi 2009</li>
<li><a href="http://www.ws.afnog.org/afnog2010/">AfNOG 2010</a>, Kigali, for three tracks: SA-E, SS-E and SI-F</li>
</ul>
<h3>How to Image</h3>
<p>Many systems administrators have heard of <a href="http://www.symantec.com/norton/ghost">Norton Ghost</a> and <a href="http://www.acronis.com/homecomputing/products/trueimage/index.html">Acronis True Image</a>, two of the most popular commercial applications.</p>
<p>However, open source alternatives such as <a href="http://freshmeat.net/projects/g4l/">G4L</a> (Linux-based) and its ancestor <a href="http://www.feyrer.de/g4u/">G4U</a> (FreeBSD-based) are pretty good, and completely free. G4L however lacks a website, and it&#8217;s not obvious how best to use it, hence this post.</p>
<p>G4L is quite similar to G4U, and I could have used G4U instead. But I find the Linux kernel&#8217;s hardware support a bit better than FreeBSD&#8217;s, and G4L supports multicasting, which enables it to install many machines at the same time with good performance.</p>
<h3>Using Ghost for Linux (G4L)</h3>
<p>I&#8217;ve successfully used Ghost 4 Linux (G4L) versions 0.27 and 0.33 for this process. 0.33 has multicast support, which allows setting up an entire room in one go, without wasting network bandwidth copying the same 4 GB disk image to each of 50 machines independently.</p>
<p>Set up an FTP server on your network with an account that supports downloads and uploads (e.g. on a local server on your network). Make sure it has plenty of disk space free, perhaps 40 GB. Create an &#8220;img&#8221; directory under the FTP user&#8217;s home directory for the images.</p>
<p>Download G4L and burn some CDs, maybe about five copies, or set up network booting (this conflicts with FreeBSD PXE installation and may require BIOS setup changes to enable PXE).</p>
<p>To boot into G4L:</p>
<ul>
<li>Reboot or power up the machine</li>
<li>Press the key to choose boot device</li>
<li>If CD-ROM is not on the list, reboot, go into the BIOS and enable booting from CD-ROM</li>
<li>Choose to boot from the CD</li>
<li>Choose the default kernel at the GRUB screen (just press Enter)
<ul>
<li>If for some reason the default kernel doesn&#8217;t work, the machine hangs or crashes or doesn&#8217;t detect the network interface, then try one or two other kernels</li>
</ul>
</li>
<li>Wait for the kernel and initrd to be loaded (two long lines of dots)</li>
<li>Then you can remove the CD, about one minute from cold boot, and start booting another PC</li>
<li>Press space to skip each of the information/advertising screens (about 8 of them)</li>
<li>Enter <code>g4l</code> at the prompt (if you go past this and get a shell, just type <code>g4l</code> at the shell prompt)</li>
<li>You can access other consoles with Ctrl-Alt-F1 to F4, log in as <code>g4l</code> with no password, and run <code>g4l</code>, <code>ifconfig</code>, <code>ping</code> or whatever</li>
<li>Choose <em>Network Use</em> (default)</li>
<li>Choose <em>Raw Mode</em> (default)</li>
<li>Check that you have an IP address (option B) or try again to acquire one by DHCP</li>
<li>If you can&#8217;t get an IP address by DHCP, check your cabling and DHCP server</li>
</ul>
<h3>Create a Restore Image (optional)</h3>
<p>Back up one of your PCs if necessary (if you plan to restore the PCs later) by:</p>
<ul>
<li>Follow the procedure above to get into Ghost for Linux</li>
<li>Enter the FTP server&#8217;s IP address, username and password</li>
<li>Choose an image name, e.g. <code>backup_original_2010_07_22.img</code></li>
<li>Choose the <em>back up</em> option</li>
<li>Press Space to select the entire disk (mark it with an asterisk [*])</li>
<li>Start backing up the image</li>
</ul>
<p>This process can take 1-2 hours. In the mean time&#8230;</p>
<h3>Set up the Master PC</h3>
<p>Boot G4L on the PC that you will use as the master. Use DD to wipe the entire disk with zeroes:</p>
<pre>
dd if=/dev/zero of=/dev/sda bs=1M
</pre>
<p>This makes the image much smaller, and transfer much faster.</p>
<p>Install FreeBSD or whatever operating system(s) on the master PC, and set it up exactly the way you want all of the PCs to be. Examples include:</p>
<ul>
<li>Install Gnome (gnome/gnome2)</li>
<li>Install Xorg (x11/xorg)</li>
<li>Install Firefox (www/firefox35)</li>
<li>Install Xpdf (print/xpdf)</li>
<li>Enable gnome and sshd in <code>/etc/rc.conf</code>, and add templates for the IP address configuration (this saves typing when setting all the machines to static IPs):
<pre>
hostname="pc01.sse.ws.afnog.org"
ifconfig_bge0="dhcp"
# ifconfig_bge0="196.200.219.101/24"
defaultrouter="196.200.219.254"
gnome_enable="YES"
sshd_enable="YES"
</pre>
</li>
<li>Create a user account (e.g. username <code>afnog</code>, password <code>afnog</code>)</li>
<li>Log into Gnome, add firefox, terminal and the Downloads folder to your toolbar, and remove epiphany and evolution</li>
<li>Edit /etc/fstab and add the proc filesystem:
<pre>
proc /proc procfs rw 0 0
</pre>
<p>(this allows GDM to display the user list and shut down and restart the machine)</li>
<li>Edit /etc/profile and set the default pager to less by adding:
<pre>
PAGER=less; export PAGER
</pre>
</li>
<li>Set the timezone by softlinking <code>/etc/localtime</code> to something like /usr/share/zoneinfo/Africa/Kigali</li>
<li>Create <code>/etc/rc.local</code> and have it run <code>/usr/sbin/ntpd -qg</code> to set the time once at boot</li>
</ul>
<p>I recommend using DHCP on this machine. Otherwise all the imaged machines will boot up with the same IP address, causing IP address conflicts, and you will have to reconfigure them before you can access the Internet at all, or reconfigure them automatically.</p>
<p>Create some SSH keys for use in administering the machines. You may wish to set up the local server already and generate the keys there for security. I recommend adding the keys to <code>/root/.ssh/authorized_keys</code>. Please test that they work, and that sshd comes up automatically after boot!</p>
<h3>Imaging the other PCs</h3>
<p>On all the PCs (master and clones):</p>
<ul>
<li>Boot G4L as above</li>
<li>Check that it has an IP address (option B)</li>
</ul>
<p>Once a master is online, all the PCs will show &#8220;press any key to start&#8221;. Pressing any key on any computer will start all the machines imaging. If any PCs are not ready yet, you will have to cancel the imaging process on all of them and start again, or image those PCs later. So:</p>
<p><strong>Start the master last!</strong> (when all the other PCs are ready)</p>
<p>Start the clones first, by following these steps on each one:</p>
<ul>
<li>Choose UDP Multicast Client (option U)</li>
<li>Select the entire disk, <code>/dev/sda</code> with the space key</li>
<li>Say yes, you&#8217;re sure</li>
<li>When it says &#8220;Compressed UDP receiver&#8221;, it&#8217;s ready and waiting for a master to appear on the network</li>
</ul>
<p>Then start the master:</p>
<ul>
<li>Get ALL the clones ready, as above, before doing this!</li>
<li>On the master, choose UDP Multicast Server (option W)</li>
<li>Select the entire disk, <code>/dev/sda</code>, with the space key</li>
<li>Leave the options blank</li>
<li>Say yes, you&#8217;re sure</li>
<li>The master start accepting connections from clients, which will happen automatically. The screens on the clients will also change.</li>
<li>Please check that every client says &#8220;Press any key to start&#8221;.</li>
<li>If not, please check it for network problems, etc.</li>
<li><strong>DO NOT</strong> stop or kill the server now, unless you want to visit every client again!</li>
<li>You can press Ctrl+C <strong>on the client</strong> and run <code>g4l</code> again to check the IP address, retry DHCP, and try the UDP Multicast Client option again.</li>
<li>This is your last chance to join any remaining clients to the group for this imaging session!</li>
<li>When all the clients are ready, press a key on the master to start transfer.</li>
</ul>
<p>The master will show progress of the transfer, and an error line if any clients fail to respond. Clients that cause too many errors will be kicked out of the group and appear to &#8220;finish&#8221; early.</p>
<p>It&#8217;s difficult to tell if the imaging process finished successfully or failed on the clients. However it appears that FreeBSD is very good at detecting filesystem corruption, and will fail to boot if the image was not completely transferred. So you can test them by trying to boot FreeBSD and seeing if it boots completely or stops with a filesystem error. Ideally this would be improved in future versions of G4L.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aptivate.org/2010/07/22/free-system-imaging-using-g4l/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mobiles for Scientific Research</title>
		<link>http://blog.aptivate.org/2010/07/09/mobiles-for-scientific-research/</link>
		<comments>http://blog.aptivate.org/2010/07/09/mobiles-for-scientific-research/#comments</comments>
		<pubDate>Fri, 09 Jul 2010 09:43:54 +0000</pubDate>
		<dc:creator>chrisw</dc:creator>
				<category><![CDATA[Mobiles]]></category>
		<category><![CDATA[Offline]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[PDAs]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[bandwidth]]></category>
		<category><![CDATA[data collection]]></category>
		<category><![CDATA[africa]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[ictp]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[science]]></category>

		<guid isPermaLink="false">http://blog.aptivate.org/?p=591</guid>
		<description><![CDATA[We know mobiles are very useful in areas where desktop computer and communications infrastructure is not easily available or affordable. And we&#8217;re very interested in mobile applications and scientific research in exactly these regions.
So I was very interested to see a new training workshop being run by the Science Dissemination Unit (SDU) of the Abdus [...]]]></description>
			<content:encoded><![CDATA[<p>We know mobiles are very useful in areas where desktop computer and communications infrastructure is not easily available or affordable. And we&#8217;re very interested in mobile applications and scientific research in exactly these regions.</p>
<p>So I was very interested to see a new training workshop being run by the <a href="http://sdu.ictp.it">Science Dissemination Unit (SDU)</a> of the <a href="http://ictp.it">Abdus Salam International Centre for Theoretical Physics (ICTP)</a>. The workshop is on <a href="http://cdsagenda5.ictp.trieste.it/full_display.php?ida=a09152">Mobile Science: Sensing, Computing and Dissemination</a> and the deadline for applications is tomorrow, July 10th.</p>
<p>Quoting from the announcement: </p>
<blockquote><p>
The Science Dissemination Unit (SDU) of the Abdus Salam International Centre for Theoretical Physics (ICTP), with the assistance of the University of Washington (USA) and of the UCLA Centerfor Embedded Networked Sensing (USA) will hold a Workshop on &#8220;Mobile Science: Sensing, Computing and Dissemination&#8221; in Trieste (Italy) from the 2 to the 5 of November 2010.</p>
<p>Mobile applications offer tremendous benefits to academic research and<br />
education, and to society as a whole throughout the world. This is an<br />
opportunity that deserves attention and promotion, especially in less<br />
developed areas where mobile phones are the first telecommunications<br />
technology in history to have more users than in the developed world.
</p></blockquote>
<p>The specific things that interested me were:</p>
<dl>
<dt>The Mobile Science workshop aims to engage the scientific community in developing countries in the design, development, and deployment of the newest mobile scientific applications;</dt>
<dd>i.e. advocating appropriate mobile applications in scientific<br />
research/academia;</dd>
<dt>Participants will learn how to apply mobile technology tools to retrieve scientific data</dt>
<dd>I.e. designing mobile apps for science data collection;</dd>
<dt>how to apply appropriate web-based analysis to assimilate mobile data into scientific studies</dt>
<dd>I.e. web-based statistical analysis and presentation, like a free online version of SPSS? As far as I know this doesn&#8217;t exist yet. The closest that I can think of is the Google Docs spreadsheet, which is of course just a spreadsheet, requires an internet connection and doesn&#8217;t allow plugins for additional scientific analysis functionality. But there could be a very interesting app to develop here.</dd>
<dt>and how to share their scientific findings with a potentially large mobile audience.</dt>
<dd>I.e. <a href="http://www.aptivate.org/webguidelines/">low bandwidth design</a> with an emphasis on web standards for cross-platform compatibility, so that it works on the largest number of mobile devices.</dd>
</dl>
<p>If you want to apply, better get on your bike (or modem?) because the deadline is tomorrow. If you want to do mobile scientific research applications, please get in touch, we&#8217;d like to help you.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aptivate.org/2010/07/09/mobiles-for-scientific-research/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simulating low bandwidth: Publishers for Development</title>
		<link>http://blog.aptivate.org/2010/06/08/simulating-low-bandwidth-publishers-for-development/</link>
		<comments>http://blog.aptivate.org/2010/06/08/simulating-low-bandwidth-publishers-for-development/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 16:09:55 +0000</pubDate>
		<dc:creator>chrisw</dc:creator>
				<category><![CDATA[Design and Usability]]></category>
		<category><![CDATA[Engineer's Log]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[bandwidth]]></category>
		<category><![CDATA[academia]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[freebsd]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[publishing]]></category>
		<category><![CDATA[research]]></category>

		<guid isPermaLink="false">http://blog.aptivate.org/?p=472</guid>
		<description><![CDATA[We think that academic publishing is an area that's both critically important to development, and simultaneously becoming more and more inaccessible to the people who need it most. The average size of web pages has been growing much faster than the average speed of connections in developing countries. We built a low bandwidth simulator ourselves, and took it to INASP and the ACU's Publishers for Development conference in Oxford to persuade the journal publishers to optimize their sites to make them accessible to everyone.]]></description>
			<content:encoded><![CDATA[<p>We think that academic publishing is an area that&#8217;s both critically important to development, and simultaneously becoming more and more inaccessible to the people who need it most.</p>
<p>The average size of web pages has been growing much faster than the average speed of connections in developing countries, and journal websites are no exception, as you can see in <a href="http://blog.aptivate.org/2009/07/09/when-it-comes-to-websites-small-is-beautiful/">Alan&#8217;s blog post</a>:</p>
<div id="attachment_488" class="wp-caption aligncenter" style="width: 510px"><a href="http://blog.aptivate.org/2010/06/08/simulating-low-bandwidth-publishers-for-development/graph-2/" rel="attachment wp-att-488"><img src="http://blog.aptivate.org/wp-content/uploads/2010/06/graph-500x381.png" alt="Average page size has grown much faster than available bandwidth" title="Average Page Size vs Bandwidth" width="500" height="381" class="size-large wp-image-488" /></a><p class="wp-caption-text">Average Page Size vs Bandwidth</p></div>
<p>As Alan points out, the average journal&#8217;s home page in his sample would take over <strong>90 seconds</strong> to load on average, for researchers at universities in developing countries. Usability research has shown that people expect a computer to respond within 30 seconds. Making them wait longer interrupts their concentration, causes dissatisfaction and annoyance, and they <strong>often abandon the process</strong>. The biggest factor in user satisfaction is speed of response.</p>
<p>While this research probably did not include users who are accustomed to slow and unreliable computers, I think it&#8217;s safe to say that most people would find it annoying and difficult to use the Internet on a dial-up modem. And even a modem would have been preferable to some of the Internet connections that I&#8217;ve experienced (and paid for) in some countries in the last few years.</p>
<p>Academics have little ability to persuade their universities to upgrade their internet connections, at a cost of several peoples&#8217; salaries (several thousand dollars a month). The only people who can change this are the publishers of the journals, by optimising their journals&#8217; websites for users with slower connections.</p>
<p>But how to persuade the publishers that this is important? We built a low bandwidth simulator ourselves, and took it to Oxford, to <a href="http://www.inasp.info">INASP</a> and the <a href="http://www.acu.ac.uk/">ACU</a>&#8217;s <a href="http://www.inasp.info/file/f5c039878f09a104df806301113361a5/publishers-for-development-pfd.html">Publishers for Development</a> conference.</p>
<h3>What We Did</h3>
<p>We set up spare machine as a <a href="http://bwmo.net">bandwidth management</a> box, and used it as a network filter for the participants. They could come and plug their laptops into the box, and browse the Internet and their own websites at a simulated slow speed.</p>
<div id="attachment_504" class="wp-caption aligncenter" style="width: 510px"><a href="http://blog.aptivate.org/2010/06/08/simulating-low-bandwidth-publishers-for-development/table-layout/" rel="attachment wp-att-504"><img src="http://blog.aptivate.org/wp-content/uploads/2010/06/table-layout-500x302.jpg" alt="Table with server, router and laptops with exercise cards stuck on top" title="Exercise Table" width="500" height="302" class="size-large wp-image-504" /></a><p class="wp-caption-text">Exercise Table</p></div>
<p>We configured the box for transparent bridging. This allowed us to insert and remove it from the network easily, just by switching over a network cable, to demonstrate the difference between fast and slow loading of pages.</p>
<p>We gave the participants at the meeting tasks to perform on various publishers&#8217; websites, for example finding and downloading an academic paper by topic or researcher.</p>
<div id="attachment_502" class="wp-caption aligncenter" style="width: 510px"><a href="http://blog.aptivate.org/2010/06/08/simulating-low-bandwidth-publishers-for-development/publishers-testing/" rel="attachment wp-att-502"><img src="http://blog.aptivate.org/wp-content/uploads/2010/06/publishers-testing-500x408.jpg" alt="Participants watching and using the throttled laptops" title="Playing the Game" width="500" height="408" class="size-large wp-image-502" /></a><p class="wp-caption-text">Playing the Game</p></div>
<p>I think they found the activities enlightening, because we had some very good comments from some of the participants:</p>
<ul>
<li>&#8220;<em>We&#8217;re so pleased that Alan was able to work his magic at the recent PfD session &#8211; his delivery is innovative, dynamic and fact-packed so it really sparks enthusiasm from the audience&#8230; [which] is demonstrably channelled into action once people return to their places of work.</em>&#8220;<br />Publishers for Development Team</li>
<li>&#8220;<em>It was really useful to try the low bandwidth! [Our site] is already considered fast but it made us think even more around this issue, what else can we do etc.</em>&#8220;<br />Anonymous Participant
</li>
<li>&#8220;<em>Alan Jackson&#8217;s information about bandwidth was kind of shocking even if I knew it before, but to really experience it was very valuable. We are going to redesign DOAJ&#8217;s home page and this must be the starting point.</em>&#8220;<br />Sonja Brage, DOAJ
</li>
<li>&#8220;<em>Site speed is a major consideration for us, and I really enjoyed Alan/Aptivate&#8217;s session, experiencing the exasperation of trying (and failing) to connect via low-bandwidth&#8230; I have a feeling that there is &#8216;excess baggage&#8217; on a number of the pages&#8230;</em>&#8220;<br />James Kitchen, OECD
</li>
</ul>
<h3>How We Did It</h3>
<p>We used FreeBSD as the operating system for the software bridge, because its <em>dummynet</em> traffic shaper is relatively easy to use, and very good at simulating slow connections.</p>
<p>We wanted to use a laptop instead of a desktop machine, so that we could carry it to the conference easily, but we had hardware compatibility issues with FreeBSD on all the laptops we had available to us (mostly IBM Thinkpads). We ended up using a compact Fujitsu desktop box.</p>
<p>We installed FreeBSD 8 on it, and configured it to transparently bridge between two interfaces. Our internet access at the conference would be wireless, but we had issues with bridging wired and wireless interfaces together. So instead we used a <a href="http://en.wikipedia.org/wiki/Linksys_WRT54G_series">Linksys WRT-54GL</a> router with the <a href="http://www.polarcloud.com/tomato">Tomato</a> firmware, which enables wireless client mode, to connect to the network:</p>
<div id="attachment_493" class="wp-caption aligncenter" style="width: 510px"><a href="http://blog.aptivate.org/2010/06/08/simulating-low-bandwidth-publishers-for-development/throttler/" rel="attachment wp-att-493"><img src="http://blog.aptivate.org/wp-content/uploads/2010/06/throttler-500x328.png" alt="WRT-54GL connected to FreeBSD throttler connected to network switch connected to client laptops" title="Throttler Network Diagram" width="500" height="328" class="size-large wp-image-493" /></a><p class="wp-caption-text">Throttler Network Diagram</p></div>
<p>And this is what it looked like in the room. Notice the essential coffee and cupcake, without which the system mysteriously failed to work:</p>
<div id="attachment_503" class="wp-caption aligncenter" style="width: 509px"><a href="http://blog.aptivate.org/2010/06/08/simulating-low-bandwidth-publishers-for-development/server-closeup/" rel="attachment wp-att-503"><img src="http://blog.aptivate.org/wp-content/uploads/2010/06/server-closeup-499x408.jpg" alt="FreeBSD server, wireless router and a laptop" title="Network Close Up" width="499" height="408" class="size-large wp-image-503" /></a><p class="wp-caption-text">Network Close Up</p></div>
<p>We configured the FreeBSD box to bring up the bridge automatically at boot time, and to load a set of <em>ipfw</em> firewall rules to enable <em>dummynet</em>, the traffic shaper. On this box, the ethernet interfaces are called <em>em0</em> and <em>rl0</em>, so we added the following lines to <em>/etc/rc.conf</em>:</p>
<pre>
ifconfig_em0="up"
ifconfig_rl0="up"
cloned_interfaces="bridge0"
ifconfig_bridge0="addm em0 addm rl0 up dhcp"

firewall_enable="YES"
firewall_type="/etc/ipfw.rules"
dummynet_enable="YES"
</pre>
<p>Then we created <em>/etc/ipfw.rules</em> with the following contents:</p>
<pre>
# with bridge mode, two nics. em0 is wan
add pipe 1 all from any to any out recv em0
add pipe 2 all from any to any out xmit em0
add allow all from any to any
pipe 1 config delay 700ms bw 40Kbit/s mask dst-ip 0x000000ff
pipe 2 config delay 700ms bw 40Kbit/s mask src-ip 0x000000ff
</pre>
<p>This configuration creates two <em>dummynet pipes</em>. Pipe 1 is for traffic received on the external interface (downloads), and pipe 2 is for traffic being sent out of the external interface (uploads). We have to follow this by a rule which allows all other traffic, otherwise local traffic (on the box itself) is denied by default when the firewall is enabled, which breaks local DNS and inbound SSH and makes the box pretty unusable on the console.</p>
<p>Then we configure both pipes to allocate 40 Kbps (kilobits per second) for each individual IP address in the private subnet (allocated by the DHCP server on the Tomato router) and a 700 ms delay in each direction, which gives a 1400 ms round trip time. This is somewhat higher than the expected 600 ms round trip for a connection by geostationary satellite.</p>
<p>The end result is that each user connects a laptop to the switch behind the box, gets an IP address from the DHCP server on the router, is NATted by the router onto the public network, and is able to browse the Internet with a connection of 40 kbps upload and download. If you remove the FreeBSD box, by connecting the switch directly to the router, you can access the public network at full speed.</p>
<p>One issue was that the public network used a captive portal, which we had to log into. We didn&#8217;t want each client on our network to have to log in separately, so we enabled NAT on the router, and in wireless client mode, all the NATted clients get the MAC address of the router, so the public network thinks that they&#8217;re all the same PC and doesn&#8217;t ask them to log in again.</p>
<h3>Why We Did it</h3>
<p>We think that members of universities and research institutions need to be able to join and participate in the global research community as equals, in order to play their part in assisting development in their home countries.</p>
<p>Programmes such as <a href="http://www.inasp.info/file/5f65fc9017860338882881402dc594e4/perii.html">PERii</a>, <a href="http://www.who.int/hinari/">HINARI</a> and <a href="http://www.aginternetwork.org/">AGORA</a> negotiate free or discounted online access to these journals for universities in developing countries. But the users still need to get online and access the content.</p>
<p>Online publishing for Western markets is usually designed for users with fast Internet connections, which Western universities have. But in other regions, universities often can&#8217;t afford fast connections, and this makes it very difficult for them to access these journals online.</p>
<p>Publishers for Development is bringing international publishers together who are interested in finding out how they might contribute to discourse and action around developing country access, encourage publication from developing country researchers and understand the diversity within research cultures/communities and the challenges these present.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aptivate.org/2010/06/08/simulating-low-bandwidth-publishers-for-development/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Writing Database Migrations</title>
		<link>http://blog.aptivate.org/2010/03/30/writing-database-migrations/</link>
		<comments>http://blog.aptivate.org/2010/03/30/writing-database-migrations/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 13:07:37 +0000</pubDate>
		<dc:creator>chrisw</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Engineer's Log]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[vcs]]></category>

		<guid isPermaLink="false">http://blog.aptivate.org/?p=387</guid>
		<description><![CDATA[Describes how to develop and implement schema and data changes in Java applications backed by SQL databases, using version control and Migrate4J.]]></description>
			<content:encoded><![CDATA[<p>As part of our work on <a href="http://www.logcluster.org/tools/cargo-tracking/rita">RITA</a>, we will need to make schema changes (such as creating tables and adding columns) to live production databases during software upgrades without losing data. Here I will show how <strong>migrations</strong> can be used to implement these changes. Although aimed at <a href="http://migrate4j.sourceforge.net/">Migrate4J</a> users, some of this applies to <a href="http://www.oracle.com/technology/pub/articles/kern-rails-migrations.html">Rails Migrations</a> as well.</p>
<p>We use Migrate4J to implement database migrations in this Java application. This requires us to write Java code to migrate up to, and down from, each specific database version, by making the required database changes: adding tables and fields, changing field names and types, and modifying data.</p>
<p>However, in our team the database designer is not the person writing these migrations. The designer is working on his copy of the database design, keeping in mind backwards compatibility with the <a href="http://www.logcluster.org/tools/cargo-tracking/lctt">LCTT</a> Access database, and giving me Postgres schema dumps. I have to compare these dumps to identify what has changed, and write the migration code.</p>
<h3><a name="comparing">What Changed?</a></h3>
<p>First of all, how does one compare dumps? I found Subversion and Diff to be very helpful. We keep the currently-implemented schema checked into Subversion <a href="http://rita.wfplogistics.org/trac/browser/rita/doc/master-schema-from-aaron.sql">here</a> as a Postgres dump. When I receive a new one, I replace this file, but don&#8217;t immediately check it in. I can use the <code>svn diff</code> command, or the <a href="http://subclipse.tigris.org/">Subclipse</a> plugin&#8217;s Compare With feature, to see all the changes since the last revision.</p>
<p>Unfortunately Postgres dumps contain some lines that change every time and which aren&#8217;t helpful to me, so after I update the dump, I run a command to remove them:</p>
<pre>sed -i.orig -e '/^-- TOC entry/d' -e '/^-- Dependencies:/d' master-schema-from-aaron.sql</pre>
<p>And then show the differences:</p>
<pre>svn diff --diff-cmd=diff -x "-u -F TABLE" master-schema-from-aaron.sql &gt; master-schema-from-aaron.diff</pre>
<p>which produces a file that I can load into a syntax highlighting editor (I often pipe it into <code>less</code> instead), and which looks like this:</p>
<pre>@@ -554,7 +596,7 @@ -- Name: bundle_type_group; Type: TABLE;
 CREATE TABLE bundle_type_group (
     id integer NOT NULL,
     description character varying(255) NOT NULL,
-    is_qty_allowed smallint,
+    is_qty_allowed smallint NOT NULL,
     record_version bigint NOT NULL,
     is_deleted smallint NOT NULL
 );</pre>
<p>This is an extract from a <a href="http://en.wikipedia.org/wiki/Diff#Unified_format">unified diff</a>. The first line, starting with <code>@@</code>, is a header that begins a new section: a block of changed lines, also called a <em>changed hunk</em> or <em>chunk</em>. It includes line numbers from the old and new dump files. It shows three lines of unchanged context above and below the lines that changed.</p>
<p>In this case the line <code>CREATE TABLE bundle_type_group</code> identifies the table being modified, but sometimes the context may not be enough. The last line containing the word <code>TABLE</code> is shown in the header, and normally this helps to identify the table as well.</p>
<p>So this section represents a change to the <code>bundle_type_group</code> table. What changed? A line has been deleted from the dump, and a line has been added. The deleted line is prefixed with <code>-</code> (minus) in the difference file, and the added line is prefixed with <code>+</code> (plus). These lines represent columns in the table.</p>
<p>In this case, the column removed and the column added are both called <code>is_qty_allowed</code>. Because the name is the same, but the types are different, this almost certainly represents a type change to an existing column. If the names were different but the types were the same, it probably represents a renamed column, and if the names and types both differ, it&#8217;s probably a deletion of one column and creation of another, discarding the old contents of the column.</p>
<p>It&#8217;s worth discussing any unclear changes with the database administrator to be sure exactly what needs to be done. Sometimes there will be data-only migration changes that don&#8217;t appear in the schema at all. For example you might decide one day that all people currently called <em>John</em> in the database should now be called <em>Jean</em>, or you might need to add a row to a system table. These can also be done with Migrate4J, but they are not structural (schema) changes.</p>
<h3><a name="migration">Creating a New Migration</a></h3>
<p>Assuming that you already have migrations <a href="http://migrate4j.sourceforge.net/#configuring">configured</a> in your application, you will have a migration package, where all the classes are named Migration_<strong>number</strong>. In our case, the migration package is <a href="http://rita.wfplogistics.org/trac/browser/rita/src/org/wfp/rita/db/migrations">org.wfp.rita.db.migrations</a>. Identify the next migration number in this package, which is usually one higher than the highest <strong>number</strong> present. Create a class in the package with this name, using this template:</p>
<pre>package org.wfp.rita.db.migrations;

/* cleaner sources: */
import static com.eroi.migrate.Execute.*;
import static com.eroi.migrate.Define.*;

public class Migration_2 implements Migration
{
    public void up()
    {
    }

    public void down()
    {
    }
}</pre>
<p>Now you can write code to implement the database changes (both schema and data) that you discovered earlier. Each new change is part of an <strong>upward migration</strong>, and the code that implements it should go into the <code>up</code> method.</p>
<p>It&#8217;s important to be able to reverse changes as well. If a schema update fails, you may want to back down to a previous schema, fix the problem that caused it to fail, and try to update again. The code to reverse the change, which is called a <strong>downward migration</strong>, goes into the <code>down()</code> method.</p>
<p>Note that most migrations lose data in either the forward or the reverse direction (up or down respectively), so you would be well advised to make an automated backup of the database before applying any migrations, in addition to your standard database backup procedures.</p>
<h3><a name="creating">Creating Tables</a></h3>
<p>The <code>Execute.createTable()</code> method takes the table name, and an array of Columns. You can create a new <code>Column</code> with one of these constructors:</p>
<ul>
<li>new Column(String columnName, int columnType)</li>
<li>new Column(String columnName,<br />
int columnType,<br />
int length,<br />
boolean primaryKey,<br />
boolean nullable,<br />
Object defaultValue,<br />
boolean autoincrement)</li>
</ul>
<dl>
<dt>columnType</dt>
<dd>The type of the column, from <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Types.html">java.sql.Types</a>, e.g. Types.INTEGER, Types.FLOAT, Types.VARCHAR.</dd>
<dt>length</dt>
<dd>The length of CHAR and VARCHAR columns. The length of all other column types, particularly DECIMAL, must be specified in another way, see below.</p>
</dd>
<dt>primaryKey</dt>
<dd>True if this column should be part of the primary key, or false otherwise (the default). You can have any number of columns in the primary key, and RITA uses composite primary keys extensively.</dd>
<dt>nullable</dt>
<dd>True if this column should be allowed to contain NULL values, and false otherwise.</dd>
<dt>defaultValue</dt>
<dd>The default value for new rows. If you set this to null, and the column is not nullable, then a value must be supplied for each record inserted.</dd>
<dt>autoincrement</dt>
<dd>True if the column should contain automatically-assigned numbers, using the AUTO_INCREMENT attribute in MySQL, or IDENTITY columns or sequences on databases that support them.</dd>
</dl>
<p>To create a new table called <code>persons</code>, with three columns:</p>
<dl>
<dt><code>ID</code></dt>
<dd>an automatically-assigned integer primary key</dd>
<dt><code>fish</code></dt>
<dd>a float</dd>
<dt><code>rope</code></dt>
<dd>a string, 40 characters long, not nullable, defaulting to <code>nylon</code></dd>
</dl>
<p>we could use the following code in the <code>up</code> migration:</p>
<pre>Execute.createTable(new Table("persons", new Column[]{
    new Column("id", Types.INTEGER, -1, true, false, null, true),
    new Column("fish", Types.FLOAT),
    new Column("rope", Types.VARCHAR, 40, false, false, "nylon", false)
}));</pre>
<p>Unfortunately this syntax doesn&#8217;t allow specifying unique keys, indexes, foreign keys, and precision and scale of decimal columns when the table is created. There is another, shorter syntax which allows specifying the precision and scale:</p>
<pre>createTable(table("persons",
    column("id", INTEGER, notnull(), primarykey()),
    column("fish", NUMERIC, precision(8), scale(5)),
    column("rope", VARCHAR, length(40), notnull(), defaultValue("nylon")),
    ));</pre>
<p>If that still seems like too much work, and you have a database dump of your new schema, have a look at <a href="#generating">generating from Postgres dumps</a> below.</p>
<p>The reverse, which you would normally put into the <code>down()</code> method, is simply to <a href="#dropping">drop the table</a>.</p>
<h3><a name="dropping">Dropping Tables</a></h3>
<p>Dropping a table is as simple as:</p>
<pre>Execute.dropTable("persons");</pre>
<p>Note that all data in the table will be lost. To recreate the empty table structure in the reverse migration, just <a href="#creating">create it again</a>.</p>
<h3><a name="adding">Adding Columns</a></h3>
<p>To add an <code>INTEGER</code> column called <code>hairs</code> to the <code>persons</code> table, you would add the following code to the <code>up()</code> method:</p>
<pre>Execute.addColumn(new Column("hairs", Types.INTEGER), "persons");</pre>
<p>The addColumn method takes a <code>Column</code> object, which you can create using either of the methods <code>new Column(...)</code> or <code>column(...)</code> described under <a href="#creating">creating tables</a> above. The <code>column(...)</code> method is shorter, and the only way to specify the scale and precision of decimal (NUMERIC) columns.</p>
<p>If the change is adding a column, the reverse is to remove the column again, which belongs in the <code>down()</code> method:</p>
<pre>Execute.dropColumn("hairs", "persons");</pre>
<p>Note that your newly added column will contain default values for all records. If you know what the values should be, or can recreate them using a query, you could <a href="queries">execute SQL queries</a> to populate it. Also note that if you migrate down past this version, the column will be dropped and all data contained in it will be lost.</p>
<h3><a name="removing">Removing Columns</a></h3>
<p>This is the exact opposite of <a href="#adding">Adding Columns</a> above. Put the <code>dropColumn()</code> in the <code>up</code> migration, and the <code>addColumn()</code> in the <code>down</code> migration.</p>
<p>Note that migrating down past this migration will not restore the data that was in your column before. If you know what it was, or can recreate it using a query, you could reinsert it using <a href="queries">SQL queries</a>.</p>
<h3><a name="renaming">Renaming Columns</a></h3>
<p>Changing the name of a column does not lose any data. For example, we can rename the column called <code>fish</code> to <code>hats</code> in the <code>persons</code> table, and hope that people don&#8217;t try to wear their pet haddock:</p>
<pre>Execute.renameColumn("fish", "hats", "persons");</pre>
<p>The <code>down()</code> migration trivially renames the column from the new name back to the old name.</p>
<h3><a name="indexes">Indexes</a></h3>
<p>You can add indexes to columns, both to improve search performance, and to enforce the uniqueness of values in certain columns. The <code>addIndex()</code> method takes an <code>Index</code> object, which you can either create by calling its constructor, or more concisely by calling <code>index()</code> or <code>uniqueIndex()</code>. Both take the same parameters:</p>
<pre>index(String indexName, String tableName, String... columnNames)</pre>
<p><code>indexName</code> is the name of the index, which can be <code>null</code> to generate a name automatically. However, such indexes cannot reliably be removed, so I recommend always naming your indexes explicitly. <code>tableName</code> is the name of the table that the index will be applied to, and <code>columnNames</code> is a list of names of columns that will be included in the index.</p>
<p>For example, to uniquely index the <code>fish</code> and <code>rope</code> columns in the <code>persons</code> table:</p>
<pre>Execute.addIndex(uniqueIndex("uk_fish_rope", "persons", "fish", "rope"));</pre>
<p>You can drop an index, for example for downward migration, using the index name and the table name:</p>
<pre>Execute.dropIndex("uk_fish_rope", "persons");</pre>
<h3><a name="foreign_keys">Foreign Keys</a></h3>
<p>Foreign keys link one table to another, to enforce referential integrity between tables. You can create them with <code>Execute.addForeignKey()</code>, which takes a <code>ForeignKey</code> object. There are four ways to construct a ForeignKey:</p>
<ul>
<li>ForeignKey(String name, String parentTable, String <strong>parentColumn</strong>, String childTable, String <strong>childColumn</strong>)</li>
<li>ForeignKey(String name, String parentTable, String parentColumn, String childTable, String childColumn, <strong>CascadeRule deleteRule, CascadeRule updateRule</strong>)</li>
<li>ForeignKey(String name, String parentTable, String[] <strong>parentColumns</strong>, String childTable, String[] <strong>childColumns</strong>)</li>
<li>ForeignKey(String name, String parentTable, String[] parentColumns, String childTable, String[] childColumns, <strong>CascadeRule cascadeDeleteRule, CascadeRule cascadeUpdateRule</strong>)</li>
</ul>
<p>As you can see, these are just the four combinations of whether parentColumns and childColumns are single column names or arrays of column names, and whether the cascade rules are specified or not (they default to &#8220;none&#8221; if not supplied).</p>
<p>For example, to force a person&#8217;s <code>fish_id</code> column to point to the ID of a record in the <code>fish</code> table, you could use this:</p>
<pre>Execute.addForeignKey(new ForeignKey("fk_persons_fish", "persons", "fish_id", "fish", "id"));</pre>
<p>You can drop a foreign key, for example for downward migration, using the key name and the child (referenced) table name:</p>
<pre>Execute.dropIndex("fk_persons_fish", "fish");</pre>
<h3><a name="queries">Executing Queries</a></h3>
<p>You can execute any arbitrary SQL statement, for example to insert rows into a newly created table or populate a newly created column:</p>
<pre>Execute.executeStatement(Configure.getConnection(),
    "INSERT INTO users SET name = 'fred', password = 'flintstone'");
Execute.executeStatement(Configure.getConnection(),
    "UPDATE users SET age = 42 WHERE name = 'barney'");</pre>
<p>Although data modification language is much more standard across databases than data definition language, it&#8217;s important to be careful only to use ANSI SQL in such statements if cross-database compatibility is important for your application (or might become important in future).</p>
<h3><a name="generating">Generating Automatically</a></h3>
<p>If you already have a table structure in a database somewhere, for example if you are retrofitting migrations to an existing project, or if you prefer using GUI tools to design databases, and to reduce the risk of errors, you may want to generate the migration code automatically.</p>
<p>I wrote a <a href="http://rita.wfplogistics.org/trac/browser/rita/tools/generate-migration-from-postgres-dump.pl">script</a> to create Migrate4J migrations automatically from Postgres database dumps. It&#8217;s not perfect, it probably only handles the SQL that we actually use, and it&#8217;s not well tested, but it may help you. Just run it with the name of the exported schema dump file as its parameter, and it will generate Java code on the standard output, that you can copy and paste into a Java source file.</p>
<p>If the schema will continue to change, and you want help with creating new table definitions in future, you can save the <a href="http://rita.wfplogistics.org/trac/browser/rita/doc/master-schema-from-aaron.migrate">generated output</a> to a file under version control. When you need to generate migration code for a new schema, just overwrite that file, and use <code>svn diff</code> as before to show the differences. They will now be expressed in Java code, which is easier to copy and paste into a new migration.</p>
<h3><a name="generating">Applying Manually</a></h3>
<p>In Eclipse, with a <code>migrate4j.properties</code> file on your classpath, you should be able to open the Migrate4J JAR file in Eclipse, expand the <code>com.eroi.migrate</code> package, right-click on <code>Engine</code> and choose &#8220;Run As/Java Application&#8221;.</p>
<h3><a name="generating">Applying Programmatically</a></h3>
<p>As we are using Hibernate, we get a database connection using its Work class, and use it to invoke the migration engine:</p>
<pre>
// set up Migration schema and run all migrations
m_Session.doWork(new Work()
{
    public void execute(Connection connection) throws SQLException
    {
        Configure.configure(connection, "org.wfp.rita.db.migrations");
        Engine.migrate();
    }
});
</pre>
<h3><a name="controlling">Version Control</a></h3>
<p>If I don&#8217;t check in the master schema changes immediately, when does it happen? I try to wait until I have all the schema changes implemented in Hibernate annotations and migrations, and run as many tests as I feel the need to run, before checking everything in.</p>
<p>This ensures that the documentation checked in is consistent with the code at that point in time, that I can see the changes to the SQL dump, the Hibernate mappings and the migrations for a single schema update and compare them side-by-side, and reduces the risk of checking in broken code.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aptivate.org/2010/03/30/writing-database-migrations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>R&amp;D: Robots and Development</title>
		<link>http://blog.aptivate.org/2010/03/16/rd-robots-and-development/</link>
		<comments>http://blog.aptivate.org/2010/03/16/rd-robots-and-development/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 19:13:28 +0000</pubDate>
		<dc:creator>alan</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Robotics]]></category>
		<category><![CDATA[participation]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[BotBuilder]]></category>
		<category><![CDATA[BoxBot]]></category>
		<category><![CDATA[BrightonRobot]]></category>
		<category><![CDATA[DrawBot]]></category>
		<category><![CDATA[Samfya Resource Centre]]></category>

		<guid isPermaLink="false">http://blog.aptivate.org/?p=399</guid>
		<description><![CDATA[The Samfya Resource Centre is a telecentre (Internet cafe) run by young women in Samfya, Zambia for other local young women - a component of Camfed's "CAMA" network. As part of our ongoing support for the Samfya Resource Centre, we have sent them robots. ]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://news.bbc.co.uk/1/hi/in_depth/8302294.stm"><strong>Samfya Resource Centre</strong></a> is a telecentre (Internet cafe) run by young women in Samfya, Zambia for other local young women &#8211; a component of<a href="http://uk.camfed.org/site/PageServer?pagename=what_success"> Camfed</a>&#8217;s &#8220;CAMA&#8221; network. As part of our ongoing support for the <a href="http://www.sciencemedianetwork.org/wiki/Samfya">Samfya Resource Centre</a>, we have sent them <strong>robots</strong>.</p>
<div id="attachment_400" class="wp-caption alignright" style="width: 330px"><a href="http://blog.aptivate.org/wp-content/uploads/2010/03/100313_114641-web.jpg"><img class="size-full wp-image-400" title="100313_114641-web" src="http://blog.aptivate.org/wp-content/uploads/2010/03/100313_114641-web.jpg" alt="drawbot" width="320" height="240" /></a><p class="wp-caption-text">(c) Fatuma Iseje</p></div>
<p>Why robots? As a child I grew up programming the<strong> <a href="http://en.wikipedia.org/wiki/ZX81">Sinclair ZX81</a></strong>. A small computer about the size of a book, with a touch-(in)sensitive membrane keyboard and <strong>1kB</strong> of memory. With computers we spend long hours staring at the screen interacting with a virtual world made of <strong>intangible</strong> pixels. I remember being constantly frustrated that my computer couldn&#8217;t do anything in the <strong>REAL</strong> world. It couldn&#8217;t turn lights on and off, it couldn&#8217;t move and back then it couldn&#8217;t even makes noises. In fact I killed the poor thing when I dropped a soldering iron through the <a href="http://www.cpu-world.com/CPUs/Z80/L_NEC-D780C-1.jpg">CPU</a> while trying to interface it to my physical world.</p>
<p>It&#8217;s all different now. With the advent of devices like the <a href="http://www.arduino.cc/"><strong>Arduino</strong></a> it&#8217;s now easy and cheap to get the computer to reach out into our world. And we can reach into its world. Not only does an <strong>Arduino</strong> let us physically interact with the computer it can also be <strong>automonous</strong>. We can <a href="http://www.instructables.com/tag/?q=arduino&amp;limit%3Atype%3Aid=on&amp;type%3Aid=on&amp;type%3Auser=on&amp;type%3Acomment=on&amp;type%3Agroup=on&amp;type%3AforumTopic=on&amp;type%3AforumTopic=on&amp;sort=none">make things</a> that interact with us without needing the computer attached to the other end of its USB umbilical cord.</p>
<p>For those that haven&#8217;t come across it yet, an Arduino is a simple micro-controller board. OK&#8230; what&#8217;s so amazing about that, there&#8217;s been micro-controller boards around for decades? Well, a few things. Firstly it has a <strong>USB</strong> port so you can easily connect it to your computer. It has its own simple <strong>programming environment</strong> using a variant of the C programming language. So it&#8217;s not dumbed down at all &#8211; no visual programming environment or anything like that. And critically there is a <a href="http://www.arduino.cc/playground/"><strong>large on-line community</strong></a> eager to share and support people who do not come from a technical background. Its design is open source, it&#8217;s cheap (£20) and you can find even <a href="http://www.botbuilder.co.uk/store/index.php?main_page=product_info&amp;cPath=4_8&amp;products_id=58">cheaper clones</a>.</p>
<p>This exploding field called &#8220;<a href="http://books.google.co.uk/books?id=STXR9vCXs5YC&amp;printsec=frontcover&amp;dq=programming+interactivity&amp;source=bl&amp;ots=kV-YNQM47b&amp;sig=f1WxkJqqitb6rgD0NOssgZZHo-c&amp;hl=en&amp;ei=-9CfS52MCJS7jAea6KjqDQ&amp;sa=X&amp;oi=book_result&amp;ct=result&amp;resnum=4&amp;ved=0CBcQ6AEwAw#v=onepage&amp;q=&amp;f=false">Physical Computing</a>&#8221; is making computing more fun, more compelling and also sometimes more useful.</p>
<p>Ok robots might be fun, but why send them to <strong>Zambia</strong>?</p>
<p>The computer used to be like a calculator on steroids. It could &#8220;<strong>compute</strong>&#8221; things. If you knew a bit about <strong>SIN</strong> or <strong>COS</strong> you could make it <a href="http://wiki.answers.com/Q/How_do_you_draw_a_circle_using_C_or_C_plus_plus_without_using_the_built_in_function">draw a circle</a>. Or calculate a volume. Now, although computers are <strong>enormously</strong> more powerful than the Sinclair ZX81, most of us use them like some mash-up of a <strong>TV</strong> and a <strong>phone</strong>. They give us access to information and lets us communicate. These are important and useful functions. But I worry most of us are in danger of treating our computers like new cars &#8211; like devices with &#8220;<em><strong>no user serviceable parts inside</strong></em>&#8220;.  Instead of seeing them as tools that we can fix, modify, improve, re-invent and tailor to our needs.</p>
<p>It&#8217;s more than that. Computers aren&#8217;t just useful for the stuff they do. I believe that programming computers, tinkering with them, making electronic circuits and building robots builds <strong>highly transferable skills</strong>. Critical thinking, logical and abstract reasoning and problem solving. In addition, programming an Arduino makes you a dab hand at <strong>searching</strong> the Internet.</p>
<p>I got into robots at <a href="http://www.buildbrighton.com/wiki/Welcome_to_BuildBrighton">BuildBrighton</a> /  <a href="http://www.buildbrighton.com/wiki/Welcome_to_BuildBrighton">BrightonRobot</a> &#8211; the Brighton hacker-spaces based out of <a href="http://theskiff.org">The Skiff</a> &#8211; and in particular through <a href="http://www.botbuilder.co.uk/store/">Steve Carpenter&#8217;s amazing kits</a>.</p>
<div id="attachment_401" class="wp-caption alignright" style="width: 191px"><a href="http://blog.aptivate.org/wp-content/uploads/2010/03/100313_105931-web.jpg"><img class="size-full wp-image-401" title="100313_105931-web" src="http://blog.aptivate.org/wp-content/uploads/2010/03/100313_105931-web.jpg" alt="" width="181" height="240" /></a><p class="wp-caption-text">Eva with the Drawbot - (c) Fatuma Iseje</p></div>
<p>As an introduction to robotics, we&#8217;ve used the &#8220;<strong>DrawBot</strong>&#8221; packaged up by Steve with excellent instructions. How complicated and expensive do you think an autonomous drawing robot would be? How about 6 components that require no soldering costing about £3?</p>
<p>Steve has also designed a great robot kit based around the Arduino &#8211; the <strong>BoxBot</strong>. The kit is designed using the <a href=" http://www.instructables.com/id/How_to_Make_Anything_Using_Acrylic_and_Machine_Sc/">Interlocking T-Bolt Construction</a> method, a cost-effective technique for low volume manufacture. With servos and everything you need minus the Arduino, the kit&#8217;s about £60. It&#8217;s a very flexible kit, you can bolt sensors or motors all over it &#8211; but this is not Lego. You need to drill holes in it.</p>
<p>Reading the <a href="http://opensource.com/education/10/2/introducing-computing-hands-secondary-education">educational posts</a> about robotics I can see that from a teacher&#8217;s point of view an Arduino and the BoxBot may not be ideal. They don&#8217;t neatly fit into lesson plans. They don&#8217;t just leap into life in a way that keeps a lesson of 30+ students moving along. They take a bit more application and research to use. But unlike Lego, Meccano and other modular systems, they blur the distinction between the kit and the rest of the world. Once you&#8217;re empowered to drill holes and wire up your BoxBot you find you&#8217;re up for drilling holes and wiring up anything.</p>
<p>Using robots in this context is an experiment for us. We don&#8217;t know how it will go. But it&#8217;s an experiment the young women of the <strong>Samfya Resource Centre</strong> are excited about.</p>
<p>We&#8217;ll keep you posted on the progress of our latest bit of <strong>R&amp;D</strong>.</p>
<p>&#8220;<strong>Hi</strong>&#8221; and &#8220;<strong>Mulishani</strong>&#8221; to Bridget, Everlyn, Fatuma, Mary, Mildred and Penelope at the SRC from the Aptivate gang!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aptivate.org/2010/03/16/rd-robots-and-development/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Getting Ready for Crisis Camp London &#8211; Day 2</title>
		<link>http://blog.aptivate.org/2010/01/28/getting-ready-for-crisis-camp-london-day-2/</link>
		<comments>http://blog.aptivate.org/2010/01/28/getting-ready-for-crisis-camp-london-day-2/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 23:48:49 +0000</pubDate>
		<dc:creator>alan</dc:creator>
				<category><![CDATA[Crisis Camp]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[participation]]></category>
		<category><![CDATA[#crisiscampLDN]]></category>

		<guid isPermaLink="false">http://blog.aptivate.org/?p=340</guid>
		<description><![CDATA[We're getting ready for the second Crisis Camp London day, this Saturday, at the London Knowledge Lab.

Considering how quickly last Saturday was put together we had a great turn out. We're hoping for, and expecting, an even larger turn out this time.

If you are technical (eg. an IT project manager, a coder, a user experience person) or have relief experience and want to help Crisis Camp London support Haiti, then please come along. More details and a link to the registration inside...]]></description>
			<content:encoded><![CDATA[<div id="attachment_342" class="wp-caption aligncenter" style="width: 230px"><a href="http://blog.aptivate.org/wp-content/uploads/2010/01/R0022973_7_blog.png"><img class="size-full wp-image-342" title="Crisis Camp London" src="http://blog.aptivate.org/wp-content/uploads/2010/01/R0022973_7_blog.png" alt="Crisis Camp London" width="220" height="165" /></a><p class="wp-caption-text">Crisis Camp London</p></div>
<p>We&#8217;re getting ready for the <strong>second</strong> <em><strong>Crisis Camp London</strong></em> day, this Saturday, at the London Knowledge Lab.</p>
<p>Considering how quickly <a href="http://blog.aptivate.org/2010/01/25/video-introducing-crisis-camp-london/">last Saturday </a>was put together we had a great turn out. We&#8217;re hoping for, and expecting, an even larger turn out this time.</p>
<p>We&#8217;re getting out all the laptops, network gear, and spare projectors we can find. We&#8217;ve got enough flip-charts to paper the Albert Hall. I even heard that Domino&#8217;s were considering sponsoring the pizza again &#8211; and with added vegan options too. Many thanks to them!</p>
<p>We&#8217;re on conference calls to the <a href="http://crisiscommons.org/">US Crisis Camps and projects</a>. We&#8217;re part of a strong team looking after the organisation, infrastructure and facilitation of the London event.</p>
<p>It really is quite something the speed with which this is coming together and the level of interest and motivation. This looks set to become an important movement.</p>
<p>If you are technical (eg. an IT project manager, a coder, a user experience person) or have relief experience and want to help Crisis Camp London support Haiti, then please come along.</p>
<ul>
<li><a href="http://wiki.crisiscommons.org/wiki/Crisis_Camp_London">find out more</a></li>
<li><a href="http://crisiscamphaiti-london.eventbrite.com/">register</a></li>
</ul>
<p>You can also help by printing out and displaying the <a href="http://blog.aptivate.org/wp-content/uploads/2010/01/Crisis_Camp_A4.pdf">Crisis Camp London Poster</a></p>
<p><em>#CrisisCampLDN</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aptivate.org/2010/01/28/getting-ready-for-crisis-camp-london-day-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>What&#8217;s the difference between Open Spaces and BarCamps?</title>
		<link>http://blog.aptivate.org/2009/12/22/whats-the-difference-between-open-spaces-and-barcamps/</link>
		<comments>http://blog.aptivate.org/2009/12/22/whats-the-difference-between-open-spaces-and-barcamps/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 13:55:00 +0000</pubDate>
		<dc:creator>alan</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[facilitation]]></category>
		<category><![CDATA[BarCamp]]></category>
		<category><![CDATA[learning]]></category>
		<category><![CDATA[ludic]]></category>
		<category><![CDATA[Open Space]]></category>
		<category><![CDATA[workshop]]></category>

		<guid isPermaLink="false">http://blog.aptivate.org/?p=225</guid>
		<description><![CDATA[Having one foot in the world of IT and another in facilitation I keep getting asked:

"What's the difference between Open Spaces and BarCamps?"

Here's how I described it to a good facilitator friend of mine (Julian from DecisionLab)...]]></description>
			<content:encoded><![CDATA[<p>Having one foot in the world of <strong>IT</strong> and another in <strong>facilitation</strong> I keep getting asked</p>
<p style="text-align: center;"><strong><em>&#8220;What&#8217;s the difference between Open Spaces and BarCamps?&#8221;</em></strong></p>
<p>Here&#8217;s how I described it to a good facilitator friend of mine (Julian from<a title="DecisonLab" href="http://decisionlab.org.uk/"> DecisionLab</a>)&#8230;</p>
<blockquote><p>&#8220;I suppose a <strong>BarCamp</strong> isn&#8217;t exactly like a pure <strong>Open</strong> <strong>Space</strong>. It&#8217;s got it&#8217;s own nuance.</p>
<p>For instance it&#8217;s generally not well regarded to plan BarCamps too far in advance. For no real reason in particular, it&#8217;s just not the BarCamp way.</p>
<p>People do prepare some stuff to take with them to a BarCamp knowing they will have an opportunity to talk about it &#8211; but they make no commitment until the day so they can change it or not give it at all.</p>
<p>Having people declare before hand makes it feel much more like a traditional conference and I think will discourage others from joining in on the spur of the moment.</p>
<p>One thing to remember about BarCamps, the big difference between BarCamps and Open Spaces is the <strong><em>ludic</em></strong> nature of BarCamps &#8211; they&#8217;re supposed to be fun and don&#8217;t have a particular outcome &#8211; they&#8217;re more like Popular Education rather than group decision making.</p>
<p>I think of it like this. Imagine you&#8217;re 11 years old and you and a gang of your friends are mad keen on <strong><em>technical</em> lego</strong>. You&#8217;ve arranged one weekend to have a sleep-over with a lego theme. You&#8217;re parents have sorted out <strong>pizza</strong> and ice cream for everyone. Everybody brings lego with them and you take the half finished robot you&#8217;re working on. During the lego-fest the gang comes up with an idea &#8211; wouldn&#8217;t it be cool if we put all our lego together and see if we can make a bridge over the stair well.</p>
<p><strong>THAT</strong> is a BarCamp. You might prepare something because it&#8217;s fun. But you&#8217;re just going along to <strong>learn</strong>, be <strong>inspired</strong>, get <strong>enthusiastic</strong>, hang out with some cool people and have a bit of a laugh.</p>
<p>The idea of getting people to coordinate their talks so they don&#8217;t have duplicates is I think wrong. You should have duplicates. If that&#8217;s what people want to talk about &#8211; duplicates give more opportunities for people to hear about it.&#8221;</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.aptivate.org/2009/12/22/whats-the-difference-between-open-spaces-and-barcamps/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
