<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Gradual Ephiphany]]></title>
  <link href="http://dizzyd.com/atom.xml" rel="self"/>
  <link href="http://dizzyd.com/"/>
  <updated>2012-01-15T12:14:36-07:00</updated>
  <id>http://dizzyd.com/</id>
  <author>
    <name><![CDATA[Dave Smith]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[10 minutes]]></title>
    <link href="http://dizzyd.com/blog/2010/10/16/10-minutes/"/>
    <updated>2010-10-16T00:00:00-06:00</updated>
    <id>http://dizzyd.com/blog/2010/10/16/10-minutes</id>
    <content type="html"><![CDATA[<p>I&#8217;ve started making an effort to spend 10 minutes reading and 10 minutes writing every day. Sometimes, the writing portion takes the form of a blog entry, sometimes a journal entry &#8211; on occasion it&#8217;s a letter to a friend. The point of it all is to practice expressing myself and expand my view on the world. Cancer, my inspiring companion, has revealed the multi-mindedness with which I pursue life to be flat and uninteresting on larger scopes.</p>

<p>Ten minutes doesn&#8217;t seem like much of a commitment on the surface. But in my world of 2 kids, always-connected IM and other distractions, I actually found the first week of the regime quite difficult. I&#8217;m used to hoping topics quickly and doing a lot of skimming. Writing emails and IMs is often very close to stream of consciousness and only occasionally requires a lot of focused thought. It seems like I&#8217;ve lost touch with the ability to put words to paper/screen efficiently and effectively. What&#8217;s worse &#8211; I&#8217;ve lost touch with the ability to absorb other topics, so ruthless is my drive to be expert in my field.</p>

<p>So, I&#8217;m trying this 10 minute regime to try and recover the skills that I&#8217;ve lost. Before I picked up programming, I loved to write; poems and short stories were great creative outlets for me. Perhaps I can recover these delights, or at least, take back the ability to communicate in the ambiguous but graceful grammar of humans.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[1.44 am]]></title>
    <link href="http://dizzyd.com/blog/2010/02/18/cancer/"/>
    <updated>2010-02-18T00:00:00-07:00</updated>
    <id>http://dizzyd.com/blog/2010/02/18/cancer</id>
    <content type="html"><![CDATA[<p>It&#8217;s 1.44 am. Woke up feeling weird; then my mind went running, afraid of what it might find.</p>

<p>I was diagnosed with follicular lymphoma three weeks ago now.</p>

<p>I&#8217;m blessed in a lot of ways. The cancer is slow moving, non aggressive &#8211; or so it appears at this point. I might not even require treatment in the near future. Even if I do require treatment, survival rates have jumped from 60% to 90% in the past five years &#8211; the treatment for this cancer is progressing quickly. My company, Basho, has been wonderful to me in terms of helping me sort out a variety of insurance issues and arranging access to very good doctors.</p>

<p>All of these things are probably the reason I&#8217;ve not had any trouble sleeping until tonight.</p>

<p>It&#8217;s still scary though. Cancer &#8211; just the word inspires fear when you first hear it. You are struck, relatively quickly, with the fragility and preciousness of life. You suddenly have a deep desire to grow old. The prospect of death is a powerful incentive to live.</p>

<p>I cried more the first few days and weeks than I ever have in my 32 years. I cried because I was scared. I cried because I was worried about my wife, our 2 year old and the new baby on the way. I cried because it felt unfair, unwarranted! I cried because I realized that there were some areas of my life that I had wasted &#8211; and I wondered if I would have the chance to rectify them.</p>

<p>As I&#8217;ve gotten further into this process, emotions have settled out a bit. I realize now just how good I have it with this cancer. What I&#8217;m facing is absolutely nothing compared to other people I know with chronic medical conditions. It&#8217;s a smudge on the screen; a minor distraction. There might be some tough times ahead, but my overall probability for immediate mortality is relatively stable and low.</p>

<p>That said, I&#8217;m determined to make the most of this challenge. If I must go through this valley, I&#8217;m going to extract every bit of growth from it that I can. I choose to grow, to push my boundaries in every dimension: physically, spiritually, mentally, emotionally.  I choose to spend more time with my family and less time with wandering the mental spaces of coding. I choose to listen more and speak less. I choose to be grateful that all of these realizations have been granted to me at 32 instead of 64.</p>

<p>It&#8217;s now 2.21 am. I think it was just the Chinese food from dinner that woke me up.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rebar]]></title>
    <link href="http://dizzyd.com/blog/2010/01/10/rebar/"/>
    <updated>2010-01-10T00:00:00-07:00</updated>
    <id>http://dizzyd.com/blog/2010/01/10/rebar</id>
    <content type="html"><![CDATA[<p>Over the past two months, I&#8217;ve been busy taking the lessons learned from <a href="http://dizzyd.com/blog/post/122">erlbox</a> and designing a pure Erlang build tool called <a href="http://hg.basho.com/rebar">rebar</a>. While erlbox is a very complete toolkit of rake functions for building Erlang code, it has a couple of significant problems. First off, the external dependency on rake is often a significant problem for developers who are not conversant in Ruby. While anyone can learn Ruby, if you&#8217;re an Erlang developer you likely have other tasks to attend to than learning a language solely for the purpose of maintaining your build system. The other significant problem with erlbox is that it spends a lot of time going in/out of Erlang to do &#8220;Erlangy&#8221; sorts of checks &#8211; like parsing/validating the .app file, running eunit, etc. This leads to erlbox being a relatively slow build system, not to mention a little awkward to maintain since it was an odd mix of Ruby and invocations of Erlang.</p>

<p>Thus, rebar was born. As a strictly Erlang implementation, it&#8217;s possible for Erlang developers to dig into it and improve/modify with minimal effort. It&#8217;s also wickedly fast, since it starts the VM up only once and has direct access to all the tools one needs to build and validate Erlang code. It has the added advantage of being able to take advantage of Erlang&#8217;s inherent parallelism, so where possible, it runs commands concurrently. Finally, it&#8217;s designed to be a self-contained escript, so using rebar doesn&#8217;t introduce any build dependencies other than a stock Erlang install. You simply drop the rebar script into your code tree and go!</p>

<p>You can see a demonstration of converting an existing app to rebar <a href="http://vimeo.com/8311407">here</a>.</p>

<p>Create and compile a simple OTP application by doing the following steps on a terminal:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> 
</span><span class='line'>$ mkdir myapp; cd myapp
</span><span class='line'>$ wget http://bitbucket.org/basho/rebar/downloads/rebar; chmod u+x rebar
</span><span class='line'>$ ./rebar create-app appid=myapp
</span><span class='line'>$ ./rebar compile
</span><span class='line'> </span></code></pre></td></tr></table></div></figure>


<p>Documentation is still scarce &#8211; that&#8217;s something I&#8217;m going to be working on over the next few weeks. The core pieces of rebar are mostly at a point that I&#8217;m happy with; now it&#8217;s time to polish. :)</p>

<p>If you have questions about rebar, or especially feedback after using it IRL, please ping me on Freenode IRC &#8211; I&#8217;m typically in the #riak room.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Running erl in a debugger]]></title>
    <link href="http://dizzyd.com/blog/2009/12/18/running-erl-in-a-debugger/"/>
    <updated>2009-12-18T00:00:00-07:00</updated>
    <id>http://dizzyd.com/blog/2009/12/18/running-erl-in-a-debugger</id>
    <content type="html"><![CDATA[<p>Let&#8217;s say you need to debug a port driver in Erlang. This typically involves gdb (unless you prefer the printf route).  Go to where erlang is installed and edit the bin/erl script. Change the last line from:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> 
</span><span class='line'> exec $BINDIR/erlexec ${1+"$@"}
</span><span class='line'> </span></code></pre></td></tr></table></div></figure>


<p>to:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> 
</span><span class='line'>if [ ! -z "$USE_GDB" ]; then
</span><span class='line'>        gdb $BINDIR/erlexec --args $BINDIR/erlexec ${1+"$@"}    
</span><span class='line'>else
</span><span class='line'>        exec $BINDIR/erlexec ${1+"$@"}
</span><span class='line'>fi
</span><span class='line'> </span></code></pre></td></tr></table></div></figure>


<p>Now all you have to do to get Erlang running in gdb is:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> 
</span><span class='line'>$ export USE_GDB=1
</span><span class='line'>$ erl
</span><span class='line'> </span></code></pre></td></tr></table></div></figure>


<p>If all goes well, you should see something like:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> 
</span><span class='line'>(dizzyd@sigr).(~)% export USE_GDB=1
</span><span class='line'>(dizzyd@sigr).(~)% erl
</span><span class='line'>GNU gdb 6.3.50-20050815 (Apple version gdb-1344) (Fri Jul  3 01:19:56 UTC 2009)
</span><span class='line'>Copyright 2004 Free Software Foundation, Inc.
</span><span class='line'>GDB is free software, covered by the GNU General Public License, and you are
</span><span class='line'>welcome to change it and/or distribute copies of it under certain conditions.
</span><span class='line'>Type "show copying" to see the conditions.
</span><span class='line'>There is absolutely no warranty for GDB.  Type "show warranty" for details.
</span><span class='line'>This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries .. done
</span><span class='line'>
</span><span class='line'>(gdb) r
</span><span class='line'>Starting program: /Users/dizzyd/Applications/erlang-r13b03/lib/erlang/erts-5.7.4/bin/erlexec 
</span><span class='line'>Reading symbols for shared libraries +. done
</span><span class='line'>
</span><span class='line'>Program received signal SIGTRAP, Trace/breakpoint trap.
</span><span class='line'>0x00007fff5fc01028 in __dyld__dyld_start ()
</span><span class='line'>(gdb) c
</span><span class='line'>Continuing.
</span><span class='line'>Reading symbols for shared libraries ... done
</span><span class='line'>Erlang R13B03 (erts-5.7.4) [source] [64-bit] [smp:8:8] [rq:8] [async-threads:0] [kernel-poll:false]
</span><span class='line'>
</span><span class='line'>Eshell V5.7.4  (abort with ^G)
</span><span class='line'>1&gt; 
</span><span class='line'> </span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Further thoughts on Dynamo's "flawed architecture"]]></title>
    <link href="http://dizzyd.com/blog/2009/11/03/further-thoughts-on-dynamos-flawed-architecture/"/>
    <updated>2009-11-03T00:00:00-07:00</updated>
    <id>http://dizzyd.com/blog/2009/11/03/further-thoughts-on-dynamos-flawed-architecture</id>
    <content type="html"><![CDATA[<p>Mr. Sarma <a href="http://jsensarma.com/blog/2009/11/dynamo-part-i-a-followup-and-re-rebuttals/">revisits</a> his claims that Dynamo is a universally &#8220;flawed architecture&#8221;. I certainly concur that Dynamo has its flaws, but making sweeping claims about something being universally so is to under-value the contribution to production thinking that Dynamo contributes. So, once again, I&#8217;m going to take a few choice quotes from Mr. Sarma and respond to them.</p>

<blockquote>
However, i remain convinced that one should not force clients to deal with stale reads in
environments where they can be avoided. As i have mentioned in the updated initial post - there
are simple examples where stale reads cause havoc. One may not be able to do conflict
resolution or the reads can affect other keys in ways that are hard to fix later.
</blockquote>


<p>Arguing applications &#8220;may not be able to do conflict resolution&#8221; is non-sensical &#8211; by definition, Dynamo requires that the application be cognizant of conflict resolution! This isn&#8217;t an arbitrary decision to make clients aware of conflicts. It&#8217;s a part of a measured approach to building a robust system. One may not agree with it, but to claim that Dynamo is universally flawed just because it does not conform with one&#8217;s personal feeling about layering is dis-ingenous at best.</p>

<p>Please understand me, I make no claim that Dynamo is the end-all-be-all for data stores. It is a terrible, terrible choice for some problem spaces. However, if you want a low-latency, highly-robust key/value store it works quite well.</p>

<blockquote> 
About Vector Clocks and multiple versions - it’s not a surprise that they were not
implemented in Cassandra. In Cassandra - the cost of having to retrieve many versions of a key
increases the disk seek costs reads multi-fold. Due to the usage of LSM trees, a disk seek may
be required for each file that has a version of the key. Even though the versions may not
require reconciliation, one still has to read them.  
</blockquote>


<p>This is an argument about implementation details of Cassandra and has nothing to do with whether or not Dynamo is a universally flawed architecture. I can say from experience that vector clocks do not have to be slow &#8211; as with anything, careful implementation can yield surprisingly fast results. I would also note that in the production systems where I&#8217;ve deployed Dynamo-clones, the actual occurrence of multiple versions (or conflicts, in Dynamo terms) is quite rare. The original Dynamo paper (sect 6.3, para 3) notes that 99.94% of all requests return a single version; this matches closely with what I&#8217;ve observed in my own production deployments today (99.91%).</p>

<p>Also, implementation-wise, one doesn&#8217;t typically keep resolved versions lying around &#8211; the only time there are multiple versions present on disk is when a conflict has not been
resolved. One <em>could</em> keep old versions around, I suppose, and in that situation I agree that you would want to carefully design your store so as to avoid unnecessary seeks when reading the &#8220;current&#8221; version.</p>

<blockquote> 
So, unfortunately, i am repeating this yet again - Dynamo’s quorum consensus
protocol seems fundamentally broken. How can one write outside the quorum group and claim a
write quorum? And when one does so - how can one get consistent reads without reading every
freaking replica all the time? (well - the answer is - one doesn’t - which is why Dynamo is
eventually consistent. I just hope that users/developers of Dynamo clones realize this now).
</blockquote>


<p>As Mr. Sarma astutely points out, the reason Dynamo works is because it makes no guarantees about instantaneous consistency. Assuming (again) that the client can tolerate conflicts and that the cluster will attempt to resync at the earliest possible opportunity, writing to non-authoritative nodes is perfectly fine. The system will <em>eventually</em> come back into consensus.</p>

<p>Unfortunately, I&#8217;m pretty sure that my arguments will be insufficient to convince Mr. Sarma of the utility of Dynamo. I hope, however, that anyone reading this discussion will consider that reviewing the concepts of a paper is a very different task from executing on those concepts. As someone who has successfully executed ideas from that paper, I can assure Mr. Sarma that the concepts not only work, but they work surprisingly well.</p>

<p>Finally, the real contribution of the Dynamo paper is the balance that was struck between performance, reliability and pragmatism in the design of a production DHT. It underscores the importance of taking nothing for granted and being willing to consider counter-intutitive solutions to hard problems.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Thoughts on Dynamo's "flawed architecture"]]></title>
    <link href="http://dizzyd.com/blog/2009/11/01/thoughts-on-dynamos-flawed-architecture/"/>
    <updated>2009-11-01T00:00:00-06:00</updated>
    <id>http://dizzyd.com/blog/2009/11/01/thoughts-on-dynamos-flawed-architecture</id>
    <content type="html"><![CDATA[<p>In general, I think it&#8217;s a little inflammatory to make sweeping statements about the fitness of a given architecture. Every architecture has its flaws; it&#8217;s an expected state when you are faced with diametrically opposing constraints. The real question that should be asked is whether or not an architecture solves the problems for which it was designed in a reliable and efficient manner.</p>

<p>Joydeep Sarma posted an entry claiming that Dynamo is a <a href="http://jsensarma.com/blog/2009/11/dynamo-a-flawed-architecture-part-i/">&#8220;flawed architecture&#8221;</a>. I&#8217;m not really qualified to prove or disprove Mr. Sarma&#8217;s claim, but having implemented a Dynamo clone, I think that he may be a little confused about how things work in these systems. What follows are a few quotes from his write-up followed by my own responses.</p>

<blockquote>
Let’s say that one is storing key-value pairs in Dynamo - where the value encodes a ‘list’. If
Dynamo returns a stale read for a key and claims the key is missing, the application will
create a new empty list and store it back in Dynamo. This will cause the existing key to be
wiped out. Depending on how ’stale’ the read was - the data loss (due to truncation of the
list) can be catastrophic. This is clearly unacceptable. No application can accept unbounded
data loss - not even in the case of a Disaster.
</blockquote>


<p>Dynamo implementations protect against this scenario by using vector clocks. If we define a &#8220;stale read&#8221; as one which returns the key (or absence thereof) and an older vector clock, then any writes which use this older/non-existent vector clock will generate a conflict and the server will store two versions of the same key. The application then has the opportunity to resolve this conflict on the next read. When used in conjuction with quoroms for reads and writes, this approach proves to be exceedingly robust.</p>

<blockquote> 
Dynamo starts by saying it’s eventually consistent - but then in Section 4.5. it claims
a quorum consensus scheme for ensuring some degree of consistency. It is hinted that by setting
the number of reads (R) and number of writes (W) to be more than the total number of replicas
(N) (ie. R+W>N) - one gets consistent data back on reads. This is flat out misleading. On close
analysis one observes that there are no barriers to joining a quorum group (for a set of
keys). Nodes may fail, miss out on many many updates and then rejoin the cluster - but are
admitted back to the quorum group without any resynchronization barrier. As a result, reading
from R copies is not sufficient to give up-to-date data.
</blockquote>


<p>One of the foundational assumptions in the Dynamo system is that you define as many replicas as necessary to achieve your desired level of reliability. As with any replication based system, if you lose all of your replicas, there is no meaningful recovery. However, if we assume that you will always have some number of replicas functional, and we introduce an appropriate quorum on operations, we can identify those nodes which return stale data and repair them appropriately. In other words, it&#8217;s perfectly possible not to have resync barrier on joining, yet still ensure consistency in the answers provided to the client.</p>

<p>It might be helpful to recall that there are three levels of repair: read-repairs, hinted handoffs and replica synchronization. Two of these three are done in near-real time, thus minimizing the actual drift between nodes. Read repair deals with stale data on a per key/operation basis; the coordinator for a request can identify nodes responding with stale data and update them accordingly, using responses from other less stale nodes. Hinted handoffs are a bulk operation that is done when a node rejoins the cluster &#8211; the keys updated while the node was down are replayed (in essence) to the rejoining node. Replica sync is something that is typically done once a day and does require a traversal of all the data for a given partition. Tricks like Merkel trees, however, permit only the changed portion of the data to be exchanged, so in practice it&#8217;s not nearly as expensive as one might imagine in the abstract.</p>

<blockquote>
Lack of point in time consistency at the surviving replica (that is evident in this scenario)
is very problematic for most applications. In cases where one transaction (B) populates entites
that refer to entities populated in previous transactions (A), the effect of B being applied to
the remote replica without A being applied leads to inconsistencies that applications are
typically ill equipped to handle (and doing so would make most applications complicated).
</blockquote>


<p>The Dynamo paper makes it very clear that applications do require more logic to deal with these situations. Yes, it&#8217;s more work for the application, but in practice, it&#8217;s not that bad. It&#8217;s also important to point out that data dependencies are handled differently in these key/value stores than they are in a typical ACID environment. Usually apps will store the data in a denormalized form, so dependencies amongst key versions are minimal (if they exist at all). This makes it much easier to deal with conflicts as all the relevant data is on hand during the resolution phase.</p>

<p>I&#8217;ll leave it to someone else to do a more exhaustive analysis of Mr. Samra&#8217;s arguments. It&#8217;s been my experience over the past 2 years that Dynamo is one of those systems that you really have to see in action (or implement it) to appreciate the wonderful elegance and resiliency of the design. It&#8217;s certainly not a one-size-fits-all solution, but works very well in the appropriate problem space.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Getting started with erlbox]]></title>
    <link href="http://dizzyd.com/blog/2009/08/19/getting-started-with-erlbox/"/>
    <updated>2009-08-19T00:00:00-06:00</updated>
    <id>http://dizzyd.com/blog/2009/08/19/getting-started-with-erlbox</id>
    <content type="html"><![CDATA[<p><a href="http://github.com/dizzyd/erlbox">erlbox</a> is a set of Rake tasks that make it easy to build Erlang applications and embedded nodes. It&#8217;s a framework that <a href="http://fiatdev.com">Phil</a> and I developed over the past few months and is now something I&#8217;d prefer not to live without. While it would be nice to have a &#8220;pure&#8221; Erlang solution for doing builds, Rake has turned out to be an excellent tool and a reasonable, pragmatic solution to the problem.</p>

<p><i>Please note that erlbox (and this blog entry) isn&#8217;t necessarily where you want to start when you&#8217;re first learning Erlang &#8211; see any of the excellent books for a good introduction to Erlang.</i></p>

<p>To get started with erlbox, you first need to install Ruby and <a href="http://rubygems.org">RubyGems</a>. One you have RubyGems installed, you can then do:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> $ gem install erlbox </span></code></pre></td></tr></table></div></figure>


<p>This should pull down erlbox as well as Rake and any other dependencies. Note that the Debian version of RubyGems is a little weird &#8211; my experience is that using RubyGems from source on Debian yields the best results.</p>

<p>Once you have erlbox installed, you&#8217;re ready to put together your an Erlang application. In keeping with OTP guidelines, we&#8217;ll start by creating a standard OTP directory structure:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> $ mkdir -p testapp/ebin testapp/src </span></code></pre></td></tr></table></div></figure>


<p>The next step is to create an application descriptor (ebin/testapp.app) so that Erlang/OTP knows how to start our application up. Drop the following text into testapp/ebin/testapp.app:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> {application, testapp,
</span><span class='line'> [{description, "Test Application"},
</span><span class='line'>  {vsn, "1"},
</span><span class='line'>  {modules, [ testapp,
</span><span class='line'>              testapp_sup ]},
</span><span class='line'>  {registered, []},
</span><span class='line'>  {applications, [kernel, 
</span><span class='line'>                  stdlib]},
</span><span class='line'>  {mod, {testapp, []}},
</span><span class='line'>  {env, [
</span><span class='line'>        ]}
</span><span class='line'> ]}. </span></code></pre></td></tr></table></div></figure>


<p>The hows/whys of OTP .app files are beyond the scope of this entry &#8211; see the Erlang docs, specifically &#8220;Working with OTP/Design Principles&#8221; for more details.</p>

<p>With the .app file and the basic directory structure in place, we are now ready to create the Rakefile that will be used by Rake to kick off the erlbox tasks. For this simple build, it&#8217;s a one-liner:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> $ echo "require 'erlbox'" &gt; testapp/Rakefile </span></code></pre></td></tr></table></div></figure>


<p>We can now use Rake to build our Erlang app:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> $ cd testapp; rake
</span><span class='line'>(in /home/dizzyd/src/testapp)
</span><span class='line'>validating testapp.app...
</span><span class='line'>rake aborted!
</span><span class='line'>One or more modules listed in testapp.app do not exist as .beam:
</span><span class='line'> * testapp
</span><span class='line'> * testapp_sup
</span><span class='line'>
</span><span class='line'>(See full trace by running task with --trace)
</span><span class='line'> </span></code></pre></td></tr></table></div></figure>


<p>As you can see, we still have some work to do. One of the important things that erlbox does is validate the application descriptor ebin/testapp.app and ensure that all the modules it lists are present in compiled form in the ebin/ directory. In this case, the .app file claimed that a module named &#8220;testapp&#8221; would be present as ebin/testapp.beam, and erlbox generated an error when the module was not found.</p>

<p>So, let&#8217;s create the source for the testapp module. Drop the following text into testapp/src/testapp.erl:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> -module(testapp).
</span><span class='line'>
</span><span class='line'>-behaviour(application).
</span><span class='line'>
</span><span class='line'>%% Application callbacks
</span><span class='line'>-export([start/2, stop/1]).
</span><span class='line'>
</span><span class='line'>%% ===============================================================
</span><span class='line'>%% Application callbacks
</span><span class='line'>%% ===============================================================
</span><span class='line'>
</span><span class='line'>start(_StartType, _StartArgs) -&gt;
</span><span class='line'>    testapp_sup:start_link().
</span><span class='line'>
</span><span class='line'>stop(_State) -&gt;
</span><span class='line'>    ok.
</span><span class='line'> </span></code></pre></td></tr></table></div></figure>


<p>We also need to define the application supervisor in testapp/src/testapp.erl:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> -module(testapp_sup).
</span><span class='line'>
</span><span class='line'>-behaviour(supervisor).
</span><span class='line'>
</span><span class='line'>%% API
</span><span class='line'>-export([start_link/0]).
</span><span class='line'>
</span><span class='line'>%% Supervisor callbacks
</span><span class='line'>-export([init/1]).
</span><span class='line'>
</span><span class='line'>%% ===================================================================
</span><span class='line'>%% API functions
</span><span class='line'>%% ===================================================================
</span><span class='line'>
</span><span class='line'>start_link() -&gt;
</span><span class='line'>    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
</span><span class='line'>
</span><span class='line'>%% ===================================================================
</span><span class='line'>%% Supervisor callbacks
</span><span class='line'>%% ===================================================================
</span><span class='line'>
</span><span class='line'>init([]) -&gt;
</span><span class='line'>    {ok,{{one_for_one,5,10}, []}}.
</span><span class='line'> </span></code></pre></td></tr></table></div></figure>


<p>The erlbox tasks know to look for all source files in testapp/src/<em>.erl and compile them to testapp/ebin/</em>.beam. With these files in place let&#8217;s try rake again:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> $ cd testapp; rake
</span><span class='line'>(in /home/dizzyd/src/testapp)
</span><span class='line'>compiling src/testapp.erl...
</span><span class='line'>compiling src/testapp_sup.erl...
</span><span class='line'>validating testapp.app...
</span><span class='line'>$ </span></code></pre></td></tr></table></div></figure>


<p>The build completed cleanly. Congratulations, you&#8217;ve just built a basic Erlang/OTP application using erlbox.</p>

<p>There are a lot more features in erlbox other than what I&#8217;ve covered here. It also has the ability to build/compile OTP embedded nodes, SNMP MIBs, port drivers and other everyday components that make up the OTP platform.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Drained]]></title>
    <link href="http://dizzyd.com/blog/2008/12/20/drained/"/>
    <updated>2008-12-20T00:00:00-07:00</updated>
    <id>http://dizzyd.com/blog/2008/12/20/drained</id>
    <content type="html"><![CDATA[<p>The last portion of this year has been draining on many fronts. It&#8217;s not a complaint &#8211; just a statement. I was grading two classes, taking another and working full time. It was too much. I worked through everything, but at different times had to neglect things that I would have preferred to focus on.</p>

<p>I am slowly recovering. Now in this slow, happy time of Christmas and New Year&#8217;s I find myself without my normal drive. I feel empty and light; it&#8217;s disturbing after the harried pace of the past 4 months. There are so many side projects that I want to work on, but simply can&#8217;t find the energy or desire to focus on them.</p>

<p>Over the years I&#8217;ve come to realize that the creative expenditure of creating software comes at a price. I have a fixed capacity for creating software &#8211; if I expend that capacity it requires time to refuel. In the interim, I can still create but at a much diminished pace, and typically with a much lower quality than what I am accustomed to. The best thing to do, typically, is NOT create. Wait, pause and be patient. Permit focus to drift until it&#8217;s ready to snap back to laser precision for the next Push.</p>

<p>This post probably sounds like nonsense &#8211; perhaps it is.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GTD and clarity]]></title>
    <link href="http://dizzyd.com/blog/2008/05/13/gtd-and-clarity/"/>
    <updated>2008-05-13T00:00:00-06:00</updated>
    <id>http://dizzyd.com/blog/2008/05/13/gtd-and-clarity</id>
    <content type="html"><![CDATA[<p>I&#8217;ve recently been bitten by the &#8220;GTD&#8221;:http://en.wikipedia.org/wiki/Getting_Things_Done bug. I&#8217;m not exactly a disorganized person &#8211; I generally do get stuff done. What attracted me to the system is the core idea of striving for clarity of thought by eliminating (brain) clutter.</p>

<p>I&#8217;ve always loved the feeling that I get when I lose myself to a particularly challenging or fun piece of coding. It&#8217;s that state of mind where you lose track of the passage of time and focus all your energies on turning ephemeral ideas into billions of electronic pulses. There is a clarity of thought in that state, and I would love to experience it more often.</p>

<p>The problem is, there is always clutter and noise. So, the logical question is, how does one eliminate these things and encourage a more constant state of clarity?</p>

<p>For myself, I&#8217;ve found that GTD is at least a starting point. It provides a framework on which to capture actions and ideas in a way that shunts the responsibility for tracking stuff from my brain to a more reliable store. As I&#8217;ve been consistently doing this for the past week, my list of actions/projects has grown far more rapidly than I would have ever thought. The amount of stuff that we juggle in our heads is truly prodigious &#8211; no wonder the average attention span in our society is under 3 minutes.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Breathe]]></title>
    <link href="http://dizzyd.com/blog/2008/03/14/118/"/>
    <updated>2008-03-14T00:00:00-06:00</updated>
    <id>http://dizzyd.com/blog/2008/03/14/118</id>
    <content type="html"><![CDATA[<p>Digits click,<br/>
Neuron to circuit, ideas flow;<br/>
Software breathes.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Morning]]></title>
    <link href="http://dizzyd.com/blog/2008/01/22/morning/"/>
    <updated>2008-01-22T00:00:00-07:00</updated>
    <id>http://dizzyd.com/blog/2008/01/22/morning</id>
    <content type="html"><![CDATA[<p>Earl grey, hot. <br/>
Morning brew, <br/>
Happy soul.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[An emacs mini-hack]]></title>
    <link href="http://dizzyd.com/blog/2007/10/14/an-emacs-mini-hack/"/>
    <updated>2007-10-14T00:00:00-06:00</updated>
    <id>http://dizzyd.com/blog/2007/10/14/an-emacs-mini-hack</id>
    <content type="html"><![CDATA[<p>There&#8217;s been a whole host of changes in my life since my last blog post. I left &#8220;Ping&#8221;:http://www.pingidentity.com back in August and am now working at &#8220;The Hive&#8221;:http://thehive.com. My wife and I also welcomed our first child into the world a few weeks ago. :)</p>

<p>At any rate, I&#8217;m now using emacs on a regular basis for editing C/C++ code and got tired of switching buffers manually between header (.h/.hpp) and implementation (.c/.cpp) files. So I hacked a little lisp for my .emacs to make life better. Maybe someone else will find this useful too..</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> 
</span><span class='line'>;; Association list of extension -&gt; inverse extension
</span><span class='line'>(setq exts '(("cpp" . ("hpp" "h"))
</span><span class='line'>             ("hpp" . ("cpp" "c"))
</span><span class='line'>             ("h"   . ("cpp" "c"))))
</span><span class='line'>
</span><span class='line'>;; Process the association list of extensions and find the last file
</span><span class='line'>;; that exists
</span><span class='line'>(defun find-other-file (fname fext)
</span><span class='line'>  (dolist (value (cdr (assoc fext exts)) result)
</span><span class='line'>    (if (file-exists-p (concat fname "." value))
</span><span class='line'>        (setq result (concat fname "." value)))))
</span><span class='line'>
</span><span class='line'>;; Toggle function that uses the current buffer name to open/find the 
</span><span class='line'>;; other file
</span><span class='line'>(defun toggle-header-buffer()
</span><span class='line'>  (interactive)
</span><span class='line'>  (let ((ext (file-name-extension buffer-file-name))
</span><span class='line'>        (fname (file-name-sans-extension buffer-file-name)))
</span><span class='line'>    (find-file (find-other-file fname ext))))
</span><span class='line'>
</span><span class='line'>;; Bind the toggle function to a global key
</span><span class='line'>(global-set-key "\M-t" 'toggle-header-buffer)
</span><span class='line'> </span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[SSH Assistant for OS X]]></title>
    <link href="http://dizzyd.com/blog/2007/07/15/ssh-assistant-for-os-x/"/>
    <updated>2007-07-15T00:00:00-06:00</updated>
    <id>http://dizzyd.com/blog/2007/07/15/ssh-assistant-for-os-x</id>
    <content type="html"><![CDATA[<p>Over the past few weeks, I&#8217;ve been working on rewriting (for the most part) <a href="http://sshassistant.org">SSH Assistant</a>. The last version, 0.8.1 has a variety of issues with the installer and functionality. I really hate it when one has to run an installer with root access to install something that really doesn&#8217;t <em>need</em> root access. So, I&#8217;ve gone back and redesigned the app to be more amenable to a &#8220;normal&#8221; user install. I&#8217;ve yet to upload a build, but you can grab the source from my <a href="http://dizzyd.com/mercurial/sshassistant">personal repo</a>. I&#8217;m hoping to cut a 1.0.x release sometime in the next week or so.</p>

<p>When you build the new SSH Assistant, the output is a single pref pane bundle. Install that bundle by double-clicking on it. Then go into the pref pane and click the &#8220;enable&#8221; checkbox. You may have to logout so that it can setup your environment.plist properly, but that&#8217;s the extent of the install process.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Notes on creating an OpenBSD DVD]]></title>
    <link href="http://dizzyd.com/blog/2007/06/21/notes-on-creating-an-openbsd-dvd/"/>
    <updated>2007-06-21T00:00:00-06:00</updated>
    <id>http://dizzyd.com/blog/2007/06/21/notes-on-creating-an-openbsd-dvd</id>
    <content type="html"><![CDATA[<p>I recently rebuilt my gateway box using <a href="http://www.openbsd.org">OpenBSD 4.1</a>. It&#8217;s pretty easy to construct a DVD that ensures you have all the stuff you need for an install. The tricky thing is getting the DVD setup to boot. Herein are my notes so that the next time I need to do this I can remember how. :)</p>

<p>There are two tricks to get this to work. First, use the mkhybrid from <a href="http://www.macports.org">MacPorts</a>. Secondly, make sure that the location of the boot image is inside the hierarchy of files being burned to disk. I&#8217;m not sure why mkhybrid requires this, but it means the difference between working or not. Ultimately the command line should look something like:</p>

<blockquote><p> mkhybrid -joliet-long -iso-level 4 -r -b 4.1/i386/cdrom41.fs -c boot.catalog -o obsd.iso OpenBSD</p></blockquote>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[School's (almost) out!]]></title>
    <link href="http://dizzyd.com/blog/2007/04/30/schools-almost-out/"/>
    <updated>2007-04-30T00:00:00-06:00</updated>
    <id>http://dizzyd.com/blog/2007/04/30/schools-almost-out</id>
    <content type="html"><![CDATA[<p>I have hardly blogged since January — school and work has just been too much. I wrapped up one class this weekend and the remaining one is mostly done. My days have been one long series of homework assignments, or so it seems. It will take some time to acclimate back to a more sane schedule that allows me to pursue other interests.</p>

<p>One thing I have been doing is continuing to work on my Erlang skills. The tricks you can pull with that platform is outright amazing.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[One year ago today...]]></title>
    <link href="http://dizzyd.com/blog/2007/04/26/one-year-ago-today/"/>
    <updated>2007-04-26T00:00:00-06:00</updated>
    <id>http://dizzyd.com/blog/2007/04/26/one-year-ago-today</id>
    <content type="html"><![CDATA[<p>One year ago today, PGM passed away. I still think of him often and miss the many conversations we had commuting to downtown Denver together. I also miss his always pragmatic approach to software development. He just had a way of cutting through fancy designs and overblown ideas to identify the heart of a solution.</p>

<p>I suppose that these characteristics that I miss are really the most superficial ones; I know that family was far more important than any amount of code or elegant design to him. That’s how it should — code lasts only long enough to get re-written, typically.</p>

<p>I guess all of this is to say that I remember him and wish things had worked out differently.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[J&N Computer Services]]></title>
    <link href="http://dizzyd.com/blog/2007/01/10/jn-computer-services/"/>
    <updated>2007-01-10T00:00:00-07:00</updated>
    <id>http://dizzyd.com/blog/2007/01/10/jn-computer-services</id>
    <content type="html"><![CDATA[<p>After my last <a href="http://www.dizzyd.com/blog/?p=102">post</a> about Monarch, I had pretty much given up on ever resurrecting my desktop machine. In an interesting turn of events, I was contacted by another computer company that was willing to honor my warranty with Monarch and help me out &#8211; <a href="http://jncs.com">J&amp;N Computer Services</a>.
Their offer was simple, if there was no physical damage to the motherboard they would RMA it with Asus and send me back a verified, functional board.</p>

<p>One week, $25 in shipping (both ways) and 10 minutes on the phone later, I have a functioning motherboard on its way back to me. Obviously, I haven&#8217;t tested it yet, but my interactions with <a href="http://jncs.com">J&amp;N</a> left me feeling that it&#8217;s a skilled outfit that knows how to keep customers happy. More importantly, I find them to have a sense of class &#8211; they went out of their way to avoid flaming Monarch in my blog comments. It&#8217;s rare to find this sort of respect (if that&#8217;s the right word) for fallen competitors in today&#8217;s business world.</p>

<p>This the type of company I like doing business with &#8211; technically competent, user friendly and well-mannered. I wasn&#8217;t planning on ever building another system, but with a company like <a href="http://jncs.com">J&amp;N</a> providing good service&#8230;why not?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Timbuk2]]></title>
    <link href="http://dizzyd.com/blog/2006/12/29/timbuk2/"/>
    <updated>2006-12-29T00:00:00-07:00</updated>
    <id>http://dizzyd.com/blog/2006/12/29/timbuk2</id>
    <content type="html"><![CDATA[<p>I&#8217;ve been needing a new bag for work/school. During the school term, I carry both school and work items on the bus &#8211; i.e. books, notebooks (computer and otherwise), pens, calculator, lunch, etc. All that stuff adds up to a good sized load; a robust bag is important. I went ahead and picked up a bag from Timbuk2 &#8211; the <a href="http://www.timbuk2.com/tb2/retail/catalog.htm?sizeId=7&amp;skusetId=29&amp;categoryId=85">Commute XL</a>. <img align="right" src="http://www.timbuk2.com/static/images/perspectives/275/commute//fall2006/7_f_jb-jb-jb.jpg"/> So far, I really love it. It&#8217;s  thoroughly water-proofed, with a solid rubber bottom and rubberized inside. It&#8217;s got a padded sleeve for the laptop and a nice broad strap. It&#8217;s a little on the pricey side, but considering the durability built into it, I suspect it&#8217;ll last for quite a while.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Resolutions for 2007]]></title>
    <link href="http://dizzyd.com/blog/2006/12/29/resolutions-for-2007/"/>
    <updated>2006-12-29T00:00:00-07:00</updated>
    <id>http://dizzyd.com/blog/2006/12/29/resolutions-for-2007</id>
    <content type="html"><![CDATA[<p>It&#8217;s another snowy day in Denver. Two massive snowstorms have left us with more snow than is typical for this time of year, so I have lots of time to think and blog. I&#8217;m not big on New Years resolutions but I think it&#8217;s wise to look back over the past year and see if corrections need to be made for the future.</p>

<p>I want to live less cheaply in 2007.</p>

<p>For me, this means reading, thinking and writing more &#8211; working and procrastinating less. It means more time listening to things that people say and less time focusing on how to respond. More yogurt, less coffee. I want to spend more time thinking about what I believe and <em>why</em>.</p>

<p>These are my resolutions. This is the person I want to be.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[3 years at Ping Identity]]></title>
    <link href="http://dizzyd.com/blog/2006/12/28/3-years-at-ping-identity/"/>
    <updated>2006-12-28T00:00:00-07:00</updated>
    <id>http://dizzyd.com/blog/2006/12/28/3-years-at-ping-identity</id>
    <content type="html"><![CDATA[<p>Yesterday was my 3 year anniversary working for <a href="http://pingidentity.com">Ping Identity</a>. It&#8217;s hard to believe that so much time has gone by, but I can genuinely say that I&#8217;m glad to still be working there.</p>
]]></content>
  </entry>
  
</feed>

