<?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>fifo.nl &#187; Habbie</title>
	<atom:link href="http://fifo.nl/author/habbie/feed" rel="self" type="application/rss+xml" />
	<link>http://fifo.nl</link>
	<description>the #fifo aggregate blog</description>
	<lastBuildDate>Fri, 03 Sep 2010 22:07:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>cron considered harmful</title>
		<link>http://7bits.nl/blog/2010/06/22/cron-considered-harmful</link>
		<comments>http://7bits.nl/blog/2010/06/22/cron-considered-harmful#comments</comments>
		<pubDate>Tue, 22 Jun 2010 07:19:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[On numerous occasions I have lamented both the design and the typical usage of cron to friends and other geeks. My main gripes:

 jobs are not protected against running concurrently (design issue)
 intervals are fixed (design issue)
 people tend to sch...]]></description>
			<content:encoded><![CDATA[On numerous occasions I have lamented both the design and the typical usage of cron to friends and other geeks. My main gripes:
<ul>
<li> jobs are not protected against running concurrently (design issue)
</li><li> intervals are fixed (design issue)
</li><li> people tend to schedule the same job at the same time on whole clusters of machines (typical usage issue)
</li></ul>

The first issue can be fixed with tools like <code>lockfile</code> and <code>setlock</code> — a lot of red tape for something that should be a default feature.
<p>
The second and third issue are closely related in that both cause undesirable load spikes because many things happen at the same time, either because of intervals phasing up or because of similar jobs running on a bunch of machines at the same time, perhaps hammering the network.
</p><p>
A specific pet peeve is <a href="http://mail.python.org/pipermail/mailman-developers/2004-April/016708.html">Mailman Reminder Day</a>. Firstly, I just don’t see the point; if my address is on a mailing list and that list is practically dead, I <em>just don’t care</em>. Secondly, it means every first of the month
I have tens of reminders that I just delete. Some of these lists are busy — for those, the reminder is a minor nuisance. But many lists are extremely quiet (think software release announcements) and for some of these lists, the reminders are over 50% of the total mail volume. It’s so wasteful. Also, I can’t help but think that all those reminders being sent out at the same time (well, divided over 24 hours because of time zone differences) cannot be good for the mail ecosystem as a whole.
</p><p>
For issues two and three, Colm MacCárthaigh wrote a few great posts detailing why cron is bad, and showcasing one potential solution to the issues at hand. I suggest reading these posts fully, they are very insightful:
</p><ul>
<li><a href="http://www.stdlib.net/~colmmacc/2009/09/14/period-pain/">Period Pain</a>
</li><li><a href="http://www.stdlib.net/~colmmacc/2009/09/27/period-pain-part-2/">Period Pain part 2</a>
</li><li><a href="http://www.stdlib.net/~colmmacc/2009/11/26/period-pain-3/">Period Pain 3</a>
</li></ul>

This post was inspired by my pet peeve about Mailman and about jobs running in parallel unintendedly; this post was triggered by <a href="http://instituut.net/">Job Snijders</a> pointing me to <a href="http://berezecki.com/?p=22">another interesting post</a>; Colm’s posts above were referred to in the comments.]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/8742/cron-considered-harmful/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>silly Python unicode mistake</title>
		<link>http://7bits.nl/blog/2010/06/12/silly-python-unicode-mistake</link>
		<comments>http://7bits.nl/blog/2010/06/12/silly-python-unicode-mistake#comments</comments>
		<pubDate>Sat, 12 Jun 2010 07:58:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[For a simple blog-to-twitter posting gateway (source code) I’m relying on the excellent feedparser and twitter modules, and I am trusting them to handle unicode strings without trouble. With most well-written Python modules (and these two are no exce...]]></description>
			<content:encoded><![CDATA[For a simple blog-to-twitter posting gateway (<a href="http://opensource.xlshosting.com/hg/blog2tweet">source code</a>) I’m relying on the excellent <code>feedparser</code> and <code>twitter</code> modules, and I am trusting them to handle unicode strings without trouble. With most well-written Python modules (and these two are no exception!) methods will return unicode strings as they see fit, and other methods will accept these unicode strings and handle all the nitty gritty encoding details for me.
<p>
A simplified version of my workflow would look like this:
</p><div class="syntax"><pre><span class="k">def</span> <span class="nf">post</span><span class="p">(</span><span class="n">entry</span><span class="p">):</span>
  <span class="n">title</span> <span class="o">=</span> <span class="n">entry</span><span class="o">.</span><span class="n">title</span>
  <span class="k">print</span> <span class="s">&quot;posting [</span><span class="si">%s</span><span class="s">]&quot;</span> <span class="o">%</span> <span class="n">title</span>
  <span class="n">api</span><span class="o">.</span><span class="n">PostUpdate</span><span class="p">(</span><span class="n">title</span><span class="p">)</span> <span class="c"># api is a twitter Api object</span>

<span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">config</span><span class="p">[</span><span class="s">&quot;feed&quot;</span><span class="p">])</span>
<span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">):</span>
  <span class="k">if</span> <span class="ow">not</span> <span class="n">e</span><span class="o">.</span><span class="n">id</span> <span class="ow">in</span> <span class="n">seen</span><span class="p">:</span>
    <span class="n">post</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
</pre></div>


This code bombed out with an exception on the first post that had a non-ASCII title. Can you spot why?
<p>
It’s the <code>print</code> statement. All the APIs I’m using have zero trouble with unicode, but print wants
to encode for your terminal and it’ll usually assume that that is ASCII. My ‘debugging’ output actually broke
the program. My workaround is to say <code>title.encode("ascii","replace")</code>
</p><p>
Brend on #python pointed out to me that the issue is not, exactly, <code>print</code>. The issue is interpolating <code>title</code>
into a non-unicode string. Depending on environment, using <code>print</code> on the unicode object might in fact work. For those environments, saying <code>print u"posting [%s]" % title</code> could help. In my case however, I ran into the issue
from cron with no locale set at all, so dumbing the string down to ascii is still the right thing to do.
</p>]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/8262/silly-python-unicode-mistake/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mac desktop Twitter client roundup</title>
		<link>http://7bits.nl/blog/2010/06/11/mac-desktop-twitter-client-roundup</link>
		<comments>http://7bits.nl/blog/2010/06/11/mac-desktop-twitter-client-roundup#comments</comments>
		<pubDate>Fri, 11 Jun 2010 13:10:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[I’ve been a Tweetie 1/Mac user for a long time now, and it has suited my needs well. However, there are minor annoyances. After Twitter acquired Tweetie developer Atebits, posts from Tweetie/Mac started showing up as posted from ‘Twitter for iPhone...]]></description>
			<content:encoded><![CDATA[I’ve been a <a href="http://www.atebits.com/tweetie-mac/">Tweetie 1/Mac</a> user for a long time now, and it has suited my needs well. However, there are minor annoyances. After <a href="http://blog.twitter.com/2010/04/twitter-for-iphone.html">Twitter acquired Tweetie developer Atebits</a>, posts from Tweetie/Mac started showing up as posted from ‘Twitter for iPhone’. Also, Tweetie has semi-excellent keyboard navigation support but it’s too buggy, making me grab my mouse/touchpad in annoyance very frequently. Given the sheer amount of Twitter clients available, I asked my friends on Twitter and Facebook to suggest some options. Here are my biased opinions on the suggestions. I would like to thank all who contributed!

<h2 id="Kiwi">Kiwi</h2>

<a href="http://kiwi-app.net/">Kiwi</a> looks and feels like it really wants to be Tweetie - but it’s nowhere close. Scrolling is jerky and the free version is
much more annoying than the occasional ad in Tweetie.

<h2 id="Echofon">Echofon</h2>

<a href="http://www.echofon.com/">Echofon</a> was recommended to me as ‘very minimal yet complete’ and it is. For single account usage, Echofon is basically on par with Tweetie for usability, including keyboard navigation. However, multiple account support seems hackish - events in one account are very hard to notice when focused on another account. This is one thing Tweetie gets absolutely right.
<p>

If I only had one account to manage, I could seriously consider switching to Echofon.

</p><h2 id="Nambu">Nambu</h2>

<a href="http://www.nambu.com/">Nambu</a> is a bit fuller-featured in the UI department than the clients above, including Tweetie. Keyboard navigation is better than Tweetie (although it lacks some shortcuts) and about as buggy. Like Echofon, single account usage is great, and Nambu has some features I really dig, like thumbnails on twitpic-posts. Multiple account support in Nambu is excellent, with a choice between combining all timelines, and having them separated with use of a sidebar. Enabling the sidebar pops out an interface that resembles a cross between Tweetie and Mail.app, very clean.<p>

If Echofon or Tweetie seem limited or minimal, Nambu is a great choice.
</p><p>
Note that adding an account to Nambu means you suddenly follow two extra accounts (@nambu and the developer). The checkbox to disable this behaviour doesn’t seem to work. Spammy if you ask me.

</p><h2 id="TweetDeck">TweetDeck</h2>

On first startup, <a href="http://www.tweetdeck.com/">TweetDeck</a> is very daunting. It <em>more than</em> fills my 13″ MacBook screen which is too much. I know that TweetDeck is -very- configurable but I did not feel up to the task. Additionally, TweetDeck notifications are not handled via Growl.

<h2 id="Yoono">Yoono</h2>

<a href="http://yoono.com/">Yoono</a>, like TweetDeck, immediately took over my screen with absolutely nothing, asking me to configure my ‘columns’ from scratch. Too much hassle.

<h2 id="Conclusion">Conclusion</h2>

After trying all these clients I went back to Tweetie. It may not be perfect but I’m too used to it. I’ll probably switch to Nambu sometime soon. Both Echofon and Nambu I will recommend to people when asked for Twitter client advice.

Update July 12th: I’ve switched to Nambu and I’m not switching back. Keyboard navigation is excellent (although a bit buggy at times). I do miss Tweetie’s Command-U to look at a specific user, but otherwise Nambu seems superior in many ways. I’ve updated the Nambu review above to account for bugfixes they made since.]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/8250/mac-desktop-twitter-client-roundup/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>a snappy definition</title>
		<link>http://7bits.nl/blog/2010/05/31/a-snappy-definition</link>
		<comments>http://7bits.nl/blog/2010/05/31/a-snappy-definition#comments</comments>
		<pubDate>Mon, 31 May 2010 14:06:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[snappy comeback, n.:

  a witty retort designed to make the audience go ‘oh, SNAP’


Also – sometimes you don’t think of a snappy comeback until hours later. Is there a word for that?]]></description>
			<content:encoded><![CDATA[snappy comeback, n.:
<blockquote>
  a witty retort designed to make the audience go ‘oh, SNAP’
</blockquote>

Also – sometimes you don’t think of a snappy comeback until hours later. Is there a word for that?]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/8046/a-snappy-definition/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unix trivia: echo cat &#124; sed statement</title>
		<link>http://7bits.nl/blog/2010/05/24/unix-trivia%3A-echo-cat-sed-statement</link>
		<comments>http://7bits.nl/blog/2010/05/24/unix-trivia%3A-echo-cat-sed-statement#comments</comments>
		<pubDate>Mon, 24 May 2010 08:48:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[I occasionally run into weird, funny or surprising aspects of Unix and Unix-like Operating Systems. I'll try to post about those regularly because they're fun.

This one popped up on irc a few weeks ago; a google search suggests it's at least 6 months ...]]></description>
			<content:encoded><![CDATA[I occasionally run into weird, funny or surprising aspects of Unix and Unix-like Operating Systems. I'll try to post about those regularly because they're fun.<p>

This one popped up on irc a few weeks ago; a google search suggests it's at least 6 months old. I have been unable to track the original source down.</p><p>

The question is: if you input <code>echo cat | sed statement</code> into your Unix shell, what comes out? Can you predict it? If not, can you try it and then explain it?</p>]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/7921/unix-trivia-echo-cat-sed-statement/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ubuntu 9.10 to 10.04: worst upgrade experience ever.</title>
		<link>http://7bits.nl/blog/2010/05/18/ubuntu-10-04-upgrade-fail</link>
		<comments>http://7bits.nl/blog/2010/05/18/ubuntu-10-04-upgrade-fail#comments</comments>
		<pubDate>Tue, 18 May 2010 22:06:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[I'm used to smooth upgrades of both single packages and full distributions, with Debian and Ubuntu. Not so for this upgrade from 9.10 to 10.04. I'll sum up the failures I encountered and my suggested fixes:

   after upgrading+rebooting, your native IP...]]></description>
			<content:encoded><![CDATA[I'm used to smooth upgrades of both single packages and full distributions, with Debian and Ubuntu. Not so for this upgrade from 9.10 to 10.04. I'll sum up the failures I encountered and my suggested fixes:
<ul>
  <li> after upgrading+rebooting, your native IPv6 is suddenly replaced by a freenet tunnel. Cause: you installed gw6c on 9.10 which came with no configuration; 10.04 updated the configuration to automatically use freenet. Fix: remove gw6c package.</li>
  <li> you're using the excellent dovecot-postfix package, and after the upgrade, no mail comes in. Cause: cmusieve is gone. Fix: change dovecot config to use sieve. </li>
  <li> lighttpd will not start, complaining about port 80. Cause: lighttpd ipv6 is basically broken in 10.04. Known issue, not fixed. Fix: add <code>server.use-ipv6="enable"</code> to lighttpd.conf </li>
  <li> dovecot is not listening on v6 anymore. Cause: the upgrade messed up your listen directives. Fix: add <code>listen = *, [::]</code> to dovecot.conf </li>
</ul>

Extra free tip: get rid of some old kernels, they tend to eat a lot of diskspace with their modules.]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/7922/ubuntu-9-10-to-10-04-worst-upgrade-experience-ever/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Choosing a database for your project</title>
		<link>http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/</link>
		<comments>http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/#comments</comments>
		<pubDate>Tue, 29 Apr 2008 15:36:33 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.openpanel.com/?p=66</guid>
		<description><![CDATA[When you are designing a project with complex storage requirements and some demands on reliability and performance, a few options come to mind.
Even though at OpenPanel we have strong feelings about NIH, we didn&#8217;t think writing our own database store was the way to go. Many smart people have already written many different database backends, [...]]]></description>
			<content:encoded><![CDATA[<p>When you are designing a project with complex storage requirements and some demands on reliability and performance, a few options come to mind.</p>
<p>Even though at <a href="http://www.openpanel.com/">OpenPanel</a> we have strong feelings about <a href="http://en.wikipedia.org/wiki/Not_Invented_Here">NIH</a>, we didn&#8217;t think writing our own database store was the way to go. Many smart people have already written many different database backends, which means that in both quantity and quality the database area is well-covered. So, writing our own was right out.</p>
<p>The second option that comes to mind is to use the most basic kind of database available: a key/value store like Berkeley DB or GDBM. Combining a few key/value stores together yields a lot of flexibility, but there&#8217;s a lot of glue you need to write, then. In programming language terms, the key/value API is not <strong>powerful</strong>. </p>
<p>The only way out then seems to be SQL. The common choice seems to be <a href="http://www.mysql.com/">MySQL</a>, and with good reason - it&#8217;s robust, fast, flexible (supporting most of the SQL standard), comes pre-packaged for any distribution, and just about any sysadmin or PHP-developer you run into knows his way around it more or less. A close second would be <a href="http://www.postgresql.org/">Postgres</a>, less popular with the common PHP developer crowd, more popular with seasoned developers in other languages, and understandably so.</p>
<p>However, we did not go for the path well-traveled. After evaluating our requirements, we realized we barely needed the power of a client/server model database with high concurrency support. Also, we figured choosing a slightly less popular implementation would deter people from messing with the database by hand.</p>
<p>We chose <a href="http://www.sqlite.org/">SQLite</a>. It&#8217;s extremely lightweight, reliable, robust and surprisingly fast. Choosing SQLite means our database is just a file (directory, to be honest) in /var/opencore, where users and admins can&#8217;t run into it by accident while mucking about in phpMyAdmin - but when they really need to mess with the database, they can, with their familiar SQL idioms. </p>
<p>SQLite has most the features a developer would expect from a database; transactions, subqueries, decent indexing support, triggers, and room for extension with user defined functions. The only thing sorely missing is foreign key support, but that&#8217;s easily implemented as <a href="http://www.sqlite.org/cvstrac/wiki?p=ForeignKeyTriggers">a bunch of triggers</a>.</p>
<p>Even though we now had this powerful database engine, we put in a lot of effort mapping our idea of an object revision model onto it (more about that in a later post) - but SQLite made it a lot less painful.</p>
<p>SQLite&#8217;s only real limitation seems its lack of concurrency, which is made worse by the locking model used that seems to invite polling for access instead of forming some kind of queue. For this reason, OpenPanel keeps just one handle to the database file and manages exclusive and shared access to it via the normal pthread mechanisms.</p>
<p>Incidentally, the current (unpublished) version of our automated web application installer tries to shoehorn its data into a key/value store and it&#8217;s hurting - even from Python! We&#8217;ll probably rewrite those bits to use SQLite as well (but, of course, separate from the OpenPanel database).</p>
<p>Summarizing, if you are looking for a data store for your software project, consider SQLite. It&#8217;s as lightweight as most key/value store libraries but throws in a hell of a lot more featurewise.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>Bookmark It</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/&amp;title=Choosing+a+database+for+your+project" rel="nofollow" title="Add to&nbsp;Del.icio.us"><img class="social_img" src="http://blog.openpanel.com/wp-content/plugins/social_bookmarks/images/delicious.png" title="Add to&nbsp;Del.icio.us" alt="Add to&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/&amp;title=Choosing+a+database+for+your+project" rel="nofollow" title="Add to&nbsp;digg"><img class="social_img" src="http://blog.openpanel.com/wp-content/plugins/social_bookmarks/images/digg.png" title="Add to&nbsp;digg" alt="Add to&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.dzone.com/links/add.html?description=Choosing+a+database+for+your+project&amp;url=http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/&amp;title=Choosing+a+database+for+your+project" rel="nofollow" title="Add to&nbsp;DZone"><img class="social_img" src="http://blog.openpanel.com/wp-content/plugins/social_bookmarks/images/dzone.png" title="Add to&nbsp;DZone" alt="Add to&nbsp;DZone" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://furl.net/storeIt.jsp?t=Choosing+a+database+for+your+project&amp;u=http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/" rel="nofollow" title="Add to&nbsp;FURL"><img class="social_img" src="http://blog.openpanel.com/wp-content/plugins/social_bookmarks/images/furl.png" title="Add to&nbsp;FURL" alt="Add to&nbsp;FURL" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/&amp;title=Choosing+a+database+for+your+project" rel="nofollow" title="Add to&nbsp;Google Bookmarks"><img class="social_img" src="http://blog.openpanel.com/wp-content/plugins/social_bookmarks/images/google.png" title="Add to&nbsp;Google Bookmarks" alt="Add to&nbsp;Google Bookmarks" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.netscape.com/submit/?U=http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/&amp;T=Choosing+a+database+for+your+project" rel="nofollow" title="Add to&nbsp;Netscape"><img class="social_img" src="http://blog.openpanel.com/wp-content/plugins/social_bookmarks/images/netscape.png" title="Add to&nbsp;Netscape" alt="Add to&nbsp;Netscape" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/&amp;title=Choosing+a+database+for+your+project" rel="nofollow" title="Add to&nbsp;reddit"><img class="social_img" src="http://blog.openpanel.com/wp-content/plugins/social_bookmarks/images/reddit.png" title="Add to&nbsp;reddit" alt="Add to&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://slashdot.org/bookmark.pl?url=http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/&amp;title=Choosing+a+database+for+your+project" rel="nofollow" title="Add to&nbsp;Slashdot"><img class="social_img" src="http://blog.openpanel.com/wp-content/plugins/social_bookmarks/images/slashdot.png" title="Add to&nbsp;Slashdot" alt="Add to&nbsp;Slashdot" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit.php?url=http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/&amp;title=Choosing+a+database+for+your+project" rel="nofollow" title="Add to&nbsp;Stumble Upon"><img class="social_img" src="http://blog.openpanel.com/wp-content/plugins/social_bookmarks/images/stumbleupon.png" title="Add to&nbsp;Stumble Upon" alt="Add to&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.spurl.net/spurl.php?url=http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/&amp;title=Choosing+a+database+for+your+project" rel="nofollow" title="Add to&nbsp;Spurl"><img class="social_img" src="http://blog.openpanel.com/wp-content/plugins/social_bookmarks/images/spurl.png" title="Add to&nbsp;Spurl" alt="Add to&nbsp;Spurl" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/" rel="nofollow" title="Add to&nbsp;Technorati"><img class="social_img" src="http://blog.openpanel.com/wp-content/plugins/social_bookmarks/images/technorati.png" title="Add to&nbsp;Technorati" alt="Add to&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://myweb2.search.yahoo.com/myresults/bookmarklet?u=http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/&amp;t=Choosing+a+database+for+your+project" rel="nofollow" title="Add to&nbsp;Yahoo My Web"><img class="social_img" src="http://blog.openpanel.com/wp-content/plugins/social_bookmarks/images/yahoo.png" title="Add to&nbsp;Yahoo My Web" alt="Add to&nbsp;Yahoo My Web" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://blog.openpanel.com/2008/04/29/choosing-a-database-for-your-project/feed/atom/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>scrolling in large resultsets with SQL</title>
		<link>http://7bits.nl/blog/2007/10/08/scrolling-in-large-resultsets-with-sql</link>
		<comments>http://7bits.nl/blog/2007/10/08/scrolling-in-large-resultsets-with-sql#comments</comments>
		<pubDate>Mon, 08 Oct 2007 07:48:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.dataloss.nl/perma/scrolling-in-large-resultsets-with-sql/</guid>
		<description><![CDATA[This article on the SQLite wiki details how to efficiently maintain a small window on a big dataset without sacrificing performance, in environments that cannot maintain actual cursors, or where doing so is prohibitively expensive. Rule 2 in the articl...]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.sqlite.org/cvstrac/wiki?p=ScrollingCursor">This article</a> on the SQLite wiki details how to efficiently maintain a small window on a big dataset without sacrificing performance, in environments that cannot maintain actual cursors, or where doing so is prohibitively expensive. Rule 2 in the article applies to other databases too; the method detailed in the article applies to any database in which keeping cursors is either impossible or expensive.</p><p>The article seems obvious; but I had not actually thought of that approach myself, so far.</p>]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/8799/scrolling-in-large-resultsets-with-sql/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>finding dangling symbolic links</title>
		<link>http://7bits.nl/blog/2007/08/15/finding-dangling-symbolic-links</link>
		<comments>http://7bits.nl/blog/2007/08/15/finding-dangling-symbolic-links#comments</comments>
		<pubDate>Wed, 15 Aug 2007 19:41:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.dataloss.nl/perma/finding-dangling-symbolic-links/</guid>
		<description><![CDATA[find -L . -type l
Replace . with the directory you want to investigate, of course. Works with both GNU and (Free)BSD find. Rationale: -L makes find act on the (transitive closuse of the) target of a symlink - unless the target doesn’t exist, in which...]]></description>
			<content:encoded><![CDATA[<p><code>find -L . -type l</code>
</p><p>Replace <code>.</code> with the directory you want to investigate, of course. Works with both GNU and (Free)BSD find. Rationale: -L makes find act on the (transitive closuse of the) target of a symlink - unless the target doesn’t exist, in which case find acts on the symlink itself. So, if the item to act on turns out to be a symlink, it has to be dangling.</p>]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/8800/finding-dangling-symbolic-links/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTTP on Unix sockets with Python</title>
		<link>http://7bits.nl/blog/2007/08/15/http-on-unix-sockets-with-python</link>
		<comments>http://7bits.nl/blog/2007/08/15/http-on-unix-sockets-with-python#comments</comments>
		<pubDate>Wed, 15 Aug 2007 14:55:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.dataloss.nl/perma/http-on-unix-sockets-with-python/</guid>
		<description><![CDATA[Initially I had a more elaborate version based on the exact connect() code in the higher class, but this simpler version works just fine. Incidentally, what the xen xm commandline tool uses works identically ;)
class UHTTPConnection(httplib.HTTPConnect...]]></description>
			<content:encoded><![CDATA[<p>Initially I had a more elaborate version based on the exact <code>connect()</code> code in the higher class, but this simpler version works just fine. Incidentally, what the xen <code>xm</code> commandline tool uses works identically ;)</p><p>
</p><div class="syntax"><pre><span class="k">class</span> <span class="nc">UHTTPConnection</span><span class="p">(</span><span class="n">httplib</span><span class="o">.</span><span class="n">HTTPConnection</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Subclass of Python library HTTPConnection that</span>
<span class="sd">       uses a unix-domain socket.</span>
<span class="sd">    &quot;&quot;&quot;</span>
 
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span>
        <span class="n">httplib</span><span class="o">.</span><span class="n">HTTPConnection</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">&#39;localhost&#39;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">path</span> <span class="o">=</span> <span class="n">path</span>
 
    <span class="k">def</span> <span class="nf">connect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_UNIX</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
        <span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">sock</span> <span class="o">=</span> <span class="n">sock</span>
</pre></div>


<p>This small hack plus the fine <a href="http://hurring.com/code/python/serialize/">PHP serialization classes</a> from Scott Hurring are the basis of <code>OpenPanel.coreclient</code>, which allows for very easy provisioning and querying of OpenPanel/opencore data. We use it mostly for unit testing.</p>]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/8801/http-on-unix-sockets-with-python/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>dpkg version sorting</title>
		<link>http://7bits.nl/blog/2006/11/16/dpkg-version-sorting</link>
		<comments>http://7bits.nl/blog/2006/11/16/dpkg-version-sorting#comments</comments>
		<pubDate>Thu, 16 Nov 2006 10:19:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.dataloss.nl/perma/dpkg-version-sorting/</guid>
		<description><![CDATA[Use this as you would use &#124; sort &#124; to sort package names according to dpkg versioning logic:

#!/usr/bin/perl
sub dpkgcomp
{
  return 1 if(system(&#34;dpkg --compare-versions $a lt $b&#34;));
  return -1 if(system(&#34;dpkg --compare-versions $a gt ...]]></description>
			<content:encoded><![CDATA[<p>Use this as you would use <code>| sort |</code> to sort package names according to dpkg versioning logic:</p>

<div class="syntax"><pre><span class="c1">#!/usr/bin/perl</span>
<span class="k">sub </span><span class="nf">dpkgcomp</span>
<span class="p">{</span>
  <span class="k">return</span> <span class="mi">1</span> <span class="k">if</span><span class="p">(</span><span class="nb">system</span><span class="p">(</span><span class="s">&quot;dpkg --compare-versions $a lt $b&quot;</span><span class="p">));</span>
  <span class="k">return</span> <span class="o">-</span><span class="mi">1</span> <span class="k">if</span><span class="p">(</span><span class="nb">system</span><span class="p">(</span><span class="s">&quot;dpkg --compare-versions $a gt $b&quot;</span><span class="p">));</span>
  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nv">@l</span> <span class="o">=</span> <span class="o">&amp;</span><span class="ow">lt</span><span class="p">;</span><span class="o">&amp;</span><span class="ow">gt</span><span class="p">;;</span>
<span class="nb">chomp</span><span class="p">(</span><span class="nv">@l</span><span class="p">);</span>
<span class="nv">@s</span> <span class="o">=</span> <span class="nb">sort</span> <span class="n">dpkgcomp</span> <span class="nv">@l</span><span class="p">;</span>
<span class="k">print</span> <span class="nb">join</span><span class="p">(</span><span class="s">&quot;\n&quot;</span><span class="p">,</span> <span class="nv">@s</span><span class="p">),</span> <span class="s">&quot;\n&quot;</span><span class="p">;</span>
</pre></div>
]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/8802/dpkg-version-sorting/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL debugging tip</title>
		<link>http://7bits.nl/blog/2006/08/11/sql-debugging-tip</link>
		<comments>http://7bits.nl/blog/2006/08/11/sql-debugging-tip#comments</comments>
		<pubDate>Fri, 11 Aug 2006 15:46:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.dataloss.nl/perma/sql-debugging-tip/</guid>
		<description><![CDATA[When you’re using a lot of SQL from a programming language (be it PHP or C++), put comments inside all your queries indicating which function executed them. That way, logging becomes much more useful, like this:

sqlite3_trace: SELECT /* createobject...]]></description>
			<content:encoded><![CDATA[<p>When you’re using a lot of SQL from a programming language (be it PHP or C++), put comments inside all your queries indicating which function executed them. That way, logging becomes much more useful, like this:

</p><div class="syntax"><pre><span class="n">sqlite3_trace</span><span class="p">:</span> <span class="k">SELECT</span> <span class="cm">/* createobject uniquecontext */</span>
   <span class="n">content</span> <span class="k">FROM</span> <span class="n">objects</span> <span class="k">WHERE</span> <span class="n">id</span><span class="o">=</span><span class="mi">4</span>
</pre></div>


<p>(I did not come up with this trick - but it is useful enough to post here anyway.)</p>]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/8803/sql-debugging-tip/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>computers plotting against humans!</title>
		<link>http://7bits.nl/blog/2006/08/07/computers-plotting-against-humans</link>
		<comments>http://7bits.nl/blog/2006/08/07/computers-plotting-against-humans#comments</comments>
		<pubDate>Mon, 07 Aug 2006 00:24:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.dataloss.nl/perma/computers-plotting-against-humans/</guid>
		<description><![CDATA[Technically I’m a glorified notepad. My ancestors were little keypads with basal unintelligent storage capabilities and names like Sharp and Casio. By pressing their keys you could call up telephone numbers and short messages on impossible-to-read li...]]></description>
			<content:encoded><![CDATA[<blockquote><p>Technically I’m a glorified notepad. My ancestors were little keypads with basal unintelligent storage capabilities and names like Sharp and Casio. By pressing their keys you could call up telephone numbers and short messages on impossible-to-read little LCD screens. I’ve searched the histories and studied examples, and I’m convinced it was all a global plot to destroy humankind’s collective eyesight.</p></blockquote><p>
– Alan Dean Foster, Greenthieves</p>]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/8804/computers-plotting-against-humans/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SSL certificate expiration</title>
		<link>http://7bits.nl/blog/2006/04/24/ssl-certificate-expiration</link>
		<comments>http://7bits.nl/blog/2006/04/24/ssl-certificate-expiration#comments</comments>
		<pubDate>Mon, 24 Apr 2006 08:37:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.dataloss.nl/perma/ssl-certificate-expiration/</guid>
		<description><![CDATA[A simple oneliner that I’ve had to look up three times now, so I’m blogging it:
openssl s_client -connect secure.gay.nl:443 &#124; 
   openssl x509 -noout -dates

]]></description>
			<content:encoded><![CDATA[<p>A simple oneliner that I’ve had to look up three times now, so I’m blogging it:</p><p>
</p><div class="syntax"><pre>openssl s_client -connect secure.gay.nl:443 | 
   openssl x509 -noout -dates
</pre></div>
]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/8805/ssl-certificate-expiration/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>putty URL selection</title>
		<link>http://7bits.nl/blog/2004/09/02/putty-url-selection</link>
		<comments>http://7bits.nl/blog/2004/09/02/putty-url-selection#comments</comments>
		<pubDate>Thu, 02 Sep 2004 13:38:00 +0000</pubDate>
		<dc:creator>Habbie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.dataloss.nl/perma/putty-url-selection/</guid>
		<description><![CDATA[Double-clicking in Putty selects what Putty considers to be a word. However, URLs are not considered words, which is very annoying.The fix turns out to be simple: in settings &#62; Windows &#62; Selection, assign `:’ (ASCII 58) to class 2.Don’t forge...]]></description>
			<content:encoded><![CDATA[<p>Double-clicking in <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/">Putty</a> selects what Putty considers to be a word. However, URLs are not considered words, which is very annoying.</p><p>The fix turns out to be simple: in settings &gt; Windows &gt; Selection, assign `:’ (ASCII 58) to class 2.</p><p>Don’t forget to save your settings.</p>]]></content:encoded>
			<wfw:commentRss>http://fifo.nl/habbie/8797/putty-url-selection/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
