<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5894461110622240119</id><updated>2012-01-09T14:55:35.498-08:00</updated><category term='ruby'/><category term='database replication'/><category term='solr'/><category term='easter egg'/><category term='darwin'/><category term='activerecord'/><category term='macos'/><category term='jabber'/><category term='mysql'/><category term='javascript jquery ie8'/><category term='utf-8'/><category term='github'/><category term='gtalk'/><category term='tomcat'/><category term='rubygems'/><category term='osx'/><category term='HTTP'/><category term='memcache'/><category term='iphone'/><category term='xcode'/><category term='zabbix'/><category term='git'/><category term='ios'/><category term='gem'/><category term='unix'/><category term='rails'/><category term='xpath'/><category term='HTML'/><category term='nokogiri'/><category term='curb'/><category term='xmpp4r'/><category term='unicode'/><category term='Zappos'/><category term='replication lag'/><title type='text'>The Benevolent Machine</title><subtitle type='html'>I believe in benevolent dictatorship provided I am the dictator. - Richard Branson</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Guy</name><uri>http://www.blogger.com/profile/14454669083613476440</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_yGR1NJWLsZA/TB8LSO0UCSI/AAAAAAAAEy0/gdooQwVeCxs/s1600-R/827436cc791e4c35bc15526648f91672_160x160.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5894461110622240119.post-2063760803804338855</id><published>2011-06-01T16:16:00.000-07:00</published><updated>2011-07-20T21:45:49.115-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>N Tips About Coding for the iPhone That I Wish I Knew Last Week</title><content type='html'>After my first week diving into iPhone / Objective C / XCode / UIKit development, here are some things I wish I knew when I started.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Interface Editor windows do &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; get saved by the "Save All Files" dialog when you launch a build.  Get in the habit of command-S saving when you make changes in the interface editor or you will wonder why your UI changes are not working.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;To associate a UI object (like a button) in the Interface Editor with a member variable, add instance variables which include the IBOutlet and IBAction declarations, and use a right-button mouse drag to associate the object and the field defined in the owning class.  The right-button action is hard to discover by inspection!&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Open the gdb window when  debugging.  It shows the NSLog output, and if you are familiar with gdb's command line, it's a lot quicker to use than the GUI.  Commands like step, continue, where, up, down, print are super useful.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;In gdb use po to print objects:&lt;br /&gt;po myObject&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;You can print the reference count for an object in gdb like this:&lt;br /&gt;print (int)[myObject retainCount]&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;When you use @property to declare a property for a class, XCode 3.2 will automatically create the instance variable if you don't do so explicitly - it doesn't add anything to you source file, but it is defined.  Apparently this is a recent feature, and so you will see some code examples that declare the variable, some that do not - they are equivalent.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Some general rules with retain/copy/assign: use assign for delegates, use copy for NSStrings or anything else that is mutable, and use retain for most other NSObject types.  Be careful about mutual retain relationships: while A retains B and B retains A, neither A nor B can be freed.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The following are NOT all the same:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; member=value&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.member=value&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [self setMember: value]&lt;br /&gt;It appears that the first version will not call the setter function, the second two will.  This distinction is critically important if you are using retain setters to increment the reference count on the assigned object.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;When writing classes that call delegates (which seems to happen a lot), it is smart to always pass the sending object as the first parameter of all callbacks, and in the protocol definition specify the callback with a full type specification ie (MyWorker *), not (id).  This pattern ensures that when you write a class that acts as a delegate for many other classes, the delegate functions all have unique function signatures.&lt;/li&gt;&lt;li&gt;The static analyzer assumes method with names starting with new (eg "newPost") always return a reference-counted object that must be released by the caller.&amp;nbsp; If you violate this naming convention the static analyzer will give you spurious leak warnings like this: "Potential leak of an object allocated on line ..."&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5894461110622240119-2063760803804338855?l=benevolentmachine.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/2063760803804338855/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benevolentmachine.blogspot.com/2011/06/n-tips-about-coding-for-iphone-that-i.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/2063760803804338855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/2063760803804338855'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/2011/06/n-tips-about-coding-for-iphone-that-i.html' title='N Tips About Coding for the iPhone That I Wish I Knew Last Week'/><author><name>Guy</name><uri>http://www.blogger.com/profile/04206227114590444504</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5894461110622240119.post-2783062210077439810</id><published>2010-11-17T16:27:00.000-08:00</published><updated>2010-11-17T18:32:41.909-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rubygems'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='osx'/><title type='text'>Using RubyGems Gem.use_paths</title><content type='html'>Here's a quick tip on Gem.use_paths that might not be obvious from the documentation.&lt;br /&gt;&lt;br /&gt;When you initially fire up rubygems, you will generally have two directories included in your Gem path; the system gems directory, and your user gems directory if you have one. &amp;nbsp;Under OS X I actually see three:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #eeeeee; background-image: initial; background-origin: initial; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; margin-bottom: 10px; margin-left: 0px; margin-right: 0px; margin-top: 0px; overflow-x: auto; overflow-y: auto; padding-bottom: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px;"&gt;&lt;span class="Apple-style-span" style="color: #333333;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;$ &lt;b&gt;uname -a&lt;/b&gt;&lt;br /&gt;Darwin euramoo 10.4.1 Darwin Kernel Version 10.4.1: Wed May 12 21:36:54 PDT 2010; root:xnu-1504.7.50~2/RELEASE_I386 i386&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;$ &lt;b&gt;irb -r rubygems&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="color: #333333;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;Gem.path&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;=&amp;gt; ["/Users/guy/.gem/ruby/1.8", "/Library/Ruby/Gems/1.8", "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8"]&lt;/pre&gt;&lt;div style="color: #333333; font-family: Georgia, serif; font-size: 13px;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: #333333; font-family: Georgia, serif; font-size: 13px;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;Now suppose you want to add a new gem directory using Gem.use_paths. &amp;nbsp;You might try something like this:&lt;/span&gt;&lt;/div&gt;&lt;div style="color: #333333; font-family: Georgia, serif; font-size: 13px;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: #333333;"&gt;&lt;div style="font-family: Georgia, serif; font-size: 13px;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;&lt;span class="Apple-style-span" style="color: black; font-family: 'Times New Roman'; font-size: medium; line-height: normal;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #eeeeee; background-image: initial; background-origin: initial; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; margin-bottom: 10px; margin-left: 0px; margin-right: 0px; margin-top: 0px; overflow-x: auto; overflow-y: auto; padding-bottom: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;&lt;span class="Apple-style-span" style="color: black; line-height: normal;"&gt;&lt;span class="Apple-style-span" style="color: #333333;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&amp;gt;&amp;gt; Gem.use_paths(nil, ["/my/special/path"])&lt;br /&gt;=&amp;gt; nil&lt;br /&gt;&amp;gt;&amp;gt; Gem.path&lt;br /&gt;=&amp;gt; ["/my/special/path", "/Library/Ruby/Gems/1.8"]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: Georgia, serif; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px; line-height: 20px;"&gt;Passing nil as the first parameter indicates you want to preserve the existing gem home directory. &amp;nbsp;You can see that this command has &lt;b&gt;dropped two of the original three default paths&lt;/b&gt;. &amp;nbsp;I didn't expect that. &amp;nbsp;One of those three was the &lt;i&gt;home&lt;/i&gt;&amp;nbsp;directory and was preserved, the other two were dropped.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: Georgia, serif; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px; line-height: 20px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: Georgia, serif; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px; line-height: 20px;"&gt;The solution is easy; if you want to add new paths without dropping any of the existing ones, &lt;b&gt;&amp;nbsp;pass Gem.path &lt;u&gt;plus&lt;/u&gt;&amp;nbsp;your new paths as the second parameter&lt;/b&gt;.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="color: black; font-family: 'Times New Roman'; font-size: medium; line-height: normal;"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: Georgia, serif; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px; line-height: 20px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #eeeeee; background-image: initial; background-origin: initial; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; margin-bottom: 10px; margin-left: 0px; margin-right: 0px; margin-top: 0px; overflow-x: auto; overflow-y: auto; padding-bottom: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px;"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="color: #333333;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;&amp;gt;&amp;gt; &lt;b&gt;Gem.use_paths(nil, Gem.path &amp;lt;&amp;lt; "/my/special/path")&lt;/b&gt;&lt;br /&gt;=&amp;gt; ["/Users/guy/.gem/ruby/1.8", "/Library/Ruby/Gems/1.8", "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8", "/my/special/path"]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium;"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: Georgia, serif; font-size: 13px; line-height: 20px;"&gt;Rubygems is smart enough not to duplicate the paths - here we have passed the home directory in as part of Gem.path and it does not show up twice in the resulting path list.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium;"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: Georgia, serif; font-size: 13px; line-height: 20px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium;"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: Georgia, serif; font-size: 13px; line-height: 20px;"&gt;Two more quick observations:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: Georgia, serif; font-size: 13px; line-height: 20px;"&gt;&lt;b&gt;Gem.dir returns the gem home directory&lt;/b&gt;; that's the only one of the default gem directories that will be preserved when you call Gem.use_paths with nil as the first parameter.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;span class="Apple-style-span"&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: Georgia, serif; font-size: 13px; line-height: 20px;"&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: Georgia, serif; font-size: 13px; line-height: 20px;"&gt;Gem.use_paths &lt;b&gt;does not necessarily return&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: Georgia, serif; font-size: 13px; line-height: 20px;"&gt;&lt;b&gt;the new path list.&lt;/b&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #333333; font-family: Georgia, serif; font-size: 13px; line-height: 20px;"&gt;&amp;nbsp;&amp;nbsp;It might, or it might return nil. &amp;nbsp;Within rubygems.rb, the return value is the result of @gem_path.uniq!, and the semantics of uniq! are such that it returns nil if no duplicates were removed. &amp;nbsp;Better ignore the return value and use Gem.path to get the actual directory list.&lt;/span&gt;&lt;/li&gt;&lt;/span&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5894461110622240119-2783062210077439810?l=benevolentmachine.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/2783062210077439810/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benevolentmachine.blogspot.com/2010/11/using-rubygems-gemusepaths.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/2783062210077439810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/2783062210077439810'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/2010/11/using-rubygems-gemusepaths.html' title='Using RubyGems Gem.use_paths'/><author><name>Guy</name><uri>http://www.blogger.com/profile/14454669083613476440</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_yGR1NJWLsZA/TB8LSO0UCSI/AAAAAAAAEy0/gdooQwVeCxs/s1600-R/827436cc791e4c35bc15526648f91672_160x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5894461110622240119.post-7695878742312400820</id><published>2010-10-28T17:29:00.000-07:00</published><updated>2010-10-28T17:30:37.672-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='macos'/><category scheme='http://www.blogger.com/atom/ns#' term='curb'/><category scheme='http://www.blogger.com/atom/ns#' term='gem'/><category scheme='http://www.blogger.com/atom/ns#' term='darwin'/><title type='text'>Errors installing the curb gem on MacOS</title><content type='html'>I've run into this issue several times now, so this post is mostly a note to me of the future.&amp;nbsp;&amp;nbsp;Under MacOS 10.4 the following error occurs if you try to install the curb gem in the usual way.&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #eeeeee; background-image: initial; background-origin: initial; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; margin-bottom: 10px; margin-left: 0px; margin-right: 0px; margin-top: 0px; overflow-x: auto; overflow-y: auto; padding-bottom: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px;"&gt;&lt;span class="Apple-style-span" style="color: #333333;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;$ &lt;b&gt;gem install --user-install curb&lt;/b&gt;&lt;br /&gt;Building native extensions.  This could take a while...&lt;br /&gt;ERROR:  Error installing curb:&lt;br /&gt;        ERROR: Failed to build gem native extension.&lt;br /&gt;&lt;br /&gt;/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby extconf.rb&lt;br /&gt;"-arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE  -fno-common  -pipe -fno-common $(cflags)"&lt;br /&gt;checking for curl-config... yes&lt;br /&gt;checking for curlinfo_redirect_time... no&lt;br /&gt;checking for curlinfo_response_code... no&lt;br /&gt;checking for curlinfo_filetime... no&lt;br /&gt;checking for curlinfo_redirect_count... no&lt;br /&gt;checking for curlinfo_os_errno... no&lt;br /&gt;checking for curlinfo_num_connects... no&lt;br /&gt;checking for curlinfo_ftp_entry_path... no&lt;br /&gt;checking for curl_version_ssl... no&lt;br /&gt;checking for curl_version_libz... no&lt;br /&gt;checking for curl_version_ntlm... no&lt;br /&gt;checking for curl_version_gssnegotiate... no&lt;br /&gt;checking for curl_version_debug... no&lt;br /&gt;checking for curl_version_asynchdns... no&lt;br /&gt;checking for curl_version_spnego... no&lt;br /&gt;checking for curl_version_largefile... no&lt;br /&gt;checking for curl_version_idn... no&lt;br /&gt;checking for curl_version_sspi... no&lt;br /&gt;checking for curl_version_conv... no&lt;br /&gt;checking for curlproxy_http... no&lt;br /&gt;checking for curlproxy_socks4... no&lt;br /&gt;checking for curlproxy_socks5... no&lt;br /&gt;checking for curlauth_basic... no&lt;br /&gt;checking for curlauth_digest... no&lt;br /&gt;checking for curlauth_gssnegotiate... no&lt;br /&gt;checking for curlauth_ntlm... no&lt;br /&gt;checking for curlauth_anysafe... no&lt;br /&gt;checking for curlauth_any... no&lt;br /&gt;checking for curle_tftp_notfound... no&lt;br /&gt;checking for curle_tftp_perm... no&lt;br /&gt;checking for curle_tftp_diskfull... no&lt;br /&gt;checking for curle_tftp_illegal... no&lt;br /&gt;checking for curle_tftp_unknownid... no&lt;br /&gt;checking for curle_tftp_exists... no&lt;br /&gt;checking for curle_tftp_nosuchuser... no&lt;br /&gt;checking for curle_send_fail_rewind... no&lt;br /&gt;checking for curle_ssl_engine_initfailed... no&lt;br /&gt;checking for curle_login_denied... no&lt;br /&gt;checking for curlmopt_maxconnects... no&lt;br /&gt;checking for curle_conv_failed... no&lt;br /&gt;checking for curle_conv_reqd... no&lt;br /&gt;checking for curle_ssl_cacert_badfile... no&lt;br /&gt;checking for curle_remote_file_not_found... no&lt;br /&gt;checking for curle_ssh... no&lt;br /&gt;checking for curle_ssl_shutdown_failed... no&lt;br /&gt;checking for curle_again... no&lt;br /&gt;checking for curle_ssl_crl_badfile... no&lt;br /&gt;checking for curle_ssl_issuer_error... no&lt;br /&gt;checking for curlopt_username... no&lt;br /&gt;checking for curlopt_password... no&lt;br /&gt;checking for curlinfo_primary_ip... no&lt;br /&gt;checking for curlauth_digest_ie... no&lt;br /&gt;checking for curlftpmethod_multicwd... no&lt;br /&gt;checking for curlftpmethod_nocwd... no&lt;br /&gt;checking for curlftpmethod_singlecwd... no&lt;br /&gt;checking for curlm_bad_socket... no&lt;br /&gt;checking for curlm_unknown_option... no&lt;br /&gt;checking for curl_multi_timeout()... no&lt;br /&gt;checking for curl_multi_fdset()... no&lt;br /&gt;checking for curl_multi_perform()... no&lt;br /&gt;checking for Ruby 1.9 Hash... no&lt;br /&gt;checking for Ruby 1.9 st.h... yes&lt;br /&gt;checking for curl_easy_escape... no&lt;br /&gt;creating curb_config.h&lt;br /&gt;creating Makefile&lt;br /&gt;&lt;br /&gt;make&lt;br /&gt;gcc -I. -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -DRUBY_EXTCONF_H=\"curb_config.h\"  -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE   -fno-common -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE  -fno-common  -pipe -fno-common  -I/opt/local/include -g -Wall  -c curb.c&lt;br /&gt;In file included from /opt/local/include/curl/curl.h:35,&lt;br /&gt;                 from curb.h:12,&lt;br /&gt;                 from curb.c:8:&lt;br /&gt;/opt/local/include/curl/curlrules.h:143: error: size of array '__curl_rule_01__' is negative&lt;br /&gt;/opt/local/include/curl/curlrules.h:153: error: size of array '__curl_rule_02__' is negative&lt;br /&gt;lipo: can't open input file: /var/tmp//ccRdCdoj.out (No such file or directory)&lt;br /&gt;make: *** [curb.o] Error 1&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;There are two solutions offered in &lt;a href="http://github.com/taf2/curb/wiki/faq"&gt;the curb FAQ&lt;/a&gt;. &amp;nbsp;I'm not a fan of the first solution listed; it installs and builds a bunch of ports, and after 10 minutes I begin to worry what new version issues&amp;nbsp;I'm going to bring down upon myself...&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #eeeeee; background-image: initial; background-origin: initial; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; margin-bottom: 10px; margin-left: 0px; margin-right: 0px; margin-top: 0px; overflow-x: auto; overflow-y: auto; padding-bottom: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px;"&gt;&lt;span class="Apple-style-span" style="color: #333333;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;sudo port install curl +universal  # don't use this one&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The second solution from the FAQ &lt;i&gt;is &lt;/i&gt;the droid you were looking for. &amp;nbsp;The form listed in the FAQ will do a root install of the gem:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #eeeeee; background-image: initial; background-origin: initial; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; margin-bottom: 10px; margin-left: 0px; margin-right: 0px; margin-top: 0px; overflow-x: auto; overflow-y: auto; padding-bottom: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px;"&gt;&lt;span class="Apple-style-span" style="color: #333333;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;sudo env ARCHFLAGS="-arch x86_64" gem install curb  # use this one&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The same approach also works &amp;nbsp;for a user-install:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #eeeeee; background-image: initial; background-origin: initial; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; margin-bottom: 10px; margin-left: 0px; margin-right: 0px; margin-top: 0px; overflow-x: auto; overflow-y: auto; padding-bottom: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px;"&gt;&lt;span class="Apple-style-span" style="color: #333333;"&gt;&lt;span class="Apple-style-span" style="line-height: 21px;"&gt;ARCHFLAGS="-arch x86_64" gem install --user-install curb&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5894461110622240119-7695878742312400820?l=benevolentmachine.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/7695878742312400820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benevolentmachine.blogspot.com/2010/10/errors-installing-curb-gem-on-macos.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/7695878742312400820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/7695878742312400820'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/2010/10/errors-installing-curb-gem-on-macos.html' title='Errors installing the curb gem on MacOS'/><author><name>Guy</name><uri>http://www.blogger.com/profile/14454669083613476440</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_yGR1NJWLsZA/TB8LSO0UCSI/AAAAAAAAEy0/gdooQwVeCxs/s1600-R/827436cc791e4c35bc15526648f91672_160x160.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5894461110622240119.post-5110442392897926996</id><published>2010-10-18T17:43:00.000-07:00</published><updated>2010-10-28T17:34:57.843-07:00</updated><title type='text'>Eliminating DeltaCopy's "File name too long" Errors</title><content type='html'>I use the Windows rsync server&amp;nbsp;&lt;a href="http://www.aboutmyip.com/AboutMyXApp/DeltaCopy.jsp"&gt;DeltaCopy&lt;/a&gt;&amp;nbsp;to backup files from a Windows 7 box using a nightly cron job running on a FreeBSD server. &amp;nbsp;DeltaCopy is a wrapper that runs the Cygwin rsync binaries as a Windows Service. &amp;nbsp;This all works well out of the box &lt;i&gt;with one exception&lt;/i&gt;: the version of Cygwin bundled with DeltaCopy doesn't support long file paths, so I get a bunch of failed copies in my nightly backup logs, like this:&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;rsync: readlink_stat("Profiles/07b6fq5u.default/Mail/Local Folders/Eudora Mail.sbd/Read.mozmsgs/!~!UENERkVCMDkAAQACAAAAAAAAAAAAAAAAABgAAAAAAAAA9XtW%2Fsf8BUe37SpujdFeE8KAAAAQAAAABb%2BHEGlU%2FkaQ5j0m1KGNZgEAAAAA%40earthlink.net.wdseml" (in mail)) failed: File name too long (91&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;The solution is to upgrade the Cygwin libraries that are used by DeltaCopy. &amp;nbsp;The current versions (1.7.7) solve this problem and are compatible with DeltaCopy. &amp;nbsp;You also need to add a couple of lines to the DeltaCopy configuration file.&lt;br /&gt;&lt;br /&gt;There are quite a few posts on this subject on line offering solutions for this, but I did not find any that contained all of the correct&amp;nbsp;information&amp;nbsp;in one place, so here's what worked for me (Windows 7, DeltaCopy 1.3, Cygwin 1.7.7).&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Download the Cygwin installer (setup.exe) available from the &lt;a href="http://www.cygwin.com/"&gt;Cygwin website&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Install the base packages, plus Net/openssh and Net/rsync&lt;/li&gt;&lt;li&gt;Stop the DeltaCopy server (either from the Control Panel or using DeltaS)&lt;/li&gt;&lt;li&gt;Copy the files below from the Cygwin installation path (eg C:\Cygwin\bin) to your DeltaCopy installation path (eg C:\DeltaCopy).&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;chmod.exe&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;cygcrypto-0.9.8.dll&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;cyggcc_s-1.dll&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;cygiconv-2.dll&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;cygintl-8.dll&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;cygminires.dll&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;cygpopt-0.dll&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;cygwin1.dll&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;cygz.dll&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;rsync.exe&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;ssh.exe&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;Edit C:\DeltaCopy\deltacd.conf and add the following two lines at the beginning of the file.&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;uid = 0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;gid = 0&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;Restart the DeltaCopy service&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5894461110622240119-5110442392897926996?l=benevolentmachine.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/5110442392897926996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benevolentmachine.blogspot.com/2010/10/eliminating-deltacopys-file-name-too.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/5110442392897926996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/5110442392897926996'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/2010/10/eliminating-deltacopys-file-name-too.html' title='Eliminating DeltaCopy&apos;s &quot;File name too long&quot; Errors'/><author><name>Guy</name><uri>http://www.blogger.com/profile/14454669083613476440</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_yGR1NJWLsZA/TB8LSO0UCSI/AAAAAAAAEy0/gdooQwVeCxs/s1600-R/827436cc791e4c35bc15526648f91672_160x160.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5894461110622240119.post-5939671955864358214</id><published>2010-08-29T18:35:00.000-07:00</published><updated>2010-08-29T19:07:57.649-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='github'/><title type='text'>Git mojo - The current branch is not tracking anything.</title><content type='html'>If you use &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt; and &lt;a href="http://github.com/"&gt;github&lt;/a&gt;, you may have run into this little nasty surprise when creating a branch locally and pushing it to the remote repository:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# create a local branch&lt;br /&gt;$ git branch mybranch&lt;br /&gt;&lt;br /&gt;# push the branch to the remote repository&lt;br /&gt;$ git push origin mybranch&lt;br /&gt;&lt;br /&gt;# modify some files and commit the changes...&lt;br /&gt;$ git commit&lt;br /&gt;&lt;br /&gt;# push the changes to github&lt;br /&gt;$ git push&lt;br /&gt;&lt;b&gt;fatal: The current branch mybranch is not tracking anything.&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;The problem here is that when the branch was created and pushed, it did not automatically set up the configuration necessary to link it to the remote repository.  Specifically what is missing in .git/config is something like this:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[branch "mybranch"]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; remote = origin&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; merge = refs/heads/mybranch&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;There are a few routes to get you back to good:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;You can edit .git/config in your local working tree and add the missing lines.&amp;nbsp; This smacks of effort.&lt;/li&gt;&lt;li&gt;You can use the following commands to add the missing configuration lines to the config file:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ git config branch.mybranch.remote origin&lt;br /&gt;$ git config branch.mybranch.merge refs/heads/mybranch&lt;/span&gt;&lt;/li&gt;&lt;li&gt;You can use git's --track (or -t) option in the original branch command to avoid this problem in the first place.&lt;/li&gt;&lt;/ol&gt;Now if only I could remember --track each time I create a new branch. &lt;br /&gt;&lt;ol&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5894461110622240119-5939671955864358214?l=benevolentmachine.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/5939671955864358214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benevolentmachine.blogspot.com/2010/08/git-mojo-current-branch-is-not-tracking.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/5939671955864358214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/5939671955864358214'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/2010/08/git-mojo-current-branch-is-not-tracking.html' title='Git mojo - The current branch is not tracking anything.'/><author><name>Guy</name><uri>http://www.blogger.com/profile/14454669083613476440</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_yGR1NJWLsZA/TB8LSO0UCSI/AAAAAAAAEy0/gdooQwVeCxs/s1600-R/827436cc791e4c35bc15526648f91672_160x160.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5894461110622240119.post-8023154191032540178</id><published>2010-07-18T23:31:00.000-07:00</published><updated>2010-07-19T01:06:53.696-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='replication lag'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='memcache'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='database replication'/><category scheme='http://www.blogger.com/atom/ns#' term='activerecord'/><title type='text'>Replication Lag - What Is It and How is it Cured?</title><content type='html'>So your database is becoming a bottleneck, and you are thinking about moving to a distributed database?  Yeah, me too.  The replication support in MySQL is easy to set up, solid as a rock, and seems to be bandwidth efficient.  Problem solved!  Well maybe not as easily as that.  Here's what I've learned migrating a complex system to a replicated environment.&lt;br /&gt;&lt;br /&gt;The obvious challenge with replication is that all writes must be directed to the master.  If you are thinking about replication, you probably already have a solution in mind for that.  In frameworks like Ruby on Rails it turns out to be relatively easy to intercept ActiveRecord writes and route them to the master.  That's a good first step, but have you considered the ramifications of replication lag on your system?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What is Replication Lag?&lt;/h3&gt;&lt;br /&gt;With a typical MySQL database running on modern hardware, with a handful of replicas, it may take a second or two for a change written to the master to be visible in a read from a slave.  Those few seconds of lag can cause major headaches.&lt;br /&gt;&lt;br /&gt;Replication lag plays havoc with the common read-update-read cycle.  Consider a hypothetical example of a user logging into a site with session cookies and a session record stored in the database.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The login request creates a new session, and returns a page that sets the session cookie and an HTML page which in turn will load some additional assets - images, scripts, etc.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A moment later the asset requests arrive with a cookie referencing a session record.  &lt;br /&gt;&lt;/li&gt;&lt;li&gt;The session record query is read-only, so it is directed to a replica.  The session record has been written to the master, but has not yet propagated to the replica, so the query fails.  This looks to the system like an invalid or expired session.  The request fails.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;This scenario applies to any real-time interactions where the user is modifying records and reloading a page which should reflect those results.  Here are some strategies that might help.  We ended up using all of these in various combinations, depending on the usage of the individual database entities.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Read From Master For Time-Critical Entities&lt;/h3&gt;If you can identify a few key database objects that are time-critical, you can force those to be always read from the master.  This obviously defeats the benefit of replication, but if you only have a small number of time-critical objects, that may be all you need.  Lucky you.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Fail-over to Master&lt;/h3&gt;It became evident while looking at replication issues on our system that whenever a database query specifies an explicit value for the primary key, the caller has a sound reason to believe that record exists.  Thus if that query fails with record-no-found, we can reasonably suppose that the record hasn't been propagated yet, and so we can retry the same query on the master database.  This turns out to be pretty easy to implement at a low level in ActiveRecord.  This solves the replication lag issue cleanly for any table that is getting periodic inserts, but the records are either never updated or the updates are not time-critical.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Caching Critical Query Results&lt;/h3&gt;If your database access is nicely abstracted (maybe through ActiveRecord) the above techniques can be implemented without even touching your application logic, which is very reassuring. Sadly there are still some corner cases left unsolved.  For example you may need to find all records related to the current session record, and you don't want to miss a record that was just inserted.  &lt;br /&gt;&lt;br /&gt;If you can't afford to load the master with the query, you can use a tool like memcached to maintain an in-memory index of the associated objects.  A short timeout (a few minutes) on the cache is fine because you really only care about the situation where the data has just changed.  Recognize that you aren't so much caching the records, but you are caching sets of record references that would otherwise be returned by a query.  Remember that memcache has a 1Mb limit to each cache entry, so design your caching strategy to ensure you don't hit this limit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5894461110622240119-8023154191032540178?l=benevolentmachine.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/8023154191032540178/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benevolentmachine.blogspot.com/2010/07/replication-lag-what-is-it-and-how-is.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/8023154191032540178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/8023154191032540178'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/2010/07/replication-lag-what-is-it-and-how-is.html' title='Replication Lag - What Is It and How is it Cured?'/><author><name>Guy</name><uri>http://www.blogger.com/profile/14454669083613476440</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_yGR1NJWLsZA/TB8LSO0UCSI/AAAAAAAAEy0/gdooQwVeCxs/s1600-R/827436cc791e4c35bc15526648f91672_160x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5894461110622240119.post-437110163862803623</id><published>2010-06-15T21:43:00.000-07:00</published><updated>2010-06-15T21:50:22.264-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript jquery ie8'/><title type='text'>Image Size Problems with JQuery and IE</title><content type='html'>I've been working on an image preloader for a JavaScript gallery / slideshow.  I use a spinner image in place of the actual images until the images finish loading, and replace the temporary image with the actual image in the jQuery load event handler.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;actualImg = jQuery('&amp;lt;img /&amp;gt;');&lt;br /&gt;actualImg.load(&lt;br /&gt;  function(){&lt;br /&gt;    tmpImg.replaceWith(actualImg);&lt;br /&gt;    fitImage(actualImg);&lt;br /&gt;  }&lt;br /&gt;).attr('src',imageUrl);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This approach works well in FireFox and Chrome, but under IE8 I found that the fitImage call failed because the image width and height were both undefined.&lt;br /&gt;&lt;br /&gt;Why doesn't IE8 set the width and size prior to the jQuery load callback?&lt;br /&gt;&lt;br /&gt;It turns out that IE8 will only set the width and height if the img node is already inserted into the DOM. I ended up with something like this (change in the first line only).&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;actualImg = jQuery('&amp;lt;img /&amp;gt;').appendTo(canvas);&lt;br /&gt;actualImg.load(&lt;br /&gt;  function(){&lt;br /&gt;    tmpImg.replaceWith(actualImg);&lt;br /&gt;    fitImage(actualImg);&lt;br /&gt;  }&lt;br /&gt;).attr('src',imageUrl);&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5894461110622240119-437110163862803623?l=benevolentmachine.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/437110163862803623/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benevolentmachine.blogspot.com/2010/06/image-size-problems-with-jquery-and-ie.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/437110163862803623'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/437110163862803623'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/2010/06/image-size-problems-with-jquery-and-ie.html' title='Image Size Problems with JQuery and IE'/><author><name>Guy</name><uri>http://www.blogger.com/profile/14454669083613476440</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_yGR1NJWLsZA/TB8LSO0UCSI/AAAAAAAAEy0/gdooQwVeCxs/s1600-R/827436cc791e4c35bc15526648f91672_160x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5894461110622240119.post-362097551995354126</id><published>2010-04-02T02:39:00.000-07:00</published><updated>2010-04-02T02:42:27.548-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='solr'/><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><title type='text'>Getting Descriptive Error Message from the Solr Ruby API</title><content type='html'>I've been working on calling Solr (the search engine) using the Solr ruby gem.&amp;nbsp; If the Solr server throws an error, the Ruby API call returns a pretty unhelpful error:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Net::HTTPFatalError: 500 "Internal Server Error"&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;I can look the error up in the Tomcat logs, but it would be a lot nicer if I could get a meaningful error message through the client API.&lt;br /&gt;&lt;br /&gt;The good news is that I found I can retrieve the entire HTTP response object via the Net::HTTPFatalError's 'data' attribute.&amp;nbsp; The HTTP response contains the full text of the error returned by Solr.&amp;nbsp; The bad news is that Tomcat, by default, formats the error using the org.apache.catalina.valves.ErrorReportValve class.&amp;nbsp; The output is human-readable, but not particularly machine-readable.&lt;br /&gt;&lt;br /&gt;So the upshot of all of this is that I can trap the exceptions returned by Solr::Connection#query and extract the Solr error text like this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; begin&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @solr.query(query, modifiers)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rescue Net::HTTPFatalError =&amp;gt; e&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if e.data.kind_of?(Net::HTTPInternalServerError)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if /&amp;lt;h1&amp;gt;([^\n]+)\n/ =~ e.data.body&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; puts "---- Solr exception -----"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; puts $1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; end&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; end&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise&lt;/span&gt;&lt;span style="font-size: x-small;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; end&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: x-small;"&gt;Which yields something like this:&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-size: x-small;"&gt;---- Solr exception -----&lt;br /&gt;HTTP Status 500 - there are more terms than documents in field "display_name", but it's impossible to sort on tokenized fields&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: x-small;"&gt;Despite being cryptic and HTMLified, that message turns out to be extremely useful.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5894461110622240119-362097551995354126?l=benevolentmachine.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/362097551995354126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benevolentmachine.blogspot.com/2010/04/getting-descriptive-error-message-from.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/362097551995354126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/362097551995354126'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/2010/04/getting-descriptive-error-message-from.html' title='Getting Descriptive Error Message from the Solr Ruby API'/><author><name>Guy</name><uri>http://www.blogger.com/profile/14454669083613476440</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_yGR1NJWLsZA/TB8LSO0UCSI/AAAAAAAAEy0/gdooQwVeCxs/s1600-R/827436cc791e4c35bc15526648f91672_160x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5894461110622240119.post-2983735910418693774</id><published>2010-03-30T18:46:00.000-07:00</published><updated>2010-03-30T18:46:34.392-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='easter egg'/><category scheme='http://www.blogger.com/atom/ns#' term='HTTP'/><category scheme='http://www.blogger.com/atom/ns#' term='Zappos'/><title type='text'>Zappos HTTP Humour</title><content type='html'>I've got to love a company that puts humour in their HTTP headers where it will be seen by almost no one.&amp;nbsp; I saw it!&lt;br /&gt;&lt;blockquote&gt;HTTP/1.1 200 OK&lt;br /&gt;Server: nginx/0.8.31&lt;br /&gt;Content-Type: text/html;charset=UTF-8&lt;br /&gt;Content-Language: en-US&lt;br /&gt;X-Core-Value: &lt;b&gt;10. Be Humble&lt;/b&gt;&lt;br /&gt;X-Recruiting:&lt;b&gt; If you're reading this, maybe you should be working at Zappos instead.&amp;nbsp; Check out jobs.zappos.com&lt;/b&gt;&lt;br /&gt;Cache-Control: max-age=1998&lt;br /&gt;Date: Tue, 30 Mar 2010 10:18:13 GMT&lt;br /&gt;Transfer-Encoding:&amp;nbsp; chunked&lt;br /&gt;Connection: keep-alive&lt;br /&gt;Connection: Transfer-Encoding&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5894461110622240119-2983735910418693774?l=benevolentmachine.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/2983735910418693774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benevolentmachine.blogspot.com/2010/03/zappos-http-humour.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/2983735910418693774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/2983735910418693774'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/2010/03/zappos-http-humour.html' title='Zappos HTTP Humour'/><author><name>Guy</name><uri>http://www.blogger.com/profile/14454669083613476440</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_yGR1NJWLsZA/TB8LSO0UCSI/AAAAAAAAEy0/gdooQwVeCxs/s1600-R/827436cc791e4c35bc15526648f91672_160x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5894461110622240119.post-2192772723351670606</id><published>2010-03-30T18:12:00.001-07:00</published><updated>2010-03-30T18:29:11.420-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='jabber'/><category scheme='http://www.blogger.com/atom/ns#' term='zabbix'/><category scheme='http://www.blogger.com/atom/ns#' term='xmpp4r'/><category scheme='http://www.blogger.com/atom/ns#' term='gtalk'/><title type='text'>Writing a Custom Zabbix Media Script for Google Talk</title><content type='html'>&lt;a href="http://www.zabbix.com/"&gt;Zabbix &lt;/a&gt;includes out-of-the box support for sending alerts by jabber,  which is great.&amp;nbsp; I've never been able to get it to work on the Google  Talk network, and it from what I've read, others have the same problem.  In Zabbix terminology, 'media' are notification methods, like email,  twitter and jabber.&amp;nbsp; Fortunately Zabbix lets you add custom media via  scripts, so we can replace the built-in jabber with one that works with  gtalk.&lt;br /&gt;&lt;br /&gt;I found the &lt;a href="http://www.zabbix.com/documentation/"&gt;Zabbix documentation&lt;/a&gt; on this a bit  thin on this subject.&amp;nbsp; The key things you need to know to write a custom  media script are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The script &lt;i&gt;must &lt;/i&gt;be stored in the  script path you specified in the configuration file:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: x-small;"&gt;AlertScriptsPath=/home/zabbix/zabbix_server/scripts/&lt;/span&gt; &lt;br /&gt;You  cannot, it seems, provide a fully-qualified path to an arbitrary  file  location.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The arguments passed to the script are, in order: &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;recipient - ie the email address or phone number&lt;/li&gt;&lt;li&gt;subject - text defined by the triggered action&lt;/li&gt;&lt;li&gt;message - text defined by the triggered action&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;I'm using ruby for the jabber script, with the &lt;a href="http://home.gna.org/xmpp4r/"&gt;xmpp4r&lt;/a&gt; gem. The script needs to be modified to insert the username and password  of a Google Talk account you create for zabbix.&amp;nbsp; You will also need to  add the zabbix user to your contact list so it has permission to contact  you.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small;"&gt;#!/usr/bin/ruby&lt;br /&gt;require 'rubygems'&lt;br /&gt;require 'xmpp4r'&lt;br /&gt;&lt;br /&gt;to = ARGV[0]&lt;br /&gt;subject = ARGV[1] # not used&lt;br /&gt;message = ARGV[2]&lt;br /&gt;&lt;br /&gt;username = 'zabbix@somedomain.com'&lt;br /&gt;password = 'somepassword'&lt;/span&gt;&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;host = 'talk.google.com'&lt;br /&gt;resource = 'Zabbix'&lt;br /&gt;port = 5222&lt;br /&gt;&lt;br /&gt;#Jabber::debug = true # Uncomment this for verbose logging&lt;br /&gt;jid = Jabber::JID::new("#{username}/#{resource}")&lt;br /&gt;&lt;br /&gt;cl = Jabber::Client::new(jid)&lt;br /&gt;cl.connect(host, port)&lt;br /&gt;cl.auth(password)&lt;br /&gt;&lt;br /&gt;# Create a message&lt;br /&gt;m = Jabber::Message::new(to, message)&lt;br /&gt;&lt;br /&gt;# Send it&lt;br /&gt;cl.send m&lt;/span&gt;&lt;/blockquote&gt;You still need to configure this new  medium in Zabbix, configure the medium for each user, and add this  medium for notification to the appropriate actions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5894461110622240119-2192772723351670606?l=benevolentmachine.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/2192772723351670606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benevolentmachine.blogspot.com/2010/03/writing-custom-zabbix-media-script-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/2192772723351670606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/2192772723351670606'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/2010/03/writing-custom-zabbix-media-script-for.html' title='Writing a Custom Zabbix Media Script for Google Talk'/><author><name>Guy</name><uri>http://www.blogger.com/profile/14454669083613476440</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_yGR1NJWLsZA/TB8LSO0UCSI/AAAAAAAAEy0/gdooQwVeCxs/s1600-R/827436cc791e4c35bc15526648f91672_160x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5894461110622240119.post-1749323116084115694</id><published>2010-03-18T18:41:00.000-07:00</published><updated>2010-03-21T18:39:18.728-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='gem'/><title type='text'>"Operation not permitted" when installing Ruby gems</title><content type='html'>I love the &lt;a href="http://rubygems.org/"&gt;ruby gem system&lt;/a&gt;.  I recently built a runtime  dependency-following gem installer, and found the gem system incredibly  versatile and extensible.   One tiny complaint is that it barfs  installing user-local gems if they include native code.  The installer  tries to chown the file, and the install fails with an error like this:&lt;br /&gt;&lt;blockquote  style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;install:  /home/guy/.gem/ruby/1.8/gems/zipruby-0.3.6/lib/zipruby.so: chown/chgrp:  Operation not permitted&lt;br /&gt;*** Error code 71&lt;/span&gt;&lt;/blockquote&gt;Installing  as root works fine, but sometimes I do not want gems to have global  visibility.  The solution is easy, but not well documented.  If the  environment variable RB_USER_INSTALL is set, the installer will skip the  chown step.  In csh, you can do this:&lt;br /&gt;&lt;blockquote  style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;&gt; setenv RB_USER_INSTALL&lt;br /&gt;&gt; gem install zipruby&lt;/span&gt;&lt;/blockquote&gt;If  you are invoking the installer from ruby code, you can set the  environment variable like this:&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;blockquote&gt;ENV['RB_USER_INSTALL'] = 'true'&lt;br /&gt;Gem::GemRunner.new.run(args)&lt;br /&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5894461110622240119-1749323116084115694?l=benevolentmachine.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/1749323116084115694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benevolentmachine.blogspot.com/2010/03/operation-not-permitted-when-installing.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/1749323116084115694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/1749323116084115694'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/2010/03/operation-not-permitted-when-installing.html' title='&quot;Operation not permitted&quot; when installing Ruby gems'/><author><name>Guy</name><uri>http://www.blogger.com/profile/14454669083613476440</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_yGR1NJWLsZA/TB8LSO0UCSI/AAAAAAAAEy0/gdooQwVeCxs/s1600-R/827436cc791e4c35bc15526648f91672_160x160.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5894461110622240119.post-2749915821797498336</id><published>2010-03-17T21:28:00.000-07:00</published><updated>2010-03-21T18:38:10.107-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='utf-8'/><category scheme='http://www.blogger.com/atom/ns#' term='nokogiri'/><category scheme='http://www.blogger.com/atom/ns#' term='unicode'/><category scheme='http://www.blogger.com/atom/ns#' term='xpath'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML'/><title type='text'>Nokogiri, XPath and UTF-8</title><content type='html'>Here's an interesting little feature of the &lt;a href="http://nokogiri.org/"&gt;Nokogiri HTML parser&lt;/a&gt; for Ruby that caused me some pain.  It turns out that when you retrieve a string from a Nokogiri document using the xpath functions, the result is converted to UTF-8, regardless of the encoding of the source document.  If you do not realise this and use iconv to re-map it to UTF-8, you will get garbage.&lt;br /&gt;&lt;br /&gt;Consider this test:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;def get_html(charset, code)&lt;br /&gt;html = "&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;meta http-equiv=\"content-type\" content=\"text/html; charset=#{charset}\"&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;div id=\"1\"&amp;gt;&lt;br /&gt; Test #{code};&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;"&lt;br /&gt;dom = Nokogiri::HTML.parse(html)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;# extract from a utf-8 html page&lt;br /&gt;code = "&amp;amp;#xf6;"&lt;br /&gt;charset = 'utf-8'&lt;br /&gt;dom = get_html(charset, code)&lt;br /&gt;PP.pp dom.search('//div').first.text&lt;br /&gt;&lt;br /&gt;# extract from a cp1122 html page&lt;br /&gt;code = "\x6a"&lt;br /&gt;charset = 'CP1122'&lt;br /&gt;html = get_html(charset, code)&lt;br /&gt;PP.pp dom.search('//div').first.text&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;I found that both of the tests produce the same output:&lt;br /&gt;&lt;blockquote  style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;"\n      Test \303\266;\n    "&lt;/span&gt;&lt;/blockquote&gt;According to &lt;a href="http://www.eki.ee/letter/chardata.cgi?ucode=f6"&gt;the letter database&lt;/a&gt;, \303\266 is the correct octal representation for this character in utf-8.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5894461110622240119-2749915821797498336?l=benevolentmachine.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/2749915821797498336/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benevolentmachine.blogspot.com/2010/03/nokogiri-xpath-and-utf-8.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/2749915821797498336'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/2749915821797498336'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/2010/03/nokogiri-xpath-and-utf-8.html' title='Nokogiri, XPath and UTF-8'/><author><name>Guy</name><uri>http://www.blogger.com/profile/14454669083613476440</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_yGR1NJWLsZA/TB8LSO0UCSI/AAAAAAAAEy0/gdooQwVeCxs/s1600-R/827436cc791e4c35bc15526648f91672_160x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5894461110622240119.post-2974521570512088040</id><published>2010-03-16T18:56:00.000-07:00</published><updated>2010-03-21T18:41:08.071-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zabbix'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><title type='text'>Adding groups of items to the Zabbix Agent</title><content type='html'>It can be a bit tedious adding custom items to &lt;a href="http://www.zabbix.com/"&gt;Zabbix&lt;/a&gt;.  Until now I've been adding separate entries to the agent configuration file like this:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;UserParameter=custom.tracker.backlog,/home/zabbix/bin/&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;custom&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;_plugin tracker.backlog&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;UserParameter=&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;custom&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;.item.count,/home/zabbix/bin/&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;custom&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;_plugin item.count&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;UserParameter=&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;custom&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;.event.count,/home/zabbix/bin/&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;custom&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;_plugin event.count&lt;/span&gt;&lt;/blockquote&gt;It turns out that Zabbix has a configuration syntax that greatly simplifies this.  As an added bonus, you don't have to restart the zabbix agent when you add new items.&lt;br /&gt;&lt;br /&gt;Replace the above lines in zabbix_agentd.conf with a line like this:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;UserParameter=custom[*],/home/zabbix/bin/custom_plugin $1&lt;/span&gt;&lt;/blockquote&gt;Then, in the Zabbix item configuration, identify each of the items supported by your script.  In my case they are named custom[item.count], custom[event.count] and custom[tracker_backlog].&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5894461110622240119-2974521570512088040?l=benevolentmachine.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benevolentmachine.blogspot.com/feeds/2974521570512088040/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benevolentmachine.blogspot.com/2010/03/adding-groups-of-items-to-zabbix-agent.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/2974521570512088040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5894461110622240119/posts/default/2974521570512088040'/><link rel='alternate' type='text/html' href='http://benevolentmachine.blogspot.com/2010/03/adding-groups-of-items-to-zabbix-agent.html' title='Adding groups of items to the Zabbix Agent'/><author><name>Guy</name><uri>http://www.blogger.com/profile/14454669083613476440</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_yGR1NJWLsZA/TB8LSO0UCSI/AAAAAAAAEy0/gdooQwVeCxs/s1600-R/827436cc791e4c35bc15526648f91672_160x160.jpg'/></author><thr:total>0</thr:total></entry></feed>
