<?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>Letsgetdugg&#187; main</title>
	<atom:link href="http://letsgetdugg.com/category/main/feed/" rel="self" type="application/rss+xml" />
	<link>http://letsgetdugg.com</link>
	<description>Random tech jargon</description>
	<lastBuildDate>Fri, 21 Jan 2011 19:31:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ruby LocaleTranslator</title>
		<link>http://letsgetdugg.com/2010/07/20/ruby-locale-translator/</link>
		<comments>http://letsgetdugg.com/2010/07/20/ruby-locale-translator/#comments</comments>
		<pubDate>Tue, 20 Jul 2010 21:05:55 +0000</pubDate>
		<dc:creator>victori</dc:creator>
				<category><![CDATA[main]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[localization]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://letsgetdugg.com/?p=741</guid>
		<description><![CDATA[Today, I am open sourcing my Ruby LocaleTranslator; the translator uses google&#8217;s translator API to translate a primary seed locale into various other languages. This eases the creation of multi-lingual sites. Not only can the LocaleTranslator translate your main seed locale into different languages but it can also recursively merge in differences, this comes in [...]]]></description>
			<content:encoded><![CDATA[<p>Today, I am open sourcing my Ruby LocaleTranslator; the translator uses google&#8217;s translator API to translate a primary seed locale into various other languages. This eases the creation of multi-lingual sites. Not only can the LocaleTranslator translate your main seed locale into different languages but it can also recursively merge in differences, this comes in handy if you have hand-optimized your translated locales.</p>
<p>Viva Localization!</p>
<p>My projects that use the LocaleTranslator;  <a href="http://uploadbooth.com/">UploadBooth</a>, <a href="http://pastebooth.com/">PasteBooth</a> and <a href="http://shrinkbooth.com/">ShrinkBooth</a>.</p>
<h3>LocaleTranslator Examples</h3>
<p><strong>en.yml</strong></p>
<pre>
<div class="codesnip-container" >site:
  hello_world: Hello World!
  home: Home
  statement: Localization should be simple!</div>
</pre>
<p>Batch Conversion of your English locale.</p>
<div class="codesnip-container" >
<div class="ruby codesnip" style="font-family:monospace;"><span class="co1">#!/opt/local/bin/ruby</span></p>
<p><span class="kw3">require</span> <span class="st0">&#8216;monkey-patches.rb&#8217;</span><br />
<span class="kw3">require</span> <span class="st0">&#8216;locale_translator.rb&#8217;</span></p>
<p>en_yml = <span class="kw4">YAML</span>::<span class="kw3">load</span><span class="br0">&#40;</span><span class="kw4">File</span>.<span class="kw3">open</span><span class="br0">&#40;</span><span class="st0">&#8216;en.yml&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p><span class="br0">&#91;</span><span class="re3">:de</span>,:ru<span class="br0">&#93;</span>.<span class="me1">each</span> <span class="kw1">do</span> <span class="sy0">|</span>lang<span class="sy0">|</span><br />
&nbsp; lang_yml = LocaleTranslator.<span class="me1">translate</span><span class="br0">&#40;</span>en_yml,<br />
&nbsp; &nbsp; <span class="re3">:to</span><span class="sy0">=&gt;</span>lang,<br />
&nbsp; &nbsp; <span class="re3">:html</span><span class="sy0">=&gt;</span>true,<br />
&nbsp; &nbsp; <span class="re3">:key</span><span class="sy0">=&gt;</span><span class="st0">&#8216;GOOGLE API KEY&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; f = <span class="kw4">File</span>.<span class="me1">new</span><span class="br0">&#40;</span><span class="st0">&quot;#{lang.to_s.downcase}.yml&quot;</span>,<span class="st0">&quot;w&quot;</span><span class="br0">&#41;</span><br />
&nbsp; f.<span class="kw3">puts</span><span class="br0">&#40;</span>lang_yml.<span class="me1">ya2yaml</span><span class="br0">&#40;</span><span class="re3">:syck_compatible</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; f.<span class="me1">close</span><br />
&nbsp; <span class="kw3">p</span> <span class="st0">&quot;Translated to #{lang.to_s}&quot;</span><br />
<span class="kw1">end</span></div>
</div>
<p>Merge in new locale keys from your English Locale into your already translated Russian locale.</p>
<div class="codesnip-container" >
<div class="ruby codesnip" style="font-family:monospace;"><span class="co1">#!/opt/local/bin/ruby</span></p>
<p><span class="kw3">require</span> <span class="st0">&#8216;monkey-patches.rb&#8217;</span><br />
<span class="kw3">require</span> <span class="st0">&#8216;locale_translator.rb&#8217;</span></p>
<p>en_yml = <span class="kw4">YAML</span>::<span class="kw3">load</span><span class="br0">&#40;</span><span class="kw4">File</span>.<span class="kw3">open</span><span class="br0">&#40;</span><span class="st0">&#8216;en.yml&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
ru_yml = <span class="kw4">YAML</span>::<span class="kw3">load</span><span class="br0">&#40;</span><span class="kw4">File</span>.<span class="kw3">open</span><span class="br0">&#40;</span><span class="st0">&#8216;ru.yml&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p>ru_new_yml = LocaleTranslator.<span class="me1">translate</span><span class="br0">&#40;</span>en_yml,<br />
&nbsp; <span class="re3">:to</span><span class="sy0">=&gt;</span>:ru,<br />
&nbsp; <span class="re3">:html</span><span class="sy0">=&gt;</span>true,<br />
&nbsp; <span class="re3">:merge</span><span class="sy0">=&gt;</span>ru_yml,<br />
&nbsp; <span class="re3">:key</span><span class="sy0">=&gt;</span><span class="st0">&#8216;GOOGLE API KEY&#8217;</span><span class="br0">&#41;</span><br />
<span class="kw3">puts</span> ru_new_yml.<span class="me1">ya2yaml</span><span class="br0">&#40;</span><span class="re3">:syck_compatible</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="br0">&#41;</span></div>
</div>
<h3>The Implementation Code</h3>
<p><strong>Support Monkey Patches</strong></p>
<p><strong>monkey-patches.rb</strong></p>
<div class="codesnip-container" >
<div class="ruby codesnip" style="font-family:monospace;"><span class="kw1">class</span> <span class="kw4">Hash</span><br />
&nbsp; <span class="kw1">def</span> to_list<br />
&nbsp; &nbsp; h2l<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">end</span><br />
&nbsp; <br />
&nbsp; <span class="kw1">def</span> diff<span class="br0">&#40;</span>hash<span class="br0">&#41;</span><br />
&nbsp; &nbsp; hsh = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; this = <span class="kw2">self</span><br />
&nbsp; &nbsp; hash.<span class="me1">each</span> <span class="kw1">do</span> <span class="sy0">|</span>k,v<span class="sy0">|</span> <br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> v.<span class="me1">kind_of</span>?<span class="kw4">Hash</span> <span class="kw1">and</span> this.<span class="me1">key</span>?k<br />
&nbsp; &nbsp; &nbsp; &nbsp; tmp = this<span class="br0">&#91;</span>k<span class="br0">&#93;</span>.<span class="me1">diff</span><span class="br0">&#40;</span>v<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; hsh<span class="br0">&#91;</span>k<span class="br0">&#93;</span> = tmp <span class="kw1">if</span> tmp.<span class="me1">size</span> <span class="sy0">&gt;</span> 0 <br />
&nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; hsh<span class="br0">&#91;</span>k<span class="br0">&#93;</span> = v <span class="kw1">unless</span> this.<span class="me1">key</span>?k <br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; hsh<br />
&nbsp; <span class="kw1">end</span><br />
&nbsp; <br />
&nbsp; <span class="kw1">def</span> merge_r<span class="br0">&#40;</span>hash<span class="br0">&#41;</span><br />
&nbsp; &nbsp; hsh = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; this = <span class="kw2">self</span><br />
&nbsp; &nbsp; hash.<span class="me1">each</span> <span class="kw1">do</span> <span class="sy0">|</span>k,v<span class="sy0">|</span> <br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> v.<span class="me1">kind_of</span>?<span class="kw4">Hash</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; hsh<span class="br0">&#91;</span>k<span class="br0">&#93;</span> = this<span class="br0">&#91;</span>k<span class="br0">&#93;</span>.<span class="me1">merge_r</span><span class="br0">&#40;</span>v<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; hsh<span class="br0">&#91;</span>k<span class="br0">&#93;</span> = v<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">merge</span><span class="br0">&#40;</span>hsh<span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">end</span><br />
&nbsp; <br />
&nbsp; private <br />
&nbsp; &nbsp; <span class="kw1">def</span> h2l<span class="br0">&#40;</span>hash<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; list = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; hash.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>k,v<span class="sy0">|</span> list = <span class="br0">&#40;</span>v.<span class="me1">kind_of</span>?<span class="kw4">Hash</span><span class="br0">&#41;</span> ? list.<span class="me1">merge_with_dups</span><span class="br0">&#40;</span>h2l<span class="br0">&#40;</span>v<span class="br0">&#41;</span><span class="br0">&#41;</span> : list <span class="sy0">&lt;&lt;</span> v <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; list<br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
<span class="kw1">end</span></p>
<p><span class="kw1">class</span> <span class="kw3">Array</span><br />
&nbsp; <span class="kw1">def</span> chunk<span class="br0">&#40;</span><span class="kw3">p</span>=2<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw2">return</span> <span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="kw1">if</span> <span class="kw3">p</span>.<span class="me1">zero</span>?<br />
&nbsp; &nbsp; p_size = <span class="br0">&#40;</span>length.<span class="me1">to_f</span> <span class="sy0">/</span> <span class="kw3">p</span><span class="br0">&#41;</span>.<span class="me1">ceil</span><br />
&nbsp; &nbsp; <span class="br0">&#91;</span>first<span class="br0">&#40;</span>p_size<span class="br0">&#41;</span>, <span class="sy0">*</span>last<span class="br0">&#40;</span>length <span class="sy0">-</span> p_size<span class="br0">&#41;</span>.<span class="me1">chunk</span><span class="br0">&#40;</span><span class="kw3">p</span> <span class="sy0">-</span> 1<span class="br0">&#41;</span><span class="br0">&#93;</span><br />
&nbsp; <span class="kw1">end</span><br />
&nbsp; <span class="kw1">def</span> to_hash<span class="br0">&#40;</span>hash<span class="br0">&#41;</span><br />
&nbsp; &nbsp; l2h<span class="br0">&#40;</span>hash,<span class="kw2">self</span><span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">end</span><br />
&nbsp; <span class="kw1">def</span> merge<span class="br0">&#40;</span>arr<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw2">self</span> <span class="sy0">|</span> arr<br />
&nbsp; <span class="kw1">end</span><br />
&nbsp; <span class="kw1">def</span> merge_with_dups<span class="br0">&#40;</span>arr<span class="br0">&#41;</span><br />
&nbsp; &nbsp; temp = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>a<span class="sy0">|</span> temp <span class="sy0">&lt;&lt;</span> a <span class="br0">&#125;</span><br />
&nbsp; &nbsp; arr.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>a<span class="sy0">|</span> temp <span class="sy0">&lt;&lt;</span> a <span class="br0">&#125;</span><br />
&nbsp; &nbsp; temp<br />
&nbsp; <span class="kw1">end</span><br />
&nbsp; <span class="kw1">def</span> merge!<span class="br0">&#40;</span>arr<span class="br0">&#41;</span><br />
&nbsp; &nbsp; temp = <span class="kw2">self</span>.<span class="me1">clone</span><br />
&nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">clear</span><br />
&nbsp; &nbsp; temp.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>a<span class="sy0">|</span> <span class="kw2">self</span> <span class="sy0">&lt;&lt;</span> a <span class="br0">&#125;</span><br />
&nbsp; &nbsp; arr.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>a<span class="sy0">|</span> <span class="kw2">self</span> <span class="sy0">&lt;&lt;</span> a <span class="kw1">unless</span> temp.<span class="kw1">include</span>?a <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw2">true</span><br />
&nbsp; <span class="kw1">end</span><br />
&nbsp; <span class="kw1">def</span> merge_with_dups!<span class="br0">&#40;</span>arr<span class="br0">&#41;</span><br />
&nbsp; &nbsp; temp = <span class="kw2">self</span>.<span class="me1">clone</span><br />
&nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">clear</span><br />
&nbsp; &nbsp; temp.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>a<span class="sy0">|</span> <span class="kw2">self</span> <span class="sy0">&lt;&lt;</span> a <span class="br0">&#125;</span><br />
&nbsp; &nbsp; arr.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>a<span class="sy0">|</span> <span class="kw2">self</span> <span class="sy0">&lt;&lt;</span> a <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw2">true</span><br />
&nbsp; <span class="kw1">end</span><br />
&nbsp; private<br />
&nbsp; &nbsp; <span class="kw1">def</span> l2h<span class="br0">&#40;</span>hash,lst<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; hsh = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; hash.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>k,v<span class="sy0">|</span> hsh<span class="br0">&#91;</span>k<span class="br0">&#93;</span> = <span class="br0">&#40;</span>v.<span class="me1">kind_of</span>?<span class="kw4">Hash</span><span class="br0">&#41;</span> ? l2h<span class="br0">&#40;</span>v,lst<span class="br0">&#41;</span> : lst.<span class="me1">shift</span> <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; hsh<br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
<span class="kw1">end</span></div>
</div>
<p><strong>The LocaleTranslator Implementation</strong></p>
<p>You need the ya2yaml and easy_translate gems. Ya2YAML can export locales in UTF-8 unlike the standard yaml implementation that can only export in binary for non-standard ascii.</p>
<p><strong>locale-translator.rb</strong></p>
<div class="codesnip-container" >
<div class="ruby codesnip" style="font-family:monospace;"><span class="re0">$KCODE</span> = <span class="st0">&#8216;UTF8&#8242;</span> <span class="kw1">if</span> RUBY_VERSION <span class="sy0">&lt;</span> <span class="st0">&#8217;1.9.0&#8242;</span><br />
<span class="kw3">require</span> <span class="st0">&#8216;rubygems&#8217;</span><br />
<span class="kw3">require</span> <span class="st0">&#8216;ya2yaml&#8217;</span><br />
<span class="kw3">require</span> <span class="st0">&#8216;yaml&#8217;</span><br />
<span class="kw3">require</span> <span class="st0">&#8216;easy_translate&#8217;</span></p>
<p><span class="kw1">class</span> LocaleTranslator<br />
&nbsp; <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">translate</span><span class="br0">&#40;</span>text,opts<span class="br0">&#41;</span><br />
&nbsp; &nbsp; opts<span class="br0">&#91;</span><span class="re3">:to</span><span class="br0">&#93;</span> = <span class="br0">&#91;</span>opts<span class="br0">&#91;</span><span class="re3">:to</span><span class="br0">&#93;</span><span class="br0">&#93;</span> <span class="kw1">if</span> opts<span class="br0">&#91;</span><span class="re3">:to</span><span class="br0">&#93;</span> <span class="kw1">and</span> !opts<span class="br0">&#91;</span><span class="re3">:to</span><span class="br0">&#93;</span>.<span class="me1">kind_of</span>?<span class="kw3">Array</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">if</span> opts<span class="br0">&#91;</span><span class="re3">:merge</span><span class="br0">&#93;</span>.<span class="me1">kind_of</span>?<span class="kw4">Hash</span> <span class="kw1">and</span> text.<span class="me1">kind_of</span>?<span class="kw4">Hash</span><br />
&nbsp; &nbsp; &nbsp; diff = opts<span class="br0">&#91;</span><span class="re3">:merge</span><span class="br0">&#93;</span>.<span class="me1">diff</span><span class="br0">&#40;</span>text<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; diff_hsh = LocaleTranslator.<span class="me1">translate</span><span class="br0">&#40;</span>diff,:to<span class="sy0">=&gt;</span>opts<span class="br0">&#91;</span><span class="re3">:to</span><span class="br0">&#93;</span>,:html<span class="sy0">=&gt;</span>true<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> opts<span class="br0">&#91;</span><span class="re3">:merge</span><span class="br0">&#93;</span>.<span class="me1">merge_r</span><span class="br0">&#40;</span>diff_hsh<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">if</span> text.<span class="me1">kind_of</span>?<span class="kw4">Hash</span><br />
&nbsp; &nbsp; &nbsp; t_arr = text.<span class="me1">to_list</span><br />
&nbsp; &nbsp; &nbsp; t_arr = t_arr.<span class="me1">first</span> <span class="kw1">if</span> t_arr.<span class="me1">size</span> == 1<br />
&nbsp; &nbsp; &nbsp; tout_arr = LocaleTranslator.<span class="me1">translate</span><span class="br0">&#40;</span>t_arr,:to<span class="sy0">=&gt;</span>opts<span class="br0">&#91;</span><span class="re3">:to</span><span class="br0">&#93;</span>,:html<span class="sy0">=&gt;</span>true<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; tout_arr = <span class="br0">&#91;</span>tout_arr<span class="br0">&#93;</span> <span class="kw1">if</span> tout_arr.<span class="me1">kind_of</span>?<span class="kw3">String</span><br />
&nbsp; &nbsp; &nbsp; tout_arr.<span class="me1">to_hash</span><span class="br0">&#40;</span>text<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">elsif</span> text.<span class="me1">kind_of</span>?<span class="kw3">Array</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> text.<span class="me1">size</span> <span class="sy0">&gt;</span> 50<br />
&nbsp; &nbsp; &nbsp; &nbsp; out = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; text.<span class="me1">chunk</span>.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>l<span class="sy0">|</span> out.<span class="me1">merge_with_dups</span>!<span class="br0">&#40;</span>EasyTranslate.<span class="me1">translate</span><span class="br0">&#40;</span>l,opts<span class="br0">&#41;</span>.<span class="me1">first</span><span class="br0">&#41;</span> <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; out<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; text = text.<span class="me1">first</span> <span class="kw1">if</span> text.<span class="me1">size</span> == 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; EasyTranslate.<span class="me1">translate</span><span class="br0">&#40;</span>text,opts<span class="br0">&#41;</span>.<span class="me1">first</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; EasyTranslate.<span class="me1">translate</span><span class="br0">&#40;</span>text,opts<span class="br0">&#41;</span>.<span class="me1">first</span><br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; <span class="kw1">end</span><br />
<span class="kw1">end</span></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://letsgetdugg.com/2010/07/20/ruby-locale-translator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MacOS X ZFS Samba Transfer Fix</title>
		<link>http://letsgetdugg.com/2010/07/18/macos-x-zfs-samba-transfer-fix/</link>
		<comments>http://letsgetdugg.com/2010/07/18/macos-x-zfs-samba-transfer-fix/#comments</comments>
		<pubDate>Sun, 18 Jul 2010 16:19:01 +0000</pubDate>
		<dc:creator>victori</dc:creator>
				<category><![CDATA[administration]]></category>
		<category><![CDATA[main]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[fix]]></category>
		<category><![CDATA[zfs]]></category>

		<guid isPermaLink="false">http://letsgetdugg.com/?p=737</guid>
		<description><![CDATA[I have a very non-standard storage setup at home. The setup is made up of a 3x500G raidz array on ZFS hosted by OSX. For the longest time I could not get files to copy over samba on ZFS. The files would stream just fine but not copy over, they would abort at the 99% [...]]]></description>
			<content:encoded><![CDATA[<p>I have a very non-standard storage setup at home. The setup is made up of a 3x500G raidz array on ZFS hosted by OSX. For the longest time I could not get files to copy over samba on ZFS. The files would stream just fine but not copy over, they would abort at the 99% transfer point. Well, I have finally found the fix for it; turn off extended attributes!</p>
<p>smb.conf</p>
<div class="codesnip-container" >#vfs objects = notify_kqueue,darwinacl,darwin_streams<br />
    vfs objects = notify_kqueue,darwinacl</p>
<p>    ; The darwin_streams module gives us named streams support.<br />
    stream support = no<br />
    ea support = no</p>
<p>    ; Enable locking coherency with AFP.<br />
    darwin_streams:brlm = no</p></div>
<p>As Charles Heston would say, You can have my ZFS when you pry it from my cold dead hands. </p>
<p>viva ZFS on OSX!</p>
]]></content:encoded>
			<wfw:commentRss>http://letsgetdugg.com/2010/07/18/macos-x-zfs-samba-transfer-fix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>STOMP Client on JRuby</title>
		<link>http://letsgetdugg.com/2010/07/16/stomp-client-on-jruby/</link>
		<comments>http://letsgetdugg.com/2010/07/16/stomp-client-on-jruby/#comments</comments>
		<pubDate>Fri, 16 Jul 2010 18:13:59 +0000</pubDate>
		<dc:creator>victori</dc:creator>
				<category><![CDATA[main]]></category>
		<category><![CDATA[jruby]]></category>
		<category><![CDATA[monkey-patching]]></category>

		<guid isPermaLink="false">http://letsgetdugg.com/?p=733</guid>
		<description><![CDATA[I recently needed to make use of our ActiveMQ message queue service to scale up write performance of CouchDB. However, there seemed to be a bug with JRuby that kills off the STOMP subscriber every 5 seconds. Digging a bit deeper into the STOMP source, I figured out a way to get around the bug [...]]]></description>
			<content:encoded><![CDATA[<p>I recently needed to make use of our <a href="http://activemq.apache.org/">ActiveMQ message queue</a> service to scale up write performance of <a href="http://couchdb.apache.org/">CouchDB</a>. However, there seemed to be a bug with <a href="http://jruby.org/">JRuby</a> that kills off the STOMP subscriber every 5 seconds. Digging a bit deeper into the STOMP source, I figured out a way to get around the bug by removing the timeout line. </p>
<p>ActiveMQ let me scale CouchDB writes from 10req/sec to 128req/sec. Huge performance win with very little effort. </p>
<p><a href="http://jira.codehaus.org/browse/JRUBY-4941">Ticket to the bug.</a></p>
<p><b>STOMP Library Monkey Patch:</b></p>
<div class="codesnip-container" >
<div class="ruby codesnip" style="font-family:monospace;"><span class="co1"># for stomp subscriber</span><br />
<span class="kw1">if</span> <span class="kw1">defined</span>?<span class="br0">&#40;</span>JRUBY_VERSION<span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">module</span> Stomp<br />
&nbsp; &nbsp; <span class="kw1">class</span> Connection<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">def</span> _receive<span class="br0">&#40;</span> read_socket <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">@read_semaphore</span>.<span class="me1">synchronize</span> <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;line = read_socket.<span class="kw3">gets</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw2">return</span> <span class="kw2">nil</span> <span class="kw1">if</span> line.<span class="kw2">nil</span>?</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1"># If the reading hangs for more than 5 seconds, abort the parsing process</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">#Timeout::timeout(5, Stomp::Error::PacketParsingTimeout) do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1"># Reads the beginning of the message until it runs into a empty line</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;message_header = <span class="st0">&#8221;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">begin</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;message_header <span class="sy0">+</span>= line<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">begin</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;line = read_socket.<span class="kw3">gets</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">rescue</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">p</span> read_socket<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">end</span> <span class="kw1">until</span> line =~ <span class="sy0">/</span>^\s?\n$<span class="sy0">/</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1"># Checks if it includes content_length header</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;content_length = message_header.<span class="me1">match</span> <span class="sy0">/</span>content<span class="sy0">-</span>length\s?:\s?<span class="br0">&#40;</span>\d<span class="sy0">+</span><span class="br0">&#41;</span>\s?\n<span class="sy0">/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;message_body = <span class="st0">&#8221;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1"># If it does, reads the specified amount of bytes</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;char = <span class="st0">&#8221;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">if</span> content_length<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;message_body = read_socket.<span class="me1">read</span> content_length<span class="br0">&#91;</span>1<span class="br0">&#93;</span>.<span class="me1">to_i</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw3">raise</span> <span class="re2">Stomp::Error::InvalidMessageLength</span> <span class="kw1">unless</span> parse_char<span class="br0">&#40;</span>read_socket.<span class="me1">getc</span><span class="br0">&#41;</span> == <span class="st0">&quot;<span class="es0">\0</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1"># Else reads, the rest of the message until the first \0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;message_body <span class="sy0">+</span>= char <span class="kw1">while</span> read_socket.<span class="me1">ready</span>? <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>char = parse_char<span class="br0">&#40;</span>read_socket.<span class="me1">getc</span><span class="br0">&#41;</span><span class="br0">&#41;</span> != <span class="st0">&quot;<span class="es0">\0</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">end</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1"># If the buffer isn&#8217;t empty, reads the next char and returns it to the buffer</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1"># unless it&#8217;s a \n</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">if</span> read_socket.<span class="me1">ready</span>?<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;last_char = read_socket.<span class="me1">getc</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;read_socket.<span class="me1">ungetc</span><span class="br0">&#40;</span>last_char<span class="br0">&#41;</span> <span class="kw1">if</span> parse_char<span class="br0">&#40;</span>last_char<span class="br0">&#41;</span> != <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">end</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1"># Adds the excluded \n and \0 and tries to create a new message with it</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Message.<span class="me1">new</span><span class="br0">&#40;</span>message_header <span class="sy0">+</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span> <span class="sy0">+</span> message_body <span class="sy0">+</span> <span class="st0">&quot;<span class="es0">\0</span>&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">#end</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; <span class="kw1">end</span><br />
<span class="kw1">end</span></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://letsgetdugg.com/2010/07/16/stomp-client-on-jruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A fix for the sound delay  with VoodooHDA and Final Cut Pro</title>
		<link>http://letsgetdugg.com/2010/07/01/a-fix-for-the-sound-delay-with-voodoohda-and-final-cut-pro/</link>
		<comments>http://letsgetdugg.com/2010/07/01/a-fix-for-the-sound-delay-with-voodoohda-and-final-cut-pro/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 03:01:52 +0000</pubDate>
		<dc:creator>victori</dc:creator>
				<category><![CDATA[main]]></category>
		<category><![CDATA[fix]]></category>

		<guid isPermaLink="false">http://letsgetdugg.com/?p=704</guid>
		<description><![CDATA[I spent the better part of the day trying to figure out why the Final Cut Pro audio was out of sync. The audio would be delayed by 3 seconds in playback. I thought it was some setting in Final Cut Pro that broke, but eventually came to the conclusion that it was the OS [...]]]></description>
			<content:encoded><![CDATA[<p>I spent the better part of the day trying to figure out why the Final Cut Pro audio was out of sync. The audio would be delayed by 3 seconds in playback. I thought it was some setting in Final Cut Pro that broke, but eventually came to the conclusion that it was the OS and not Final Cut Pro that was causing the audio delay. The specific cause was the <a href="http://code.google.com/p/voodoohda/">VoodooHDA</a> driver, even though it worked perfect in ordinary applications such as iTunes and Safari it had a delay issue with Final Cut Pro. The Fix? Install <a href="http://code.google.com/p/soundflower/">SoundFlowerBed</a> and configure your audio output settings in it. This somehow magically fixes the delay issue in the VoodooHDA driver. I thought I should post it here for &#8220;internet&#8221; record keeping.</p>
<p><img src="http://letsgetdugg.com/wp-content/uploads/2010/07/sf1.jpg" alt="sf1.jpg" border="0" width="430" height="412" /></p>
]]></content:encoded>
			<wfw:commentRss>http://letsgetdugg.com/2010/07/01/a-fix-for-the-sound-delay-with-voodoohda-and-final-cut-pro/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Clustering Wicket for fun and profit!</title>
		<link>http://letsgetdugg.com/2010/02/07/clustering-wicket-for-fun-and-profit/</link>
		<comments>http://letsgetdugg.com/2010/02/07/clustering-wicket-for-fun-and-profit/#comments</comments>
		<pubDate>Sun, 07 Feb 2010 17:55:09 +0000</pubDate>
		<dc:creator>victori</dc:creator>
				<category><![CDATA[administration]]></category>
		<category><![CDATA[main]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[clustering]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[wicket]]></category>

		<guid isPermaLink="false">http://letsgetdugg.com/?p=615</guid>
		<description><![CDATA[I hate expired sessions, death to all expired sessions. Traditionally a Java servlet container has a fixed session time, a flood of traffic can potentially cause JVM OOM errors if the session time is set too high. I wanted a smart session container that can hold onto sessions for as long as possible and expire [...]]]></description>
			<content:encoded><![CDATA[<p>I hate expired sessions, death to all expired sessions. Traditionally a Java servlet container has a fixed session time, a flood of traffic can potentially cause <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/OutOfMemoryError.html">JVM OOM errors</a> if the session time is set too high. I wanted a smart session container that can hold onto sessions for as long as possible and expire sessions only when it is absolutely necessary; A <a href="http://memcached.org/">Memcached</a> store would be perfect for this. </p>
<p>There for I recently open sourced the <a href="http://github.com/victori/jetty-session-cache">jetty-session-store</a> to solve this problem. With the jetty-session-store you can save your session state to Ehcache, <a href="http://memcached.org/">Memcached</a> or the database. State should not be bound to a single JVM, Viva Shared Session Stores! </p>
<p>So now that jetty-session-store is out in the wild you can technically cluster Wicket using just the <a href="http://wicket.sourceforge.net/apidocs/wicket/protocol/http/HttpSessionStore.html">HttpSessionStore</a>. However, it isn’t very efficient with the way Memcached allocates data in fixed sized cache buckets.</p>
<p>1. Wicket sessions under the HttpSessionStore can get quite large, well over 1Mb in size. A Wicket session not only stores the session state but also the previous serialized pages the user has visited. </p>
<p>2. Serializing and de-serializing a large data structure can get expensive. The HttpSessionStore retains an <a href="http://wicket.apache.org/docs/1.4/org/apache/wicket/AccessStackPageMap.html">AccessStackPageMap</a>, which is a list data structure consisting of multiple <a href="http://cwiki.apache.org/WICKET/page-maps.html">page map revisions</a>. </p>
<p>So instead of saving one large AccessStackPageMap, I wrote a <a href="http://wicket.apache.org/docs/wicket-1.3.2/wicket/apidocs/org/apache/wicket/protocol/http/SecondLevelCacheSessionStore.html">SecondLevelCacheSessionStore</a> that saves a page map revision per cache entry. This leads to much better cache utilization and a whole lot less serialization on the wire. Not to mention this avoids the whole 1Mb Memcached size limit.</p>
<p>Before you go willy nilly with clustering, read the <a href="http://cwiki.apache.org/WICKET/render-strategies.html">Wicket render strategies page</a>. <b>Wicket requires session affinity for buffered responses with the default rendering strategy.</b></p>
<h3>Clustering Wicket has never been easier.</h3>
<p>Here is an example on how to offload page maps to a hybrid EhCache/Memcached cache. Memcached for long term shared storage while EhCache for short-lived fast cache look ups. </p>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;"><span class="kw1">public</span> <span class="kw1">class</span> WebApp <span class="kw1">extends</span> WebApplication <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @Override<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> ISessionStore newSessionStore<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// localhost:11211 &#8212; memcached server</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// &quot;fabpagestore&quot; &#8212; unique appender to avoid key clashes.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// 300 &#8212; 5 minute TTL for local ehcache.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw1">new</span> SecondLevelCacheSessionStore<span class="br0">&#40;</span><span class="kw1">this</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">new</span> CachePageStore<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aarrays+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Arrays</span></a>.<span class="me1">asList</span><span class="br0">&#40;</span><span class="st0">&quot;localhost:11211&quot;</span><span class="br0">&#41;</span>,<span class="st0">&quot;fabpagestore&quot;</span>,300<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>Here is an example on how to offload page maps to the database. </p>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;"><span class="kw1">public</span> <span class="kw1">class</span> WebApp <span class="kw1">extends</span> WebApplication <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @Override<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> ISessionStore newSessionStore<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// &quot;fabpagestore&quot; &#8212; unique appender to avoid key clashes.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw1">new</span> SecondLevelCacheSessionStore<span class="br0">&#40;</span><span class="kw1">this</span>,<span class="kw1">new</span> CachePageStore<span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">new</span> DBCache<span class="br0">&#40;</span><span class="st0">&quot;jdbc:mysql://foo/mydb&quot;</span>, <span class="st0">&quot;myname&quot;</span>, <span class="st0">&quot;mypass&quot;</span>, <span class="st0">&quot;com.driver.Name&quot;</span>, <span class="st0">&quot;fabpagestore&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>Here is my CachePageStore;</p>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;"><span class="kw1">package</span> <span class="co2">com.base.pagestore</span><span class="sy0">;</span></p>
<p><span class="kw1">import</span> <span class="co2">com.base.cache.AsyncMemcache</span><span class="sy0">;</span><br />
<span class="kw1">import</span> <span class="co2">com.base.cache.ICache</span><span class="sy0">;</span><br />
<span class="kw1">import</span> <span class="co2">org.apache.wicket.Page</span><span class="sy0">;</span><br />
<span class="kw1">import</span> <span class="co2">org.apache.wicket.protocol.http.SecondLevelCacheSessionStore.IClusteredPageStore</span><span class="sy0">;</span><br />
<span class="kw1">import</span> <span class="co2">org.apache.wicket.protocol.http.pagestore.AbstractPageStore</span><span class="sy0">;</span><br />
<span class="kw1">import</span> <span class="co2">org.slf4j.Logger</span><span class="sy0">;</span><br />
<span class="kw1">import</span> <span class="co2">org.slf4j.LoggerFactory</span><span class="sy0">;</span></p>
<p><span class="kw1">import</span> <span class="co2">java.util.List</span><span class="sy0">;</span></p>
<p><span class="kw1">public</span> <span class="kw1">class</span> CachePageStore <span class="kw1">extends</span> AbstractPageStore <span class="kw1">implements</span> IClusteredPageStore <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">private</span> ICache cache<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">private</span> Logger logger <span class="sy0">=</span> LoggerFactory.<span class="me1">getLogger</span><span class="br0">&#40;</span>CachePageStore.<span class="kw1">class</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">public</span> CachePageStore<span class="br0">&#40;</span><span class="kw1">final</span> List<span class="sy0">&lt;</span>String<span class="sy0">&gt;</span> servers, <span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> poolName, <span class="kw1">final</span> <span class="kw4">int</span> ttl<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="br0">&#40;</span>servers, poolName, <span class="kw2">true</span>, ttl<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">public</span> CachePageStore<span class="br0">&#40;</span><span class="kw1">final</span> List<span class="sy0">&lt;</span>String<span class="sy0">&gt;</span> servers, <span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> poolName, <span class="kw4">boolean</span> async, <span class="kw1">final</span> <span class="kw4">int</span> ttl<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="br0">&#40;</span><span class="kw1">new</span> AsyncMemcache<span class="br0">&#40;</span>servers, poolName, async, ttl<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">public</span> CachePageStore<span class="br0">&#40;</span><span class="kw1">final</span> ICache cache<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span>.<span class="me1">cache</span> <span class="sy0">=</span> cache<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="co1">// If pageVersion -1 must return highest page version.</span><br />
&nbsp; &nbsp; <span class="kw1">protected</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getKey<span class="br0">&#40;</span><span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessId, <span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> pageMapName, <span class="kw1">final</span> <span class="kw4">int</span> pageId, <span class="kw1">final</span> <span class="kw4">int</span> pageVersion<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> pageVer <span class="sy0">=</span> <span class="br0">&#40;</span>pageVersion <span class="sy0">==</span> <span class="sy0">-</span>1<span class="br0">&#41;</span> <span class="sy0">?</span> 0 <span class="sy0">:</span> pageVersion<span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>pageVersion <span class="sy0">==</span> <span class="sy0">-</span>1<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> meta <span class="sy0">=</span> getMeta<span class="br0">&#40;</span>sessId, pageMapName, pageId<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pageVer <span class="sy0">=</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Ainteger+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Integer</span></a>.<span class="me1">valueOf</span><span class="br0">&#40;</span>meta<span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> sessId <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> pageMapName <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> pageId <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> pageVer<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="co1">// If pageVersion -1 must return highest page version.</span><br />
&nbsp; &nbsp; <span class="co1">// If ajaxVersion -1 must return highest version.</span><br />
&nbsp; &nbsp; <span class="kw1">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getKey<span class="br0">&#40;</span><span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessId, <span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> pageMapName, <span class="kw1">final</span> <span class="kw4">int</span> pageId, <span class="kw1">final</span> <span class="kw4">int</span> pageVersion, <span class="kw1">final</span> <span class="kw4">int</span> ajaxVersion<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Default it to 0 initially</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> ajaxVer <span class="sy0">=</span> <span class="br0">&#40;</span>ajaxVersion <span class="sy0">==</span> <span class="sy0">-</span>1<span class="br0">&#41;</span> <span class="sy0">?</span> 0 <span class="sy0">:</span> ajaxVersion<span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> pageVer <span class="sy0">=</span> <span class="br0">&#40;</span>pageVersion <span class="sy0">==</span> <span class="sy0">-</span>1<span class="br0">&#41;</span> <span class="sy0">?</span> 0 <span class="sy0">:</span> pageVersion<span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>pageVersion <span class="sy0">==</span> <span class="sy0">-</span>1 <span class="sy0">||</span> ajaxVersion <span class="sy0">==</span> <span class="sy0">-</span>1<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> meta <span class="sy0">=</span> getMeta<span class="br0">&#40;</span>sessId, pageMapName, pageId<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>pageVersion <span class="sy0">==</span> <span class="sy0">-</span>1<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pageVer <span class="sy0">=</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Ainteger+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Integer</span></a>.<span class="me1">valueOf</span><span class="br0">&#40;</span>meta<span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>ajaxVersion <span class="sy0">==</span> <span class="sy0">-</span>1<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ajaxVer <span class="sy0">=</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Ainteger+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Integer</span></a>.<span class="me1">valueOf</span><span class="br0">&#40;</span>meta<span class="br0">&#91;</span>1<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> sessId <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> pageMapName <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> pageId <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> pageVer <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> ajaxVer<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">protected</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> storeKey<span class="br0">&#40;</span><span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessionId, <span class="kw1">final</span> Page page<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> sessionId <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> page.<span class="me1">getPageMapName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> page.<span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> page.<span class="me1">getCurrentVersionNumber</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> page.<span class="me1">getAjaxVersionNumber</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">protected</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getBaseKey<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessionId, Page page<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> sessionId <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> page.<span class="me1">getPageMapName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> page.<span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">protected</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getMetaKey<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessionId, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> pageMap, <span class="kw4">int</span> id<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> getBaseKey<span class="br0">&#40;</span>sessionId,pageMap,id<span class="br0">&#41;</span><span class="sy0">+</span><span class="st0">&quot;_meta&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">protected</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getMetaKey<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessionId, Page page<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> getBaseKey<span class="br0">&#40;</span>sessionId,page<span class="br0">&#41;</span><span class="sy0">+</span><span class="st0">&quot;_meta&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">protected</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getBaseKey<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessionId, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> pageMap, <span class="kw4">int</span> id<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>id <span class="sy0">==</span> <span class="sy0">-</span>1<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> sessionId <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> pageMap<span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> sessionId <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> pageMap <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span> <span class="sy0">+</span> id<span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">boolean</span> containsPage<span class="br0">&#40;</span><span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessionId, <span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> pageMapName, <span class="kw1">final</span> <span class="kw4">int</span> pageId, <span class="kw1">final</span> <span class="kw4">int</span> pageVersion<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> key <span class="sy0">=</span> getKey<span class="br0">&#40;</span>sessionId, pageMapName, pageId, pageVersion, <span class="sy0">-</span>1<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>logger.<span class="me1">isDebugEnabled</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logger.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&quot;CheckExists: &quot;</span> <span class="sy0">+</span> key<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> cache.<span class="me1">keyExists</span><span class="br0">&#40;</span>key<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> destroy<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">public</span> <span class="sy0">&lt;</span>T<span class="sy0">&gt;</span> Page getPage<span class="br0">&#40;</span><span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessionId, <span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> pagemap, <span class="kw1">final</span> <span class="kw4">int</span> id, <span class="kw1">final</span> <span class="kw4">int</span> versionNumber, <span class="kw1">final</span> <span class="kw4">int</span> ajaxVersionNumber<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> key <span class="sy0">=</span> getKey<span class="br0">&#40;</span>sessionId, pagemap, id, versionNumber, ajaxVersionNumber<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>logger.<span class="me1">isDebugEnabled</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logger.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&quot;GetPage: &quot;</span> <span class="sy0">+</span> key<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>Page<span class="br0">&#41;</span> cache.<span class="me1">get</span><span class="br0">&#40;</span>key<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> pageAccessed<span class="br0">&#40;</span><span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessionId, <span class="kw1">final</span> Page page<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="co1">// If ID == -1 remove the entire pagemap; getBaseKey() takes care of this.</span><br />
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> removePage<span class="br0">&#40;</span><span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessionId, <span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> pagemap, <span class="kw1">final</span> <span class="kw4">int</span> id<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> key <span class="sy0">=</span> getBaseKey<span class="br0">&#40;</span>sessionId, pagemap, id<span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>logger.<span class="me1">isDebugEnabled</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logger.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&quot;RemovePage: &quot;</span> <span class="sy0">+</span> key<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; cache.<span class="me1">remove</span><span class="br0">&#40;</span>getMetaKey<span class="br0">&#40;</span>sessionId, pagemap, id<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> k <span class="sy0">:</span> cache.<span class="me1">getKeys</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>k.<span class="me1">startsWith</span><span class="br0">&#40;</span>key<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cache.<span class="me1">remove</span><span class="br0">&#40;</span>k<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">protected</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> getMeta<span class="br0">&#40;</span><span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessionId, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> pageMap, <span class="kw4">int</span> pageId<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> metaKey <span class="sy0">=</span> getMetaKey<span class="br0">&#40;</span>sessionId,pageMap,pageId<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aobject+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Object</span></a> ret <span class="sy0">=</span> cache.<span class="me1">get</span><span class="br0">&#40;</span>metaKey<span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>logger.<span class="me1">isDebugEnabled</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logger.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&quot;GetMeta: &quot;</span> <span class="sy0">+</span> metaKey<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>ret <span class="sy0">==</span> <span class="kw2">null</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw1">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="br0">&#123;</span><span class="st0">&quot;0&quot;</span>,<span class="st0">&quot;0&quot;</span><span class="br0">&#125;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a>.<span class="me1">valueOf</span><span class="br0">&#40;</span>ret<span class="br0">&#41;</span>.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&quot;:&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">protected</span> <span class="kw4">void</span> storeMeta<span class="br0">&#40;</span><span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessionId, <span class="kw1">final</span> Page page<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> metaKey <span class="sy0">=</span> getMetaKey<span class="br0">&#40;</span>sessionId, page<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aobject+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Object</span></a> ret <span class="sy0">=</span> cache.<span class="me1">get</span><span class="br0">&#40;</span>metaKey<span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>logger.<span class="me1">isDebugEnabled</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logger.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&quot;StoreMeta: &quot;</span> <span class="sy0">+</span> metaKey<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>ret <span class="sy0">==</span> <span class="kw2">null</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cache.<span class="me1">put</span><span class="br0">&#40;</span>metaKey,page.<span class="me1">getCurrentVersionNumber</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">+</span><span class="st0">&quot;:&quot;</span><span class="sy0">+</span>page.<span class="me1">getAjaxVersionNumber</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> vals <span class="sy0">=</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a>.<span class="me1">valueOf</span><span class="br0">&#40;</span>ret<span class="br0">&#41;</span>.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&quot;:&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> currPage <span class="sy0">=</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Ainteger+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Integer</span></a>.<span class="me1">valueOf</span><span class="br0">&#40;</span>vals<span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> currAjax <span class="sy0">=</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Ainteger+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Integer</span></a>.<span class="me1">valueOf</span><span class="br0">&#40;</span>vals<span class="br0">&#91;</span>1<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>page.<span class="me1">getCurrentVersionNumber</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">&gt;</span> currPage<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; currPage <span class="sy0">=</span> page.<span class="me1">getCurrentVersionNumber</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>page.<span class="me1">getAjaxVersionNumber</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">&gt;</span> currAjax<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; currAjax <span class="sy0">=</span> page.<span class="me1">getAjaxVersionNumber</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cache.<span class="me1">put</span><span class="br0">&#40;</span>metaKey,currPage<span class="sy0">+</span><span class="st0">&quot;:&quot;</span><span class="sy0">+</span>currAjax<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> storePage<span class="br0">&#40;</span><span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessionId, <span class="kw1">final</span> Page page<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sKey <span class="sy0">=</span> storeKey<span class="br0">&#40;</span>sessionId, page<span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>logger.<span class="me1">isDebugEnabled</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logger.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&quot;StorePage: &quot;</span> <span class="sy0">+</span> sKey<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; cache.<span class="me1">put</span><span class="br0">&#40;</span>sKey, page<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; storeMeta<span class="br0">&#40;</span>sessionId,page<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> unbind<span class="br0">&#40;</span><span class="kw1">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sessionId<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>logger.<span class="me1">isDebugEnabled</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logger.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&quot;Unbind: &quot;</span> <span class="sy0">+</span> sessionId<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> key <span class="sy0">:</span> cache.<span class="me1">getKeys</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>key.<span class="me1">startsWith</span><span class="br0">&#40;</span>sessionId<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cache.<span class="me1">remove</span><span class="br0">&#40;</span>key<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p><span class="br0">&#125;</span></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://letsgetdugg.com/2010/02/07/clustering-wicket-for-fun-and-profit/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cleanly Designed Wicket Sites That Scale</title>
		<link>http://letsgetdugg.com/2010/02/02/clean-looking-wicket-sites-that-can-scale/</link>
		<comments>http://letsgetdugg.com/2010/02/02/clean-looking-wicket-sites-that-can-scale/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 03:06:18 +0000</pubDate>
		<dc:creator>victori</dc:creator>
				<category><![CDATA[main]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[wicket]]></category>

		<guid isPermaLink="false">http://letsgetdugg.com/?p=591</guid>
		<description><![CDATA[I’ll start this post off with a quote from IRC ivaynberg: you cant build good looking sites with wicket victori: lies ivaynberg: or public-facing sites I have to admit that Wicket appeals more to the “backend” programmer than to the front-end design conscious developer. For every good-looking Wicket site out there, there are ten abysmal [...]]]></description>
			<content:encoded><![CDATA[<p>I’ll start this post off with a quote from IRC</p>
<pre>
<div class="codesnip-container" >ivaynberg: you cant build good looking sites with wicket
victori: lies
ivaynberg: or public-facing sites</div>
</pre>
<p>I have to admit that <a href="http://wicket.apache.org/">Wicket</a> appeals more to the “backend” programmer than to the front-end design conscious developer. For every good-looking Wicket site out there, there are ten abysmal looking Wicket sites. Just look at the <a href="http://cwiki.apache.org/WICKET/websites-based-on-wicket.html">Wicket Wiki</a>, it is littered with some dreadfully designed sites (Sorry Guys, this isn’t personal). You can tell right off the bat that the developers behind the sites care more about OO and clean code rather than clean design.  Well to be frank, I don’t even know if the code behind the listed sites is even elegant. However, the fact that the sites are written on Wicket, tells me that the developers care about things such as <a href="http://en.wikipedia.org/wiki/Separation_of_concerns">separation of concerns</a> and <a href="http://en.wikipedia.org/wiki/Object-oriented_programming">object oriented programming</a>.</p>
<p>So to combat against the whole mentality that Wicket can’t scale and any site done in Wicket must look atrocious. I have decided to compile a list of some awesomely kick ass public-facing / good-looking Wicket sites. </p>
<p>If you don’t see your site and you feel that it should have made the list, feel free to leave a comment with your site’s URL. </p>
<h2>High Traffic Wicket Sites</h2>
<h3>adscale.de</h3>
<p>This site has an <a href="http://www.alexa.com/siteinfo/adscale.de">Alexa 1,700 traffic rank</a> and runs on a single Tomcat servlet container. No proxy caches, no fancy clustering just Tomcat.</p>
<p><a href="http://adscale.de/"><br />
<img width="480" src="http://letsgetdugg.com/wp-content/uploads/2010/07/adscalede.jpg" alt="" /><br />
</a></p>
<h3>vegas.com</h3>
<p>Next time someone states that no public facing sites are ever written in wicket, point them to vegas.com. </p>
<p><a href="http://vegas.com/"><br />
<img width="480" src="http://letsgetdugg.com/wp-content/uploads/2010/07/vegassite.jpg" alt="" /><br />
</a></p>
<p><br/><br/></p>
<h2>Clean Wicket Sites</h2>
<h3>kontain.com</h3>
<p>The design behind this site is quite good and sets the design bar in my book.</p>
<p><a href="http://kontain.com/"><br />
<img width="480" src="http://letsgetdugg.com/wp-content/uploads/2010/07/kontain1.jpg" alt="" /><br />
</a></p>
<h3>meetmoi.com</h3>
<p>Ah, I remember when the developer behind meetmoi dropped by #wicket and stated that he is officially working on it full time with a million dollars in venture capital seed money. </p>
<p><a href="http://meetmoi.com/"><br />
<img width="480" src="http://letsgetdugg.com/wp-content/uploads/2010/07/meetmoi1.jpg" alt="" /><br />
</a></p>
<h3>songtexte.com</h3>
<p>Don&#8217;t know much about this site, aside that it looks clean and the author did the original <a href="http://bside.com/">b-side wicket site</a> that got replaced with wordpress. </p>
<p><a href="http://songtexte.com/"><br />
<img width="480" src="http://letsgetdugg.com/wp-content/uploads/2010/07/songtexte.jpg" alt="" /><br />
</a></p>
<h3>memolio.com</h3>
<p><a href="http://memolio.com/"><br />
<img width="480" src="http://letsgetdugg.com/wp-content/uploads/2010/07/memolio.jpg" alt="" /><br />
</a></p>
<h3>fabulously40.com</h3>
<p>Disclaimer: this is the site I developed and I think it looks good <img src='http://letsgetdugg.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><a href="http://fabulously40.com/"><br />
<img width="480" src="http://letsgetdugg.com/wp-content/uploads/2010/07/fab40site.jpg" alt="fab40site.jpg" alt="" /><br />
</a></p>
<h3>winerevolution.com</h3>
<p><a href="http://Winerevolution.com/"><br />
<img width="480" src="http://letsgetdugg.com/wp-content/uploads/2010/07/winerevolution.jpg" alt="" /><br />
</a></p>
<h3>islamicdesignhouse.com</h3>
<p><a href="http://islamicdesignhouse.com/"><br />
<img width="480" src="http://letsgetdugg.com/wp-content/uploads/2010/07/islamicdesignhouse.jpg" alt="" /><br />
</a></p>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://letsgetdugg.com/2010/02/02/clean-looking-wicket-sites-that-can-scale/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Speedy PostgreSQL Parallel Compression Dumps</title>
		<link>http://letsgetdugg.com/2010/01/18/speedy-postgresql-parallel-compression-dumps/</link>
		<comments>http://letsgetdugg.com/2010/01/18/speedy-postgresql-parallel-compression-dumps/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 20:31:30 +0000</pubDate>
		<dc:creator>victori</dc:creator>
				<category><![CDATA[administration]]></category>
		<category><![CDATA[main]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[databases]]></category>
		<category><![CDATA[postgresql]]></category>

		<guid isPermaLink="false">http://letsgetdugg.com/?p=557</guid>
		<description><![CDATA[I used to backup our database using the following statement; pg_dump -h fab2 -Fc -Z9 somedb > somedb.db Once our dataset grew into the gigabytes, it took a very long time to do database dumps. Today, I stumbled upon yet another awesome blog post done by Ted Dzibua mentioning two useful parallel compression utilities. So [...]]]></description>
			<content:encoded><![CDATA[<p>I used to backup our database using the following statement;</p>
<div class="codesnip-container" >pg_dump -h fab2 -Fc -Z9 somedb > somedb.db</div>
<p>Once our dataset grew into the gigabytes, it took a very long time to do database dumps. Today, I stumbled upon yet another awesome blog post done by <a href="http://teddziuba.com/2010/01/options-for-parallel-compressi.html">Ted Dzibua</a> mentioning two useful parallel compression utilities. So why not try parallel compression with <a href="http://www.postgresql.org/">PostgreSQL</a> dumps?</p>
<p><a href="http://compression.ca/pbzip2/">pbzip2</a> &#8211; Parallel BZIP2: Parallel implementation of BZIP2. BZIP2 is well known for being balls slow, so speed it up using multiple CPUs.</p>
<p><a href="http://www.zlib.net/pigz/">pigz</a> &#8211; Parallel GZIP: Parallel implementation of GZIP written by Mark Adler.</p>
<p>Time to try this out with our PostgreSQL dump, here are the result times.</p>
<p>• This was done on a quad core xeon 2.66ghz machine. </p>
<div class="codesnip-container" ># time pg_dump -U secret -h fab2 somedb | pigz -c > somedb.gz</p>
<p>real	2m7.332s<br />
user	1m16.414s<br />
sys	0m8.233s</p>
<p># time pg_dump -U secret -h fab2 somedb | pbzip2 -c > somedb.bz2</p>
<p>real	4m14.253s<br />
user	10m35.879s<br />
sys	0m10.904s</p></div>
<p>The original database was 1.6gigs. The compressed files came out to&#8230;.</p>
<div class="codesnip-container" ># du -hs somedb.*<br />
 147M	somedb.bz2<br />
 194M	somedb.gz</div>
<p>And just to make this post complete, to pipe the SQL dump back into PostgreSQL </p>
<div class="codesnip-container" ># dropdb somedb<br />
# createdb somedb<br />
# gzip -d -c somedb.gz | psql somedb</div>
]]></content:encoded>
			<wfw:commentRss>http://letsgetdugg.com/2010/01/18/speedy-postgresql-parallel-compression-dumps/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Relax, Satan is on your side.</title>
		<link>http://letsgetdugg.com/2010/01/05/relax-satan-is-on-your-side/</link>
		<comments>http://letsgetdugg.com/2010/01/05/relax-satan-is-on-your-side/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 22:17:20 +0000</pubDate>
		<dc:creator>victori</dc:creator>
				<category><![CDATA[administration]]></category>
		<category><![CDATA[main]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[satan]]></category>

		<guid isPermaLink="false">http://letsgetdugg.com/?p=540</guid>
		<description><![CDATA[I just pushed up a new version of Satan to GitHub. For the uniformed uninformed Satan is my process reaper for run away unix processes. Satan was designed to work with Solaris&#8217; SMF self-healing properties. Basically, Satan kills while SMF revives. The new version that was pushed up contains HTTP health checks, so Satan now [...]]]></description>
			<content:encoded><![CDATA[<p>I just pushed up a new version of <a href="http://github.com/victori/satan">Satan to GitHub</a>. For the <s>uniformed</s> uninformed Satan is my process reaper for run away unix processes. Satan was designed to work with Solaris&#8217; <a href="http://www.sun.com/bigadmin/features/articles/smf_example.jsp">SMF self-healing properties</a>. Basically, Satan kills while SMF revives. The new version that was pushed up contains HTTP health checks, so Satan now has the ability to kill processes that are not responding back with a HTTP/200 response code. </p>
<p>The motivation behind HTTP health checks was because once a month or so at <a href="http://fabulously40.com/">Fabulously40</a> our <a href="http://activemq.apache.org/">ActiveMQ</a> would break down while still accepting connections, the only way to figure out if it was <em>zombified</em> was to check the HTTP administrator interface. If the ActiveMQ instance was actually knelled over, the administrator interface would come back with a HTTP/500 response code, hence the birth of HTTP health checks. </p>
<p>Here is our Satan configuration file that we use at Fabulously40. </p>
<p>The &#8220;args&#8221; property might be a bit confusing, it is a snippet of text that Satan looks for in the arguments passed to your application to identify the running process. So for example, if you start your ActiveMQ instance with the following arguments; &#8220;java -jar activemq.jar -Dactivemq=8161 -XXXXX&#8221; Placing &#8220;8161&#8243; in args property would be a good unique identifier for Satan to pick up on.</p>
<pre>
<div class="codesnip-container" >Satan.watch do |s|
  s.name = "jvm instances"                # name of job
  s.user = "webservd"                     # under what user
  s.group = "webservd"                    # under what group
  s.deamon = "java"                       # deamon binary name to grep for
  s.args = nil                            # globally look for specific arguments, optional
  s.debug = true                          # if to write out debug information
  s.safe_mode = false                     # If in safe mode, satan will not kill ;-(
  s.interval = 10.seconds                 # interval to run at to collect statistics
  s.sleep_after_kill = 1.minute           # sleep after killing, satan is tired!
  s.contact = "victori@fabulously40.com"  # admin contact, optional if you want email alerts

  s.kill_if do |process|
    process.condition(:cpu) do |cpu|      # on cpu condition
      cpu.name  = "50% CPU limit"         # name for job
      cpu.args  = "jetty"                 # make sure this is a jetty process, optional
      cpu.above = 48.percent              # if above certain percentage
      cpu.times = 5                       # how many times we can hit this condition before killing
    end

    process.condition(:memory) do |memory|  # on memory condition
      memory.name  = "850MB limit"          # name for job
      memory.args  = "jetty"                # make sure this is a jetty process, optional
      memory.above = 850.megabytes          # limit for memory use
      memory.times = 5                      # how many times we can hit this condition before killing
    end

    # ActiveMQ tends to die on us under heavy load so we need the power of satan!
    process.condition(:http) do |http|                        # on http condition
      http.name   = "HTTP ActiveMQ Check"                     # name for job
      http.args   = "8161"                                    # look for specific app arguments
                                                              # to associate app to URI
      http.uri    = "http://localhost:8161/admin/queues.jsp"  # the URI
      http.times  = 5                                         # how many times before kill
    end
  end
end</div>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://letsgetdugg.com/2010/01/05/relax-satan-is-on-your-side/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Why deadlines go to hell</title>
		<link>http://letsgetdugg.com/2009/12/16/why-deadlines-go-to-hell/</link>
		<comments>http://letsgetdugg.com/2009/12/16/why-deadlines-go-to-hell/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 21:55:27 +0000</pubDate>
		<dc:creator>victori</dc:creator>
				<category><![CDATA[administration]]></category>
		<category><![CDATA[main]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[productivity]]></category>

		<guid isPermaLink="false">http://letsgetdugg.com/?p=527</guid>
		<description><![CDATA[Ted Dziuba beautifully articulated why deadlines go to crap and seemingly straight forward tasks go out the window. You sir have done a public service for us all, thank you. What I hate is fording endless rivers of horseshit that are in the way of seemingly simple tasks. And I hate it even more when [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://teddziuba.com/2009/12/how-i-spot-valuable-engineers.html">Ted Dziuba</a> beautifully articulated why deadlines go to crap and seemingly straight forward tasks go out the window. You sir have done a public service for us all, thank you.</p>
<pre>
<div class="codesnip-container" >What I hate is fording endless rivers of horseshit that are in the way
of seemingly simple tasks. And I hate it even more when I have to explain
to a non-programmer what I am doing, "building LXML against a different
version of libiconv because I think it might be the source of a crash". 

"But all I asked you to do was parse some documents."

Good times.</div>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://letsgetdugg.com/2009/12/16/why-deadlines-go-to-hell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby ThreadSafe JSMin Library</title>
		<link>http://letsgetdugg.com/2009/12/13/ruby-threadsafe-jsmin-library/</link>
		<comments>http://letsgetdugg.com/2009/12/13/ruby-threadsafe-jsmin-library/#comments</comments>
		<pubDate>Mon, 14 Dec 2009 05:19:47 +0000</pubDate>
		<dc:creator>victori</dc:creator>
				<category><![CDATA[main]]></category>
		<category><![CDATA[jruby]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://letsgetdugg.com/?p=517</guid>
		<description><![CDATA[I needed a thread-safe JSMin library for compressing javascripts on the fly on UploadBooth, so I took an existing ruby implementation and made it thread safe. I don&#8217;t think there was license defined when I got it, so I am re-releasing it as-is. require &#8216;monitor&#8217; class JSMin &#160; EOF = -1 &#160; include MonitorMixin &#160; [...]]]></description>
			<content:encoded><![CDATA[<p>I needed a thread-safe JSMin library for compressing javascripts on the fly on <a href="http://uploadbooth.com/">UploadBooth</a>, so I took an existing ruby implementation and made it thread safe. I don&#8217;t think there was license defined when I got it, so I am re-releasing it as-is.</p>
<div class="codesnip-container" >
<div class="ruby codesnip" style="font-family:monospace;"><span class="kw3">require</span> <span class="st0">&#8216;monitor&#8217;</span></p>
<p><span class="kw1">class</span> JSMin<br />
&nbsp; EOF = <span class="sy0">-</span>1<br />
&nbsp; <span class="kw1">include</span> MonitorMixin</p>
<p>&nbsp; <span class="co1"># jsmin &#8212; Copy the input to the output, deleting the characters which are</span><br />
&nbsp; <span class="co1"># insignificant to JavaScript. Comments will be removed. Tabs will be</span><br />
&nbsp; <span class="co1"># replaced with spaces. Carriage returns will be replaced with linefeeds.</span><br />
&nbsp; <span class="co1"># Most spaces and linefeeds will be removed.</span><br />
&nbsp; <span class="co1"># thread safe</span><br />
&nbsp; <span class="kw1">def</span> minimize<span class="br0">&#40;</span>jstext<span class="br0">&#41;</span><br />
&nbsp; &nbsp; synchronize <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; <span class="re1">@theA</span> = <span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span class="re1">@theB</span> = <span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span class="re1">@current</span> = 0<br />
&nbsp; &nbsp; &nbsp; <span class="re1">@output</span> = <span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; &nbsp; <span class="re1">@text</span> = jstext<br />
&nbsp; &nbsp; &nbsp; <span class="re1">@theA</span> = <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; action<span class="br0">&#40;</span>3<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>@theA != <span class="re2">JSMin::EOF</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="re1">@theA</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">when</span> <span class="st0">&quot; &quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>isAlphanum<span class="br0">&#40;</span>@theB<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action<span class="br0">&#40;</span>1<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action<span class="br0">&#40;</span>2<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">when</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="br0">&#40;</span>@theB<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">when</span> <span class="st0">&quot;{&quot;</span>,<span class="st0">&quot;[&quot;</span>,<span class="st0">&quot;(&quot;</span>,<span class="st0">&quot;+&quot;</span>,<span class="st0">&quot;-&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action<span class="br0">&#40;</span>1<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">when</span> <span class="st0">&quot; &quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action<span class="br0">&#40;</span>3<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>isAlphanum<span class="br0">&#40;</span>@theB<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action<span class="br0">&#40;</span>1<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action<span class="br0">&#40;</span>2<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="br0">&#40;</span>@theB<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">when</span> <span class="st0">&quot; &quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>isAlphanum<span class="br0">&#40;</span>@theA<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action<span class="br0">&#40;</span>1<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action<span class="br0">&#40;</span>3<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">when</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="br0">&#40;</span>@theA<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">when</span> <span class="st0">&quot;}&quot;</span>,<span class="st0">&quot;]&quot;</span>,<span class="st0">&quot;)&quot;</span>,<span class="st0">&quot;+&quot;</span>,<span class="st0">&quot;-&quot;</span>,<span class="st0">&quot;<span class="es0">\&quot;</span>&quot;</span>,<span class="st0">&quot;<span class="es0">\\</span>&quot;</span>, <span class="st0">&quot;&#8217;&quot;</span>, <span class="st0">&#8216;&quot;&#8217;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action<span class="br0">&#40;</span>1<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>isAlphanum<span class="br0">&#40;</span>@theA<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action<span class="br0">&#40;</span>1<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action<span class="br0">&#40;</span>3<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action<span class="br0">&#40;</span>1<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; <span class="re1">@output</span><br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; <span class="kw1">end</span><br />
&nbsp; <br />
&nbsp; private<br />
&nbsp; <span class="co1"># isAlphanum &#8212; return true if the character is a letter, digit, underscore,</span><br />
&nbsp; <span class="co1"># dollar sign, or non-ASCII character</span><br />
&nbsp; <span class="kw1">def</span> isAlphanum<span class="br0">&#40;</span>c<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp;<span class="kw2">return</span> <span class="kw2">false</span> <span class="kw1">if</span> !c <span class="sy0">||</span> c == <span class="re2">JSMin::EOF</span><br />
&nbsp; &nbsp; &nbsp;<span class="kw2">return</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>c <span class="sy0">&gt;</span>= <span class="st0">&#8216;a&#8217;</span> <span class="sy0">&amp;&amp;</span> c <span class="sy0">&lt;</span>= <span class="st0">&#8216;z&#8217;</span><span class="br0">&#41;</span> <span class="sy0">||</span> <span class="br0">&#40;</span>c <span class="sy0">&gt;</span>= <span class="st0">&#8217;0&#8242;</span> <span class="sy0">&amp;&amp;</span> c <span class="sy0">&lt;</span>= <span class="st0">&#8217;9&#8242;</span><span class="br0">&#41;</span> <span class="sy0">||</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#40;</span>c <span class="sy0">&gt;</span>= <span class="st0">&#8216;A&#8217;</span> <span class="sy0">&amp;&amp;</span> c <span class="sy0">&lt;</span>= <span class="st0">&#8216;Z&#8217;</span><span class="br0">&#41;</span> <span class="sy0">||</span> c == <span class="st0">&#8216;_&#8217;</span> <span class="sy0">||</span> c == <span class="st0">&#8216;$&#8217;</span> <span class="sy0">||</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;c == <span class="st0">&#8216;<span class="es0">\&#8217;</span> || c[0] &gt; 126)<br />
&nbsp; end</p>
<p>&nbsp; # get &#8212; return the next character from stdin. Watch out for lookahead. If<br />
&nbsp; # the character is a control character, translate it to a space or linefeed.<br />
&nbsp; # thread safe<br />
&nbsp; def get<br />
&nbsp; &nbsp; return JSMin::EOF if @current&gt;(@text.length-1)<br />
&nbsp; &nbsp; c = @text[@current]<br />
&nbsp; &nbsp; @current += 1<br />
&nbsp; &nbsp; c = c.chr<br />
&nbsp; &nbsp; return c if (c &gt;= &quot; &quot; || c == &quot;<span class="es0">\n</span>&quot; || c.unpack(&quot;c&quot;) == JSMin::EOF)<br />
&nbsp; &nbsp; return &quot;<span class="es0">\n</span>&quot; if (c == &quot;<span class="es0">\r</span>&quot;)<br />
&nbsp; &nbsp; return &quot; &quot;<br />
&nbsp; end</p>
<p>&nbsp; # Get the next character without getting it.<br />
&nbsp; def peek<br />
&nbsp; &nbsp; &nbsp; lookaheadChar = @text[@current]<br />
&nbsp; &nbsp; &nbsp; return lookaheadChar.chr<br />
&nbsp; end</p>
<p>&nbsp; # mynext &#8212; get the next character, excluding comments.<br />
&nbsp; # peek() is used to see if a &#8216;</span><span class="sy0">/</span><span class="st0">&#8216; is followed by a &#8216;</span><span class="sy0">/</span><span class="st0">&#8216; or &#8216;</span><span class="sy0">*</span><span class="st0">&#8216;.<br />
&nbsp; def mynext<br />
&nbsp; &nbsp; &nbsp; c = get<br />
&nbsp; &nbsp; &nbsp; if (c == &quot;/&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(peek == &quot;/&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while(true)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c = get<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (c &lt;= &quot;<span class="es0">\n</span>&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return c<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(peek == &quot;*&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while(true)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case get<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; when &quot;*&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (peek == &quot;/&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return &quot; &quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; when JSMin::EOF<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise &quot;Unterminated comment&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; return c<br />
&nbsp; end</p>
<p>&nbsp; # action &#8212; do something! What you do is determined by the argument: 1<br />
&nbsp; # Output A. Copy B to A. Get the next B. 2 Copy B to A. Get the next B.<br />
&nbsp; # (Delete A). 3 Get the next B. (Delete B). action treats a string as a<br />
&nbsp; # single character. Wow! action recognizes a regular expression if it is<br />
&nbsp; # preceded by ( or , or =.<br />
&nbsp; def action(a)<br />
&nbsp; &nbsp; &nbsp; if(a==1)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @output &lt;&lt; @theA<br />
&nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; if(a==1 || a==2)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @theA = @theB<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (@theA == &quot;<span class="es0">\&#8217;</span>&quot; || @theA == &quot;<span class="es0">\&quot;</span>&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (true)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @output &lt;&lt; @theA<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @theA = get<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break if (@theA == @theB)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise &quot;Unterminated string literal&quot; if (@theA &lt;= &quot;<span class="es0">\n</span>&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (@theA == &quot;<span class="es0">\\</span>&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @output &lt;&lt; @theA<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @theA = get<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; if(a==1 || a==2 || a==3)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @theB = mynext<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (@theB == &quot;/&quot; &amp;&amp; (@theA == &quot;(&quot; || @theA == &quot;,&quot; || @theA == &quot;=&quot; ||<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@theA == &quot;:&quot; || @theA == &quot;[&quot; || @theA == &quot;!&quot; ||<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@theA == &quot;&amp;&quot; || @theA == &quot;|&quot; || @theA == &quot;?&quot; ||<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@theA == &quot;{&quot; || @theA == &quot;}&quot; || @theA == &quot;;&quot; ||<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@theA == &quot;<span class="es0">\n</span>&quot;))<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @output &lt;&lt; @theA<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @output &lt;&lt; @theB<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (true)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @theA = get<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (@theA == &quot;/&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elsif (@theA == &quot;<span class="es0">\\</span>&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @output &lt;&lt; @theA<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @theA = get<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elsif (@theA &lt;= &quot;<span class="es0">\n</span>&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise &quot;Unterminated RegExp Literal&quot; + @output<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @output &lt;&lt; @theA<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @theB = mynext<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; end<br />
&nbsp; end<br />
end</span></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://letsgetdugg.com/2009/12/13/ruby-threadsafe-jsmin-library/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

