<?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>richwklein.com &#187; Work</title>
	<atom:link href="http://richwklein.com/category/work/feed/" rel="self" type="application/rss+xml" />
	<link>http://richwklein.com</link>
	<description>A blog about nothing</description>
	<lastBuildDate>Wed, 08 Sep 2010 16:32:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
	<atom:link rel='hub' href='http://richwklein.com/?pushpress=hub'/>
		<item>
		<title>IE is Being Mean to Me</title>
		<link>http://richwklein.com/2010/03/26/ie-is-being-mean-to-me/</link>
		<comments>http://richwklein.com/2010/03/26/ie-is-being-mean-to-me/#comments</comments>
		<pubDate>Fri, 26 Mar 2010 16:14:05 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Media]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[Explorer]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Internet Explorer]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mean]]></category>
		<category><![CDATA[Rant]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[Viral]]></category>

		<guid isPermaLink="false">http://richwklein.com/?p=1509</guid>
		<description><![CDATA[I so feel this guys pain. I&#8217;ve been in the situation many times before trying to get javascript/html working cross browser.]]></description>
			<content:encoded><![CDATA[<p>I so feel this guys pain.  I&#8217;ve been in the situation many times before trying to get javascript/html working cross browser.<br />
<object class="video pad"><param name="movie" value="http://www.youtube.com/v/vTTzwJsHpU8&#038;hl=en_US&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/vTTzwJsHpU8&#038;hl=en_US&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://richwklein.com/2010/03/26/ie-is-being-mean-to-me/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>JavaScript Singletons in Firefox Add-ons</title>
		<link>http://richwklein.com/2010/01/19/javascript-singletons-in-firefox-add-ons/</link>
		<comments>http://richwklein.com/2010/01/19/javascript-singletons-in-firefox-add-ons/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 21:20:08 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[Add-On]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Extension]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[Hack]]></category>
		<category><![CDATA[Iframe]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Service]]></category>
		<category><![CDATA[Singleton]]></category>
		<category><![CDATA[Tip]]></category>
		<category><![CDATA[Trick]]></category>
		<category><![CDATA[XPCOM]]></category>

		<guid isPermaLink="false">http://richwklein.com/?p=984</guid>
		<description><![CDATA[Occasionally when developing add-ons for Firefox, you want your JavaScript to only run once for the lifetime of the application. Normally, you would place your code in a browser overlay, but this causes the code to run every time a new window is opened. There are several ways to get around this. You could write [...]]]></description>
			<content:encoded><![CDATA[<p>Occasionally when developing <a href="http://addons.mozilla.org">add-ons</a> for <a href="http://getfirefox.com">Firefox</a>, you want your JavaScript to only run once for the lifetime of the application.  Normally, you would place your code in a browser overlay, but this causes the code to run every time a new window is opened.  There are several ways to get around this.  You could write an <a href="https://developer.mozilla.org/en/XPCOM">XPCOM service</a> or use a <a href="https://developer.mozilla.org/en/JavaScript_code_modules">JavaScript module</a>.  These are both valid methods and work very well if your code is Firefox specific.  However, if you are also writing your add-on for <a href="http://www.google.com/chrome">Chrome</a>, you might want the code to be able to run in both places.  Here is a nice little hack that uses the hidden window so that you can run your <a href="http://code.google.com/chrome/extensions/background_pages.html">Chrome background page</a> within an iframe in Firefox. </p>
<p><span id="more-984"></span></p>
<pre>

  function getBackgroundPage(id, src) {

    // get the firefox hidden window
    var win = Components.classes["@mozilla.org/appshell/appShellService;1"].
                   getService(Components.interfaces.nsIAppShellService).
                   hiddenDOMWindow;

    // if the iframe was previously loaded store it and callback
    var iframe = win.document.getElementsById(id);
    if (iframe)
      return iframe.contentWindow;

    // create the iframe
    iframe = win.document.createElement("iframe");
    iframe.setAttribute("id", id);
    iframe.setAttribute("style", "display:none;");

    // load the source
    iframe.setAttribute("src", src);
    win.document.documentElement.appendChild(iframe);

    // return the content window
    return iframe.contentWindow;
</pre>
<p>Now you can access your background page by including the script in your overlay and doing:</p>
<pre>
  var bgp = getBackgroundPage("id for background page", "url of the background page");
</pre>
<p>** UPDATE **<br />
instead of setting the style to display:none you should instead set the attribute &#8220;collapsed&#8221; to true.  This causes docshell errors in some cases.</p>
<p><strike>iframe.setAttribute(&#8220;style&#8221;, &#8220;display:none;&#8221;);</strike><br />
iframe.setAttribute(&#8220;collapsed&#8221;, &#8220;true&#8221;);</p>
]]></content:encoded>
			<wfw:commentRss>http://richwklein.com/2010/01/19/javascript-singletons-in-firefox-add-ons/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web Tech Studios</title>
		<link>http://richwklein.com/2009/12/23/web-tech-studios/</link>
		<comments>http://richwklein.com/2009/12/23/web-tech-studios/#comments</comments>
		<pubDate>Wed, 23 Dec 2009 20:55:57 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[Contract]]></category>
		<category><![CDATA[Studios]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Web Tech Studios]]></category>
		<category><![CDATA[WTS]]></category>

		<guid isPermaLink="false">http://richwklein.com/?p=969</guid>
		<description><![CDATA[Web Tech Studios is a company I created to cover the work I do in my spare time. The focus of the company is providing custom solutions for clients. We will also supply free Firefox add-ons. For the add-ons we are asking for donations to cover the development cost. After much trial and error the [...]]]></description>
			<content:encoded><![CDATA[<p>Web Tech Studios is a company I created to cover the work I do in my spare time.  The focus of the company is providing custom solutions for clients.  We will also supply free Firefox add-ons.  For the add-ons we are asking for donations to cover the development cost.</p>
<p>After much trial and error the <a href="http://webtechstudios.com">website</a> for my company &#8220;Web Tech Studios&#8221; is now live.  Please, look it over and let me know what you think.  You can also follow me on twitter <a href="http://twitter.com/webtechstudios">@webtechstudios</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://richwklein.com/2009/12/23/web-tech-studios/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Diamond in the HTML &#8220;Rough&#8221;</title>
		<link>http://richwklein.com/2009/12/08/diamond-in-the-html-rough/</link>
		<comments>http://richwklein.com/2009/12/08/diamond-in-the-html-rough/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 17:12:35 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[Add-On]]></category>
		<category><![CDATA[Clover]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Diamond]]></category>
		<category><![CDATA[Extension]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[Hack]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[KwiClick]]></category>
		<category><![CDATA[Search]]></category>
		<category><![CDATA[Search Clover]]></category>
		<category><![CDATA[Shadow]]></category>
		<category><![CDATA[Transform]]></category>

		<guid isPermaLink="false">http://richwklein.com/?p=937</guid>
		<description><![CDATA[For the latest version of KwiClick we introduced a feature called search clovers. When you highlight a word on a page, a single diamond shaped &#8220;clover&#8221; appears. When you hover over the diamond, 3 more diamonds appear creating a 4 leaf clover configuration. To create these diamonds we use two html tags, an img surrounded [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://richwklein.com/wp-content/uploads/2009/12/clovers.png"><img src="http://richwklein.com/wp-content/uploads/2009/12/clovers.png" alt="KwiClick Search Clovers" title="KwiClick Search Clovers" width="106" height="125" class="alignleft pad" /></a>For the latest <a href="https://addons.mozilla.org/en-US/firefox/addon/5655">version</a> of <a href="http://www.kwiclick.com/">KwiClick</a> we introduced a feature called search clovers.  When you highlight a word on a page, a single diamond shaped &#8220;clover&#8221; appears.  When you hover over the diamond, 3 more diamonds appear creating a 4 leaf clover configuration.  To create these diamonds we use two html tags, an img surrounded by a div.  <a href="http://richwklein.com/wp-content/uploads/2009/12/cloveroverlap.png"><img src="http://richwklein.com/wp-content/uploads/2009/12/cloveroverlap.png" alt="Clover Overlap" title="Clover Overlap" width="91" height="89" class="alignright pad" /></a>In Firefox versions prior to 3.5 we used a background image on the div to create the look of a the diamond.  The corners of the images overlapped each other causing problems when a user tried to hover or click on one of them.</p>
<p><span id="more-937"></span><br />
With Firefox 3.5 we were able to fix this by creating the diamond using only html and some specialized css tags.  Using the tags: -moz-transform, -moz-border-radius, and -moz-box-shadow we rotate the div 45 degrees and add a shadow to them.</p>
<pre>
  display: inline-block !important;
  border: 2px solid #494949 !important;
  background: none !important;
  background-color: white !important;
  -moz-transform: rotate(45deg) !important;
  -moz-border-radius: 4px !important;
  -moz-box-shadow: grey 2px 2px 2px !important;
</pre>
<p> This also rotates the content within the div.  To fix that we rotate the image back 45 degrees. </p>
<pre>
  -moz-transform: rotate(-45deg) !important;
</pre>
<p>And viola, a diamond with all the html event goodness, made with only html and css.  Safari and Chrome support these transforms with -webkit-transform so this same effect can be used there.  </p>
]]></content:encoded>
			<wfw:commentRss>http://richwklein.com/2009/12/08/diamond-in-the-html-rough/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Caching Parsed Django Templates</title>
		<link>http://richwklein.com/2009/12/01/caching-parsed-django-templates/</link>
		<comments>http://richwklein.com/2009/12/01/caching-parsed-django-templates/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 17:09:18 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Compile]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Template]]></category>
		<category><![CDATA[Tip]]></category>
		<category><![CDATA[Trick]]></category>

		<guid isPermaLink="false">http://richwklein.com/?p=924</guid>
		<description><![CDATA[Standard Django rendering parses a template every time it is rendered. Storing the parsed template can be a nice little speed up for your Django site. This code snippet does a great job of doing that for all templates. One drawback to this approach though is that the server needs restarted whenever a template changes. [...]]]></description>
			<content:encoded><![CDATA[<p>Standard <a href="http://www.djangoproject.com/">Django</a> rendering parses a template every time it is rendered.  Storing the parsed template can be a nice little speed up for your Django site.  <a href="http://www.djangosnippets.org/snippets/507/">This</a> code snippet does a great job of doing that for all templates.  One drawback to this approach though is that the server needs restarted whenever a template changes.  I&#8217;ve taken a slightly different approach to this where I create a separate method for caching and rendering templates.  I only call this when rendering several templates in a view and the speed up is absolutely necessary.  Some places you might consider doing this is when sending out bulk emails or when rendering a long list of objects and each object uses the same template.</p>
<p>First create a file called template.py in your application.  Then we create a method that will cache a template when called and return the rendered template.</p>
<pre>
from django.template import Context, loader

template_cache = {}
def render_cached(template_name, dictionary=None):
    global template_cache

    t = template_cache.get(template_name, None)
    if not t or settings.DEBUG:
        template_cache[template_name] = t = loader.get_template(template_name)

    dictionary = dictionary or {}
    context_instance = Context(dictionary)
    return t.render(context_instance)
</pre>
<p>This method takes two arguments the template name and a dictionary to use for the template context.  It first gets the template out of the cache.  It then looks if the template was retrieved or if your debug setting is on.  If either of these cases exist, it uses the base django loader to retrieve the parsed template and store it in the cache dictionary.  Then we create a context instance for the dictionary and return the rendered code.</p>
<p>To be able to use the method you just import and call it.</p>
<pre>
from template import render_cached
html = render_cached("sometemplate.html", {})
</pre>
]]></content:encoded>
			<wfw:commentRss>http://richwklein.com/2009/12/01/caching-parsed-django-templates/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>KwiClick 2.4.1</title>
		<link>http://richwklein.com/2009/11/29/kwiclick-2-4-1/</link>
		<comments>http://richwklein.com/2009/11/29/kwiclick-2-4-1/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 13:58:28 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[Add-On]]></category>
		<category><![CDATA[Clover]]></category>
		<category><![CDATA[Extension]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[KwiClick]]></category>
		<category><![CDATA[Search]]></category>
		<category><![CDATA[Search Clover]]></category>
		<category><![CDATA[Update]]></category>
		<category><![CDATA[Version]]></category>

		<guid isPermaLink="false">http://richwklein.com/?p=917</guid>
		<description><![CDATA[KwiClick 2.4.1 was released on AMO this week. This is a pretty large update from the last AMO release so make sure to check it out. Here is a list of what is new in this release: New Search Clovers for selection based searching functionality Updated Bing provider Updated compatibility for ff 3.6betas Improve sqlite [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://addons.mozilla.org/en-US/firefox/addon/5655">KwiClick 2.4.1</a> was released on AMO this week.  This is a pretty large update from the last AMO release so make sure to check it out.  Here is a list of what is new in this release:</p>
<ul>
<li>New Search Clovers for selection based searching functionality</li>
<li>Updated Bing provider</li>
<li>Updated compatibility for ff 3.6betas</li>
<li>Improve sqlite performance</li>
<li>Trim leading and trailing spaces from searches to improve accuracy</li>
<li>Updated kwiclick skin</li>
<li>Replace getBoxObjectFor with getBoundingClientRect</li>
<li>Clover preferences to fine tune functionality</li>
<li>Turn on/off clover from statusbar button</li>
<li>Updated wikipedia provider increases accuracy of searching and results</li>
</ul>
<p>Here is the video for the 2.4 release which was submitted to the extend firefox contest.  This is a pretty good explanation of the things you can do with <a href="http://kwiclick.com">KwiClick</a>.<br />
<object class="pad video"><param name="movie" value="http://www.youtube.com/v/tsP7LuuRWPQ&#038;hl=en_US&#038;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/tsP7LuuRWPQ&#038;hl=en_US&#038;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://richwklein.com/2009/11/29/kwiclick-2-4-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FAIL:  libIDL on Mac OS X 10.6 (Snow Leopard)</title>
		<link>http://richwklein.com/2009/10/27/fail-libidl-on-mac-os-x-10-6-snow-leopard/</link>
		<comments>http://richwklein.com/2009/10/27/fail-libidl-on-mac-os-x-10-6-snow-leopard/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 19:11:08 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[10.6]]></category>
		<category><![CDATA[32 bit]]></category>
		<category><![CDATA[64]]></category>
		<category><![CDATA[Add-On]]></category>
		<category><![CDATA[bit]]></category>
		<category><![CDATA[Compile]]></category>
		<category><![CDATA[Extension]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[Gecko]]></category>
		<category><![CDATA[Interface]]></category>
		<category><![CDATA[LibIDL]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[OS]]></category>
		<category><![CDATA[Question]]></category>
		<category><![CDATA[SDK]]></category>
		<category><![CDATA[Snow Leopard]]></category>
		<category><![CDATA[XPCOM]]></category>

		<guid isPermaLink="false">http://richwklein.com/?p=904</guid>
		<description><![CDATA[Since I upgraded my laptop to Snow Leopard, I&#8217;ve been trying to setup my development environment so that I can compile idl files. I need to do this for one of the Firefox extension I work on. I&#8217;ve been able to put this off for a while since my interfaces haven&#8217;t changed in a while. [...]]]></description>
			<content:encoded><![CDATA[<p>Since I upgraded my laptop to Snow Leopard, I&#8217;ve been trying to setup my development environment so that I can compile idl files.  I need to do this for one of the Firefox extension I work on.  I&#8217;ve been able to put this off for a while since my interfaces haven&#8217;t changed in a while.  I&#8217;ve recently changed an interface so now I need to get the idl compiling setup.  When I&#8217;ve set this up in the past, I haven&#8217;t had any problems.  I install the gecko sdk, install libidl, and I&#8217;m ready to roll.  This time I can&#8217;t make it work so I&#8217;m turning to you, the interweb, to help me figure this out.  Here is what I&#8217;ve go so far.</p>
<p>I install the <a href="https://developer.mozilla.org/en/Gecko_SDK">Gecko 1.9.1 SDK</a> from developer.mozilla.org.  I then install libidl using the following commands in MacPorts:</p>
<pre>
sudo port selfupdate
sudo port sync
sudo port install libidl
</pre>
<p>Now, when I run my build script I get the error:</p>
<pre>
     [exec] dyld: Library not loaded: /opt/local/lib/libIDL-2.0.dylib
     [exec]   Referenced from: /Developer/xulrunner-sdk-1.9.1/bin/xpidl
     [exec]   Reason: no suitable image found.  Did find:
     [exec] 	/opt/local/lib/libIDL-2.0.dylib: mach-o, but wrong architecture
</pre>
<p>Figuring that libidl is compiled as 64 bit and the gecko sdk is 32 bit, I go searching the web.  This leads me to a forum post on <a href="http://forums.mozillazine.org/viewtopic.php?f=12&#038;t=1518455">compiling Camino on Snow Leopard</a>.</p>
<blockquote><p>
Mac OS 10.6 is 64-bit as native, while Camino is far from 64-bit ready. So cross-compiling to 32-bit is required.<br />
First hurdle was to cross-compile and install the required libIDL library, in 32-bit. Luckily MacPorts contain a universal libIDL, so after I got the hint about &#8220;versions&#8221; I got that going using the command &#8211; &#8220;sudo port install libIDL +universal&#8221;.
</p></blockquote>
<p>Alright, so now I&#8217;m trying to install the universal libIDL file and I hit another error.</p>
<pre>
Command output:       _IDL_inhibit_get in libIDL_2_la-parser.o
      _IDL_queue_new_ident_comment in libIDL_2_la-parser.o
      _IDL_file_set in libIDL_2_la-parser.o
      ___IDL_do_pragma in libIDL_2_la-parser.o
      _IDL_ns_scope_levels_from_here in libIDL_2_la-ns.o
      _IDL_tree_properties_copy in libIDL_2_la-util.o
      _IDL_tree_walk2 in libIDL_2_la-util.o
      _IDL_tree_to_IDL in libIDL_2_la-util.o
      _IDL_tree_get_scope in libIDL_2_la-util.o
      _IDL_tree_remove_inhibits in libIDL_2_la-util.o
      _IDL_tree_property_remove in libIDL_2_la-util.o
      _IDL_tree_property_get in libIDL_2_la-util.o
      _IDL_tree_property_set in libIDL_2_la-util.o
  "_g_log", referenced from:
      _IDL_check_type_cast in libIDL_2_la-util.o
      _IDL_tree_walk_real in libIDL_2_la-util.o
      _IDL_tree_walk_real in libIDL_2_la-util.o
      _IDL_emit_IDL_literal in libIDL_2_la-util.o
      _IDL_tree_get_node_info in libIDL_2_la-util.o
      _IDL_tree_get_scope in libIDL_2_la-util.o
      _IDL_tree_remove_empty_modules in libIDL_2_la-util.o
      _IDL_tree_remove_inhibits in libIDL_2_la-util.o
      _IDL_tree_process_forward_dcls in libIDL_2_la-util.o
      _load_inhibits in libIDL_2_la-util.o
      _IDL_tree_free in libIDL_2_la-util.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make[2]: *** [libIDL-2.la] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2
</pre>
<p>Here is where I&#8217;m stuck.  I have no idea what symbols are missing.  Please, leave me a comment if you have any ideas on how to make this work.</p>
<p>** Update **<br />
This is what I did to get this to work.</p>
<pre>
sudo port -f uninstall installed
sudo port install libIDL universal
</pre>
]]></content:encoded>
			<wfw:commentRss>http://richwklein.com/2009/10/27/fail-libidl-on-mac-os-x-10-6-snow-leopard/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>State of Broadband in Rural Iowa</title>
		<link>http://richwklein.com/2009/08/17/state-of-broadband-in-rural-iowa/</link>
		<comments>http://richwklein.com/2009/08/17/state-of-broadband-in-rural-iowa/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 14:00:31 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[AOL]]></category>
		<category><![CDATA[Broadband]]></category>
		<category><![CDATA[Caps]]></category>
		<category><![CDATA[Cost]]></category>
		<category><![CDATA[GigaOm]]></category>
		<category><![CDATA[Hughes Net]]></category>
		<category><![CDATA[Iowa]]></category>
		<category><![CDATA[Iowa Telecom]]></category>
		<category><![CDATA[Local]]></category>
		<category><![CDATA[Mediacom]]></category>
		<category><![CDATA[Qwest]]></category>
		<category><![CDATA[Rant]]></category>
		<category><![CDATA[Rural]]></category>
		<category><![CDATA[Telecom]]></category>
		<category><![CDATA[Verizon]]></category>
		<category><![CDATA[Wild Blue]]></category>

		<guid isPermaLink="false">http://richwklein.com/?p=844</guid>
		<description><![CDATA[I work full time for AOL, LLC and telecommute to work. Because of this I need to have broadband in my home. We currently live in the smallish town of Indianola, Iowa and we use Mediacom for our broadband access. The current high speed package we have is $50 a month (7MB download, 512KB upload, [...]]]></description>
			<content:encoded><![CDATA[<p>I work full time for <a href="http://corp.aol.com/">AOL, LLC</a> and telecommute to work.  Because of this I need to have broadband in my home.  We currently live in the smallish town of Indianola, Iowa and we use <a href="http://www.mediacomcc.com/">Mediacom</a> for our broadband access.  The current high speed package we have is $50 a month (7MB download, 512KB upload, and no usage cap).  I typical average about 300MB up and 2GB down a day.  We&#8217;ve been in the process of building a new home less than ten miles away, about 5 miles outside of the city limits.  I&#8217;ve been trying to find out what kind of broadband options are available in the area so I can figure out what carrier we would have for the home office.  This has lead me to discover just how abysmal coverage is in rural areas and just how difficult it is to even find out what&#8217;s available in my area.  Here is what I&#8217;ve been able to find out:
<ul>
<li><a href="http://www.mediacomonlineoffers.com/">Mediacom</a> is not available in my area.</li>
<li><a href="http://www.qwest.com/">Qwest</a> dial-up service is the only thing available.</li>
<li><a href="http://www22.verizon.com/Residential/HighspeedInternet/">Verizon</a> is not available in my area.</li>
<li><a href="http://www.verizonwireless.com/b2c/mobilebroadband/">Verizon</a> mobile broadband is available for $59.99 a month with a maximum 5GB per month.</li>
<li><a href="http://www.iowatelecom.com/businessservices/article.asp?id=171&#038;PID=135">Iowa Telecom</a> needs a phone number to find out if it&#8217;s available.</li>
<li><a href="http://www.hughesnet.com/">Hughes Net</a> costs 7 times as much for a comparable package.</li>
<li><a href="http://www.wildblue.com/">Wild Blue</a> offers a package for $79.95 that is 1/5th the speed and has a maximum 17GB per month.</li>
</ul>
<p><iframe width="500" height="400" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.com/maps/ms?hl=en&amp;ie=UTF8&amp;split=0&amp;gl=us&amp;ei=BymISrO_BoXoM4XO3fsO&amp;msa=0&amp;msid=105274418796614357700.0004714424abd815d1131&amp;ll=41.35568,-93.530045&amp;spn=0.103082,0.171661&amp;z=12&amp;output=embed"></iframe><br /><small>View <a href="http://maps.google.com/maps/ms?hl=en&amp;ie=UTF8&amp;split=0&amp;gl=us&amp;ei=BymISrO_BoXoM4XO3fsO&amp;msa=0&amp;msid=105274418796614357700.0004714424abd815d1131&amp;ll=41.35568,-93.530045&amp;spn=0.103082,0.171661&amp;z=12&amp;source=embed" class="pad">House Locations</a> in a larger map</small></p>
<p>An interesting side note:  I started working on this post over the weekend.  OM Malik has two stories today about the state of broadband in the US.
<ul>
<li><a href="http://gigaom.com/2009/08/17/q2-2009-broadband/">Broadband Growth Falls Sharply in the U.S.</a></li>
<li><a href="http://gigaom.com/2009/08/17/what-my-daughters-broken-leg-taught-me-about-broadband/">What My Daughter’s Broken Leg Taught Me About Broadband</a></li>
<li><b>Update:</b>  Another great story about rural broadband.  <a href="http://arstechnica.com/tech-policy/news/2009/08/rural-broadband-more-jobs-better-salaries.ars"><br />
Rural broadband = more jobs, better salaries</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://richwklein.com/2009/08/17/state-of-broadband-in-rural-iowa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Improving Django Cache &#8211; Part III</title>
		<link>http://richwklein.com/2009/08/11/improving-django-cache-part-iii/</link>
		<comments>http://richwklein.com/2009/08/11/improving-django-cache-part-iii/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 14:00:51 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tip]]></category>
		<category><![CDATA[Trick]]></category>

		<guid isPermaLink="false">http://richwklein.com/?p=670</guid>
		<description><![CDATA[We&#8217;ve setup a custom cache backend and modified it to fix cache keys. Now, we are going to tackle a much more complicated problem; dogpiling. Dogpiling occurs when an entry in the cache expires. If you get multiple requests for that cached item before it’s new value can be calculated, you end up with attempts [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve setup a <a href="http://richwklein.com/2009/07/28/improving-django-cache-part-i/">custom cache backend</a> and modified it to <a href="http://richwklein.com/2009/08/04/improving-django-cache-part-ii/">fix cache keys</a>.  Now, we are going to tackle a much more complicated problem; dogpiling.</p>
<p>Dogpiling occurs when an entry in the cache expires.  If you get multiple requests for that cached item before it’s new value can be calculated, you end up with attempts from each of those requests to refresh the cache.  To prevent this, we are going to work from the <a href=”http://www.djangosnippets.org/snippets/155/”>MintCache</a> implementation that stores slightly stale data to pass on to requests while the first request for expired data calculates the new value to store in the cache.<br />
<span id="more-670"></span></p>
<p>The magic to make this happen is in two methods added to the CacheClass, pack_values and examine_values.  The pack_values method is used to pack the necessary data so it can be stored in the cache and examine_value is used when data is retrieved from the cache to see if it is expired.</p>
<pre>
    def pack_values(self, value, timeout, refreshed=False):
        refresh_time = (timeout or self.default_timeout) + time.time()
        real_timeout = (timeout or self.default_timeout) + 30
        stored_value = value
        if isinstance(value, unicode):
            stored_value = value.encode('utf-8')
        return (real_timeout, (stored_value, refresh_time, refreshed))
</pre>
<pre>
    def examine_value(self, fixed_key, packed, default=None):
        if packed is None:
            return default

        value, refresh_time, refreshed = packed
        if (time.time() &gt; refresh_time) and not refreshed:
            # Store the stale value while the cache revalidates for another
            # 30 seconds.
            real_timeout, packed = self.pack_values(value, 30, True)
            self._cache.set(fixed_key, packed, real_timeout)
            return None

        if isinstance(value, basestring):
            return smart_unicode(value)
        return value
</pre>
<p>Add calls to these methods from the base methods and your done.</p>
<pre>
    def add(self, key, value, timeout=0):
        fixed_key = self.fix_key(key)
        real_timeout, packed = self.pack_values(value, timeout)
        return self._cache.add(fixed_key, packed, real_timeout)

    def get(self, key, default=None):
        fixed_key = self.fix_key(key)
        packed = self._cache.get(fixed_key)
        return self.examine_value(fixed_key, packed, default)

    def set(self, key, value, timeout=0):
        fixed_key = self.fix_key(key)
        real_timeout, packed = self.pack_values(value, timeout)
        self._cache.set(fixed_key, packed, real_timeout)

    def delete(self, key):
        fixed_key = self.fix_key(key)
        self._cache.delete(fixed_key)

    def get_many(self, keys):
        fixed_keys = map(self.fix_key, keys)
        cache_dict = self._cache.get_multi(fixed_keys)
        final_dict = {}
        for fixed_key, packed_value in cache_dict.iteritems():
            key = keys[fixed_keys.index(fixed_key)]
            final_dict[key] = self.examine_value(fixed_key, packed_value)
        return final_dict
</pre>
]]></content:encoded>
			<wfw:commentRss>http://richwklein.com/2009/08/11/improving-django-cache-part-iii/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Improving Django Cache &#8211; Part II</title>
		<link>http://richwklein.com/2009/08/04/improving-django-cache-part-ii/</link>
		<comments>http://richwklein.com/2009/08/04/improving-django-cache-part-ii/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 14:00:45 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tip]]></category>
		<category><![CDATA[Trick]]></category>

		<guid isPermaLink="false">http://richwklein.com/?p=668</guid>
		<description><![CDATA[In part I of this series we setup a custom django cache backend based on the current memcached implementation. For the second installment in this series we are going to start modifying our custom cache backend. Memcached has a couple of limitations it sets on keys. Currently the length limit of a key is set [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://richwklein.com/2009/07/28/improving-django-cache-part-i/">part I</a> of this series we setup a custom <a href="http://www.djangoproject.com/">django</a> cache backend based on the current <a href="http://www.danga.com/memcached/">memcached</a> implementation.  For the second installment in this series we are going to start modifying our custom cache backend.</p>
<p>Memcached has a couple of limitations it sets on keys. Currently the length limit of a key is set at 250 characters and the key must not include control characters or whitespace.  These limitations can be a problem when dealing with long permalinks or rendered template nodes.  First thing we need to do is create a method that will fix keys.<br />
<span id="more-668"></span></p>
<pre>
def fix_key(self, key):
    from django.utils.encoding import smart_str
    import md5

    cache_key = re.sub(r'\s+', '-', key)
    cache_key = smart_str(cache_key)
    if len(cache_key) &gt; 250:
        cache_key = cache_key[:200] + '-' + md5.new(cache_key).hexdigest()
        return cache_key
</pre>
<p>This method will replace whitespaces with dashes and limit the key length so that it never exceeds the 250 limit set by memcached.  Now we just have to change the methods on CacheClass so that they call fix_key and pass the newly generated key into memcached calls.  </p>
<p>The method get_many takes some special consideration.  This method takes a list of keys and returns a dictionary of key value pairs.  This means fix_key needs to be called on all keys passed into the list.  Memcached will return a dict with the fixed keys so they must be translated back to the original keys.</p>
<pre>
def get_many(self, keys):
    fixed_keys = map(self.fix_key, keys)
    cache_dict = self._cache.get_multi(fixed_keys)
    final_dict = {}
    for fixed_key, value in cache_dict.iteritems():
        key = keys[fixed_keys.index(fixed_key)]
        final_dict[key] = value
    return final_dict
</pre>
<p>Now your shouldn&#8217;t have to worry about cache keys in your django application. <a href="http://richwklein.com/2009/08/11/improving-django-cache-part-iii/">Continue on to part III</a></p>
]]></content:encoded>
			<wfw:commentRss>http://richwklein.com/2009/08/04/improving-django-cache-part-ii/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.343 seconds -->
