<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Paul Smith</title>
  <subtitle>Programmer, co-founder of EveryBlock</subtitle>
  <link href="http://pauladamsmith.com/atom.xml" rel="self" />
  <link href="http://pauladamsmith.com/" />
  <id>pauladamsmith.com</id>
  <updated>2011-09-04T16:00:00Z</updated>
  <author>
    <name>Paul Smith</name>
    <email>paulsmith@pobox.com</email>
  </author>
  <entry>
    <title>Going to work for Democrats</title>
    <link href="/blog/2011/09/dnc.html" />
    <id>http://pauladamsmith.com/blog/2011/09/dnc.html</id>
    <updated>2011-09-04T16:00:00Z</updated>
    <content type="html">&lt;img src=&#34;/images/eb-to-dnc.png&#34; style=&#34;display: block; float: right; margin-left: 15px&#34;&gt;

&lt;p&gt;I have some exciting news: in a couple of weeks, I will be the new deputy
director of technology at the &lt;a href=&#34;http://www.democrats.org/&#34;&gt;Democratic National Committee&lt;/a&gt;. I’ll
be helping to create software that helps get Democrats elected. It’s
a great opportunity for me to do what I love for an organization that I
passionately support. I hope to help make the technology department there
top-notch in terms of software engineering practices, bringing what I’ve
learned from having helped develop, deploy, and grow &lt;a href=&#34;http://www.everyblock.com/&#34;&gt;EveryBlock&lt;/a&gt;. And
I’ll have some projects of my own, which will hopefully advance the
state of campaign software somewhat. It’s especially exciting, too, to
be able to collaborate with &lt;a href=&#34;http://twitter.com/harper&#34;&gt;friends&lt;/a&gt; &lt;a href=&#34;http://twitter.com/detour1999&#34;&gt;in&lt;/a&gt; &lt;a href=&#34;http://twitter.com/gabaug&#34;&gt;Chicago&lt;/a&gt;
&lt;a href=&#34;http://twitter.com/scottvdp&#34;&gt;working&lt;/a&gt; &lt;a href=&#34;http://twitter.com/aconbere&#34;&gt;on&lt;/a&gt; &lt;a href=&#34;http://www.barackobama.com/&#34;&gt;that one campaign&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have been volunteering on political campaigns—federal, state, and
local races—for years, and have often lamented the state of campaign
software. It’s partly understandable, because campaigns tend to be
all-hands-on-deck, hair-on-fire affairs, where it’s hard to justify
long-range planning and software development, even if it might make
the lives of your staff, organizers and volunteers easier, since your
organization may not even exist for more than a few months. And campaigns
rarely have in-house software engineers, so opportunities to capture and
encode knowledge in the form of software, and explore new technologies,
are missed.&lt;/p&gt;
&lt;p&gt;Obama For America gets this—that’s why they’ve hired like a start-up
for this campaign cycle, recognizing that great software is a competitive
advantage and no longer an afterthought you contract out for. And the DNC
gets it, too, and that’s why I’m excited to join them. The chance to
help re-elect this president, restore Democratic majorities in Congress,
and also to help down-ballot Democrats across the country in this and
future campaign cycles is one I couldn’t pass up.&lt;/p&gt;
&lt;p&gt;I’ll be commuting to the DNC’s offices in Washington, D.C. from Baltimore
on a regular basis, though I’ll still be working from home a couple of days
each week, so that I won’t too miss much of &lt;a href=&#34;/blog/2011/08/maxine.html&#34;&gt;this kind of stuff&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It’s a bittersweet development, because I’ll be leaving EveryBlock,
which I helped found 4 years ago. With the success of the &lt;a href=&#34;http://blog.everyblock.com/2011/mar/21/redesign/&#34;&gt;recent
relaunch&lt;/a&gt;, though, I feel now is as good a time as any to step
away. The site is in great hands, and the response from users to the
new version has been enthusiastic. It couldn’t have a better home than
&lt;a href=&#34;http://www.msnbc.com/&#34;&gt;msnbc.com&lt;/a&gt;, who have provided great guidance and resources. I’m
thrilled with the success we’ve had and for how far it’s come, and
I’m confident that it will continue to be the best place on the internet
to help make your block a better place.&lt;/p&gt;
&lt;p&gt;I am particularly grateful for having worked with my great EveryBlock
colleagues. I’m humbled by them and their talents and work ethic. It
was a privilege to learn from them and improve my craft, however modestly,
by their examples.&lt;/p&gt;
&lt;p&gt;For now, I’m focusing on winding down at EveryBlock, and getting prepared
for a new commute (I’ll try to hack it with the MARC train and a bike)
and a campaign season now fully engaged. It’s a thrilling opportunity,
and I hope to make the most of it.&lt;/p&gt;
&lt;p&gt;—&lt;a href=&#34;http://twitter.com/paulsmith&#34;&gt;@paulsmith&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Maxine</title>
    <link href="/blog/2011/08/maxine.html" />
    <id>http://pauladamsmith.com/blog/2011/08/maxine.html</id>
    <updated>2011-08-27T20:10:00Z</updated>
    <content type="html">&lt;p&gt;&lt;a href=&#34;http://www.flickr.com/photos/psmith/6076865981/&#34; title=&#34;P1040879.jpg by pauladamsmith, on Flickr&#34;&gt;&lt;img src=&#34;http://farm7.static.flickr.com/6184/6076865981_a0c284c99a.jpg&#34; width=&#34;500&#34; height=&#34;334&#34; alt=&#34;P1040879.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;One month ago today, Maxine Mills Smith arrived in this world. Her mom gave
birth to her at Mercy Medical Center in Baltimore, Maryland, at six in the
morning. She was, and continues to be, a long and strong gal. She enjoys
being carried about and looking up at the changing scenery. Like her father,
she zonks out to the motion of a vehicle ride, be it stroller or car. She
has healthy lungs, likes to exercise them, and is a vocal chirper. She
has been respecting her mom and dad with 5 and 6-hour stretches of sleep
at night, but likes to mix it up from time to time and throw her mom some
napless curveballs. When she is awake, she is bright and alert. Given the
choice, she’d rather have some light assistance and try to stand and
monster march (I said she was strong) than squirm around on her belly like
a beetle.  Her binky is a frequent companion, and she is a champion eater
of mom’s milk.  The doctors and nurses at the pediatrician’s office
think she is doing fine, and give her an extra wink. We think she’s is
doing fine, too. Family love Maxine. Welcome home, my daughter.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Parsing and formatting date/time in Go</title>
    <link href="/blog/2011/05/go_time.html" />
    <id>http://pauladamsmith.com/blog/2011/05/go_time.html</id>
    <updated>2011-05-20T02:00:00Z</updated>
    <content type="html">&lt;p&gt;Go takes an interesting approach to &lt;a href=&#34;http://golang.org/pkg/time/&#34;&gt;parsing strings to time objects,
and formatting time objects as strings&lt;/a&gt;. Instead of using codes like
most languages to represent component parts of a date/time string
representation—like &lt;code&gt;%Y&lt;/code&gt; for a 4-digit year like “2011” or &lt;code&gt;%b&lt;/code&gt;
for an abbreviated month name like “Feb”—Go uses a mnemonic device:
there is a standard time, which is:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;Mon Jan 2 15:04:05 MST 2006  (MST is GMT-0700)
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Or put another way:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;01/02 03:04:05PM &amp;#39;06 -0700
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Instead of having to remember or lookup the traditional formatting codes for
functions like &lt;code&gt;strftime&lt;/code&gt;, you just count one-two-three-four and each place
in the standard time corresponds to a component of a date/time object (the
&lt;code&gt;Time&lt;/code&gt; type in Go): one for day of the month, two for the month, three for
the hour (in 12-hour time), four for the minutes, etc.&lt;/p&gt;
&lt;p&gt;The way you put this into action is by putting together the parts of
the standard time in a layout string that matches the format of either
the string representation you want to parse into a &lt;code&gt;Time&lt;/code&gt; object or the
opposite direction, when you want to generate a string representation from
an &lt;code&gt;Time&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;Parsing:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;k&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;quot;fmt&amp;quot;&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;quot;time&amp;quot;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;quot;Thu, 05/19/11, 10:47PM&amp;quot;&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;// Writing down the way the standard time would look like formatted our way&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;layout&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;quot;Mon, 01/02/06, 03:04PM&amp;quot;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Parse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;layout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;// =&amp;gt; &amp;quot;Thu May 19 22:47:00 +0000 2011&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Formatting:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;k&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;quot;fmt&amp;quot;&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;quot;time&amp;quot;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SecondsToLocalTime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1305861602&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ZoneOffset&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;2006-01-02 15:04:05 -0700&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;// =&amp;gt; &amp;quot;2011-05-20 03:20:02 -0400&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;There are predefined constants in the &lt;code&gt;time&lt;/code&gt; package for common formats
such as RFCs 822 and 3339.&lt;/p&gt;
&lt;p&gt;The use of a mnemonic over obscure formatting codes I think reflects the
pragmatism of Go’s developers and their focus on creating a language
that makes its users more productive. While it is a break with tradition
to abandon &lt;code&gt;strftime&lt;/code&gt;-style formatting, they probably recognized that most
developers, no matter how experienced, reach for &lt;code&gt;man strftime&lt;/code&gt; or similar
documentation more often than not (hell, I have a mug with the codes printed
on it), and each time they do, it is an expensive context switch, in terms
of lost focus. Writing the standard time down the way yours looks may be
quirky, but it&#39;s easy to recall, and it also happens to match the shape of
your time string, syntatically.&lt;/p&gt;
&lt;p&gt;It’s fascinating to see a language with the pedigree of Go—from the
minds of long-time C and Unix developers—toss aside certain old and
venerable ways of doing things. But it’s consistent with a language
that’s relatively small (in the good way of being comprehensible and
coherent), focused on efficiency, and careful in what it includes.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>A partial list of metaphors, visual and otherwise, anti-skeuomorphism zealots have to tackle to reach utopia</title>
    <link href="/blog/2011/04/floppy.html" />
    <id>http://pauladamsmith.com/blog/2011/04/floppy.html</id>
    <updated>2011-04-05T18:48:00Z</updated>
    <content type="html">&lt;p&gt;&lt;img alt=&#34;icons&#34; src=&#34;/images/icons.jpg&#34; /&gt;
Motivated by irrational hatred and overstated claims of the continuing
utility of a 3.5&#34; floppy disk icon to mean “save”:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Handset icon, meaning “phone,” on every iPhone, Android&lt;/li&gt;
&lt;li&gt;e&lt;strong&gt;mail&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Web&lt;strong&gt;site&lt;/strong&gt; (implies a physical place)&lt;/li&gt;
&lt;li&gt;Wrench or cog icon, meaning “settings” or “preferences”&lt;/li&gt;
&lt;li&gt;Shopping cart icon&lt;/li&gt;
&lt;li&gt;Clock with analog hands, meaning “time” or time-centric application&lt;/li&gt;
&lt;li&gt;Incandescent light bulb, several meanings, including energy settings&lt;/li&gt;
&lt;li&gt;Bound, paper book, meaning “book”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course there are many, many anachronistic interface elements and metaphors
in the world, and &lt;a href=&#34;/blog/2010/10/old_things.html&#34;&gt;we get by okay&lt;/a&gt;. Mainly,
this is because new generations don’t suddenly appear next to us and
start using our computers without any foreknowledge of the metaphorical
items. They spend time learning with the old fogeys for whom information was
sometimes stored inside square pieces of plastic and metal. This overlap is
necessary in general because knowledge about tools is not encoded in our
genetic material. All understanding of &lt;em&gt;use&lt;/em&gt; is part of a multi-layered
strata of culture, experience, and relationships.&lt;/p&gt;
&lt;p&gt;The real problem anti-floppy-disk people have is explaining a harm,
specifically, a harm that matters. Often when we think of user interface
improvements that matter, we think of examples like improving medical devices
to reduce user error, changes that literally save people’s lives. Or
tweaks to software that improve user efficiency and productivity, saving
money. It’s hard to conceive of what might be improved by finding a better
metaphor for “save” other than some designers’ personal sensibilities.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>More Redis internals: Tracing a GET & SET</title>
    <link href="/blog/2011/03/redis_get_set.html" />
    <id>http://pauladamsmith.com/blog/2011/03/redis_get_set.html</id>
    <updated>2011-03-10T19:48:00Z</updated>
    <content type="html">&lt;p&gt;In my &lt;a href=&#34;/articles/redis-under-the-hood.html&#34;&gt;previous article&lt;/a&gt;, I took a
superficial look at how Redis starts up and prepares itself to process
commands. In this article, I&#39;ll follow a &lt;code&gt;GET&lt;/code&gt; and a &lt;code&gt;SET&lt;/code&gt; command as
they move from client through the server and back. The &lt;code&gt;GET&lt;/code&gt; will be for
a key that doesn&#39;t exist, and the &lt;code&gt;SET&lt;/code&gt; will set that key.  Then I&#39;ll look
quickly at a subsequent &lt;code&gt;GET&lt;/code&gt; and how it differs.&lt;/p&gt;
&lt;p&gt;As before, I&#39;m exploring Redis with the source code open in my editor and
indexed with a &lt;code&gt;tags&lt;/code&gt; file, and the Redis server running under &lt;code&gt;gdb&lt;/code&gt; in
another terminal.&lt;/p&gt;
&lt;p&gt;Caveat: this article was written against the codebase of Redis 2.2.1. With
respect to my previous article, for a list of what has changed in Redis since
I wrote it, see this &lt;a href=&#34;http://news.ycombinator.com/item?id=2301804&#34;&gt;comment on
HN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit:&lt;/strong&gt; I made two minor changes based on feedback—Redis keys are not Redis
objects, they are &lt;code&gt;sds&lt;/code&gt; strings; and you don’t have to hack the Makefile to
compile without optimizations.&lt;/p&gt;
&lt;h1&gt;GET&lt;/h1&gt;
&lt;p&gt;Let&#39;s execute the command &lt;code&gt;get users:1234&lt;/code&gt; on Redis.&lt;/p&gt;
&lt;h2&gt;Preparing&lt;/h2&gt;
&lt;p&gt;If you inspect certain variables under &lt;code&gt;gdb&lt;/code&gt;, you might not get what you want.
Instead you see a message like &#34;&lt;value temporarily unavailable, due to
optimizations&gt;.&#34; This is because the compiler has optimized the machine code
in such a fashion that the portion of memory you wanted to look at that was
never used, at least for the variable under inspection. To make stepping
through the code and inspecting a little easier, we make sure that Redis is
not compiled with optimizations. You can do this by either building Redis with
the following invocation:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;n&#34;&gt;make&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;noopt&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;or by setting an environment variable:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;n&#34;&gt;OPTIMIZATION&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;make&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Sending the command from the client&lt;/h2&gt;
&lt;p&gt;If we look at the &lt;code&gt;repl&lt;/code&gt; loop of redis-cli, we see that it uses the
&lt;code&gt;linenoise&lt;/code&gt; library to split the arguments of the command. It dispatches on
the first argument. The loop checks for client commands that aren&#39;t processed
as a command by the Redis server, like &lt;code&gt;exit&lt;/code&gt;/&lt;code&gt;quit&lt;/code&gt;, &lt;code&gt;clear&lt;/code&gt; (to clear the screen),
and &lt;code&gt;connect&lt;/code&gt; (which is a way to connect to a specified Redis server on host
port, instead of the default host of 127.0.0.1 and port of 6379.&lt;/p&gt;
&lt;p&gt;Any other argument is considered the name of a command to send to the server.
The remaining arguments are the arugments for that command.&lt;/p&gt;
&lt;p&gt;We&#39;re trying to get the on-the-wire representation of the &lt;code&gt;get users:1234&lt;/code&gt; command.
redis-cli uses a &lt;code&gt;redisContext&lt;/code&gt; struct to encapsulate the state of the
connection to the server, as well as the output buffer where the command in
the form of the Redis protocol is written for sending to the server. We know
from reading the source of hiredis (the Redis C client library that the redis-cli
program is built on) that the &lt;code&gt;obuf&lt;/code&gt; field is where the raw command is stored:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;cp&#34;&gt;# hiredis.h:107&lt;/span&gt;
&lt;span class=&#34;cm&#34;&gt;/* Context for a connection to Redis */&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;typedef&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;redisContext&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;flags&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;obuf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* Write buffer */&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* Error flags, 0 when there is no error */&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;errstr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* String representation of error when applicable */&lt;/span&gt;

    &lt;span class=&#34;cm&#34;&gt;/* Function set for reply buildup and reply reader */&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;redisReplyObjectFunctions&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;redisContext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If we set a breakpoint on &lt;code&gt;cliReadReply&lt;/code&gt;, we can inspect the output buffer and
see exactly how the command looks as a bytestring bound for the server.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;client $ gdb src/redis-cli
(gdb) b cliReadReply
(gdb) run
Starting program: /home/paul/src/redis-2.2.0-RC2/src/redis-cli 
Reading symbols for shared libraries +. done
redis&amp;gt; get users:1234

Breakpoint 1, cliReadReply (output_raw_strings=0) at redis-cli.c:421
421         if (redisGetReply(context,&amp;amp;_reply) != REDIS_OK) {
(gdb) p context-&amp;gt;obuf 
$1 = 0x100102428 &amp;quot;*2\r\n$3\r\nget\r\n$10\r\nusers:1234\r\n&amp;quot;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We see that the Redis command &lt;code&gt;get users:1234&lt;/code&gt; as entered in our client is
translated to &lt;code&gt;*2\r\n$3\r\nget\r\n$10\r\nusers:1234\r\n&lt;/code&gt;. Any Redis client is
going to convert our command expressed in its respective syntax to the same
on-the-wire format. So in Python:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; redis_client.get(&amp;#39;users:1234&amp;#39;)
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;will send the same &lt;code&gt;*2\r\n$3\r\nget\r\n$10\r\nusers:1234\r\n&lt;/code&gt; bytestring to
the server. &lt;/p&gt;
&lt;p&gt;Let&#39;s print that bytestring to screen and render those `rn&#39;s as line feeds
so we can see an expanded view and get a better look at the protocol.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;*2
$3
get
$10
users:1234
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The first bit is &lt;code&gt;*2&lt;/code&gt;, which tells us that the arity of the command,
including the command name, is 2. That is, the server should expect two
arguments to follow.&lt;/p&gt;
&lt;p&gt;The next bit is &lt;code&gt;$3&lt;/code&gt;, which means that the length of the first argument in
bytes is 3. The argument itself follows, our command name, &lt;code&gt;get&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The next bit after that is &lt;code&gt;$10&lt;/code&gt;, so the length in bytes of the second
argument is 10. Our one and only argument to the command is next,
&lt;code&gt;users:1234&lt;/code&gt;, the key we are trying to &lt;code&gt;get&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Receiving the command on the server&lt;/h2&gt;
&lt;p&gt;If you remember from the last article, &lt;code&gt;readQueryFromClient&lt;/code&gt; is a good place
to set a breakpoint in your debugger on the server side for inspecting an
inbound client command.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;server $ gdb src/redis-server
(gdb) b readQueryFromClient
Breakpoint 1 at 0x100011445: file networking.c, line 882.
(gdb) run redis.conf
Starting program: /home/paul/src/redis-2.2.0-RC2/src/redis-server redis.conf
Reading symbols for shared libraries +. done
[63700] 01 Mar 11:04:40 * Server started, Redis version 2.2.1
[63700] 01 Mar 11:04:40 * The server is now ready to accept connections on port 6379
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now back in the terminal with the client running in the debugger, continue to
send the command to the server, which will stop at the breakpoint we set.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;# client
(gdb) c
Continuing.

# server
Breakpoint 1, readQueryFromClient (el=0x100200000, fd=5, privdata=0x100804e00, mask=1) at networking.c:801
801     void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Let&#39;s step to the following line:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;cp&#34;&gt;# src/networking.c:808&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;nread&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;read&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;buf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REDIS_IOBUF_LEN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If we step to here in our debugger, we see that the server read 30 bytes. If
you count the number of bytes in our Redis protocol-encoded command,
&lt;code&gt;*2\r\n$3\r\nget\r\n$10\r\nusers:1234\r\n&lt;/code&gt;, you&#39;ll see it&#39;s 30. Just for good
measure, let&#39;s look at the 30 bytes beginning at the memory location pointed
to by &lt;code&gt;buf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;(gdb) p nread
30
(gdb) x/30cb buf
0x7fff5fbfeaf0: 42 &amp;#39;*&amp;#39;  50 &amp;#39;2&amp;#39;  13 &amp;#39;\r&amp;#39; 10 &amp;#39;\n&amp;#39; 36 &amp;#39;$&amp;#39;  51 &amp;#39;3&amp;#39;  13 &amp;#39;\r&amp;#39; 10 &amp;#39;\n&amp;#39;
0x7fff5fbfeaf8: 71 &amp;#39;G&amp;#39;  69 &amp;#39;E&amp;#39;  84 &amp;#39;T&amp;#39;  13 &amp;#39;\r&amp;#39; 10 &amp;#39;\n&amp;#39; 36 &amp;#39;$&amp;#39;  49 &amp;#39;1&amp;#39;  48 &amp;#39;0&amp;#39;
0x7fff5fbfeb00: 13 &amp;#39;\r&amp;#39; 10 &amp;#39;\n&amp;#39; 117 &amp;#39;u&amp;#39; 115 &amp;#39;s&amp;#39; 101 &amp;#39;e&amp;#39; 114 &amp;#39;r&amp;#39; 115 &amp;#39;s&amp;#39; 58 &amp;#39;:&amp;#39;
0x7fff5fbfeb08: 49 &amp;#39;1&amp;#39;  50 &amp;#39;2&amp;#39;  51 &amp;#39;3&amp;#39;  52 &amp;#39;4&amp;#39;  13 &amp;#39;\r&amp;#39; 10 &amp;#39;\n&amp;#39;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And we can see our whole command bytestring is there, byte by byte.&lt;/p&gt;
&lt;p&gt;The server has now read in the entirety of our command in one step.  (Because
we had a relatively short command, one that fits inside a kernel buffer, and
we are the only client on a loopback network device, this is the case, but it
need not be. Since Redis is event-driven, this function,
&lt;code&gt;readQueryFromClient&lt;/code&gt;, is called whenever there are bytes from buffers to be
read. If our command was particularly long, or there was a lot of network
contention, the command may take more than one I/O event before it is fully
read. For this reason, Redis builds up a buffer per client and appends bytes
to it on each call to this function. It only proceeds with processing the
command when it has been fully read. But we don&#39;t need to consider this in our
simple example, so we will proceed.)&lt;/p&gt;
&lt;p&gt;We&#39;re going to elide the processing of the input buffer. This is the point
where the server takes the Redis protocol-encoded bytestring of our request
and unpacks it into arguments on the client struct object. If you are
interested in the details of that parsing, examine the function
&lt;code&gt;processMultibulkBuffer&lt;/code&gt; in &lt;code&gt;networking.c&lt;/code&gt;. All we are interested in at this
point is that the &lt;code&gt;argc&lt;/code&gt; member of the client object is the number of command
arguments (counting the command name itself) and &lt;code&gt;argv&lt;/code&gt; is a pointer to the
list of arguments.&lt;/p&gt;
&lt;p&gt;The bit of code we care at this point is &lt;code&gt;processCommand&lt;/code&gt;. The first thing the
server does is look up the command in its command table (see &#34;Setting up
command table&#34; in the previous article, but note that this lookup is now O(1),
see the HN thread linked above). Assuming the command is found (which our
&lt;code&gt;get&lt;/code&gt; will be), the server will double-check that the arity of the command as
defined in the command table matches the number of arguments received from the
client (&lt;code&gt;c-&amp;gt;argc&lt;/code&gt;).&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;cp&#34;&gt;# redis.c:998&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lookupCommand&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ptr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;addReplyErrorFormat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;unknown command &amp;#39;%s&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ptr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REDIS_OK&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arity&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arity&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;
           &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;addReplyErrorFormat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;wrong number of arguments for &amp;#39;%s&amp;#39; command&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REDIS_OK&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Skip down to the end of &lt;code&gt;processCommand&lt;/code&gt;. Because our humble &lt;code&gt;get&lt;/code&gt; is not a
&#34;multi&#34; command like &lt;code&gt;mget&lt;/code&gt;, &lt;code&gt;mset&lt;/code&gt;, etc., it doesn&#39;t require queue-like
processing of the underlying multiple commands, so we go right to &lt;code&gt;call&lt;/code&gt;,
which is where our command is dispatched.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;cp&#34;&gt;# redis.c:953&lt;/span&gt;
&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;redisClient&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;redisCommand&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dirty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;dirty&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dirty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;proc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;dirty&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dirty&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dirty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;appendonly&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dirty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;feedAppendOnlyFile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dirty&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;flags&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REDIS_CMD_FORCE_REPLICATION&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;listLength&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slaves&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;replicationFeedSlaves&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slaves&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;listLength&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;monitors&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;replicationFeedMonitors&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;monitors&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stat_numcommands&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Let&#39;s focus on line 952, &lt;code&gt;cmd-&amp;gt;proc(c);&lt;/code&gt;. This is Redis&#39;s dynamic dispatching
of command function calling. Redis makes this clean and simple by
encapsulating commands and giving all the actual underlying command functions
the same function signature, taking our client object, which carries the
payload of our command&#39;s arguments. So we&#39;re interested in looking into the
details of the Redis command object and the actual function that will handle
our &lt;code&gt;get&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;cp&#34;&gt;# redis.h:504&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;redisCommand&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;redisCommandProc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;proc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;flags&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;cm&#34;&gt;/* Use a function to determine which keys need to be loaded&lt;/span&gt;
&lt;span class=&#34;cm&#34;&gt;     * in the background prior to executing this command. Takes precedence&lt;/span&gt;
&lt;span class=&#34;cm&#34;&gt;     * over vm_firstkey and others, ignored when NULL */&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;redisVmPreloadProc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vm_preload_proc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;cm&#34;&gt;/* What keys should be loaded in background when calling this command? */&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vm_firstkey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* The first argument that&amp;#39;s a key (0 = no keys) */&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vm_lastkey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;cm&#34;&gt;/* THe last argument that&amp;#39;s a key */&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vm_keystep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;cm&#34;&gt;/* The step between first and last key */&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If we pop up to the top of &lt;code&gt;redis.c&lt;/code&gt;, we see the definition of the Redis command
table, and our &lt;code&gt;get&lt;/code&gt; is the first entry.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;cp&#34;&gt;# redis.c:71&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;redisCommand&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;readonlyCommandTable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;get&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getCommand&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;getCommand&lt;/code&gt; is the function that does the actual work for our command.
It&#39;s a thin wrapper for &lt;code&gt;getGenericCommand&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;cp&#34;&gt;# t_string.c:62&lt;/span&gt;
&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getGenericCommand&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;redisClient&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;robj&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lookupKeyReadOrReply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shared&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nullbulk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REDIS_OK&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REDIS_STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;addReply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shared&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wrongtypeerr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REDIS_ERR&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;addReplyBulk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REDIS_OK&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getCommand&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;redisClient&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;getGenericCommand&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The arguments to &lt;code&gt;lookupKeyReadOrReply&lt;/code&gt; are the client object, the key
&lt;code&gt;users:1234&lt;/code&gt; we&#39;re trying to look up, and an object, &lt;code&gt;shared.nullbulk&lt;/code&gt; that
will be the default reply to the client if the key is not found.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;cp&#34;&gt;# db.c:58&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;robj&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;lookupKeyReadOrReply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;redisClient&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;robj&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;robj&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;robj&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lookupKeyRead&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;addReply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;lookupKeyRead&lt;/code&gt; is a thin wrapper for &lt;code&gt;lookupKey&lt;/code&gt; that handles removing keys
that have been set to expire.&lt;/p&gt;
&lt;p&gt;Now we get to the heart of the &lt;code&gt;get&lt;/code&gt; command -- looking up the key in the
database.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;cp&#34;&gt;# db.c:9&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;robj&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;lookupKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;redisDb&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;robj&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;dictEntry&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;de&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dictFind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ptr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;de&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;robj&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dictGetEntryVal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;de&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

        &lt;span class=&#34;cm&#34;&gt;/* Update the access time for the aging algorithm.&lt;/span&gt;
&lt;span class=&#34;cm&#34;&gt;         * Don&amp;#39;t do it if we have a saving child, as this will trigger&lt;/span&gt;
&lt;span class=&#34;cm&#34;&gt;         * a copy on write madness. */&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bgsavechildpid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bgrewritechildpid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lru&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lruclock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vm_enabled&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;storage&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REDIS_VM_MEMORY&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;storage&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REDIS_VM_SWAPPING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
            &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
                &lt;span class=&#34;cm&#34;&gt;/* If we were swapping the object out, cancel the operation */&lt;/span&gt;
                &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;storage&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REDIS_VM_SWAPPING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
                    &lt;span class=&#34;n&#34;&gt;vmCancelThreadedIOJob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
                &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;notify&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;storage&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REDIS_VM_LOADING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

                &lt;span class=&#34;cm&#34;&gt;/* Our value was swapped on disk. Bring it at home. */&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;redisAssert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REDIS_VMPOINTER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vmLoadObject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;dictGetEntryVal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;de&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

                &lt;span class=&#34;cm&#34;&gt;/* Clients blocked by the VM subsystem may be waiting for&lt;/span&gt;
&lt;span class=&#34;cm&#34;&gt;                 * this key... */&lt;/span&gt;
                &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;notify&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;handleClientsBlockedOnSwappedKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stat_keyspace_hits&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stat_keyspace_misses&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Redis uses its own hash table implementation to store keys and their values in
memory. Inside the &lt;code&gt;db&lt;/code&gt; object, the field &lt;code&gt;dict&lt;/code&gt; is a pointer to the hash
value for the current Redis database (remember there can be up to 16 separate
databases in a single Redis server instance, indexed by number).&lt;/p&gt;
&lt;p&gt;First, Redis calls &lt;code&gt;dictFind&lt;/code&gt; with the database&#39;s hash table and a pointer
to the key&#39;s bytestring. &lt;code&gt;dictFind&lt;/code&gt; looks up the hash of the key in the
table, using a standard algorithm that should be familiar to anyone who&#39;s
implemented a hash table (check out &lt;code&gt;dict.c&lt;/code&gt; starting at line 391 if you&#39;re
interested, the table is an array with linked lists for colliding hashes).&lt;/p&gt;
&lt;p&gt;If the key is found in the table, &lt;code&gt;dictFind&lt;/code&gt; returns a pointer to the entry in
the table. Otherwise, it returns &lt;code&gt;NULL&lt;/code&gt;. Back in &lt;code&gt;lookupKey&lt;/code&gt;, if the entry is
not null, Redis retrieves the value (i.e., the Redis object our key
references) from the hash table via &lt;code&gt;dictGetEntryVal&lt;/code&gt; and takes care of a bit
of bookkeeping for expiry and VM, if the key was found, and stats in either
case (hits and misses). If the entry was &lt;code&gt;NULL&lt;/code&gt;, then &lt;code&gt;lookupKey&lt;/code&gt; also returns
&lt;code&gt;NULL&lt;/code&gt;; we&#39;ll see how this is handled by Redis for a reply to the client when
the key is not found, which is the case for us at this stage.&lt;/p&gt;
&lt;p&gt;With the value of &lt;code&gt;lookupKey&lt;/code&gt;, we&#39;ll go back up the stack to our callers. Back
to &lt;code&gt;lookupKeyReadOrReply&lt;/code&gt;, we look at line 60:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;cp&#34;&gt;# t_string.c:60&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;addReply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Since we got &lt;code&gt;NULL&lt;/code&gt; from &lt;code&gt;lookupKey&lt;/code&gt; this time, we call &lt;code&gt;addReply&lt;/code&gt;.  The value
of &lt;code&gt;reply&lt;/code&gt; here comes from the call in &lt;code&gt;getGenericCommand&lt;/code&gt;, and it is
&lt;code&gt;shared.nullbulk&lt;/code&gt;. This field in the global struct object &lt;code&gt;shared&lt;/code&gt; is
initialize thusly:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;cp&#34;&gt;# redis.c:712&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;shared&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nullbulk&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;createObject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;REDIS_STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sdsnew&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;$-1&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\r\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We can see that it is a Redis string object who&#39;s on-the-wire value is
&lt;code&gt;$-1\r\n&lt;/code&gt;, meaning a length of -1, Redis&#39;s way of indicating null to a
client, according to the protocol.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;addReply&lt;/code&gt; builds the reply to the client. It does this by first setting up a
write event on the main event loop listener with &lt;code&gt;_installWriteEvent&lt;/code&gt;. This
makes sure that the reply is written out to the client connection when there
are bytes present in the buffer. Next, Redis adds the reply to the client&#39;s
buffer. If the reply object were an non-string value like an integer, or a
list, or a set, Redis would first decode it to a bytestring that can be
serialized to, for example, on a socket. Redis string objects are encoded
&#34;raw,&#34; or as-is. The &lt;code&gt;nullbulk&lt;/code&gt; object is technically a string object, so no
decoding is necessary in our case. In any case, the reply bytestring is copied
to the client&#39;s reply buffer with &lt;code&gt;_addReplyToBuffer&lt;/code&gt;, which for all intents
and purposes completes the execution of our &lt;code&gt;get&lt;/code&gt; command on the server.&lt;/p&gt;
&lt;p&gt;The client will read the on-the-wire reply of &lt;code&gt;$-1\r\n&lt;/code&gt; and know that it is a
string reply of length -1, and therefore is the null (or &#34;nil,&#34; in the context
of &lt;code&gt;redis-cli&lt;/code&gt;) object, and to convert that into the appropriate object for
the language of the client. Back to our &lt;code&gt;redis-cli&lt;/code&gt; client patiently waiting
for a reply from our breakpointed server, which we continue from, that looks
like:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;(nil)
redis&amp;gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;SET&lt;/h1&gt;
&lt;p&gt;The &lt;code&gt;set&lt;/code&gt; command proceeds much the same way as the &lt;code&gt;get&lt;/code&gt;, up to the point of
command dispatching on the server.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;# client
redis&amp;gt; set users:1234 &amp;quot;Paul Smith&amp;quot;

# server
Breakpoint 1, readQueryFromClient (el=0x100400000, fd=6, privdata=0x100805e00, mask=1) at networking.c:801
801     void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
(gdb) n
802         redisClient *c = (redisClient*) privdata;
(gdb) n
808         nread = read(fd, buf, REDIS_IOBUF_LEN);
(gdb) n
809         if (nread == -1) {
(gdb) print nread
$1 = 47
(gdb) x/47cb buf
0x7fff5fbfeba0: 42 &amp;#39;*&amp;#39;  51 &amp;#39;3&amp;#39;  13 &amp;#39;\r&amp;#39; 10 &amp;#39;\n&amp;#39; 36 &amp;#39;$&amp;#39;  51 &amp;#39;3&amp;#39;  13 &amp;#39;\r&amp;#39; 10 &amp;#39;\n&amp;#39;
0x7fff5fbfeba8: 115 &amp;#39;s&amp;#39; 101 &amp;#39;e&amp;#39; 116 &amp;#39;t&amp;#39; 13 &amp;#39;\r&amp;#39; 10 &amp;#39;\n&amp;#39; 36 &amp;#39;$&amp;#39;  49 &amp;#39;1&amp;#39;  48 &amp;#39;0&amp;#39;
0x7fff5fbfebb0: 13 &amp;#39;\r&amp;#39; 10 &amp;#39;\n&amp;#39; 117 &amp;#39;u&amp;#39; 115 &amp;#39;s&amp;#39; 101 &amp;#39;e&amp;#39; 114 &amp;#39;r&amp;#39; 115 &amp;#39;s&amp;#39; 58 &amp;#39;:&amp;#39;
0x7fff5fbfebb8: 49 &amp;#39;1&amp;#39;  50 &amp;#39;2&amp;#39;  51 &amp;#39;3&amp;#39;  52 &amp;#39;4&amp;#39;  13 &amp;#39;\r&amp;#39; 10 &amp;#39;\n&amp;#39; 36 &amp;#39;$&amp;#39;  49 &amp;#39;1&amp;#39;
0x7fff5fbfebc0: 48 &amp;#39;0&amp;#39;  13 &amp;#39;\r&amp;#39; 10 &amp;#39;\n&amp;#39; 80 &amp;#39;P&amp;#39;  97 &amp;#39;a&amp;#39;  117 &amp;#39;u&amp;#39; 108 &amp;#39;l&amp;#39; 32 &amp;#39; &amp;#39;
0x7fff5fbfebc8: 83 &amp;#39;S&amp;#39;  109 &amp;#39;m&amp;#39; 105 &amp;#39;i&amp;#39; 116 &amp;#39;t&amp;#39; 104 &amp;#39;h&amp;#39; 13 &amp;#39;\r&amp;#39; 10 &amp;#39;\n&amp;#39;
(gdb) print (char *)buf
$2 = 0x7fff5fbfeba0 &amp;quot;*3\r\n$3\r\nset\r\n$10\r\nusers:1234\r\n$10\r\nPaul Smith\r\n&amp;quot;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This time, our protocol-encoded bytestring is 47 bytes long, owing to the
extra argument &#34;Paul Smith&#34; and the length tag it requires. Also notice the
leading &lt;code&gt;*3&lt;/code&gt; indicates there are three arguments: &lt;code&gt;set&lt;/code&gt;, &lt;code&gt;users:1234&lt;/code&gt;, &lt;code&gt;Paul Smith&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&#39;s skip ahead now to the point in &lt;code&gt;call&lt;/code&gt; in &lt;code&gt;redis.c&lt;/code&gt;, after the command has
been looked-up in the command table and the server is about ready to call the
underlying &lt;code&gt;proc&lt;/code&gt; function with the client object argument. The &lt;code&gt;set&lt;/code&gt; command,
in the form of a &lt;code&gt;redisCommand&lt;/code&gt; struct, looks like this:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;cp&#34;&gt;# redis.c:73&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;set&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setCommand&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;REDIS_CMD_DENYOOM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Notice that the arity of the command is 3, which includes the leading command
name, plus key and value, and matches what we expect from the client. The
&lt;code&gt;set&lt;/code&gt; command has a flag that &lt;code&gt;get&lt;/code&gt; did not: the constant &lt;code&gt;REDIS_CMD_DENYOOM&lt;/code&gt;
means that, in out-of-memory situations where Redis can&#39;t allocate any more
memory, the execution of the command should be denied. (The absence of this
flag means that Redis can continue to serve client &#34;read&#34; requests like &lt;code&gt;get&lt;/code&gt;
even when the server can no longer write any new data.)&lt;/p&gt;
&lt;p&gt;I set a breakpoint on &lt;code&gt;setCommand&lt;/code&gt; and let the server continue running until
that point:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;# server
(gdb) b setCommand
Breakpoint 2 at 0x10001a6e2: file t_string.c, line 48.
(gdb) c
Continuing.
Breakpoint 2, setCommand (c=0x100805e00) at t_string.c:48
48          c-&amp;gt;argv[2] = tryObjectEncoding(c-&amp;gt;argv[2]);
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Incidentally, you can inspect the values of the client&#39;s command arguments at
any time, with a simple &lt;code&gt;gdb&lt;/code&gt; invocation. The arguments are of type &lt;code&gt;robj&lt;/code&gt;,
which has a field &lt;code&gt;ptr&lt;/code&gt; that is a pointer to the actual value in memory. Since
in our &lt;code&gt;set&lt;/code&gt; case these are strings, we can inspect them by typecasting to
&lt;code&gt;char *&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;(gdb) p (char *)c-&amp;gt;argv[0]-&amp;gt;ptr
$10 = 0x10032ae78 &amp;quot;set&amp;quot;
(gdb) p (char *)c-&amp;gt;argv[1]-&amp;gt;ptr
$11 = 0x10032b068 &amp;quot;users:1234&amp;quot;
(gdb) p (char *)c-&amp;gt;argv[2]-&amp;gt;ptr
$12 = 0x10032b098 &amp;quot;Paul Smith&amp;quot;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The first thing the server does in &lt;code&gt;setCommand&lt;/code&gt; is encode the value being set
with &lt;code&gt;tryObjectEncoding&lt;/code&gt;. It will try to create an efficient encoding if the
bytestring can be interpreted as an integer, for example. This can save space
especially in the case where many numbers are being stored.  Additionally,
Redis will try to reuse shared integers as values instead of allocating
resources for new ones -- see the previous article for more on the creation
and use of shared integers.&lt;/p&gt;
&lt;p&gt;Once the value being set has been encoded, &lt;code&gt;setGenericCommand&lt;/code&gt; is called
(&lt;code&gt;set&lt;/code&gt; shares &lt;code&gt;setGenericCommand&lt;/code&gt; with the &lt;code&gt;setnx&lt;/code&gt; and &lt;code&gt;setex&lt;/code&gt; commands). From
here, &lt;code&gt;dbAdd&lt;/code&gt; is called, with the client, key, and value as arguments. &lt;code&gt;dbAdd&lt;/code&gt;
will only add the value to the database&#39;s hash table if the key does not
already exist. In our case, since the key &lt;code&gt;users:1234&lt;/code&gt; does not exist, the
value of &lt;code&gt;dictFind&lt;/code&gt; is null, and the function proceeds to add the value with
&lt;code&gt;dictAdd&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dictAdd&lt;/code&gt; takes the dictionary hash table, key, and value as arguments. It
uses &lt;code&gt;_dictKeyIndex&lt;/code&gt; to find the index of a free slot in the hash table for
our new entry. See the implementation in &lt;code&gt;dict.c&lt;/code&gt; and &lt;code&gt;dict.h&lt;/code&gt; for the details
of key hashing, and the structure of the dictionary and its component hash
tables (each Redis dictionary contains two hash tables in order to provide
incremental rehashing as the dictionary grows). &lt;code&gt;dictAdd&lt;/code&gt; allocates memory for
the new entry and stores it in the new index.&lt;/p&gt;
&lt;p&gt;The server returns back up the stack from &lt;code&gt;dictAdd&lt;/code&gt; and &lt;code&gt;dbAdd&lt;/code&gt; to
&lt;code&gt;setGenericCommand&lt;/code&gt;, where it increments the reference count on our new value.
Redis uses reference counting in order to free memory used by values that have
been deleted or have expired. It then &#34;touches&#34; the key so that if any clients
are &lt;code&gt;watch&lt;/code&gt;ing the key, the next &lt;code&gt;exec&lt;/code&gt; command will fail. It also increments
the server&#39;s &lt;code&gt;dirty&lt;/code&gt; flag, which it uses to determine when to write out the
dump file to disk. Finally, it writes out the reply to the client, which is a
shared object, &lt;code&gt;shared.ok&lt;/code&gt;. This is special Redis string object in the
protocol that consists of the bytestring &#34;+OKrn&#34;. Clients will typically
convert this into the equivalent &#34;true&#34; value for their language.&lt;/p&gt;
&lt;h1&gt;GET redux&lt;/h1&gt;
&lt;p&gt;Our key is now set, so we can try the &lt;code&gt;get users:1234&lt;/code&gt; command again and see
how it differs for a found key.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;cp&#34;&gt;# db.c:9&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;robj&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;lookupKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;redisDb&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;robj&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;dictEntry&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;de&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dictFind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ptr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;de&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;robj&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dictGetEntryVal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;de&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

        &lt;span class=&#34;c1&#34;&gt;// ... skipping the lru &amp;amp; vm parts ...&lt;/span&gt;

        &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stat_keyspace_hits&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The point where a &lt;code&gt;get&lt;/code&gt; on an existing key and a &lt;code&gt;get&lt;/code&gt; on a non-existent key
differ is line 11, where the &lt;code&gt;de&lt;/code&gt; entry in the database&#39;s dictionary is found.
&lt;code&gt;dictGetEntryVal&lt;/code&gt; is a simple macro for accessing the field in the &lt;code&gt;de&lt;/code&gt; struct
that carries the value associated with the key. Redis updates its statistics
to indicate a key hit and returns the value object.&lt;/p&gt;
&lt;p&gt;Again, as with the key miss from above (remember the null value is a Redis
object, too), the value is decoded into the Redis bytestring protocol. This is
the response to the client, and we have concluded our &lt;code&gt;GET&lt;/code&gt;/&lt;code&gt;SET&lt;/code&gt;/&lt;code&gt;GET&lt;/code&gt; dance.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>The All-Blue-Collar League</title>
    <link href="/blog/2011/01/bluecollarleague.html" />
    <id>http://pauladamsmith.com/blog/2011/01/bluecollarleague.html</id>
    <updated>2011-01-24T00:22:00Z</updated>
    <content type="html">&lt;p&gt;In honor of the &lt;a href=&#34;http://sportsillustrated.cnn.com/football/nfl/gameflash/2011/01/23/4353_recap.html?&amp;amp;eref=sihp&#34;&gt;all&lt;/a&gt;-&lt;a href=&#34;http://sportsillustrated.cnn.com/football/nfl/gameflash/2011/01/23/4354_recap.html?eref=sihp&#34;&gt;union&lt;/a&gt; Super Bowl, I present the
All-Blue-Collar League, a collection of U.S. professional sports franchises
named after local unions, industry.&lt;/p&gt;
&lt;p&gt;In solidarity:&lt;/p&gt;
&lt;table id=&#34;teams&#34;&gt;
    &lt;tr&gt;
        &lt;th&gt;NFL&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr class=&#34;team packers&#34; title=&#34;Named after the Indian Packing Company&#34;&gt;
        &lt;td&gt;&lt;span&gt;&lt;/span&gt;Green Bay &lt;b&gt;Packers&lt;/b&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class=&#34;team steelers&#34; title=&#34;Pittsburgh’s economy centered around the steel industry for many years.&#34;&gt;
        &lt;td&gt;&lt;span&gt;&lt;/span&gt;Pittsburgh &lt;b&gt;Steelers&lt;/b&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class=&#34;team cowboys&#34; title=&#34;Texas cowboys were freelance livestock herders and handlers.&#34;&gt;
        &lt;td&gt;&lt;span&gt;&lt;/span&gt;Dallas &lt;b&gt;Cowboys&lt;/b&gt;&lt;/td&gt;
    &lt;/tr&gt;

&lt;tr&gt;
        &lt;th&gt;MLB&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr class=&#34;team astros&#34; title=&#34;NASA’s Johnson Space Center and the greater space industry is a huge employer in the Houston region.&#34;&gt;
        &lt;td&gt;&lt;span&gt;&lt;/span&gt;Houston &lt;b&gt;Astros&lt;/b&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class=&#34;team brewers&#34; title=&#34;Named for the city’s association with the beer brewing industry.&#34;&gt;
        &lt;td&gt;&lt;span&gt;&lt;/span&gt;Milwaukee &lt;b&gt;Brewers&lt;/b&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class=&#34;team mariners&#34; title=&#34;The city’s location makes it a natural for many maritime industries, including fishmongering, and fishwivery.&#34;&gt;
        &lt;td&gt;&lt;span&gt;&lt;/span&gt;Seattle &lt;b&gt;Mariners&lt;/b&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class=&#34;team rangers&#34; title=&#34;The Texas Rangers have been a statewide law enforcement agency since 1823, the oldest such agency in the U.S.&#34;&gt;
        &lt;td&gt;&lt;span&gt;&lt;/span&gt;Texas &lt;b&gt;Rangers&lt;/b&gt;&lt;/td&gt;
    &lt;/tr&gt;

&lt;tr&gt;
        &lt;th&gt;NBA&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr class=&#34;team pistons&#34; title=&#34;Detroit is synonymous with the American auto industry, a source of high-quality middle-class jobs for most of the 20th century.&#34;&gt;
        &lt;td&gt;&lt;span&gt;&lt;/span&gt;Detroit &lt;b&gt;Pistons&lt;/b&gt;&lt;/td&gt;
    &lt;/tr&gt;

&lt;tr&gt;
        &lt;th&gt;NHL&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr class=&#34;team oilers&#34; title=&#34;Edmonton is one of Canada’s major oil refinery centers.&#34;&gt;
        &lt;td&gt;&lt;span&gt;&lt;/span&gt;Edmonton &lt;b&gt;Oilers&lt;/b&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Thanks to &lt;a href=&#34;http://twitter.com/kostuch&#34;&gt;@kostuch&lt;/a&gt;, &lt;a href=&#34;http://twitter.com/ikesmith&#34;&gt;@ikesmith&lt;/a&gt;, &lt;a href=&#34;http://twitter.com/joshandrews&#34;&gt;@joshandrews&lt;/a&gt;, &lt;a href=&#34;http://twitter.com/tcarmody&#34;&gt;@tcarmody&lt;/a&gt;,
&lt;a href=&#34;http://twitter.com/lmsahistory&#34;&gt;@lmsahistory&lt;/a&gt;, and &lt;a href=&#34;http://twitter.com/janieporche&#34;&gt;@janieporche&lt;/a&gt; for suggestions.&lt;/p&gt;
&lt;style&gt;
#teams {
    width: 100%;
    margin-bottom: 1em;
}

#teams tr {
    clear: both;
}

#teams th {
    padding: 5px 6px;
}

#teams th {
    background: hsla(215, 35%, 35%, 1.0);
    color: white;
}

#teams td {
    height: 50px;
    line-height: 50px;
    padding: 5px 0;
    border-bottom: 1px solid hsla(215, 35%, 35%, 0.5);
}

#teams td span {
    display: block;
    float: left;
    height: 50px;
    width: 50px;
    margin-right: 10px;
    background-image: url(/images/blue_collar_sprite.png);
    background-repeat: no-repeat;
}

#teams .explanation {
    display: none;
}

.brewers td span { background-position: -50px 0px; }
.cowboys td span { background-position: -100px 0px; }
.mariners td span { background-position: -150px 0px; }
.oilers td span { background-position: -200px 0px; }
.packers td span { background-position: -250px 0px; }
.pistons td span { background-position: -300px 0px; }
.rangers td span { background-position: -350px 0px; }
.steelers td span { background-position: -400px 0px; }
&lt;/style&gt;</content>
  </entry>
  <entry>
    <title>Gold is the same as paper</title>
    <link href="/blog/2011/01/gold.html" />
    <id>http://pauladamsmith.com/blog/2011/01/gold.html</id>
    <updated>2011-01-14T19:38:00Z</updated>
    <content type="html">&lt;div style=&#34;float: right; margin-left: 1em; padding: 5px&#34;&gt;&lt;a
href=&#34;http://www.flickr.com/photos/7159212@N05/442965594/&#34; title=&#34;photo by tao_zhyn on Flickr&#34;&gt;&lt;img
src=&#34;/images/gold.jpg&#34; width=&#34;240&#34; height=&#34;128&#34; alt=&#34;gold coins&#34;
class=&#34;facebook-image&#34;&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;We won’t return to a gold standard because changing to a fiat currency was
one of the great innovations of modern economics. You aren’t literally
and figuratively weighed down by gold, and that allows central banks and
governments to set policy that allows them to rebound from crises, spur
growth, and lift people out of poverty and short lifespans. As &lt;a href=&#34;http://www.thenation.com/audio/157757/breakdown-should-us-return-gold-standard&#34; title=&#34;Episode of The Breakdown with Chris Hayes podcast by The Nation&#34;&gt;Liaquat
Ahamed points out&lt;/a&gt;, the gold standard is also a sure way to get yourself
in a deflationary cycle.&lt;/p&gt;
&lt;p&gt;But, wait! gold bugs will say. That paper isn’t worth the paper it’s
printed on. Gold has &lt;em&gt;real&lt;/em&gt; value, that’s why it was the world’s
currency for many years. The problem with this is that money is a
&lt;a href=&#34;http://en.wikipedia.org/wiki/Turtles_all_the_way_down&#34;&gt;turtles-all-the-way-down&lt;/a&gt; concept. Gold is just as much a pointer
to value as paper is, except it has many more downsides: it’s heavier,
more cumbersome to exchange, and has a fixed supply.&lt;/p&gt;
&lt;p&gt;Gold isn’t valuable in and of itself. You can’t live in gold. You can’t eat
gold. You can’t clothe yourself in gold. A gold coin can’t paint your house,
or build you a website. You could (hypothetically) use it to put your kids
through college, so it that sense it’s valuable to you, but &lt;em&gt;only in its
exchange&lt;/em&gt;, because on the other end, the trustees and professors and janitors
at the college need to live somewhere, eat something, wear something,
and have websites built. And again they exchange it for those goods and
services. So really the only thing that’s intrinsic to this little economy
I’ve just described is the fact that you, the college trustees, the service
providers, et al., all agree on the value or rate of exchange. It’s like
an algebraic equation where constants cancel out — gold is the constant,
so we can abstract it away. It may as well be “neighborhood fun bucks,”
so long as everyone agrees on the rate of exchange for goods and services.&lt;/p&gt;
&lt;p&gt;And there you have it. Economies have nothing to do with the particulars of
their currencies, and everything to do with people and institutions trusting
that, in exchange for some amount, I will receive something of perceived
equal value. Trust, and perception. Currencies are just a convenient
means by which we mitigate that exchange, an abstraction, a stand-in
for a hypothetical exchange, ultimately, an exchange built on trust.&lt;/p&gt;
&lt;p&gt;Interestingly, the only inherent value gold has is in its use as
jewelry. Which, aside from any aesthetic concerns, couldn’t be more
appropriate for our discussion, because people wear gold jewelry &lt;em&gt;as a
signifier of wealth&lt;/em&gt;. A pointer, a marker, an abstraction for the wealth
itself, which, again, is just the potential for exchange.&lt;/p&gt;
&lt;p&gt;It is this essential trust network at the core of economics that explains
why there is so much noise about gold. It reflects a lack of trust on the
part of gold advocates in our central banking and governmental institutions,
which they feel pursue policies that aren’t in their interest, or are in
the interest of undeserving populations. The switch to a gold standard,
therefore, has nothing to do with inflation or any other “economic”
concern, and everything to do with pursuing a political objective. The
market of exchange in this little political economy is for ideas about
reprioritizing our institutions. Which is a legitimate topic of national
debate. But reverting to the gold standard, as a practical economic matter,
would be bonkers.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Taking Go for a spin</title>
    <link href="/blog/2011/01/go.html" />
    <id>http://pauladamsmith.com/blog/2011/01/go.html</id>
    <updated>2011-01-12T12:00:00Z</updated>
    <content type="html">&lt;p&gt;I was struck by the high-level abstractions &lt;a href=&#34;http://golang.org/&#34;&gt;Go&lt;/a&gt;
provides for writing networked clients and servers, even by the standards of
conventionally high-level languages like Python. Given Go’s identification
as a systems programming language, this is initially surprising, because
such languages tend to be low-level for performance reasons (Go does
expose a lot of low-level interfaces through various packages like &lt;code&gt;os&lt;/code&gt;
and &lt;code&gt;syscall&lt;/code&gt;), but of course there would be good support for these
things because Go is a modern language designed by folks with many years
of experience writing networked servers.&lt;/p&gt;
&lt;p&gt;Specifically, the &lt;code&gt;net&lt;/code&gt; package provides the &lt;code&gt;Listener&lt;/code&gt; and &lt;code&gt;Conn&lt;/code&gt; types
that hide many of the details of setting up socket connections. A simple
&lt;code&gt;net.Listen(&#34;tcp&#34;, &#34;:1234&#34;)&lt;/code&gt; is enough to get the equivalent of a listener,
or server, socket. The &lt;code&gt;bufio&lt;/code&gt; package provides buffered read methods,
simplifying common tasks like reading lines from a socket.&lt;/p&gt;
&lt;p&gt;Let’s dive in and take a look at one way to implement a classic echo
server. I tried to use Go’s language features for concurrent communication,
goroutines and channels, at crucial points. Where a different implementation
in different language might fork a new process or spawn a new thread to
handle a new client connection, a goroutine was started and the details
of the connection communicated with a channel.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;k&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;quot;net&amp;quot;&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;quot;bufio&amp;quot;&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;quot;strconv&amp;quot;&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;quot;fmt&amp;quot;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PORT&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3540&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;All Go programs must have a &lt;code&gt;package main&lt;/code&gt;. We declare a number of packages to
be imported, &lt;code&gt;net&lt;/code&gt; and &lt;code&gt;bufio&lt;/code&gt; already mentioned, &lt;code&gt;strconv&lt;/code&gt; for its conversion
function &lt;code&gt;Itoa()&lt;/code&gt; that converts an integer to a string, and &lt;code&gt;fmt&lt;/code&gt; for printing
strings to the console. Our echo server will listen on port 3540.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;k&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;net&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Listen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;tcp&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;quot;:&amp;quot;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;strconv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Itoa&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PORT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;panic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;couldn&amp;#39;t start listening: &amp;quot;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;conns&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;clientConns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;go&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;handleConn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&amp;lt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;conns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Every Go program must have a function &lt;code&gt;main()&lt;/code&gt; in its &lt;code&gt;package main&lt;/code&gt;. We start
by declaring and initializing a new listener for our echo server. We choose
the more generic &lt;code&gt;net.Listen()&lt;/code&gt; over &lt;code&gt;net.TCPListen()&lt;/code&gt;, because we can
conveniently parameterize the type of the listener with a string to the first
argument of &lt;code&gt;Listen&lt;/code&gt;. (It is generally preferred in Go to deal with the most
generic type, or interface, especially when writing function and method
signatures, and either allow a specific type to be inferred by the compiler or
specify it when declaring/initializing a variable.) &lt;code&gt;&#34;:&#34; + strconv.Itoa(PORT)&lt;/code&gt;
is a string concentation expression, and the port constant we defined earlier
is converted to a string. (Strictly, a numeric constant is not an integer of a
particular type, but the string conversion function works here because the
compiler converts the constant into the concrete type to match the function
signature.)&lt;/p&gt;
&lt;p&gt;The idiom for Go when handling multiple return values where the last has an
error type is to check the main object for nil, and then &lt;code&gt;panic()&lt;/code&gt; with the
stringified error object. This is generally preferred over printing to stderr
and using &lt;code&gt;os.Exit()&lt;/code&gt;, because it gives callers higher up the stack the chance
to &lt;code&gt;recover()&lt;/code&gt;, sort of a raise/catch exception flow.&lt;/p&gt;
&lt;p&gt;Using Go’s compact syntax for simultaneous declaration and initialization, we
set &lt;code&gt;conns&lt;/code&gt; to the value of the function call &lt;code&gt;clientConns(server)&lt;/code&gt;. This is
the channel we’ll use for getting new client connections.&lt;/p&gt;
&lt;p&gt;The equivalent of a infinite loop like &lt;code&gt;while True:&lt;/code&gt; or &lt;code&gt;for (;;)&lt;/code&gt; in Go is
&lt;code&gt;for { ... }&lt;/code&gt;. Each time through the loop, we start a goroutine, calling
&lt;code&gt;handleConn()&lt;/code&gt; with the value of the receive operation on our client connections
channel. The unary receive operator &lt;code&gt;&amp;lt;-&lt;/code&gt; blocks until a value is available on
the channel, in our case, a new client having connected.&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;k&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;clientConns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;listener&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;net&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Listener&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;chan&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;net&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Conn&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ch&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;make&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;chan&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;net&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Conn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;go&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;listener&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Accept&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;couldn&amp;#39;t accept: &amp;quot;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
                &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;
            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;++&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;%d: %v &amp;lt;-&amp;gt; %v\n&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LocalAddr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RemoteAddr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;ch&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}()&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ch&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We create a new channel of type &lt;code&gt;net.Conn&lt;/code&gt;, which corresponds to the type that
we’ll get from calling &lt;code&gt;Accept()&lt;/code&gt; on our listener connection object. We start
off a new, anonymous goroutine which runs in an infinite loop, constantly
accepting new connections. &lt;code&gt;listener.Accept()&lt;/code&gt; blocks as long as there are no
new clients to deal with, but since we’re running inside a goroutine and
&#34;detached&#34; from the main program flow, other already-connected clients can
continue to be handled without interruption (this is where a &lt;code&gt;fork()&lt;/code&gt; or a new
thread would happen in a typical server). Instead of &lt;code&gt;panic()&lt;/code&gt;ing here if
there is an error connecting with the client, we simply note it on the console
of the server and move on. We also keep track of the number of clients we’ve
seen with the counter &lt;code&gt;i&lt;/code&gt;. &lt;code&gt;fmt.Printf()&lt;/code&gt; works like you’d expect, though the
&lt;code&gt;%v&lt;/code&gt; format is not like anything in C’s &lt;code&gt;printf()&lt;/code&gt; — it prints a value in a
default format and works for any type, somewhat like &lt;code&gt;repr()&lt;/code&gt; in Python.&lt;/p&gt;
&lt;p&gt;The binary &lt;code&gt;&amp;lt;-&lt;/code&gt; communication operator is used to send the client, of type
&lt;code&gt;net.Conn&lt;/code&gt; to the channel we created at the top. Go has lexical scope (and is
garbage-collected), so &lt;code&gt;ch&lt;/code&gt; is available inside the anonymous goroutine and
after our function returns (because the infinite &lt;code&gt;Accept()&lt;/code&gt;ing for-loop keeps
the goroutine alive).&lt;/p&gt;
&lt;div class=&#34;codehilite&#34;&gt;&lt;pre&gt;&lt;span class=&#34;k&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;handleConn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;client&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;net&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Conn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bufio&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;NewReader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ReadBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sc&#34;&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// EOF, or worse&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;As we saw back in &lt;code&gt;main()&lt;/code&gt;, &lt;code&gt;handleConn()&lt;/code&gt; is invoked as a goroutine with each
new client connection (the connection being received from the other side of
the channel we just created). &lt;code&gt;bufio.NewReader()&lt;/code&gt; wraps the client object with
a nicer interface for reading lines of bytes from. If we decided to use the
&lt;code&gt;Read()&lt;/code&gt; method of the &lt;code&gt;net.Conn&lt;/code&gt; object, our code would be more complex,
having to check for the substring &lt;code&gt;&#34;\n&#34;&lt;/code&gt; and testing for EOF. Instead, we can
treat this as a line-oriented protocol, and simply get a line and write it
back to the client, as long as there are lines to be read.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://gist.github.com/775764&#34;&gt;Here’s the whole thing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The pattern of getting new connections from a channel and starting a goroutine
to handle them is conceptually clean, and also happens to be a straightforward
way to write a multiplexing, concurrent server.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Use Oplop for your web site passwords</title>
    <link href="/blog/2010/12/oplop.html" />
    <id>http://pauladamsmith.com/blog/2010/12/oplop.html</id>
    <updated>2010-12-18T05:52:52Z</updated>
    <content type="html">&lt;div style=&#34;float: right; margin-left: 1em; padding: 5px&#34;&gt;&lt;a href=&#34;http://www.flickr.com/photos/slieschke/226873460/&#34; title=&#34;Secure password of the week by Simon Lieschke, on Flickr&#34;&gt;&lt;img src=&#34;http://farm1.static.flickr.com/85/226873460_c8eabd2911_m.jpg&#34; width=&#34;240&#34; height=&#34;180&#34; alt=&#34;Secure password of the week&#34; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href=&#34;http://news.google.com/?q=gawker+breach&#34;&gt;Gawker breach&lt;/a&gt; made mainstream what’s been known for a
while: we don’t use good passwords, and we use the same password over
and over again on multiple sites, exposing us to a potential chain
reaction of account intrusions if it is uncovered.&lt;/p&gt;
&lt;p&gt;One way to address this problem is to use a password generator—the
idea is that all you have to remember is a single, good, strong
password, and the password generator will spit out a random string of
characters to be used as a password on a particular site. This
generated password is hard for an attacker to guess, and hard for them
to “crack” with password-attacking software. You’re not supposed to
remember or even care what the actual password is: you just remember
the master password. And if one of the sites you have an account with
is compromised, it may suck for you with respect to your sensitive
information on that site, but because the generated password is unique
to the site, you’re safe from having it used against you on other
sites where you have accounts.&lt;/p&gt;
&lt;img src=&#34;/images/oplop-screenshot.png&#34; alt=&#34;Oplop screenshot&#34;
style=&#34;float: left; margin-right: 1em; padding: 5px&#34;&gt;

&lt;p&gt;The password generator I use is called &lt;a href=&#34;https://oplop.appspot.com/&#34;&gt;Oplop&lt;/a&gt;. It’s just a web
site, so you visit it in your browser; there’s nothing to
install. There are two fields to enter—a nickname, and the master
password. The nickname is any name you want to identify the site or
service for which you need a password. After you enter a nickname and
your master password, you click the “Create” button, and an
unguessable password is generated for you in the field below the
button. Enter that password into the site that’s asking you for a
password, and you’re all done. The next time you visit the site and
need to enter your password, you repeat the process exactly to get the
same unique password that’s just for that site.&lt;/p&gt;
&lt;p&gt;There are a few tips and tricks to using Oplop successfully. The
nickname is just a label that you remember to refer to the site you
need a password for, but if it is different by even one character, an
entirely different password will be generated. So it’s important to be
consistent, and ideally use a simple convention so that you enter the
label the same way every time. I’ve chosen a convention of using
all-lowercase and no non-alphanumeric characters, and the domain name
of the site, minus the top-level domain (the .com or .org, etc.). For
example, if I’m on amazon.com, I’ll use “amazon” (without the quotes)
for the nickname. If I was visiting a site with the domain name
“Cat-Pics-123.net”, I’d use “catpics123” for the nickname. Whatever
your convention for nicknames, it should be simple and you should use
it consistently.&lt;/p&gt;
&lt;p&gt;Your master password should be a good one—fairly long and hard to
guess—since it is the key to the kingdom. Security researchers often
praise the idea of “passphrase,” a sentence instead of a single
word. These can often be easier to remember and are just as strong if
not stronger than shorter, gobbledygook passwords, even if the
passphrase is composed of simple words. A four or five word sentence,
separated with spaces, should suffice, although longer passphrases are
even better. In any case, use care when entering your master password
into Oplop. By default, it doesn’t do any checking, so, like in the
case of the nickname, a single character’s difference means a whole
different generated password. You can optionally click on the checkbox
“Validate master password?”, which adds an additional password field
for you to re-enter your master password, providing a simple check
that might catch a typo in the first field.&lt;/p&gt;
&lt;p&gt;The final tip is to cut-and-paste the generated password out of its
field instead of copy-and-paste. It’s not so much a tip per se because
Oplop recommends that you do this right on the page, but it’s
important enough to reiterate. Doing it this way prevents someone from
snooping over your shoulder, or if you are careless and leave the
Oplop page open untentionally on a shared computer.&lt;/p&gt;
&lt;p&gt;You might have stopped short at the notion of a web-based password
generator. Isn’t it insecure to trust a web site to generate a
password for you? The answer is, you are only actually interacting
with your browser—there is no network activity taking place when you
generate a password with Oplop. That is because the entire Oplop
program is just HTML and JavaScript loaded in your browser, and it is
your browser on your local computer that takes the nickname and master
password, performs the cryptographic magic on them, and outputs the
generated password. In fact, Oplop works offline just as well. You can
test it by visiting the site and bookmarking it on your iPhone or
Android, deleting the browser window, putting the phone in airplane
mode, then loading Oplop from the bookmark. It works just the same as
if you were connected to the internet.&lt;/p&gt;
&lt;p&gt;The browser-centric nature of Oplop gets to another key concept about
it—there’s nothing to install. In fact, it is essentially already
installed on any internet-enabled device with a JavaScript-enabled
browser. There’s no central database of account names and generated
passwords, like you might expect, and which password generators like
1Password and Password Gorilla are built around. These programs work
similarly to Oplop in the end result, but their central database
presents a user experience problem—it needs to be shared among the
computers you want to use the program on. This can make it difficult
to retrieve a password if you are on your friend’s laptop or a PC at
an internet café. Not only do you have to install the password
generator software itself, if you are allowed to by policy of the
computer’s owner or manager, you have to synchronize the central
database with the computer. By simply eschewing the notion of storing
account names and passwords, Oplop provides a universally-accessible
password management tool. Those unique generated passwords are just
ephemera, the results of combining the secret you keep in your head
(your master password), the site nicknames, and a cryptographic
function in your computer. Even the notion of the “master password” is
turned on its head—it’s not unlocking some database of passwords, it’s
&lt;a href=&#34;http://code.google.com/p/oplop/wiki/HowItWorks&#34;&gt;combined with the nickname to make a cryptographic hash&lt;/a&gt;, the
bits of which make up the final generated password. You could start
using a different master password at any time, which essentially would
invalidate any extant passwords generated with the old one (you still
would have to manually go in and update each password on each site,
though).&lt;/p&gt;
&lt;p&gt;There are other approaches to securing your passwords, including
&lt;a href=&#34;http://www.schneier.com/blog/archives/2005/06/write_down_your.html&#34;&gt;writing them down&lt;/a&gt;. In fact, if you have trouble
remembering strong passwords or passphrases of sufficient length, you
might consider writing down your Oplop master password on a slip of
paper you keep in your wallet.&lt;/p&gt;
&lt;p&gt;Oplop is not perfect—it outputs a fixed style of generated passwords
that may not meet the password criteria for various sites and
services, which require certain lengths, or a certain mix of
characters. It also doesn&#39;t address the need of strong,
crypotgraphically-secure storage of ad-hoc information such as credit
card numbers and other sensitive account information, which are often
stored alongside passwords and account names in more traditional
central database-style password generator programs. But this is by
design and not a failing of Oplop. I continue to use Password Gorilla
for this scenario, especially for protecting financial
information. Also, there are certain &lt;a href=&#34;http://code.google.com/p/oplop/wiki/ThreatModel&#34;&gt;threats Oplop can’t protect
against&lt;/a&gt;, And it’s worth understanding what they are before
you start using it.&lt;/p&gt;
&lt;p&gt;Oplop addresses the proliferation of passwords across multiple web
site accounts, is simple to use, and works everywhere there’s a
browser. So stop using “letmein” for all your web site accounts—you’d
be much better off plugging that in to Oplop as your master
password. But don’t. Use a better one.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>del.icio.us is dead, long live del.icio.us</title>
    <link href="/blog/2010/12/delicious.html" />
    <id>http://pauladamsmith.com/blog/2010/12/delicious.html</id>
    <updated>2010-12-17T05:55:03Z</updated>
    <content type="html">&lt;p&gt;&lt;img src=&#34;/images/delicious-logo.png&#34; alt=&#34;Delicious logo&#34;
style=&#34;float: right; margin-left: 1em; padding: 5px&#34;&gt; It slipped today
that Yahoo! will soon to shut down &lt;a href=&#34;http://delicious.com/&#34;&gt;Delicious&lt;/a&gt;, née
del.icio.us, the social bookmarking site. When it became obvious a few
years ago care and feeding of the site had more or less stopped, I
fled the service, like many other users, for the clones.&lt;/p&gt;
&lt;p&gt;Delicious was important for two reasons. It was all about
discovery—what your friends and the other interesting people you were
following were reading. Predating Digg and reddit, it was the first
service to do what Twitter and Facebook now do so well—point you at a
URL you will probably be interested in, by virtue of having been
vetted by your social network.&lt;/p&gt;
&lt;p&gt;It was also important because it popularized &#34;folksonomies,&#34; the
now-ubiqitous act of tagging items as a lightweight, and therefore
actually used and useful, alternative to categorization. You can thank
del.icio.us for tag clouds and high-quality Flickr searches, for
example.&lt;/p&gt;
&lt;p&gt;Delicious was internet plumbing, but it never became essential
internet plumbing. You could automatically update your blog from it
with what you were reading (and so many people did that they stopped
writing in long-form and just published from their Delicious accounts
a link and some commentary, it resembled an early Twitter-esque
microblog in that way). Lots of people offloaded their brains to it
(especially reference material and how-to guides and programming tips,
learning stuff they intended to come back to later). But unlike its
big Yahoo! sister Flickr, which has become an essential pipeline for
web images, Delicious never grew much beyond what it was in the early
days, never caught fire as a social network in its own right despite
millions of users. Whether this was due to neglect or mismanagement or
cluelessness, in any case, it was a missed opportunity, to become
essential.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/#!/simonw/status/15519434139508736&#34;&gt;People&lt;/a&gt; &lt;a href=&#34;https://twitter.com/#!/michael_nielsen/status/15511360536313857&#34;&gt;are&lt;/a&gt; &lt;a href=&#34;https://twitter.com/#!/michael_nielsen/status/15515090346315776&#34;&gt;wondering&lt;/a&gt; if Yahoo!
understands what the shutdown means for their reputation, when it
comes to safeguarding user data or being reliably available. It&#39;s a
classic &lt;a href=&#34;http://www.dataliberation.org/&#34;&gt;data liberation&lt;/a&gt; problem, and if Yahoo! doesn&#39;t make
it easy for users to take their bookmarks out of Delicious (or their
photos out of Flickr for that matter), folks might not trust a future
Yahoo! product with their data.&lt;/p&gt;
&lt;p&gt;Bookmarking lives on despite the fact that you can pretty much Google
anything, replacing the offboard-brain reference index, and that
social network-based discovery is now dominated by Twitter and
Facebook—people still like being able to curate their own little
slice of the web. &lt;a href=&#34;http://pinboard.in/&#34;&gt;pinboard.in&lt;/a&gt; is one post-Delicious site
that looks particularly promising and vital; tellingly, it refers to
itself as anti-social bookmarking.&lt;/p&gt;
&lt;p&gt;Farewall, Delicious—for a few years at least, you were essential to
&lt;a href=&#34;http://delicious.com/thaislump&#34;&gt;me&lt;/a&gt;.&lt;/p&gt;</content>
  </entry>
  </feed>
