<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Glyphy</title>
  <link rel="alternate" type="text/html" href="http://glyphy.com"/>
  <link rel="self" type="application/atom+xml" href="http://glyphy.com/atom/feed"/>
  <id>http://glyphy.com/atom/feed</id>
  <updated>2007-12-24T12:41:13-08:00</updated>
  <entry>
    <title>bzr-loom : a better example</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/bzr-loom-better-example-2008-07-08" />
    <id>http://glyphy.com/bzr-loom-better-example-2008-07-08</id>
    <published>2008-07-08T17:19:16-07:00</published>
    <updated>2008-07-08T17:19:16-07:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="bzr" />
    <summary type="html"><![CDATA[<p>If the <a href="http://glyphy.com/bzr-loom-2008-07-07">last post</a> made sense, there&#8217;s a much more in-depth example <a href="http://bazaar-vcs.org/Documentation/LoomAsSmarterQuilt">here</a>.</p>

<p>Combine <a href="https://code.launchpad.net/bzr-loom">bzr-loom</a> with <a href="http://bazaar-vcs.org/BzrTools">shelf</a> and you can handle any sort of interruptions in your workflow without having to manually keep track of uncommitted changes.</p>

<p>One downside of bzr-loom is the terminology. <span class="geshifilter"><code class="geshifilter-text">bzr combine-thread</code></span> actually destroys the thread tossing all the changes made in it, which can be unpleasantly surprising. There&#8217;s a <a href="https://bugs.launchpad.net/bzr-loom/+bug/200819">bug</a> about it, though.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>If the <a href="http://glyphy.com/bzr-loom-2008-07-07">last post</a> made sense, there&#8217;s a much more in-depth example <a href="http://bazaar-vcs.org/Documentation/LoomAsSmarterQuilt">here</a>.</p>

<p>Combine <a href="https://code.launchpad.net/bzr-loom">bzr-loom</a> with <a href="http://bazaar-vcs.org/BzrTools">shelf</a> and you can handle any sort of interruptions in your workflow without having to manually keep track of uncommitted changes.</p>

<p>One downside of bzr-loom is the terminology. <code>bzr combine-thread</code> actually destroys the thread tossing all the changes made in it, which can be unpleasantly surprising. There&#8217;s a <a href="https://bugs.launchpad.net/bzr-loom/+bug/200819">bug</a> about it, though.</p>
    ]]></content>
  </entry>
  <entry>
    <title>bzr-loom</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/bzr-loom-2008-07-07" />
    <id>http://glyphy.com/bzr-loom-2008-07-07</id>
    <published>2008-07-07T20:16:29-07:00</published>
    <updated>2008-07-07T20:16:29-07:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="bzr" />
    <summary type="html"><![CDATA[<p>Branching may be cheap in DVCSs from the technical perspective, but sometimes it&#8217;s other factors that make it a pain. For example, the environment setup procedure could be very tedious, or you may be unable to use hardlinks (Windows) and your branches are too large. The <a href="https://code.launchpad.net/bzr-loom">bzr-loom</a> plugin comes in handy in these situations. A very simple example follows:</p>

<div class="geshifilter"><pre class="geshifilter-bash"><span style="color: #808080; font-style: italic;">## Install bzr-loom using `bzr branch <span style="color: #c20cb9; font-weight: bold;">lp</span>:bzr-loom` <span style="color: #000000; font-weight: bold;">in</span> your .bazaar/plugins/</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Create a new repository</span>
$ bzr init bzr
$ <span style="color: #7a0874; font-weight: bold;">cd</span> bzr
&nbsp;
<span style="color: #808080; font-style: italic;"># Create a new file</span>
$ <span style="color: #7a0874; font-weight: bold;">echo</span> initial &gt; first
&nbsp;
<span style="color: #808080; font-style: italic;"># Check it in</span>
$ bzr add first
added first
$ bzr ci -m <span style="color: #ff0000;">&quot;initial&quot;</span>
Committing to: /home/tro/temp/bzr/
added first
Committed revision <span style="color: #000000;">1</span>.
&nbsp;
$ <span style="color: #c20cb9; font-weight: bold;">cat</span> first
initial
&nbsp;
<span style="color: #808080; font-style: italic;"># Set the branch nick specifically. This is the initial development </span><span style="color: #ff0000;">&quot;thread&quot;</span>.
$ bzr nick initial
&nbsp;
<span style="color: #808080; font-style: italic;"># Create a loom. From this point on, you have to have the plugin to interact with this repo directly</span>
$ bzr loomify
&nbsp;
<span style="color: #808080; font-style: italic;"># Only one thread exists right now</span>
$ bzr show-loom
=&gt;initial
&nbsp;
<span style="color: #808080; font-style: italic;"># Add a new thread <span style="color: #7a0874; font-weight: bold;">&#40;</span>acts <span style="color: #c20cb9; font-weight: bold;">as</span> another branch inside the current directory<span style="color: #7a0874; font-weight: bold;">&#41;</span></span>
$ bzr create-thread feature<span style="color: #000000;">-1</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Add a new file</span>
$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;second file&quot;</span> &gt; second
$ bzr add second
added second
$ bzr ci -m <span style="color: #ff0000;">&quot;+second&quot;</span>
Committing to: /home/tro/temp/bzr/
added second
Committed revision <span style="color: #000000;">2</span>.
&nbsp;
<span style="color: #808080; font-style: italic;"># Switch back to the initial dev thread. Note how </span><span style="color: #ff0000;">&quot;second&quot;</span> disappears, since it is <span style="color: #000000; font-weight: bold;">in</span> another thread.
$ bzr down-thread
All changes applied successfully.
Moved to thread <span style="color: #ff0000;">'initial'</span>.
$ bzr show-loom
  feature<span style="color: #000000;">-1</span>
=&gt;initial
$ <span style="color: #c20cb9; font-weight: bold;">ls</span>
first
&nbsp;
<span style="color: #808080; font-style: italic;"># Switch to feature<span style="color: #000000;">-1</span></span>
$ bzr up-thread <span style="color: #808080; font-style: italic;"># this would <span style="color: #000000; font-weight: bold;">do</span> a merge, <span style="color: #000000; font-weight: bold;">if</span> any new changes were made <span style="color: #000000; font-weight: bold;">in</span> </span><span style="color: #ff0000;">&quot;initial&quot;</span>
$ <span style="color: #c20cb9; font-weight: bold;">ls</span>
first  second
&nbsp;
<span style="color: #808080; font-style: italic;"># Edit first</span>
$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;edit in feature-1 thread&quot;</span> &gt;&gt; first
$ <span style="color: #c20cb9; font-weight: bold;">cat</span> first
initial
edit <span style="color: #000000; font-weight: bold;">in</span> feature<span style="color: #000000;">-1</span> thread
$ bzr ci -m <span style="color: #ff0000;">&quot;useless text meant to illustrate merging between threads&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># At this point pretend that we are satisfied with the changes <span style="color: #000000; font-weight: bold;">in</span> </span><span style="color: #ff0000;">&quot;feature-1&quot;</span>
<span style="color: #808080; font-style: italic;"># and want to merge them into </span><span style="color: #ff0000;">&quot;initial&quot;</span>. Go there.
$ bzr down-thread
$ <span style="color: #c20cb9; font-weight: bold;">ls</span>
first
$ bzr merge -r thread:feature<span style="color: #000000;">-1</span> .
+N  second
 M  first
All changes applied successfully.
&nbsp;
<span style="color: #808080; font-style: italic;"># Merged changes from feature<span style="color: #000000;">-1</span> to initial</span>
$ <span style="color: #c20cb9; font-weight: bold;">ls</span>
first  second
$ <span style="color: #c20cb9; font-weight: bold;">cat</span> first
initial
edit <span style="color: #000000; font-weight: bold;">in</span> feature<span style="color: #000000;">-1</span> thread
$ <span style="color: #c20cb9; font-weight: bold;">cat</span> second
second <span style="color: #c20cb9; font-weight: bold;">file</span></pre></div>

<p>This gives you a limited git-like ability to spawn off new branches in the current directory.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>Branching may be cheap in DVCSs from the technical perspective, but sometimes it&#8217;s other factors that make it a pain. For example, the environment setup procedure could be very tedious, or you may be unable to use hardlinks (Windows) and your branches are too large. The <a href="https://code.launchpad.net/bzr-loom">bzr-loom</a> plugin comes in handy in these situations. A very simple example follows:</p>

<div class="geshifilter"><pre class="geshifilter-bash"><span style="color: #808080; font-style: italic;">## Install bzr-loom using `bzr branch <span style="color: #c20cb9; font-weight: bold;">lp</span>:bzr-loom` <span style="color: #000000; font-weight: bold;">in</span> your .bazaar/plugins/</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Create a new repository</span>
$ bzr init bzr
$ <span style="color: #7a0874; font-weight: bold;">cd</span> bzr
&nbsp;
<span style="color: #808080; font-style: italic;"># Create a new file</span>
$ <span style="color: #7a0874; font-weight: bold;">echo</span> initial &gt; first
&nbsp;
<span style="color: #808080; font-style: italic;"># Check it in</span>
$ bzr add first
added first
$ bzr ci -m <span style="color: #ff0000;">&quot;initial&quot;</span>
Committing to: /home/tro/temp/bzr/
added first
Committed revision <span style="color: #000000;">1</span>.
&nbsp;
$ <span style="color: #c20cb9; font-weight: bold;">cat</span> first
initial
&nbsp;
<span style="color: #808080; font-style: italic;"># Set the branch nick specifically. This is the initial development </span><span style="color: #ff0000;">&quot;thread&quot;</span>.
$ bzr nick initial
&nbsp;
<span style="color: #808080; font-style: italic;"># Create a loom. From this point on, you have to have the plugin to interact with this repo directly</span>
$ bzr loomify
&nbsp;
<span style="color: #808080; font-style: italic;"># Only one thread exists right now</span>
$ bzr show-loom
=&gt;initial
&nbsp;
<span style="color: #808080; font-style: italic;"># Add a new thread <span style="color: #7a0874; font-weight: bold;">&#40;</span>acts <span style="color: #c20cb9; font-weight: bold;">as</span> another branch inside the current directory<span style="color: #7a0874; font-weight: bold;">&#41;</span></span>
$ bzr create-thread feature<span style="color: #000000;">-1</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Add a new file</span>
$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;second file&quot;</span> &gt; second
$ bzr add second
added second
$ bzr ci -m <span style="color: #ff0000;">&quot;+second&quot;</span>
Committing to: /home/tro/temp/bzr/
added second
Committed revision <span style="color: #000000;">2</span>.
&nbsp;
<span style="color: #808080; font-style: italic;"># Switch back to the initial dev thread. Note how </span><span style="color: #ff0000;">&quot;second&quot;</span> disappears, since it is <span style="color: #000000; font-weight: bold;">in</span> another thread.
$ bzr down-thread
All changes applied successfully.
Moved to thread <span style="color: #ff0000;">'initial'</span>.
$ bzr show-loom
  feature<span style="color: #000000;">-1</span>
=&gt;initial
$ <span style="color: #c20cb9; font-weight: bold;">ls</span>
first
&nbsp;
<span style="color: #808080; font-style: italic;"># Switch to feature<span style="color: #000000;">-1</span></span>
$ bzr up-thread <span style="color: #808080; font-style: italic;"># this would <span style="color: #000000; font-weight: bold;">do</span> a merge, <span style="color: #000000; font-weight: bold;">if</span> any new changes were made <span style="color: #000000; font-weight: bold;">in</span> </span><span style="color: #ff0000;">&quot;initial&quot;</span>
$ <span style="color: #c20cb9; font-weight: bold;">ls</span>
first  second
&nbsp;
<span style="color: #808080; font-style: italic;"># Edit first</span>
$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;edit in feature-1 thread&quot;</span> &gt;&gt; first
$ <span style="color: #c20cb9; font-weight: bold;">cat</span> first
initial
edit <span style="color: #000000; font-weight: bold;">in</span> feature<span style="color: #000000;">-1</span> thread
$ bzr ci -m <span style="color: #ff0000;">&quot;useless text meant to illustrate merging between threads&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># At this point pretend that we are satisfied with the changes <span style="color: #000000; font-weight: bold;">in</span> </span><span style="color: #ff0000;">&quot;feature-1&quot;</span>
<span style="color: #808080; font-style: italic;"># and want to merge them into </span><span style="color: #ff0000;">&quot;initial&quot;</span>. Go there.
$ bzr down-thread
$ <span style="color: #c20cb9; font-weight: bold;">ls</span>
first
$ bzr merge -r thread:feature<span style="color: #000000;">-1</span> .
+N  second
 M  first
All changes applied successfully.
&nbsp;
<span style="color: #808080; font-style: italic;"># Merged changes from feature<span style="color: #000000;">-1</span> to initial</span>
$ <span style="color: #c20cb9; font-weight: bold;">ls</span>
first  second
$ <span style="color: #c20cb9; font-weight: bold;">cat</span> first
initial
edit <span style="color: #000000; font-weight: bold;">in</span> feature<span style="color: #000000;">-1</span> thread
$ <span style="color: #c20cb9; font-weight: bold;">cat</span> second
second <span style="color: #c20cb9; font-weight: bold;">file</span></pre></div>

<p>This gives you a limited git-like ability to spawn off new branches in the current directory.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Wotan Server</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/wotan-server-2008-05-12" />
    <id>http://glyphy.com/wotan-server-2008-05-12</id>
    <published>2008-05-12T20:23:29-07:00</published>
    <updated>2008-05-12T20:23:29-07:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="cell" />
    <category term="random" />
    <summary type="html"><![CDATA[<p><a href="http://www.wotanserver.com">These guys</a> totally saved me today. I dropped my phone today (had it on my lap when I got up) and its screen got all messed up. Turns out flashing the firmware helps restore things to normal state. <a href="http://fma.sourceforge.net/">Float</a>&#8217;s helped to restore contacts and msgs. Success.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p><a href="http://www.wotanserver.com">These guys</a> totally saved me today. I dropped my phone today (had it on my lap when I got up) and its screen got all messed up. Turns out flashing the firmware helps restore things to normal state. <a href="http://fma.sourceforge.net/">Float</a>&#8217;s helped to restore contacts and msgs. Success.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Python concurrency</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/python-concurrency-2008-05-04" />
    <id>http://glyphy.com/python-concurrency-2008-05-04</id>
    <published>2008-05-04T08:58:05-07:00</published>
    <updated>2008-05-04T08:58:05-07:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="distributed" />
    <category term="python" />
    <category term="xmpp" />
    <summary type="html"><![CDATA[<p>Part of the reason why <s>pjs</s> <a href="http://pjabberd.googlecode.com/">pjabberd</a> only works on a single processing unit (core) right now is because of the <a href="http://en.wikipedia.org/wiki/Global_Interpreter_Lock">GIL</a> in Python. The architecture uses the asyncore module (asynchronous, like <a href="http://twistedmatrix.com/trac/">twisted</a>). Looks like it was a good choice, though. In <a href="http://www.artima.com/forums/flat.jsp?forum=106&amp;thread=230001">Concurrency with Python, Twisted, and Flex</a> Bruce Eckel demonstrates how he got extreme parallelism from Python+Twisted by spawning <em>n</em> python interpreters, where <em>n</em> is the number of processing units on a machine, and communicating between them via sockets. The Flex part can be mostly ignored. This will come in handy for pjabberd when we add support for multiprocess operation and clustering.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>Part of the reason why <s>pjs</s> <a href="http://pjabberd.googlecode.com/">pjabberd</a> only works on a single processing unit (core) right now is because of the <a href="http://en.wikipedia.org/wiki/Global_Interpreter_Lock">GIL</a> in Python. The architecture uses the asyncore module (asynchronous, like <a href="http://twistedmatrix.com/trac/">twisted</a>). Looks like it was a good choice, though. In <a href="http://www.artima.com/forums/flat.jsp?forum=106&amp;thread=230001">Concurrency with Python, Twisted, and Flex</a> Bruce Eckel demonstrates how he got extreme parallelism from Python+Twisted by spawning <em>n</em> python interpreters, where <em>n</em> is the number of processing units on a machine, and communicating between them via sockets. The Flex part can be mostly ignored. This will come in handy for pjabberd when we add support for multiprocess operation and clustering.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Jabber video</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/jabber-video-2008-04-18" />
    <id>http://glyphy.com/jabber-video-2008-04-18</id>
    <published>2008-04-18T12:40:55-07:00</published>
    <updated>2008-04-18T12:40:55-07:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="490" />
    <category term="video" />
    <category term="xmpp" />
    <summary type="html"><![CDATA[<p>This is my lame-o jabber video.</p>

<p><embed src="http://blip.tv/play/AbOzPQA" type="application/x-shockwave-flash" width="640" height="510" allowscriptaccess="always" allowfullscreen="true"></embed></p>

<p>Video editing on Linux sucks. I used <a href="http://cinelerra.org/">Cinerella</a> to make this. Issues encountered:</p>

<ul>
<li>The slides had to be <em>individually</em> exported to PNG from OpenOffice.</li>
<li>Each slide then had to be <em>individually</em> resized in gimp to match the size in the video. Cinerella just couldn&#8217;t do that for me.</li>
<li>Cinerella crashes once in a while, so I learned to save my work every 5 seconds.</li>
<li>Cinerella&#8217;s UI is awful, but you get used to it.</li>
<li>The biggest problem is its importing and rendering. I had to try out 10-15 different combinations of audio/video formats to make it render the video properly. It couldn&#8217;t import any avis or movs that I generated from <a href="http://recordmydesktop.iovar.org/about.php">recordmydesktop</a>&#8217;s ogvs (via mencoder). The only format it liked was mp4.</li>
<li>Then it couldn&#8217;t get the sound right. It was recorded with Audacity in mono with 16kbps bitrate. Cinerella kept producing either no sound or sound in only one channel. I had to manually drop the bitrate in the rendered result to 16kbps and tinker with output settings (neither mp3 nor mpeg audio worked). I had to <em>manually</em> duplicate the contents of the audio track into another, which resulted in 2-channel output (<strong>even though the project was already set to 2-chan</strong>).</li>
</ul>

<p>To give it credit though, the docs are pretty decent.</p>

<p>I spent way too much time making it all work. Next time, I&#8217;ll just find a Mac that I can use to do this.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>This is my lame-o jabber video.</p>

<p><embed src="http://blip.tv/play/AbOzPQA" type="application/x-shockwave-flash" width="640" height="510" allowscriptaccess="always" allowfullscreen="true"></embed></p>

<p>Video editing on Linux sucks. I used <a href="http://cinelerra.org/">Cinerella</a> to make this. Issues encountered:</p>

<ul>
<li>The slides had to be <em>individually</em> exported to PNG from OpenOffice.</li>
<li>Each slide then had to be <em>individually</em> resized in gimp to match the size in the video. Cinerella just couldn&#8217;t do that for me.</li>
<li>Cinerella crashes once in a while, so I learned to save my work every 5 seconds.</li>
<li>Cinerella&#8217;s UI is awful, but you get used to it.</li>
<li>The biggest problem is its importing and rendering. I had to try out 10-15 different combinations of audio/video formats to make it render the video properly. It couldn&#8217;t import any avis or movs that I generated from <a href="http://recordmydesktop.iovar.org/about.php">recordmydesktop</a>&#8217;s ogvs (via mencoder). The only format it liked was mp4.</li>
<li>Then it couldn&#8217;t get the sound right. It was recorded with Audacity in mono with 16kbps bitrate. Cinerella kept producing either no sound or sound in only one channel. I had to manually drop the bitrate in the rendered result to 16kbps and tinker with output settings (neither mp3 nor mpeg audio worked). I had to <em>manually</em> duplicate the contents of the audio track into another, which resulted in 2-channel output (<strong>even though the project was already set to 2-chan</strong>).</li>
</ul>

<p>To give it credit though, the docs are pretty decent.</p>

<p>I spent way too much time making it all work. Next time, I&#8217;ll just find a Mac that I can use to do this.</p>
    ]]></content>
  </entry>
  <entry>
    <title>C++ trim function</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/c-trim-function-2008-04-15" />
    <id>http://glyphy.com/c-trim-function-2008-04-15</id>
    <published>2008-04-15T15:25:30-07:00</published>
    <updated>2008-04-15T15:25:30-07:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="494" />
    <category term="c++" />
    <summary type="html"><![CDATA[<p>Trim function for C++ std::string:</p>

<div class="geshifilter"><pre class="geshifilter-cpp"><span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std;
<span style="color: #339900;">#include &lt;string&gt;</span>
&nbsp;
<span style="color: #0000ff;">inline</span> string trim<span style="color: #000000;">&#40;</span><span style="color: #0000ff;">const</span> string&amp; o<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
  string ret = o;
  <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span>* chars = <span style="color: #666666;">&quot;<span style="color: #666666; font-weight: bold;">\n</span><span style="color: #666666; font-weight: bold;">\t</span><span style="color: #666666; font-weight: bold;">\v</span><span style="color: #666666; font-weight: bold;">\f</span><span style="color: #666666; font-weight: bold;">\r</span> &quot;</span>;
  ret.<span style="color: #00eeff;">erase</span><span style="color: #000000;">&#40;</span>ret.<span style="color: #00eeff;">find_last_not_of</span><span style="color: #000000;">&#40;</span>chars<span style="color: #000000;">&#41;</span><span style="color: #0000dd;">+1</span><span style="color: #000000;">&#41;</span>;
  ret.<span style="color: #00eeff;">erase</span><span style="color: #000000;">&#40;</span><span style="color: #0000dd;">0</span>, ret.<span style="color: #00eeff;">find_first_not_of</span><span style="color: #000000;">&#40;</span>chars<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;
  <span style="color: #0000ff;">return</span> ret;
<span style="color: #000000;">&#125;</span></pre></div>

<p>It returns a new string, sort of like it&#8217;s done in Qt or Java.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>Trim function for C++ std::string:</p>

<div class="geshifilter"><pre class="geshifilter-cpp"><span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std;
<span style="color: #339900;">#include &lt;string&gt;</span>
&nbsp;
<span style="color: #0000ff;">inline</span> string trim<span style="color: #000000;">&#40;</span><span style="color: #0000ff;">const</span> string&amp; o<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
  string ret = o;
  <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span>* chars = <span style="color: #666666;">&quot;<span style="color: #666666; font-weight: bold;">\n</span><span style="color: #666666; font-weight: bold;">\t</span><span style="color: #666666; font-weight: bold;">\v</span><span style="color: #666666; font-weight: bold;">\f</span><span style="color: #666666; font-weight: bold;">\r</span> &quot;</span>;
  ret.<span style="color: #00eeff;">erase</span><span style="color: #000000;">&#40;</span>ret.<span style="color: #00eeff;">find_last_not_of</span><span style="color: #000000;">&#40;</span>chars<span style="color: #000000;">&#41;</span><span style="color: #0000dd;">+1</span><span style="color: #000000;">&#41;</span>;
  ret.<span style="color: #00eeff;">erase</span><span style="color: #000000;">&#40;</span><span style="color: #0000dd;">0</span>, ret.<span style="color: #00eeff;">find_first_not_of</span><span style="color: #000000;">&#40;</span>chars<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;
  <span style="color: #0000ff;">return</span> ret;
<span style="color: #000000;">&#125;</span></pre></div>

<p>It returns a new string, sort of like it&#8217;s done in Qt or Java.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Double wick</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/double-wick-2008-04-07" />
    <id>http://glyphy.com/double-wick-2008-04-07</id>
    <published>2008-04-07T14:40:35-07:00</published>
    <updated>2008-04-07T14:40:35-07:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="images" />
    <category term="random" />
    <summary type="html"><![CDATA[<p><a href="http://www.flickr.com/photos/tro/2397152982/" title="Double wick by troworld, on Flickr"><img src="http://farm3.static.flickr.com/2156/2397152982_4fbf9a52a1.jpg" width="500" height="375" alt="Double wick" /></a></p>

<p>I don&#8217;t really know how it&#8217;s being held in place. <strong>Magic!</strong></p>
    ]]></summary>
    <content type="html"><![CDATA[<p><a href="http://www.flickr.com/photos/tro/2397152982/" title="Double wick by troworld, on Flickr"><img src="http://farm3.static.flickr.com/2156/2397152982_4fbf9a52a1.jpg" width="500" height="375" alt="Double wick" /></a></p>

<p>I don&#8217;t really know how it&#8217;s being held in place. <strong>Magic!</strong></p>
    ]]></content>
  </entry>
  <entry>
    <title>pysqlite db locking issues</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/pysqlite-db-locking-issues-2008-03-30-4" />
    <id>http://glyphy.com/pysqlite-db-locking-issues-2008-03-30-4</id>
    <published>2008-03-30T11:04:35-07:00</published>
    <updated>2008-03-31T16:13:01-07:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="490" />
    <category term="db" />
    <category term="issues" />
    <summary type="html"><![CDATA[<p><strong>Update</strong>: This issue went away when I upgraded to pysqlite 2.4.1 (from 2.3.2), so I doubt the info below is really correct.</p>

<p>I just stumbled upon this issue (&#8220;database is locked&#8221;), so I&#8217;m posting in case someone googles for this.</p>

<p>With <a href="http://pysqlite.org/">Pysqlite</a>, the default isolation level is <a href="http://glyphy.com/sqlite-isolation-levels-2008-03-27">DEFERRED</a>, which means that for all write statements (INSERT/UPDATE/etc.) pysqlite implicitly opens a transaction and you have to commit it to allow other writers to proceed. Apparently, when committing <a href="http://article.gmane.org/gmane.comp.python.db.pysqlite.user/1770">the writer thread holds a global lock</a>, not just a write lock, which prevents readers from making progress too. This lock is held even if your transaction only has SELECT (read) statements. So you have to explicitly commit those transactions.</p>

<p>So, I thought, hey, why not just make all my SELECT statements execute within &#8220;autocommit&#8221; connections (<span class="geshifilter"><span class="geshifilter"><code class="geshifilter-text">isolation_level=None</code></span></span>)? Turns out that you have to close the connection explicitly after executing a SQL query even in autocommit mode to unlock the db for other threads:</p>

<div class="geshifilter"><pre class="geshifilter-python">con = getDBConnFromSomewhere<span style="color: black;">&#40;</span>isolation_level=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
c = con.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
res = c.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;SELECT ...&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># do something with result</span>
c.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
con.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># this is important</span></pre></div>
    ]]></summary>
    <content type="html"><![CDATA[<p><strong>Update</strong>: This issue went away when I upgraded to pysqlite 2.4.1 (from 2.3.2), so I doubt the info below is really correct.</p>

<p>I just stumbled upon this issue (&#8220;database is locked&#8221;), so I&#8217;m posting in case someone googles for this.</p>

<p>With <a href="http://pysqlite.org/">Pysqlite</a>, the default isolation level is <a href="http://glyphy.com/sqlite-isolation-levels-2008-03-27">DEFERRED</a>, which means that for all write statements (INSERT/UPDATE/etc.) pysqlite implicitly opens a transaction and you have to commit it to allow other writers to proceed. Apparently, when committing <a href="http://article.gmane.org/gmane.comp.python.db.pysqlite.user/1770">the writer thread holds a global lock</a>, not just a write lock, which prevents readers from making progress too. This lock is held even if your transaction only has SELECT (read) statements. So you have to explicitly commit those transactions.</p>

<p>So, I thought, hey, why not just make all my SELECT statements execute within &#8220;autocommit&#8221; connections (<span class="geshifilter"><code class="geshifilter-text">isolation_level=None</code></span>)? Turns out that you have to close the connection explicitly after executing a SQL query even in autocommit mode to unlock the db for other threads:</p>

<div class="geshifilter"><pre class="geshifilter-python">con = getDBConnFromSomewhere<span style="color: black;">&#40;</span>isolation_level=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
c = con.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
res = c.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;SELECT ...&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># do something with result</span>
c.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
con.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># this is important</span></pre></div>
    ]]></content>
  </entry>
  <entry>
    <title>SQLite isolation levels</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/sqlite-isolation-levels-2008-03-27" />
    <id>http://glyphy.com/sqlite-isolation-levels-2008-03-27</id>
    <published>2008-03-27T12:45:14-07:00</published>
    <updated>2008-03-27T12:47:32-07:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="490" />
    <category term="db" />
    <category term="issues" />
    <summary type="html"><![CDATA[<p>I couldn&#8217;t find a simple explanation of SQLite&#8217;s isolation levels on Google or the <a href="http://sqlite.org/">official site</a>. I just tried them out with pysqlite.</p>

<p><a href="http://sqlite.org/">SQLite</a> has three isolation levels: DEFERRED, IMMEDIATE and EXCLUSIVE. The default is DEFERRED. Since SQLite requires a global db lock to commit writes, you can only have one writer per database with many potential readers. The levels seem to work like this:</p>

<ul>
<li><strong>DEFERRED</strong>. You can start a deferred transaction with &#8220;BEGIN DEFERRED&#8221; and it won&#8217;t block other writes. If you begin a write (UPDATE/INSERT/&#8230;) query it will attempt to acquire the global write lock. So it will either block other writers or block while waiting for other writers to complete their transactions. It will also wait for all the currently-running readers to finish before committing, but the readers aren&#8217;t blocked until you actually commit the transaction. I didn&#8217;t test this, but I assume that while the write is taking place, the readers are blocked.</li>
<li><strong>IMMEDIATE</strong>. &#8220;BEGIN IMMEDIATE&#8221; will attempt to acquire a write lock as soon as possible. If it&#8217;s successful, no other writers will be able to make progress until your transaction is complete, even if there are no modifications in it. Readers aren&#8217;t affected.</li>
<li><strong>EXCLUSIVE</strong>. As soon as &#8220;BEGIN EXCLUSIVE&#8221; is executed, if a write lock is acquired, no other queries can be executed outside the current transaction. They all block until you commit/rollback, including readers.</li>
</ul>

<p>Does this sound right?</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>I couldn&#8217;t find a simple explanation of SQLite&#8217;s isolation levels on Google or the <a href="http://sqlite.org/">official site</a>. I just tried them out with pysqlite.</p>

<p><a href="http://sqlite.org/">SQLite</a> has three isolation levels: DEFERRED, IMMEDIATE and EXCLUSIVE. The default is DEFERRED. Since SQLite requires a global db lock to commit writes, you can only have one writer per database with many potential readers. The levels seem to work like this:</p>

<ul>
<li><strong>DEFERRED</strong>. You can start a deferred transaction with &#8220;BEGIN DEFERRED&#8221; and it won&#8217;t block other writes. If you begin a write (UPDATE/INSERT/&#8230;) query it will attempt to acquire the global write lock. So it will either block other writers or block while waiting for other writers to complete their transactions. It will also wait for all the currently-running readers to finish before committing, but the readers aren&#8217;t blocked until you actually commit the transaction. I didn&#8217;t test this, but I assume that while the write is taking place, the readers are blocked.</li>
<li><strong>IMMEDIATE</strong>. &#8220;BEGIN IMMEDIATE&#8221; will attempt to acquire a write lock as soon as possible. If it&#8217;s successful, no other writers will be able to make progress until your transaction is complete, even if there are no modifications in it. Readers aren&#8217;t affected.</li>
<li><strong>EXCLUSIVE</strong>. As soon as &#8220;BEGIN EXCLUSIVE&#8221; is executed, if a write lock is acquired, no other queries can be executed outside the current transaction. They all block until you commit/rollback, including readers.</li>
</ul>

<p>Does this sound right?</p>
    ]]></content>
  </entry>
  <entry>
    <title>Qt GDB errors</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/qt-gdb-errors-2008-03-23" />
    <id>http://glyphy.com/qt-gdb-errors-2008-03-23</id>
    <published>2008-03-23T01:21:46-07:00</published>
    <updated>2008-03-23T01:21:46-07:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="494" />
    <category term="issues" />
    <summary type="html"><![CDATA[<p>I&#8217;ve been having strange problems with Qt4 applications and GDB. I can&#8217;t debug any Qt4 app in either Eclipse or KDevelop. See <a href="http://lists.trolltech.com/qt-interest/2008-03/msg00664.html">this thread</a> on the qt-interest list. The error I get:</p>

<div class="geshifilter"><pre class="geshifilter-text">Cannot insert breakpoint 0.
Error accessing memory address 0x0: Input/output error.</pre></div>

<p>Running GDB from the command line on the binary works fine. I just found that NetBeans 6.0 with the C++ plugin works fine as well. I wonder what&#8217;s wrong with Eclipse and KDevelop. Could be the way they try to interface with GDB.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>I&#8217;ve been having strange problems with Qt4 applications and GDB. I can&#8217;t debug any Qt4 app in either Eclipse or KDevelop. See <a href="http://lists.trolltech.com/qt-interest/2008-03/msg00664.html">this thread</a> on the qt-interest list. The error I get:</p>

<div class="geshifilter"><pre class="geshifilter-text">Cannot insert breakpoint 0.
Error accessing memory address 0x0: Input/output error.</pre></div>

<p>Running GDB from the command line on the binary works fine. I just found that NetBeans 6.0 with the C++ plugin works fine as well. I wonder what&#8217;s wrong with Eclipse and KDevelop. Could be the way they try to interface with GDB.</p>
    ]]></content>
  </entry>
  <entry>
    <title>XMPP span</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/xmpp-span-2008-03-17" />
    <id>http://glyphy.com/xmpp-span-2008-03-17</id>
    <published>2008-03-17T13:49:28-07:00</published>
    <updated>2008-03-17T13:49:28-07:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="xmpp" />
    <summary type="html"><![CDATA[<p><a href="http://www.saint-andre.com/jabber/Presence-Dial-Tone.pdf">These slides</a> by <a href="http://stpeter.im/">Peter Saint-Andre</a> cover a lot of interesting potential applications of XMPP (and similar technologies). The vastness of applications is astounding.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p><a href="http://www.saint-andre.com/jabber/Presence-Dial-Tone.pdf">These slides</a> by <a href="http://stpeter.im/">Peter Saint-Andre</a> cover a lot of interesting potential applications of XMPP (and similar technologies). The vastness of applications is astounding.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Oh DreamHost</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/oh-dreamhost-2008-03-05" />
    <id>http://glyphy.com/oh-dreamhost-2008-03-05</id>
    <published>2008-03-05T20:45:34-08:00</published>
    <updated>2008-03-07T11:17:12-08:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="meta" />
    <category term="rant" />
    <summary type="html"><![CDATA[<pre><div class="geshifilter"><pre class="geshifilter-text">20:26:50 up 48 days, 23:46,  6 users,  load average: 111.92, 104.49, 104.97</pre></div></pre>

<p>They say that the load on the server is &#8220;still within acceptable levels&#8221;.</p>

<p><em>Update: they fixed the problem. Apparently it was a <a href="http://www.dreamhoststatus.com/2008/03/03/blingy-file-server-issues/">file-server issue</a> causing slow I/O</em></p>
    ]]></summary>
    <content type="html"><![CDATA[<pre><code>20:26:50 up 48 days, 23:46,  6 users,  load average: 111.92, 104.49, 104.97
</code></pre>

<p>They say that the load on the server is &#8220;still within acceptable levels&#8221;.</p>

<p><em>Update: they fixed the problem. Apparently it was a <a href="http://www.dreamhoststatus.com/2008/03/03/blingy-file-server-issues/">file-server issue</a> causing slow I/O</em></p>
    ]]></content>
  </entry>
  <entry>
    <title>Quick update on the XMPP project</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/quick-update-xmpp-project-2008-03-04" />
    <id>http://glyphy.com/quick-update-xmpp-project-2008-03-04</id>
    <published>2008-03-04T08:24:31-08:00</published>
    <updated>2008-03-04T08:24:31-08:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="490" />
    <category term="xmpp" />
    <summary type="html"><![CDATA[<p>Done:</p>

<ul>
<li>Routing protocol. It&#8217;s very simple. Just a dictionary of handlers with sequential routing rules. Will post more about it when I have time.</li>
<li>In-process and threaded handlers. The threaded handlers are messy, but seem to work. They&#8217;ll be required for all I/O operations.</li>
<li>XMPP &lt;stream>s.</li>
<li>SASL PLAIN and DIGEST-MD5 auth (no iq-auth yet, which means most clients can&#8217;t connect yet). Gaim does connect properly, though.</li>
</ul>

<p>TODO:</p>

<ul>
<li>S2S (ie. dialback)</li>
<li>&lt;message>, &lt;presence> from RFC 3921.</li>
<li>rosters and subscriptions  from RFC 3921. Probably won&#8217;t have time for privacy lists this term.</li>
<li>TLS using tlslite. Have been trying to make it work with my own asyncore module (which watches functions as well as sockets!).</li>
<li>docs + c2s/s2s tests.</li>
</ul>
    ]]></summary>
    <content type="html"><![CDATA[<p>Done:</p>

<ul>
<li>Routing protocol. It&#8217;s very simple. Just a dictionary of handlers with sequential routing rules. Will post more about it when I have time.</li>
<li>In-process and threaded handlers. The threaded handlers are messy, but seem to work. They&#8217;ll be required for all I/O operations.</li>
<li>XMPP &lt;stream>s.</li>
<li>SASL PLAIN and DIGEST-MD5 auth (no iq-auth yet, which means most clients can&#8217;t connect yet). Gaim does connect properly, though.</li>
</ul>

<p>TODO:</p>

<ul>
<li>S2S (ie. dialback)</li>
<li>&lt;message>, &lt;presence> from RFC 3921.</li>
<li>rosters and subscriptions  from RFC 3921. Probably won&#8217;t have time for privacy lists this term.</li>
<li>TLS using tlslite. Have been trying to make it work with my own asyncore module (which watches functions as well as sockets!).</li>
<li>docs + c2s/s2s tests.</li>
</ul>
    ]]></content>
  </entry>
  <entry>
    <title>Asynchronous DNS queries in Python</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/asynchronous-dns-queries-python-2008-02-09" />
    <id>http://glyphy.com/asynchronous-dns-queries-python-2008-02-09</id>
    <published>2008-02-09T12:38:35-08:00</published>
    <updated>2008-02-09T12:39:14-08:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="490" />
    <category term="python" />
    <category term="xmpp" />
    <summary type="html"><![CDATA[<p>When you have an application that&#8217;s event-driven (like <a href="http://twistedmatrix.com/trac/">twisted</a>), you&#8217;ve gotta eliminate all potentially blocking operations, or you risk putting your entire app to sleep while you wait for the blocking operation to complete. The XMPP server I&#8217;m working on has to send out DNS queries all the time, and these could take a while. I had to figure out how to make these queries asynchronous, so that they wouldn&#8217;t block the entire server. There are <a href="http://dustman.net/andy/python/adns-python">adns bindings</a>, but the GNU adns library is licensed under the GPL (I&#8217;m trying to stick to more liberal licenses) and not straightforward to install on Windows. There&#8217;s a <a href="http://www.dnspython.org/">DNS toolkit library</a> for python, but it doesn&#8217;t support asynchronous lookups natively. Enter the <a href="http://docs.python.org/lib/module-asyncore.html">asyncore module</a>. The following should allow you to query DNS and then get callbacks to <span class="geshifilter"><span class="geshifilter"><code class="geshifilter-text">handle_read()</code></span></span> when the data is available.</p>

<div class="geshifilter"><pre class="geshifilter-python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">asyncore</span>, <span style="color: #dc143c;">socket</span>
<span style="color: #ff7700;font-weight:bold;">from</span> dns <span style="color: #ff7700;font-weight:bold;">import</span> resolver, rdatatype, rdataclass, message
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> AsyncDNS<span style="color: black;">&#40;</span><span style="color: #dc143c;">asyncore</span>.<span style="color: black;">dispatcher</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">asyncore</span>.<span style="color: black;">dispatcher</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">r</span> = resolver.<span style="color: black;">Resolver</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">query</span> = <span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">create_socket</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">socket</span>.<span style="color: black;">AF_INET</span>, <span style="color: #dc143c;">socket</span>.<span style="color: black;">SOCK_DGRAM</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">r</span>.<span style="color: black;">nameservers</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, <span style="color: #008000;">self</span>.<span style="color: black;">r</span>.<span style="color: black;">port</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> makeQuery<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, server<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">query</span> = message.<span style="color: black;">make_query</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'_xmpp-server._tcp.%s'</span> % server,
                                   rdatatype.<span style="color: black;">SRV</span>, rdataclass.<span style="color: black;">IN</span><span style="color: black;">&#41;</span>.<span style="color: black;">to_wire</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> writable<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">query</span><span style="color: black;">&#41;</span> &gt; <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> handle_read<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        data = <span style="color: #008000;">self</span>.<span style="color: black;">recv</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4096</span><span style="color: black;">&#41;</span>
        answer = message.<span style="color: black;">from_wire</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> answer.<span style="color: black;">answer</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>.<span style="color: black;">to_text</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> handle_write<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">send</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">query</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">query</span> = <span style="color: #483d8b;">''</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> handle_accept<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>: <span style="color: #ff7700;font-weight:bold;">pass</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> handle_connect<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>: <span style="color: #ff7700;font-weight:bold;">pass</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> handle_bind<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>: <span style="color: #ff7700;font-weight:bold;">pass</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> handle_close<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">self</span>.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    d = AsyncDNS<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    d.<span style="color: black;">makeQuery</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'livejournal.com'</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">asyncore</span>.<span style="color: black;">loop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div>
    ]]></summary>
    <content type="html"><![CDATA[<p>When you have an application that&#8217;s event-driven (like <a href="http://twistedmatrix.com/trac/">twisted</a>), you&#8217;ve gotta eliminate all potentially blocking operations, or you risk putting your entire app to sleep while you wait for the blocking operation to complete. The XMPP server I&#8217;m working on has to send out DNS queries all the time, and these could take a while. I had to figure out how to make these queries asynchronous, so that they wouldn&#8217;t block the entire server. There are <a href="http://dustman.net/andy/python/adns-python">adns bindings</a>, but the GNU adns library is licensed under the GPL (I&#8217;m trying to stick to more liberal licenses) and not straightforward to install on Windows. There&#8217;s a <a href="http://www.dnspython.org/">DNS toolkit library</a> for python, but it doesn&#8217;t support asynchronous lookups natively. Enter the <a href="http://docs.python.org/lib/module-asyncore.html">asyncore module</a>. The following should allow you to query DNS and then get callbacks to <span class="geshifilter"><code class="geshifilter-text">handle_read()</code></span> when the data is available.</p>

<div class="geshifilter"><pre class="geshifilter-python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">asyncore</span>, <span style="color: #dc143c;">socket</span>
<span style="color: #ff7700;font-weight:bold;">from</span> dns <span style="color: #ff7700;font-weight:bold;">import</span> resolver, rdatatype, rdataclass, message
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> AsyncDNS<span style="color: black;">&#40;</span><span style="color: #dc143c;">asyncore</span>.<span style="color: black;">dispatcher</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">asyncore</span>.<span style="color: black;">dispatcher</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">r</span> = resolver.<span style="color: black;">Resolver</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">query</span> = <span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">create_socket</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">socket</span>.<span style="color: black;">AF_INET</span>, <span style="color: #dc143c;">socket</span>.<span style="color: black;">SOCK_DGRAM</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">r</span>.<span style="color: black;">nameservers</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, <span style="color: #008000;">self</span>.<span style="color: black;">r</span>.<span style="color: black;">port</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> makeQuery<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, server<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">query</span> = message.<span style="color: black;">make_query</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'_xmpp-server._tcp.%s'</span> % server,
                                   rdatatype.<span style="color: black;">SRV</span>, rdataclass.<span style="color: black;">IN</span><span style="color: black;">&#41;</span>.<span style="color: black;">to_wire</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> writable<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">query</span><span style="color: black;">&#41;</span> &gt; <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> handle_read<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        data = <span style="color: #008000;">self</span>.<span style="color: black;">recv</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4096</span><span style="color: black;">&#41;</span>
        answer = message.<span style="color: black;">from_wire</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> answer.<span style="color: black;">answer</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>.<span style="color: black;">to_text</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> handle_write<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">send</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">query</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">query</span> = <span style="color: #483d8b;">''</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> handle_accept<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>: <span style="color: #ff7700;font-weight:bold;">pass</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> handle_connect<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>: <span style="color: #ff7700;font-weight:bold;">pass</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> handle_bind<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>: <span style="color: #ff7700;font-weight:bold;">pass</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> handle_close<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">self</span>.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    d = AsyncDNS<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    d.<span style="color: black;">makeQuery</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'livejournal.com'</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">asyncore</span>.<span style="color: black;">loop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div>
    ]]></content>
  </entry>
  <entry>
    <title>EPIGRAMS IN PROGRAMMING</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/epigrams-programming-2008-02-06" />
    <id>http://glyphy.com/epigrams-programming-2008-02-06</id>
    <published>2008-02-06T13:59:57-08:00</published>
    <updated>2008-02-06T14:01:05-08:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="cs" />
    <category term="lists" />
    <summary type="html"><![CDATA[<p><a href="http://www.cs.yale.edu/quotes.html">EPIGRAMS IN PROGRAMMING</a> seem to be quite old (1982), but most are still relevant. Some that I found interesting:</p>

<ul>
<li>7. <strong>It is easier to write an incorrect program than understand a correct one.</strong> When you see a working piece of code that you don&#8217;t like (for whatever reason), try to understand it first before deciding to rewrite it &#8220;The Right Way&#8221;</li>
<li>19. <strong>A language that doesn&#8217;t affect the way you think about programming, is not worth knowing.</strong> I better learn COBOL, &#8216;cause I hear it&#8217;s a whole other programming experience. Also, try saying that to someone who&#8217;s out of a job and has a family to feed. You learn whatever gets you to tomorrow in some situations.</li>
<li>21. <strong>Optimization hinders evolution.</strong> Highly-optimized code sometimes results in <a href="http://www.google.com/codesearch?q=%22not+expected+to+understand+this%22&amp;hl=en&amp;btnG=Search+Code">&#8220;You&#8217;re not expected to understand this&#8221;</a></li>
<li>26. <strong>There will always be things we wish to say in our programs that in all known languages can only be said poorly.</strong> I guess this is why new programming languages continue to be invented.</li>
<li>57. <strong>It is easier to change the specification to fit the program than vice versa.</strong></li>
<li>64. <strong>Often it is the means that justify the ends: Goals advance technique and technique survives even when goal structures crumble.</strong></li>
<li>94. <strong>Interfaces keep things tidy, but don&#8217;t accelerate growth: Functions do.</strong> But keeping things tidy is necessary to have growth or you end up wasting time figuring out what goes where. So, in a way, interfaces do accelerate growth.</li>
<li>117. <strong>It goes against the grain of modern education to teach children to program. What fun is there in making plans, acquiring discipline in organizing thoughts, devoting attention to detail and learning to be self-critical?</strong> &#8220;It goes against the grain of modern education to teach children to (important activity). What fun is there in (necessary skill), (good quality)*3?&#8221; I wonder if I&#8217;ll be hating on the <em>modern education system</em> when I&#8217;m 60.</li>
</ul>

<p>A bunch of these are so obvious they don&#8217;t say much at all, but it just seems like Alan couldn&#8217;t stop cranking them out after the first few.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p><a href="http://www.cs.yale.edu/quotes.html">EPIGRAMS IN PROGRAMMING</a> seem to be quite old (1982), but most are still relevant. Some that I found interesting:</p>

<ul>
<li>7. <strong>It is easier to write an incorrect program than understand a correct one.</strong> When you see a working piece of code that you don&#8217;t like (for whatever reason), try to understand it first before deciding to rewrite it &#8220;The Right Way&#8221;</li>
<li>19. <strong>A language that doesn&#8217;t affect the way you think about programming, is not worth knowing.</strong> I better learn COBOL, &#8216;cause I hear it&#8217;s a whole other programming experience. Also, try saying that to someone who&#8217;s out of a job and has a family to feed. You learn whatever gets you to tomorrow in some situations.</li>
<li>21. <strong>Optimization hinders evolution.</strong> Highly-optimized code sometimes results in <a href="http://www.google.com/codesearch?q=%22not+expected+to+understand+this%22&amp;hl=en&amp;btnG=Search+Code">&#8220;You&#8217;re not expected to understand this&#8221;</a></li>
<li>26. <strong>There will always be things we wish to say in our programs that in all known languages can only be said poorly.</strong> I guess this is why new programming languages continue to be invented.</li>
<li>57. <strong>It is easier to change the specification to fit the program than vice versa.</strong></li>
<li>64. <strong>Often it is the means that justify the ends: Goals advance technique and technique survives even when goal structures crumble.</strong></li>
<li>94. <strong>Interfaces keep things tidy, but don&#8217;t accelerate growth: Functions do.</strong> But keeping things tidy is necessary to have growth or you end up wasting time figuring out what goes where. So, in a way, interfaces do accelerate growth.</li>
<li>117. <strong>It goes against the grain of modern education to teach children to program. What fun is there in making plans, acquiring discipline in organizing thoughts, devoting attention to detail and learning to be self-critical?</strong> &#8220;It goes against the grain of modern education to teach children to (important activity). What fun is there in (necessary skill), (good quality)*3?&#8221; I wonder if I&#8217;ll be hating on the <em>modern education system</em> when I&#8217;m 60.</li>
</ul>

<p>A bunch of these are so obvious they don&#8217;t say much at all, but it just seems like Alan couldn&#8217;t stop cranking them out after the first few.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Caffeine</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/caffeine-2008-02-03" />
    <id>http://glyphy.com/caffeine-2008-02-03</id>
    <published>2008-02-03T12:16:34-08:00</published>
    <updated>2008-02-03T12:16:34-08:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="random" />
    <summary type="html"><![CDATA[<p><a href="http://www.sinfest.net/archive_page.php?comicID=2680"><img src="http://www.sinfest.net/comikaze/comics/2008-01-07.gif" alt="caffeine" title="" /></a></p>

<p>Basically, yes.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p><a href="http://www.sinfest.net/archive_page.php?comicID=2680"><img src="http://www.sinfest.net/comikaze/comics/2008-01-07.gif" alt="caffeine" title="" /></a></p>

<p>Basically, yes.</p>
    ]]></content>
  </entry>
  <entry>
    <title>New Year&#039;s Resolutions at work</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/new-years-resolutions-work-2008-01-30" />
    <id>http://glyphy.com/new-years-resolutions-work-2008-01-30</id>
    <published>2008-01-30T11:47:02-08:00</published>
    <updated>2008-01-30T11:47:02-08:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="random" />
    <category term="stats" />
    <summary type="html"><![CDATA[<p><img src="http://glyphy.com/gal/d/1162-1/trends-gym.png" alt="Resolutions" title="" /></p>

<p>Come to your own conclusions&#8230;</p>
    ]]></summary>
    <content type="html"><![CDATA[<p><img src="http://glyphy.com/gal/d/1162-1/trends-gym.png" alt="Resolutions" title="" /></p>

<p>Come to your own conclusions&#8230;</p>
    ]]></content>
  </entry>
  <entry>
    <title>XMPP in the news</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/xmpp-news-2008-01-28" />
    <id>http://glyphy.com/xmpp-news-2008-01-28</id>
    <published>2008-01-28T15:33:44-08:00</published>
    <updated>2008-02-06T15:52:26-08:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="490" />
    <category term="xmpp" />
    <summary type="html"><![CDATA[<p>There&#8217;s quite a bit of commotion around XMPP. <a href="http://www.dehora.net/journal/2008/01/26/journal-notes/">Bill de hÓra</a> collects a bunch of links in a single post. I stumbled recently upon <a href="http://iss.im/">ISS</a>, which uses JIDs for identities. <a href="http://www.rssping.com/">RSSPing</a> looks like a hack compared to the XMPP standard (with <a href="http://www.xmpp.org/extensions/xep-0060.html">PubSub</a>).</p>

<p>This is all exciting as my <a href="https://stanley.cdf.toronto.edu/drproject/consulting-2008-01">CSC490</a> project involves creating a Python-based XMPP framework (disguised as a server).</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>There&#8217;s quite a bit of commotion around XMPP. <a href="http://www.dehora.net/journal/2008/01/26/journal-notes/">Bill de hÓra</a> collects a bunch of links in a single post. I stumbled recently upon <a href="http://iss.im/">ISS</a>, which uses JIDs for identities. <a href="http://www.rssping.com/">RSSPing</a> looks like a hack compared to the XMPP standard (with <a href="http://www.xmpp.org/extensions/xep-0060.html">PubSub</a>).</p>

<p>This is all exciting as my <a href="https://stanley.cdf.toronto.edu/drproject/consulting-2008-01">CSC490</a> project involves creating a Python-based XMPP framework (disguised as a server).</p>
    ]]></content>
  </entry>
  <entry>
    <title>Workrave keystrokes since 2005</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/workrave-keystrokes-2005-2008-01-04" />
    <id>http://glyphy.com/workrave-keystrokes-2005-2008-01-04</id>
    <published>2008-01-04T21:51:16-08:00</published>
    <updated>2008-01-04T21:52:58-08:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="stats" />
    <category term="work" />
    <summary type="html"><![CDATA[<p><img src="http://glyphy.com/files/workrave-20080105.png" alt="workrave" title="" /></p>

<p>This graph was generated using <a href="http://workrave.svn.sourceforge.net/viewvc/workrave/workrave/trunk/contrib/plot/">gnuplot-workrave</a>. The steady slope from 2005 to 2006 is caused by too little data between the two extremes. I think I didn&#8217;t have <a href="http://www.workrave.org/">workrave</a> running during that time. The recent drop was due to the holidays.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p><img src="http://glyphy.com/files/workrave-20080105.png" alt="workrave" title="" /></p>

<p>This graph was generated using <a href="http://workrave.svn.sourceforge.net/viewvc/workrave/workrave/trunk/contrib/plot/">gnuplot-workrave</a>. The steady slope from 2005 to 2006 is caused by too little data between the two extremes. I think I didn&#8217;t have <a href="http://www.workrave.org/">workrave</a> running during that time. The recent drop was due to the holidays.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Beautiful Code &amp; Dreaming in Code</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/beautiful-code-dreaming-code" />
    <id>http://glyphy.com/beautiful-code-dreaming-code</id>
    <published>2007-12-28T11:23:47-08:00</published>
    <updated>2007-12-28T11:24:20-08:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="books" />
    <category term="cs" />
    <summary type="html"><![CDATA[<p><img src="http://glyphy.com/gal/d/148-2/IMG_0335.JPG" alt="Beautiful Code &amp; Dreaming in Code" title="" /></p>

<p>Now to find the time to read both before the semester starts.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p><img src="http://glyphy.com/gal/d/148-2/IMG_0335.JPG" alt="Beautiful Code &amp; Dreaming in Code" title="" /></p>

<p>Now to find the time to read both before the semester starts.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Pink Hippo</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/pink-hippo" />
    <id>http://glyphy.com/pink-hippo</id>
    <published>2007-12-23T18:48:52-08:00</published>
    <updated>2007-12-25T10:36:19-08:00</updated>
    <author>
      <name>dv</name>
    </author>
    <category term="images" />
    <category term="random" />
    <summary type="html"><![CDATA[<p><img src="http://farm3.static.flickr.com/2001/2132481744_c257ff3bb7.jpg" alt="Pink Hippo" title="" /></p>
    ]]></summary>
    <content type="html"><![CDATA[<p><img src="http://farm3.static.flickr.com/2001/2132481744_c257ff3bb7.jpg" alt="Pink Hippo" title="" /></p>
    ]]></content>
  </entry>
  <entry>
    <title>First post</title>
    <link rel="alternate" type="text/html" href="http://glyphy.com/content/first-post" />
    <id>http://glyphy.com/content/first-post</id>
    <published>2007-12-11T16:57:40-08:00</published>
    <updated>2007-12-24T12:41:13-08:00</updated>
    <author>
      <name>dv</name>
    </author>
    <summary type="html"><![CDATA[<p>Testing. 1, 2, 3.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>Testing. 1, 2, 3.</p>
    ]]></content>
  </entry>
</feed>
