<?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>Canned Platypus</title>
	<atom:link href="http://pl.atyp.us/wordpress/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://pl.atyp.us/wordpress</link>
	<description>Saving the world one byte at a time since 2000</description>
	<lastBuildDate>Fri, 27 Apr 2012 14:04:05 +0000</lastBuildDate>
	<language>en-us</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Git Tricks</title>
		<link>http://pl.atyp.us/wordpress/index.php/2012/04/git-tricks/</link>
		<comments>http://pl.atyp.us/wordpress/index.php/2012/04/git-tricks/#comments</comments>
		<pubDate>Fri, 27 Apr 2012 14:04:05 +0000</pubDate>
		<dc:creator>Jeff Darcy</dc:creator>
				<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://pl.atyp.us/wordpress/?p=3485</guid>
		<description><![CDATA[I was just talking to a coworker about a couple of things I did a while back to make working with git a little less painful, so I figured I might as well share them with everyone. The first is a post-checkout script, to regenerate cscope information any time a new branch is checked out. [...]]]></description>
			<content:encoded><![CDATA[<p>I was just talking to a coworker about a couple of things I did a while back to make working with git a little less painful, so I figured I might as well share them with everyone.</p>
<p>The first is a <a href="/scripts/post-checkout">post-checkout script</a>, to regenerate cscope information any time a new branch is checked out.  Just put this in $your_git_tree/.git/hooks to use it.  If anybody knows how to make this global instead of per-tree, or how to do the same thing for every other git operation that might add/remove source files in your tree, please let me know.</p>
<p>The second is a <a href="/scripts/pwd_with_branch">window-title script</a> which will check to see if you&#8217;re in a git tree and, if so, add the current branch to the current directory.  For example, my PROMPT_COMMAND looks like this.</p>
<blockquote><p>&#8216;printf &#8220;\033]0;%s@%s:%s\007&#8243; &#8220;${USER}&#8221; &#8220;${HOSTNAME%%.*}&#8221; &#8220;$(pwd_with_branch)&#8221;&#8216;</p></blockquote>
<p>As a result, one of my window titles now looks like this.</p>
<blockquote><p>jdarcy@jdarcy-dt:~/projects/glusterfs_github (hsrepl)</p></blockquote>
<p>Here, &#8220;hsrepl&#8221; is the name of the branch I&#8217;m currently working on.  You could just as easily use this to set your command prompt instead of your window title if you were so inclined.</p>
<p>Enjoy, and patches welcome.  ;)</p>
]]></content:encoded>
			<wfw:commentRss>http://pl.atyp.us/wordpress/index.php/2012/04/git-tricks/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Patch Based Filesystem</title>
		<link>http://pl.atyp.us/wordpress/index.php/2012/04/patch-based-filesystem/</link>
		<comments>http://pl.atyp.us/wordpress/index.php/2012/04/patch-based-filesystem/#comments</comments>
		<pubDate>Tue, 10 Apr 2012 18:47:52 +0000</pubDate>
		<dc:creator>Jeff Darcy</dc:creator>
				<category><![CDATA[uncategorized]]></category>

		<guid isPermaLink="false">http://pl.atyp.us/wordpress/?p=3472</guid>
		<description><![CDATA[Even when I&#8217;m happy with my current project, I often like to think about alternative solutions to the same basic set of distributed-data problems that are my area of expertise. So it is with GlusterFS. I think that&#8217;s on a good track, with a robust set of features already and a clear path to being [...]]]></description>
			<content:encoded><![CDATA[<p>Even when I&#8217;m happy with my current project, I often like to think about alternative solutions to the same basic set of distributed-data problems that are my area of expertise.  So it is with GlusterFS.  I think that&#8217;s on a good track, with a robust set of features already and a clear path to being the best available solution for an even broader area, but . . . there&#8217;s always a &#8220;but&#8221; isn&#8217;t there?  As I&#8217;ve worked on GlusterFS for the last few years, there have been certain patterns of problems and feature additions that have proven unexpectedly difficult.  A lot of these come down to the issue of write granularity and conflicting simultaneous writes.  For example, what if two HekaFS clients using block-based encryption try to write different parts of the same cipher block at the same time?  They&#8217;re not conflicting from the user&#8217;s point of view, so one shouldn&#8217;t be allowed to undo the other, but they are conflicting in the sense that every byte written affects every byte of that cipher block.  It&#8217;s impossible to merge the two writes without keys, and of course the server can&#8217;t have keys in our model.  Erasure coding runs into much the same problem.  In both cases, the solution is to serialize the read-modify-write sequences used for partial writes.  We can have all sorts of fun with various optimistic locking schemes and so on, but the net result is still a bit sad.  When these issues are considered in the context of asynchronously replicating those writes across geographic locations, things become even uglier . . . and that&#8217;s the train of thought leading to this post.  Is there a fundamentally different approach, absolutely infeasible to implement within GlusterFS, that would handle this combination (async replication plus erasure coding plus encryption) more gracefully?  If I were to design such a system from the ground up, here&#8217;s what it might look like.  While I&#8217;m at it, I&#8217;ll throw in some other ideas that aren&#8217;t really related to this fundamental problem, just for fun.</p>
<ul>
<li>Would I even want the result to be a filesystem?  I&#8217;ve often said that one of the reasons I got involved with GlusterFS was because I really didn&#8217;t want to develop an entire filesystem, and I still feel that way.  There&#8217;s tremendous value in the result, but if I were to do something on my own maybe I&#8217;d go for something less complicated.  Object (or &#8220;blob&#8221;) stores like S3 or Swift are about twenty times easier to implement, and many people seem willing to adopt them instead of filesystems, so maybe I&#8217;d do that.  With things like HTTP <a href="http://tools.ietf.org/html/rfc5789">PATCH</a> coming along I&#8217;d still have to deal with overlapping byte-aligned writes within a file/object (I&#8217;m just going to say &#8220;file&#8221; from here on for simplicity), but that&#8217;s OK.</li>
<li>Distribution would still be based on consistent hashing.  I have many of my own favorite tweaks in this area, most of which are equally applicable to GlusterFS and PBFS.</li>
<li>The first major change I&#8217;d make is to get out of the business of dealing with cluster membership and consensus with respect to configuration myself.  There&#8217;s other software available to do just that, so there&#8217;s no need to implement an inferior home-grown version or put up with its deficiencies.</li>
<li>The other major change would be a move from a &#8220;write in place&#8221; model to more of a log-structured or &#8220;event sourcing&#8221; model.  When a client writes data, the entire write is encrypted and erasure coded according to its own internal alignment, regardless of how it&#8217;s aligned with respect to the file.  The pieces are then distributed among the servers responsible for that file.  Voila, no more server-side merging or read-modify-write sequences.</li>
<li>As pieces of the write&#8217;s contents are being written to several servers, information about the write as a whole is fully replicated to a smaller set of servers.  Any one of these &#8220;catalog&#8221; servers can then, when asked about that write, identify which servers got erasure fragments and also provide any authentication/integrity metadata necessary to validate the combined result.</li>
<li>Since the entire write is maintained as a single unit, that unit can be transmitted verbatim to another site.  It can even be erasure-coded differently on that end, to satisfy different requirements e.g. at a primary vs. DR site.  This simplifies matters greatly compared to approaches that require writes to be merged somehow before being propagated.</li>
<li>As with other patch-based systems as they&#8217;re well known and understood in the source-control world, the merging happens on the client side during reads.  To read a byte range within a file, you ask one of its catalog servers for <b>all</b> current writes overlapping that range.  What you get back is potentially a list of writes, with extent and ordering information.    It&#8217;s up to you to decrypt and merge to get the bytes you need.  In some cases, it would make sense to re-encrypt and write back the results so that the next reader only gets a single chunk, but that&#8217;s optional.  In that case, the write-back might cause some or all of the previous chunks to be marked as no longer current and (eventually) garbage-collected.</li>
</ul>
<p>As I&#8217;m sure you can see, this is a very different kind of animal than GlusterFS &#8211; or, for that matter, any other distributed filesystem.  Both the read and write paths are fundamentally different.  Writes can be significantly more efficient, but reads are more complicated and rely more on high scale to deliver good aggregate performance.  It would certainly be an interesting exercise, if only I had time&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://pl.atyp.us/wordpress/index.php/2012/04/patch-based-filesystem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Coding Metaphor: The Dangerous Room</title>
		<link>http://pl.atyp.us/wordpress/index.php/2012/03/coding-metaphor-the-dangerous-room/</link>
		<comments>http://pl.atyp.us/wordpress/index.php/2012/03/coding-metaphor-the-dangerous-room/#comments</comments>
		<pubDate>Sun, 11 Mar 2012 14:58:00 +0000</pubDate>
		<dc:creator>Jeff Darcy</dc:creator>
				<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://pl.atyp.us/wordpress/?p=3456</guid>
		<description><![CDATA[I came up with this little parable about coding in complex systems. Warning: it&#8217;s a bit graphic. Imagine you have a remote view of an ordinary room, with doors at each end. You see a man enter at one end. He crosses to the other end, pausing a couple of times and once stooping to [...]]]></description>
			<content:encoded><![CDATA[<p>I came up with this little parable about coding in complex systems.  Warning: it&#8217;s a bit graphic.</p>
<blockquote><p>Imagine you have a remote view of an ordinary room, with doors at each end.  You see a man enter at one end.  He crosses to the other end, pausing a couple of times and once stooping to examine something on the floor, then exits at the other end.  There seems to be nothing remarkable about this.  Then you watch a second man try to cross the room.  When he gets half-way across, panels in the walls slide down and the man is skewered with arrows from several hidden crossbows.  The screen flickers.  A third man tries to cross, and doesn&#8217;t even get a quarter of the way across before a green gas seeps from vents near the ceiling and he collapses.  The screen flickers again.  After you watch a score more of failed attempts to cross the room, the smoke from the latest explosion reveals something: the room is criss-crossed with beams of light, some of which turn on and off, and it&#8217;s when people cross these beams that Bad Things happen.  You think back to the first man, and realize that he might crossed in the only possible safe way.  You briefly consider that he was lucky, but it&#8217;s just too implausible.  It&#8217;s much more likely that he knew exactly what he was doing, that his pauses and stooping were carefully calculated to avoid the various traps.  Only then do you realize how skillful his performance was.</p></blockquote>
<p>Yeah, I know, it&#8217;s like those &#8220;ninja&#8221; metaphors that I usually consider so childish.  I was going to try something less colorful, but Amy happened to overhear this little story as I was trying it out on Cindy, and she keeps asking me to tell it again, so maybe being childish isn&#8217;t so bad.  Anyway, the point is that working on a very complex system (such as I do on GlusterFS) can be a bit like crossing that room.  The code contains all sorts of hidden traps for the unwary.  I&#8217;ve taken my share of arrows in the knee, that&#8217;s for sure (and now you know what inspired the metaphor).  Usually you have to go through many iterations of being that second or third or tenth person before you have a day where you feel like that first one.  You know all of the non-obvious requirements and constraints (traps) between you and what you&#8217;re trying to accomplish.  Maybe you even relax (disarm) a couple, but mostly you just do the delicate dance around them and get to the point where your new feature works (get out alive).  Then somebody watching says, &#8220;Pffft, you just walked across a room.  What&#8217;s hard about that?&#8221;  That&#8217;s why people who have learned &#8211; the hard way &#8211; how to bend a piece of code in ways it wasn&#8217;t originally intended to bend sometimes seem intolerant of dabblers&#8217; or onlookers&#8217; commentary.  That&#8217;s one of the reasons I stuck with this metaphor: the complexity is hidden.  I thought of using a different metaphor of a complex mechanism with many levers and such, but anyone seeing such a mechanism would realize it&#8217;s complex.  In this case, you could watch the first man cross the room a hundred times and never realize he was engaged in a complex task.</p>
<p>If there&#8217;s a moral here, it&#8217;s twofold.  First, don&#8217;t assume something&#8217;s easy just because you see someone do it without mishap or obvious effort.  They might be applying a great deal of hard-won knowledge to make things go so smoothly.  Second, when you&#8217;re attempting to do something in a complex environment, expect that you&#8217;ll get killed a few times.  Respect the dangers, but don&#8217;t be afraid of them.  You can always reload from your last save.  Each time you find a trap, you learn.  After enough tries, you might find a way to avoid them all, and the result might even be more satisfying than if things had been easy to begin with.</p>
]]></content:encoded>
			<wfw:commentRss>http://pl.atyp.us/wordpress/index.php/2012/03/coding-metaphor-the-dangerous-room/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Yak Electrolysis</title>
		<link>http://pl.atyp.us/wordpress/index.php/2012/01/yak-electrolysis/</link>
		<comments>http://pl.atyp.us/wordpress/index.php/2012/01/yak-electrolysis/#comments</comments>
		<pubDate>Thu, 05 Jan 2012 16:27:41 +0000</pubDate>
		<dc:creator>Jeff Darcy</dc:creator>
				<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://pl.atyp.us/wordpress/?p=3413</guid>
		<description><![CDATA[While I was reviewing a patch yesterday, I found code that used lots of distinct directory names for a series of tests &#8211; test1 would use brick1 and brick2, test2 would use brick3 and brick4, etc. I&#8217;ve run into this pattern myself, and it can be a bit of a maintenance problem as tests are [...]]]></description>
			<content:encoded><![CDATA[<p>While I was reviewing a patch yesterday, I found code that used lots of distinct directory names for a series of tests &#8211; test1 would use brick1 and brick2, test2 would use brick3 and brick4, etc.  I&#8217;ve run into this pattern myself, and it can be a bit of a maintenance problem as tests are added or removed.  For example, in the test scripts for iwhd, there were multiple occasions when adding a test led to accidental reuse of names, and much non-hilarity ensued (everything about that project was non-hilarious but that&#8217;s a story for another time).  The simplest pattern to deal with this is something like the following, which I suggested in a review comment:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">sequence</span>=<span style="color: #000000;">0</span>
...
<span style="color: #666666; font-style: italic;"># Test 1</span>
<span style="color: #007800;">sequence</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#40;</span>sequence+<span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #007800;">srcdir</span>=<span style="color: #000000; font-weight: bold;">/</span>foo<span style="color: #000000; font-weight: bold;">/</span>bar<span style="color: #007800;">$sequence</span>
<span style="color: #007800;">sequence</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#40;</span>sequence+<span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #007800;">dstdir</span>=<span style="color: #000000; font-weight: bold;">/</span>foo<span style="color: #000000; font-weight: bold;">/</span>bar<span style="color: #007800;">$sequence</span>
...
<span style="color: #666666; font-style: italic;"># Test 2</span>
<span style="color: #007800;">sequence</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#40;</span>sequence+<span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #007800;">thedir</span>=<span style="color: #000000; font-weight: bold;">/</span>foo<span style="color: #000000; font-weight: bold;">/</span>bar<span style="color: #007800;">$sequence</span></pre></div></div>

<p>This works pretty well, but the inline manipulation of $sequence kind of bugged me so I tried to put it in a function.  My first try looked something like this.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">sequence</span>=<span style="color: #000000;">0</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> next_value <span style="color: #7a0874; font-weight: bold;">&#123;</span>
    <span style="color: #007800;">sequence</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#40;</span>sequence+<span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
    <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$sequence</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #007800;">thedir</span>=<span style="color: #000000; font-weight: bold;">/</span>foo<span style="color: #000000; font-weight: bold;">/</span>bar<span style="color: #000000; font-weight: bold;">/</span>$<span style="color: #7a0874; font-weight: bold;">&#40;</span>next_value<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>Yeah, I hear the laughter.  For those who didn&#8217;t get the joke yet, this falls prey to bash&#8217;s handling of variable scope and subshells.  The $(next_value) construct ends up getting executed in a subshell, so changes it makes to variables aren&#8217;t reflected in the parent and you end up with the same value every time.  I really should have stopped there, satisfying myself with the original inline version.  Sure, that version can still hit the scope/subshell issue, but only if you use functions in your own code and not as a side effect of the idiom itself.  I realized that getting around the scope/subshell issue would involve something ugly and inefficient, which is why I should have stopped, but I was intrigued.  Surely, I thought, there should be a way to do this in an encapsulated and yet robust way.  The first idea was to stick the persistent context in a temporary file.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">tmpfile</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>my_secure_tmpfile_generator<span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> next_value <span style="color: #7a0874; font-weight: bold;">&#123;</span>
    <span style="color: #007800;">prev_value</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #007800;">$tmpfile</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
    <span style="color: #007800;">next_value</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#40;</span>prev_value+<span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
    <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$next_value</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #007800;">$tmpfile</span>
    <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$next_value</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>OK, it&#8217;s kind of icky, but it should work.  Again, I should have stopped there, but that temporary file bothered me.  Surely I could do that without the file I/O, perhaps by spawning a subprocess and talking to that through a pipe.  Yes, folks, I had embarked on a quest to find the most insanely complicated way to solve a pretty simple problem.  The result is <a href="/scripts/generator.sh">generator.sh</a> and here&#8217;s an example of how to use it.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">source</span> generator.sh
start_generator int_generator <span style="color: #000000;">5</span> <span style="color: #000000;">6</span>
...
<span style="color: #007800;">dir1</span>=<span style="color: #000000; font-weight: bold;">/</span>foo<span style="color: #000000; font-weight: bold;">/</span>bar$<span style="color: #7a0874; font-weight: bold;">&#40;</span>next_value <span style="color: #000000;">5</span> <span style="color: #000000;">6</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #007800;">dir2</span>=<span style="color: #000000; font-weight: bold;">/</span>foo<span style="color: #000000; font-weight: bold;">/</span>bar$<span style="color: #7a0874; font-weight: bold;">&#40;</span>next_value <span style="color: #000000;">5</span> <span style="color: #000000;">6</span><span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>Doesn&#8217;t look too bad, does it?  OK, now go ahead and look at how it&#8217;s done.  <b>I dare you.</b>  Here are some of the funnier bits.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># start_generator</span>
<span style="color: #007800;">ctop</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">mktemp</span> <span style="color: #660033;">-t</span> <span style="color: #660033;">-u</span> fifoXXXXXX<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #c20cb9; font-weight: bold;">mkfifo</span> <span style="color: #007800;">$ctop</span> <span style="color: #000000; font-weight: bold;">||</span> <span style="color: #007800;">fubar</span>=<span style="color: #000000;">1</span></pre></div></div>

<p>Yes, really.  Not polluting the filesystem with a temporary file was part of the point here, but I ended up dropping not one but two orts instead.  (Cool word, and yes, I did use a thesaurus.)  To be fair, these are only visible in the filesystem momentarily before they&#8217;re opened and then deleted, but still.  I tried to find a way to do this with anonymous pipes, but there just didn&#8217;t <b>quite</b> seem to be a way to get bash to do that right.  Here&#8217;s the next fun bit.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># start_generator</span>
<span style="color: #007800;">$1</span> <span style="color: #000000; font-weight: bold;">&lt;</span> <span style="color: #007800;">$ptoc</span> <span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #007800;">$ctop</span> <span style="color: #000000; font-weight: bold;">&amp;</span>
<span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;exec $2&gt; <span style="color: #007800;">$ptoc</span>&quot;</span>
<span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;exec $3&lt; <span style="color: #007800;">$ctop</span>&quot;</span></pre></div></div>

<p>The first line invokes the subprocess, with input and output fifos.  The two execs are the bash way to create read and write file descriptors for a file.  They&#8217;re wrapped in evals to satisfy my goal of making things as complicated as possible by allowing the caller to specify both the generator function/program and the file descriptors to use.  Eval is very evil, of course, so let&#8217;s play Spot The Security Flaw.
</pre>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">start_generator int_generator <span style="color: #ff0000;">&quot;do_something_evil;&quot;</span>
<span style="color: #666666; font-style: italic;"># ...causes us to eval...</span>
<span style="color: #7a0874; font-weight: bold;">exec</span> do_something_evil;<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #007800;">$ptoc</span></pre></div></div>

<p>I'm not going to fix this, because it's only an "insider" threat.  This code already runs with the same privilege as the caller, and can't do anything the caller can't.  They could also pass in a totally bogus generator function, and I'm not going to worry about that either because they'd only be shooting themselves.  On to the next fun piece.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># next_value</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #c20cb9; font-weight: bold;">more</span> <span style="color: #000000;">1</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #007800;">$1</span>
<span style="color: #c20cb9; font-weight: bold;">read</span> <span style="color: #660033;">-u</span> <span style="color: #007800;">$2</span> x</pre></div></div>

<p>Again, this is kind of standard bash stuff to write and then read from specific file descriptors.  Having an example of this is one of the main reasons I didn't just throw away the script.  With a little bit of tweaking, the same technique could be used as the basis for a general form of IPC to/from a subprocess, and that might be useful some day.</p>
<p>To reiterate: this is some of the craziest code I've ever written.  It's way more complicated than other solutions that better satisfy any likely set of requirements, and the implementation threads its way through some particularly perilous bash minefields.  FFS, I might as well have just used mktemp in the first place and skipped <b>all</b> of this.  You'd have to be nuts to solve this problem this way, but maybe my documentation of the discoveries I made along the way will help someone solve a similar problem.  Or maybe it's just a funny story about bash scripting gone horribly wrong.</p>
]]></content:encoded>
			<wfw:commentRss>http://pl.atyp.us/wordpress/index.php/2012/01/yak-electrolysis/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Scaling Filesystems vs. Other Things</title>
		<link>http://pl.atyp.us/wordpress/index.php/2012/01/scaling-filesystems-vs-other-things/</link>
		<comments>http://pl.atyp.us/wordpress/index.php/2012/01/scaling-filesystems-vs-other-things/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 20:12:23 +0000</pubDate>
		<dc:creator>Jeff Darcy</dc:creator>
				<category><![CDATA[distributed]]></category>
		<category><![CDATA[systems]]></category>

		<guid isPermaLink="false">http://pl.atyp.us/wordpress/?p=3415</guid>
		<description><![CDATA[David Strauss tweeted an interesting comment about using filesystems (actually he said &#8220;block devices&#8221; but I think he really meant filesystems) for scale and high availability. I thought I was following him (I definitely am now) but in fact I saw the comment when it was retweeted by Jonathan Ellis. The conversation went on a [...]]]></description>
			<content:encoded><![CDATA[<p>David Strauss tweeted an interesting comment about using filesystems (actually he said &#8220;block devices&#8221; but I think he really meant filesystems) for scale and high availability.  I thought I was following him (I definitely am now) but in fact I saw the comment when it was retweeted by Jonathan Ellis.  The conversation went on a while, but quickly reached a point where it became impossible to fit even a minimally useful response under 140 characters, so I volunteered to extract the conversation into blog form.</p>
<p>Before I start, I&#8217;d like to point out that I know both David and Jonathan.  They&#8217;re both excellent engineers and excellent people.  I also don&#8217;t know the context in which David originally made his statement.  On the other hand, NoSQL/BigData folks pissing all over things they&#8217;re too lazy to understand has been a bit of a hot button for me lately (e.g. see <a href="/wordpress/index.php/2011/10/stop-the-hate/">Stop the Hate</a>).  So I&#8217;m perfectly willing to believe that David&#8217;s original statement was well intentioned, perhaps a bit hasty or taken out of context, but I also <b>know</b> that others with far less ability and integrity than he has are likely to take such comments even further out of context and use them in their ongoing &#8220;filesystems are irrelevant&#8221; marketing campaign.  So here&#8217;s the conversation so far, rearranged to show the diverging threads of discussion and with some extra commentary from me.</p>
<div style="margin-left: 1cm; background-color: #dddddd">
<div style="margin-left: 0cm"><b>DavidStrauss</b> Block devices are the wrong place scale and do HA. It&#8217;s always expensive (NetApp), unreliable (SPOF), or administratively complex (Gluster).</div>
<p></p>
<div style="margin-left: 1cm"><b>Obdurodon</b> Huh? GlusterFS is *less* administratively complex than e.g. Cassandra. *Far* less. Also, block dev != filesystem.</div>
<p></p>
<div style="margin-left: 1cm"><b>Obdurodon</b> It might not be the right choice for any particular case, but for reasons other than administrative complexity.<br /><i>What reasons, then?  Wrong semantics, wrong performance profile, redundant wrt other layers of the system, etc.  I think David and I probably agree that scale and HA should be implemented in the highest layer of any particular system, not duplicated across layers or pushed down into a lower layer to make it Somebody Else&#8217;s Problem (the mistake made by every project to make the HDFS NameNode highly available).  However, not all systems have the same layers.  If what you need is a filesystem, then the filesystem layer might very well be the right place to deal with these issues (at least as they pertain to data rather than computation).  If what you need is a column-oriented database, that might be the right place.  This is where I think the original very general statement fails, though it seems likely that David was making it in a context where layering two systems had been suggested.</i></div>
<p></p>
<div style="margin-left: 2cm"><b>DavidStrauss</b> GlusterFS is good as it gets but can still get funny under split-brain given the file system approach: http://t.co/nRu1wNqI<br /><i>I was rather amused by David quoting my own answer (to a question on the Gluster community site) back at me, but also a bit mystified by the apparent change of gears.  Wasn&#8217;t this about administrative complexity a moment ago?  Now it&#8217;s about consistency behavior?</i></div>
<p></p>
<div style="margin-left: 3cm"><b>Obdurodon</b> I don&#8217;t think the new behavior (in my answer) is markedly weirder than alternatives, or related to being a filesystem.</div>
<p></p>
<div style="margin-left: 4cm"><b>DavidStrauss</b> It&#8217;s related to it being a filesystem because the consistency model doesn&#8217;t include a natural, guaranteed split-brain resolution.</div>
<p></p>
<div style="margin-left: 5cm"><b>Obdurodon</b> Those &#8220;guarantees&#8221; have been routinely violated by most other systems too. I&#8217;m not sure why you&#8217;d single out just one.<br /><i>I&#8217;ll point out here that Cassandra&#8217;s handling of Hinted Handoff has only very recently reached the standard David seems to be advocating, and was pretty &#8220;funny&#8221; (to use his term) before that.  The other Dynamo-derived projects have also done well in this regard, but other &#8220;filesystem alternatives&#8221; have behavior that&#8217;s too pathetic to be funny.</i></div>
<p></p>
<div style="margin-left: 6cm"><b>DavidStrauss</b> I&#8217;m not singling out Gluster. I think elegant split-brain recovery eludes all distributed POSIX/block device systems.<br /><i>Perhaps this is true of filesystems in practice, but it&#8217;s not inherent in the filesystem model.  I think it has more to do with who&#8217;s working on filesystems, who&#8217;s working on databases, who&#8217;s working on distributed systems, and how people in all of those communities relate to one another.  It just so happens that the convergence of database and distributed-systems work is a bit further along, but I personally intend to apply a lot of the same distributed-system techniques in a filesystem context and I see no special impediment to doing so.</i></div>
<p></p>
<div style="margin-left: 2cm"><b>DavidStrauss</b> #Gluster has also come a long way in admin complexity, but high-latency (geo) replication still requires manual failover.</div>
<p></p>
<div style="margin-left: 3cm"><b>Obdurodon</b> Yes, IMO geosync in its current form is tres lame. That&#8217;s why I still want to do *real* wide-area replication.</div>
<p></p>
<div style="margin-left: 4cm"><b>DavidStrauss</b> Top-notch geo replication requires embracing split-brain as a normal operating mode and having guaranteed, predictable recovery.</div>
<p></p>
<div style="margin-left: 5cm"><b>Obdurodon</b> Agreed wrt geo-replication, but that still doesn&#8217;t support your first general statement since not all systems need that.</div>
<p></p>
<div style="margin-left: 6cm"><b>DavidStrauss</b> Agreed on need for geo-replication, but geo-repl. issues are just an amplified version of issues experienced in any cluster.<br /><i>As I&#8217;ve pointed out before, <a href="/wordpress/index.php/2010/03/replication-ii/">I disagree</a>.  Even systems that do need this feature need not &#8211; and IMO should not &#8211; try to do both local/sync and remote/async replication within a single framework.  They&#8217;re different beasts, most relevantly with respect to split brain being a normal operating mode.  I&#8217;ve spent my share of time pointing out to Stonebraker and other NewSQL folks that partitions really do occur even within a single data center, but they&#8217;re far from being a normal case there and that does affect how one arranges the code to handle it.</i></div>
<p></p>
<div style="margin-left: 0cm"><b>Obdurodon</b> I&#8217;m loving this conversation, but Twitter might not be the right forum. I&#8217;ll extract into a blog post.</div>
<p></p>
<div style="margin-left: 1cm"><b>DavidStrauss</b> You mean complex, theoretical distributed systems issues aren&#8217;t best handled in 140 characters or less? :-)</div>
</div>
<p>I think that about covers it.  As I said, I disagree with the original statement in its general form, but might find myself agreeing with it in a specific context.  As I see it, aggregating local filesystems to provide a single storage pool with a filesystem interface and aggregating local filesystems to provide a single storage pool with another interface (such as a column-oriented database) aren&#8217;t even different enough to say that one is definitely preferable to the other.  The same fundamental issues, and many of the same techniques, apply to both.  Saying that filesystems are the wrong way to address scale is like saying that a magnetic #3 Phillips screwdriver is the wrong way to turn a screw.  Sometimes it is exactly the right tool, and other times the &#8220;right&#8221; tool isn&#8217;t as different from the &#8220;wrong&#8221; tool as its makers would have you believe.</p>
]]></content:encoded>
			<wfw:commentRss>http://pl.atyp.us/wordpress/index.php/2012/01/scaling-filesystems-vs-other-things/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Confessions of a MOO Programmer</title>
		<link>http://pl.atyp.us/wordpress/index.php/2011/12/confessions-of-a-moo-programmer/</link>
		<comments>http://pl.atyp.us/wordpress/index.php/2011/12/confessions-of-a-moo-programmer/#comments</comments>
		<pubDate>Fri, 30 Dec 2011 15:39:57 +0000</pubDate>
		<dc:creator>Jeff Darcy</dc:creator>
				<category><![CDATA[uncategorized]]></category>

		<guid isPermaLink="false">http://pl.atyp.us/wordpress/?p=3407</guid>
		<description><![CDATA[Most people nowadays seem to learn about object-oriented programming via Python or Ruby. Before that it was C++ or Java, and before that Smalltalk or (some flavor of) LISP. My first exposure to object-oriented programming was through none of these, but instead through LambdaMOO. Best known as a persistent multi-user environment, LambdaMOO also had its [...]]]></description>
			<content:encoded><![CDATA[<p>Most people nowadays seem to learn about object-oriented programming via Python or Ruby.  Before that it was C++ or Java, and before that Smalltalk or (some flavor of) LISP.  My first exposure to object-oriented programming was through none of these, but instead through <a href="http://www.moo.mud.org">LambdaMOO</a>.  Best known as a persistent multi-user environment, LambdaMOO also had its own fairly unique programming language.  For one thing, it was prototype-based whereas most other OOP langages tend to be class-based.  This means that you never have to create a class just so you could create one instance.  You just create objects, which can be used directly or (sort of) as a class, or even both.  There is no distinction between virtual and non-virtual methods, nor between static and instance methods, no abstract classes or singleton-pattern nonsense.  You could build almost all of these things yourself, but you don&#8217;t have to conform to just one model.</p>
<p>However, the most interesting thing about MOOcode is its approach to permissions.  Because it was designed to work in a multi-user environment, where users were often neither trusting nor trustworthy but still called each others&#8217; code constantly, MOO needed a pretty robust permissions system.  This was no lame private/protected/public model, without even the concept of an owner and thus without the ability to infer rights based on ownership.  Each object, each &#8220;verb&#8221; and each property has an owner.  The language includes primitives to determine the object for the previous call (<i>caller</i>), the operative permissions in that call (<i>caller_perms</i>), or even the whole call stack (<i>callers</i>).  This lets you implement basically whatever permissions scheme you wanted.  For example, &#8220;caller==this&#8221; is kind of like &#8220;protected&#8221; in C++, and &#8220;caller==#12345&#8243; is kind of like declaring #12345 as a &#8220;friend&#8221; likewise.  At the other extreme, one could go looking further up the stack to see if the current verb is being called in some particular context even if there are multiple &#8220;unexpected&#8221; calls in between.</p>
<p>The most unusual thing about the MOO permission system is that every verb runs with the permissions of its author &#8211; not the user who caused it to be invoked.  This is kind of like every program in UNIX being &#8220;set UID&#8221; by default, which seems crazy but actually works quite well.  It makes most kinds of &#8220;trojan horse&#8221; attacks impossible, for one thing.  The person who has to worry about improper access to data is also the person &#8211; the verb author/owner &#8211; who can add code to prevent it.  The exact workings of MOO property ownership and inheritance were a bit strange sometimes, but most MOO programmers learned the basics and were able to secure their code pretty quickly.</p>
<p>Because of all these features, programming in MOOcode was a very fluid and enjoyable experience.  Python comes closest among the languages I know well, though I&#8217;ve dabbled with Lua and it seems even closer.  If I ever decide to spend time on inventing my own language instead of using one to get something else done, it would probably be a prototype-based OOP language with extra features for concurrency/distribution, and in that context MOO&#8217;s permission model is about as good a starting point as I&#8217;ve seen.  It&#8217;s too bad that most people who could benefit from studying it are probably put off by its origins in a game-like environment.</p>
]]></content:encoded>
			<wfw:commentRss>http://pl.atyp.us/wordpress/index.php/2011/12/confessions-of-a-moo-programmer/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Extracting Data From Quassel</title>
		<link>http://pl.atyp.us/wordpress/index.php/2011/12/extracting-data-from-quassel/</link>
		<comments>http://pl.atyp.us/wordpress/index.php/2011/12/extracting-data-from-quassel/#comments</comments>
		<pubDate>Fri, 09 Dec 2011 17:06:59 +0000</pubDate>
		<dc:creator>Jeff Darcy</dc:creator>
				<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://pl.atyp.us/wordpress/?p=3399</guid>
		<description><![CDATA[Earlier this morning I needed to reconstruct a conversation with someone on an IRC channel, and I don&#8217;t generally keep text logs of IRC activity. However, I do use Quassel, which maintains a substantial backlog for me, and I also happen to know that the backlog is stored in a SQLite3 database. I poked around [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this morning I needed to reconstruct a conversation with someone on an IRC channel, and I don&#8217;t generally keep text logs of IRC activity.  However, I do use <a href="http://quassel-irc.org/">Quassel</a>, which maintains a substantial backlog for me, and I also happen to know that the backlog is stored in a <a href="http://www.sqlite.org/">SQLite3</a> database.  I poked around a bit and figured out enough of the schema to extract the information I wanted.  I&#8217;ll probably need it again so I turned my manual hacking into a script, and other people might need to do the same thing so I&#8217;m publishing the script.  Here it is: <a href="/scripts/convo.py">convo.py</a>.  Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://pl.atyp.us/wordpress/index.php/2011/12/extracting-data-from-quassel/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>When Coding Standards Hurt Quality</title>
		<link>http://pl.atyp.us/wordpress/index.php/2011/11/when-coding-standards-hurt-quality/</link>
		<comments>http://pl.atyp.us/wordpress/index.php/2011/11/when-coding-standards-hurt-quality/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 18:23:43 +0000</pubDate>
		<dc:creator>Jeff Darcy</dc:creator>
				<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://pl.atyp.us/wordpress/?p=3393</guid>
		<description><![CDATA[Most of my work is on code that has &#8220;initialize all local variables at declaration time&#8221; as part of the coding standard. I&#8217;ve never been a big fan, but I&#8217;m very reluctant to get into coding-standard arguments (probably as the result of having had to enforce them for so long) so I just let it [...]]]></description>
			<content:encoded><![CDATA[<p>Most of my work is on code that has &#8220;initialize all local variables at declaration time&#8221; as part of the coding standard.  I&#8217;ve never been a big fan, but I&#8217;m very reluctant to get into coding-standard arguments (probably as the result of having had to enforce them for so long) so I just let it go.  The other day, Rusty Russell offered up a <a href="http://rusty.ozlabs.org/?p=232">better reason</a> to avoid this particular standard.  The crux of the matter is that there&#8217;s a difference between a value being initialized vs. it being initialized <b>correctly</b>, and the difference is too subtle to define a usable standard.  Sometimes there is a reasonable default value, and you want to initialize to that value instead of setting it in ten different places.  Other times every value has a distinct important meaning, and code depends on a variable having one of those instead of a bland default.  Does NULL mean &#8220;unassigned&#8221; or &#8220;no such entry&#8221; or &#8220;allocate for me&#8221; or something else?  The worst part of all this is that required initializers prevent compilers and static-analysis tools from finding real uninitalized-variable errors for you.  As far as they&#8217;re concerned it was initialized; they don&#8217;t know that the initial value, if left alone, will cause other parts of your program to blow up.  If you need a real value, what you really want to do is leave the variable uninitialized at declaration time, and let compilers etc. do what they&#8217;re good at to find any cases where it&#8217;s used without being set to a real value first.  If your coding standard precludes this, your coding standard is hurting code quality.</p>
<p>Rusty suggests that new languages should be designed with a built-in concept of undefined variables.  At the very least, each type should have a value that can not be set, and that only the interpreter/compiler can check.  This last part is important, because otherwise people will use it to mean NULL, with all of the previously-mentioned ambiguity that entails.  The &#8220;uninitialized&#8221; value for each type should mean <b>only</b> that &#8211; never &#8220;ignored&#8221; or &#8220;doesn&#8217;t matter&#8221; or anything else.  A slightly better approach is to make &#8220;uninitialized&#8221; only one of many variable annotations that are possible, as in <a href="http://www.cs.umd.edu/~jfoster/cqual/">cqual</a>.  Maybe some of that functionality will even be baked into gcc or LLVM (small pieces already are), providing the same functionality in current languages.  Until then, the best option is to educate people about why it can sometimes be good to leave variables uninitialized until you have a real value for them.</p>
]]></content:encoded>
			<wfw:commentRss>http://pl.atyp.us/wordpress/index.php/2011/11/when-coding-standards-hurt-quality/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>My Android Experiment</title>
		<link>http://pl.atyp.us/wordpress/index.php/2011/11/my-android-experiment/</link>
		<comments>http://pl.atyp.us/wordpress/index.php/2011/11/my-android-experiment/#comments</comments>
		<pubDate>Fri, 04 Nov 2011 14:56:47 +0000</pubDate>
		<dc:creator>Jeff Darcy</dc:creator>
				<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://pl.atyp.us/wordpress/?p=3390</guid>
		<description><![CDATA[A while back, I bought an Asus EeePad Transformer. A bit later I bought the base unit which has a keyboard and extra battery. I still love it. Being able to switch between landscape and portrait orientation on a whim is really awesome, because so many sites look so much better in one format. The [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, I bought an Asus EeePad Transformer.  A bit later I bought the base unit which has a keyboard and extra battery.  I still love it.  Being able to switch between landscape and portrait orientation on a whim is really awesome, because so many sites look so much better in one format.  The battery life is phenomenal.  I can get a full day of near-continuous use with the tablet alone, and the battery in the base is even bigger.  It&#8217;s even smart about draining the base-unit battery to keep the built-in one as full as possible.</p>
<p>The last couple of days, I had to travel to NYC, so I decided to experiment with using this as my travel computer.  I did bring another (small) laptop along just in case, but resolved not to use it &#8211; and I didn&#8217;t, except as a reserve battery for my MiFi portable wireless gadget.  However, I have run into two serious limitations.  One is that I can&#8217;t use it for presentations.  Besides the fact that it physically has only a (mini) HDMI whereas most projectors are still VGA, I can&#8217;t find any decent software for presentations.  I&#8217;ve looked at several apps and a couple of online services.  They&#8217;re all awful.  Is it too much to ask that a presentation program handle a simple two-level bullet list properly?  Apparently.  The other problem is that I can&#8217;t really use this thing for terminal sessions.  The base-unit keyboard actually lacks an escape key.  As a vi user, that&#8217;s crippling.  I could use emacs instead, but the handling of the control key also seems a bit erratic.  I tried using the on-screen escape key in ConnectBot, but eventually settled on using Hacker&#8217;s Keyboard instead.  While I was able to get some work done (Gluster guys: that&#8217;s how I did the quorum-optional patch) it was certainly not very pleasant.  I&#8217;d like to avoid solutions that require rooting the device, but I might have to resort to that.</p>
<p>I still love using the EeePad at home, and in meetings.  I just might not be able to use it as a road machine and that makes me sad.  Maybe the software situation will improve over the next year or so.</p>
]]></content:encoded>
			<wfw:commentRss>http://pl.atyp.us/wordpress/index.php/2011/11/my-android-experiment/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>To The Cloud . . . And Beyond!</title>
		<link>http://pl.atyp.us/wordpress/index.php/2011/11/to-the-cloud-and-beyond/</link>
		<comments>http://pl.atyp.us/wordpress/index.php/2011/11/to-the-cloud-and-beyond/#comments</comments>
		<pubDate>Tue, 01 Nov 2011 13:00:40 +0000</pubDate>
		<dc:creator>Jeff Darcy</dc:creator>
				<category><![CDATA[site]]></category>

		<guid isPermaLink="false">http://pl.atyp.us/wordpress/?p=3388</guid>
		<description><![CDATA[You might not have noticed, but I just moved. As part of my ongoing project to consolidate my various web &#8220;properties&#8221; I upgraded and updated my Rackspace cloud server (which I&#8217;ve been using for two years), and put nginx + php_fpm + mysql on it to serve my websites. It probably wasn&#8217;t the best idea [...]]]></description>
			<content:encoded><![CDATA[<p>You might not have noticed, but I just moved.  As part of my ongoing project to consolidate my various web &#8220;properties&#8221; I upgraded and updated my Rackspace cloud server (which I&#8217;ve been using for two years), and put nginx + php_fpm + mysql on it to serve my websites.  It probably wasn&#8217;t the best idea to do the move on the same day I posted something as inflammatory as my last post &#8211; there was some virtual-memory tuning I&#8217;d forgotten, and I did get bitten by the uber-stupid &#8220;OOM Killer&#8221; under the Hacker News load &#8211; but it all seems to be working out otherwise.  One of the nice things is that I can resize my server any time I expect a similar spike, then shrink it again when the spike&#8217;s over.  If I were really motivated I&#8217;d do it all automatically, but I don&#8217;t have that kind of spare time.</p>
<p>So, as usual, please let me know if you see any glitches.  One of the things the traffic spike did for me was show that normal stuff is working, but some stuff around the edges might still need tweaking.  I know FTP access and image links to womb.atyp.us (in old posts) aren&#8217;t working.  Anything else?</p>
]]></content:encoded>
			<wfw:commentRss>http://pl.atyp.us/wordpress/index.php/2011/11/to-the-cloud-and-beyond/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using disk: basic (Requested URI is rejected)
Database Caching 10/13 queries in 0.033 seconds using disk: basic

Served from: pl.atyp.us @ 2012-05-21 04:00:31 -->
