<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Doing better</title>
	<atom:link href="http://www.longacre-scm.com/blog/index.php/feed" rel="self" type="application/rss+xml" />
	<link>http://www.longacre-scm.com/blog</link>
	<description>Opinions on CM, software development, and process automation from Longacre.</description>
	<lastBuildDate>Wed, 31 Mar 2010 20:40:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Add VC &#8220;branch&#8221; to your prompt</title>
		<link>http://www.longacre-scm.com/blog/index.php/2010/03/add-vc-branch-to-your-prompt</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2010/03/add-vc-branch-to-your-prompt#comments</comments>
		<pubDate>Wed, 31 Mar 2010 20:40:18 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/?p=85</guid>
		<description><![CDATA[Inspired by a recent discussion on IRC, here&#8217;s another little piece of bash script goodness. This one goes in your startup files, and it integrates with your $PS1 prompt variable. The script adds your VC branch to the prompt. I&#8217;ve included SVN and GIT, and I&#8217;m sure you could trivially add CVS if need be. [...]]]></description>
			<content:encoded><![CDATA[<p>Inspired by a recent discussion on IRC, here&#8217;s another little piece of bash script goodness. This one goes in your startup files, and it integrates with your $PS1 prompt variable. The script adds your VC branch to the prompt. I&#8217;ve included SVN and GIT, and I&#8217;m sure you could trivially add CVS if need be. Other VC tools may not be such a good fit &#8212; in many cases, they encode project info as part of the path, so the standard &#8217;show the working directory&#8217; prompt is enough.</p>
<p>(On the other hand, if you&#8217;ve got one that needs special treatment, drop me a line and I&#8217;ll add it here.)</p>
<p><code>
<pre>
if which git > /dev/null
then
	parse_git_path() {
		if [[ -d .git ]]
		then
			git branch --no-color \
			| sed -rne '/^\*/s/^\* (.*)$/(git:\1) /p'
			return 0
		else
			return 1
		fi
	}
else
	parse_git_path() {
		return 1
	}
fi

if which svn > /dev/null
then
	parse_svn_path() {
		if [[ -d .svn ]]
		then
			local rroot=$(svn info | sed -ne 's/Repository Root: //p')
			svn info 		\
			| sed -rne "s#^URL: $rroot/(trunk|branches/[^/]*).*#(svn:^/\1) #p"
			return 0
		else
			return 1
		fi
	}
else
	parse_svn_path() {
		return 1
	}
fi

parse_vc_path() {
	parse_git_path \
	|| parse_svn_path
}

export PS1="\[\e]0;\$(parse_vc_path)\w\a\]${debian_chroot:+($debian_chroot)}\$(parse_vc_path)\w\$ "
</pre>
<p></code><br />
The key is that bash performs command substitution on PS1 each time it prints it, so you can have whatever command sequence you want get run. In this case, it&#8217;s a script that does whatever processing is needed in order to determine the &#8220;branch&#8221;, if any, that you&#8217;re on.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2010/03/add-vc-branch-to-your-prompt/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Some bash goodness</title>
		<link>http://www.longacre-scm.com/blog/index.php/2009/10/some-bash-goodness</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2009/10/some-bash-goodness#comments</comments>
		<pubDate>Wed, 28 Oct 2009 15:09:48 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Off-topic]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/index.php/2009/10/some-bash-goodness</guid>
		<description><![CDATA[Here&#8217;s some bash goodness (well, not really) to make &#8216;less&#8217; a little bit more useful.
&#160;
less() {
 &#160; &#160; &#160; &#160;local -a args
&#160;
 &#160; &#160; &#160; &#160;for arg
 &#160; &#160; &#160; &#160;do
 &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;case &#8220;$arg&#8221; in
 &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;*:[[:digit:]]* )
 &#160; &#160; &#160; &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<div>Here&#8217;s some bash goodness (well, not really) to make &#8216;less&#8217; a little bit more useful.</div>
<div>&#160;</div>
<div>less() {</div>
<div> &#160; &#160; &#160; &#160;local -a args</div>
<div>&#160;</div>
<div> &#160; &#160; &#160; &#160;for arg</div>
<div> &#160; &#160; &#160; &#160;do</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;case &#8220;$arg&#8221; in</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;*:[[:digit:]]* )</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;line=${arg/#+(?):/}</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;args[${#args[*]}]=&#8221;+$line&#8221;</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;arg=${arg/%:+(?)/}</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;;;</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;esac</div>
<div>&#160;</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;args[${#args[*]}]=$arg</div>
<div> &#160; &#160; &#160; &#160;done</div>
<div>&#160;</div>
<div> &#160; &#160; &#160; &#160;$( which less ) &#8220;${args[@]}&#8221;</div>
<div>}</div>
<div>&#160;</div>
<div>Basically, this shell function loads when you tell it to (in your .profile, likely), and it replaces the &#8216;less&#8217; command. When you type &#8216;less &#8230;&#8217; on the command line, the function runs.</div>
<div>&#160;</div>
<div>It scans through the args, looking for one like filename.c:24, and if it finds that kind of arg, it replaces it with +24 filename.c &#8212; translating the syntax used by a *lot* of compilers into the syntax used by less for opening a file and jumping directly to the line number.</div>
<div>&#160;</div>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2009/10/some-bash-goodness/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why not 2 stacks?</title>
		<link>http://www.longacre-scm.com/blog/index.php/2009/06/why-not-2-stacks</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2009/06/why-not-2-stacks#comments</comments>
		<pubDate>Wed, 01 Jul 2009 00:05:13 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Off-topic]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/?p=76</guid>
		<description><![CDATA[I was googling around the other day for compiler wisdom when I stumbled on a computer security &#8220;research&#8221; paper. Some one or ones were postulating some theoretical result about vulnerability to buffer overflow attacks in blah, blah, blah special case. I didn&#8217;t read it, because that&#8217;s not what I was after.
But it made me think: [...]]]></description>
			<content:encoded><![CDATA[<p>I was googling around the other day for compiler wisdom when I stumbled on a computer security &#8220;research&#8221; paper. Some one or ones were postulating some theoretical result about vulnerability to buffer overflow attacks in <i>blah, blah, blah</i> special case. I didn&#8217;t read it, because that&#8217;s not what I was after.</p>
<p>But it made me think: how come Microsoft hasn&#8217;t just solved this problem already? Two &#8220;stacks&#8221; would wipe out the overflow attack problem at minimal cost.<br />
<span id="more-76"></span></p>
<h3>Back Story</h3>
<p>If you don&#8217;t know, here&#8217;s a very (!) short summary of the problem.</p>
<p>Computer software uses &#8220;subroutines&#8221; to do everything. In fact, even the &#8220;main&#8221; program is a subroutine. Because subroutines can call other subroutines, they can &#8220;stack up&#8221;. That is, &#8220;main&#8221; can call &#8220;sell ticket&#8221; which can call &#8220;print schedule&#8221; which can call &#8220;draw table&#8221;, etc.</p>
<h4>What&#8217;s a stack?</h4>
<p>In modern systems, there is no really good way to keep track of how many routines will get stacked up, a general-purpose data structure called a &#8220;stack&#8221; is used. This is so important that CPU&#8217;s explicitly support a single &#8220;call stack&#8221; with special CPU instructions like push and pop, special registers to access the stack, and all kinds of <i>incredibly expensive</i> stuff. </p>
<p>A stack works by &#8220;stacking&#8221; data, in much the same way they stack plates at a buffet restaurant (or cafeteria). The only data item you can get to is the one at the &#8220;top&#8221; of the stack. (The only plate you can take is the one on the top of the stack. See?) If you want to put on more data, it goes on the top of the stack, and the stack grows. If you want to take off data, you take it off the top of the stack, and the stack shrinks.</p>
<p>In this case, though, there are two ways to think about what &#8220;data&#8221; means. One way is to think of data as being individual units. One number goes on the stack, then another number goes on top of it, etc. But another way is to think of data &#8220;sets&#8221; going on the stack. If you think about the back button on your web browser, it acts like a stack. You click on a link, and a page gets <strong>pushed</strong> on to the &#8220;history&#8221; in the browser. You click &#8220;Back&#8221; and a page gets <strong>popped</strong> off the stack, leaving a different page visible in the browser. But these pages aren&#8217;t just a single number. There&#8217;s a URL, the page contents, maybe some form data, etc.</p>
<p>In terms of computer subroutines, each subroutine may have some &#8220;local data&#8221; that it needs to store. The URL of a web page, or the name of the current user, for example. And this data is expected to be used within the subroutine, maybe passed down into any sub-subroutines that get called, and then it will disappear when the subroutine finishes. </p>
<p>So a subroutine may have a bunch of local data, much like a web page in your browers. That can also be managed as part of a stack, using what is called a <em>stack frame</em>. A stack frame is a collection of data that all gets jammed onto the stack at one time, so the subroutine can use it. Again,&#8221;modern CPUs&#8221; (pretty much all of them built since the 1970&#8217;s) support this directly.</p>
<h4>How important is the stack?</h4>
<p>The de facto standard computer in the world today is the Intel x86 CPU of some kind: Pentium, Opteron, whatever you want to call it. Back when dinosaurs roamed the earth and nobody thought a 16-bit computer was worth the extra money over a 8-bit computer, the x86 family had about 30,000 transistors on board. Now, when people are arguing the relative merits of 32 versus 64 bit computing, the transistor count is about a billion.</p>
<p>The x86 family of computers work using &#8220;registers.&#8221; A register is a place in the center of the CPU where a number can be held while other stuff gets done to it. If you want to add two numbers, you use a register. If you want to store the result, you probably use another register. They are absolutely crucial to the design of the x86, and most other widespread CPUs. (There are alternative architectures: stack based and accumulator based CPUs. But nobody buys them except for special applications.)</p>
<p>The x86 registers back in the time of the 8088 and 8086 computer were called:</p>
<ul>
<li><tt>AX</tt> The <em>accumulator</em> register, best for math.</li>
<li><tt>BX</tt> The <em>base address</em> register, best for pointer references.</li>
<li><tt>CX</tt> The <em>counter</em> register, best for loop counts.</li>
<li><tt>DX</tt> The <em>data</em> register, used for multiply/divide operations, I/O operations, and indirect addressing.</li>
<li><tt>SI</tt> The <em>source index</em> register, for memory-to-memory block operations, like copying data.</li>
<li><tt>DI</tt> The <em>destination index</em> register, used for memory block operations, like SI.</li>
<li><tt>BP</tt> The <em>base pointer</em> register, used to point to the base of the stack frame.</li>
<li><tt>SP</tt> The <em>stack pointer</em> register, used to point to the current &#8220;top&#8221; of the stack.</li>
</ul>
<p>There were some additional registers, like IP, flags, CS, DS, ES, and SS. But they weren&#8217;t (and still aren&#8217;t) general purpose registers, can&#8217;t participate in computations, and generally don&#8217;t get modified much by programs. Because the registers listed above are <em>general purpose</em> registers, they can be used for things not listed above. For example, if you need to store a temporary intermediate result while you are computing some other value, you can always jam it into the DI register. (or SI, or DX, or whatever you like). But not BP or SP.</p>
<p>So back in the day, when we had to carve our own computers out of rocks using nothing buy a bronze chisel and a wooden mallet, BP and SP were given over to the stack frame. That&#8217;s two registers <em>out of eight</em> &#8212; 25%, for you liberal arts majors &#8212; assigned to do the job of keeping track of the stack.</p>
<h4>And now?</h4>
<p>When the 80&#215;86 family went 32-bit, the registers changed. The 32-bit registers were called &#8220;extended&#8221; registers, and so the names became: <tt>eax, ebx, ecx, edx, edi, esi, ebp, esp</tt>. </p>
<p>Now, with the advent of the 64-bit x86 family, the names have changed again: <tt>rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp.</tt> But in addition, AMD added 8 new registers to the x64 architecture, and Intel followed suit.</p>
<p>This means that if you&#8217;re using a 32-bit CPU, or a 64-bit CPU in compatibility mode, you&#8217;re using 8 registers, still, and 2 of them are dedicated to the stack, still. (25%, still, for you liberal arts majors.) If you&#8217;re using a 64-bit CPU in 64-bit mode, then you&#8217;ve got 16 registers (that&#8217;s 12.5% for all you Art History grads).</p>
<p>So the stack frame, and the stack pointer, and this whole stack &#8220;thang&#8221; are pretty important.</p>
<h3>What&#8217;s a buffer overflow attack?</h3>
<p>So there&#8217;s a stack, and your subroutines use it. The most obvious way they can use it is to store a &#8220;return address&#8221; on it. If you have a subroutine called sub_1, it might have the stack set up like this:</p>
<pre>
    :
  ????
  ????
  1234 < -- SP
</pre>
<p>Where the SP (stack pointer) points to 1234. What's 1234? Well, it's the return address -- an address is a location in computer memory -- where it will send program control when it finishes doing whatever it is doing.</p>
<p>And if the sub_1 routine calls a sub_2 routine, the stack will look like:
</pre>
<pre>
    :
  ????
  ????
  1234
  1299 < -- SP
</pre>
<p>When the CPU executes a <tt>call</tt> instruction, it pushes the return address (of the instruction right after the call) onto the stack automatically. (And yes, on Intel platforms the stack always goes down instead of up. Don't ask why, it doesn't matter.)</p>
<p>When the sub_2 routine returns control to sub_1, it pops the stack and uses the address that it gets to branch back.
</pre>
<pre>
    :
  ????
  ????
  1234 < -- SP
  1299
</pre>
<p>Of course the 1299 is still down there -- it doesn't get erased. Instead, the SP adds 4 (4 is the size of a return address on a 32-bit [4 byte] CPU) and we go on. Very efficient, very fast, and very automatic with all the special instruction support.</p>
<h4>Stack Frames, redux</h4>
<p>When the program has local data it needs to store, the situation gets a little more complex. The caller pushes a return address, then the callee (the local subroutine) moves the stack pointer a little bit more, to make room. If sub_2 needs 12 bytes of storage, the <em>preamble</em> of the subroutine looks like this:
</pre>
<pre>
   push(ebp)
   ebp = esp
   esp = esp - 12
</pre>
<p>A preamble is a standard set of code that gets executed at the top of every function. It is generated automatically by the compiler &#8212; programmers don&#8217;t have to think about inserting it.</p>
<p>When it comes time to clean up and leave the subroutine, the corresponding code is the <em>postamble</em> and it does something like:</p>
<pre>
   esp = esp + 12
   pop ebp
   return
</pre>
<p>(In fact, this is wrong. But the effect is the same and it&#8217;s easier for you to understand.)</p>
<p>Before the subroutine is called, the stack looks like:</p>
<pre>
    :
  ????
  ????
  1234   < -- SP
</pre>
<p>Then when the call happens, the stack looks like:
</pre>
<pre>
    :
  ????
  ????
  1234
  1299  < -- SP
</pre>
<p>Then when the preamble runs, we get:
</pre>
<pre>
    :
  ????
  ????
  1234
  1299
   BP'  < -- BP
   ?
   ?
   ?     <-- SP (12 bytes = 3 x 32bit words of "stack frame" storage)
</pre>
<p>Note that the new BP is pointing to the place on the stack where the previous BP was stored.</p>
<h4>So?</h4>
<p>So there's a stack frame, and it's a little complex, and it's sitting there on the stack. And in the middle of that stack is the "local data" the subroutine needs.</p>
<p>Sometimes the "local data" includes what is called a "buffer." A buffer is just a space to store a bunch of characters in a row. For example, if the program is going to ask me for my name and address, it needs a place to store however-many characters go into a name and address.</p>
<p>If the buffer is 12 bytes long, I could enter my name as "Austin" and there would be not problem. But if I entered "Austin Hastings" (14 letters, with the space) the buffer would not be long enough to store the name. The problem is that if I am allowed to just enter any old thing, I might deliberately do something destructive. Suppose we are using our previous example:
</pre>
<pre>
    :
  ????
  ????
  1234
  1299
   BP'  < -- BP
   ?
   ?
   ?     <-- SP (12 bytes = 3 x 32bit words of "stack frame" storage)
</pre>
<p>If I type my name as "Austin Hastings", the buffer overflows, like this:
</pre>
<pre>
    :
  ????
  ????
  1234
  1299
  ngs   < -- BP
  asti
  in H
  Aust  <-- SP
</pre>
<p>The old value of BP gets wiped out, and so the calling subroutine will have a bunch of bogus data (because it accesses all the local variables relative to where BP is pointing).</p>
<p>But if I type my name as "Austin Hastings.1215" look what happens to the return address that is supposed to point to the subroutine that called us:
</pre>
<pre>
    :
  ????
  ????
  1234
  1215    -- look here!
  ngs.   < -- BP
  asti
  in H
  Aust  <-- SP
</pre>
<p>See? The return address got changed by me typing in a special, too-long name. This is called a "buffer overflow attack", and if done right it can cause the subroutine to return control to a new program, written by the attacker.</p>
<h3>Why can Microsoft solve the problem?</h3>
<p>First, Microsoft writes Windows, the most attacked system in the world. And it writes the Microsoft C/C++ compiler, which is the tool of choice for compiling on Windows. Since anything Microsoft does will get copied by the Linux and Apple guys, this is a no-brainer. If Microsoft solves the problem, everyone will copy them and solve the problem for their own sites.</p>
<h3>Okay, <em>how</em> can Microsoft solve the problem?</h3>
<p>The solution to the "attack" part of the problem is to use two stacks. There are two registers already, and one of them rarely gets used (SP). So split them into two different stacks, and you eliminate the ability of an attacker to overwrite the return address (by separating the stack frame data from the "just-a-stack" data).</p>
<h4>Details</h4>
<p>Here's what the previous example would look like with two stacks.
</pre>
<pre>
  "Frames":          "Stack":
      :                1234
    ????               EBP(1)  < -- SP(2)
    ????  <-- BP(2)    1299
    ....               EBP(2)  <-- SP(3)
    ....
    ....  <-- BP(3)
</pre>
<p>Notice that I've drawn the buffer as dots, and whatever was in the caller's local data as question marks. Notice also that the important data -- the frame pointers and return addresses -- are in a totally different place from the stack frame data. This means that no buffer overflow attack can reach them. </p>
<h4>That's it?</h4>
<p>Yep. That's it.</p>
<p>Mind you, it's an expensive it. But not a horribly expensive one. Microsoft, and the GCC folks, and Intel, and anybody else that writes a compiler, would have to come up with a transition plan to take us from one system to another. It would probably easier for Microsoft, since they can deliver their system (Windows) all at once. This recompile would have to happen for almost every problem, so it might take a while for total coverage. But the "most attacked" programs are things like email servers, web servers, the PHP interpreter, etc. There is a pretty short list of those, and getting them secured might take an hour and a half, if everyone would work together.</p>
<h4>Any problems with this idea?</h4>
<p>First, it doesn't just magically make everything work. Some solutions, like W(+)E, try to do that. If you can just "solve it in hardware" then the problem goes away without messing around with that 23-year-old program that the boss uses but nobody has the source for.</p>
<p>Second, this approach doesn't require anybody to buy a new computer. (But keep reading!) So unless Microsoft forces an upgrade with Windows 7 or 8 or whatever (and when have they ever forced an upgrade?) there's no money in it for the CPU vendors.</p>
<p>Also, don't forget that this only protects against buffer overrun attacks that try to force code execution. It won't protect you from corruption of <em>data</em> that is in a stack frame buffer or local variable. Someone might try to rewrite their account balance, or change your password, or whatever. </p>
<h4>Checksum the Stack Frame</h4>
<p>There's a solution for that, too. And it could involve new hardware. Just create a "checksum" value for the stack frame, and put it right at the end of each subroutine's frame. That way, if an attacker overruns a buffer it will destroy the checksum. </p>
<p>Obviously I don't mean a real checksum. What I mean is something unpredictable, unlikely to occur at random, and easily checked. Most of the registers wouldn't work, since their values are generally predictable. It would make sense to create a dedicated register for this on the CPU -- which would also allow Intel to make some new hardware -- and push the "random" value on both the frame stack and the SP stack (for checking).</p>
<h3>If you're so damn smart, why aren't you rich?</h3>
<p>I used to do a lot of assembly programming. So I've always kind of wondered why this wasn't obvious to everybody else. And it may well be that there's some critical flaw in the logic. Probably having to do with interrupt-proofing the two-stack transition. </p>
<p>But maybe there's not. Maybe it's just obvious to me. In which case, I hereby demand that anyone who implements this must call it "Austin's Device". And if you implement the checksum idea, that shall be "Austin's Other Device." </p>
<p>But there's an old joke about an Economics professor and one of his grad students walking across the quad. And the grad student says, "Look, professor! There's a $100 bill lying on the ground."</p>
<p>To which the professor replies, "Don't be absurd. If there were really a $100 bill lying on the ground, someone would pick it up."</p>
<p>Maybe you know what's wrong with my clever device? If so, please let me know.</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2009/06/why-not-2-stacks/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Things left unsaid&#8230;</title>
		<link>http://www.longacre-scm.com/blog/index.php/2009/06/things-left-unsaid</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2009/06/things-left-unsaid#comments</comments>
		<pubDate>Sat, 27 Jun 2009 23:15:18 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Off-topic]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/?p=69</guid>
		<description><![CDATA[In my copious spare time I&#8217;m working on a programming language called &#8220;Close.&#8221; It&#8217;s a C-like systems programming language targeted at the Parrot VM.
Now, I&#8217;m not a compiler guy. But I don&#8217;t have to be. Because Parrot comes with the Parrot Compiler Toolkit (PCT), a set of code that can render an Abstract Syntax Tree [...]]]></description>
			<content:encoded><![CDATA[<p>In my copious spare time I&#8217;m working on a programming language called &#8220;Close.&#8221; It&#8217;s a C-like systems programming language targeted at the <a href="http://www.parrot.org">Parrot VM.</a></p>
<p>Now, I&#8217;m not a compiler guy. But I don&#8217;t have to be. Because Parrot comes with the Parrot Compiler Toolkit (PCT), a set of code that can render an Abstract Syntax Tree (AST) into executable code. The result is that I built a grammar using Perl6, then wrote some action methods hooked to the grammar that built the AST. Then I stood back and let PCT do it&#8217;s voodoo. The time between starting the project and now has been about 3 weeks, and I was busy with other stuff for 30 percent or so of that.</p>
<p>Okay, that&#8217;s cool. Parrot+PCT rocks, as Allison Randal <a href="http://www.linux-mag.com/cache/7373/1.html">points out</a>. But it&#8217;s not my point. The reason I wrote Close was because people were still coding in PIR &#8212; Parrot&#8217;s version of assembly language &#8212; years after starting the project. D&#8217;oh! Everybody knows that the first thing you do with a new architecture is develop a C compiler.</p>
<p>Well, somebody had to do it. So I stepped up. I talked a little bit about it at the Parrot Virtual Machine Workshop last week in Pittsburgh, and some other people acted interested. As a result, it&#8217;s up on Google code at http://close.googlecode.com. But the key for me was a conversation I had with Uri Guttman in a hallway at <a href="http://yapc10.org/yn2009/">YAPC10</a> (the conference to which the PVMW was attached).</p>
<p>I showed Uri this code:</p>
<pre>
void test_foreach()
{
	pmc the_list = new ResizableStringArray;
	push the_list, "alpha", "beta", "gamma", "delta", "omega";

	pmc new_list = new ResizableStringArray;
	int count = 0;

	foreach (str i: the_list) {
		push new_list, i;
		++count;
	}

	ok(count, 5, "f/e Iterate over each element");

	count = 0;
	int pass = 1;

	foreach (i : new_list) {
		if (i != the_list[count++]) {
			pass = 0;
		}
	}

	ok(pass, "f/e Same items, same order");
}
</pre>
<p>And Uri read through it, figured out what I was doing, and said, &#8220;Well, I don&#8217;t like your coding style. And I really don&#8217;t like single letter variable names, even inside a loop.&#8221;</p>
<p>And my first reaction was &#8220;Up yours, bud!&#8221; But I swallowed that, and then it hit me: I won!</p>
<p>The whole point of implementing Close was to stop writing code that looks like this:</p>
<pre>
.sub 'uniquereg' :method
    .param string rtype
    unless rtype goto err_nortype
    if rtype == 'v' goto reg_void
    .local string reg
    reg = 'P'
    $I0 = index 'Ss~Nn+Ii', rtype
    if $I0 < 0 goto reg_psin
    reg = substr 'SSSNNNII', $I0, 1
  reg_psin:
    reg = concat '$', reg
    .tailcall self.'unique'(reg)
  reg_void:
    .return ('')
  err_nortype:
    self.'panic'('rtype not set')
.end
</pre>
<p>And so what occurred to me was that I showed Uri some code that <em>didn't</em> look like that. It looked like C. And so naturally he read it. And he commented on something that was relevant to him. Not "Gee, I can read your code!" but "Of course I can read your code -- it's C. But I don't like your curly braces."</p>
<p>Win. Win. Win. </p>
<p>Hearing what Uri did <strong>not</strong> say was the key.</p>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2009/06/things-left-unsaid/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Being a trust specialist</title>
		<link>http://www.longacre-scm.com/blog/index.php/2009/04/being-a-trust-specialist</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2009/04/being-a-trust-specialist#comments</comments>
		<pubDate>Mon, 27 Apr 2009 07:25:57 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[General CM]]></category>
		<category><![CDATA[Organizations]]></category>
		<category><![CDATA[Practice]]></category>
		<category><![CDATA[Software CM]]></category>
		<category><![CDATA[Theory]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/index.php/2009/04/being-a-trust-specialist</guid>
		<description><![CDATA[Most of the readers of this blog are CM specialists. Whether you&#8217;re a corporate CM librarian, or a build manager, you are focused on what the industry now calls &#8220;Application Lifecycle Management.&#8221; That&#8217;s an attempt to give a name to the collection of roles and functions we perform. It isn&#8217;t so much that the people [...]]]></description>
			<content:encoded><![CDATA[<p>Most of the readers of this blog are CM specialists. Whether you&#8217;re a corporate CM librarian, or a build manager, you are focused on what the industry now calls &#8220;Application Lifecycle Management.&#8221; That&#8217;s an attempt to give a name to the collection of roles and functions we perform. It isn&#8217;t so much that the people are diversifying, as that the collection of tools that were all trying to fit under the &#8220;Configuration Management Tool&#8221; umbrella got too large. Change tracking? Sure, that&#8217;s a CM function. Version control? Yep. Requirements management? Well &#8230; okay. UML? Not so much. Trouble ticketing? Yeah, I guess. ITIL? Sure, why not?</p>
<p><a href="http://bradapp.blogspot.com/">Brad Appleton</a> is, in my opinion, one of the all-around smart guys in the CM space. His focus for the last few years has been on Agile CM, but his writings are applicable to anybody doing software development, for a <i>very </i>broad definition of software &#8211; most of what he writes is applicable to almost any kind of intellectual property. And recently Brad has been doing some blogging about books on various flavors of &#8216;trust. &#8216;</p>
<p>Trust, to me, is one of those core values for most CM specialists. The fact is that CM is a simple job. There are certain requirements, and once you meet them you get to go home. In that way it&#8217;s a lot like being a system administrator: is the system up, is everything working? Okay, go home. Now admittedly it can be pretty hard to meet some of those requirements. That&#8217;s why I didn&#8217;t say it was an easy job &#8211; just a simple one. But that&#8217;s where trust comes in. Because whether your shop is an agile shop or not, the CM guys are more affected by trust than any single other thing.<br />
<span id="more-65"></span></p>
<p>Let me repeat that: CM guys are more affected by trust than any single other thing.</p>
<p>I&#8217;m a CM consultant. I get called in by shops that either don&#8217;t have CM and want to build a team, or by shops that already HAVE a CM team but have experienced enough CM failures that they don&#8217;t trust them any more. Since most companies obtain headcount by calling up a body shop and ordering it by the pound (kilos for the EU, I guess), I don&#8217;t usually get called <i>first</i> for CM team setups. It&#8217;s usually only after there are some bodies on site, when it turns out that CM specialists that are great at keeping an existing system going don&#8217;t have so much experience in starting a new system up from scratch. So there&#8217;s usually some kind of mess on the floor when I show up.</p>
<p>What does that mean for you? Well, it means that if you see me at your shop, you should make sure your resume is up to date. (Sorry, but it&#8217;s true.) It also means that you can keep me, or somebody like me, from showing up if you concentrate on building trust with your customers.</p>
<p>Brad&#8217;s first blog post about trust was on Covey&#8217;s &#8220;The Speed of Trust,&#8221; and in that book there are five &#8220;rings of trust&#8221; outlined. The second and third rings, or types, are interpersonal trust and organizational trust. That&#8217;s where I live, and if you&#8217;re smart it&#8217;s where you spend time each day maintaining your relationships with your customers.</p>
<p>It&#8217;s a pretty simple set of questions, but it makes all the difference. </p>
<ol>
<li>Do the people you interact with understand what you need from them, and understand how to deliver it?</li>
<li>Do they understand what services you can provide to them, and how to request them? </li>
<li>Are all of these things practicable?</li>
<li>Do they perceive you as doing what is needed, on time, and without unnecessary oversight?</li>
<li>Do they perceive you as requesting things that are objective, and consistent, and in keeping with your and their function?</li>
<li>Do they believe the estimates and the explanations you give them?</li>
</ol>
<p>If you can answer yes to all of those, you&#8217;ll never work with me. That&#8217;s because your customers trust you. If you can&#8217;t &#8211; if your customers distrust you &#8211; then as the level of trust decreases, the likelihood of a &#8220;fixer&#8221; being called in for your team goes up. In the credit card business, your interest rate goes up. In the CM business, the level of interest in working with you goes down.</p>
<p>If you&#8217;re a CM manager for a military systems contractor, then you&#8217;ve got a CM plan. And you&#8217;ve got a set of prescribed deliverables. And if the developers &#8211; software, firmware, systems engineers, whatever &#8211; know how to deliver each release to you, and it&#8217;s an automated, mechanical, simple chore, then you&#8217;re halfway there. If your other customers &#8211; the clients, and the development team that need to roll back to an earlier release &#8211; can submit a request and quickly get some kind of link, or bundle, or set of typing instructions, then you&#8217;re all the way done.</p>
<p>If you&#8217;re a build guy, or a release guy, or a deployment guy for a software team &#8211; agile or not &#8211; then the activities might be different but the questions aren&#8217;t. Does the team know how to get you to do a build, or cut a release, or deploy a package? Are there any bogus hoops they have to jump through? Have you built any passive-aggressive walls, saying &#8220;we want the development team to do this thing which they really ought to trust us to do but they overrode us that one time and now we&#8217;re bitter and whiny and nobody loves us&#8221;? Can a developer quickly get to the codeface of some old branch from six months ago?</p>
<p>I guess the short form is this. Are you doing your job? Are you making it as easy as possible for your customers to ask you to do your job for them? Because in my experience &#8211; and I&#8217;ll admit my experiences are all negative &#8211; if you aren&#8217;t doing your job, or if you&#8217;re making your customers pay some kind of &#8220;tax&#8221; (time, whining, paperwork, hoop-jumping, sloth, inefficiency) then you&#8217;re going to lose trust. And once you lose trust, you&#8217;ll see a little bureaucracy get started. And when that doesn&#8217;t work (and it rarely does) you&#8217;ll get to meet me. I&#8217;ll be the guy &#8220;we brought in to help gets things caught up.&#8221;</p>
<p>This isn&#8217;t a threat, quite. Because I don&#8217;t know you. It&#8217;s a reflection of the world as I see it, because I&#8217;m like a specialist doctor &#8211; nobody makes an appointment with a gastroenterologist to talk about how healthy they are. In my case, nobody calls me up and says, &#8220;We&#8217;d like to pay you to fly out here and sit in a conference room and live in a hotel for two weeks so that we can tell you how smoothly our build and deployment works!&#8221; (Man, I would LOVE that.) But what I get instead is, &#8220;We need you to come and fix our build and deployment procedures. Our developers don&#8217;t trust the CM team, and we&#8217;ve had a couple of blown deployments in the last few months.&#8221;</p>
<p>So anyway, I guess the upshot of this blog post &#8211; and this is much too depressing to be a CM Journal article, so it&#8217;ll stay a blog post &#8211; is that you need to make sure your house is in order, trust-wise. Go read one or more of the books on Brad&#8217;s list. Because CM teams seem far more Boolean than development teams. Developers can say &#8220;It&#8217;ll be done soon,&#8221; while CM&#8217;ers have to say &#8220;it&#8217;s not done.&#8221; And saying &#8220;it&#8217;s not done&#8221; leads pretty directly to &#8220;you&#8217;re not hired.&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2009/04/being-a-trust-specialist/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unit tests for MySQL scripts</title>
		<link>http://www.longacre-scm.com/blog/index.php/2009/04/unit-tests-for-mysql-scripts</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2009/04/unit-tests-for-mysql-scripts#comments</comments>
		<pubDate>Sun, 26 Apr 2009 01:07:09 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Practice]]></category>
		<category><![CDATA[Software CM]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[database]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/index.php/2009/04/58</guid>
		<description><![CDATA[Recently I had the opportunity to develop a unit testing framework for MySQL scripts in mostly-pure SQL. While I can&#8217;t share the code, I can certainly describe what we did, and why we did it. Hopefully it will be useful to you.

My client was reorganizing a development team into an agile mode in order to [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I had the opportunity to develop a unit testing framework for MySQL scripts in mostly-pure SQL. While I can&#8217;t share the code, I can certainly describe what we did, and why we did it. Hopefully it will be useful to you.<br />
<span id="more-58"></span></p>
<p>My client was reorganizing a development team into an agile mode in order to deal with an outsourcing disaster. It was one of those horror stories that starts out like &#8220;We were 3 years in to a 10 month project, when &#8230;&#8221; I was brought on to help ramp up their build and deployment processes, to get continuous integration and testing systems up, and to help mechanize their deployments.</p>
<p>The impetus for the MySQL unit test framework came from a short term contractor. The one &#8220;constant&#8221; in the otherwise highly-variable environment had been that the team wasn&#8217;t changing. Suddenly, that stopped being true. We had a handful of contractors in for a short term surge, and none of them were familiar with the application, or with SQL (it seemed). The offender was using the CI server as his syntax checker for database scripts. Yikes!</p>
<p>Luckily, the garbage he delivered was syntactically invalid. The mysql command-line client rejected the script and exited with an error status, which caused the CI script to log a failure, and &#8230; voila! Everyone credited me with doing a great job of implementing CI, because it was even checking the database stuff. Like a good consultant, I said &#8220;Yes. Of course.&#8221; Then I ran back to my desk, thinking &#8220;Oh, no! I&#8217;ve got to come up with a unit test framework for the MySQL stuff, pronto!&#8221; And I did.</p>
<p><strong>Solutions</strong></p>
<p>The software was a pretty complex web app, and the target environment was a mixture of Linux and Windows. As a result, when I looked at existing SQL unit test frameworks (<a href="http://www.dbunit.org/">dbUnit</a> and <a href="http://sqlunit.sourceforge.net/">sqlUnit,</a> respectively) I had to reject them. They are decent products &#8211; and free &#8211; but the fact is that they expect certain things about their runtime environment that we couldn&#8217;t deliver. We had to build our own MySQL unit test framework, ideally in &#8220;pure&#8221; MySQL.</p>
<p>Fortunately for me, a nice guy named Giuseppe Maxia maintains a web site at <a href="http://www.datacharmer.org">datacharmer.org,</a> and he has written a library of general-purpose MySQL code. (Called the General Purpose Stored Routine library, or gp_sr_lib.) Among the all this well-written, free, already debugged code was a set of testing routines. Thirty minutes into my development effort, I was already 80% done. Woo-hoo!</p>
<p>The GP library test routines are a good start on a mysqlUnit library, and I strongly recommend that if you need such a library you stop reading here and go download the code. Right now. </p>
<p><strong>Rolling (y)our Own</strong></p>
<p>There are a couple of gotchas that you&#8217;ll want to watch out for in your own unit testing library. First, the tests should be able to integrate into your CI engine. In particular, you need to decide on and implement some kind of failure mode &#8211; either fail when the first problem occurs, or fail after running all test cases. If you&#8217;re running the mysql client via some kind of exec call, be aware that while syntax errors will cause the client to exit with a failure code, other errors will not cause a failure. Instead, the client prints a diagnostic and returns zero. What&#8217;s more, the syntax does not support a deliberate abort from within the SQL engine.</p>
<p>In my own case, I chose to follow the model that Maxia has provided, and NOT fail as soon as a test fails. Rather, my code collected the results of all the tests that were run, and summarized them. In order to get &#8220;fail on error&#8221; behavior out of the mysql command line client, I coded a routine that would perform a &#8220;SELECT force_mysql_client_abort FROM no_such_table&#8221;. This definitely does cause the client to abort, at least until some developer creates a table called &#8220;no_such_table.&#8221; Then I wrapped the test cases in an &#8220;ignore failure&#8221; script that called the summarizer after all the cases had run, which in turn would call the abort routine if the error count was non-zero.</p>
<p>Another thing I chose to &#8220;fix&#8221; was the routine names. Maxia&#8217;s code includes both functions and procedures, but the names are not really in keeping with the style used in the various xUnit test frameworks. The library contains a procedure for asserting the existence of a database table. It is called as:</p>
<p><code>CALL check_table('db name', 'table name');<br />
</code></p>
<p>I opted to &#8220;embrace and extend&#8221; the library. I wrapped these types of checks into functions, like this:</p>
<p><code><br />
set_database('db name');<br />
assert_table_exists('table name');<br />
assert_table_exists_in_db('other table', 'other db');<br />
</code></p>
<p>And in general, wherever there is a straight-ahead assert, I also added an &#8220;assert_not&#8221;. In terms of effect, there is no real difference in behavior between Maxia&#8217;s naming and my own. But I felt that the developers, who were using jUnit and nUnit, would be more comfortable learning a set of routines that had a similar structure and style.</p>
<p><strong>Going Most of the Way: DDL</strong></p>
<p>I tried to make a list of the various things that SQL scripts might do. The most obvious &#8212; and this probably accounted for two thirds or more of the scripts we had &#8212; is DDL statements. DDL (Data Definition Language) is that subset of SQL that relates to defining databases, tables, indexes, triggers, and the like. While the most frequently executed SQL statements are DML (Data Manipulation Language), DDL is where it&#8217;s at for most of the human-generated script files: CREATE TABLE, ADD INDEX, etc.</p>
<p>The great thing is that the assertions for these statements are trivial to write. Maxia&#8217;s library includes the CHECK_TABLE procedure, and some code for looking up procedures and functions. Adding other stuff, like keys and constraints, is pretty straightforward. By the end of the day you should have a long list of functions like assert_table_exists, assert_index_exists, assert_database_exists, and  assert_column_has_type.</p>
<p><strong>Deploy Early</strong></p>
<p>At this point, you&#8217;re ready to go live. Except that you need to build a framework to run these tests. That&#8217;s going to depend a lot on your deployment process, and on your particular CI environment. Sorry. The simplest idea would be to write a script that matches the file names of test files, and runs them one at a time. Call that script from CI, and make sure the exit status is meaningful.</p>
<p>Forget the next couple of sections, because most of the database changes you&#8217;re likely to see are DDL. Developers and DBAs do a lot of adding fields, adding indexes, and sometimes adding tables. If you have just the existence assertions for each kind of object, your library will cover two-thirds or more of the statements being delivered. That&#8217;s not a trivial amount of test coverage for a day or two of work. Ship it! Your developers will need some training, and you&#8217;ll need to beat on the thing once it&#8217;s deployed to your CI servers to make sure that the errors are coming out correctly. </p>
<p><strong>Sell to the Development Team</strong></p>
<p>I recommend that you write some simple tests of things you know to be true. Confirm the positive cases first. Then sit down with a smart, involved developer and pair develop some unit tests for code he hasn&#8217;t written yet. Do it the way you want the developers to do it, including deciding how to handle assertions that don&#8217;t exist yet. </p>
<p>In our case, the DBAs had already established a naming convention for database update files. I chose to duplicate the file names, which would look like ####_description.sql, changing the .sql extension to .test.sql. This let the testing framework associate the test with the delivered change. When running a &#8220;from zero&#8221; deployment, the test framework would then run TEST-CHANGE-TEST and expect the first test to fail and the second to pass. This demonstrated that the test was meaningful for the change (remember, the change is supposed to repair a shortcoming that is demonstrated by the test).</p>
<p>Once you&#8217;ve got buy-in from your chosen developer, sit down and develop a presentation that the two of you can give. Point to specific examples of blown deployments as reasons for unit testing the SQL. Then get the coder to explain the available test assertions. Then explain the framework you&#8217;ve developed to integrate the testing library with CI, and explain what failures are going to look like. And don&#8217;t forget to point them at the documentation you&#8217;ve written on the project wiki. This should get your team on board, and now you can start looking for other assertions to write. You can also start tightening the screws on your framework. Make it so that no change can be delivered without at least one test.</p>
<p><strong>Simple DML Checking</strong></p>
<p>The next obvious category of SQL statements to check is simple DML. These are the CRUD verbs: INSERT, SELECT, UPDATE and DELETE.  Except that SELECT can be pretty hard to check within SQL, so it&#8217;s best to ignore it for now in favor of the others. The problem with DML is knowing what to check for. If you insert a row, should you check that the ROW_COUNT() returns 1? Or should you query for the particular key of that row? </p>
<p>I&#8217;m pretty convinced that DML commands in scripts are going to be metadata related. That is, your application may be inserting customer records, or video titles, or whatever you track. But if a developer codes a DELETE, INSERT, or UPDATE into a deployable script, I think the intent is either to perform some kind of bulk fix (convert data fields, or eliminate nulls) or it is adjusting the &#8220;background&#8221; data &#8212; the list of postal codes, state and province names, etc. that your application relies on. In the case of the simple background data, if you added or updated it, you should check it explicitly: assert that for a specific key, the values are as expected. </p>
<p>Some examples of helpful functions would be <code>assert_statement_affects_rowcount(prepared_statement, num_rows), assert_table_column_matches_count('table name', 'column', value, count),</code> and their negatives. The way to do dynamic programming in MySQL is with prepared statements. You can construct a string containing a SQL statement, use PREPARE to assign it to an identifier, and then EXECUTE the identifier:</p>
<p><code><br />
PREPARE stmt<br />
    FROM<br />
        CONCAT("SELECT COUNT(*) FROM ", table_name, " WHERE ", field_name, " = ?");<br />
</code></p>
<p><code><br />
EXECUTE stmt USING value;<br />
</code></p>
<p>In the more complex case of a data format or type update, the update should be encoded in a stored procedure. This way you can unit test the stored procedure with sample data. Once the procedure is ready to go, write a script that calls the procedure &#8211; confident already that the procedure will work &#8211; and test the invocation by confirming random elements of the data have converted correctly.</p>
<p><strong>Testing Result Sets</strong></p>
<p>As mentioned, testing SELECT can be a real challenge. While it is easy to create an assert_row_count(num) to confirm that your query returned the right number of values, it can be much harder to create a function to assert that a particular ordering exists, or that the results are truly grouped by postal code.</p>
<p>The first thing to do is go ahead and write the assertion functions for number of rows returned by the query. That&#8217;s simple, straightforward, and it can stand in place of more complex stuff for a long time. You may not ever get around to writing the more challenging assertions &#8212; if the tests are designed well enough, the number of results may be meaningful enough. If you do need to write more, especially if the query is complex, pass the query as a string to your assertion, prepare it as a statement, and make sure the results go into a temporary table. Then you can write whatever horribly complex code you need against the temporary table, without having to worry about losing context.</p>
<p><strong>Testing Triggers</strong></p>
<p>Triggers are going to be harder to test than other pieces of code because of the diverse ways you can invoke them. For example, a DELETE trigger may need to be checked with a simple delete statement as well as with a CASCADE from a foreign key relationship. Beyond creating assertions for the existence and type of triggers (BEFORE/AFTER, INSERT/UPDATE/DELETE, etc.) there isn&#8217;t really any obvious set of assertions to write. It&#8217;s more a question of deciding how to test the effects of the triggers, and of documenting the ways the trigger can be invoked.</p>
<p><strong>Conclusion</strong></p>
<p>Unit testing, and test-first development, are well established best practices. But it&#8217;s easy to overlook the &#8220;small stuff&#8221; when developers are setting up frameworks for testing their code. Database updates are small, but when they go wrong they can take out the rest of the system. It&#8217;s important to apply the same techniques, and get the same value, to this part of your development. Now you can.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2009/04/unit-tests-for-mysql-scripts/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Three</title>
		<link>http://www.longacre-scm.com/blog/index.php/2009/01/three</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2009/01/three#comments</comments>
		<pubDate>Thu, 22 Jan 2009 11:52:13 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Off-topic]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[monitors]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/?p=49</guid>
		<description><![CDATA[
As you can probably tell, my three LCD monitors are all present and accounted for. And yeah, before you ask, it ROCKS!
One very interesting &#8220;problem&#8221; is that none of the monitors I received shipped with a DVI cable. I have no idea why that is &#8212; all of the smaller LCD monitors I saw last [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.longacre-scm.com/blog/wp-content/uploads/2009/01/img4-2.jpg"><img src="http://www.longacre-scm.com/blog/wp-content/uploads/2009/01/img4-2-300x169.jpg" alt="" title="img4-2" width="300" height="169" class="alignnone size-fullsize wp-image-50" /></a></p>
<p>As you can probably tell, my three LCD monitors are all present and accounted for. And yeah, before you ask, it ROCKS!</p>
<p>One very interesting &#8220;problem&#8221; is that none of the monitors I received shipped with a DVI cable. I have no idea why that is &#8212; all of the smaller LCD monitors I saw last summer came out of the box with both VGA and DVI cables, but these bigger, high-dollar products came with just VGA.</p>
<p>But that&#8217;s not a problem, because while the first monitor was a nice <a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16824254035">Hanns-G</a>, which I plugged in to the VGA output from my laptop docking station, the other two are even nicer &#8212; they&#8217;re <a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16824236038">ASUS VW223-B</a> monitors with &#8220;EzLink&#8221; (ASUS&#8217;s feature name for <a href="http://www.displaylink.com">DisplayLink&#8217;s</a> technology).</p>
<p>I found the two monitors on clearance from NewEgg.com. They were $159 plus NJ sales tax, call it $175 each. Apparently part of the clearance was getting rid of the products entirely, since the products are now shown as &#8220;Deactivated Item&#8221; on NewEgg&#8217;s site. </p>
<p>The DisplayLink/EzLink technology is an on-the-fly compression mechanism that sends video requests (probably just re-encoding Direct-X requests, but it might be something different) over USB. I wondered how well that technology would perform, but I was planning on buying a USB/VGA adapter device and finding out. Well, no need. </p>
<p>Both of the ASUS monitors are plugged in to USB, since they didn&#8217;t include a DVI adapter and since my Hanns-G is already taking up the VGA output port. And they work swimmingly. Not only is the display nice, but you can watch videos and other streaming media over the USB connection. I will admit that my limited experiment, watching three (different) videos on three different monitors at the same time, seemed to show some &#8220;snow&#8221; in the video images of the ASUS (USB linked) monitors. I&#8217;m guessing that this is a compression artifact, with the drivers sacrificing video in factor of speed. If that&#8217;s true, they&#8217;re doing it exactly right. The result was kind of like watching a slightly imperfect broadcast (over-the-air) television signal: a little fuzz, and some salt/pepper, but the underlying picture was clear.</p>
<p>The DisplayLink drivers installed smoothly, and once installed the driver had no problem picking up when I plugged in the third monitor. That little Windows &#8220;de-dum&#8221; sound for a new USB device, and I could instantly extend the desktop one more time. The monitors can be controlled from the taskbar, including specifically a rotation option. Also, the monitors appear in the standard Windows Display control panel, so you can specify location and resolution.</p>
<p><a href="http://www.longacre-scm.com/blog/wp-content/uploads/2009/01/display-properties.jpg"><img src="http://www.longacre-scm.com/blog/wp-content/uploads/2009/01/display-properties-150x150.jpg" alt="Snapshot of Display Properties dialog showing locations, orientation" title="display-properties" width="150" height="150" class="alignnone size-thumbnail wp-image-52" /></a></p>
<p>As you can see in the above image, setting the rotation causes the correct data to be reflected back to windows. And you&#8217;ll have to take my word for it, but you can get a LOT of lines of code onto a 22&#8243; monitor in portrait mode. Here&#8217;s the bottom of a <a href="http://www.scintilla.org/SciTE.html">Scite</a> window, where the top of the window is showing top-of-file:</p>
<p><a href="http://www.longacre-scm.com/blog/wp-content/uploads/2009/01/scite-cpp-bottom.jpg"><img src="http://www.longacre-scm.com/blog/wp-content/uploads/2009/01/scite-cpp-bottom-150x150.jpg" alt="" title="scite-cpp-bottom" width="150" height="150" class="alignnone size-thumbnail wp-image-53" /></a></p>
<p>Yes, that&#8217;s 104 lines of source code on a single screen. Given that subroutines and methods are supposed to fit &#8220;on a single page,&#8221; I may have discovered the ultimate solution to <em>all</em> refactoring problems.</p>
<p>This is so cool!</p>
<p>One thing worth pointing out is that the monitors themselves do not support rotation. They come with the kind of cheap plastic stand that you would expect. Instead, I bought a third-party monitor stand from the <a href="http://www.ergotechgroup.com/products/heavy-duty-17-30-36/triple-lcd-desk-stand-62/">Ergotech Group.</a> They don&#8217;t have an on-line store, but rely on other vendors for retail sales. I found a bunch of places where I could choose to pay about a million dollars for that stand, and then I found <a href="http://www.pcconnection.com/IPA/Shop/Product/Detail.htm?sku=9018451">PC Connection,</a> where $250 seemed like a bargain. </p>
<p>All told, the monitors ($522) and the stand ($267) cost me $790. Sitting here, beginning to develop retinal cancer from the massive volume of monitor-light being blasted at my eyes, it was totally worth it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2009/01/three/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting L A R G E R</title>
		<link>http://www.longacre-scm.com/blog/index.php/2009/01/getting-l-a-r-g-e-r</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2009/01/getting-l-a-r-g-e-r#comments</comments>
		<pubDate>Fri, 16 Jan 2009 08:22:53 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Off-topic]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/?p=44</guid>
		<description><![CDATA[I just spent a bunch of time out west (which, since I live on the east coast, isn&#8217;t saying much) working with a client trying to do agile development. I have a kind of gentlemen&#8217;s agreement with the client that I won&#8217;t write anything that makes them look too bad. Presumably, they&#8217;ll be kind enough [...]]]></description>
			<content:encoded><![CDATA[<p>I just spent a bunch of time out west (which, since I live on the east coast, isn&#8217;t saying much) working with a client trying to do agile development. I have a kind of gentlemen&#8217;s agreement with the client that I won&#8217;t write anything that makes them look too bad. Presumably, they&#8217;ll be kind enough to do the same thing for me <img src='http://www.longacre-scm.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>That said, I want to talk about something that I absolutely cannot stand about the development environment out there:  They have really big monitors, usually two per pairing station. And I don&#8217;t.</p>
<p>It&#8217;s a little bit surprising how easy it was to get used to working with multiple monitors. In fact, towards the end of the engagement I got moved in to a cubicle that had three monitors in it &#8211; one for the old user&#8217;s laptop, one for a desktop that was sitting there, and one small one unused. Since I was bringing two monitors with me, that took me up to five monitors. Sadly, I couldn&#8217;t talk the IT guys into buying the Lenovo advanced docking station that supported a plug-in video controller, or I&#8217;m sure I could have driven all five monitors off my laptop.</p>
<p>Now, you might be asking &#8220;what on earth could you do with five monitors?&#8221; And, you know, I&#8217;m not entirely sure myself. But I would surely have loved to find out. In the meantime, I got away with using <a href="http://synergy2.sourceforge.net/">Synergy</a> to share my laptop&#8217;s keyboard and mouse with another computer, and then drove three monitors from my laptop with a USB video adapter. </p>
<p>What can I do with four monitors? One of them was my designated remote desktop box, for connecting to the Windows servers the team was using. The other three? Well, whatever I wanted. </p>
<p>I almost always had Firefox open in one monitor, maximized. Because I was almost always working on something that required frequent reference to online forums or documentation. CM consultants never spend much time in the &#8220;well documented, easy to configure&#8221; part of the system. Go figure.</p>
<p>Sometimes I had email open in another monitor, but more often I had a text editor maximized. And then I stuck a couple of shell windows (MSYS, Powershell, Cygwin, rxvt, whatever it takes) in the other monitor. And then I silently wished that I could have gotten that fifth monitor up, because sometimes you need to RDP into two different remote servers, in order to test a deployment script. </p>
<p>So, yeah. I&#8217;m addicted to having multiple monitors. LOTS of them. And my addiction is growing. Two monitors, which I&#8217;m using now, just isn&#8217;t enough anymore. So I&#8217;ve taken steps. I&#8217;m ordering more monitors. And a monitor stand to hang them from, because that was one thing that I didn&#8217;t have out west. And this time, they&#8217;re going to be BIG. </p>
<p>Apparently, Alienware hasn&#8217;t released their <a href="http://www.youtube.com/watch?v=2yT6OuGXmGo&#038;feature=channel">promised</a> 3&#8242;-wide ubermonitor, but Panasonic <em>has</em> got a 103&#8243; screen in production. Sadly, I can&#8217;t afford one. So I&#8217;m going to settle for 22&#8243; LCD monitors. </p>
<p>Now, you&#8217;re probably saying &#8220;Wait, why not get two 24 or 30 inch monitors?&#8221; And there are three answers. One, I like having a &#8220;main&#8221; screen in front of me. Two monitors would put the main screen at an angle (bad) or put the main screen in front and require twisting my neck in one direction half the time (bad). So three is the right number. Second, the native resolutions for the big displays is too large for my laptop to drive, and is also too large for a USB video adapter to drive, and is also too large for a Matrox TripleHead2Go adapter to drive. So 1650&#215;1050 or 1650&#215;1200 is the right size. And third, they don&#8217;t make three-across monitor mounting brackets quite that big yet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2009/01/getting-l-a-r-g-e-r/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Two Conferences</title>
		<link>http://www.longacre-scm.com/blog/index.php/2008/09/two-conferences</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2008/09/two-conferences#comments</comments>
		<pubDate>Wed, 17 Sep 2008 02:15:52 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Industry]]></category>
		<category><![CDATA[Practice]]></category>
		<category><![CDATA[Software CM]]></category>
		<category><![CDATA[Theory]]></category>
		<category><![CDATA[database]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/index.php/2008/09/two-conferences</guid>
		<description><![CDATA[Austin Hastings (that&#8217;s me) will be speaking at two conferences coming up in October. Both presentations will be focusing on LDM.
First, there&#8217;s the Telelogic User Group Conference 2008, in Austin, Texas. That&#8217;s obviously focused on Telelogic, and on CM Synergy and Telelogic Change, or whatever it&#8217;s called this week. Since I spent a fair amount [...]]]></description>
			<content:encoded><![CDATA[<p>Austin Hastings (that&#8217;s me) will be speaking at two conferences coming up in October. Both presentations will be focusing on LDM.</p>
<p>First, there&#8217;s the <a href="http://www.telelogic.com/campaigns/2008/ugc/americas/index.cfm">Telelogic User Group Conference 2008,</a> in Austin, Texas. That&#8217;s obviously focused on Telelogic, and on CM Synergy and Telelogic Change, or whatever it&#8217;s called this week. Since I spent a fair amount of time during the initial implementation of LDM wishing that I could use the kind of one-off ad hoc queries that Change is so good at, I suppose it&#8217;s appropriate.</p>
<p>The second conference is <a href="http://www.cmconf.de/agenda/">CMconf.DE,</a> in Munich, Germany. Sadly, it will be a few weeks after Oktoberfest &#8212; otherwise there would be no hope at all of getting hotel space, I suppose. I&#8217;ll just have to wander around looking for any leftover barrels of beer, slightly-used lederhosen, or oompa bands that I can scrounge up. The theme is the same &#8212; presenting LDM and some other approaches to database CM. </p>
<p>In both cases, the time constraints are really biting. LDM needs an understanding of the other ways to do (fail at) database CM before I can really talk about it, and I&#8217;m pretty sure that most people haven&#8217;t thought beyond one way, if that many. So I&#8217;ll be speaking really, really fast, and inviting attendees to stick around afterwards to talk about it.</p>
<p>Anyway, that&#8217;s two continents in a single month &#8212; not bad, if I do say so. If I could just find a conference in India, China, or Israel, I could sweep the northern hemisphere.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2008/09/two-conferences/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gotcha: XML include processing in CruiseControl.NET</title>
		<link>http://www.longacre-scm.com/blog/index.php/2008/06/gotcha-xml-include-processing-in-cruisecontrolnet</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2008/06/gotcha-xml-include-processing-in-cruisecontrolnet#comments</comments>
		<pubDate>Tue, 24 Jun 2008 16:24:36 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/index.php/2008/06/gotcha-xml-include-processing-in-cruisecontrolnet</guid>
		<description><![CDATA[Release 1.4 of CruiseControl.NET includes a new Configuration Preprocessor. The great thing is that this provides a C preprocessor-like macro syntax, so projects can be made using relatively powerful templates.
The bad thing is that it&#8217;s new, and so there are some gotcha&#8217;s laying around. I just found one:
I defined a ccnet.config file structured like this:


&#60;cruisecontrol
 [...]]]></description>
			<content:encoded><![CDATA[<p>Release 1.4 of CruiseControl.NET includes a new <a href="http://confluence.public.thoughtworks.org/display/CCNET/Configuration+Preprocessor">Configuration Preprocessor</a>. The great thing is that this provides a C preprocessor-like macro syntax, so projects can be made using relatively powerful templates.</p>
<p>The bad thing is that it&#8217;s new, and so there are some gotcha&#8217;s laying around. I just found one:</p>
<p>I defined a ccnet.config file structured like this:</p>
<blockquote><pre>

&lt;cruisecontrol
  xmlns:cb="urn:ccnet.config.builder"
  >
  &lt;!-- Define some local configuration symbols -->
  &lt;cb:define
    FOO="bar"
    />
  &lt;!-- Define a CCnet project template called "cb:PROJECT" -->
  &lt;cb:define
    name="PROJECT"
    >
    &lt;project
      name = "$(projectName)"
      >
      &lt;!--
          guts go here
          -->
    &lt;/project>
  &lt;/cb>
  &lt;!-- Use template -->
  &lt;cb:PROJECT
    projectName = "My dog has fleas"
    />
&lt;/cruisecontrol>
</pre>
</blockquote>
<p>That worked fine, and I could see how to rubber-stamp that project template to all my various continuous-integration areas and other workspaces.</p>
<p>But then I got clever, and decided to separate out the template from the local configuration.</p>
<blockquote><pre>

&lt;cruisecontrol
  xmlns:cb="urn:ccnet.config.builder"
  >

  &lt;!-- Define some local configuration symbols -->
  &lt;cb:define
    FOO="bar"
    />

  <strong>&lt;!-- Include template(s) file -->
  &lt;cb:include
    href = "project-template.xml"
    /></strong>

  &lt;!-- Use template -->
  &lt;cb:PROJECT  projectName = "My dog has fleas"  />
&lt;/cruisecontrol>
</pre>
</blockquote>
<p>By unfortunate coincidence, I had to reboot my laptop at this point &#8212; I kicked the power strip under the desk, removing power to the docking station. The Lenovo I&#8217;m using (client provided) doesn&#8217;t handle this at all, so it was restart time. When I came back up, the CruiseControl.NET service wouldn&#8217;t start.</p>
<p>Debugging is simple and easy with the &#8220;ccnet.exe&#8221; command line utility. Just run<br />
<code><br />
ccnet.exe -config:ccnet.config -validate</p>
<p></code></p>
<p>The error, though, was incomprehensible:</p>
<blockquote><pre>
C:\Program Files\CruiseControl.NET\server>ccnet -config:ccnet.config -validate
CruiseControl.NET Server 1.4.0.3400 -- .NET Continuous Integration Server
Copyright c 2008 ThoughtWorks Inc.  All Rights Reserved.
.NET Runtime Version: 2.0.50727.1433    Image Runtime Version: v2.0.50727
OS Version: Microsoft Windows NT 5.1.2600 Service Pack 3        Server locale: e
n-US

[CCNet Server:DEBUG] The trace level is currently set to debug.  This will cause
 CCNet to log at the most verbose level, which is useful for setting up or debug
ging the server.  Once your server is running smoothly, we recommend changing th
is setting in C:\Program Files\CruiseControl.NET\server\ccnet.exe.config to a lo
wer level.
[CCNet Server:INFO] Reading configuration file "C:\Program Files\CruiseControl.NET\server\ccnet.config"
[CCNet Server:ERROR] Exception: The configuration file contains invalid xml: C:\Program Files\CruiseControl.NET\server\ccnet.config
----------
ThoughtWorks.CruiseControl.Core.Config.ConfigurationException: The configuration file contains invalid xml: C:\Program Files\CruiseControl.NET\server\ccnet.config ---> System.Xml.XmlException: 'cb' is an undeclared namespace. Line 1, position 2.
   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.Throw(String res, String arg, Int32 lineNo, Int32 linePos)
   at System.Xml.XmlTextReaderImpl.LookupNamespace(NodeData node)
   at System.Xml.XmlTextReaderImpl.ElementNamespaceLookup()
   at System.Xml.XmlTextReaderImpl.ParseAttributes()
   at System.Xml.XmlTextReaderImpl.ParseElement()
   at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
   at System.Xml.XmlTextReaderImpl.Read()
   at System.Xml.XPath.XPathDocument.LoadFromReader(XmlReader reader, XmlSpace space)
   at System.Xml.XPath.XPathDocument..ctor(Stream stream)
   at ThoughtWorks.CruiseControl.Core.Config.Preprocessor.ConfigPreprocessorEnvironment.push_include(String href)
   at ThoughtWorks.CruiseControl.Core.Config.Preprocessor.ConfigPreprocessor.PreProcess(XmlReader input, XmlWriter output, PreprocessorUrlResolver resolver, Uri input_uri)
   at ThoughtWorks.CruiseControl.Core.Config.DefaultConfigurationFileLoader.CreateXmlValidatingLoader(FileInfo configFile)
   at ThoughtWorks.CruiseControl.Core.Config.DefaultConfigurationFileLoader.AttemptLoadConfiguration(FileInfo configFile)
   --- End of inner exception stack trace ---
   at ThoughtWorks.CruiseControl.Core.Config.DefaultConfigurationFileLoader.AttemptLoadConfiguration(FileInfo configFile)
   at ThoughtWorks.CruiseControl.Core.Config.DefaultConfigurationFileLoader.Load(FileInfo configFile)
   at ThoughtWorks.CruiseControl.Core.Config.FileConfigurationService.Load()
   at ThoughtWorks.CruiseControl.Core.Config.FileWatcherConfigurationService.Load()
   at ThoughtWorks.CruiseControl.Core.Config.CachingConfigurationService.Load()
   at ThoughtWorks.CruiseControl.Core.CruiseServer..ctor(IConfigurationService configurationService, ProjectIntegratorListFactory projectIntegratorListFactory, IProjectSerializer projectSerializer)
   at ThoughtWorks.CruiseControl.Core.CruiseServerFactory.Create(Boolean remote, String configFile)
   at ThoughtWorks.CruiseControl.Core.ConsoleRunner.Run()
   at ThoughtWorks.CruiseControl.Console.ConsoleMain.Main(String[] args)
----------
</pre>
</blockquote>
<p>Even worse, the error message is presented in white text on a glaring red background, so as to be all but unreadable. Looking at it now, in retrospect (and black &#038; white), I can see clues that I missed the first time. Specifically, the string &#8220;push_include.&#8221;</p>
<p>Anyway, the problem turned out to be the way the Configuration Processor deals with XML includes. It is <strong>not</strong> a C preprocessor &#8212; it includes subtrees, not text. </p>
<p>The answer turns out to be in the included file. References in the included file to the &#8220;cb:&#8221; XML namespace have to be accompanied in that file by some definition. Adding the same xmlns= statement does the trick:</p>
<blockquote><pre>

&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;cb:define  <strong>xmlns:cb="urn:ccnet.config.builder"</strong>  name = "PROJECT"  >
  &lt;!-- blah blah -->
&lt;/cb:define>
</pre>
</blockquote>
<p>Problem solved. Now let the rubber-stamping begin!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2008/06/gotcha-xml-include-processing-in-cruisecontrolnet/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
