<?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>shallop.com</title> <atom:link href="http://shallop.com/feed/" rel="self" type="application/rss+xml" /><link>http://shallop.com</link> <description>Striving for Zero State Because Entropy Requires No Maintenance</description> <lastBuildDate>Fri, 18 May 2012 17:24:49 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=</generator> <item><title>Apple Mail Encryption with GPGMail and OpenPGP</title><link>http://shallop.com/2012/05/apple-mail-encryption-with-gpgmail-and-openpgp/</link> <comments>http://shallop.com/2012/05/apple-mail-encryption-with-gpgmail-and-openpgp/#comments</comments> <pubDate>Fri, 18 May 2012 16:50:55 +0000</pubDate> <dc:creator>Micheal Shallop</dc:creator> <category><![CDATA[Technical]]></category> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[advice]]></category> <category><![CDATA[apple]]></category> <category><![CDATA[email]]></category> <category><![CDATA[encryption]]></category> <category><![CDATA[gpg]]></category> <category><![CDATA[gpgmail]]></category> <category><![CDATA[gpgtools]]></category> <category><![CDATA[help]]></category> <category><![CDATA[how-to]]></category> <category><![CDATA[mail]]></category> <category><![CDATA[openphp]]></category> <category><![CDATA[opinion]]></category> <category><![CDATA[privacy]]></category> <category><![CDATA[technical]]></category> <category><![CDATA[tutorial]]></category> <guid
isPermaLink="false">http://shallop.com/?p=522</guid> <description><![CDATA[I&#8217;ve dabbled with encryption several times over the past few decades, never really getting serious about it.  It started when, in college, I would see that the faculty in the CS department had these weird signature blocks appended to the their USEnet posts containing something called a public key. This is like setting a can [...]]]></description> <content:encoded><![CDATA[<img
style='float: left; margin-right: 10px; border: none;' src='http://www.gravatar.com/avatar.php?gravatar_id=ab05b85b6786c70c1e1db98e219f015f&amp;default=http://www.shallop.com/wp-content/uploads/avatar_2868.jpg' alt='No Gravatar' width=40 height=40/><div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fshallop.com%2F2012%2F05%2Fapple-mail-encryption-with-gpgmail-and-openpgp%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fshallop.com%2F2012%2F05%2Fapple-mail-encryption-with-gpgmail-and-openpgp%2F&amp;source=mshallop&amp;style=normal&amp;b=2" height="61" width="50" /><br
/> </a></div><p><img
class="alignleft size-full wp-image-523" style="margin: 5px;" title="images-2" src="http://shallop.com/wp-content/uploads/2012/05/images-2.jpeg" alt="" width="204" height="204" /></p><p>I&#8217;ve dabbled with encryption several times over the past few decades, never really getting serious about it.  It started when, in college, I would see that the faculty in the CS department had these weird signature blocks appended to the their USEnet posts containing something called a <em>public key</em>.</p><p>This is like setting a can of lighter fluid and box of blue-tip matches in front of a 10 year-old boy &#8212; irresistible.</p><p>What I found in the later years is that using encryption for email is a lot like being one of the early adopters of the telephone.  Now that I have one, who am I going to call?  My family certainly doesn&#8217;t use encryption in their email&#8230;those that have discovered email anyway.</p><p>Co-workers aren&#8217;t likely to invest the time and effort into encryption simply because we&#8217;re all too busy with work to be playing spy-games with our de-coder rings.</p><p>And, Dorothy, we&#8217;re not in Academia anymore where, I imagine, it&#8217;s really in use.  Closeted anarchists posting semi-heretical Berkeley-esqe rants against the Proletariat and all that.</p><p>And then there&#8217;s the whole nouveau post-9/11 trend of &#8220;Guilty until Proven Innocent&#8221; thing happening.  I imagine some fedora-capped DHS agent squinting at me in a menacing fashion while I try to reason a plausible excuse for being so brazen as to <em>need</em> encryption for my emails in the first place&#8230;</p><p>So, at this point, let&#8217;s assume that, like me, you&#8217;re willing to whack the hornet&#8217;s nest with a stick and use encryption for your emails and that you actually have someone on the other end willing to dust-off the de-coder ring and play with you.  We&#8217;ll also assume that you know what PGP, GPG and OpenPGP actually are, and that you know how basic public-key encryption works.  (If not, leave comments to this article and I will do a future article explaining same.)</p><p><em>Standard Disclaimer: I am providing this tutorial as a hands-on, learn-with-me type of tutorial.  I am not an expert, nor do I pretend to claim anything other than neophyte status when it comes to encryption.  I do not advocate, support, or intend for you to use this, or any, technology as a means to intentionally bending, fracturing, or breaking laws in one or more jurisdictions.  MY only intent is to share what I&#8217;ve recently learned with you and to have some fun.</em></p><p>OK &#8211; that crap out of the way, let&#8217;s get started.  First, as the title implies, this set-up is for Apple Mail under OS X Lion.  The release of the OS I&#8217;m currently working on is 10.7.4.</p><p><span
style="background-color: #ccffcc;"><a
href="http://www.gpgtools.org/installer/index.html"><span
style="background-color: #ccffcc;">Download</span></a> and install the GPGTools utility  (Version 2012.03.18 as of this writing.)</span></p><p>Although this article is for Apple mail, the GPGTools utility includes support for Enigmail in Thunderbird 7.  When you launch the installation utility, you&#8217;ll be presented with a list of packages to install.  I installed all packages.</p><p>Once the install has been completed, you&#8217;ll see a little dialog box appear on your desk top telling you the installation was successful, and would you like to read the Quickstart Tutorial?  This would be a good thing to do because I am not going to walk you thought the next steps in any great detail.  This reference, however, does.  With pictures.  So&#8230; go there and follow the installation step to:</p><p><span
style="background-color: #ccffcc;">Generate a key</span></p><p>You will generate a public and a private key.  Anyone with whom you wish to exchange encrypted email with must also have done the same.  They&#8217;re called <em>public</em> and <em>private </em>keys for a reason.  One you share with the public and one you do not.  Key, using the nomenclature, are stored on what&#8217;s called a <em>keyring</em>.  There are public and private key-rings.  GPGTools refers to key-rings as <em> keychains</em> - these are one and the same things.</p><p><span
style="background-color: #ffff00;">Please note that for whichever email account you&#8217;re going to use to generate a key-pair for, that account must already exist in Apple mail.  The email address is case-sensitive so make sure you type it in exactly as it is stored in Apple Mail &#8212; otherwise, your encryption will not work.</span></p><p>Over the years, I have created several key-pairs for various email addresses I have had.  What&#8217;s critically important to remember is this:  write down your pass-phrase.  Also, click on the <em>Advanced options</em> tab, and set an expiration date (a couple of years is fine and 4-years is the current default &#8211; point being: set an expiration date) for your keys.  That way if, after a few years, you return to a previous email account address, and you&#8217;ve certainly forgotten your passphrase from lack of use, then you&#8217;ll still be able to generate a new key pair if the old one has expired.  To remove a key pair, most public key rings require you to enter your passphrase.  This is known as a conundrum.</p><p>Once you&#8217;ve created your passphrase and uploaded your key, and you can see your new key in your keychain, open Apple Mail.  Send an email to</p><p><a
href="http://shallop.com/wp-content/uploads/2012/05/encryptedmessage.jpg"><img
class="size-medium wp-image-533 alignright" style="border-width: 1px; border-color: black; border-style: solid; margin: 5px;" title="encryptedmessage" src="http://shallop.com/wp-content/uploads/2012/05/encryptedmessage-300x83.jpg" alt="" width="300" height="83" /></a></p><p>the email address you&#8217;ve just created (I know&#8230;) and you should see two buttons appear in the lower-right corner of the header bar as shown in the image on the right.</p><p>The two buttons, as shown above, allow you to either <em>sign</em> or <em>encrypt</em> your mail message.</p><p
style="text-align: left;"><em>Signing</em> your email is flagging the email to the recipient assuring them that it was actually you who sent the mail.  In order to sign an email, OpenPGP has to have access to your private key. (You did keep your private key private, right?)  Since you&#8217;re the only one, presumably, with access to your private key, then signing the mail guarantees to the recipient that the mail did come from you.</p><p
style="text-align: left;">The recipient does not need to have your public key, nor do you need to have the recipient&#8217;s public key, to sign an email.  Think of this as the &#8220;certified mail&#8221; from the US Post Office equivalent for email.</p><p
style="text-align: left;">If you have a recipient&#8217;s public key, then you may send them an encrypted email.  The recipient will need to have your public key in order to decrypt and read the email &#8212; this is why we store public keys on public key rings.</p><div
id="wpshdo_1" class="wp-synhighlighter-outer"><div
id="wpshdt_1" class="wp-synhighlighter-expanded"><table
border="0" width="100%"><tr><td
align="left" width="80%"><a
name="#codesyntax_1"></a><a
id="wpshat_1" class="wp-synhighlighter-title" href="#codesyntax_1"  onClick="javascript:wpsh_toggleBlock(1)" title="Click to show/hide code block">Source code</a></td><td
align="right"><a
href="#codesyntax_1" onClick="javascript:wpsh_code(1)" title="Show code only"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a
href="#codesyntax_1" onClick="javascript:wpsh_print(1)" title="Print code"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a
href="http://shallop.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div
id="wpshdi_1" class="wp-synhighlighter-inner" style="display: block;"><pre class="text" style="font-family:monospace;">-----BEGIN PGP SIGNATURE-----
&nbsp;
Version: GnuPG/MacGPG2 v2.0.18 (Darwin)
&nbsp;
iQEcBAEBAgAGBQJPtnyiAAoJEC4S4zGLhwvBFNMH/1Yoh59etAcYZpAhZ+htpd81
QzZWDxOR2PeXtPkY3GWl4vdW7GABJ9ysl8vpdErsDtXs6LEVZXag5mV6CGTDNXmm
pdozUJCgNwbHTgoIUdjinmAXLR+4pYSfALTB1S2qpxzMpykBkR7SMuPm3+0LC77/
dwnsSVx5CNtJd8cPoPjwXJ6zaStJCNK+H17MItS5kpw3MqMU35qZdNCDV6ehhA8j
FmTyFoh1TeTmuBrNECWz9z3KniG6SWVl3K21LmS8PQExeHq8qcHGBz5yK2YhoW/w
bn4PIyHaUiXKQTNhYBSd1DrCPUWJKDJ+VCKQ0L97aUPeVPQBI14jsFOgc1dwUjs=
=xfmB
-----END PGP SIGNATURE-----</pre></div></div><p>That&#8217;s pretty much it &#8212; once you send a signed an encrypted mail, you can rest assured that (hopefully) your emails are safe from casually-prying eyes as they&#8217;re no longer being sent in clear-text across the ether sphere.</p><p>Here&#8217;s the raw-text (what&#8217;s sent out over the ether) of an encrypted email message:</p><p>&nbsp;</p><div
id="wpshdo_2" class="wp-synhighlighter-outer"><div
id="wpshdt_2" class="wp-synhighlighter-expanded"><table
border="0" width="100%"><tr><td
align="left" width="80%"><a
name="#codesyntax_2"></a><a
id="wpshat_2" class="wp-synhighlighter-title" href="#codesyntax_2"  onClick="javascript:wpsh_toggleBlock(2)" title="Click to show/hide code block">Source code</a></td><td
align="right"><a
href="#codesyntax_2" onClick="javascript:wpsh_code(2)" title="Show code only"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a
href="#codesyntax_2" onClick="javascript:wpsh_print(2)" title="Print code"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a
href="http://shallop.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div
id="wpshdi_2" class="wp-synhighlighter-inner" style="display: block;"><pre class="text" style="font-family:monospace;">Return-Path: &lt;mshallop@gmail.com&gt;
&nbsp;
Received: from [192.168.0.2] (c-50-136-203-107.hsd1.ca.comcast.net. [50.136.203.107])
by mx.google.com with ESMTPS id qu6sm6794406pbc.36.2012.05.18.09.54.57
(version=TLSv1/SSLv3 cipher=OTHER);
Fri, 18 May 2012 09:54:58 -0700 (PDT)
Content-Type: multipart/encrypted; boundary=&quot;Apple-Mail=_4C5344B9-76FE-43EF-8620-073841EBF944&quot;; protocol=&quot;application/pgp-encrypted&quot;;
Subject: test both
Mime-Version: 1.0 (Apple Message framework v1278)
X-Pgp-Agent: GPGMail 201 (a30)
From: Micheal Shallop &lt;mshallop@gmail.com&gt;
Date: Fri, 18 May 2012 09:54:56 -0700
Content-Transfer-Encoding: 7bit
Message-Id: &lt;407C94BA-32A1-4930-B9F6-BBFE7900D213@gmail.com&gt;
Content-Description: OpenPGP encrypted message
To: Micheal Shallop &lt;mshallop@gmail.com&gt;
X-Mailer: Apple Mail (2.1278)
&nbsp;
This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)
--Apple-Mail=_4C5344B9-76FE-43EF-8620-073841EBF944
Content-Transfer-Encoding: 7bit
Content-Type: application/pgp-encrypted
Content-Description: PGP/MIME Versions Identification
&nbsp;
Version: 1
&nbsp;
--Apple-Mail=_4C5344B9-76FE-43EF-8620-073841EBF944
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename=encrypted.asc
Content-Type: application/octet-stream;
name=encrypted.asc
Content-Description: OpenPGP encrypted message
&nbsp;
-----BEGIN PGP MESSAGE-----
Version: GnuPG/MacGPG2 v2.0.18 (Darwin)
&nbsp;
hQEMAy4S4zGLhwvBAQf/YX1vGFhG0CLd7UU79fjHd4/nIHH9DVVsi8oqsmIwBNpl
zXvDZf3+uw3B7Shk3bls1fHcUdU8LZprY+HbQVZlh7IiGZ28K67rNIHKUtwuoX2I
DpZcLdRPGn1iGi7TNRs/3Fn3fjCCT15uVAbZZRvR1G3XqUc+//3TstCMTaNtg5Rl
KZbKnnrOaIt/OAou7BFCLQgGKAAIa3m/gFHEQxxLVaAQ3JISeX4/UZ7YlXAj5SYp
juVRKfekmjpoFoM4erf0Jjaw63lSjAZWXJi1m6IY8uSkzQZRUwANMYE577mBiZhw
d1kIBJfBlxWjUOK6FYV3bDZFjc2Fn2WM4+tEloOrcNLpASNVPOh332341GjxwVAg
USYLkh1Co7yqaQ1c830CD58XxmYsR/x0B8etL1bYQtZDJYITMa649tYCYtrAvHSw
GsgwDD67yaICruIJqwPAtz5+fkoF9xnlltz0UTUSsmzrlGkdbkHSnVrvOdgbvJEz
60UM1p7idKEcR5SCkNuLD9hYJaD/C7qRhyxYfjyjPlwtSSb9aSY+TBa0t/lRmPtU
q5N/EHRdm3CmTVqE3eT1IOoRsFibYfRJNJnkqgmVZdoHm/QhTOmuyK1SeBbB3P7F
Lnw7hS6aB7RMISg8rWiPGap+QVO8lzMjIXhd5BDu1Kxkk5dr7FLOC37aSC7X52VT
QcwvYlYPSV5s+ivFk/uKtB8L3k9rHsYHHkP13lli2a9ELy+KTv0SFp0Q8ClaC9Xm
RoWXKQxrTV2wxub4/V0UfSSUfct0mHfTFDltpDPAfaEL/ARgvIUI2SD6WXvfbums
yG2fS4Rr9NHr9bgkZJqt+anNGQOmly7654ecckD+Nj2PtmXnowBOrub91VvXSfKB
TKHZ7xmX9GOnk6qsFZppiXIxDXR9zYeLb5Ks0hCF3XDhXu8DAkS4vbmPm7BIn6fu
N1niCzihe187mJ3bKAj5rLSHpbBrMt/XcbaL+eNz7xIEtpWQjk+8qFUaxl5NxIX1
KtCwLhxUeZUCKHIv/cGOJKPANfdhN2SYHasFJvJ1Jts4us4JJg4rBjH50hiYaQ3W
OhGSQP7kvcKqMzHBhSXBKPpnwBtJ+tkXy5IpeMHUrREpGt39EOO4oiiyRYSrrm2T
GswOJwvv4Z32hreR2eAgfPAXZW3R6MtGA07xN3mqPtV1IO+izegbflVpQEi8Zlq3
KfT/ljoLiDTKdIsrlfIgtgec+G5SH6znO9Kv1IidYg9wtdL6G2bsTP9pCV24bCem
srTw3NDKfTK56Yu1ESQpf0WYMTzpGjzDhyHW86F5ej+jJV2rd4kicxvy0HJXOGbI
iHPvKVVoA7bMvvfVARoMIlqiQ5gzm41+
=z4VQ
-----END PGP MESSAGE-----
&nbsp;
--Apple-Mail=_4C5344B9-76FE-43EF-8620-073841EBF944--</pre></div></div><p>&nbsp;</p><p>Reference Pages and Additional Reading:</p><p><a
href="http://support.gpgtools.org/kb/how-to/first-steps-where-do-i-start-where-do-i-begin">GPGTools First Steps</a><br
/> <a
href="http://chronicle.com/blogs/profhacker/secure-email-in-thunderbird-and-apple-mail-with-gpg/30936">Secure Email in Thunderbird and Apple Mail with GPG</a></p> ]]></content:encoded> <wfw:commentRss>http://shallop.com/2012/05/apple-mail-encryption-with-gpgmail-and-openpgp/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>1Password on Ubuntu 11.10 (Oneiric)</title><link>http://shallop.com/2012/04/1password-on-ubuntu-11-10-oneiric/</link> <comments>http://shallop.com/2012/04/1password-on-ubuntu-11-10-oneiric/#comments</comments> <pubDate>Mon, 23 Apr 2012 19:01:40 +0000</pubDate> <dc:creator>Micheal Shallop</dc:creator> <category><![CDATA[Technical]]></category> <category><![CDATA[11.10]]></category> <category><![CDATA[1password]]></category> <category><![CDATA[access]]></category> <category><![CDATA[chrome]]></category> <category><![CDATA[file]]></category> <category><![CDATA[google]]></category> <category><![CDATA[linux]]></category> <category><![CDATA[oneiric]]></category> <category><![CDATA[tweek]]></category> <category><![CDATA[ubuntu]]></category> <category><![CDATA[uri]]></category> <category><![CDATA[utility]]></category> <category><![CDATA[work-around]]></category> <guid
isPermaLink="false">http://shallop.com/?p=515</guid> <description><![CDATA[First, I apologize for being off-the-grid for so long.  I recently started working for a new company and am deep in the throes of the start-up life.  I started working on this incredibly long article about building the ultimate Ubuntu-based development machine and got kind of lost in the details once I hit about 5,000 [...]]]></description> <content:encoded><![CDATA[<img
style='float: left; margin-right: 10px; border: none;' src='http://www.gravatar.com/avatar.php?gravatar_id=ab05b85b6786c70c1e1db98e219f015f&amp;default=http://www.shallop.com/wp-content/uploads/avatar_2868.jpg' alt='No Gravatar' width=40 height=40/><div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fshallop.com%2F2012%2F04%2F1password-on-ubuntu-11-10-oneiric%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fshallop.com%2F2012%2F04%2F1password-on-ubuntu-11-10-oneiric%2F&amp;source=mshallop&amp;style=normal&amp;b=2" height="61" width="50" /><br
/> </a></div><p><a
href="http://shallop.com/wp-content/uploads/2012/04/1password.png"><img
class="alignleft  wp-image-516" style="border-image: initial; border-width: 1px; border-color: black; border-style: solid; margin: 5px;" title="1password" src="http://shallop.com/wp-content/uploads/2012/04/1password.png" alt="" width="387" height="164" /></a></p><p>First, I apologize for being off-the-grid for so long.  I recently started working for a new company and am deep in the throes of the start-up life.  I started working on this incredibly long article about building the ultimate Ubuntu-based development machine and got kind of lost in the details once I hit about 5,000 words.  It&#8217;s a <em>very</em> long article.</p><p>I&#8217;ve also been incredibly busy in mongo-development and have learned an entire catalog of new tips and tricks that I can&#8217;t wait to share &#8212; just trying to find the time to document everything!</p><p>So, in the meantime, I thought I&#8217;d share this little useful tip.</p><p>Recently, I&#8217;ve moved my development platform over to Ubuntu 11.10 &#8212; out of necessity rather than choice &#8212; and have been learning a lot about making the transition from the Mac (where we have Linux smugness without the administrative overhead) to to a more hands-on platform.</p><p>I initially chose Ubuntu because I wanted something a little more automated that RedHat or CentOS when it came to system updates and configuration &#8212; I need concentrate of developing software, not administrating the development platform.  Ubuntu fits this requirement quite nicely.</p><p>In making the switch over from Mac to Ubuntu, most of my development tools ported straight across &#8212; PHPStorm, Chrome, Xdebug.  Other tools are native such as mongo, apache2, mysql, and PHP5.  And still other tools are facsimiles of the Mac utilities such as guake, evolution, keepassX and others.</p><p>The one tool/utility I miss the most, however, is 1Password from AgileBits software.  Seeing how they have absolutely no plans for porting their platform over to Linux, I opted to use KeepassX as my password manager program.  Not as fancy and no browser integration, but it gets the j0b done.  And, of course, I can store my key files in the cloud using Ubuntu-One.</p><p>Until I discovered <a
href="http://help.agilebits.com/1Password_Windows/onepasswordanywhere.html">1PasswordAnywhere</a>.</p><p>1PasswordAnywhere is a web-based version of 1Password that gives you access to your accounts via a web portal of sorts.</p><p>I say &#8220;of sorts&#8221; &#8230; while you&#8217;re loading an HTML page into your browser, you&#8217;re doing so as a <em>file</em> request and not as a <em>http</em> request.  The difference is that your &#8220;secure&#8221; data is served locally to your browser across your file system and not over the wire via the internet.</p><p>The first thing to do is locate your 1Password storage.  For most of us, this should be on <a
href="https://www.dropbox.com/">dropbox</a>.</p><div
class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div
class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span
style="color: #666666; font-style: italic;"># sudo apt-get install nautilus-dropbox</span></div></div><p><a
href="http://shallop.com/wp-content/uploads/2012/04/dropbox.png"><img
class="alignright  wp-image-517" style="border-image: initial; border-width: 1px; border-color: black; border-style: solid; margin: 5px;" title="dropbox" src="http://shallop.com/wp-content/uploads/2012/04/dropbox.png" alt="" width="314" height="125" /></a>Open your dropbox folder from the top-menu and select your 1Password folder.</p><p>When you open the 1Password folder you want to look for the file <em>1Password.html</em>.</p><p>Don&#8217;t double-click on this file yet because, if you do, you&#8217;re going to see this error message shown in the image below:</p><p><a
href="http://shallop.com/wp-content/uploads/2012/04/1PAnywhereFailedToLoadFile.jpg"><img
class="size-medium wp-image-518 alignleft" style="border-image: initial; border-width: 1px; border-color: black; border-style: solid; margin: 5px;" title="1PAnywhereFailedToLoadFile" src="http://shallop.com/wp-content/uploads/2012/04/1PAnywhereFailedToLoadFile-300x115.jpg" alt="" width="300" height="115" /></a>This error message (and sorry if this layout is a bit confusing) requires that you disable a setting in your browser (and I&#8217;m assuming you&#8217;re using Chrome) for the html page to be displayed correctly.</p><p>By default, file:// URIs cannot read other file:// URIs.  You can disable this by launching Chrome from the command line with the option: &#8211;allow-file-access-from-files as shown below in the code block:</p><div
class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div
class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span
style="color: #666666; font-style: italic;"># nohup google-chrome --allow-file-access-from-files 2&amp;gt;&amp;amp;1 &amp;amp;</span></div></div><p>When you start Chrome with this switch, and you double-click on your <em>1Password.html</em> file, you should see 1PasswordAnywhere displayed successfully in your browser window!</p><p>Couple of notes &#8211;</p><ul><li>1PasswordAnywhere locks itself after a minute requiring your master password to unlock</li><li>There&#8217;s still no browser extension allowing you to auto-submit your credentials to a site</li></ul><p>What you do get, however, is access to all of your 1Password data that you&#8217;ve saved from your other devices.  For me, personally, this is substantial and well worth the effort of loading Chrome from the command line.</p><p>It&#8217;s not that I have anything against KeepassX, mind you.  It&#8217;s just that I don&#8217;t want the redundancy and synchronization issues of managing hundreds of logins and other account data.</p><p>I promise that I&#8217;ll get the uber-article out on making the ultimate development platform on Ubuntu soon &#8211; I&#8217;m waiting until the 12.04 release which should be dropping within a week or two.</p><p>Hope this helps!</p> ]]></content:encoded> <wfw:commentRss>http://shallop.com/2012/04/1password-on-ubuntu-11-10-oneiric/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>BuddyPress &#8212; Pages failing to load (404)</title><link>http://shallop.com/2012/01/buddypress-pages-failing-to-load-404/</link> <comments>http://shallop.com/2012/01/buddypress-pages-failing-to-load-404/#comments</comments> <pubDate>Fri, 20 Jan 2012 22:46:45 +0000</pubDate> <dc:creator>Micheal Shallop</dc:creator> <category><![CDATA[Technical]]></category> <category><![CDATA[404]]></category> <category><![CDATA[allowoverride]]></category> <category><![CDATA[apache]]></category> <category><![CDATA[buddypress]]></category> <category><![CDATA[conf.d]]></category> <category><![CDATA[configuration]]></category> <category><![CDATA[error]]></category> <category><![CDATA[followsymlinks]]></category> <category><![CDATA[found]]></category> <category><![CDATA[install]]></category> <category><![CDATA[mod_rewrite]]></category> <category><![CDATA[not]]></category> <category><![CDATA[wordpress]]></category> <guid
isPermaLink="false">http://shallop.com/?p=497</guid> <description><![CDATA[I was going insane working on a buddypress install for our intranet&#8217;s tech-blog because every page I attempted to load into WordPress following the Buddypress install resulted in a 404 error. Eventually, after several (re)installs, I tracked the issue down to a mod_rewrite issue.  Because I&#8217;m using sub-directories through a &#60;directory&#62; tag in my apache [...]]]></description> <content:encoded><![CDATA[<img
style='float: left; margin-right: 10px; border: none;' src='http://www.gravatar.com/avatar.php?gravatar_id=ab05b85b6786c70c1e1db98e219f015f&amp;default=http://www.shallop.com/wp-content/uploads/avatar_2868.jpg' alt='No Gravatar' width=40 height=40/><div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fshallop.com%2F2012%2F01%2Fbuddypress-pages-failing-to-load-404%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fshallop.com%2F2012%2F01%2Fbuddypress-pages-failing-to-load-404%2F&amp;source=mshallop&amp;style=normal&amp;b=2" height="61" width="50" /><br
/> </a></div><p><img
class="alignleft  wp-image-498" style="margin: 5px;" title="featured_buddypress" src="http://shallop.com/wp-content/uploads/2012/01/featured_buddypress.jpg" alt="" width="123" height="126" /></p><p>I was going insane working on a buddypress install for our intranet&#8217;s tech-blog because every page I attempted to load into WordPress following the Buddypress install resulted in a 404 error.</p><p>Eventually, after several (re)installs, I tracked the issue down to a mod_rewrite issue.  Because I&#8217;m using sub-directories through a &lt;directory&gt; tag in my apache configuration, my .htaccess file looks different from the normal WP/BP installations:</p><div
id="wpshdo_3" class="wp-synhighlighter-outer"><div
id="wpshdt_3" class="wp-synhighlighter-expanded"><table
border="0" width="100%"><tr><td
align="left" width="80%"><a
name="#codesyntax_3"></a><a
id="wpshat_3" class="wp-synhighlighter-title" href="#codesyntax_3"  onClick="javascript:wpsh_toggleBlock(3)" title="Click to show/hide code block">Source code</a></td><td
align="right"><a
href="#codesyntax_3" onClick="javascript:wpsh_code(3)" title="Show code only"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a
href="#codesyntax_3" onClick="javascript:wpsh_print(3)" title="Print code"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a
href="http://shallop.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div
id="wpshdi_3" class="wp-synhighlighter-inner" style="display: block;"><pre class="bash" style="font-family:monospace;"><span class="co0"># BEGIN WordPress</span>
<span class="sy0">&lt;</span>IfModule mod_rewrite.c<span class="sy0">&gt;</span>
    RewriteEngine On
    RewriteBase <span class="sy0">/</span>techblog<span class="sy0">/</span>
    RewriteRule ^index\.php$ - <span class="br0">&#91;</span>L<span class="br0">&#93;</span>
    RewriteCond <span class="sy0">%</span><span class="br0">&#123;</span>REQUEST_FILENAME<span class="br0">&#125;</span> <span class="sy0">!</span>-f
    RewriteCond <span class="sy0">%</span><span class="br0">&#123;</span>REQUEST_FILENAME<span class="br0">&#125;</span> <span class="sy0">!</span>-d
    RewriteRule . <span class="sy0">/</span>techblog<span class="sy0">/</span>index.php <span class="br0">&#91;</span>L<span class="br0">&#93;</span>
<span class="sy0">&lt;/</span>IfModule<span class="sy0">&gt;</span></pre></div></div><p>I kept mucking about in this file thinking that there was something in my configuration that was incorrect causing me to 404 whenever I left the main page.</p><p>My boss inserted an error into the .htaccess file and, when we reloaded the page, we didn&#8217;t generate a 500 error &#8212; the site&#8217;s main page loaded, but the sub-pages were still broken.  That we injected an intentional error and the page loaded indicated that mod_rewrite was ignoring .htaccess and so the problem had to be further up in the food chain.</p><p>My &lt;directory&gt; alias was incorrect in two places:</p><div
id="wpshdo_4" class="wp-synhighlighter-outer"><div
id="wpshdt_4" class="wp-synhighlighter-expanded"><table
border="0" width="100%"><tr><td
align="left" width="80%"><a
name="#codesyntax_4"></a><a
id="wpshat_4" class="wp-synhighlighter-title" href="#codesyntax_4"  onClick="javascript:wpsh_toggleBlock(4)" title="Click to show/hide code block">Source code</a></td><td
align="right"><a
href="#codesyntax_4" onClick="javascript:wpsh_code(4)" title="Show code only"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a
href="#codesyntax_4" onClick="javascript:wpsh_print(4)" title="Print code"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a
href="http://shallop.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div
id="wpshdi_4" class="wp-synhighlighter-inner" style="display: block;"><pre class="bash" style="font-family:monospace;">Alias <span class="sy0">/</span>techblog <span class="sy0">/</span>var<span class="sy0">/</span>www<span class="sy0">/</span>techblog
&nbsp;
<span class="sy0">&lt;</span>Directory <span class="st0">&quot;/var/www/techblog&quot;</span><span class="sy0">&gt;</span>
    Options Indexes MultiViews
    Order allow,deny
    Allow from all
<span class="sy0">&lt;/</span>Directory<span class="sy0">&gt;</span></pre></div></div><p>First, I learned that you have to <em>explicitly</em> state <strong>AllowOverride All</strong> &#8211; the default setting was:<strong> AllowOverride None</strong>.  Which tells Apache to ignore the .htaccess file.  Deleting that line from my configuration did not have the anticipated effect of telling Apache to <em>not</em> ignore the .htaccess file; you must explicitly state <strong>AllowOverride All</strong>.</p><p>The second thing I learned was that you have to add <strong>FollowSymlinks</strong> to the <em>Options</em> directive so that your permalinks will be honored.  My configuration file now looks like this:</p><div
id="wpshdo_5" class="wp-synhighlighter-outer"><div
id="wpshdt_5" class="wp-synhighlighter-expanded"><table
border="0" width="100%"><tr><td
align="left" width="80%"><a
name="#codesyntax_5"></a><a
id="wpshat_5" class="wp-synhighlighter-title" href="#codesyntax_5"  onClick="javascript:wpsh_toggleBlock(5)" title="Click to show/hide code block">Source code</a></td><td
align="right"><a
href="#codesyntax_5" onClick="javascript:wpsh_code(5)" title="Show code only"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a
href="#codesyntax_5" onClick="javascript:wpsh_print(5)" title="Print code"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a
href="http://shallop.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div
id="wpshdi_5" class="wp-synhighlighter-inner" style="display: block;"><pre class="bash" style="font-family:monospace;">Alias <span class="sy0">/</span>techblog <span class="sy0">/</span>var<span class="sy0">/</span>www<span class="sy0">/</span>techblog
&nbsp;
<span class="sy0">&lt;</span>Directory <span class="st0">&quot;/var/www/techblog&quot;</span><span class="sy0">&gt;</span>
Options Indexes MultiViews FollowSymlinks
AllowOverride All
Order allow,deny
Allow from all
<span class="sy0">&lt;/</span>Directory<span class="sy0">&gt;</span></pre></div></div><p>When I restarted Apache, the BP site correctly loaded the sub-pages without error.</p><p>&nbsp;</p> ]]></content:encoded> <wfw:commentRss>http://shallop.com/2012/01/buddypress-pages-failing-to-load-404/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Renaming mongodb Columns</title><link>http://shallop.com/2012/01/renaming-mongodb-columns/</link> <comments>http://shallop.com/2012/01/renaming-mongodb-columns/#comments</comments> <pubDate>Mon, 09 Jan 2012 21:32:09 +0000</pubDate> <dc:creator>Micheal Shallop</dc:creator> <category><![CDATA[Technical]]></category> <category><![CDATA[10gen]]></category> <category><![CDATA[collection]]></category> <category><![CDATA[column]]></category> <category><![CDATA[database]]></category> <category><![CDATA[documentation]]></category> <category><![CDATA[index]]></category> <category><![CDATA[internals]]></category> <category><![CDATA[mongo]]></category> <category><![CDATA[mongodb]]></category> <category><![CDATA[nosql]]></category> <category><![CDATA[problem]]></category> <category><![CDATA[problem-based]]></category> <category><![CDATA[reindex]]></category> <category><![CDATA[rename]]></category> <category><![CDATA[schema]]></category> <category><![CDATA[solution]]></category> <category><![CDATA[solution-based]]></category> <category><![CDATA[technical]]></category> <category><![CDATA[update]]></category> <guid
isPermaLink="false">http://shallop.com/?p=491</guid> <description><![CDATA[Today I was putzing around in the geo-spatial collection when I noticed that I had an unhappy over one of the column names within the collection. In the mySQL world, changing a column name is pretty straight-forward courtesy of the alter table command. Mongo&#8230;not so much&#8230; &#60;BEGIN_UNRELATED_SIDE_RANT&#62; The Mongo documentation is normally the first place most [...]]]></description> <content:encoded><![CDATA[<img
style='float: left; margin-right: 10px; border: none;' src='http://www.gravatar.com/avatar.php?gravatar_id=ab05b85b6786c70c1e1db98e219f015f&amp;default=http://www.shallop.com/wp-content/uploads/avatar_2868.jpg' alt='No Gravatar' width=40 height=40/><div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fshallop.com%2F2012%2F01%2Frenaming-mongodb-columns%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fshallop.com%2F2012%2F01%2Frenaming-mongodb-columns%2F&amp;source=mshallop&amp;style=normal&amp;b=2" height="61" width="50" /><br
/> </a></div><p><img
class="alignleft  wp-image-477" style="margin: 5px;" title="mongodb" src="http://shallop.com/wp-content/uploads/2011/12/mongodb.jpeg" alt="" width="180" height="180" /></p><p>Today I was putzing around in the geo-spatial collection when I noticed that I had an unhappy over one of the column names within the collection.</p><p>In the mySQL world, changing a column name is pretty straight-forward courtesy of the <em>alter table</em> command.</p><p>Mongo&#8230;not so much&#8230;</p><p>&lt;BEGIN_UNRELATED_SIDE_RANT&gt;</p><p>The Mongo documentation is normally the first place most of us go when we&#8217;re looking for help in using our favorite noSQL database.</p><p>Why?</p><p>Well&#8230;because that&#8217;s usually where Google directs us to go and also because there just isn&#8217;t a whole lot of documentation out there on the subject to begin with.</p><p>The mongo (10gen) documentation is pretty good.  It&#8217;s not, however, excellent.  And I can articulate the reason why.</p><p>It&#8217;s pretty easy to identify documentation written by engineers as opposed to documentation written by everyone else (on the planet).  And not because of technical content or the (ab)use of really big and impressive-sounding jargon.</p><p>No &#8211; it&#8217;s because most engineering-authored documents are written using a <em>solution-based</em> voice instead of a <em>problem-based</em> voice.</p><p>Think about it:  when I have to go to the man-page for help, it&#8217;s because I have a <em>problem</em>.  If I had a <em>solution</em>, I would be writing a blog post.    But since I have a <em>problem</em>, I need the man-pages, online docs, whatever, to help me figure-out a <em>solution.</em></p><p><em></em>Engineering documents are written from a solution perspective:  the document assumes you possess some bit of arcane lore (which is probably just exactly that little bit of lore that you&#8217;re missing which has caused your trip to the documentation vault) and everything that is explained within the document all hinges on this piece of knowledge which the author, albeit with the finest of intentions, assumes is already firmly in your mental possession.</p><p>And that&#8217;s why I usually don&#8217;t like 10gen&#8217;s documentation.  But, like I said earlier, it&#8217;s the only game in (Google)town.</p><p>&lt;END_UNRELATED_SIDE_RANT&gt;</p><p>In mongo, to change the name of a column within a collection, you first have to be on a release of mongodb 1.7.2 or later.  Since most of us bleeding-edge, early-adopter types are all 2.x versioned, this shouldn&#8217;t be an issue.</p><p>This <a
href="http://www.mongodb.org/display/DOCS/Updating">page</a> from 10Gen is the <em>update</em> page and, within, talked about the $rename modifier to the <em>update</em> command.  What the section doesn&#8217;t say, because it&#8217;s assuming you&#8217;re wanting to update records and not schema, is how to apply a change to all of the records in your collection.</p><p>In my case, I have a column-name which I fat-fingered the name right out it&#8217;s camel-case:  <em>CountryID</em> instead of <em>countryID</em>.  (And, yes, OCD-peeps, I know that it&#8217;s not <em>strictly</em> camelCase, thank-you!)  I want to spin through all 3.7 million rows in my collection and rename this column&#8230;</p><div
id="wpshdo_6" class="wp-synhighlighter-outer"><div
id="wpshdt_6" class="wp-synhighlighter-expanded"><table
border="0" width="100%"><tr><td
align="left" width="80%"><a
name="#codesyntax_6"></a><a
id="wpshat_6" class="wp-synhighlighter-title" href="#codesyntax_6"  onClick="javascript:wpsh_toggleBlock(6)" title="Click to show/hide code block">Source code</a></td><td
align="right"><a
href="#codesyntax_6" onClick="javascript:wpsh_code(6)" title="Show code only"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a
href="#codesyntax_6" onClick="javascript:wpsh_print(6)" title="Print code"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a
href="http://shallop.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img
border="0" style="border: 0 none" src="http://shallop.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div
id="wpshdi_6" class="wp-synhighlighter-inner" style="display: block;"><pre class="javascript" style="font-family:monospace;"><span class="sy0">&gt;</span> db.<span class="me1">geodata_geo</span>.<span class="me1">update</span><span class="br0">&#40;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span> <span class="sy0">,</span> <span class="br0">&#123;</span> $rename <span class="sy0">:</span> <span class="br0">&#123;</span> <span class="st0">'CountryID'</span> <span class="sy0">:</span> <span class="st0">'countryID'</span> <span class="br0">&#125;</span><span class="br0">&#125;</span><span class="sy0">,</span> <span class="kw2">true</span><span class="sy0">,</span> <span class="kw2">true</span> <span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div><p>So what we have here is the update command to the collection (geodata_geo) and four parameters:</p><ol><li>{} &#8212; the empty set (this is what&#8217;s missing from the 10gen doc) implying to do whatever to each record in the collection</li><li>$rename &#8212; the <em>modifier</em> to the update command which, in this case: replace &#8216;CountryID&#8217; with &#8216;countryID&#8217;</li><li>false &#8212; indicates to allow upserts if the record does not exist</li><li>true &#8212; multi option:  means to apply command to <em>all</em> records since, by default, the update() quits after updating the first record</li></ol><p>And I run this command and mongo goes off (whirr&#8230;whirr &#8230; I have two-node replication&#8230;) and renames the column in my collection!</p><p><span
style="color: #ff0000;">What it <strong>didn&#8217;t</strong> do was update my index. </span></p><p>So, after my column-renaming completed, I needed to drop the index(es) that had &#8216;CountryID&#8217; as members and re-index the collection to reflect the new column name.</p><p>Executing getIndexes() confirmed that my mongo world was back in it&#8217;s correct orbit and life, once again, was good.</p> ]]></content:encoded> <wfw:commentRss>http://shallop.com/2012/01/renaming-mongodb-columns/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>SWTOR: iMac Graphic Settings for 30-70 fps Framerate</title><link>http://shallop.com/2011/12/swotr-imac-graphic-settings-for-30-70-fps-framerate/</link> <comments>http://shallop.com/2011/12/swotr-imac-graphic-settings-for-30-70-fps-framerate/#comments</comments> <pubDate>Thu, 29 Dec 2011 18:33:03 +0000</pubDate> <dc:creator>Micheal Shallop</dc:creator> <category><![CDATA[Gaming]]></category> <category><![CDATA[Technical]]></category> <category><![CDATA[configuration]]></category> <category><![CDATA[fps]]></category> <category><![CDATA[graphics]]></category> <category><![CDATA[imac]]></category> <category><![CDATA[old]]></category> <category><![CDATA[republic]]></category> <category><![CDATA[settings]]></category> <category><![CDATA[star]]></category> <category><![CDATA[starwars]]></category> <category><![CDATA[swtor]]></category> <category><![CDATA[wars]]></category> <guid
isPermaLink="false">http://shallop.com/?p=482</guid> <description><![CDATA[Star Wars &#8211; The Old Republic (SWTOR) has pretty much dried-up my technical productivity since it&#8217;s release last week.  Staying true to my altoholic self, I&#8217;ve now got 6 teenage-level toons running around. I&#8217;m surprised, after playing fantasy-based RPGs for the last decade, how much I am enjoying this game.  True &#8211; it is just [...]]]></description> <content:encoded><![CDATA[<img
style='float: left; margin-right: 10px; border: none;' src='http://www.gravatar.com/avatar.php?gravatar_id=ab05b85b6786c70c1e1db98e219f015f&amp;default=http://www.shallop.com/wp-content/uploads/avatar_2868.jpg' alt='No Gravatar' width=40 height=40/><div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fshallop.com%2F2011%2F12%2Fswotr-imac-graphic-settings-for-30-70-fps-framerate%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fshallop.com%2F2011%2F12%2Fswotr-imac-graphic-settings-for-30-70-fps-framerate%2F&amp;source=mshallop&amp;style=normal&amp;b=2" height="61" width="50" /><br
/> </a></div><p><img
class="alignleft size-medium wp-image-483" style="margin: 5px;" title="star-wars-the-old-republic-logo" src="http://shallop.com/wp-content/uploads/2011/12/star-wars-the-old-republic-logo-300x165.jpg" alt="" width="300" height="165" /></p><p>Star Wars &#8211; The Old Republic (SWTOR) has pretty much dried-up my technical productivity since it&#8217;s release last week.  Staying true to my altoholic self, I&#8217;ve now got 6 teenage-level toons running around.</p><p>I&#8217;m surprised, after playing fantasy-based RPGs for the last decade, how much I am enjoying this game.  True &#8211; it is just another MMO similar in aspects to WoW or Rift.  But it&#8217;s that change of the menu from fantasy to sci-fi that&#8217;s making the transition so enjoyable.</p><p>I do wonder what&#8217;s happening on Telara&#8230;</p><p>Anyway, I play on a 27&#8242; iMac i7 using Bootcamp with Windows-7 Ultimate 64-bit edition installed to play both SWOTR and Rift.  Installation was really easy &#8211; albeit time consuming &#8212; and once I got the right (as in correct) combination dialed-in for my graphics settings, game play is very smooth and responsive.</p><p>Here&#8217;s a screen shot of my settings.  Basically, I&#8217;m running in full-screen windowed-mode, custom-settings.  I have high-texture settings and high character detail, medium texture anisotropy, and low shader complexity and low shadow quality.  Grass quality is set to 100% and tree quality is set to 50%.</p><p
style="text-align: center;"><a
href="http://shallop.com/wp-content/uploads/2011/12/swotr-settings.png"><img
class="aligncenter  wp-image-484" style="margin: 5px;" title="swotr-settings" src="http://shallop.com/wp-content/uploads/2011/12/swotr-settings-1024x624.png" alt="" width="717" height="437" /></a></p><p
style="text-align: left;">I&#8217;ve reduced the size of the image a bit; click on it to view it in full-screen.</p><p
style="text-align: left;">In spaceport, my resting framerate (to enable fps display, press CTRL+SHIFT+f and the fps is displayed in the lower-left corner of the screen) is about 60 fps on average.</p><p
style="text-align: left;">Most of the time when I&#8217;m bouncing about, I&#8217;m usually around 50fps &#8212; still very smooth with no noticeable lag, jerkiness or stuttering.</p><p
style="text-align: left;">FWIW &#8212; I play on Drooga&#8217;s Pleasure Barge (server) and my main is named Mal&#8217;loathe.  Sith, of course.</p> ]]></content:encoded> <wfw:commentRss>http://shallop.com/2011/12/swotr-imac-graphic-settings-for-30-70-fps-framerate/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Why is my mongo query so slow?</title><link>http://shallop.com/2011/12/why-is-my-mongo-query-so-slow/</link> <comments>http://shallop.com/2011/12/why-is-my-mongo-query-so-slow/#comments</comments> <pubDate>Mon, 19 Dec 2011 19:45:52 +0000</pubDate> <dc:creator>Micheal Shallop</dc:creator> <category><![CDATA[Technical]]></category> <category><![CDATA[architecture]]></category> <category><![CDATA[btree]]></category> <category><![CDATA[collection]]></category> <category><![CDATA[cursor]]></category> <category><![CDATA[database]]></category> <category><![CDATA[dba]]></category> <category><![CDATA[development]]></category> <category><![CDATA[documents]]></category> <category><![CDATA[explain]]></category> <category><![CDATA[indexing]]></category> <category><![CDATA[LAMP]]></category> <category><![CDATA[millis]]></category> <category><![CDATA[mongo]]></category> <category><![CDATA[mongodb]]></category> <category><![CDATA[nscanned]]></category> <category><![CDATA[optimization]]></category> <category><![CDATA[plan]]></category> <category><![CDATA[programming]]></category> <category><![CDATA[query]]></category> <category><![CDATA[search]]></category> <category><![CDATA[technical]]></category> <category><![CDATA[tutorial]]></category> <guid
isPermaLink="false">http://shallop.com/?p=476</guid> <description><![CDATA[Why&#8217;s my mongodb query so slow? I got my geospatial collection set-up &#8212; I am running some really great queries making sure that the locations I am pulling aren&#8217;t in any sort of cache, and I am just blown-away by how fast data is being returned. The problem is:  when I query the collection to pull [...]]]></description> <content:encoded><![CDATA[<img
style='float: left; margin-right: 10px; border: none;' src='http://www.gravatar.com/avatar.php?gravatar_id=ab05b85b6786c70c1e1db98e219f015f&amp;default=http://www.shallop.com/wp-content/uploads/avatar_2868.jpg' alt='No Gravatar' width=40 height=40/><div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fshallop.com%2F2011%2F12%2Fwhy-is-my-mongo-query-so-slow%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fshallop.com%2F2011%2F12%2Fwhy-is-my-mongo-query-so-slow%2F&amp;source=mshallop&amp;style=normal&amp;b=2" height="61" width="50" /><br
/> </a></div><p><img
class="alignleft  wp-image-477" style="margin: 5px;" title="mongodb" src="http://shallop.com/wp-content/uploads/2011/12/mongodb.jpeg" alt="" width="180" height="180" />Why&#8217;s my mongodb query so slow?</p><p>I got my geospatial collection set-up &#8212; I am running some really great queries making sure that the locations I am pulling aren&#8217;t in any sort of cache, and I am just blown-away by how <em>fast</em> data is being returned.</p><p>The problem is:  when I query the collection to pull up the requisite lon/lat data by name:  city &amp; state, or city &amp; country, the query seems to take <em>seconds</em> to complete!</p><p>I set-up the table correctly&#8230;I indexed the crap out of all my columns&#8230;a week or two ago, I was at the mongoSV 2011 in Santa Clara and learned some really cool stuff about queries, indexing, and performance management, so let&#8217;s dig-out the notes and see where I went wrong.  Because I <em>strongly</em> doubt that the problem is in mongo but, rather as we used to say in technical support: this is a PBCK issue&#8230;</p><p>The first thing I want to do is run an explain against my query so I can see mongo&#8217;s query plan for my query.  This should provide me with a starting point for trying to figure out what went wrong.</p><blockquote><p>&gt; db.geodata_geo.find({ cityName : &#8220;Anniston&#8221;, stateName : &#8220;Alabama&#8221; }).explain();</p></blockquote><p>By adding the trailing function: <em>.explain()</em>, I&#8217;m requesting that mongoDB return the query-plan to me instead of executing the query.  I hit enter to launch the explain() and get back the following output:</p><blockquote><p>&gt; db.geodata_geo.find({ cityName : &#8220;Anniston&#8221;, stateName : &#8220;Alabama&#8221;}).explain();<br
/> {<br
/> &#8220;cursor&#8221; : &#8220;<strong>BasicCursor</strong>&#8220;,<br
/> &#8220;nscanned&#8221; : <strong>3691723</strong>,<br
/> &#8220;nscannedObjects&#8221; : <strong>3691723</strong>,<br
/> &#8220;n&#8221; : 1,<br
/> &#8220;millis&#8221; : <strong>2269</strong>,<br
/> &#8220;nYields&#8221; : 0,<br
/> &#8220;nChunkSkips&#8221; : 0,<br
/> &#8220;isMultiKey&#8221; : false,<br
/> &#8220;<strong>indexOnly</strong>&#8221; : false,<br
/> &#8220;indexBounds&#8221; : {</p><p>}<br
/> }</p></blockquote><p>The important information, I <strong>bold</strong>-faced in the query output (above).   What this output is telling me is that I&#8217;ve using a &#8220;BasicCursor&#8221; for my search cursor &#8212; which is indicates that, yes, I am doing a table-scan on the collection.  So, already I know my query is not optimal.  But, wait!  More good news&#8230;</p><p>The value for <em>nscanned</em> and <em>nscannedObjects</em> is the same: 3,691,723 &#8212; which coincidently is the same as the cardinality of the collection.  This number is the number of documents scanned to satisfy the query which, given it&#8217;s value, confirms that I am doing a full table scan.</p><p><em>millis</em> tells me the number of milliseconds that the query would take:  2.269 seconds:  way too slow for my back-end methods() serving a REST API &#8212; unacceptable.</p><p>And then we get to the tell:  <em>IndexOnly</em> tells me that if the query could have been resolved by an (existing) covering index.  Seeing the value <em>false</em> here tells me that the collection has no index on the columns I am scanning against.</p><p>What?!?  I <em>know</em> I indexed this collection&#8230;</p><p>So, I run db.geodata_geo.getIndexes() to dump my indexes and &#8230; I &#8230; don&#8217;t see my name columns indexed.  Oh, I remembered to index the the ID and Code columns&#8230;but somehow, indexing the Name columns completely slipped past my lower brain-pan.</p><p>I add these indexes to my collection:</p><blockquote><p>&gt; db.geodata_geo.ensureIndex({ cityName : 1 });<br
/> &gt; db.geodata_geo.ensureIndex({ stateName : 1 });</p></blockquote><p>And then I rerun the query plan and see the following output:</p><blockquote><p>&gt; db.geodata_geo.find({ cityName : &#8220;Anniston&#8221;, stateName : &#8220;Alabama&#8221;}).explain();<br
/> {<br
/> &#8220;cursor&#8221; : &#8220;<strong>BtreeCursor</strong> cityName_1&#8243;,<br
/> &#8220;nscanned&#8221; : <strong>2</strong>,<br
/> &#8220;nscannedObjects&#8221; : <strong>2</strong>,<br
/> &#8220;n&#8221; : 1,<br
/> &#8220;millis&#8221; : <strong>101</strong>,<br
/> &#8220;nYields&#8221; : 0,<br
/> &#8220;nChunkSkips&#8221; : 0,<br
/> &#8220;isMultiKey&#8221; : false,<br
/> &#8220;indexOnly&#8221; : false,<br
/> &#8220;indexBounds&#8221; : {<br
/> &#8220;cityName&#8221; : [<br
/> [<br
/> "Anniston",<br
/> "Anniston"<br
/> ]<br
/> ]<br
/> }<br
/> }</p></blockquote><p>Instead of <em>BasicCursor</em>, I see <em>BtreeCursor</em> which gives me a happy.  I also see that the <em>nscanned</em> and <em>nscannedObjects</em> values are now more realistic&#8230;seriously:  2 is a LOT better than 3.6 million something, right?  Another happy for me!</p><p>I score the third happy when I see that the millis has dropped down to 101:  0.101 seconds to execute this search/query!  Not jaw-dropping, I agree &#8212; but acceptable considering that everything is running off my laptop&#8230;I know production times will be much, much lower.</p><p>&nbsp;</p><p>In the end, I learned that a simple tool like .explain() can tell me where my attention is needed when it comes to optimization and fixing even simple, seemingly innocent queries.  Knowing what you&#8217;re looking at, and what you&#8217;re looking for, is pretty much thick-end of the baseball bat when it comes to crushing one out of the park.</p><p>I hope this helps!</p><p>&nbsp;</p><p>Reference Link:  <a
href="http://www.mongodb.org/display/DOCS/Explain">Explain</a></p> ]]></content:encoded> <wfw:commentRss>http://shallop.com/2011/12/why-is-my-mongo-query-so-slow/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Searching MongoDB Sub-Documents&#8230;</title><link>http://shallop.com/2011/12/searching-mongodb-sub-documents/</link> <comments>http://shallop.com/2011/12/searching-mongodb-sub-documents/#comments</comments> <pubDate>Thu, 15 Dec 2011 20:46:22 +0000</pubDate> <dc:creator>Micheal Shallop</dc:creator> <category><![CDATA[Technical]]></category> <category><![CDATA[collection]]></category> <category><![CDATA[database]]></category> <category><![CDATA[document]]></category> <category><![CDATA[how-to]]></category> <category><![CDATA[LAMP]]></category> <category><![CDATA[mongo]]></category> <category><![CDATA[mysql]]></category> <category><![CDATA[programming]]></category> <category><![CDATA[search]]></category> <category><![CDATA[sub-document]]></category> <category><![CDATA[technical]]></category> <category><![CDATA[tutorial]]></category> <guid
isPermaLink="false">http://shallop.com/?p=465</guid> <description><![CDATA[I&#8217;ve recently finished a mongo collection that stores all auditing data from my application &#8212; specifically, it records every database transaction, conducted in either mySQL or mongo, assigning an event-identifier to the event, and storing the data under an event ID within a single sessionManger object. Sounds good? Well, I like it.   This design [...]]]></description> <content:encoded><![CDATA[<img
style='float: left; margin-right: 10px; border: none;' src='http://www.gravatar.com/avatar.php?gravatar_id=ab05b85b6786c70c1e1db98e219f015f&amp;default=http://www.shallop.com/wp-content/uploads/avatar_2868.jpg' alt='No Gravatar' width=40 height=40/><div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fshallop.com%2F2011%2F12%2Fsearching-mongodb-sub-documents%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fshallop.com%2F2011%2F12%2Fsearching-mongodb-sub-documents%2F&amp;source=mshallop&amp;style=normal&amp;b=2" height="61" width="50" /><br
/> </a></div><p><img
class="alignleft  wp-image-466" style="margin: 5px;" title="mongo searching" src="http://shallop.com/wp-content/uploads/2011/12/stress-cartoon.jpg" alt="" width="224" height="209" /></p><p>I&#8217;ve recently finished a mongo collection that stores all auditing data from my application &#8212; specifically, it records every database transaction, conducted in either mySQL or mongo, assigning an event-identifier to the event, and storing the data under an event ID within a single sessionManger object.</p><p>Sounds good?</p><p>Well, I like it.   This design eliminated the need to maintain meta-data in my data tables since I can pull transaction history for any record that I&#8217;ve accessed.</p><p>The problem is that, being new to mongodb, accessing what I&#8217;ve put into mongodb isn&#8217;t (yet) as intuitive as, say, my mySQL skills are.</p><p>Sub-documents within a mongo document are analogous to the results of a mySQL join.  One of the key motivators in storing this information in mongodb to begin with was that I could de-normalize the data by storing the sub-document with it&#8217;s parent instead of having to incur the expense of a search-join-fetch later.</p><p>Traditionally, any data objects defined as a one-to-many type of a relationship (1:m) were stored in multiple mySQL tables and were accessed via some sort of join mechanism.</p><p>Mongodb breaks that traditional mold by allowing you to store a sub-document (the &#8220;m&#8221; part of the 1:m relationship) within the same document in which you&#8217;re currently working.</p><p>Using my sessionManger document, I have a document that looks something like this:</p><div
class="codecolorer-container javascript blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div
class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span
style="color: #009900;">&#123;</span><br
/> _id <span
style="color: #339933;">:</span> somevalue<span
style="color: #339933;">,</span><br
/> foo <span
style="color: #339933;">:</span> bar<span
style="color: #339933;">,</span><br
/> event <span
style="color: #339933;">:</span> <span
style="color: #009900;">&#123;</span><span
style="color: #009900;">&#125;</span><span
style="color: #339933;">,</span><br
/> argle <span
style="color: #339933;">:</span> bargle<span
style="color: #339933;">,</span><br
/> <span
style="color: #009900;">&#125;</span></div></div><p>My desire is to, for every database event that is recorded, enter information about that event within the sub-document that I&#8217;ve wittily named &#8220;event&#8221;.</p><p>In my PHP code, I&#8217;ve written a sequence manager for mongo that maintains a document containing sequence values for various tables.  Think of this as the functional version of mySQL&#8217;s auto-increment feature.  I decided, then, for the sessionManager events, I would use this key sequence to obtain unique values and use those as my sub-document index.  I&#8217;d then store whatever data I needed to store using the sequence value as a sub-document key, or index:</p><div
class="codecolorer-container javascript blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div
class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span
style="color: #009900;">&#123;</span><br
/> _id <span
style="color: #339933;">:</span> somevalue<span
style="color: #339933;">,</span><br
/> foo<span
style="color: #339933;">:</span> bar<span
style="color: #339933;">,</span><br
/> event <span
style="color: #339933;">:</span> <span
style="color: #009900;">&#123;</span><br
/> n <span
style="color: #339933;">:</span> <span
style="color: #009900;">&#123;</span><br
/> created <span
style="color: #339933;">:</span> dateval<span
style="color: #339933;">,</span><br
/> table <span
style="color: #339933;">:</span> tableName<span
style="color: #339933;">,</span><br
/> schema <span
style="color: #339933;">:</span> dbSchema<span
style="color: #339933;">,</span><br
/> query <span
style="color: #339933;">:</span> lastQuery<br
/> <span
style="color: #009900;">&#125;</span><br
/> <span
style="color: #009900;">&#125;</span><br
/> argle <span
style="color: #339933;">:</span> bargle<br
/> <span
style="color: #009900;">&#125;</span></div></div><p>So, when I need to add another event, I just create a new sub-document under the event key, then add the data I need to store under the sub-document index key.</p><p>Worked like a champ!</p><p>And then I asked myself:  &#8221;So, Brainiac, how would you go about extracting event -n- from your collection?&#8221;</p><p>I went through a lot of failed query attempts, bugged a lot of people, googled and saw stuff  that led me down many plush ratholes until I finally, through some serious trial-and-error, got the answer&#8230;</p><p>&gt; db.mytable.find( { foo : bar }, { &#8216;event.n&#8217; : 1 } );</p><p>where n = the number of the event I want to find.</p><p>If I want to get all of the events for a particular document (sessionManger object), then I would write something like:</p><p>&gt; db.mytable.find( {foo : bar}, { event : 1});</p><p>If I wanted to return all of the events for all of the objects, then I would write this:</p><p>&gt; db.mytable.find( {}, {event : 1});</p><p>What I&#8217;ve not been able to figure out, so far, is how I can use <a
title="Mongo doc on $slice" href="http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements" target="_blank">$slice</a> to grab a range of events within a document.  Everything I try returns the full sub-set of documents back to me.  The doc tells me that $slice is used to return a subrange of array elements, which is what I thought &#8220;event.n&#8221; was but, apparently, it&#8217;s not.  (I think it&#8217;s an object (sub-document) which is why $slice fails for me.)</p><p>It&#8217;s not a big deal because, programmatically, I can grap the entire sub-document from it&#8217;s parent and parse in-memory to get the desired record.  And, if I know what the value for -n- is, then I can fetch just that one sub-document.  So, I&#8217;m ok for now.  However, please feel free to enlighten me with your expertise and experience should you see where I am failing here, ok?</p><p>&nbsp;</p> ]]></content:encoded> <wfw:commentRss>http://shallop.com/2011/12/searching-mongodb-sub-documents/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>mongodb, geospatial indexing, and advanced queries&#8230;.</title><link>http://shallop.com/2011/11/mongodb-geospatial-indexing-and-advanced-queries/</link> <comments>http://shallop.com/2011/11/mongodb-geospatial-indexing-and-advanced-queries/#comments</comments> <pubDate>Fri, 25 Nov 2011 15:00:08 +0000</pubDate> <dc:creator>Micheal Shallop</dc:creator> <category><![CDATA[Technical]]></category> <category><![CDATA[1:M]]></category> <category><![CDATA[collection]]></category> <category><![CDATA[data]]></category> <category><![CDATA[database]]></category> <category><![CDATA[db]]></category> <category><![CDATA[denormalization]]></category> <category><![CDATA[denormalize]]></category> <category><![CDATA[document]]></category> <category><![CDATA[double]]></category> <category><![CDATA[float]]></category> <category><![CDATA[interval]]></category> <category><![CDATA[mantissa]]></category> <category><![CDATA[mongo]]></category> <category><![CDATA[mongodb]]></category> <category><![CDATA[mysql]]></category> <category><![CDATA[normalization]]></category> <category><![CDATA[normalize]]></category> <category><![CDATA[PHP]]></category> <category><![CDATA[point]]></category> <category><![CDATA[relation]]></category> <category><![CDATA[relational]]></category> <category><![CDATA[round]]></category> <category><![CDATA[rounding]]></category> <category><![CDATA[table]]></category> <guid
isPermaLink="false">http://shallop.com/?p=461</guid> <description><![CDATA[I&#8217;ve been working to build, and re-build, a geospatial table for work.  There&#8217;s been a lot of challenges in this project for me as this is the first time that I&#8217;ve had to architect db designs incorporating mongodb with mySQL. The mongo geospatial repository will be replacing several tables in the legacy mySQL system &#8212; as [...]]]></description> <content:encoded><![CDATA[<img
style='float: left; margin-right: 10px; border: none;' src='http://www.gravatar.com/avatar.php?gravatar_id=ab05b85b6786c70c1e1db98e219f015f&amp;default=http://www.shallop.com/wp-content/uploads/avatar_2868.jpg' alt='No Gravatar' width=40 height=40/><div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fshallop.com%2F2011%2F11%2Fmongodb-geospatial-indexing-and-advanced-queries%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fshallop.com%2F2011%2F11%2Fmongodb-geospatial-indexing-and-advanced-queries%2F&amp;source=mshallop&amp;style=normal&amp;b=2" height="61" width="50" /><br
/> </a></div><p><a
href="http://shallop.com/wp-content/uploads/2011/11/mongo-db-huge-logo_0.png"><img
class="size-full wp-image-462 alignleft" style="margin: 5px;" title="mongo-db-huge-logo_0" src="http://shallop.com/wp-content/uploads/2011/11/mongo-db-huge-logo_0.png" alt="" width="312" height="104" /></a></p><p>I&#8217;ve been working to build, and re-build, a geospatial table for work.  There&#8217;s been a lot of challenges in this project for me as this is the first time that I&#8217;ve had to <em>architect</em> db designs incorporating mongodb with mySQL.</p><p>The mongo geospatial repository will be replacing several tables in the legacy mySQL system &#8212; as you may know, mongodb comes with full <a
href="http://www.mongodb.org/display/DOCS/Geospatial+Indexing">geospatial</a> support so executing queries against a collection (table) built in this manner is shocking in terms of it&#8217;s response speeds &#8212; especially when you compare those speeds to the traditional mySQL algorithms for extracting geo-points based on distance ranges for lat/lon coordinates.  The tl;dr for this paragraph is:  no more hideous trigonometric mySQL queries!</p><p>What I learned in this exercise was that the key to architecting a mongo <em>collection</em> requires you to re-think how data is stored.  Mongo stores data as a collection of <em>documents</em>.  The key to successful thinking, at least in terms of mongo storage, is <em>denormalization</em> of your data objects.</p><p>Let&#8217;s use a standard <em>customer</em> object as an example.  Every <em>customer </em>has at least one <em>phone</em> number.  Most, if not all, <em>customers</em> have more than one <em>phone</em> number.  We could define several columns in the <em>customer</em> table for the phone numbers: workphone, homephone, cellphone, otherphone and store the data that way.  Problem is that we will eventually hit the wall where we have the need to store numbers for which we don&#8217;t have columns pre-defined:  faxphone, skypephone, tddphone, vrsphone, etc.</p><p>RDBMS design demands a normalization of this 1:M data design by requiring a second table to store just <em>phone</em> numbers for each <em>customer</em>.  The <em>phone </em>table would have a primary key (id), the customer id, the customer phone number and perhaps a short, descriptive, field explaining the purpose of this number.  To get the <em>phone</em> data for a <em>customer</em>, then, you&#8217;d simply query (or join) the <em>phone</em> table based on the <em>customer</em> ID to get all the phone tuples for that customer.</p><p>Mongo, on the other hand, sees every customer as a <em>document</em>.  Think of each <em>customer</em> in your collection as a piece of paper.  You want to go into your collection and retrieve on piece of paper upon which has <em>all the customer data</em>.  So, for example, you retrieve the document for &#8220;John Smith&#8221; and on this document, it lists several key-value pairs, underneath an array called phone:</p><blockquote><p>phone : {<br
/> home : (408) 123-4567,<br
/> work : (415) 123-4567,<br
/> cell : (312) 765-4321<br
/> }</p></blockquote><p>&#8230;and so on&#8230;</p><p>Mongo stores the <em>document</em> for this, or any user, by de-normalizing the data relationships within the <em>customer</em> object.  These relationships can be maintained as sub-arrays within the document.  Because mongo is schema-less, every <em>customer</em> object isn&#8217;t required to have all the possible combinations of phone numbers.  So, if you were to do a search where you pull-up all customers with fax numbers, our Mr. Smith would <em>not</em> appear in this list since he has no fax number listed in his phone array.</p><p>See?</p><p>This first step towards clarity in mongo architecture, then, is to think of all the data when you design a class object and include that data within a single <em>document</em>.  Data that was stored, in traditional RDBMS relation-based tables, is incorporated into the document as sub-arrays to the document.</p><p>But, you&#8217;re asking, what if you want to later add a fax number to John Smith&#8217;s phone collection?  Can you do that?</p><p>Sure!</p><p>Again, this is the inherent strength in mongodb &#8212; it&#8217;s schema-less!  Adding another number to the existing collection of phone numbers, or adding a new &#8220;column&#8221; to the document itself, requires only that you update that document.  That&#8217;s it!</p><p>So, returning back to the geospatial build, I used mySQL pull the legacy data, and collect the updated catalog tables into a single database.  Then I built new tables that (a) eliminated columns I no longer needed and, (b), de-normalized the data so that every tuple in every table reflected <em>all </em>of the data.</p><p>I then combined the five tables into a single table under a new primary-key value and then imported this data directly into a mongo collection.  This took several hours as my collection has over 3.6 million rows.</p><p>Once I had the collection in mongo, I made a mongo-dump of the collection so that I&#8217;d could recover back to this point in-case anything went south.  (Which it did&#8230;)</p><p>I executed a PHP script I wrote to scan the mySQL table, get the tuple by the newly-created primary key, and then create the sub-array in the mongo collection for the geospatial data.  See, in order to impose a geospatial index, your lat/lon data has to be a sub-array within the primary collection.  There&#8217;s no way I&#8217;ve yet discovered to import data over from either a flat (csv) file, or directly from mySQL, so that it creates your sub-array automagically.  Hence, the home-brew PHP script to parse through the mySQL records and build (insert) the sub-array in the newly-created mongodb collection.</p><p><span
style="background-color: #ffff99;">(Side note:  I was careful to maintain the maximum mantissa values for the lat/lon fields by importing initially, into mySQL as varchar(255) fields &#8212; this kept my 13-digit mantissas.  When I imported the data into mongodb, mongo converted these values into <em>doubles</em> and kept the precision.  However, my PHP program, casting these values to either (float) or (double) converted (round) the matissa to 7-digit precision.  Suitable for task?  Yes.  Annoying to lose this data?  Yes.  If you have a solution to this, please leave me a comment at the end of this article.  Thanks!   <img
src='http://shallop.com/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> )</span></p><p>The next step was to add the geo-spatial index to the collection:</p><blockquote><p>&gt; db.geodata_geo.ensureIndex( { loc : &#8220;2d&#8221; } );<br
/> point not in interval of [ -180, 180 )</p></blockquote><p>What?</p><p>This error message was telling me that my data was out of range of the acceptable lat/lon values!</p><p>I tried searching for the data culprits:</p><blockquote><pre>&gt; db.geodata_geo.find( { "loc" : { $exists : true }}).count();
3685667
&gt; db.geodata_geo.find({"loc.lon" : {$lt : -180}}).count();
0
&gt; db.geodata_geo.find({"loc.lon" : {$gt : 180}}).count();
0
&gt; db.geodata_geo.find({"loc.lat" : {$gt : 180}}).count();
0
&gt; db.geodata_geo.find({"loc.lat" : {$lt : -180}}).count();
0</pre></blockquote><p>These queries were telling me that while I have over 3.6 million records indexed, none are outside of the -180,180 boundaries.</p><blockquote><pre>&gt; db.geodata_geo.find({"loc.lat" : {$gt : -180}, "loc.lon" : {$lt : 180}}).count();
3685663</pre><pre>&gt; db.geodata_geo.find( { "loc" : { $exists : true }}).count();
3685667</pre></blockquote><p>These queries tell me that I have a delta of 4-records that exists outside of the -180, 180 boundary.</p><p>Wait...wut?</p><p>I focus on the $gt/$lt and wonder if I have an "edge" case.  Given that I've lost 6-digits of my mantissa, I wonder if mongo has rounded my data to my edge cases of 180:</p><blockquote><p>&gt; db.geodata_geo.find({"loc.lon" : 180 });</p></blockquote><p>And I get back exactly four records that have a lon-value of exactly 180:</p><blockquote><p>"loc" : { "lon" : 180, "lat" : -16.1499996 }</p></blockquote><p>This, to me, seems to be an error in how mongodb indexes geospatial data.  If 180 is an allowed value for lat/lon, then why throw the error when you ensure the index?  I decide to handle this rounding problem by expanding the allowable limits of my query:</p><blockquote><pre>&gt; db.geodata_geo.ensureIndex({ "loc" : "2d" }, { min : -180, max : 181 });
&gt; db.geodata_geo.getIndexes();
[
	{
		"v" : 1,
		"key" : {
			"_id" : 1
		},
		"ns" : "dev_honeybadger.geodata_geo",
		"name" : "_id_"
	},
	{
		"v" : 1,
		"key" : {
			"loc" : "2d"
		},
		"ns" : "dev_honeybadger.geodata_geo",
		"name" : "loc_",
		"min" : -180,
		"max" : 181
	}
]</pre></blockquote><p>And I see that my geospatial index has been created.  Now, to test:</p><blockquote><p>&gt; db.geodata_geo.find( { loc : {$near : [-50,50] } } ).limit(5);</p></blockquote><p>And it <em>immediately</em> returns five records (Elliston, Bonavista, Elliston Station, Catalina and Port Union, Division #7,  in Canada) that I asked for.</p><p>My geospatial index is complete!  Now, all I need to do is add my regular indexes for keyed searching and export the table off my development environment.</p><p>&nbsp;</p><p>&nbsp;</p> ]]></content:encoded> <wfw:commentRss>http://shallop.com/2011/11/mongodb-geospatial-indexing-and-advanced-queries/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Converting a mySQL Column to AutoIncrement</title><link>http://shallop.com/2011/10/converting-a-mysql-column-to-autoincrement/</link> <comments>http://shallop.com/2011/10/converting-a-mysql-column-to-autoincrement/#comments</comments> <pubDate>Wed, 26 Oct 2011 17:04:30 +0000</pubDate> <dc:creator>Micheal Shallop</dc:creator> <category><![CDATA[Technical]]></category> <category><![CDATA[auto]]></category> <category><![CDATA[auto_increment]]></category> <category><![CDATA[convert]]></category> <category><![CDATA[increment]]></category> <category><![CDATA[key]]></category> <category><![CDATA[mysql]]></category> <category><![CDATA[primary]]></category> <guid
isPermaLink="false">http://shallop.com/?p=444</guid> <description><![CDATA[We&#8217;re updating a large dataset at work &#8212; there&#8217;s about an 18% increase in the number of tuples in the new dataset spread across a highly-normalized 8 or so tables. I have to port the new data into a (more) efficient table structure &#8212; so I&#8217;m de-normalizing the heck out of the data reducing the [...]]]></description> <content:encoded><![CDATA[<img
style='float: left; margin-right: 10px; border: none;' src='http://www.gravatar.com/avatar.php?gravatar_id=ab05b85b6786c70c1e1db98e219f015f&amp;default=http://www.shallop.com/wp-content/uploads/avatar_2868.jpg' alt='No Gravatar' width=40 height=40/><div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fshallop.com%2F2011%2F10%2Fconverting-a-mysql-column-to-autoincrement%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fshallop.com%2F2011%2F10%2Fconverting-a-mysql-column-to-autoincrement%2F&amp;source=mshallop&amp;style=normal&amp;b=2" height="61" width="50" /><br
/> </a></div><p><img
class="alignleft size-medium wp-image-445" style="margin: 5px;" title="mysql" src="http://shallop.com/wp-content/uploads/2011/10/mysql-296x300.png" alt="" width="237" height="240" /></p><p>We&#8217;re updating a large dataset at work &#8212; there&#8217;s about an 18% increase in the number of tuples in the new dataset spread across a highly-normalized 8 or so tables.</p><p>I have to port the new data into a (more) efficient table structure &#8212; so I&#8217;m de-normalizing the heck out of the data reducing the schema from eight tables to a single table.</p><p>In the old architecture, four of the tables have unique key values that were imposed on the data during the original port.  So, to maintain application compatibility in the data catalog, these key values have to be maintained.  Additionally, new tuples of data have to be added to the data set and new (old) key values assigned.</p><p>In porting over one of the updated tables, which uses a string-code as the primary key, I first export the old table columns (pkey, str_code) into a temp table and then add an auto_increment int() column to the new table marking the column as default = null.  I then do a simple update-join to bring over the old pkey values based on the native str_code.</p><p>This leaves me with a new numeric column that has a variable number of NULL values (representing the delta of the new-data import) interspersed with the legacy data pkey -&gt; str_code values.</p><p>The problem is: how do I convert the NULL pkey fields to a meaningful value that maintains the auto-increment without causing mysql to totally freak?</p><p>The first thing I do is get the max-value of the pkey:</p><blockquote><pre>select max(pkey_field_name) from table_name;</pre><pre>+---------------+
| max(pkey_...) |
+---------------+
|          4162 |
+---------------+
1 row in set (0.00 sec)</pre></blockquote><p>Next, I need to reset the auto_increment value of the column because, since the column is just a numeric column, it currently defaults to zero.  Attempting to convert the column on-the-fly to auto-increment will cause mysql to spit and error out about duplicate primary key values&#8230;</p><blockquote><pre>mysql&gt; alter table table_name auto_increment=4163;</pre><pre>Query OK, 3965 rows affected (0.05 sec)
Records: 3965 Duplicates: 0 Warnings: 0</pre></blockquote><p>Now that I have the auto_increment reset, I can convert the column to auto_increment type and, in the process of converting, mySQL will re-number the NULL column key values using the new auto_increment value so that my numbering scheme is seamless.</p><p>When I query the data back, I can see that my new column is completely re-ordered with the legacy data maintained and the new data correctly keyed.</p><p>Resetting the auto-increment key is a handy little trick to know &#8212; I also use it when building test datasets and I need a fast way to reset my table values.</p><p>Hope this helps!</p><p>&nbsp;</p><p>&nbsp;</p><p>Note:  Here&#8217;s the complete and full steps to successfully complete this operation.</p><p>(DDL for admin1 table)</p><pre>CREATE TABLE `admin1` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `field1` varchar(255) NOT NULL,
  `field2` varchar(255) NOT NULL,
  `field3` varchar(255) NOT NULL,
  `field4` varchar(255) NOT NULL,
  `field5` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=4163 DEFAULT CHARSET=utf8</pre><p>(DDL for admin1ll table)</p><pre>CREATE TABLE `admin1ll` (
  `field1` int(11) NOT NULL,
  `field2` varchar(255) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8</pre><p>&nbsp;</p><p><strong>Step 1:  Create a new integer column in the table</strong></p><p>ALTER TABLE `meridian`.`admin1` DROP COLUMN `id`, ADD COLUMN `id` int UNSIGNED FIRST, CHANGE COLUMN `field1` `field1` varchar(255) NOT NULL AFTER `id`, CHANGE COLUMN `field2` `field2` varchar(255) NOT NULL AFTER `field1`, CHANGE COLUMN `field3` `field3` varchar(255) NOT NULL AFTER `field2`, CHANGE COLUMN `field4` `field4` varchar(255) NOT NULL AFTER `field3`, CHANGE COLUMN `field5` `field5` varchar(255) NOT NULL AFTER `field4`;</p><p><strong>Step 2:  Update the new column by inserting the previous-tables pkey values</strong></p><p>update admin1, admin1ll<br
/> set admin1.id = admin1ll.field1<br
/> where admin1.field1 = admin1ll.field2</p><p><strong>Step 3: Update the Auto_Increment value:</strong></p><p>&gt; select max(id) from admin1;</p><p><em>4030</em></p><p>&gt; alter table admin1 auto_increment=4031;</p><p><em>Note:  the row count does not imply or set the auto_increment value!</em></p><p><strong>Step 4: Reformat Column</strong></p><p>Set column to auto_increment, unsignent, not null, primary key</p><p><strong>Step 5:  Validate!</strong></p><p>select *</p><p>from admin1, admin1ll</p><p>where admin1.id &lt;&gt; admin1ll.field1</p><p>and admin1.field1 = admin1ll.field2</p><p>&gt; Empty set (1.70 sec)</p> ]]></content:encoded> <wfw:commentRss>http://shallop.com/2011/10/converting-a-mysql-column-to-autoincrement/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>HTC Thunderbolt &#8211;  The Honeymoon?  Definitely Over.</title><link>http://shallop.com/2011/10/htc-thunderbolt-verizon-vs-iphone-4-att-2/</link> <comments>http://shallop.com/2011/10/htc-thunderbolt-verizon-vs-iphone-4-att-2/#comments</comments> <pubDate>Wed, 26 Oct 2011 01:14:51 +0000</pubDate> <dc:creator>Micheal Shallop</dc:creator> <category><![CDATA[Rant]]></category> <category><![CDATA[Technical]]></category> <category><![CDATA[WTF]]></category> <category><![CDATA[android]]></category> <category><![CDATA[AT&T]]></category> <category><![CDATA[battery]]></category> <category><![CDATA[bloatware]]></category> <category><![CDATA[crapware]]></category> <category><![CDATA[froyo]]></category> <category><![CDATA[gingerbread]]></category> <category><![CDATA[google]]></category> <category><![CDATA[htc]]></category> <category><![CDATA[iPhone]]></category> <category><![CDATA[iphone4s]]></category> <category><![CDATA[jailbreak]]></category> <category><![CDATA[Leg]]></category> <category><![CDATA[performance]]></category> <category><![CDATA[restore]]></category> <category><![CDATA[review]]></category> <category><![CDATA[root]]></category> <category><![CDATA[smartphone]]></category> <category><![CDATA[thunderbolt]]></category> <category><![CDATA[Verizon]]></category> <guid
isPermaLink="false">http://shallop.com/2011/10/htc-thunderbolt-verizon-vs-iphone-4-att-2/</guid> <description><![CDATA[First, let me begin by saying that I have been an Apple fan for a long time. In addition to using their computers, I was a first generation adopter of both the iPod and the iPhone.  I&#8217;ve gone through the original iPhone, the 3G and the 4. What I like about the iPhone can be [...]]]></description> <content:encoded><![CDATA[<img
style='float: left; margin-right: 10px; border: none;' src='http://www.gravatar.com/avatar.php?gravatar_id=ab05b85b6786c70c1e1db98e219f015f&amp;default=http://www.shallop.com/wp-content/uploads/avatar_2868.jpg' alt='No Gravatar' width=40 height=40/><div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fshallop.com%2F2011%2F10%2Fhtc-thunderbolt-verizon-vs-iphone-4-att-2%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fshallop.com%2F2011%2F10%2Fhtc-thunderbolt-verizon-vs-iphone-4-att-2%2F&amp;source=mshallop&amp;style=normal&amp;b=2" height="61" width="50" /><br
/> </a></div><p>First, let me begin by saying that I have been an Apple fan for a long time. In addition to using their computers, I was a first generation adopter of both the iPod and the iPhone.  I&#8217;ve gone through the original iPhone, the 3G and the 4.</p><p>What I like about the iPhone can be summed up by saying that it represents exemplary engineering on top of a ghastly deployment.</p><p>After all those years of being an iPhone user with AT&amp;T, I could no longer justify paying for AT&amp;T&#8217;s sub-standard cellular services.  The times I could complete a conversation on my iPhone without dropping the call, or losing call quality was an extremely rare event.  (And I live in the Bay area, home to AT&amp;T which is touted as one of their major coverage areas&#8230;.)</p><p>AT&amp;T&#8217;s cellular service is simply pathetic.  As a matter of fact, I deemed it justifiable to pay the contract cancellation penalty with AT&amp;T to come to Verizon.  I never realized how bad AT&amp;T service was, however, until switched to Verizon.   Within my first week of using my Thunderbolt, I experienced NO dropped calls, NO poor signals, NO service interruptions of any kind.  (Unless I was connected to an AT&amp;T cellular customer&#8230;)</p><p>And, while Apple is, in my opinion, the best hardware engineer in the business, the other factor in my decision to move phone platforms was that Apple never quite got the whole synchronization thing down. (Pre-iCloud)  I really don&#8217;t need seven different listings for my veterinarian in my address book.  Syncing services with Google have been working for me perfectly &#8211; and I don&#8217;t have to pay them $99 per year to screw up my address book contents or my calendar.</p><p>So I dropped .me and my iPhone for a Google phone living in a Google world.  Since the Android requires a Google account, (Hey! I have one of those!), setting up my phone required that I only provide it with my account information and everything from that point was auto-magically configured for me.  Insta-integration with all my Google-based services.  Plus really cool stuff like Google Voice for messaging.</p><p>&#8230;.</p><p>It&#8217;s now been six months with the Android. Apple has just released their iPhone 4S&#8230;and, within a day, I find myself browsing the provider&#8217;s pages looking/comparing contracts and service offerings.  What the hell am I doing?!?</p><p>The shine on this Android HTC Thunderbolt phone is definitely gone.  While I like most of the Verizon services, specifically the quality of the cellular coverage, I am really dissatisfied with some of their processes and, as far as the phone is concerned, the HTC Thunderbolt is a complete a total piece of crap.  I will NEVER, EVER buy another phone from HTC every again.</p><p><strong>Problems with Verizon and the HTC Thunderbolt Nobody Talks About:</strong></p><p><strong>1. Crapware</strong></p><p>I rooted my Android within a week of getting it.  Verizon pre-loaded the Thunderbolt with an amazing amount of crapware that they don&#8217;t allow you to delete off their phone.  Seriously bad software.  That does nothing except eat tons of space in my memory store.  Once I rooted the phone (similar to the jail-breaking process for the iPhone), I was able to delete that bloatware and regain my lost storage for other applications.</p><p><strong>2. Say My Name, Bitch!</strong></p><p>Of course there&#8217;s a problem with rooting your phone &#8212; and that&#8217;s dealing with Verizon&#8217;s never-ending attempts to force software updates down your throat and to your phone.  Should you make the tragic mistake of leaving your phone &#8220;on&#8221; (which I do when sitting at my desk with the phone plugged into the charger) then Verizon assumes control of your phone by forcing your phone to accept updates over the network.</p><p>Since you&#8217;ve rooted your phone, said updates (which are image zip files stored to your cache) will not install after the download completes and the phone reboots itself.  All without any confirmation or interaction from your part.  Special, no?</p><p>When your phone reboots, you&#8217;re presented with the broken-android symbol and you have to go into your root-tools menu to delete the cached files from your phone.  This removes the forced-download and allows you to reboot your phone into it&#8217;s previously rooted state.  Of course, leave your phone on for too long and here it comes again!</p><p>There&#8217;s no &#8220;off&#8221; switch to disable the forced downloads.  Verizon&#8217;s attitude, gleaned from the forums, is that: &#8220;It&#8217;s our network.  Suffer, bitch.&#8221;</p><p><strong>3. Random Reboots and Disappearing Apps</strong></p><p>My co-workers claim that my phone re-booting itself (without an &#8220;upgrade&#8221; being pushed down) is because I rooted my phone.  After reading the complaints about the HTC Thunderbolt out on the etherstream &#8211; I beg to differ.  I think the HTC/Verizon mash-up operating system is just so crappy it crashes and forces a reboot.  I&#8217;ve noticed that this happens when the network flips around a lot.  I&#8217;ve also noticed it booting for no apparent reason.</p><p>What&#8217;s also special is that apps just disappear off your phone following a reboot.  Once your phone restarts, you have to give it several moments of 4G time to restore whatever apps it randomly deleted.  Totally weird behavior.  It&#8217;s almost like using a Windows operating system.</p><p><strong>4. I&#8217;ve Lost My Network and I Can&#8217;t Get Up</strong></p><p>Several times with this Thunderbolt I&#8217;ve noticed that I&#8217;m stuck in 1G mode.  I try toggling the mobile network connection off/on to reset it, but it always comes back to the 1G network.  This occasionally happens when it gets stuckin 3G mode as well.  (Funny, I&#8217;ve never seen 2G&#8230;)</p><p>The only way I&#8217;ve found to fix this problem is to force a restart.  When the phone regains consciousness, it happily joins the 4G network.</p><p><strong>5. Sucks like a Starving Vampire</strong></p><p>Granted, the Gingerbread update is supposed to fix a lot of the issues with the HTC Thunderbolt&#8217;s ability to drain your battery faster than a starving vampire in a blood bank.  I even upgraded, spending about $50, for a uber-battery, doubling the phone&#8217;s weight and thickness.  It&#8217;s worth it, though, having a battery that can last me on the train ride between San Jose and San Francisco.</p><p>There&#8217;s entire web pages devoted to tricks and tips to prolonging the battery life on this phone all of which basically involve crippling, or at least diminishing, all of the features that justified the purchase of your phone in the first place.</p><p>I&#8217;m really hoping Gingerbread offers better battery life as, since I don&#8217;t live in a winter-zone anymore, it&#8217;s a shame to waste the hand-warming features of a rapidly depleting battery.</p><p>&nbsp;</p><p>So&#8230;I un-rooted my phone so that I could get the Gingerbread update, replacing Froyo on this phone.  I have no idea why it takes Verizon so long to roll-out these updates.  Perhaps their visual basic programmers are having a hard time with all the Android unixey stuff.  Who knows?  I mean, you have to make sure that the user can&#8217;t delete the fucking golf demo, right?</p><p>When Gingerbread was finally available for the Thunderbolt, the update lasted all of a day, if that, before Verizon yanked the update from the download stream.  It was as if they were like: QA testing?  We&#8217;ve heard of that&#8230;  The update was so bug-ridden that it was disabling or severely-impairing phone functionality.</p><p>Now, as of yesterday, they&#8217;re starting to push the Gingerbread update back out to the users.  At a time when Google is announcing the Ice Cream Sandwich update (the successor to Gingerbread), Verizon, after one false-start, is now only 1 release behind on the operating system.</p><p>Tell me &#8212; why am I paying premium rates for a phone Verizon and HTC can&#8217;t keep current?</p><p>So, as soon as I come into a little cash, I think I will call Verizon customer services (snicker) and complain to them about this phone and their inability to provide a stable (or current) operating system platform.  I&#8217;d like to negotiate them into a new Motorola Android phone&#8230;Verizon seems ti play better with Motorola &#8212; timely updates, better hardware, non thermo-radioactive battery, etc.</p><p>I want to stay in the Google universe because everything works there.  The iPhone is looking sexy &#8212; but it&#8217;s still not 4G&#8230;not yet&#8230;</p> ]]></content:encoded> <wfw:commentRss>http://shallop.com/2011/10/htc-thunderbolt-verizon-vs-iphone-4-att-2/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
