<?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>Record and Reverie</title>
	<atom:link href="http://www.cod3r.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cod3r.com</link>
	<description>General things I find interesting</description>
	<lastBuildDate>Thu, 02 Sep 2010 18:06:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Google&#8217;s Link Redirection</title>
		<link>http://www.cod3r.com/2010/08/googles-link-redirection/</link>
		<comments>http://www.cod3r.com/2010/08/googles-link-redirection/#comments</comments>
		<pubDate>Tue, 31 Aug 2010 02:42:50 +0000</pubDate>
		<dc:creator>Graham Booker</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.cod3r.com/?p=370</guid>
		<description><![CDATA[Google, for quite some time, has been redirected clicks on links in their search results to www.google.com/url?&#8230;. While I don&#8217;t approve of such practices, I didn&#8217;t mind it so much since this is presumably an effort to improve their search results. That changed recently, when I noticed that my history in Safari was filled with [...]]]></description>
			<content:encoded><![CDATA[<p>Google, for quite some time, has been redirected clicks on links in their search results to www.google.com/url?&#8230;.  While I don&#8217;t approve of such practices, I didn&#8217;t mind it so much since this is presumably an effort to improve their search results.  That changed recently, when I noticed that my history in Safari was filled with entries containing that URL as the title.  Considering the fact that I often use the history to re-find a page with pertinent information, this is bordering on making my browser usage useless.  Note: I tend to cmd-click links so they show up in new tabs.  If you just click the link, the title in the history is correct.</p>
<p><strong>Edit:</strong> My solution that was here previously didn&#8217;t work properly.  I&#8217;ve developed a Safari Extension to correct this, and am currently testing it.  If it passes the tests, I&#8217;ll likely put it up here.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cod3r.com/2010/08/googles-link-redirection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Text Compression Code Released</title>
		<link>http://www.cod3r.com/2010/07/text-compression-code-released/</link>
		<comments>http://www.cod3r.com/2010/07/text-compression-code-released/#comments</comments>
		<pubDate>Sat, 17 Jul 2010 20:36:22 +0000</pubDate>
		<dc:creator>Graham Booker</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.cod3r.com/?p=363</guid>
		<description><![CDATA[After it&#8217;s original post, I got a request for the code I used in my text compression technique. I&#8217;ve not gotten around to cleaning up the code and separating it from it&#8217;s test environment so it can be distributed separately. You can read more about it in its own page. Sometime soon, I&#8217;ll get around [...]]]></description>
			<content:encoded><![CDATA[<p>After it&#8217;s <a href="http://www.cod3r.com/2009/07/text-compression-techniques/">original post</a>, I got a request for the code I used in my text compression technique.  I&#8217;ve not gotten around to cleaning up the code and separating it from it&#8217;s test environment so it can be distributed separately.  You can read more about it in its own <a href="http://www.cod3r.com/programming/text-compression/">page</a>.</p>
<p>Sometime soon, I&#8217;ll get around to releasing my code for fetching old Escape Pod episodes that I <a href="http://www.cod3r.com/2009/09/incorrect-podcast-order-on-my-ipod/">hinted at earlier</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cod3r.com/2010/07/text-compression-code-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ZFS on Western Digital EARS drives</title>
		<link>http://www.cod3r.com/2010/06/zfs-on-western-digital-ears-drives/</link>
		<comments>http://www.cod3r.com/2010/06/zfs-on-western-digital-ears-drives/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 21:21:23 +0000</pubDate>
		<dc:creator>Graham Booker</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.cod3r.com/?p=351</guid>
		<description><![CDATA[According to the stats, my previous post was one of the more popular on this site. This was in response to a question I was asking myself before building a NAS box at home. In looking at the components to use in building it, I came across another question. How does one fix the performance [...]]]></description>
			<content:encoded><![CDATA[<p>According to the stats, <a href="http://www.cod3r.com/2010/04/zfs-on-different-sized-disks/">my previous post</a> was one of the more popular on this site.  This was in response to a question I was asking myself before building a NAS box at home.  In looking at the components to use in building it, I came across another question.  How does one fix the performance of ZFS on Western Digital&#8217;s green drives with model numbers ending in &#8220;EARS&#8221; (WD15EARS, WD20EARS, etc)?  I&#8217;ve split this into sections, with a bold title, so readers can read the parts that are most interesting.  I&#8217;ve described why WD changed their drives, why this is a problem, what the solutions are.  Hope you enjoy this.</p>
<p><strong>Background</strong><br />
First, some background on how drives work internally:  A hard drive stores data on the platters in blocks, or sectors.  The sector size is typically 512 bytes for a magnetic disk.  With each sector, the disk must store a start code and an Error Correction Code (ECC).  The start code is necessary so the disk can find a particular sector, and the ECC is necessary to correct any errors in the data read from the disk.<br />
Western Digital decided to change from 512 byte sectors to 4096 byte sectors.  This means that the new sector  can store the same amount of data as 8 of the previous sectors.  Since each sector needs a start code, this means there are now 7 fewer start codes for each new sector.<br />
The ECC of the 4096 byte sector needs to be larger than the ECC of a 512 byte sector, but it doesn&#8217;t need to be 8 times as big.  This is due to the fact that ECC is better at correcting errors with larger block sizes and thus a lower rate (or percentage in size) ECC can achieve the same Bit Error Rate (BER).  Interesting side note: Hard drives are designed to store data so compactly and so close to the limits of the hardware that data is expected to have some corruption as it was stored, and rely on the ECC to correct the corruption.  In fact, the manufactures intentionally design the drives so that it will have a few corruptions but few enough that the ECC can handle it.<br />
With the reduction in the number of start codes, and decrease in ECC rate, larger sector sizes allow for greater density of data on the drive itself.</p>
<p><strong>Writing Sectors</strong><br />
When a computer does a read, it reads an entire sector at a time.  When it does a write, it, again, writes an entire sector at a time.  There is no such mechanism to write only a part of a sector.  Western Digital&#8217;s EARS drives have 4096-byte sectors, but the drive claims it has 512-byte sectors (since some opperating systems still in use cannot handle different sector sizes).  This means that the drive does some work internally to handle this difference.  Often, when writing data to a hard drive, multiple consecutive sectors are written.  If a computer writes 8 512-byte sectors in a row, which all correspond to the same 4096-byte sector, then the drive can simply wait until all 8 sectors are written and write out all the data as a single 4096-byte sector.  This is what the EARS drives do when sectors are written.  If not all 8 sectors are written, then the drive has to do a partial sector write.  This is typically not the case since many file system operate on 4096-byte blocks, and thus write 4096 bytes at a time.</p>
<p><strong>Partial Sector Write</strong><br />
If not all 8 512-byte sectors in a 4096-byte sector are written, then the drive has to write part of a sector.  So, the drive must find the data on the drive, and write the part of the sector that has changed, right?<br />
Wrong.  The problem is the ECC was written with the 4096 bytes that was there previously, so it must be updated.  Due to the nature of how the ECC is computed, one cannot write a new ECC without first reading at least some of the data that was in the original sector.  While it is possible to read the data to be overwritten, the old ECC, and compute the new ECC, this can propagate errors beyond the ECC&#8217;s ability to correct.  So, the drive must read the 4096-byte sector, correct any data errors in the sector, substitute in the changed data, compute the new ECC, wait for that part of the drive to spin around again, and write the data to the drive.  In comparison, if all 8 512-byte sectors were written, then the drive need only compute the new ECC and write the data.<br />
So, if a single 512-byte sector is written, the drive must read 4096 bytes, wait for a rotation, and then write 4096 bytes.  On a 7200 RPM drive, the waiting for a single rotation is 8.333 ms.  If one assumes no smart scheduling, this results in a maximum throughput of a megabyte every 2 seconds, which is reminiscent of drives from the previous decade.  Obviously, intelligent scheduling is utilized, but in the best case scenario, the drives performance will be dropped to half.  From this, one can see that it is crucial to always write 4096 bytes at a time to get the best performance.</p>
<p><strong>Alignment</strong><br />
As stated in the previous section, the best performance comes when 4096 bytes is written at a time, but this data must also be properly aligned.  If 2048 bytes is written to one sector and 2048 to the next, then this involves 2 reads and 2 writes of 4096 bytes each.  So all writes must be aligned on 8 sector boundaries (sector 0, 8, 16, 24, 32, etc)  This is why Western Digital put in a jumper to help with the alignment since some formatting methods start on sector 63, which is not an 8 sector boundary.  Those on Unix/Linux systems must pay special attention to this when formatting the drive.</p>
<p><strong>Solutions</strong><br />
The solutions depend on the file system you are using.  If you know your file system uses 4096-byte blocks, then you only need to ensure that the file system is properly aligned on 8-sector boundaries.  So, when partitioning the drive, ensure that the partition offsets are divisible by 8.</p>
<p><strong>ZFS</strong><br />
So, what does this have to do with ZFS?  ZFS doesn&#8217;t have a pre-set block size.  It uses variable sized blocks depending on the amount of data it is writing.  If it&#8217;s writing 1000 bytes, then it will write the minimum number of sectors necessary to fit that data, which in the case of 512-byte sectors, is 2.  This means that writing 1000 bytes requires reading and writing 4096 bytes or maybe 8192 depending on alignment.  This means that properly aligning the partition will not solve the issue with ZFS.  Here we need a different solution.</p>
<p><strong>File System Agnostic Solution</strong><br />
The best solution is for the file system to think the drive has 4096-byte sectors.  Since the drive will not claim this it needs to be done in software (really Western Digital, did you think this was not worthy of a jumper on the drive?  It would have made things much easier).  Since ZFS has performance issues on Linux anyway due to it&#8217;s kernel&#8217;s license, I won&#8217;t cover it at all.  The primary case I&#8217;ve seen this issue raised is from those using FreeNAS on FreeBSD.  Here, there are two solutions, depending on whether you want your drive encrypted or not.  Both of these solutions give a new device, which the rest of the OS sees as a normal drive, but the drive has 4096-byte sectors, which are properly aligned.  Warning, both of these methods destroy the data on the drive.<br />
<strong>Not Encrypted</strong><br />
The drive can be presented as a drive with 4096-byte sectors by using gnop.  Here is how one would create a raidz1 pool for da1-4:<br />
<code>for i in da1 da2 da3 da4; do gnop create -S 4096 $i; done<br />
zpool create tank da1.nop da2.nop da3.nop da4.nop</code><br />
The for loop must be run on each reboot otherwise ZFS will not see the da*.nop devices.<br />
<strong>Encrytped</strong><br />
The encryption setup is similar:<br />
<code>for i in da1 da2 da3 da4; do geli init -s 4096 $i; done<br />
for i in da1 da2 da3 da4; do geli attach $i; done<br />
zpool create tank da1.eli da2.eli da3.eli da4.eli</code><br />
Here the second for loop needs to be executed on each reboot.  On FreeNAS, the encryption can be made simpler by setting up the drives in the GUI to use encryption, then after the encryption is setup, go into the shell, and execute the two for loops, then continue setting up the encrypted drive in the gui to use ZFS.</p>
<p>So, that&#8217;s how to handle ZFS on WD EARS drives.  I&#8217;ve read reports that some, if not all, of what I described in the solutions will be in the next version of FreeNAS.  Here&#8217;s hoping that it will.</p>
<p>BTW, the primary legacy Operating System that cannot properly handle the 4096-byte sector is Windows XP.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cod3r.com/2010/06/zfs-on-western-digital-ears-drives/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ZFS on different sized disks</title>
		<link>http://www.cod3r.com/2010/04/zfs-on-different-sized-disks/</link>
		<comments>http://www.cod3r.com/2010/04/zfs-on-different-sized-disks/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 00:04:20 +0000</pubDate>
		<dc:creator>Graham Booker</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.cod3r.com/?p=310</guid>
		<description><![CDATA[I&#8217;ve read many posts on how to handle ZFS/Raid-Z on differently sized disks. The goal is to gain the most disk space availability while still retaining the redundancy of surviving a single disk failure. The posts I&#8217;ve read either would achieve the theoretical capacity, or be capable of expansion, but not both. I devised a [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve read many posts on how to handle <a href="http://en.wikipedia.org/wiki/ZFS">ZFS</a>/<a href="http://en.wikipedia.org/wiki/RAID-Z">Raid-Z</a> on differently sized disks.  The goal is to gain the most disk space availability while still retaining the redundancy of surviving a single disk failure.  The posts I&#8217;ve read either would achieve the theoretical capacity, or be capable of expansion, but not both.  I devised a way to get both at the same time, and it&#8217;s relatively simple.</p>
<p>The problem is the following:  A Raid-Z configuration uses n partitions, giving the user the capacity of n-1 of those partitions, with the nth being the redundant to survive a failure.  If the n partitions are not the same size, with the smallest being x, only the first x bytes of each partition is used.  One cannot remove a Raid-Z from an active pool without a backup/restore.  One cannot add a disk to a Raid-Z without a backup/restore (<a href="http://blogs.sun.com/ahl/entry/expand_o_matic_raid_z">maybe in the future</a>).  The only expansion that can be done is to replace the partitions with larger ones, and once the smallest partition is increased, the available space increases.</p>
<p>For the purposes of demonstrating this technique, I will use an example with 4 disks:</p>
<ul>
<li>125G</li>
<li>250G</li>
<li>500G</li>
<li>750G</li>
</ul>
<p>The biggest theoretical capacity of the array, while retaining single disk failure resiliency, is simply the total size of the array minus the largest disk.  This means that the capacity of the above example is 875G.  So, how does one achieve this capacity?  I proposed the following structure using 3 raids:</p>
<p><a href="http://www.cod3r.com/images/2010/04/Initial-Disks.png"><img src="http://www.cod3r.com/images/2010/04/Initial-Disks-300x165.png" alt="" title="Initial Disks" width="300" height="165" class="aligncenter size-medium wp-image-331" /></a></p>
<p>If you add the capacity in the above, you can see it is 3*125G + 2*125G + 250G = 875G, which is the theoretical capacity.</p>
<p>Suppose I wish to replace the smallest disk, 125G, with a new disk, say 1T.  Using the same layout, I should see something like this:</p>
<p><a href="http://www.cod3r.com/images/2010/04/Final-Disks.png"><img src="http://www.cod3r.com/images/2010/04/Final-Disks-300x210.png" alt="" title="Final Disks" width="300" height="210" class="aligncenter size-medium wp-image-334" /></a><br />
If you add the capacity in the above, you can see it is 3*250G + 2*250G + 250G = 1500G, which again is the theoretical capacity.</p>
<p>The question is, can I migrate from the first configuration to the last without a backup/restore process?  The answer is <strong>YES</strong>, and data is moved/copied at most once.</p>
<p>For the purposes of demonstration, I&#8217;m going to show the expansion with 5 drives connected, but the expansion can be done by immediately replacing the smallest drive with the largest and relying on the redundancy to keep things intact in the process.</p>
<p>First, connect the 1T drive and partition it as 250G, 250G, 250G, leaving the rest free.  Replace the first 125G partition on 750G disk with the first 250G partition on the 1T disk:<br />
<a href="http://www.cod3r.com/images/2010/04/Step-1.png"><img src="http://www.cod3r.com/images/2010/04/Step-1-300x171.png" alt="" title="Step 1" width="300" height="171" class="aligncenter size-medium wp-image-335" /></a></p>
<p>Continue the replacement:<br />
<a href="http://www.cod3r.com/images/2010/04/Step-2.png"><img src="http://www.cod3r.com/images/2010/04/Step-2-300x171.png" alt="" title="Step 2" width="300" height="171" class="aligncenter size-medium wp-image-336" /></a></p>
<p><a href="http://www.cod3r.com/images/2010/04/Step-3.png"><img src="http://www.cod3r.com/images/2010/04/Step-3-300x171.png" alt="" title="Step 3" width="300" height="171" class="aligncenter size-medium wp-image-337" /></a></p>
<p>Repeat the same process with the 3 partitions on the 500G disk:<br />
<a href="http://www.cod3r.com/images/2010/04/Step-4.png"><img src="http://www.cod3r.com/images/2010/04/Step-4-300x171.png" alt="" title="Step 4" width="300" height="171" class="aligncenter size-medium wp-image-338" /></a><br />
At this point, the move of the blue raid is complete.  Depending on the sizes of the disks, the blue raid may be bigger, at which point the pool immediately increases in size.  In this example, it does not change size.</p>
<p>Repeat with the 2 partitions on the 250G disk:<br />
<a href="http://www.cod3r.com/images/2010/04/Step-5.png"><img src="http://www.cod3r.com/images/2010/04/Step-5-300x171.png" alt="" title="Step 5" width="300" height="171" class="aligncenter size-medium wp-image-339" /></a><br />
At this point, the red raid is complete.  In this example, the red raid has changed from 250G to 500G, and the job isn&#8217;t complete yet!</p>
<p>Repeat for the final time with partition on the 125G disk:<br />
<a href="http://www.cod3r.com/images/2010/04/Step-6.png"><img src="http://www.cod3r.com/images/2010/04/Step-6-300x171.png" alt="" title="Step 6" width="300" height="171" class="aligncenter size-medium wp-image-340" /></a><br />
Now we are done, and can disconnect the 125G disk if not done already.  In this example, the green raid has changed from 375G to 750G, yielding a total change of 875G to 1500G.</p>
<p><strong>Note:</strong> There is one limitation with this structure.  Ordering the disks in increasing size, disk(n) must be at least as big as 2*(disk(n-1))-disk(n-2).  This essentially means that if a disk is xG bigger than it&#8217;s previous disk, then the next disk must be at least xG bigger than this disk.  Since disk sizes tend to grow exponentially, this assumption shouldn&#8217;t be much of a problem since the requirement is at least linear growth.</p>
<p>The disk sizes in this example meet the requirement I listed above.  Given the requirements of this expansion, the disk added in this example must be at least 1000G, since disk 4 is 250G bigger than disk 3, disk 5 must be at least 250G bigger than disk 4, or 1000G.</p>
<p>This technique also allows adding another disk, under the same conditions.  Consider adding a 1T disk and creating another Raid-Z:<br />
<a href="http://www.cod3r.com/images/2010/04/Add-Disk.png"><img src="http://www.cod3r.com/images/2010/04/Add-Disk-300x171.png" alt="" title="Add Disk" width="300" height="171" class="aligncenter size-medium wp-image-341" /></a><br />
I didn&#8217;t structure the partitions in nice pretty rows to demonstrate the fact that not all of the data needs to be moved (in this case, 750G of data is not moved).  In this example, the capacity increased from 875G to 1625G, again the theoretical capacity.</p>
<p>Anyway, I thought of this while considering using ZFS/Raid-Z in a <a href="http://freenas.org">FreeNAS</a> setup.  I haven&#8217;t tested any of this; it&#8217;s theoretical only.  What do you think?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cod3r.com/2010/04/zfs-on-different-sized-disks/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Common Media Player Framework</title>
		<link>http://www.cod3r.com/2010/02/common-media-player-framework/</link>
		<comments>http://www.cod3r.com/2010/02/common-media-player-framework/#comments</comments>
		<pubDate>Sat, 27 Feb 2010 19:27:43 +0000</pubDate>
		<dc:creator>Graham Booker</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.cod3r.com/?p=292</guid>
		<description><![CDATA[About 3 weeks ago, Kevin (developer of NitoTV) and I decided it was a bit silly how we were each writing playback mechanisms on the AppleTV with little to no collaboration between us. So, we decided to write a Common Media Player Framework, which is licensed using LGPL. Kevin sent me the code he used [...]]]></description>
			<content:encoded><![CDATA[<p>About 3 weeks ago, Kevin (developer of <a href="http://wiki.awkwardtv.org/wiki/NitoTV">NitoTV</a>) and I decided it was a bit silly how we were each writing playback mechanisms on the AppleTV with little to no collaboration between us.  So, we decided to write a Common Media Player Framework, which is licensed using LGPL.</p>
<p>Kevin sent me the code he used for DVD playback inside NitoTV as a place to start.  I stripped it down to a smaller piece, and started the framework.  After I had it doing basic playback, I worked on overlays to provide feedback to the user.  Now, hitting up and down changes the overlays between normal, chapter view, audio/subtitle selection, and zoom.<br />
<div id="attachment_294" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.cod3r.com/images/2010/02/Chapter-Overlay.png"><img src="http://www.cod3r.com/images/2010/02/Chapter-Overlay-300x168.png" alt="" title="Chapter Overlay" width="300" height="168" class="size-medium wp-image-294" /></a><p class="wp-caption-text">Chapter Overlay Sceenshot</p></div></p>
<p>Also, I added a pretty menu using a blurred image as the resume menu.  This is more consistent with Apple&#8217;s own playback<br />
<div id="attachment_296" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.cod3r.com/images/2010/02/Resume-Overlay.png"><img src="http://www.cod3r.com/images/2010/02/Resume-Overlay-300x168.png" alt="" title="Resume Overlay" width="300" height="168" class="size-medium wp-image-296" /></a><p class="wp-caption-text">Resume Overlay</p></div></p>
<p>In addition, I used my work on AC3 Passthrough in <a href="http://www.perian.org">Perian</a> to see if I could pull off the same in DVD Playback.  The issue is the AppleTV claims to only have a device which can play uncompressed audio, not one that can send Dolby Digital to a decoder.  So, I created an audio driver that claims to do exactly that and pipe the data through to the optical/HDMI port.  It was a lot of fun getting that working, and then I added support for DTS.</p>
<p>Anyway, now <a href="http://appletv.nanopi.net/">Sapphire</a> uses the common media player framework for DVD playback.  In the future, we&#8217;ll add other playback mechanisms as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cod3r.com/2010/02/common-media-player-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Passed My Defense</title>
		<link>http://www.cod3r.com/2010/02/passed-my-defense/</link>
		<comments>http://www.cod3r.com/2010/02/passed-my-defense/#comments</comments>
		<pubDate>Sat, 13 Feb 2010 00:29:44 +0000</pubDate>
		<dc:creator>Graham Booker</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.cod3r.com/?p=290</guid>
		<description><![CDATA[I haven&#8217;t posted here in a while, and with good reason. About two weeks ago, I passed my Ph.D. defense. So, come May, I will officially have a doctorate in Computer Engineering, though I am effectively done with my degree.]]></description>
			<content:encoded><![CDATA[<p>I haven&#8217;t posted here in a while, and with good reason.  About two weeks ago, I passed my Ph.D. defense.  So, come May, I will officially have a doctorate in Computer Engineering, though I am effectively done with my degree.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cod3r.com/2010/02/passed-my-defense/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Incorrect Podcast Order on my iPod</title>
		<link>http://www.cod3r.com/2009/09/incorrect-podcast-order-on-my-ipod/</link>
		<comments>http://www.cod3r.com/2009/09/incorrect-podcast-order-on-my-ipod/#comments</comments>
		<pubDate>Thu, 10 Sep 2009 23:00:05 +0000</pubDate>
		<dc:creator>Graham Booker</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.cod3r.com/?p=279</guid>
		<description><![CDATA[One of these days I will learn not to grab the latest and &#8220;greatest&#8221; software the moment it comes out. Yesterday, I upgraded my iTunes to version 9 and my iPod Touch&#8217;s firmware to 3.1.1. Then, I noticed that one of my podcasts was out of order, and furthermore, the release date was no longer [...]]]></description>
			<content:encoded><![CDATA[<p>One of these days I will learn not to grab the latest and &#8220;greatest&#8221; software the moment it comes out.  Yesterday, I upgraded my iTunes to version 9 and my iPod Touch&#8217;s firmware to 3.1.1.  Then, I noticed that one of my podcasts was out of order, and furthermore, the release date was no longer showing up on the iPod itself.  Strangely, only one podcast was having this issue.</p>
<p>I started to suspect that this was my fault, since this one podcast, <a href="http://escapepod.org/">Escape Pod</a> was a podcast I was listening by going through its archives.  I had written a program which downloads the archived episodes, and modifies the ID3 tags so iTunes will properly recognize the file as a podcast and insert it into its database as if it had downloaded it itself.  Getting the release date working correctly was one of the harder points, so I figured that I still didn&#8217;t have it quite correct and the new iPod firmware was being more sensitive to it.  I got even more annoyed by the fact that iTunes, after upgrading my iPod&#8217;s firmware, decided to trash the old firmware versions preventing me from ever downgrading.</p>
<p>Then, I read online discussions where others were having this problem.  Now I know that it is not my fault, but rather something that Apple screwed up.  I also saw someone who noted that they had upgraded their iTunes, but not their iPod, and had the same issue.  So, I trashed iTunes, pulled out my Snow Leopard disk, found the iTunes package on the disk, installed it, reverted my iTunes library to the backup prior to the upgrade, and voila, my podcasts are sorting correctly again.</p>
<p>Now if only I will learn to let others try first, and upgrade myself after reading their reports.  This is a really sloppy bug on Apple&#8217;s part, and likely means that iTunes 9 was rush.  I&#8217;m actually happier back on 8, especially since the window zoom still functions as a toggle between the mini player and the normal window, which was changed in 9.</p>
<p>Hopefully someone will benefit from this post, and not upgrade to iTunes 9 until this regression is resolved.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cod3r.com/2009/09/incorrect-podcast-order-on-my-ipod/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Text Compression Techniques</title>
		<link>http://www.cod3r.com/2009/07/text-compression-techniques/</link>
		<comments>http://www.cod3r.com/2009/07/text-compression-techniques/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 22:17:20 +0000</pubDate>
		<dc:creator>Graham Booker</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.cod3r.com/?p=264</guid>
		<description><![CDATA[A friend of mine develops on an Bible application for the iPhone, BibleXpress. Since his application includes several translations with the app, he once mentioned to me the possibility of compressing them to save space. Any compression that is done must achieve a good ratio, but more importantly, decompression must be fast. I took it [...]]]></description>
			<content:encoded><![CDATA[<p>A friend of mine develops on an Bible application for the iPhone, <a href="http://www.biblexpress.com/">BibleXpress</a>.  Since his application includes several translations with the app, he once mentioned to me the possibility of compressing them to save space.  Any compression that is done must achieve a good ratio, but more importantly, decompression must be fast.  I took it upon myself to find a compression algorithm that could fit the bill.</p>
<p>In my test case, I worked with the NASB translation of the Bible.  The raw text of this translation, minus formatting and book/chapter/verse identifiers is 3.965MB.  Since the iPhone already has zlib, using gzip compression is an obvious choice.  When compressed with gzip, the file size becomes 1.189MB, a significant savings.  Even though bzip2 is not readily available on the iPhone (at least not that I could find), I tested its compression which produced a file size of 0.8548MB.  While these mechanisms provide a significantly smaller file, when one desires a certain portion of the file, one must first decompress the entire file up to that point.  This is an expensive operation on a small device such as the iPhone.</p>
<p>One compromise is to compress each book individually.  This yields a file size of 1.242MB.  However, some books, such as Psalms, are still quite large, requiring a long decompression operation to read some of it&#8217;s chapters.  Since the application displays a chapter at a time, a logical compression block would be a single chapter which yields a file size of 1.628MB.  While this is a large increase in file size, a single chapter can be decompressed without requiring decompression of any other parts of the file.</p>
<p>I was not happy with these compression ratios and was determined to find a better way.  I looked into Huffman encoding, which uses a variable length string of bits to represent a symbol.  Its compression ratio does not change with the order of symbols, which typically means it won&#8217;t provide as high a compression ratio.  However, if you are told which bit is the start of a string, you may begin decompression without examining any of the file which precedes it.  In addition, the decompression scheme only requires walking a binary tree, which means it is also quite fast.  So, if Huffman encoding can be made to provide a good compression ratio, it will work well for this problem.</p>
<p>When using Huffman encoded, the question becomes how to decompose the string into symbols.  One typical decomposition is to make each character into a symbol.  While this is an easy representation, it doesn&#8217;t provide a good compression ratio.  Instead, I chose to make each word into a symbols.  After adding in punctuation, the tree contained 16,246 words.  This resulted in a dictionary size of 0.1364MB.  When compressed, the entire Bible was represented by a Huffman encoding of 0.9947MB, meaning a total of 1.131MB for the compressed stream and dictionary.</p>
<p>After this experiment, I concluded that Huffman encoding of words is the best for a large quantity of text.  It yielded a compression ratio that was better than gzip (though not as good as bzip2), but at the same time a scheme that could decompress individual parts of the file without having to read preceding parts.  In this scheme, a single chapter can be decompressed very quickly, and still have a high compression ratio.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cod3r.com/2009/07/text-compression-techniques/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>New Car</title>
		<link>http://www.cod3r.com/2009/07/new-car/</link>
		<comments>http://www.cod3r.com/2009/07/new-car/#comments</comments>
		<pubDate>Tue, 28 Jul 2009 22:33:22 +0000</pubDate>
		<dc:creator>Graham Booker</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.cod3r.com/?p=256</guid>
		<description><![CDATA[Well, after much hassle, I now have a new car. Here are some pictures: The whole ordeal was mostly due to the CARS program, which is often known by &#8220;Cash for Clunkers&#8221;. Anyway, I finally got that resolved and got a lot more for my old truck than I would have ever gotten in trade-in [...]]]></description>
			<content:encoded><![CDATA[<p>Well, after much hassle, I now have a new car.  Here are some pictures:<br />
<a href="http://www.cod3r.com/images/2009/07/New-Car-Front.jpg"><img src="http://www.cod3r.com/images/2009/07/New-Car-Front-300x200.jpg" alt="New Car Front" title="New Car Front" width="300" height="200" class="alignnone size-medium wp-image-258" /></a><br />
<a href="http://www.cod3r.com/images/2009/07/New-Car-Side.jpg"><img src="http://www.cod3r.com/images/2009/07/New-Car-Side-300x200.jpg" alt="New Car Side" title="New Car Side" width="300" height="200" class="alignnone size-medium wp-image-259" /></a></p>
<p>The whole ordeal was mostly due to the <a href="http://www.cars.gov">CARS</a> program, which is often known by &#8220;Cash for Clunkers&#8221;.  Anyway, I finally got that resolved and got a lot more for my old truck than I would have ever gotten in trade-in value.  So now I have a VW Jetta, and so far I&#8217;m happy with it.  I just need to get used to driving a car instead of a truck, but otherwise it drives well.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cod3r.com/2009/07/new-car/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using Newer Subversion in Xcode</title>
		<link>http://www.cod3r.com/2009/07/using-newer-subversion-in-xcode/</link>
		<comments>http://www.cod3r.com/2009/07/using-newer-subversion-in-xcode/#comments</comments>
		<pubDate>Sat, 25 Jul 2009 20:05:47 +0000</pubDate>
		<dc:creator>Graham Booker</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.cod3r.com/?p=251</guid>
		<description><![CDATA[I use MacPorts to get a whole host of utilities. In addition, I&#8217;ve always used it to obtain later versions of subversion that the one provided with the OS. Xcode, on the other hand, is locked into using the version of Subversion which is installed in /usr (currently version 1.4.4 where as I have 1.6.3). [...]]]></description>
			<content:encoded><![CDATA[<p>I use <a href="http://www.macports.org/">MacPorts</a> to get a whole host of utilities.  In addition, I&#8217;ve always used it to obtain later versions of subversion that the one provided with the OS.  Xcode, on the other hand, is locked into using the version of Subversion which is installed in /usr (currently version 1.4.4 where as I have 1.6.3).  Since I often work in the command line, eventually I will use the newer version of Subversion on a directory which I also use in Xcode.  This causes a problem since the command line utility will upgrade the local repository format in such a way that old versions of Subversion (Xcode&#8217;s) cannot use it.</p>
<p>So, my options are:</p>
<ul>
<li>Only use the command line utility, or use Xcode, on a single repository checkout, but never both.</li>
<li>Use a horribly out of date version of Subversion</li>
<li>Hack Xcode&#8217;s plugin to work with newer versions of Subversion</li>
</ul>
<p>I chose the last, as it should give me the best of both worlds.  If you were to conduct a quick Google search, you would find a whole host of people posing a solution which involves <strong>moving around system libraries</strong>!!!!!  This is a horrible idea, as it breaks other things such as Apache.  Buried somewhere in the sea of bad ideas, I ran across a good one, written by <a href="http://lists.apple.com/archives/Xcode-users//2008/Sep/msg00525.html">Jean-Daniel Dupas and improved by Philippe Casgrain</a> which only changes the path location of libraries used by Xcode&#8217;s Subversion plugin.  This script worked well for Subversion 1.5, but recent versions of Subversion would cause Xcode to crash in libapr.  The solution is to add libapr and libaprutil to the script.  Here is the corrected script for your use.<br />
<code><br />
#!/bin/sh</p>
<p>if [ "$#" -lt "2" ]<br />
then<br />
  echo "Usage: xcode-svn-update.sh
<path to XcodeSubversionPlugin>
<path to svn base folder>"<br />
  echo "Example: xcode-svn-update.sh /Developer/Library/Xcode/Plug-<br />
ins/\c"<br />
  echo "XcodeSubversionPlugin.xcplugin/Contents/MacOS/<br />
XcodeSubversionPlugin /opt/local"<br />
  exit 1;<br />
fi</p>
<p># Save a backup copy, if necessary<br />
if [ -e "$1_Old" ]<br />
then<br />
  echo "Backup copy of \"$1\" exists."<br />
else<br />
  echo "Saving a backup copy of \"$1\"."<br />
  cp "$1" "$1_Old"<br />
fi</p>
<p>echo "Updating install path using svn libraries in \"$2\"..."<br />
install_name_tool -change \<br />
  /usr/lib/libapr-1.0.dylib \<br />
  $2/lib/libapr-1.0.dylib "$1"<br />
install_name_tool -change \<br />
  /usr/lib/libaprutil-1.0.dylib \<br />
  $2/lib/libaprutil-1.0.dylib "$1"<br />
install_name_tool -change \<br />
  /usr/lib/libsvn_client-1.0.dylib \<br />
  $2/lib/libsvn_client-1.0.dylib "$1"<br />
install_name_tool -change \<br />
  /usr/lib/libsvn_delta-1.0.dylib \<br />
  $2/lib/libsvn_delta-1.0.dylib "$1"<br />
install_name_tool -change \<br />
  /usr/lib/libsvn_diff-1.0.dylib \<br />
  $2/lib/libsvn_diff-1.0.dylib "$1"<br />
install_name_tool -change \<br />
  /usr/lib/libsvn_fs_fs-1.0.dylib \<br />
  $2/lib/libsvn_fs_fs-1.0.dylib "$1"<br />
install_name_tool -change \<br />
  /usr/lib/libsvn_fs-1.0.dylib \<br />
  $2/lib/libsvn_fs-1.0.dylib "$1"<br />
install_name_tool -change \<br />
  /usr/lib/libsvn_ra_local-1.0.dylib \<br />
  $2/lib/libsvn_ra_local-1.0.dylib "$1"<br />
install_name_tool -change \<br />
  /usr/lib/libsvn_ra_svn-1.0.dylib \<br />
  $2/lib/libsvn_ra_svn-1.0.dylib "$1"<br />
install_name_tool -change \<br />
  /usr/lib/libsvn_ra-1.0.dylib \<br />
  $2/lib/libsvn_ra-1.0.dylib "$1"<br />
install_name_tool -change \<br />
  /usr/lib/libsvn_repos-1.0.dylib \<br />
  $2/lib/libsvn_repos-1.0.dylib "$1"<br />
install_name_tool -change \<br />
  /usr/lib/libsvn_subr-1.0.dylib \<br />
  $2/lib/libsvn_subr-1.0.dylib "$1"<br />
install_name_tool -change \<br />
  /usr/lib/libsvn_wc-1.0.dylib \<br />
  $2/lib/libsvn_wc-1.0.dylib "$1"<br />
echo "Done!"<br />
</code></p>
<p>Now, how long till Xcode supports <a href="http://mercurial.selenic.com/wiki/">Mercurial</a>?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cod3r.com/2009/07/using-newer-subversion-in-xcode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
