<?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>Benjamin Schweizer.</title>
	<atom:link href="http://benjamin-schweizer.de/feed" rel="self" type="application/rss+xml" />
	<link>http://benjamin-schweizer.de</link>
	<description>Technology, Art and Culture.</description>
	<lastBuildDate>Wed, 01 Feb 2012 22:39:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Colorful Terminals: Theme Support for Tmux</title>
		<link>http://benjamin-schweizer.de/colorful-terminals-theme-support-for-tmux.html</link>
		<comments>http://benjamin-schweizer.de/colorful-terminals-theme-support-for-tmux.html#comments</comments>
		<pubDate>Wed, 21 Dec 2011 23:39:50 +0000</pubDate>
		<dc:creator>Benjamin Schweizer</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://benjamin-schweizer.de/?p=478</guid>
		<description><![CDATA[Most modern terminals have 88/256 color support, but only few applications take advantage of this. Popular software like Irssi, Mignight Commander or Aptitude are still using 16 color mode. To overcome this, I&#8217;ve created a patch for tmux (a screen-like terminal multiplexer). This patch adds a new &#8220;map-color&#8221; command, which can be used to translate [...]]]></description>
			<content:encoded><![CDATA[<p>Most modern terminals have 88/256 color support, but only few applications take advantage of this. Popular software like Irssi, Mignight Commander or Aptitude are still using 16 color mode.</p>
<p>To overcome this, I&#8217;ve created a patch for <a href="http://tmux.sourceforge.net/">tmux</a> (a screen-like terminal multiplexer). <a href="http://benjamin-schweizer.de/files/tmux/">This patch</a> adds a new &#8220;map-color&#8221; command, which can be used to translate from 16 to 256 color palettes.</p>
<pre>
map-colour 7 4 208 236
</pre>
<p>The example above would translate the 16 color pair &#8220;gray on blue&#8221; to 256 color pair &#8220;dark orange on dark grey&#8221;. It matches the default Irssi status line.</p>
<pre>
reset-colours
map-colour * 4 * 236
map-colour * 6 * 238
</pre>
<p>The second example illustrates the use of the color-reset command along with the map-color wildcard feature. First, all existing color mappings are cleared. Then, two new mappings are added: all blue backgrounds map to a grey shade, and all cyan backgrounds map to a similar grey shade.</p>
<p>With these commands, one can create complete themes. I&#8217;ve put <a href="http://benjamin-schweizer.de/files/tmux/tmux-themes/">some examples</a> aside the source code. They can be activated using the source command like &#8220;source /usr/share/tmux/amber.tmux.conf&#8221;.</p>
<p><img src="http://benjamin-schweizer.de/files/tmux/tmux-themes/tmux_amber_irssi.png" /></p>
<p>To apply <a href="http://benjamin-schweizer.de/files/tmux/">the colormap patch</a>, grab the current tmux-1.5 source tree, replace the patched files and run &#8220;aclocal &#038;&#038; automake&#8221; for updating the configure script. Now, you can &#8220;./configure &#038;&#038; make &#038;&#038; make install&#8221; tmux as before.</p>
<p>Of course, contributions are welcome!</p>
<p>→ <a href="http://tmux.sourceforge.net/">tmux project site</a><br />
→ <a href="http://benjamin-schweizer.de/files/tmux/">tmux colourmap patch</a></p>
]]></content:encoded>
			<wfw:commentRss>http://benjamin-schweizer.de/colorful-terminals-theme-support-for-tmux.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Remaining Anonymous</title>
		<link>http://benjamin-schweizer.de/remaining-anonymous.html</link>
		<comments>http://benjamin-schweizer.de/remaining-anonymous.html#comments</comments>
		<pubDate>Wed, 20 Jul 2011 19:39:09 +0000</pubDate>
		<dc:creator>Benjamin Schweizer</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://benjamin-schweizer.de/?p=457</guid>
		<description><![CDATA[Sometimes, it&#8217;s better to remain anonymous. For this, I am using the Tor anonymity network from a dedicated user account on a Linux machine. This user account is somewhat special, hence it is locked down by the local firewall and cannot open any outgoing internet connection. The only way out is the Tor network, which [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes, it&#8217;s better to remain anonymous. For this, I am using the <a href="http://www.torproject.org/">Tor anonymity network</a> from a dedicated user account on a Linux machine. This user account is somewhat special, hence it is locked down by the local firewall and cannot open any outgoing internet connection. The only way out is the Tor network, which ensures this user&#8217;s identity is effectively kept private. Here&#8217;s how:</p>
<pre>
# part of my bashrc
sudo /sbin/iptables -D OUTPUT -o eth0 -m owner --uid-owner $USER -j REJECT
sudo /sbin/iptables -A OUTPUT -o eth0 -m owner --uid-owner $USER -j REJECT
export LD_PRELOAD="/usr/lib/torsocks/libtorsocks.so"
export HOSTNAME="somewhere"
PS1="\A \[\e[30;100m\] $HOSTNAME \[\e[0m\]:\w\$ "
</pre>
<p>First, I ensure a proper firewall rule is set up which forbids all outgoing traffic (this requires sudo permissions). Then, the <a href="http://code.google.com/p/torsocks/">Torsocks</a> library is preloaded to this environment. This ensures all programs that are invoked from this shell are also wrapped to use the Tor proxy. Torsocks wraps most programs that use TCP sockets and (in contrast to torify/socksify), it also wraps DNS requests properly. Any other UDP and ICMP traffic is effectively blocked by the local firewall.</p>
<p>Next thing is to figure out some <a href="https://gitweb.torproject.org/torspec.git?a=blob_plain;hb=HEAD;f=address-spec.txt">special hostnames</a> within the Tor network. For example, &#8220;elinks http://www.ip2location.com.klollely.exit/&#8221; will use the exit note klollely (<a href="http://proxy.org/tor.shtml">which is in Russia</a>) and &#8220;telnet towel.blinkenlights.nl.uhhhhhh.exit&#8221; will open a Telnet connection originating from Thailand. Have fund and use it for good.</p>
]]></content:encoded>
			<wfw:commentRss>http://benjamin-schweizer.de/remaining-anonymous.html/feed</wfw:commentRss>
		<slash:comments>1620</slash:comments>
		</item>
		<item>
		<title>Measuring Disk IO Performance</title>
		<link>http://benjamin-schweizer.de/measuring-disk-io-performance.html</link>
		<comments>http://benjamin-schweizer.de/measuring-disk-io-performance.html#comments</comments>
		<pubDate>Sat, 14 Aug 2010 11:01:27 +0000</pubDate>
		<dc:creator>Benjamin Schweizer</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[benchmark]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[download]]></category>
		<category><![CDATA[freebsd]]></category>
		<category><![CDATA[hdd]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mac os x]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://benjamin-schweizer.de/?p=324</guid>
		<description><![CDATA[Hard disk drives have become larger and larger over the years, but their rotation speeds remain at nearly the same level since decades. This has lead to some odd trait: we have seen greatly improved transfer rates for sequential input/output, but random input/output remains at nearly the same level since ever. The reason for this [...]]]></description>
			<content:encoded><![CDATA[<p>Hard disk drives have become larger and larger over the years, but their rotation speeds remain at nearly the same level since decades. This has lead to some odd trait: we have seen greatly improved transfer rates for sequential input/output, but random input/output remains at nearly the same level since ever.</p>
<p><img class="alignleft" style="margin-top: 10px; margin-bottom: 10px;" src="http://upload.wikimedia.org/wikipedia/commons/thumb/5/52/Hard_drive-en.svg/300px-Hard_drive-en.svg.png" alt="Diagram of a computer hard disk drive, (cc) Surachit" width="300" height="214" />The reason for this is the physical build-up of hard disk drives: to read (or write) some random position on the magnetic layer, a drive needs to move its heads to a given track and <em>wait</em> until the requested sector arrives. Typical mean access times for this are in the range from 5ms to 15ms, resulting in 50-150 random <a href="http://en.wikipedia.org/wiki/IOPS">input/output operations per second</a> (IOPS).</p>
<p>In practice, there are some measures to deal with this constraint. Modern hard drives utilize native command queuing (NCQ) to optimize seek times, we use disk arrays to spread the io load on multiple spindles (RAID), various caching strategies reduce the amount of input/output operations that are issued to the drive and read-ahead/prefetching tries to load the data beforehand.</p>
<p>Though, the question arises: how many input/output operations can we actually perform with all these optimizations in place? Let&#8217;s benchmark this. One tool that we can use for this is <a href="http://benjamin-schweizer.de/files/iops/">iops(1)</a>, a benchmark utility that runs on Linux/FreeBSD/Mac OS X. Iops issues random read requests with increasing blocksizes:</p>
<pre>
$ sudo ./iops --num_threads 1 --time 2 /dev/md1
/dev/md1,   6.00 TB, 1 threads:
 512   B blocks:   43.9 IO/s,  21.9 KiB/s (179.8 kbit/s)
   1 KiB blocks:   46.7 IO/s,  46.7 KiB/s (382.9 kbit/s)
   2 KiB blocks:   46.4 IO/s,  92.7 KiB/s (759.6 kbit/s)
   4 KiB blocks:   37.5 IO/s, 150.0 KiB/s (  1.2 Mbit/s)
   8 KiB blocks:   33.6 IO/s, 268.5 KiB/s (  2.2 Mbit/s)
  16 KiB blocks:   29.5 IO/s, 471.4 KiB/s (  3.9 Mbit/s)
  32 KiB blocks:   26.0 IO/s, 833.3 KiB/s (  6.8 Mbit/s)
  64 KiB blocks:   24.0 IO/s,   1.5 MiB/s ( 12.6 Mbit/s)
 128 KiB blocks:   24.1 IO/s,   3.0 MiB/s ( 25.3 Mbit/s)
 256 KiB blocks:   20.1 IO/s,   5.0 MiB/s ( 42.1 Mbit/s)
 512 KiB blocks:   18.5 IO/s,   9.3 MiB/s ( 77.6 Mbit/s)
   1 MiB blocks:   16.9 IO/s,  16.9 MiB/s (142.0 Mbit/s)
   2 MiB blocks:   11.7 IO/s,  23.3 MiB/s (195.7 Mbit/s)
   4 MiB blocks:    9.2 IO/s,  36.6 MiB/s (307.3 Mbit/s)
   8 MiB blocks:    5.1 IO/s,  41.0 MiB/s (343.6 Mbit/s)
  16 MiB blocks:    3.8 IO/s,  60.8 MiB/s (510.2 Mbit/s)
  32 MiB blocks:    3.1 IO/s, 100.6 MiB/s (843.7 Mbit/s)
  64 MiB blocks:    2.0 IO/s, 127.2 MiB/s (  1.1 Gbit/s)
 128 MiB blocks:    1.1 IO/s, 141.7 MiB/s (  1.2 Gbit/s)
 256 MiB blocks:    0.5 IO/s, 136.1 MiB/s (  1.1 Gbit/s)
</pre>
<p>In this example, the tested device is a Linux software raid5 with four 2 TB, 5.400rpm disks. We have started iops(1) with a single thread and a sampling time of two seconds for each block size. The results show that we reach about 45 IOPS for very small block sizes (or 22ms per IO request).</p>
<p>Now, let&#8217;s increase the number of threads and see how this affects overall performance:</p>
<pre>
$ sudo ./iops --num_threads 16 --time 2 /dev/md1
/dev/md1,   6.00 TB, 16 threads:
 512   B blocks:  151.4 IO/s,  75.7 KiB/s (620.3 kbit/s)
   1 KiB blocks:  123.7 IO/s, 123.7 KiB/s (  1.0 Mbit/s)
   2 KiB blocks:  117.0 IO/s, 234.1 KiB/s (  1.9 Mbit/s)
   4 KiB blocks:   97.7 IO/s, 390.6 KiB/s (  3.2 Mbit/s)
   8 KiB blocks:   78.6 IO/s, 629.1 KiB/s (  5.2 Mbit/s)
  16 KiB blocks:   60.7 IO/s, 970.7 KiB/s (  8.0 Mbit/s)
caught ctrl-c, bye.
</pre>
<p>We see that concurrent requests increase the IO limit to 150 IOPS. This indicates that the requests are actually spread to multiple spindles or optimized by native command queuing. I guess it&#8217;s the spindles, but we could investigate further by benchmarking a single disk instead of the array. Though, this is beyond the scope of this blog post.</p>
<p>→ <a href="http://hg.sickos.org/iops/archive/tip.tar.bz2">get the latest source code</a><br />
→ <a href="https://wiki.sickos.org/iops">visit project page</a><br />
→ <a href="http://hg.sickos.org/iops">visit mercurial repository</a></p>
]]></content:encoded>
			<wfw:commentRss>http://benjamin-schweizer.de/measuring-disk-io-performance.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Building rsync3 on Mac OS X (Universal Binary)</title>
		<link>http://benjamin-schweizer.de/building-rsync3-on-mac-os-x-universal-binary.html</link>
		<comments>http://benjamin-schweizer.de/building-rsync3-on-mac-os-x-universal-binary.html#comments</comments>
		<pubDate>Mon, 26 Jul 2010 16:15:21 +0000</pubDate>
		<dc:creator>Benjamin Schweizer</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[rsync]]></category>
		<category><![CDATA[rsync3]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[universal binary]]></category>

		<guid isPermaLink="false">http://benjamin-schweizer.de/?p=307</guid>
		<description><![CDATA[Apple Mac OS X 10.4-10.6 ships with a modified version of rsync2 that has support for extended attributes and resource forks. Though, it &#8220;does not perform as well as rsync 3.x, consumes more memory (especially for transfers of many files), and will copy unmodified resource forks every single time&#8221; (Mike Bombich). Luckily, you can install [...]]]></description>
			<content:encoded><![CDATA[<p>Apple Mac OS X 10.4-10.6 ships with a modified version of <a href="http://www.samba.org/rsync/">rsync2</a> that has support for extended attributes and resource forks. Though, it &#8220;does not perform as well as rsync 3.x, consumes more memory (especially for transfers of many files), and will copy unmodified resource forks every single time&#8221; (<a href="http://www.bombich.com/mactips/rsync.html">Mike Bombich</a>).</p>
<p>Luckily, you can install rsync3 from <a href="http://www.macports.org/">MacPorts</a>, using Mike&#8217;s <a href="http://www.bombich.com/ccc_features.html">Carbon Copy Cloner</a> (which ships with a mutilated binary) or compile it on your own. This is an receipt for building an rsync3 universal binary that runs on Mac OS X 10.4-10.6 ppc/x86/x86_64:</p>
<pre>
# 2010-07-07, benjamin: receipt for building rsync3 universal binary for
#   mac os x 10.4+ ppc/i386/x86_64 on a build host running 10.6
#   based upon http://www.bombich.com/mactips/rsync.html

# install xcode from http://developer.apple.com/technologies/xcode.html

# get sources
curl -O http://samba.anu.edu.au/ftp/rsync/rsync-3.0.7.tar.gz
curl -O http://samba.anu.edu.au/ftp/rsync/rsync-patches-3.0.7.tar.gz

# optionally verify signatures
curl -O http://samba.anu.edu.au/ftp/rsync/rsync-3.0.7.tar.gz.asc
gpg --verify rsync-3.0.7.tar.gz.asc
curl -O http://samba.anu.edu.au/ftp/rsync/rsync-patches-3.0.7.tar.gz.asc
gpg --verify rsync-patches-3.0.7.tar.gz.asc

# apply patches relevant for preserving Mac OS X metadata
tar xvzf rsync-3.0.7.tar.gz
tar xvzf rsync-patches-3.0.7.tar.gz
cd rsync-3.0.7/
patch -p1 &lt;patches/fileflags.diff
patch -p1 &lt;patches/crtimes.diff

# build 10.4+ ppc binary
CC="gcc-4.0" LDFLAGS="-arch ppc" CFLAGS="-arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4" ./configure
make -j4
mv rsync rsync3.ppc

# build 10.4+ x86 binary
CC="gcc-4.0" LDFLAGS="-arch i386" CFLAGS="-arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4" ./configure
make -j4
mv rsync rsync3.i386

# build 10.5+ x86_64 binary
CC="gcc-4.2" LDFLAGS="-arch x86_64" CFLAGS="-arch x86_64 -isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5" ./configure
make -j4
mv rsync rsync3.x86_64

# combine platform specific binaries into an universal binary
lipo -create rsync3.ppc rsync3.i386 rsync3.x86_64 -output rsync3

# eof.</pre>
<p>You can find binaries, patches etc. in the download section below.</p>
<p>→ <a href="http://benjamin-schweizer.de/files/rsync3/">download binaries</a></p>
]]></content:encoded>
			<wfw:commentRss>http://benjamin-schweizer.de/building-rsync3-on-mac-os-x-universal-binary.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unix Terminals: Surviving the Encoding Hell</title>
		<link>http://benjamin-schweizer.de/unix-terminals-surviving-the-encoding-hell.html</link>
		<comments>http://benjamin-schweizer.de/unix-terminals-surviving-the-encoding-hell.html#comments</comments>
		<pubDate>Thu, 15 Apr 2010 14:08:19 +0000</pubDate>
		<dc:creator>Benjamin Schweizer</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[cp1252]]></category>
		<category><![CDATA[cp850]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[latin1]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[terminal]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[umlauts]]></category>
		<category><![CDATA[unicode]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[utf8]]></category>

		<guid isPermaLink="false">http://benjamin-schweizer.de/?p=255</guid>
		<description><![CDATA[Every now and then, I see people using misconfigured text terminals. People show up in chatrooms and post gibberish or they leave broken umlauts in text, html and source files. This is mostly the case because they (or you) have a broken terminal configuration. In this post, I will try to explain how terminal encodings [...]]]></description>
			<content:encoded><![CDATA[<p>Every now and then, I see people using misconfigured text terminals. People show up in chatrooms and post gibberish or they leave broken umlauts in text, html and source files. This is mostly the case because they (or you) have a broken terminal configuration. In this post, I will try to explain how terminal encodings work and how you can fix things.</p>
<p>Generally spoken, things break if you are using a different terminal encoding than your peers. When you enter text like umlauts and other international characters, it gets encoded using your local terminal encoding (something like latin1, utf-8 or cp850). If a different encoding is used to display this data, you are likely to see gibberish and other strange effects in your terminal. Thus, we need to define what encoding we want to use for a specific file, a chatroom or on a system-wide level. A good guess would be utf8 nowadays, but us-ascii/ascii7 is also pretty common.</p>
<p>First, let&#8217;s find out our actual terminal encoding. Just enter some umlauts like &#8220;äöü&#8221; and show the binary representation in hexadecimal:</p>
<pre>$ printf "äöü" | xxd
0000000: c3a4 c3b6 c3bc                           ......
</pre>
<p>In this example, we find &#8220;c3a4 c3b6 c3bc&#8221; which indicates that the umlauts got encoded into utf8. Other possible results would be &#8220;e4 f6 fc&#8221; for win1252 or &#8220;84 94 81&#8243; for cp850. You can lookup <a href="http://benjamin-schweizer.de/files/umlauts/umlauts.bin">some more encodings here</a>. (Of course, you can also check the manual for your terminal emulator).</p>
<p>Now that we know our actual terminal encoding, we need to tell this to the system libraries and other console software. This is done using <a href="http://linux.die.net/man/5/locale">locale(5)</a>, a standard that is used by almost any program that is capable of doing character encoding and not just passes dumb binary data. To do so, you can list all available encodings by running &#8220;locale -a&#8221; and pick an appropriate one:</p>
<pre>$ locale -a
C
de_DE.utf8
en_US.utf8
POSIX</pre>
<p>This list contains entries in the format location_language.encoding; additional locales can be created using tools like locale-gen(1). I use &#8220;en_US.utf-8 hence my terminal uses utf8 and I prefer English program output. This locale string should be set as $LC_ALL as environment variable (or LC_CTYPE if you want to ignore the language and location). Some terminals do this automatically, but we can also do this in our ~/.profile file which is sourced whenever a new terminal is started. For compatibility with older software, we also set $LANG to the same value:</p>
<pre>export LC_ALL=en_US.utf-8
export LANG="$LC_ALL"</pre>
<p>You can check the result in a new terminal by typing &#8220;locale&#8221;; if you see &#8220;C&#8221; instead of your locale string, something went wrong and the locales felt back to the default settings. Check that your locale string is in the list. When everything looks ok, you should see the utf8 line in my <a href="http://benjamin-schweizer.de/files/umlauts/umlauts.bin">umlauts test file</a> (just type &#8220;cat umlauts.bin&#8221;).</p>
<p>Now that we have checked the local terminal settings, we should do the same for hosts where we ssh into. Luckily, ssh can forward our locales settings, just append &#8220;SendEnv LANG LC_ALL&#8221; to ~/.ssh/config and check that your locale is also available on the remote host. Voila, you have a properly working terminal with defined locales.</p>
<p>If you still see malformed characters, it is likely that you use software that does not know about locales at all and just passes raw data. In theory, such software should fall back to us-ascii/ascii7 and strip or replace all other characters. If this fails, you can either use another program or you are forced to use a terminal program with the same binary encoding (or avoid umlauts if you are on IRC;-).</p>
]]></content:encoded>
			<wfw:commentRss>http://benjamin-schweizer.de/unix-terminals-surviving-the-encoding-hell.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More Fun with the Python Class Dispatcher</title>
		<link>http://benjamin-schweizer.de/more-fun-with-the-python-class-dispatcher.html</link>
		<comments>http://benjamin-schweizer.de/more-fun-with-the-python-class-dispatcher.html#comments</comments>
		<pubDate>Fri, 26 Mar 2010 13:15:39 +0000</pubDate>
		<dc:creator>Benjamin Schweizer</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[class dispatcher]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tricks]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://benjamin-schweizer.de/?p=224</guid>
		<description><![CDATA[In a recent post, I have demonstrated how to do prototype-style method injection in Python. Today, I&#8217;ll show how you can have even more fun with the class dispatcher by changing the base class of an object during run-time. But first, let me illustrate a real-world problem where this proposed solution becomes handy&#8230; Like many [...]]]></description>
			<content:encoded><![CDATA[<p>In a recent post, I have demonstrated how to do <a href="http://benjamin-schweizer.de/fun-with-the-python-class-dispatcher.html">prototype-style method injection in Python</a>. Today, I&#8217;ll show how you can have even more fun with the class dispatcher by changing the base class of an object during run-time. But first, let me illustrate a real-world problem where this proposed solution becomes handy&#8230;</p>
<p>Like many others, I&#8217;ve jumped the distributed computing hype and spent a lot of time with nosql databases (I prefer <a href="http://www.mongodb.org/">Mongo</a>). Due to the document-based storage model, the actual document type is stored inside a given document. In example, imagine you have something like {&#8216;type&#8217;: &#8216;post&#8217;, &#8216;id&#8217;: 23, &#8230;} stored inside a collection, say it represents a blog post. When you load an object from the database, you cannot decide what type it is unless you have retrieved it from the database. If you want to represent the retrieved data as an object, you have to add a loader that fetches the raw data and decides what type of object it should create. So, it is likely that you end up with an interface like this:</p>
<pre>db = DB()
post = Post()
id = db.save(post)
same_post = db.get(id)
db.delete(id)
</pre>
<p>This is fairly ok, but you&#8217;ll end up splitting the interface into a db object and a post object. The db object appears reasonable because it can load the raw data and create objects of different types like Post or Comment, depending on the type variable. This is ok, but I think we can do better. Imagine an interface like this:</p>
<pre>post = Post()
id = post.save()
same_post = Post(id)
same_post.delete()
</pre>
<p>It feels more intuitive and reflects the way you would describe the actual task. You could have the database code in the same object (or a parent of it) and make things more explicit. Though, if you cannot determine the object type before you fetch it from the database, you cannot decide what type of object to create. So, if you invoke the constructor of a post object, but you find the actual type to be &#8220;comment&#8221;, how can you change the base class now? Like this:</p>
<pre>class Generic:
    def __init__(self, class_name=None):
        if not class_name:
            return

        classes = globals()
        if not class_name in classes:
            raise Exception("%s not found in global scope" % class_name)
        _class = classes[class_name]
        if not type(_class) == type(self.__class__):
            raise Exception("%s is not a class" % class_name)

        self.__class__ = _class

class Specialized(Generic):
    pass

c = Generic("Specialized")
print c     # prints &lt;Specialized&gt;</pre>
<p>In this example,we run the constructor of class Generic and dependent on some contextual data (class_name here), we change the base class of our object after instantiation. What we get is an object of class Specialized even though we invoked the constructor of Generic. This methodology can easily be applied to our blog example, making the interface much cleaner and more expressive.</p>
]]></content:encoded>
			<wfw:commentRss>http://benjamin-schweizer.de/more-fun-with-the-python-class-dispatcher.html/feed</wfw:commentRss>
		<slash:comments>3650</slash:comments>
		</item>
		<item>
		<title>Samsung LED TV: The Good, The Bad, The Ugly</title>
		<link>http://benjamin-schweizer.de/samsung-led-tv-the-good-the-bad-the-ugly.html</link>
		<comments>http://benjamin-schweizer.de/samsung-led-tv-the-good-the-bad-the-ugly.html#comments</comments>
		<pubDate>Wed, 24 Mar 2010 15:09:07 +0000</pubDate>
		<dc:creator>Benjamin Schweizer</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[firmware]]></category>
		<category><![CDATA[gpl]]></category>
		<category><![CDATA[license]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mode number]]></category>
		<category><![CDATA[samsung]]></category>
		<category><![CDATA[tv]]></category>

		<guid isPermaLink="false">http://benjamin-schweizer.de/?p=203</guid>
		<description><![CDATA[Recently, we&#8217;ve bought a shiny new Samsung LED TV. It&#8217;s a Series 6 model with a large screen and an integrated DVB-C decoder. The TV set is pretty fine, it runs a Linux-based firmware and has an integrated media player. After reading the tech specs, I&#8217;ve found out about the differences of Series 6 and [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, we&#8217;ve bought a shiny new Samsung LED TV. It&#8217;s a Series 6 model with a large screen and an integrated DVB-C decoder. The TV set is pretty fine, it runs <a href="http://downloadcenter.samsung.com/content/UM/200910/20091012160308796/GNU_license-1113.pdf">a Linux-based firmware</a> and has an integrated media player.</p>
<p>After reading the tech specs, I&#8217;ve found out about the differences of Series 6 and Series 7 models and started worrying. The hardware is almost the same: Series 7 models have a CI+ interface and an additional USB port but this is not important for me. Both TV sets run the same firmware, but on Series 6 models, the integrated media player does not play movies. Hence the hardware is nearly the same, this limitation has no technical reasons.</p>
<p>So, I&#8217;ve investigated further&#8230; A friend suggested that we could patch the firmware and enable the movie playback there. I&#8217;ve contacted Samsung and requested a copy of the GPL-licensed source code. Though, their customer support never responded to my request. After this, I started to tinker with the firmware binary files, but I had to find that they are encrypted and digitally signed (using OpenSSL, lol).</p>
<p>This means, even if you get Samsung to hand over the source code, they won&#8217;t allow you to use it in the sense of correcting bugs on your own television. Bad karma; this is clearly not the will of the original software authors.</p>
<p style="text-align: center;"><img class="aligncenter" src="http://farm3.static.flickr.com/2640/4112072507_419f2bb68e.jpg" alt="" /></p>
<p>In spite of everything, there&#8217;s yet a simple solution &#8211; at least for the media player issue. The firmware holds <a href="http://www.flickr.com/photos/nk-h/4102072907/">a hidden service menu</a> that can be entered by pressing INFO-MENU-MUTE-POWER when the TV is in standby. From there, I was able to change the model number to a Series 7 model and reach the fully-featured media player (see <a href="http://www.smovs.dk/htpc/index.php?note=16&amp;subject=Samsung%20UE32B6050%20(6000%20series%20LED%20TV)%20movie%20mode">here</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://benjamin-schweizer.de/samsung-led-tv-the-good-the-bad-the-ugly.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Improved Python Traceback Module</title>
		<link>http://benjamin-schweizer.de/improved-python-traceback-module.html</link>
		<comments>http://benjamin-schweizer.de/improved-python-traceback-module.html#comments</comments>
		<pubDate>Wed, 27 Jan 2010 21:39:50 +0000</pubDate>
		<dc:creator>Benjamin Schweizer</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[Code1]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[stack]]></category>
		<category><![CDATA[traceback]]></category>

		<guid isPermaLink="false">http://benjamin-schweizer.de/?p=188</guid>
		<description><![CDATA[Like any modern language, Python comes along with a nice traceback module. This module gives you stack traces from the line of code where an exception is raised up to the next try-except clause. So, you can easily catch exceptions and write stack traces into a debug log. This debugging technique is pretty handy to [...]]]></description>
			<content:encoded><![CDATA[<p>Like any modern language, Python comes along with a nice <a href="http://docs.python.org/library/traceback.html">traceback module</a>. This module gives you stack traces from the line of code where an exception is raised up to the next try-except clause. So, you can easily catch exceptions and write stack traces into a debug log. This debugging technique is pretty handy to drill down bugs and I use it a lot in prototyping.</p>
<p>Using the traceback module is straight forward for evident programming mistakes. However, real bugs are context-sensitive and they can hardly be reproduced without the actual data that was processed when an exception was raised. If you can reproduce a specific bug, you can add some logging code in front and inspect the variables the next time the bug is triggered. But if a bug occurs once in a blue moon, you&#8217;d be better in logging the data the first time an exception raises.</p>
<pre>import tracebackturbo as traceback

def erroneous_function():
    ham = u"unicode string with umlauts äöü."
    eggs = "binary string with umlauts äöü."
    i = 23
    if i&gt;5:
        raise Exception("it's true!")

try:
    erroneous_function()
except:
    print traceback.format_exc(with_vars=True)</pre>
<p>Here&#8217;s my solution; an improved Python traceback module the logs variables from the local scope next to the affected code. You can find a working copy in our Mercirual repository (see the below).</p>
<pre>Traceback (most recent call last):
  File "test.py", line 11, in <module>
    Local variables:
      __builtins__ = </module><module '__builtin__' (built-in)>
      __doc__ = None
      __file__ = "x"
      __name__ = "__main__"
      __package__ = None
      erroneous_function = <function erroneous_function at 0x100435050>
      traceback = &lt;module 'tracebackturbo' from '/private/tmp/python-...
    erroneous_function()
  File "test.py", line 8, in erroneous_function
    Local variables:
      eggs = "binary string with umlauts \xc3\xa4\xc3\xb6\xc3\xbc."
      ham = u"unicode string with umlauts ???."
      i = 23
    raise Exception("it's true!")
Exception: it's true!
</function></module></pre>
<p>I am not sure if it is the &#8220;right&#8221; solution as sensitive information might be logged. This might have security implications for some real-world scenarios where webapps report stack traces to the end user (e.g. by using cgitb in production).</p>
<p>Credit: this code was inspired by <a href="http://code.activestate.com/recipes/52215/">format_exc_plus</a> by Bryn Keller.</p>
<p>2010-01-28: there&#8217;s an active discussion on <a href="http://thread.gmane.org/gmane.comp.python.devel/110326">python-dev</a>.<br />
2011-06-25: I&#8217;ve renamed the module, enable print_vars by default and merge with upstream</p>
<p>→ <a href="http://hg.sickos.org/python-traceback/archive/tip.tar.bz2">get latest source code</a><br />
→ <a href="http://hg.sickos.org/python-traceback/">visit mercurial repository</a></p>
]]></content:encoded>
			<wfw:commentRss>http://benjamin-schweizer.de/improved-python-traceback-module.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Adding a Custom LDAP Schema to Open Directory on 10.5+</title>
		<link>http://benjamin-schweizer.de/adding-a-custom-ldap-schema-to-open-directory.html</link>
		<comments>http://benjamin-schweizer.de/adding-a-custom-ldap-schema-to-open-directory.html#comments</comments>
		<pubDate>Fri, 15 Jan 2010 09:55:10 +0000</pubDate>
		<dc:creator>Benjamin Schweizer</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[ldap]]></category>
		<category><![CDATA[leopard]]></category>
		<category><![CDATA[open directory]]></category>
		<category><![CDATA[openldap]]></category>
		<category><![CDATA[schema]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://benjamin-schweizer.de/?p=183</guid>
		<description><![CDATA[Open Directory is a key component of Mac OS X Server. It consists of OpenLDAP, MIT Kerberos, Password Server and a tool chain that enables GUI administration. Sadly, adding new ldap schemas to the directory server is not documented in the advanced administration guides and you have to tinker with the command line tools. I [...]]]></description>
			<content:encoded><![CDATA[<p>Open Directory is a key component of Mac OS X Server. It consists of OpenLDAP, MIT Kerberos, Password Server and a tool chain that enables GUI administration. Sadly, adding new ldap schemas to the directory server is not documented in the <a href="http://www.apple.com/server/macosx/resources/documentation.html">advanced administration guides</a> and you have to tinker with the command line tools. I could not find any good documentation how you to add a custom LDAP schema, so I&#8217;ll show my solution here.</p>
<p>Mac OS X Server 10.5 ships with OpenLDAP 2.3. This release supports run-time configuration, which means that the LDAP schemas are stored within the directory server and you cannot simply put your new schema file in /etc/openldap/schema/; you have to convert it to an LDIF file and load this into the directory itself. This can be done during run-time but it breaks replication if you do so. So, instead you have to create a proper old-style config and run a manual conversion to the new run-time config.</p>
<p>To do so, you need to place the new schema file in /etc/openldap/schema/some-new.schema. This directory is copied  to new replicas when you join them, so you won&#8217;t break the Apple tool chain. Then, you need to include the new schema file from /etc/openldap/slapd.conf; this has no direct effect but slaptest(1) uses this to re-create the run-time config. Finally, convert the old-style config to a new <a href="http://www.zytrax.com/books/ldap/ch6/slapd-config.html">run-time config using slaptest(1)</a> like &#8220;slaptest -f slapd.conf -F slapd.d&#8221; and restart slapd:</p>
<pre>cd /etc/openldap
cp some-new.schema schema/
cat &gt;&gt; slapd.conf &lt;&lt;HERE
include /etc/openldap/schema/some-new.schema
HERE
mv slapd.d slapd.d_bak
slaptest -f slapd.conf -F slapd.d
launchctl unload /System/Library/LaunchDaemons/org.openldap.slapd.plist
launchctl load /System/Library/LaunchDaemons/org.openldap.slapd.plist
</pre>
<p><strong>Beware</strong>: we are deleting the old run-time config here and create a new one from the static config. If you have changed the config without adopting the old-style config, you might loose modifications. So, check twice if all required schemas are included from slapd.conf. AFAIK, Kerio Mailserver is troublesome here as it is not adding the include lines to slapd.conf. Though, thise procedure is exactly what the Apple tool chain does on replication and I suggest you do it exactly this way. Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://benjamin-schweizer.de/adding-a-custom-ldap-schema-to-open-directory.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Eight Questions on Twitter</title>
		<link>http://benjamin-schweizer.de/eight-questions-on-twitter.html</link>
		<comments>http://benjamin-schweizer.de/eight-questions-on-twitter.html#comments</comments>
		<pubDate>Thu, 07 Jan 2010 21:54:15 +0000</pubDate>
		<dc:creator>Benjamin Schweizer</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[rant]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://benjamin-schweizer.de/?p=158</guid>
		<description><![CDATA[Why&#8230; is it too slow for real-time communications (that is available on IRC since 1988)? can&#8217;t #hashtags contain unicode? is there a length limit for my nickname? can&#8217;t I sign on from multiple computers simultanously? does their web page no auto-refresh? is it always over capacity? didn&#8217;t they register appropriate country TLDs like .de? have [...]]]></description>
			<content:encoded><![CDATA[<p>Why&#8230;</p>
<ol>
<li>is it too slow for real-time communications (that is available on IRC since 1988)?</li>
<li>can&#8217;t #hashtags contain unicode?</li>
<li>is there a length limit for my nickname?</li>
<li>can&#8217;t I sign on from multiple computers simultanously?</li>
<li>does their web page no auto-refresh?</li>
<li>is it always over capacity?</li>
<li>didn&#8217;t they register appropriate country TLDs like .de?</li>
<li>have they shut down their Jabber interface?</li>
</ol>
<ol></ol>
]]></content:encoded>
			<wfw:commentRss>http://benjamin-schweizer.de/eight-questions-on-twitter.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

