<?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>Michael Goffin</title>
	<atom:link href="http://www.mgoff.in/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mgoff.in</link>
	<description>geek</description>
	<lastBuildDate>Mon, 19 Jul 2010 04:37:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>A Strategic Reason To Move Away From WASD</title>
		<link>http://www.mgoff.in/2010/07/19/a-strategic-reason-to-move-away-from-wasd/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=a-strategic-reason-to-move-away-from-wasd</link>
		<comments>http://www.mgoff.in/2010/07/19/a-strategic-reason-to-move-away-from-wasd/#comments</comments>
		<pubDate>Mon, 19 Jul 2010 04:37:08 +0000</pubDate>
		<dc:creator>Michael Goffin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[gaming]]></category>

		<guid isPermaLink="false">http://www.mgoff.in/?p=117</guid>
		<description><![CDATA[Ever since I started gaming when I was a kid, everyone used WASD for their primary movement controls. Back when I was a kid it made sense too. The keys are in the same layout as the arrow keys, but they allow you to have access to other keys around it (with the added bonus [...]]]></description>
			<content:encoded><![CDATA[<p>
Ever since I started gaming when I was a kid, everyone used WASD for their primary movement controls. Back when I was a kid it made sense too. The keys are in the same layout as the arrow keys, but they allow you to have access to other keys around it (with the added bonus of not having to reach across the keyboard with your left hand). But by the time I got to college, WASD didn&#8217;t work for me anymore:</p>
<ul>
<li>My hands grew and my fingers felt very cramped.</li>
<li>The W key seemed way too shifted to the left to be comfortable, resulting in my index and ring finger fighting for key space.</li>
<li>Pushing my hand so far left on the keyboard resulted in me having access to fewer keys easily.</li>
</ul>
<p>I spent time thinking of a better keybinding layout. Moving my hand to the middle of the keyboard started to get uncomfortable, and my wrist started to curve in a way that made using an &#8220;arrow keys&#8221; layout impossible. Here&#8217;s what I wanted to accomplish:</p>
<ul>
<li>More comfortable, natural keybinding layout for my hand.</li>
<li>A layout that also gave me access to more keys quickly.</li>
<li>The new keys that are available need to be used in a way that makes sense.</li>
<li>The layout needs to work across multiple genres of games so I am always using the same comfortable binding scheme.</li>
</ul>
<p>While I was thinking of a new layout, I noticed my hand resting on certain keys of the keyboard, and it hit me. My new layout was EASF. The interesting thing is by putting my hand on these keys, a couple things happen naturally:</p>
<ul>
<li>My pinky finger rests nicely on the shift key (used commonly for walk/run/use) and CTRL becomes easier to hit (which I use for Ventrilo).</li>
<li>My thumb rests nicely on the space bar (used commonly for jumping).</li>
<li>Instead of just having Q available to my index/ring finger, I now had W as well (I tend to use W for things like Flashlight, which are normally bound to F).</li>
<li>R for reload, and G for grenade are <b>much</b> easier to use, and exposes T and 5 as a new easy-access keys.</li>
<li>Instead of using C for duck/crouch, I can now use D, which is much closer to the rest of my movement keys.</li>
<li>Z, X, C, and V are easier to hit now that my hand isn&#8217;t cramped up and can be used for misc stuff (although I use V as push-to-talk in-game voice chat primarily).</li>
<li>TAB is still just as easy to hit except now I don&#8217;t have to raise my pinky off of shift to get to it.</li>
</ul>
<p>I tried using RSDG (shifting one key to the right). It&#8217;s also pretty comfortable, but I find that hitting TAB becomes annoying, SHIFT is ok but sometimes my pinky hits Z, CTRL is too hard to quickly use, H doesn&#8217;t make sense for grenade and T doesn&#8217;t make sense for reload, and Q becomes difficult to hit making it useless.
</p>
<p>
Of course, you need to use what is right for you, but from a strategic standpoint, I found that moving away from WASD made using the keyboard so much easier and more comfortable. Maybe EASF isn&#8217;t for you, but I highly recommend experimenting and finding the best keybinding layout for your hand. I&#8217;ve been using this layout for 9 years and it hasn&#8217;t let me down yet. It&#8217;s also really fun to watch people try and play a game on my machine!</p>
<p align="right"><a class="tt" href="http://twitter.com/home/?status=A+Strategic+Reason+To+Move+Away+From+WASD+http://is.gd/dxDPo" title="Post to Twitter"><img class="nothumb" src="http://www.mgoff.in/wp-content/plugins/tweet-this/icons/tt-twitter-micro4.png" alt="Post to Twitter" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mgoff.in/2010/07/19/a-strategic-reason-to-move-away-from-wasd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HAProxy: Gathering Stats Using `socat`</title>
		<link>http://www.mgoff.in/2010/07/14/haproxy-gathering-stats-using-socat/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=haproxy-gathering-stats-using-socat</link>
		<comments>http://www.mgoff.in/2010/07/14/haproxy-gathering-stats-using-socat/#comments</comments>
		<pubDate>Wed, 14 Jul 2010 17:36:11 +0000</pubDate>
		<dc:creator>Michael Goffin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[haproxy]]></category>
		<category><![CDATA[socat]]></category>

		<guid isPermaLink="false">http://www.mgoff.in/?p=114</guid>
		<description><![CDATA[We use Zabbix to monitor our systems at work. It&#8217;s a great open source alternative. One of things I&#8217;ve been working on recently is auditing our monitoring system for defunct monitoring points, unmonitored services, and proper triggers and alerts based on our SLA requirements. HAProxy was one of those items. There are standard monitoring points [...]]]></description>
			<content:encoded><![CDATA[<p>
We use <a href="http://www.zabbix.com/">Zabbix</a> to monitor our systems at work. It&#8217;s a great open source alternative. One of things I&#8217;ve been working on recently is auditing our monitoring system for defunct monitoring points, unmonitored services, and proper triggers and alerts based on our SLA requirements. <a href="http://haproxy.1wt.eu/">HAProxy</a> was one of those items.
</p>
<p>
There are standard monitoring points like PID changes, web interface availability, CPU/Memory usage, etc. But what about monitoring things like MAXCONN and CURCONNS? Turns out there&#8217;s a way to get this data from HAProxy using what they call a &#8220;stats socket.&#8221; This information isn&#8217;t found in the <b>haproxy-en.txt</b> file, but in the <b>configuration.txt</b> file. In my installation, it isn&#8217;t in <b>/usr/share/doc/haproxy</b> like everything else. I actually found this on the official <a href="http://haproxy.1wt.eu/download/1.4/doc/configuration.txt">website</a>. Here&#8217;s the interesting bit:</p>
<blockquote><p>
stats socket
<path> [{uid | user} <uid>] [{gid | group} <gid>] [mode <mode>]<br />
  [level <level>]</p>
<p>  Creates a UNIX socket in stream mode at location
<path>. Any previously<br />
  existing socket will be backed up then replaced. Connections to this socket<br />
  will return various statistics outputs and even allow some commands to be<br />
  issued. Please consult section 9.2 &#8220;Unix Socket commands&#8221; for more details.</p>
<p>  An optional &#8220;level&#8221; parameter can be specified to restrict the nature of<br />
  the commands that can be issued on the socket :<br />
    &#8211; &#8220;user&#8221; is the least privileged level ; only non-sensitive stats can be<br />
      read, and no change is allowed. It would make sense on systems where it<br />
      is not easy to restrict access to the socket.</p>
<p>    &#8211; &#8220;operator&#8221; is the default level and fits most common uses. All data can<br />
      be read, and only non-sensible changes are permitted (eg: clear max<br />
      counters).</p>
<p>    &#8211; &#8220;admin&#8221; should be used with care, as everything is permitted (eg: clear<br />
      all counters).</p>
<p>  On platforms which support it, it is possible to restrict access to this<br />
  socket by specifying numerical IDs after &#8220;uid&#8221; and &#8220;gid&#8221;, or valid user and<br />
  group names after the &#8220;user&#8221; and &#8220;group&#8221; keywords. It is also possible to<br />
  restrict permissions on the socket by passing an octal value after the &#8220;mode&#8221;<br />
  keyword (same syntax as chmod). Depending on the platform, the permissions on<br />
  the socket will be inherited from the directory which hosts it, or from the<br />
  user the process is started with.
</p></blockquote>
<p>Simple enough. Edit your <b>haproxy.cfg</b> and add this into your &#8220;global&#8221; section:</p>
<pre>
global
        daemon
        maxconn 100
        quiet
        user haproxy
        group haproxy
        stats socket    /tmp/haproxy
</pre>
<p><a href="http://www.mgoff.in/2010/04/18/haproxy-reloading-your-config-with-minimal-service-impact/">Reload your HAProxy config</a> and you should now see a socket setup in <b>/tmp</b> (note in the <a href="http://www.freebsd.org/cgi/man.cgi?query=ls">ls</a> output that the &#8220;s&#8221; at the beginning of the permission set denotes the file type as a socket):</p>
<pre>
# ls -lah /tmp/haproxy
srwxr-xr-x 1 root root 0 2010-07-14 12:53 /tmp/haproxy
#
</pre>
<p>Now we can query HAProxy using this socket for some stats. A great way to do this is using <a href="http://www.dest-unreach.org/socat/">socat</a>. If you don&#8217;t have it installed, you can compile from <a href="http://www.dest-unreach.org/socat/download/">source</a>, or use the package management system for your OS (ex: &#8220;apt-get install socat&#8221; for Ubuntu).
</p>
<p>
To query for some stats, you can try the following commands:</p>
<pre>
# echo “show info” | socat unix-connect:/tmp/haproxy stdio
# echo “show stat” | socat unix-connect:/tmp/haproxy stdio
# echo “show errors” | socat unix-connect:/tmp/haproxy stdio
# echo “show sess” | socat unix-connect:/tmp/haproxy stdio
</pre>
<p>More information on interacting with HAProxy through the stats socket can be found in section <b>&#8220;9.2. Unix Socket commands&#8221;</b> of the configuration.txt file I linked to above (it&#8217;s the last section in the file).</p>
<p align="right"><a class="tt" href="http://twitter.com/home/?status=HAProxy%3A+Gathering+Stats+Using+%60socat%60+http://is.gd/drVrn" title="Post to Twitter"><img class="nothumb" src="http://www.mgoff.in/wp-content/plugins/tweet-this/icons/tt-twitter-micro4.png" alt="Post to Twitter" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mgoff.in/2010/07/14/haproxy-gathering-stats-using-socat/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>VIM Syntax Highlighting For Varnish VCL Files</title>
		<link>http://www.mgoff.in/2010/05/28/vim-syntax-highlighting-for-varnish-vcl-files/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=vim-syntax-highlighting-for-varnish-vcl-files</link>
		<comments>http://www.mgoff.in/2010/05/28/vim-syntax-highlighting-for-varnish-vcl-files/#comments</comments>
		<pubDate>Fri, 28 May 2010 04:25:35 +0000</pubDate>
		<dc:creator>Michael Goffin</dc:creator>
				<category><![CDATA[VIM]]></category>
		<category><![CDATA[Varnish]]></category>

		<guid isPermaLink="false">http://www.mgoff.in/?p=104</guid>
		<description><![CDATA[Varnish has become a popular topic of conversation lately, and rightly so. It is amazing. The Varnish-cache project describes it as simply a high-performance HTTP Accelerator. Outside of its use as a caching layer, it is also an excellent load balancer and proxy. One of the great things about Varnish is the Varnish Configuration Language. [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href="http://varnish-cache.org/">Varnish</a> has become a popular topic of conversation lately, and rightly so. It is amazing. The Varnish-cache project describes it as simply a high-performance HTTP Accelerator. Outside of its use as a caching layer, it is also an excellent load balancer and proxy.
</p>
<p>
One of the great things about Varnish is the <a href="http://varnish-cache.org/wiki/VCL">Varnish Configuration Language</a>. VCL files define the policies for Varnish when handling requests and for caching and are written in a syntax similar to C and Perl. What makes this so amazing is the following:</p>
<blockquote><p>
When a new configuration is loaded, the varnishd management process translates the VCL code to C and compiles it to a shared object which is then dynamically linked into the server process.
</p></blockquote>
<p>This just blows my mind. Talk about going the extra mile to squeeze out as much performance as you can from your application. It makes the VCL syntax much easier to understand when you can think about it in these terms and know what the application is going to do with it.
</p>
<p>
I&#8217;ve been sifting through VCL files in my free time to accumulate a list of nifty tricks that I might be interesting in using in the future. <a href="http://www.vim.org/">VIM</a> being my editor of choice, I hunted for a syntax file that would help when reading VCL files. I ran across <a href="http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/packages/vim-syntax-vcl/vcl.vim">one</a> written by Elan Ruusamäe and it was exactly what I needed. Download the latest version and put it in your ~/.vim/syntax directory. Then make the following additions to your .vimrc:</p>
<pre>
au BufRead,BufNewFile *.vcl :set ft=vcl
au! Syntax vcl source ~/.vim/syntax/vcl.vim
</pre>
<p>Now I can enjoy syntax highlighting when ripping through example code like I would most other things I edit with VIM.</p>
<p align="right"><a class="tt" href="http://twitter.com/home/?status=VIM+Syntax+Highlighting+For+Varnish+VCL+Files+http://is.gd/csx9F" title="Post to Twitter"><img class="nothumb" src="http://www.mgoff.in/wp-content/plugins/tweet-this/icons/tt-twitter-micro4.png" alt="Post to Twitter" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mgoff.in/2010/05/28/vim-syntax-highlighting-for-varnish-vcl-files/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Facebook: When Will It End?</title>
		<link>http://www.mgoff.in/2010/05/09/facebook-when-will-it-end/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=facebook-when-will-it-end</link>
		<comments>http://www.mgoff.in/2010/05/09/facebook-when-will-it-end/#comments</comments>
		<pubDate>Sun, 09 May 2010 15:31:36 +0000</pubDate>
		<dc:creator>Michael Goffin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Privacy]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://www.mgoff.in/?p=101</guid>
		<description><![CDATA[The questions that people have pondered as of late about personal data being exposed through Facebook have brought up some really interesting articles. There was an article several days ago from Wired about the &#8220;accidental&#8221; exposure of email addresses, and the glitch that allowed you to see your friend&#8217;s personal chats using a tool that [...]]]></description>
			<content:encoded><![CDATA[<p>
The questions that people have pondered as of late about personal data being exposed through <a href="http://www.facebook.com">Facebook</a> have brought up some really interesting articles. There was an article several days ago from <a href="http://www.wired.com/geekdad/2010/05/the-facebook-privacy-war-what-is-personal-data/?utm_source=feedburner&#038;utm_medium=feed&#038;utm_campaign=Feed:+wired/index+(Wired:+Index+3+(Top+Stories+2))&#038;utm_content=Google+Feedfetcher">Wired</a> about the &#8220;accidental&#8221; exposure of email addresses, and the glitch that allowed you to see your friend&#8217;s personal chats using a tool that was supposed to help you be more secure. Jamie Zawinski posted to his <a href="http://jwz.livejournal.com/1234802.html">Livejournal</a> with information showing that Facebook exposes your friend&#8217;s email address (encoded in Base64) in all of the notification emails you get. Matt McKeon posted a most-excellent <a href="http://mattmckeon.com/facebook-privacy/">visual interpretation</a> of how much of your information has been exposed <b>by default</b> using Facebook over the years.
</p>
<p>
When is this going to end? I really don&#8217;t want to wake up one morning, attempt to buy something on Amazon, and have it pop up saying it can just use the data it already knows about me from Facebook to fill out my billing and shipping information, along with my preferred payment method &#8211; when I didn&#8217;t give it access to. I don&#8217;t want to log into Netflix and have it pop up saying it&#8217;s gone through my Facebook friend&#8217;s profiles and found movie recommendations for me &#8211; when I didn&#8217;t give it access to. I don&#8217;t want to go to CVS and the pharmacist already have drugs for me because Facebook notified them of a status update I made about being ill. But over time, it seems that&#8217;s what Facebook is aiming for. The ability to be &#8220;all-knowing&#8221; about every user they have, and to let anyone have access to that information if they&#8217;re willing to pay for it.
</p>
<p>
It was bad enough everyone decided it was &#8220;fun&#8221; to let their friends (read: the Internet) know their exact location so they can &#8220;level up&#8221; in a game. I&#8217;m sure Facebook used that data wherever it could. These games are exactly what Facebook wants: a great way to disguise their ability to farm as much data about you as possible in order to make money off of you just living your life. Nice.
</p>
<p>
A lot of people complained about <a href="http://www.google.com">Google</a> doing the same thing. But there&#8217;s a fairly large difference. Most of the stuff Google does is <b>opt-in</b>. You&#8217;re not required to join <a href="http://www.orkut.com">Orkut</a> because you have a <a href="http://www.gmail.com">GMail</a> account, but you could. You don&#8217;t have to use Google Calendar because you have a GMail account, but you could. You don&#8217;t have to allow Google Buzz to aggregate your Twitter, Facebook, Picasa, etc., but you could. Not so much with Facebook. You have to constantly keep an eye on what you need to <b>opt-out</b> of, if it&#8217;s even an option for you to do so.
</p>
<p>
I already have friends who are deleting their accounts and cutting their losses with Facebook. Some people ask &#8220;what alternative do we have to keep in touch with friends the way we do on Facebook?&#8221; Good question. There isn&#8217;t one. The only collective of services that comes close would be some type of Twitter + Livejournal + MySpace thing. And even then, it&#8217;s clunky and much more difficult to follow. But really, what do most people use Facebook for? The status updates. If you change your address, that&#8217;s a status update. If you change your relationship status, that&#8217;s a status update. If you post a set of pictures, that&#8217;s a status update (&#8220;I&#8217;m posting pictures, check them out!&#8221; is what you&#8217;re telling people). Everything you do to your profile is done to tell everyone else about it. Twitter can do just that. Sure you may need to use a photo-hosting service like <a href="http://picasa.google.com/">Picasa</a> or <a href="http://www.flickr.com">Flickr</a>, and a video-hosting service like <a href="http://www.youtube.com">YouTube</a> so you can keep your stuff in collections and link to them. But companies like <a href="http://www.rememberthemilk.com/">Remember the Milk</a> and <a href="http://www.evernote.com/">Evernote</a> already allow you to <b>opt-in</b> and let them read your tweets so you can automatically post information to them to make things easier. <a href="http://twitpic.com/">Twitpic</a> instantly replaces your &#8220;mobile uploads&#8221; gallery. There&#8217;s plenty of mobile apps and desktop apps to follow Twitter and keep yourself connected.
</p>
<p>
The point is, if you rip away all of the fat, fluff, and cruft that&#8217;s accumulated on Facebook over the years, you get to the bare essentials of what it is and you realize that there are other services out there for you. Services that do just as good, if not a better job of sharing that information without sharing <b>all</b> of your information when you don&#8217;t want them to. Think about how much your privacy is worth.</p>
<p align="right"><a class="tt" href="http://twitter.com/home/?status=Facebook%3A+When+Will+It+End%3F+http://is.gd/c1oM4" title="Post to Twitter"><img class="nothumb" src="http://www.mgoff.in/wp-content/plugins/tweet-this/icons/tt-twitter-micro4.png" alt="Post to Twitter" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mgoff.in/2010/05/09/facebook-when-will-it-end/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Upgrading Gitorious</title>
		<link>http://www.mgoff.in/2010/04/27/upgrading-gitorious/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=upgrading-gitorious</link>
		<comments>http://www.mgoff.in/2010/04/27/upgrading-gitorious/#comments</comments>
		<pubDate>Tue, 27 Apr 2010 15:35:31 +0000</pubDate>
		<dc:creator>Michael Goffin</dc:creator>
				<category><![CDATA[Git]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Gitorious]]></category>
		<category><![CDATA[Redmine]]></category>

		<guid isPermaLink="false">http://www.mgoff.in/?p=90</guid>
		<description><![CDATA[[2010-07-12] UPDATE: I just confirmed that this works for the latest mainline. We use Gitorious at work as our Git front-end. We opted to not use Github since we wanted something we didn&#8217;t have to pay for, and was internal to our network. It has a great feature-set, and pretty much does everything we need [...]]]></description>
			<content:encoded><![CDATA[<p><b>[2010-07-12] UPDATE:</b> I just confirmed that this works for the latest mainline.</p>
<p>
We use Gitorious at work as our Git front-end. We opted to not use Github since we wanted something we didn&#8217;t have to pay for, and was internal to our network. It has a great feature-set, and pretty much does everything we need it to do and more.
</p>
<p>
There is a bit of documentation on how to get Gitorious installed (as painful as it may be), but there&#8217;s little to no documentation on how to upgrade it once it&#8217;s installed. I just went through an upgrade and it turned out to be much easier than I was anticipating.
</p>
<p>
First, we need to get the latest source:</p>
<pre>
  $ cd ~
  $ mkdir ~/gitorious
  $ git clone git://gitorious.org/gitorious/mainline.git gitorious
</pre>
<p>Next, we need to go through and compare all of the configuration files.</p>
<pre>
  $ cd gitorious
  $ cd config
  $ diff &lt;foo&gt; /path/to/current/gitorious/install/configs/&lt;foo&gt;
</pre>
<p>Where <b>foo</b> is any specific configuration file in the new Gitorious source and your current install. I found that for the most part I was able to copy my old configs in place and not have to change anything.
</p>
<p>This step is dependent on your install, but I made a few custom modifications to the source. I did not like how the &#8220;Projects&#8221; and &#8220;Repositories&#8221; pages were not listed alphabetically. They seemed to be ordered by descending creation date. Here&#8217;s the changes if you want to see how to do this as well:</p>
<pre>
--- app/views/projects/index.html.erb       2010-04-27 10:57:09.109711812 -0400
+++ /var/www/gitorious/app/views/projects/index.html.erb        2010-04-27 10:29:50.799722064 -0400
@@ -25,7 +25,7 @@
 &lt;h1&gt;Projects&lt;/h1&gt;

 &lt;ul class="project_list"&gt;
-&lt;% @projects.each do |project| -%&gt;
+&lt;% @projects.sort_by { |p| p[:title] }.each do |project| -%&gt;
   &lt;li class="project_list_item"&gt;
     &lt;%= render :partial =&gt; project, :object =&gt; project -%&gt;
   &lt;/li&gt;
--- app/views/projects/show.html.erb        2010-04-27 10:57:09.109711812 -0400
+++ /var/www/gitorious/app/views/projects/show.html.erb 2010-04-27 10:29:50.799722064 -0400
@@ -32,7 +32,7 @@
   &lt;%= render_markdown(@project.description, :auto_link) -%&gt;
 &lt;/div&gt;

-&lt;% @project.repositories.mainlines.each do |repo| -%&gt;
+&lt;% @project.repositories.mainlines.sort_by { |r| r[:name] }.each do |repo| -%&gt;
   &lt;%= render :partial =&gt; "repositories/overview", :locals =&gt; {:repository =&gt; repo} -%&gt;
 &lt;% end -%&gt;
</pre>
<p>We also use Redmine at work for issues and project management within our team. One of the features of Redmine is the ability to browse source and do code reviews. In order to do this, Redmine needs access to the repositories. A lot of solutions out there suggest writing cronjobs to clone the source into a place Redmine can read. I found this horrible since the clone will be out-of-date quickly unless you have a cronjob which runs more frequently than your developers commit. My solution is a bit better, and allows for live-code browsing. We happen to have Redmine on the same system as Gitorious (both being Ruby on Rails, this worked out nicely). In our Redmine install, I created a symlink to the Gitorious <b>repositories</b> folder (you can use an NFS mount if they are hosted on different machines). That solved Redmine&#8217;s ability to have direct access to the source. The problem with that is the Gitorious naming-scheme is not human-readable. So the problem we had is how to tell Redmine which folder to look at for a specific project. We solved this by using the directory information in the Gitorious database and exposing it in a format that can be pasted into Redmine. Here&#8217;s the diff for this feature if you want to use it:</p>
<pre>
--- app/views/repositories/show.html.erb    2010-04-27 10:57:09.109711812 -0400
+++ /var/www/gitorious/app/views/repositories/show.html.erb     2010-04-27 10:29:50.809717943 -0400
@@ -63,6 +63,9 @@
       &lt;strong&gt;&lt;%= t("views.repos.created") %&gt;:&lt;/strong&gt;
       &lt;%= @repository.created_at.to_s(:short) -%&gt;
     &lt;/li&gt;
+    &lt;li&gt;
+      &lt;strong&gt;Redmine: &lt;/strong&gt;/var/www/redmine/repositories/&lt;%= @repository.real_gitdir.to_s() -%&gt;
+    &lt;/li&gt;
   &lt;/ul&gt;

   &lt;ul class="links"&gt;
</pre>
<p>This will show up in Gitorious in the informational section on the right-hand side when viewing a repository.
</p>
<p>Now that you have copied your configuration files over, and your personalized code changes, it&#8217;s time to put the new source in place. <b>Backup your current install and current database before doing anything</b>. Once that is backed up, delete the old install, and put the new one in place. Copy your <b>repositories</b> directory from the old install into the new one. Copy your <b>public/system</b> directory from your old install to the new one to migrate avatars. Then update the database (this is assuming you are using the production environment):</p>
<pre>
  $ cd /path/to/new/gitorious/install
  $ rake db:migrate RAILS_ENV=production
</pre>
<p>This shouldn&#8217;t return any errors, just a list of database changes that were made to accommodate the new install. If that is successful, you can restart your services (we use Apache, so it was just a matter of restarting Apache) and then visit your Gitorious page to make sure nothing is horribly broken. If there are any problems, it is most likely an issue with the version of Ruby, or of the gems you have installed. Review the contents of <b>/path/to/new/gitorious/install/README</b> for information on what versions are required and how to install them.</p>
<p align="right"><a class="tt" href="http://twitter.com/home/?status=Upgrading+Gitorious+http://is.gd/bW3mK" title="Post to Twitter"><img class="nothumb" src="http://www.mgoff.in/wp-content/plugins/tweet-this/icons/tt-twitter-micro4.png" alt="Post to Twitter" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mgoff.in/2010/04/27/upgrading-gitorious/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>HAProxy: Reloading Your Config With Minimal Service Impact</title>
		<link>http://www.mgoff.in/2010/04/18/haproxy-reloading-your-config-with-minimal-service-impact/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=haproxy-reloading-your-config-with-minimal-service-impact</link>
		<comments>http://www.mgoff.in/2010/04/18/haproxy-reloading-your-config-with-minimal-service-impact/#comments</comments>
		<pubDate>Mon, 19 Apr 2010 03:34:10 +0000</pubDate>
		<dc:creator>Michael Goffin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[haproxy]]></category>

		<guid isPermaLink="false">http://www.mgoff.in/?p=77</guid>
		<description><![CDATA[HAProxy is a high performance load balancer. It is very light-weight, and free, making it a great option if you are in the market for a load balancer and need to keep your costs down. Lately we&#8217;ve been making a lot of load balancer changes at work to accommodate new systems and services. Even though [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href="http://haproxy.1wt.eu/">HAProxy</a> is a high performance load balancer. It is very light-weight, and free, making it a great option if you are in the market for a load balancer and need to keep your costs down.
</p>
<p>
Lately we&#8217;ve been making a lot of load balancer changes at work to accommodate new systems and services. Even though we have two load balancers running with <a href="http://www.keepalived.org/">keepalived</a> taking care of any failover situations, I was thinking about how we go about reloading our configuration files. In the event of a change, the &#8220;common&#8221; way to get the changes to take effect is to run <b>/etc/init.d/haproxy restart</b>. This is bad for a couple major reasons:</p>
<ol>
<li>You are temporarily shutting your load balancer down</li>
<li>You are severing any current connections going through the load balancer</li>
</ol>
<p>You might say, &#8220;if you have two load balancers with keepalived, restarting the service should be fine since keepalived will handle the failover.&#8221; This, however, isn&#8217;t always true. Keepalived uses advertisements to determine when to fail over. The default advertisement interval is 1 second (configurable in keepalived.conf). The skew time helps to keep everyone from trying to transition at once. It is a number between 0 and 1, based on the formula <b>(256 &#8211; priority) / 256</b>. As defined in the RFC, the backup must receive an advertisement from the master every <b>(3 * advert_int) + skew_time</b> seconds. If it doesn&#8217;t hear anything from the master, it takes over.
</p>
<p>
Let&#8217;s assume you are using the default interval of 1 second. On my test machine, this is the duration of time it takes to restart haproxy:</p>
<pre>
# time /etc/init.d/haproxy restart
 * Restarting haproxy haproxy
   ...done.

real    0m0.022s
user    0m0.000s
sys     0m0.016s
</pre>
<p>In this situation, haproxy would restart much faster than your 1 second interval. You could get lucky and happen to restart it just before the check, but luck is not consistent enough to be useful. Also, in very high-traffic situations, you&#8217;ll be causing a lot of connection issues. So we cannot rely on keepalived to solve the first problem, and it definitely doesn&#8217;t solve the second problem.
</p>
<p>
After sifting through haproxy documentation (the text-based documentation, not the man page) (/usr/share/doc/haproxy/haproxy-en.txt.gz on Ubuntu), I came across this:</p>
<pre>
    313
    314     global
    315         daemon
    316         quiet
    317         nbproc  2
    318         pidfile /var/run/haproxy-private.pid
    319
    320     # to stop only those processes among others :
    321     # kill $(&lt;/var/run/haproxy-private.pid)
    322
    323     # to reload a new configuration with minimal service impact and without
    324     # breaking existing sessions :
    325     # haproxy -f haproxy.cfg -p $(&lt;/var/run/haproxy-private.pid) -st $(&lt;/var/run/haproxy-private.pid)
</pre>
<p>That last command is the one of interest. The -p asks the process to write down each of its children&#8217;s pids to the specified pid file, and the -st specifies a list of pids to send a SIGTERM to after startup. But it does this in an interesting way:</p>
<pre>
    609 The '-st' and '-sf' command line options are used to inform previously running
    610 processes that a configuration is being reloaded. They will receive the SIGTTOU
    611 signal to ask them to temporarily stop listening to the ports so that the new
    612 process can grab them. If anything wrong happens, the new process will send
    613 them a SIGTTIN to tell them to re-listen to the ports and continue their normal
    614 work. Otherwise, it will either ask them to finish (-sf) their work then softly
    615 exit, or immediately terminate (-st), breaking existing sessions. A typical use
    616 of this allows a configuration reload without service interruption :
    617
    618  # haproxy -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)
</pre>
<p>The end-result is a reload of the configuration file which is not visible by the customer. It also solves the second problem! Let&#8217;s look at an example of the command and look at the time compared to our above example:</p>
<pre>
# time haproxy -f /etc/haproxy.cfg -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)

real    0m0.018s
user    0m0.000s
sys     0m0.004s
</pre>
<p>I&#8217;ve specified the config file I want to use and the pid file haproxy is currently using. The <b>$(cat /var/run/haproxy.pid)</b> takes the output of <b>cat /var/run/haproxy.pid</b> and passes it in to the -sf parameter as a list, which is what it is expecting. You will notice that the time is actually faster too (.012s sys, and .004s real). It may not seem like much, but if you are dealing with very high volumes of traffic, this can be pretty important. Luckily for us it doesn&#8217;t matter because we&#8217;ve been able to reload the haproxy configuration without dropping any connections and without causing any customer-facing issues.
</p>
<p>
<b>UPDATE:</b> There is a reload in some of the init.d scripts (I haven&#8217;t checked every OS, so this can vary), but it uses the -st option which will break existing sessions, as opposed to using -sf to do a graceful hand-off. You can modify the haproxy_reload() function to use the -sf if you want. I also find it a bit confusing that the documentation uses <b>$(cat /path/to/pidfile)</b> whereas this haproxy_reload() function uses <b>$(<$PIDFILE)</b>. Either should work, but really, way to lead by example&#8230;</p>
<p align="right"><a class="tt" href="http://twitter.com/home/?status=HAProxy%3A+Reloading+Your+Config+With+Minimal+Service+Impact+http://is.gd/bW3mM" title="Post to Twitter"><img class="nothumb" src="http://www.mgoff.in/wp-content/plugins/tweet-this/icons/tt-twitter-micro4.png" alt="Post to Twitter" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mgoff.in/2010/04/18/haproxy-reloading-your-config-with-minimal-service-impact/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Motorola Droid 2.1 Update URL</title>
		<link>http://www.mgoff.in/2010/03/31/android-2-1-update-url/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=android-2-1-update-url</link>
		<comments>http://www.mgoff.in/2010/03/31/android-2-1-update-url/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 13:11:37 +0000</pubDate>
		<dc:creator>Michael Goffin</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[DroidMod]]></category>
		<category><![CDATA[Droid]]></category>

		<guid isPermaLink="false">http://www.mgoff.in/?p=73</guid>
		<description><![CDATA[The official Motorola Droid 2.1 update is out. You can get it here: ESD81-from-ESD56. Word in the DroidMod community is that we&#8217;ve rooted it already. I&#8217;m sure over the next day or so it&#8217;s going to be a whirlwind of forum updates and IRC chat to get this thing to the masses as quickly as [...]]]></description>
			<content:encoded><![CDATA[<p>
The official Motorola Droid 2.1 update is out. You can get it here: <a href=" https://android.clients.google.com/updates/voles/signed-voles-ESE81-from-ESD56.fa406da6.zip">ESD81-from-ESD56</a>.
</p>
<p>
Word in the DroidMod community is that we&#8217;ve rooted it already. I&#8217;m sure over the next day or so it&#8217;s going to be a whirlwind of forum updates and IRC chat to get this thing to the masses as quickly as possible. But it also doesn&#8217;t seem like it is doing anything more than what DroidMod 1.0 has already provided. When I have more details, I&#8217;ll pass it along.</p>
<p align="right"><a class="tt" href="http://twitter.com/home/?status=Motorola+Droid+2.1+Update+URL+http://is.gd/bW3mN" title="Post to Twitter"><img class="nothumb" src="http://www.mgoff.in/wp-content/plugins/tweet-this/icons/tt-twitter-micro4.png" alt="Post to Twitter" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mgoff.in/2010/03/31/android-2-1-update-url/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hiding Sections In MediaWiki</title>
		<link>http://www.mgoff.in/2010/03/26/hiding-sections-in-mediawiki/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=hiding-sections-in-mediawiki</link>
		<comments>http://www.mgoff.in/2010/03/26/hiding-sections-in-mediawiki/#comments</comments>
		<pubDate>Fri, 26 Mar 2010 17:35:56 +0000</pubDate>
		<dc:creator>Michael Goffin</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[MediaWiki]]></category>

		<guid isPermaLink="false">http://www.mgoff.in/?p=67</guid>
		<description><![CDATA[I recently implemented the Bugzilla Reports extension at work for MediaWiki. We use MediaWiki to outline release notes and other documentation, and we include in those notes a list of related bugs that were resolved and closed. With so much manual work to write out the bugs and link to them, it made more sense [...]]]></description>
			<content:encoded><![CDATA[<p>
I recently implemented the <a href="http://www.mediawiki.org/wiki/Extension:Bugzilla_Reports">Bugzilla Reports</a> extension at work for MediaWiki. We use MediaWiki to outline release notes and other documentation, and we include in those notes a list of related bugs that were resolved and closed. With so much manual work to write out the bugs and link to them, it made more sense to include this extension so displaying those bugs is just a simple query. But what I also noticed is that our list of bugs can be quite long depending on the size and nature of the release notes. It would be great if we could hide sections so in the event the bugs section was too huge, you can easily hide/show it. Enter <a href="http://jquery.com/">jQuery</a>!
</p>
<p>
I won&#8217;t go into the specifics of setting up jQuery on MediaWiki, but you can find a decent summary of the steps <a href="http://www.thusa.co.za/blog/gareth-davies/getting-jquery-running-mediawiki">here</a>. Once you have that working, you&#8217;ll need to do the following:</p>
<ul>
<li>For the skin you are using, edit the <b> /&lt;path to mediawiki install&gt;/skins/&lt;skin name&gt;.php</b> file
<li>After the <b>&lt;/body&gt;</b> tag and after your script tags for including jQuery, add the following:
</ul>
<pre>
&lt;script&gt;
    $(":header>span.mw-headline").click( function() {
        var $start = $(":header").index($(this).parent());
        var $end   = $start + 1;
        $(":header").eq($start).toggleClass("highlight");
        $(":header").eq($start).nextAll().not(":header").toggle();
        $(":header").eq($end).nextAll().not(":header").toggle();
    });
&lt;/script&gt;
</pre>
<p>And that&#8217;s it! The reason we look for the span with a class of &#8220;mw-headline&#8221; is because of the &#8220;Edit&#8221; section buttons. If we look for just the header, you&#8217;ll wind up catching the Edit button and if you try to click the Edit link you&#8217;ll actually toggle the section instead. This is also why we we get the index of <i>$(this).parent()</i>. Since we clicked on an element inside the header, we don&#8217;t want to use the index of that element otherwise it won&#8217;t toggle everything correctly.
</p>
<p>
Props to <a href="http://www.mail-archive.com/jquery-en@googlegroups.com/msg40033.html">Andi</a> for some example code. Made it easy to tweak it a little to get the Edit button working again.</p>
<p align="right"><a class="tt" href="http://twitter.com/home/?status=Hiding+Sections+In+MediaWiki+http://is.gd/bW3mQ" title="Post to Twitter"><img class="nothumb" src="http://www.mgoff.in/wp-content/plugins/tweet-this/icons/tt-twitter-micro4.png" alt="Post to Twitter" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mgoff.in/2010/03/26/hiding-sections-in-mediawiki/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How The Droid Was Rooted</title>
		<link>http://www.mgoff.in/2010/03/21/how-the-droid-was-rooted/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=how-the-droid-was-rooted</link>
		<comments>http://www.mgoff.in/2010/03/21/how-the-droid-was-rooted/#comments</comments>
		<pubDate>Sun, 21 Mar 2010 22:29:50 +0000</pubDate>
		<dc:creator>Michael Goffin</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[CarolinaCon]]></category>

		<guid isPermaLink="false">http://www.mgoff.in/?p=58</guid>
		<description><![CDATA[As promised, here is a link to the presentation I gave today at CarolinaCon. If you were at the con and you find your way here, drop me a comment and let me know what you thought. How The Droid Was Rooted (if you use Google Chrome, right-click and &#8220;save link as&#8221;) I had a [...]]]></description>
			<content:encoded><![CDATA[<p>
As promised, here is a link to the presentation I gave today at CarolinaCon. If you were at the con and you find your way here, drop me a comment and let me know what you thought.</p>
<p><a href="http://www.mgoff.in/dump/info/droid.pptx">How The Droid Was Rooted</a> (if you use Google Chrome, right-click and &#8220;save link as&#8221;)
</p>
<p>
I had a great time this weekend. I got to see a lot of old friends, make a lot of new friends, and contribute back to the community. Thanks to <a href="http://www.nc2600.org/">NC2600</a> for letting me present and for putting on another great con. See everyone next year!</p>
<p align="right"><a class="tt" href="http://twitter.com/home/?status=How+The+Droid+Was+Rooted+http://is.gd/bW3mR" title="Post to Twitter"><img class="nothumb" src="http://www.mgoff.in/wp-content/plugins/tweet-this/icons/tt-twitter-micro4.png" alt="Post to Twitter" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mgoff.in/2010/03/21/how-the-droid-was-rooted/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CarolinaCon 2010 This Weekend!</title>
		<link>http://www.mgoff.in/2010/03/19/carolinacon-2010-this-weekend/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=carolinacon-2010-this-weekend</link>
		<comments>http://www.mgoff.in/2010/03/19/carolinacon-2010-this-weekend/#comments</comments>
		<pubDate>Fri, 19 Mar 2010 05:07:15 +0000</pubDate>
		<dc:creator>Michael Goffin</dc:creator>
				<category><![CDATA[CarolinaCon]]></category>

		<guid isPermaLink="false">http://www.mgoff.in/?p=55</guid>
		<description><![CDATA[CarolinaCon starts tomorrow evening. If you happen to be around the Raleigh area, I highly recommend coming and enjoying some of the talks that are lined up. You can&#8217;t beat three days of great talks, networking, and rocking out for $20. As I did last year, I&#8217;m still tweaking my talk. It&#8217;s ready to rock [...]]]></description>
			<content:encoded><![CDATA[<p>
CarolinaCon starts tomorrow evening. If you happen to be around the Raleigh area, I highly recommend coming and enjoying some of the talks that are lined up. You can&#8217;t beat three days of great talks, networking, and rocking out for $20. As I did last year, I&#8217;m still tweaking my talk. It&#8217;s ready to rock as is, but I tend to fuss over this type of stuff and I want to make sure I include as much information as I can without going over my time slot, and making time for questions during/after the talk.
</p>
<p>
After my talk is done, I&#8217;ll be posting the presentation for anyone to download if they can&#8217;t make it. If you do get a chance to go, find me and say hi!</p>
<p align="right"><a class="tt" href="http://twitter.com/home/?status=CarolinaCon+2010+This+Weekend%21+http://is.gd/bW3mT" title="Post to Twitter"><img class="nothumb" src="http://www.mgoff.in/wp-content/plugins/tweet-this/icons/tt-twitter-micro4.png" alt="Post to Twitter" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mgoff.in/2010/03/19/carolinacon-2010-this-weekend/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
