<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
    <title>anil.recoil.org</title>
    <description>anil madhavapeddy :: no content, no fuss</description>
    <link>http://anil.recoil.org/</link>
    <copyright>Copyright (C) 2002-2010 Anil Madhavapeddy</copyright>
    
    
    <item>
      <title>Yurts for Digital Nomads</title>
      <link>http://anil.recoil.org/2010/04/29/yurts-for-digital-nomads.html</link>
      <pubDate>2010-04-29T00:00:00+01:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2010/04/29/yurts-for-digital-nomads</guid>
      <description>&lt;p&gt;The App Engine data collector for Personal Containers is coming on nicely, and is on track for an alpha preview release &lt;a href='http://github.com/avsm/perscon/blob/master/README.md'&gt;fairly soon&lt;/a&gt;. Working with AppEngine has been interesting; it&amp;#8217;s got excellent availability and you can&amp;#8217;t beat the price (free), but coding robust Python that doesn&amp;#8217;t trip over the tight resource limits for individual requests, asynchronous tasks and queries is tricky. While it is good for small records such as my &lt;a href='http://github.com/avsm/perscon/tree/master/plugins/iPhone/'&gt;iPhone&lt;/a&gt; or Find My iPhone &lt;a href='http://github.com/avsm/perscon/blob/master/appengine/perscon/drivers/fmi.py'&gt;GPS traces&lt;/a&gt; traces, it doesn&amp;#8217;t work so well with my gigabytes of photographs or decades of e-mail.&lt;/p&gt;

&lt;p&gt;This confirmed our earlier intuition that there is no one perfect solution for personal data handling; instead, we need to &lt;em&gt;embrace diversity&lt;/em&gt; and construct an infrastructure that can cope with change over the coming decades. Mobile programming has changed beyond recognition in just a few years, and cloud providers are specialising in different ways (e.g. &lt;a href='http://www.picloud.com/'&gt;PiCloud&lt;/a&gt; for simple compute, or &lt;a href='http://aws.amazon.com'&gt;EC2&lt;/a&gt; for fancy services like elastic &lt;a href='http://aws.amazon.com/elasticloadbalancing/'&gt;load balancing&lt;/a&gt;).&lt;/p&gt;
&lt;a href='http://anil.recoil.org/images/nomads-diagram.png'&gt;&lt;img src='http://anil.recoil.org/images/nomads-diagram-300.png' style='float:right' /&gt;&lt;/a&gt;
&lt;p&gt;So to recognise this, we are building components that all interoperate with your personal data, keep it secure, and ensure it persists for more than a few years. &lt;a href='http://www.malteschwarzkopf.de/'&gt;Malte Schwarzkopf&lt;/a&gt; came up with the term &amp;#8220;digital &lt;a href='http://en.wikipedia.org/wiki/Yurt'&gt;yurts&lt;/a&gt;&amp;#8221;, and it&amp;#8217;s stuck. We&amp;#8217;ve written a &lt;a href='http://perscon.net/papers/digital-yurts-draft1.pdf'&gt;draft paper&lt;/a&gt; about it, and would love to hear your comments and feedback on the approach.&lt;/p&gt;

&lt;p&gt;There are some interesting recent trends that make doing this particularly important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The New York Times wrote about the &lt;a href='http://www.nytimes.com/2010/05/02/magazine/02self-measurement-t.html'&gt;data-driven life&lt;/a&gt; increasingly influencing our decision making. Current sensor data such as GPS traces are just harbringers for the privacy disaster that would be information such as heart rates or your consumption habits getting into the public domain. &lt;em&gt;(link via &lt;a href='http://www.cl.cam.ac.uk/~dgm36/'&gt;Derek Murray&lt;/a&gt;)&lt;/em&gt;.&lt;/li&gt;

&lt;li&gt;Facebook has announced a brand new API platform to get access to your information. The &lt;a href='http://eff.org'&gt;EFF&lt;/a&gt; has a fantastic timeline of &lt;a href='http://www.eff.org/deeplinks/2010/04/facebook-timeline'&gt;Facebook&amp;#8217;s Eroding Privacy&lt;/a&gt; over the last five years, to demonstrate how unsafe it is to trust your data to any third-party. We&amp;#8217;ve started developing an information dump plugin for Facebook, but the API just changed mid-way and so it has to be started again (volunteers welcome!).&lt;/li&gt;

&lt;li&gt;In the UK, the &lt;a href='http://en.wikipedia.org/wiki/Digital_Economy_Act_2010'&gt;Digital Economy Act&lt;/a&gt; is an extremely controversial act that makes anonymity and privacy all the more important. We&amp;#8217;re assembling an open-source &lt;a href='http://www.scribd.com/doc/28393106/Using-Dust-Clouds-to-Enhance-Anonymous-Communication'&gt;dust cloud&lt;/a&gt; that integrates Tor into personal containers to automatically grant you anonymity as you communicate with your friends.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you&amp;#8217;re interested, join our &lt;a href='http://perscon.net/contact.html'&gt;group&lt;/a&gt; or contact &lt;a href='http://anil.recoil.org'&gt;me&lt;/a&gt; directly. At this stage, you need desire and the ability to hack code, but things are settling down over the next few months&amp;#8230;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Pulling together a user interface</title>
      <link>http://anil.recoil.org/2010/04/15/uiprototype.html</link>
      <pubDate>2010-04-15T00:00:00+01:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2010/04/15/uiprototype</guid>
      <description>&lt;p&gt;We&amp;#8217;ve been &lt;a href='http://github.com/avsm/perscon'&gt;hacking&lt;/a&gt; away on fleshing out the &lt;a href='http://code.google.com/appengine'&gt;App Engine&lt;/a&gt; node for personal containers. We&amp;#8217;re building this node first because, crucially, deploying an App Engine VM is free to anyone with a Google account. &lt;a href='http://anil.recoil.org/images/perscon-extjs.png'&gt;&lt;img src='http://anil.recoil.org/images/perscon-extjs-thumb.png' style='float:right' /&gt;&lt;/a&gt; The service itself is limited since you can only respond to HTTP or XMPP requests and do HTTP fetches, and so its primary use is as an always-on data collection service with a webmail-style UI written using &lt;a href='http://www.extjs.com/'&gt;extjs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Personal containers gather data from a wide variety of sources, and normalise them into a format which understands people (address book entries, with a set of services such as e-mail, phone, IM and online IDs), places (GPS, WOEID), media (photos, movies) and messages (Tweets, emails, Facebook messages). I&amp;#8217;ll post more about the data model behind personal containers in a follow-up as the format settles.&lt;/p&gt;

&lt;p&gt;The App Engine node has a number of plugins to gather data and aggregate them into a single view (see screenshot). Plugins include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://github.com/avsm/perscon/tree/master/plugins/iPhoto/'&gt;iPhoto&lt;/a&gt; &lt;img src='http://anil.recoil.org/images/iphoto_30x30.png' width='15' /&gt; extracts location (via EXIF), people present (associated via &lt;a href='http://gizmodo.com/5141741/what-to-know-about-iphoto-09-face-detection-and-recognition'&gt;faces&lt;/a&gt;), and of course, the actual photograph.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://github.com/avsm/perscon/tree/master/plugins/Adium/'&gt;Adium&lt;/a&gt; &lt;img src='http://anil.recoil.org/images/chat_30x30.png' width='15' /&gt; logs all IMs into a threaded chat view.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://github.com/avsm/perscon/tree/master/plugins/iPhone/'&gt;iPhone&lt;/a&gt; &lt;img src='http://anil.recoil.org/images/phone_30x30.png' width='15' /&gt; uses the backup files on a Mac to extract SMS messages, phone call records (and it could also get photographs and browsing history, although it currently doesn&amp;#8217;t). An AppEngine tracker can also use &lt;a href='http://www.apple.com/mobileme/features/find-my-iphone.html'&gt;FindMyIPhone&lt;/a&gt; to poll your iPhone regularly to keep track of your location without publishing it to Google or Yahoo (and hopefully in iPhone 4.0, we can operate as a background service at last!).&lt;/li&gt;

&lt;li&gt;&lt;a href='http://github.com/avsm/perscon/tree/master/appengine/twitter.py'&gt;Twitter&lt;/a&gt; &lt;img src='http://anil.recoil.org/images/twitter_30x30.png' width='15' /&gt; runs directly on AppEngine (authenticated via OAuth) and synchronizes with a Twitter feed.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://github.com/avsm/perscon/tree/master/plugins/MacOS-SyncServices/'&gt;SyncServices&lt;/a&gt; hooks into the MacOS X &lt;a href='http://developer.apple.com/macosx/syncservices.html'&gt;sync framework&lt;/a&gt; and initially subscribes to Address Book updates. This seems to be the first open-source sync alternative to the expensive Mobile Me, as far as I can tell. I&amp;#8217;m planning to expand this to also subscribe to the full set of sync information (e.g. calendars).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;#8217;m switching tacks briefly; we received an &lt;a href='http://aws.amazon.com/education/aws-in-education-research-grants/'&gt;Amazon Research Grant&lt;/a&gt; recently and I&amp;#8217;m building a node that runs as a Linux server to act as a longer-term archival and search server. This is being written in OCaml and uses &lt;a href='http://1978th.net/tokyocabinet/'&gt;Tokyo Cabinet&lt;/a&gt; (with Jake Donham&amp;#8217;s excellent &lt;a href='http://github.com/jaked/otoky'&gt;bindings&lt;/a&gt;) and so should be speedy and a useful alternative implementation of the HTTP REST interface. The plan is to automatically synchronize meta-data across all the nodes of a personal container, but store large and historical data away from expensive cloud storage such as App Engine.&lt;/p&gt;

&lt;p&gt;There are lots more plugins in development, such as &lt;a href='http://foursquare.com'&gt;Foursquare&lt;/a&gt; and &lt;a href='http://gowalla.com'&gt;Gowalla&lt;/a&gt; OAuth collectors, an &lt;a href='http://github.com/avsm/perscon/tree/master/android'&gt;Android&lt;/a&gt; mobile application to upload location and contacts information, and Google GData synchronization. If you&amp;#8217;re interested in one of these or something else, please do &lt;a href='http://perscon.net/contact.html'&gt;get in touch&lt;/a&gt; or just fork the &lt;a href='http://github.com/avsm/perscon'&gt;project&lt;/a&gt; and start hacking!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Opening a website</title>
      <link>http://anil.recoil.org/2010/03/29/intro.html</link>
      <pubDate>2010-03-29T00:00:00+01:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2010/03/29/intro</guid>
      <description>&lt;p&gt;We&amp;#8217;ve been working away at building a new type of database to help individuals keep reigns on their ever-increasing personal digital information. The first prototypes run freely on &lt;a href='http://code.google.com/appengine'&gt;Google App Engine&lt;/a&gt; to gather your data behind-the-scenes, and we are working on more advanced versions that run on embedded devices and the cloud.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re interested in keeping track of your personal data, you can start off with the &lt;a href='http://perscon.net/install.html'&gt;installation&lt;/a&gt; instructions to clone your own version. After that, read up on the &lt;a href='http://perscon.net/design.html'&gt;design&lt;/a&gt; of the system (which is still changing as we research new ideas around it). When you find something you want to fix, or add a new plugin data source, just clone the &lt;a href='http://github.com/avsm/perscon'&gt;code&lt;/a&gt; and send us back fixes!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>C#, F# and Other Programming Language Fun at PDC 2008</title>
      <link>http://anil.recoil.org/2008/11/01/c-f-and-other-programming-language-fun-at-pdc-2008.html</link>
      <pubDate>2008-11-01T00:00:00+00:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2008/11/01/c-f-and-other-programming-language-fun-at-pdc-2008</guid>
      <description>&lt;p&gt;My favourite session of &lt;a href='http://www.microsoftpdc.com/'&gt;PDC 2008&lt;/a&gt; was by &lt;a href='http://en.wikipedia.org/wiki/Anders_Hejlsberg'&gt;Anders Hejlsberg&lt;/a&gt; as he described the &lt;a href='http://channel9.msdn.com/pdc2008/TL16/'&gt;Future of C#&lt;/a&gt;. Anders is an excellent speaker, and it was educational watching how he made fairly complex type systems come across to an audience more used to simpler programming languages. I say this after attending &lt;a href='http://www.icfpconference.org/'&gt;ICFP&lt;/a&gt; recently, where that wasn&amp;#8217;t true of all the presentations!&lt;/p&gt;

&lt;p&gt;The high-level message was exactly what I wanted to hear: in order to exploit multi-core processors more effectively, Microsoft&amp;#8217;s languages are focussing on improvements in three areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Declarative&lt;/em&gt; constructs: making the programmer define overall goals and constraints enables a tool-chain to more effectively scale computation across multiple processors. An example of this in C# 3.0 is the &lt;a href='http://msdn.microsoft.com/en-us/library/bb308959.aspx'&gt;Language Integrated Query&lt;/a&gt; (LINQ) domain specific language for defining queries.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;em&gt;Dynamic&lt;/em&gt; interoperability: Although Anders is a big fan of static type systems (robust, high-performance, enable intelligent tools), he pointed out that a lot of the systems that C# programmers have to deal with are fundamentally dynamic. Examples are web interfaces such as SOAP/REST APIs, COM objects for talking to other Microsoft applications, or scripting language integration (e.g. Python or Ruby).&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;em&gt;Concurrent&lt;/em&gt; programming: dealing with multiple cores requires splitting up computation into parallel threads, and the resulting parallel mass of code is often hard to debug (e.g. difficulties of reproducing obscure concurrency issues) and statically reason about.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An interesting aside was his assertion about &amp;#8220;co-evolution&amp;#8221;. Microsoft have a number of languages which have recently been unified under the CLR, such as Visual Basic, C# and most recently &lt;a href='http://research.microsoft.com/fsharp/'&gt;F#&lt;/a&gt;. Rather than have one language race ahead of the others, they like to &amp;#8220;borrow&amp;#8221; features as appropriate into other languages. This is obviously made easier by having a common run-time foundation, and an example of co-evolution is the introduction of &lt;a href='http://blogs.msdn.com/ericwhite/pages/Lambda-Expressions.aspx'&gt;lambdas&lt;/a&gt; into C# 3.0 as obviously seen in F#.&lt;/p&gt;

&lt;h2 id='concurrency'&gt;Concurrency&lt;/h2&gt;

&lt;p&gt;Anders observes that all the attempts to automatically parallelize software has not yielded good results in the past, and so support needs to be built into the language to do &amp;#8220;top-down&amp;#8221; parallelism instead of the compiler inferring it from the bottom-up. To this end, they are introducing &lt;a href='http://blogs.msdn.com/somasegar/archive/2007/11/29/parallel-extensions-to-the-net-fx-ctp.aspx'&gt;parallel extensions&lt;/a&gt; into the .NET framework. This makes use of functional features to parallelize code, including LINQ queries or CPU-intensive compute.&lt;/p&gt;

&lt;p&gt;For an example of how this code looks, check out Jurgen Van Gael&amp;#8217;s post on using &lt;a href='http://undirectedgrad.blogspot.com/2007/12/f-and-task-parallel-library.html'&gt;F# with the Task Parallel Library&lt;/a&gt;. I wanted to learn more about this, and wandered over to the Hands On Labs where F# and Visual Studio 10 were all pre-installed. I then ran into an extremely cool feature of F#&amp;#8230; &lt;a href='http://blogs.msdn.com/dsyme/archive/2007/10/11/introducing-f-asynchronous-workflows.aspx'&gt;asynchronous workflows&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;F# introduces an extension to the usual &lt;code&gt;let&lt;/code&gt; ML operator in the form of &lt;code&gt;let!&lt;/code&gt;. As &lt;a href='http://blogs.msdn.com/dsyme/'&gt;Don Syme&lt;/a&gt; explains on his &lt;a href='http://blogs.msdn.com/dsyme/archive/2007/10/11/introducing-f-asynchronous-workflows.aspx'&gt;blog&lt;/a&gt; ), this can be interpreted as &lt;em&gt;&amp;#8220;run the asynchronous computation on the right and wait for its result. If necessary suspend the rest of the workflow as a callback awaiting some system event&amp;#8221;&lt;/em&gt;. So this construct lets you write straight-line code which can potentially block, without the hassle of spawning threads or encoding continuation passing style constructs in the code. Already a nice improvement over OCaml! (although to be fair I&amp;#8217;ve not had a chance to check out some of the &lt;a href='http://camlp3l.inria.fr/eng.htm'&gt;parallel OCaml extensions&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id='dynamic_programming'&gt;Dynamic Programming&lt;/h2&gt;

&lt;p&gt;Dynamic programming is the main focus of C# 4.0. In order to support dynamic objects as first-class citizens in a statically typed world, they introduce a &lt;code&gt;dynamic&lt;/code&gt; static type. This forces all method resolution on that object to happen at run-time and disables static checks by the compiler (aside from looking from mixups between dynamic and static objects). The &lt;code&gt;dynamic&lt;/code&gt; type now makes it easy to wrap support for Python, Ruby and Javascript, since the relevant dispatch functions can all be hidden away in the method resolver at run-time, leaving the programmer with a single syntax for invoking methods across these different languages.&lt;/p&gt;

&lt;p&gt;The actual definition of method resolvers is pretty straight-forward; he demonstrated custom getters and setters (similar to Python for example) by using the &lt;code&gt;IDynamicObject&lt;/code&gt; interface to define actions to take when properties are accessed. His example did the usual dictionary wrapper which mapped setting arbitrary properties onto an internal dictionary variable.&lt;/p&gt;

&lt;p&gt;Another improvement in this space is the addition of optional arguments and labelled arguments. Both of these have well-defined semantics (optional arguments have to come after non-optional ones, and evaluation of arguments is left-to-right) and are purely syntactic improvements with no run-time cost. One of the best examples he showed of using these around COM interoperability. In current versions of C#, due to the lack of named arguments a common function such as &lt;em&gt;&amp;#8220;Save As&amp;#8221;&lt;/em&gt; might require 12 or more stub arguments to be specified as &lt;code&gt;ref missing&lt;/code&gt;. Now, those long, repetitive lines can be folded down to only the arguments which are required.&lt;/p&gt;

&lt;p&gt;Sort of related to the earlier co-evolution was his demonstration of how similar Javascript and C# syntax is now with this new support. He took a Silverlight 2 code snippet written in Javascript and ported it over to C# 4.0 with some very mechanical changes. The languages are definitely converging fast!&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re interested in checking out more on this topic, look at &lt;a href='http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython'&gt;IronPython&lt;/a&gt;, the &lt;a href='http://en.wikipedia.org/wiki/Dynamic_Language_Runtime'&gt;Dynamic Language Runtime&lt;/a&gt; (DLR), and the &lt;a href='http://channel9.msdn.com/pdc2008/TL10/'&gt;TL10&lt;/a&gt; session on dynamic languages on .NET. The DLR is currently maintained as part of IronPython, but is being moved out to sit on top of the CLR for more languages such as Visual Basic, Javascript or COM. The DLR covers common optimizations which are useful for scripting languages, such as call-site caching, dynamic dispatch and expression trees (e.g. for LINQ). The DLR has a bunch of binders which bridge between different backends such as .NET, Silverlight, the native Python or Ruby backends, or COM applications such as Microsoft office.&lt;/p&gt;

&lt;h2 id='metaprogramming'&gt;Meta-programming&lt;/h2&gt;

&lt;p&gt;Later on at the &lt;a href='http://channel9.msdn.com/pdc2008/TL57/'&gt;Future of Programming Languages&lt;/a&gt; panel session, Anders talked about meta-programming as being one of the future improvement he&amp;#8217;s looking at. Currently, there is a lot of ad-hoc code generation in place when creating Windows applications, and unifying this into the language would give safety and maintainability improvements.&lt;/p&gt;

&lt;p&gt;In order to do this, for C# 5.0 they are rewriting the compiler to be self-hosting in C#, since it has historically been a C++ application. This permits them to switch the compiler from being a traditional &amp;#8220;black box&amp;#8221; compiler to a hosted .NET service which can be called directly by .NET programs in order to do dynamic run-time compilation of code. Other portions of the compiler chain are also exposed to permit incremental program construction by third-party code.&lt;/p&gt;

&lt;p&gt;He demonstrated this with a pretty nifty C# top-level, into which he directly typed Winforms code to construct a window with a few simple buttons using the C# compiler server. Not to be outdone by this, &lt;a href='http://tirania.org/'&gt;Miguel de Icaza&lt;/a&gt; promptly upstaged Anders at his (fantastic) &lt;a href='http://channel9.msdn.com/pdc2008/PC54/'&gt;Mono 2.2 session&lt;/a&gt;. He demonstrated the new C# shell which is present in Mono trunk builds and can essentially be used like an OCaml or Python top-level to mess around and manipulate C# code. He also talked about embedded Mono and SIMD support which pushes their compiler ahead of Microsoft&amp;#8217;s in the 3D performance game.&lt;/p&gt;

&lt;h2 id='summary'&gt;Summary&lt;/h2&gt;

&lt;p&gt;I&amp;#8217;m firmly convinced about the potential of F# now. I had the opportunity at the Open Spaces area to quiz &lt;a href='http://weblogs.asp.net/Scottgu/'&gt;Scott Guthrie&lt;/a&gt; about whether or not F# was a toy language. He replied using the same arguments as Anders that the higher-level language approach (declarative, functional) was very important strategically to Microsoft to let their developer platform continue to survive in a multi-core world.&lt;/p&gt;

&lt;p&gt;This boils down to the individual languages not being that important any more (as seen by the sharing of features between C# and F#), and the underlying execution layer (the CLR/DLR) adding efficient support. Now any old language can adopt higher-level features without having to re-do all the optimization grunt work again and again. Much like &lt;a href='http://www.xen.org'&gt;Xen&lt;/a&gt; offers a new golden age for innovative new OS research by freeing programmers from writing a million hardware device drivers, it looks like .NET is ushering in a new age of programming language innovation!&lt;/p&gt;

&lt;p&gt;Inspired by the PDC talks, I&amp;#8217;ve got &lt;a href='http://monodevelop.com/'&gt;MonoDevelop&lt;/a&gt; and F# up and running on my Macbook Air, and am just playing with &lt;a href='http://gtk-sharp.sourceforge.net/'&gt;GTK#&lt;/a&gt; and &lt;a href='http://www.mono-project.com/CocoaSharp'&gt;CocoaSharp#&lt;/a&gt;. If this works as well as OCaml, then it might finally be time to abandon the old stalwart and move to a new language for my day-to-day stuff!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Working through TED videos on the train</title>
      <link>http://anil.recoil.org/2008/10/28/working-through-ted-videos-on-the-train.html</link>
      <pubDate>2008-10-28T00:00:00+00:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2008/10/28/working-through-ted-videos-on-the-train</guid>
      <description>&lt;p&gt;I&amp;#8217;m over at the &lt;a href='http://www.microsoftpdc.com/'&gt;Microsoft PDC&lt;/a&gt; in Los Angeles this week, and commuting over from Anand&amp;#8217;s place in Camarillo using the &lt;a href='http://www.metrolinktrains.com/'&gt;Metrolink&lt;/a&gt;. The 3 hour commute gives me a great excuse to catch up on my &lt;a href='http://www.ted.com/'&gt;TED&lt;/a&gt; talks on my iPhone.&lt;/p&gt;

&lt;p&gt;The entire set of talks is &lt;a href='http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=160892972'&gt;available&lt;/a&gt; online via iTunes, and these really stood out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Jared Diamond on &lt;a href='http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?i=43138920&amp;amp;id=160892972'&gt;Why Societies Collapse&lt;/a&gt; : he talks about lots of civilizations which have reached tipping points and have collapsed, often catastrophically. Not a funny or entertaining one, but lots of solid, well-researched facts. Also see his &lt;a href='http://www.amazon.com/Collapse-Societies-Choose-Fail-Succeed/dp/0670033375'&gt;book&lt;/a&gt; which George Dunlap recommended to me but is still in my reading list.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Mih?ly Cs?kszentmih?lyi on &lt;a href='http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?i=42793807&amp;amp;id=160892972'&gt;Creativity, fulfillment and flow&lt;/a&gt; : again, a really well-researched talk which categorizes human motivation into a 2D space of challenge vs skill, and the different emotions which are evoked by being in different situations (e.g. apathy requires no challenge and no skill, and anxiety results if you have low skill and a high challenge ahead of you). The &amp;#8220;flow&amp;#8221; he argues for is the ideal pinnacle of where we should aim to get to in our lives.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Finally, what I consider to be the greatest TED talk I&amp;#8217;ve ever seen is by the late &lt;a href='http://en.wikipedia.org/wiki/Paul_MacCready'&gt;Paul MacCready&lt;/a&gt; on &lt;a href='http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?i=42696989&amp;amp;id=160892972'&gt;Nature vs Humans, and what we can do about it&lt;/a&gt; : he starts off slowly by showing some graphs about the impact of humanity on the population of the planet (hint: we&amp;#8217;ve taken over), and finishes off with some truly awesome demonstrations of natural planes, such as Ornithopters or solar-powered tiny fliers that do not require gas to fly. Highly recommended if you only watch one TED video at all!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are about 80 videos left on my viewing list.. this is going to take a while!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Peeking under the hood of High Availability</title>
      <link>http://anil.recoil.org/2008/09/17/peeking-under-the-hood-of-high-availability.html</link>
      <pubDate>2008-09-17T00:00:00+01:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2008/09/17/peeking-under-the-hood-of-high-availability</guid>
      <description>&lt;p&gt;Well, the big launch of &lt;a href='http://www.xenserver5.com/'&gt;XenServer 5&lt;/a&gt; has gone smoothly, and with it have arrived a flood of questions about how exactly the new &lt;a href='http://xenserver5.com/ha.php'&gt;High Availability&lt;/a&gt; functionality works.&amp;#160; I&amp;#8217;ll use this post to explain the overall architecture of HA in XenServer 5, and also how some of the fault detection and failure planning works.&lt;/p&gt;

&lt;p&gt;Fundamentally, HA is about making sure important VMs are always running on a resource pool. There are two aspects to this: reliably &lt;b&gt;detecting host failure&lt;/b&gt;, and computing a &lt;b&gt;failure plan&lt;/b&gt; to deal with swift recovery.&lt;/p&gt;

&lt;p&gt;Detecting host failure reliably is difficult since you need to remotely distinguish between a host disappearing for a while versus exploding in a ball of flames.&amp;#160; If we mistakenly decide that a master host has broken down and elect a new master in its place, there may be unpredictable results if the original host were to make a comeback&amp;#33;&amp;#160;&amp;#160; Similarly, if there is a network issue and a resource pool splits into two equal halves, we need to ensure that only one half accesses the shared storage and not both simultaneously.&lt;/p&gt;

&lt;h2 id='heartbeating_for_availability'&gt;Heartbeating for availability&lt;/h2&gt;
&lt;a href='http://anil.recoil.org/images/citrix/ha-wizard-3b.png'&gt;&lt;img src='http://anil.recoil.org/images/citrix/ha-wizard-3b-thumb.jpg' align='right' /&gt;&lt;/a&gt;
&lt;p&gt;We solve all these problems in XenServer by having two mechanisms: a &lt;b&gt;storage heartbeat&lt;/b&gt; and a &lt;b&gt;network heartbeat&lt;/b&gt;. When you enable HA in a pool, you must nominate an iSCSI or FC storage repository to be the heartbeat SR. XenServer automatically creates a couple of small virtual disks in this SR. The first disk is used by every physical host in the resource pool as a &lt;b&gt;shared quorum disk&lt;/b&gt;. Each host allocates itself a unique block in the shared disk and regularly writes to the block to indicate that it is alive.&lt;/p&gt;

&lt;p&gt;I asked &lt;a href='http://dave.recoil.org/'&gt;Dave 'highly available' Scott&lt;/a&gt;, the principal engineer behind HA about the startup process:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;When HA starts up, all hosts exchange data over both network and storage channels, indicating which hosts &lt;em&gt;they&lt;/em&gt; can see over both channels; i.e. which I/O paths are working and which are not.&amp;#160; This liveness information is exchanged until a fixed point is reached and all of the hosts are satisfied that they are in agreement about what they can see.&amp;#160; When this happens, the HA functionality is &amp;#8216;armed&amp;#8217; and the pool is protected.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;This HA arming process can take a few minutes to settle for larger pools, but is only required when HA is first enabled.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;Once HA is active, each host regularly writes storage updates to the heartbeat virtual disk, and network packets over the management interface.&amp;#160; It is vital to ensure that network adapters are &lt;a href='http://docs.xensource.com/XenServer/5.0.0/1.0/en_gb/reference.html#networking-standalone_host_config-bonds'&gt;bonded&lt;/a&gt; for resilience, and that storage interfaces are using &lt;a href='http://docs.xensource.com/XenServer/5.0.0/1.0/en_gb/reference.html#id2557754'&gt;dynamic multipathing&lt;/a&gt; where supported.&amp;#160; This will ensure that any single adapter or wiring failures do not result in any availability issues.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;a href='http://anil.recoil.org/images/citrix/ha-wizard-5.png'&gt;&lt;img src='http://anil.recoil.org/images/citrix/ha-wizard-5-thumb.jpg' align='right' /&gt;&lt;/a&gt;
&lt;p&gt;The worst-case scenario for HA is the situation where a host is thought to be off-line but is actually still writing to the shared storage, since this can result in corruption of persistent data.&amp;#160; In order to prevent this situation without requiring active power strip control, we implemented &lt;b&gt;hypervisor-level fencing&lt;/b&gt;.&amp;#160; This is a Xen modification which will hard-power the host off at a very low-level if it doesn&amp;#8217;t hear regularly from a watchdog process running in the control domain.&amp;#160; Since it is implemented at a very low-level, this also covers the case where the control domain becomes unresponsive for any reason.&lt;/p&gt;

&lt;p&gt;Hosts will self-fence (i.e. power off and restart) in the event of any heartbeat failure unless any of the following hold true:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The storage heartbeat is present for all hosts but the network has partitioned (so that there are now two groups of hosts).&amp;#160; In this case, all of the hosts which are members of the largest network partition stay running, and the hosts in the smaller network partition self-fence.&amp;#160; The assumption here is that the network outage has isolated the VMs, and they ought to be restarted on a host with working networking.&amp;#160; If the network partitions are exactly the same size, then only one of them will self-fence according to a stable selection function.&lt;/li&gt;

&lt;li&gt;If the storage heartbeat goes away but the network heartbeat remains, then the hosts check to see if they can see all other hosts over the network.&amp;#160; If this condition holds true, then the hosts remain running on the assumption that the storage heartbeat server has gone away.&amp;#160; This doesn&amp;#8217;t compromise VM safety, but any network glitches will result in fencing since that would mean both heartbeats have disappeared.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='planning_for_failure'&gt;Planning for failure&lt;/h2&gt;

&lt;p&gt;The heartbeat system gives us reliable notification of host failure, and so we move onto the second step of HA: capacity planning for failure.&lt;/p&gt;

&lt;p&gt;A resource pool consists of several physical hosts (say, 16), each with potentially different amounts of host memory and a different number of running VMs.&amp;#160; In order to ensure that no single host failure will result in the VMs on that host being unrestartable (e.g. due to insufficient memory on any other host), the XenServer pool dynamically computes a &lt;b&gt;failure plan&lt;/b&gt; which calculates the actions that would be taken on any host failure.&lt;/p&gt;

&lt;p&gt;But there&amp;#8217;s one more complexity&amp;#8230; a single host failure plan does not cover more advanced cases such as network partitions which take out entire groups of hosts.&amp;#160; It would be very useful to be able to create a plan that could tolerate more than a single host failure, so that administrators could ignore the first host failure and be safe in the knowledge that (for example) three more hosts could fail before the pool runs out of spare capacity.&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s exactly what we do in XenServer&amp;#8230; the resource pool &lt;em&gt;dynamically&lt;/em&gt; computes a failure plan which considers the &amp;#8220;number of host failures to tolerate&amp;#8221; (or &lt;em&gt;nhtol&lt;/em&gt;).&amp;#160; This represents the number of disposable servers in a pool for a given set of protected VMs.&lt;/p&gt;

&lt;p&gt;The planning algorithms are pretty complex, since doing a brute force search of all possible failures across all hosts across all VMs is an exponential problem.&amp;#160; We apply heuristics to ensure we can compute a plan in a reasonably small time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;for up to 3 host failures, we do a comprehensive search which tries almost all permutations.&amp;#160; This covers corner cases such as having hosts or VMs with very different amounts of memory (e.g. 4GB vs 128GB).&amp;#160; Rather than calculate memory slots or otherwise approximate results, we just deal with them individually and give very accurate plans.&lt;/li&gt;

&lt;li&gt;for greater than 3 host failures, we make conservative decisions by approximating every VM to be as large as the largest, and considering each host to be the same as the most densely packed host.&amp;#160; We do not approximate the host memory, and so having pools with uneven amounts of host memory will be fine.&amp;#160; However, in approximate planning mode having a single very large VM will result in a low &lt;em&gt;nhtol&lt;/em&gt; value.&amp;#160; If this is a problem, then try to reduce the &lt;em&gt;nhtol&lt;/em&gt; or try to have a more even spread of VM memory sizes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since planning algorithms are designed for unexpected host failures, we only consider absolutely essential resource reservations which would prevent the VM from starting on the alternative host (e.g. storage is visible, and enough memory is present).&amp;#160; We do not perform CPU reservation on the basis that it can be optimised at a later stage via live relocation once the VM is back up and running.&lt;/p&gt;

&lt;h3 id='overcommit_protection'&gt;Overcommit protection&lt;/h3&gt;

&lt;p&gt;We now have HA armed and a failover plan for our VMs.&amp;#160; But what if you want to make changes to your configuration after HA is enabled?&amp;#160; This is dealt with via &lt;b&gt;overcommit protection&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;The XenServer pool dynamically calculates a new failover plan in response to every XenAPI call which would affect it (e.g. starting a new VM).&amp;#160; If a new plan cannot be calculated due to insufficient resources across the pool, the XenServer will return an &lt;b&gt;overcommitment&lt;/b&gt; error message to the client which blocks the operation.&lt;/p&gt;

&lt;h4 id='the_what_if_machine'&gt;The &amp;#8220;What if?&amp;#8221; Machine&lt;/h4&gt;
&lt;a href='http://anil.recoil.org/images/citrix/ha-wizard-4b.png'&gt;&lt;img src='http://anil.recoil.org/images/citrix/ha-wizard-4b-thumb.jpg' align='right' /&gt;&lt;/a&gt;
&lt;p&gt;This overcommit protection would be quite irritating if you have to keep trying things and seeing if a plan exists or not, and so we built in a &amp;#8221;&lt;a href='http://www.gotfuturama.com/Information/Encyc-55-What_If_Machine/'&gt;What If?&lt;/a&gt;&amp;#8221; machine into XenServer to facilitate counter-factual reasoning.&lt;/p&gt;

&lt;p&gt;When reconfiguring HA via XenCenter, you can supply a hypothetical series of VM priorities, and XenServer will return a number of host failures which would be tolerated under this scheme.&amp;#160; This lets you try various combinations of VM protections depending on your business needs, and see if the number of host failures is appropriate to the level of paranoia you desire.&lt;/p&gt;

&lt;p&gt;This can even be done via the CLI, using the snappily named &amp;#8221;&lt;b&gt;xe pool-ha-compute-max-host-failures-to-tolerate&lt;/b&gt;&amp;#8221; when HA is enabled.&lt;/p&gt;

&lt;p&gt;The nice thing about XenServer HA is that it is done at the XenAPI level, and so&amp;#160; any of the standard clients (such as the xe CLI or XenCenter) or any third-party clients which use the XenAPI will all interoperate just fine.&amp;#160; The XenServer pool dynamically recalculates plans in response to the client requests, and so no special &amp;#8220;oracle&amp;#8221; is required outside of the pool to figure out HA plans.&lt;/p&gt;

&lt;p&gt;Finally, HA makes master election completely invisible.&amp;#160; Any host in a pool can be a master host, and the pool database is constantly replicated across all nodes and also backed up to shared storage on the heartbeat SR for additional safety.&amp;#160; Any XenAPI client can connect to any host, and a redirect is issued to the current master host.&lt;/p&gt;

&lt;h2 id='protection_levels'&gt;Protection Levels&lt;/h2&gt;

&lt;p&gt;Each VM in an HA pool can be either &lt;b&gt;fully protected&lt;/b&gt;, &lt;b&gt;best-effort&lt;/b&gt; or &lt;b&gt;unprotected&lt;/b&gt;. VMs which are protected are all included in the failover planning, and if no plan exists for which they can all be reliably restarted then the pool is considered to be overcommitted. Hugh Warrington (who implemented the XenCenter HA support) explained what use protection levels are:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;Best-effort VMs are not considered when calculating a failover plan, but the pool will still try to start them as a one-off if a host that is running them fails.&amp;#160; This restart is attempted after all protected VMs are restarted, and if the attempt to start them fails then it will not be retried.&amp;#160; This is a useful setting for test/dev VMs which aren&amp;#8217;t critical to keep running, but would be nice to do so in a pool which also has some important VMs which absolutely must run.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;a href='http://anil.recoil.org/images/citrix/ha-wizard-5.png'&gt;&lt;img src='http://anil.recoil.org/images/citrix/ha-wizard-5-thumb.jpg' align='right' /&gt;&lt;/a&gt;
&lt;p&gt;There are some advanced features which are only available via the CLI.&amp;#160;&amp;#160; Each protected VM in an HA pool can be assigned a numeric &lt;tt&gt;ha-restart-priority&lt;/tt&gt;.&amp;#160; If a pool is well-resourced with a high &lt;em&gt;nhtol&lt;/em&gt;, then these restart priorities are not relevant: the VMs are all guaranteed to be started.&lt;/p&gt;
&lt;p&gt;If more hosts fail than have been planned for, then the priorities are used to determine the order in which VMs are restarted.&amp;nbsp; This ensures that in over-committed pools, the most important VMs are restarted first.&amp;nbsp; Although the pool will start priority 1 VMs first, they might not finish booting before the priority 2 VMs, and so this should not be used as the basis for service ordering.&lt;/p&gt;&lt;p&gt;Note that it's very important to &lt;b&gt;ensure that a VM is agile&lt;/b&gt; when protecting it by HA.&amp;nbsp; If the VM is not agile (e.g has a physical CD drive mapped in from a host), then it can only be assigned Best Effort restart since it is tied to one host.&lt;/p&gt;
&lt;h2 id='xencenter_support_for_ha'&gt;XenCenter support for HA&lt;/h2&gt;
&lt;p&gt;The best practice for HA is not to make configuration changes while it is enabled.&amp;nbsp; Instead, it is intended to be the &quot;2am safeguard&quot; which will restart hosts in the event of a problem when there isn't a human administrator nearby.&amp;nbsp; If you are actively making configuration changes such as applying patches, then HA should be disabled for the duration of these changes.&lt;/p&gt;
&lt;p&gt;XenCenter makes some common changes under HA much more user-friendly, which I asked &lt;a href='http://community.citrix.com/blogs/citrite/ewanm/'&gt;Ewan Mellor&lt;/a&gt; (the principal GUI engineer) about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Normally a protected VM cannot be shut down via the CLI or from within the guest (a shutdown from within the guest will automatically restart it).&amp;#160; If you try to shutdown from XenCenter, it will give you the option of unprotecting the VM and then shutting it down first.&amp;#160; Thus, accidental in-guest shutdowns wont result in downtime, but administrators can still stop a protected guest if they really want to.&lt;/li&gt;

&lt;li&gt;If you want to reboot a host when HA is enabled, XenCenter automatically uses the hypothetical planning calculation to determine if this would invalidate the failover plan.&amp;#160; If it doesn&amp;#8217;t affect it, then the host is shut down normally.&amp;#160; If the plan would be violated, but the &lt;em&gt;nhtol&lt;/em&gt; is greater than 1, XenCenter will give the administrator the option of lowering the &lt;em&gt;nhtol&lt;/em&gt; value by 1.&amp;#160; This reduces the overall resilience of the pool, but always ensures that at least one host failure will be tolerated.&amp;#160; When the host comes back up, the plan is automatically recalculated and the original &lt;em&gt;nhtol&lt;/em&gt; value restored if appropriate.&lt;/li&gt;

&lt;li&gt;If you try to apply a hotfix, then XenCenter will disable HA for the duration of the pool patching wizard.&amp;#160; It is important to manually keep an eye on hotfix application to ensure that host failures do not disrupt the operation of the pool.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, I hope this short article has given you a taster&amp;#8230; just kidding! This post is almost as long as my PhD thesis, but then, HA is a complex topic. Please do feel free to get back to me with comments and feedback about how we can improve it in the future releases, or if you just love it the way it is.&amp;#160; Many thanks to Dave Scott, Richard Sharp, Ewan Mellor and Hugh Warrington for their input to this article.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Shedding some light on XenApp on XenServer performance tuning</title>
      <link>http://anil.recoil.org/2008/08/04/shedding-some-light-on-xenapp-on-xenserver-performance-tuning.html</link>
      <pubDate>2008-08-04T00:00:00+01:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2008/08/04/shedding-some-light-on-xenapp-on-xenserver-performance-tuning</guid>
      <description>&lt;p&gt;You won&amp;#8217;t be surprised to hear that we spend a lot of time improving &lt;a href='http://www.citrix.com/XenApp'&gt;XenApp&lt;/a&gt; performance when running on &lt;a href='http://www.citrix.com/XenServer'&gt;XenServer&lt;/a&gt;. Although there are some good benchmark comparisons available (such as the &lt;a href='http://community.citrix.com/x/_4ENAg'&gt;Tolly Group&lt;/a&gt; report), I still get a lot of customers asking about what the &amp;#8220;secret sauce&amp;#8221; is. I sat down with George Dunlap, the lead XenServer performance engineer to chat about the very first optimisation we did back in XenServer 4.0 last year.&lt;/p&gt;

&lt;p&gt;Before we dive in, we first need to explain how a normal operating system handles memory. George explains:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;Modern desktop and server processors don&amp;#8217;t access memory directly using its physical address. They use &amp;#8217;&lt;a href='http://en.wikipedia.org/Virtual_Memory'&gt;virtual memory&lt;/a&gt;&amp;#8217; to separate the addresses that processes use to read and write memory from the actual memory itself. This allows operating systems to hide from processes all the dirty details of how much memory there is, where in physical memory the process needs to write to, and so on.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;However, the actual processor still needs to translate from a &lt;a href='http://en.wikipedia.org/wiki/Virtual_address'&gt;virtual address&lt;/a&gt; to the physical memory address in order to actually read and write any memory. This translation is done with something called &lt;a href='http://en.wikipedia.org/wiki/Page_tables'&gt;page tables&lt;/a&gt;.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;Page tables are used to implement virtual memory by mapping virtual addresses to physical addresses. The operating system constructs page tables using physical memory addresses, and then puts the physical address of the &amp;#8220;top-level&amp;#8221; page table into a hardware register called the &amp;#8216;base pointer&amp;#8217;. Then the processor will read these page tables to translate virtual addresses to physical addresses as needed, before reading and writing to physical memory.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most modern processor types have some sort of paging mechanism, although XenServer is specifically tuned for &lt;a href='http://en.wikipedia.org/wiki/X86-64'&gt;x86-64&lt;/a&gt; CPUs. An excellent book on the general topic is &lt;a href='http://en.wikipedia.org/wiki/Special:BookSources/0130313580'&gt;Modern Operating Systems&lt;/a&gt; by &lt;a href='http://www.cs.vu.nl/~ast/'&gt;Andrew Tanenbaum&lt;/a&gt;. When XenServer creates Windows VMs, it takes advantage of the &lt;a href='http://en.wikipedia.org/wiki/X86_virtualization'&gt;virtualization extensions&lt;/a&gt; in modern CPUs, which requires special memory handling in Xen. George explains this further:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;When we create a virtual machine, we virtualize the memory as well; that means that the guest operating system&amp;#8217;s idea of physical memory does not match up to real physical memory on the host. Traditionally, what the guest thinks of as physical memory is called &amp;#8220;physical memory&amp;#8221;, and what the hypervisor thinks of as physical memory is called &amp;#8220;machine memory&amp;#8221;. Since this terminology is a bit confusing, Xen tends to call what the guest thinks of as physical memory as &amp;#8220;guest physical&amp;#8221; memory, just to help make things more clear.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;This means that any fully-virtualized operating system, like Windows, will create page tables using guest physical memory, and will point the base pointer at the guest physical address of the top-level page table. Unfortunately, the hardware still needs to map from virtual memory address to machine addresses, not guest physical addresses.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;In order to allow this to happen, the hypervisor sets up &lt;b&gt;shadow page tables&lt;/b&gt;. These page tables are generated by the hypervisor are copies of the guest page tables, but with the guest physical addresses converted into machine physical addresses. The guest cannot access them directly, and they don&amp;#8217;t reside in the guest&amp;#8217;s physical memory; they&amp;#8217;re generated out of a pool of memory that the hypervisor allocates when a VM is created, called &amp;#8220;shadow page table memory&amp;#8221;.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;What this means is that whenever the guest operating system wants to map some new memory, after it writes the data into the page table but before it can actually use it, the hypervisor needs to translate the change to the guest page table into changes to the shadow page table. So any workload that involves a lot of this will necessarily involve the hypervisor a lot, which causes overhead.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So shadow page tables are our mechanism of giving a guest an interface which is identical to real hardware (so it doesn&amp;#8217;t need to be modified), but still intercepting changes before they reach the real hardware. You can find more details from the &lt;a href='http://www.xensource.com/files/summit_3/XenSummit_Shadow2.pdf'&gt;XenSummit 2006 talk&lt;/a&gt; or from the 2005 &lt;a href='http://www.cl.cam.ac.uk/research/srg/netos/papers/2005-migration-nsdi-pre.pdf'&gt;NSDI paper&lt;/a&gt;. So how is this all relevant to XenApp performance? Back to George&amp;#8230;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;The hypervisor allocates a certain amount of memory for each VM to use for shadow page tables; this is called &lt;b&gt;shadow page table memory&lt;/b&gt;. As new page tables are created and old ones aren&amp;#8217;t used anymore, the hypervisor cycles through this shadow page table memory. When it needs a new page and there isn&amp;#8217;t enough, it will &amp;#8216;unshadow&amp;#8217; the guest page tables that haven&amp;#8217;t been used for the longest time to reclaim shadow memory, so that it can use more.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;We don&amp;#8217;t know ahead of time how much shadow memory a given workload will use, but we can estimate based on the amount of memory that the VM has. We allocate enough shadow memory for each page to be mapped once, more or less, then add an extra 50% to have some slack. For all the workloads we&amp;#8217;ve tested, that&amp;#8217;s been enough &amp;#8211; except XenApp.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;XenApp is the one workload we&amp;#8217;ve found that requires more shadow page table memory than our standard default. Because XenApp generally starts hundreds of copies of the same process, the same memory ends up mapped in hundreds of different processes. What happens when all of those processes are active is that XenServer is continually unshadowing one process&amp;#8217; page tables in order to shadow another process&amp;#8217; pagetables; only to have to re-shadow the original ones a second or two later when it runs again! This is called &lt;a href='http://en.wikipedia.org/wiki/Thrash_(computer_science)'&gt;thrashing&lt;/a&gt;, when there&amp;#8217;s not enough of a limited resource.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once the bottleneck was discovered, the solution was simple. In XenServer 4.1, we created a special XenServer application template called &lt;em&gt;&quot;Citrix XenApp&quot;&lt;/em&gt;, which has an increased shadow multiplier that reserves more shadow memory for the guest when it starts. This is also a good example of how templates hide the complexities of performance tuning from the user, but still permitting custom modifications if they are required. For example, on your XenServer host with a VM called &amp;#8220;XenApp&amp;#8221;, you could view the shadow multiplier by using the CLI:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# xe vm-list name-label=XenApp params=HVM-shadow-multiplier
  HVM-shadow-multiplier ( RW)    : 4.000&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The same value is also available from XenCenter in the Optimization pane, but of course do remember that the default value was chosen through extensive testing and doesn&amp;#8217;t need to be changed. Most of the other templates in XenServer also have carefully tuned settings (e.g. the hardware platform flags) to ensure smooth running, or in the case of Linux templates, to support &lt;a href='http://docs.xensource.com/XenServer/4.1.0/1.0/en_gb/sdk.html#id2553443'&gt;para-virtual installation&lt;/a&gt;. This is why it&amp;#8217;s so important that you not use the &lt;em&gt;&quot;Other Install Media&quot;&lt;/em&gt; template in preference of a more specialised one!&lt;/p&gt;

&lt;p&gt;I mentioned at the beginning of this post that this was the first of many XenApp optimisations. We&amp;#8217;ve just released the &lt;a href='https://www.citrix.com/English/ss/downloads/details.asp?downloadId=1679827&amp;amp;productId=683148'&gt;public beta&lt;/a&gt; of the latest XenServer (&amp;#8220;Orlando&amp;#8221;) which is even faster. The story of what those improvements are, and the tools which George and his team uses to analyze the inner workings of Xen, are a topic for a future post. For now, get downloading XenServer and start virtualizing your XenApp installations! Or if you&amp;#8217;re feeling inspired, go over to &lt;a href='http://xen.org/'&gt;xen.org&lt;/a&gt;, check out the source, and get coding&amp;#8230;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Installing Ubuntu on XenServer</title>
      <link>http://anil.recoil.org/2008/07/02/installing-ubuntu-on-xenserver.html</link>
      <pubDate>2008-07-02T00:00:00+01:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2008/07/02/installing-ubuntu-on-xenserver</guid>
      <description>&lt;p&gt;I thought I&amp;#8217;d kick off my Citrix blog with a question I get pretty often from Linux enthusiasts: how to install unsupported Linux distributions on XenServer 4.1.&lt;/p&gt;

&lt;p&gt;The most common solution people find is to use the &amp;#8220;Other Install Media&amp;#8221; template, insert the distribution installation CD, and find that the mouse cursor doesn&amp;#8217;t work when they boot into X11. The reason for this is that they are using the hardware-assisted emulation mode of installing Linux. In this mode (dubbed &amp;#8220;HVM&amp;#8221;), all input and output is emulated, and in particular the mouse interface uses the USB tablet interface. If the distribution doesn&amp;#8217;t include a driver for USB tablets, then no mouse will appear.&lt;/p&gt;

&lt;p&gt;Windows guests run at high-speed in HVM mode due to the installation of the XenServer tools which install &lt;a href='http://xen.org/files/summit_3/xen-pv-drivers.pdf'&gt;high-speed drivers&lt;/a&gt;, but these are not necessary for Linux distributions since they can be run in &lt;a href='http://en.wikipedia.org/wiki/Paravirtualization'&gt;para-virtualized&lt;/a&gt; mode (dubbed &amp;#8220;PV&amp;#8221;). This involves obtaining a Xen-enabled PV kernel from the distribution, and modifying the VM record in XenServer to boot into this kernel instead of HVM mode. The XenServer built-in templates for popular distributions such as RHEL, CentOS or SUSE Linux already automate all this and are in PV mode from the installer onwards.&lt;/p&gt;

&lt;p&gt;In the remainder of this post, I&amp;#8217;ll explain how to take a distribution without direct support (&lt;a href='http://www.ubuntu.com/'&gt;Ubuntu&lt;/a&gt; &lt;a href='https://wiki.ubuntu.com/HardyHeron'&gt;8.04&lt;/a&gt;), get it installed in HVM mode on XenServer 4.1, and convert it to PV mode with a XenCenter graphical console.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Download the &quot;&lt;a href='http://www.ubuntu.com/GetUbuntu/download'&gt;Alternative Installation CD&lt;/a&gt;&quot;.  The main installation CD uses graphical mode, which won't install as well in HVM mode due to the use of esoteric 16-bit mode instructions for the graphics operations.  The 16-bit emulation mechanisms vary between processors (with better support on AMD chips, and a software instruction emulator required on Intel VT chips).  However, the Ubuntu alternate CD uses a text-based installer which works fine.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;Create a new VM on the XenServer 4.1 host using the &quot;Windows Server 2003&quot; template.  This template is set up with a sensible set of hardware emulation flags and default disks, and so is a good base for the HVM installation of Ubuntu as well.  Attach the Ubuntu ISO you just downloaded to the VM, and proceed to install Ubuntu as normal.  You should install it onto the first disk, to make the subsequent steps in this guide easier.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;When the installation is finished, reboot the VM (don't forget to detach the installation ISO first).  It should boot up in HVM mode into the graphical login screen.  The XenCenter display will show it as not being optimized, which is fine.  At this stage, I prefer to work via a remote command-line using SSH.  Open up a Terminal from Ubuntu, and run &quot;&lt;tt&gt;sudo apt-get install openssh-server&lt;/tt&gt;&quot;.  Then find out the VM's IP address with &quot;&lt;tt&gt;ifconfig eth0&lt;/tt&gt;&quot;, and then connect to it remotely.  Alternatively, you can continue to type in the commands directly into the terminal as well.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;On the Ubuntu guest, you now need to install the latest Xen version of the Ubuntu kernel:
	&lt;ul&gt;
		&lt;li&gt;Install the Linux kernel virtual package with &quot;&lt;tt&gt;sudo apt-get install linux-image-xen&lt;/tt&gt;&quot;.  This is a virtual package which pulls in the latest Xen kernel and modules, in my case &lt;tt&gt;2.6.24.19.21&lt;/tt&gt;.&lt;/li&gt;
		&lt;li&gt;You now need to workaround a &lt;a href='http://www.mail-archive.com/grub-devel@gnu.org/msg06024.html'&gt;bug&lt;/a&gt; in grub.  Due to the switch in recent versions of Linux to work with the hypervisor-independent &lt;a href='http://xen.xensource.com/files/xensummit_4/xen-paravirt_ops_Fitzhardinge.pdf'&gt;paravirt_ops&lt;/a&gt; interface, &lt;tt&gt;update-grub&lt;/tt&gt; doesn't update the grub configuration with your newly installed Xen kernel.  To fix this:
		&lt;ul&gt;
			&lt;li&gt;Open &lt;tt&gt;/boot/grub/menu.lst&lt;/tt&gt; in your favourite editor.&lt;/li&gt;
			&lt;li&gt;Scroll to the bottom to the kernel list, and find the entry which looks like:
&lt;div class='preformatted panel' style='border-width: 1px;'&gt;&lt;div class='preformattedContent panelContent'&gt;
&lt;pre&gt;title           Ubuntu 8.04, kernel 2.6.24-16-generic
root            (hd0,0)
kernel          /boot/vmlinuz-2.6.24-16-generic root=UUID=&amp;lt;uuid&amp;gt; ro quiet splash
initrd          /boot/initrd.img-2.6.24-16-generic
quiet
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
			&lt;li&gt;Add a new entry which is similar to this, but change all references to the &lt;tt&gt;2.6.24-16-generic&lt;/tt&gt; to the Xen kernel.  In &lt;tt&gt;/boot&lt;/tt&gt; I have &lt;tt&gt;vmlinuz-2.6.24-19-xen&lt;/tt&gt;, so my new entry looks like:
&lt;div class='preformatted panel' style='border-width: 1px;'&gt;&lt;div class='preformattedContent panelContent'&gt;
&lt;pre&gt;title           Ubuntu 8.04, kernel 2.6.24-19-xen
root            (hd0,0)
kernel          /boot/vmlinuz-2.6.24-19-xen root=UUID=&amp;lt;uuid&amp;gt; ro quiet splash
initrd          /boot/initrd.img-2.6.24-19-xen
quiet
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
			&lt;li&gt;Also edit the &lt;tt&gt;default&lt;/tt&gt; entry in the &lt;tt&gt;menu.lst&lt;/tt&gt; to match the number of the kernel you just added.  I set mine to 3, since it is the fourth entry in the list and the indexing starts from 0.&lt;/li&gt;
		&lt;/ul&gt;
		&lt;/li&gt;
	&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;When this is done, shut down the guest but do not reboot it just yet.  You first need to edit the VM record for your Ubuntu VM to convert it to PV boot mode.  From the control domain console of your XenServer:
	&lt;ul&gt;
		&lt;li&gt;Determine the UUID of the Ubuntu VM by using the &lt;tt&gt;xe&lt;/tt&gt; CLI:
		&lt;ul&gt;
			&lt;li&gt;&lt;tt&gt;xe vm-list name-label=Ubuntu params=uuid --minimal&lt;/tt&gt; : this will print out the UUID of the VM named &quot;Ubuntu&quot;.  If you are logged into the control domain, pressing the &lt;tt&gt;&amp;lt;tab&amp;gt;&lt;/tt&gt; key will perform auto-completion of UUIDs in subsequent XE commands, so you don't need to keep typing it in every time!&lt;/li&gt;
			&lt;li&gt;&lt;tt&gt;xe vm-param-set uuid=&amp;lt;uuid&amp;gt; HVM-boot-policy=&lt;/tt&gt; : this will clear the HVM boot mode from the VM.&lt;/li&gt;
			&lt;li&gt;&lt;tt&gt;xe vm-param-set uuid=&amp;lt;uuid&amp;gt; PV-bootloader=pygrub&lt;/tt&gt; : this will switch the VM to using to the pygrub bootloader which starts the guest in PV mode by examining its filesystem for kernel.&lt;/li&gt;
			&lt;li&gt;&lt;tt&gt;vm vm-param-set uuid=&amp;lt;uuid&amp;gt; PV-args=&quot;console=tty0 xencons=tty&quot;&lt;/tt&gt; : this configures the kernel boot arguments to display the login console on the correct TTY, so that it shows up in the XenCenter console.&lt;/li&gt;
		&lt;/ul&gt;
		&lt;/li&gt;
		&lt;li&gt;Next, you need to flag the root disk of the VM as bootable so that pygrub knows where to look for the PV kernel:
		&lt;ul&gt;
			&lt;li&gt;&lt;tt&gt;xe vm-disk-list uuid=&amp;lt;uuid&amp;gt;&lt;/tt&gt; and look for the UUID of the VBD for the disk.  VBD stands for &quot;Virtual Block Device&quot; and represents how to map the virtual disk into the virtual machine.&lt;/li&gt;
			&lt;li&gt;&lt;tt&gt;xe vbd-param-set uuid=&amp;lt;vbd uuid&amp;gt; bootable=true&lt;/tt&gt; will set the root disk VBD to be bootable.&lt;/li&gt;
		&lt;/ul&gt;
		&lt;/li&gt;
	&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;You should be all set now!  If you boot up the Ubuntu VM, it should start up in text-mode with the high-speed PV kernel.  If it doesn't work due to an incorrect grub configuration, you can use the &lt;tt&gt;xe-edit-bootloader&lt;/tt&gt; script in the XenServer control domain to edit the &lt;tt&gt;grub.conf&lt;/tt&gt; until it works.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;The next step is to install the XenServer tools within the guest, so that metrics such as the network interface IP addresses are recorded and reported from XenCenter.  To do this:
	&lt;ul&gt;
		&lt;li&gt;Due to a portability issues with the default shell in Ubuntu (&lt;a href='http://en.wikipedia.org/wiki/Debian_Almquist_shell'&gt;dash&lt;/a&gt;), you will need to replace it by: &lt;tt&gt;sudo apt-get -y install bash &amp;amp;&amp;amp; sudo dpkg-reconfigure dash&lt;/tt&gt;.  We've actually fixed this issue in future releases of XenServer, but for XenServer 4.1 you will need to use &lt;tt&gt;bash&lt;/tt&gt;.&lt;/li&gt;
		&lt;li&gt;Attach the XenServer Tools ISO into the VM, and mount it into the guest with &lt;tt&gt;sudo mount /dev/xvdd /mnt&lt;/tt&gt;&lt;/li&gt;
		&lt;li&gt;Install the tools with &lt;tt&gt;sudo dpkg -i /mnt/Linux/xe-guest-utilities_4.1.0-257_i386.deb&lt;/tt&gt;.&lt;/li&gt;
		&lt;li&gt;The warnings about the VM being unoptimized should disappear, and additional information such as the IP address of the guest should appear in XenCenter.&lt;/li&gt;
	&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;In order to access the Ubuntu installation via the graphical console, you need to configure it to run &lt;a href='http://www.realvnc.com/'&gt;VNC&lt;/a&gt; on the external network interface.  XenCenter polls the guest to see if it is listening on the VNC port 5900, and offers the option to switch to the graphical console if it finds it.  I followed the excellent instructions on this &lt;a href='http://ubuntuforums.org/showpost.php?p=4963842&amp;amp;postcount=1'&gt;forum post&lt;/a&gt;.  To summarise them:
	&lt;ul&gt;
		&lt;li&gt;&lt;tt&gt;sudo apt-get install vnc4server xinetd&lt;/tt&gt; : to install the required packages&lt;/li&gt;
		&lt;li&gt;Edit &lt;tt&gt;/etc/gdm/gdm.conf&lt;/tt&gt; and uncomment the &lt;tt&gt;RemoteGreeter=/usr/lib/gdm/gdmlogin&lt;/tt&gt; line, set the key &lt;tt&gt;Enable=true&lt;/tt&gt; in the &lt;tt&gt;&lt;span class='error'&gt;&amp;#91;xdcmp&amp;#93;&lt;/span&gt;&lt;/tt&gt; section.&lt;/li&gt;
		&lt;li&gt;Install a new service file for &lt;tt&gt;xinetd&lt;/tt&gt; into &lt;tt&gt;/etc/xinetd.d/Xvnc&lt;/tt&gt; with the following contents:
&lt;div class='preformatted panel' style='border-width: 1px;'&gt;&lt;div class='preformattedContent panelContent'&gt;
&lt;pre&gt;service Xvnc
{
  type = UNLISTED
  disable = no
  socket_type = stream
  protocol = tcp
  wait = no
  user = nobody
  server = /usr/bin/Xvnc
  server_args = -inetd -query localhost -geometry 1024x768  -depth 16 -cc 3 -once -SecurityTypes=none -extension XFIXES
  port = 5900
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
		&lt;li&gt;The major difference from the forum poster is to run it on port 5900, and not to restrict it to just localhost (since XenCenter also needs to connect to it).&lt;/li&gt;
		&lt;li&gt;Finally, restart the &lt;tt&gt;xinetd&lt;/tt&gt; service by running &lt;tt&gt;sudo /etc/init.d/xinetd restart&lt;/tt&gt;.&lt;/li&gt;
	&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Once you're done with this installation, you can shut down the VM and convert it to a template.  Any exports or clones will continue to run in PV mode, since the XenServer XVA export format records all of the metadata required to re-create the VM records.&lt;/p&gt;&lt;p&gt;Enjoy the Ubuntu on XenServer experience!  Remember to report any issues you have with the in-guest packages on the Ubuntu support forums, or just give them positive feedback.&lt;/p&gt;&lt;p&gt;PS: many thanks to Andrew Peace and Ian Campbell for assistance.  May their Linux beards remain long and uncut.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Parsing EXIF/IPTC photo tags using pyexiv2 on Leopard</title>
      <link>http://anil.recoil.org/2008/04/17/parsing-exif-iptc-photo-tags-using-pyexiv2-on-leopard.html</link>
      <pubDate>2008-04-17T00:00:00+01:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2008/04/17/parsing-exif-iptc-photo-tags-using-pyexiv2-on-leopard</guid>
      <description>&lt;p&gt;I&amp;#8217;ve been looking around at refreshing my current photo gallery to make it easier to update, since I&amp;#8217;m around 1000 photos behind over the last year. Part of making it easier to use is to adopt an &lt;a href='http://www.apple.com/aperture'&gt;Aperture&lt;/a&gt;-based system of marking the metadata directly in the image itself, and figuring out how to render so many pictures more effectively in my &lt;a href='http://anil.recoil.org/gallery/'&gt;gallery&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The best library I could find to do the job is &lt;a href='http://www.exiv2.org'&gt;Exiv2&lt;/a&gt; and its associated Python bindings &lt;a href='http://tilloy.net/dev/pyexiv2/'&gt;pyexiv2&lt;/a&gt;. They use the rather complex &lt;a href='http://www.boost.org/doc/libs/1_35_0/libs/python/doc/index.html'&gt;Boost.Python&lt;/a&gt; bindings, which are a total pain to compile on MacOS X Leopard.&lt;/p&gt;

&lt;p&gt;In order to get it to work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Use the latest &lt;a href='http://www.finkproject.org'&gt;Fink&lt;/a&gt; to install:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;python25&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;boost1.34.python25&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;libexiv2&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;scons&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Download the latest &lt;a href='http://tilloy.net/dev/pyexiv2/download.htm'&gt;pyexiv2 distribution&lt;/a&gt;, extract it, and drop in my &lt;a href='http://anil.recoil.org/files/pyexiv2/Makefile'&gt;exiv2 Leopard Makefile&lt;/a&gt; into the extracted directory.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Type in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;make&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;sudo make install&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Test it out by running python2.5 and experimenting with importing pyexiv2 (see the pyexiv2 &lt;a href='http://tilloy.net/dev/pyexiv2/developers.htm'&gt;developer guide&lt;/a&gt; for more information.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;#8217;ll tidy this up into a fink package sometime, but for now I want to press on with finishing my &lt;a href='http://www.djangoproject.org/'&gt;Django&lt;/a&gt; experiments.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Sushi, Seattle and Seahawks</title>
      <link>http://anil.recoil.org/2007/04/11/sushi-seattle-and-seahawks.html</link>
      <pubDate>2007-04-11T00:00:00+01:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2007/04/11/sushi-seattle-and-seahawks</guid>
      <description>&lt;a href='http://anil.recoil.org/gallery/images/redmond-view-1-large.jpg' title='Random view of Redmond countryside' rel='lightbox'&gt;&lt;img src='http://anil.recoil.org/gallery/images/redmond-view-1-medium.jpg' alt='Random view of Redmond countryside' style='float:right' /&gt; &lt;/a&gt;
&lt;p&gt;So I&amp;#8217;m hanging at the &lt;a href='http://www.xensource.com/'&gt;XenSource&lt;/a&gt; Redmond office for a few days, and munching on delicious sushi at &lt;a href='http://www.florestaurant.com/index.htm'&gt;Flo&lt;/a&gt;, and it turns out that the dude behind us was none other than &lt;a href='http://www.nfl.com/players/playerpage/12429'&gt;Matt Hasselbeck&lt;/a&gt;! It seems like only two years ago that I was cheering on the &lt;a href='http://www.steelers.com/'&gt;Pittsburgh Steelers&lt;/a&gt; and &lt;a href='http://en.wikipedia.org/wiki/Jerome_Bettis'&gt;the Bus&lt;/a&gt; as they owned the &lt;a href='http://www.seahawks.com/'&gt;Seahawks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately, I only realised my brief brush with celebrity on our way out of the restaurant, which also probably saved me from saying something stupid to him. As if! But anyway, the, err, moral of this post is that you must check out Flo Sushi if you&amp;#8217;re in Seattle and eat the spider roll, it&amp;#8217;s awesome.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Karnatik Jazz, Live Painting, and such things...</title>
      <link>http://anil.recoil.org/2007/04/08/karnatik-jazz-live-painting-and-such-things.html</link>
      <pubDate>2007-04-08T00:00:00+01:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2007/04/08/karnatik-jazz-live-painting-and-such-things</guid>
      <description>&lt;p&gt;Had a great evening out in San Francisco on Friday, when we visited the &lt;a href='http://www.redpoppyarthouse.org/'&gt;Red Poppy Art House&lt;/a&gt; on Folsom Street to check out a really unique Jazz experience.&lt;/p&gt;

&lt;p&gt;The boys from &lt;a href='http://www.vidyamusic.com/'&gt;VidyA&lt;/a&gt; recently took up an artist-in-residence position there, and performed their fusion of traditional Indian &lt;a href='http://www.karnatik.com/'&gt;Karnatik&lt;/a&gt; music with modern Jazz pieces. They&amp;#8217;ve been making some &lt;a href='http://sfgate.com/cgi-bin/article.cgi?f=/c/a/2007/01/10/DDGTFNF6OE1.DTL&amp;amp;type=music'&gt;waves&lt;/a&gt; in the SF Jazz scene already it seems, and to top it all of, the owner of the art house did a live painting session during the performance. The audience passed out random bits of stuff, and he incorporated it into a piece done over the course of an evening. Talk about artistic overload!&lt;/p&gt;

&lt;p&gt;Love the area as well; there&amp;#8217;s a nice friendly &lt;a href='http://www.folsomstreetcoffee.com/'&gt;coffee-house&lt;/a&gt; down the road (which is pretty much my only criteria, apart from not getting shot and such).&lt;/p&gt;
&lt;table align='center' width='90%'&gt;
&lt;tr&gt;
&lt;td class='bimg'&gt;
&lt;a href='http://anil.recoil.org/gallery/2007/04/07/index.html#sf-mission-4'&gt;&lt;img src='http://anil.recoil.org/gallery/images/sf-mission-4-medium.jpg' border='0' height='140' alt='My school was never this cool.' width='140' /&gt;&lt;/a&gt;&lt;br /&gt;My school was never this cool.&lt;/td&gt;
&lt;td class='bimg'&gt;&lt;a href='http://anil.recoil.org/gallery/2007/04/07/index.html#sf-mission-8'&gt;&lt;img src='http://anil.recoil.org/gallery/images/sf-mission-8-medium.jpg' border='0' height='140' alt='The area was a mix of Latino and African, it seemed' width='140' /&gt;&lt;/a&gt;&lt;br /&gt;The area was a mix of Latino and African, it seemed&lt;/td&gt;
&lt;td class='bimg'&gt;&lt;a href='http://anil.recoil.org/gallery/2007/04/07/index.html#sf-mission-9'&gt;&lt;img src='http://anil.recoil.org/gallery/images/sf-mission-9-medium.jpg' border='0' height='140' alt='And in the Red Poppy Art House, eclectic art abounds' width='140' /&gt;&lt;/a&gt;&lt;br /&gt;And in the Red Poppy Art House, eclectic art abounds&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</description>
    </item>
    
    <item>
      <title>Core stability exercising</title>
      <link>http://anil.recoil.org/2007/04/08/core-stability-exercising.html</link>
      <pubDate>2007-04-08T00:00:00+01:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2007/04/08/core-stability-exercising</guid>
      <description>&lt;p&gt;It&amp;#8217;s been a wierd exercise year; I went from hard-core powerlifting (go 220lb bench!), to playing a lot of badminton and tennis, and then ending off the PhD era with breaking my knee (details not suitable for blog publication). &lt;br /&gt; &lt;a href='http://anil.recoil.org/gallery/images/ajay-stretch-1-large.jpg' title='Ajay having a little stretch' rel='lightbox'&gt;&lt;img src='http://anil.recoil.org/gallery/images/ajay-stretch-1-medium.jpg' alt='Ajay having a nice stretch' style='float:right' /&gt; &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As anyone it&amp;#8217;s happened to knows, a knee injury is really annoying to recover from as it feels really &amp;#8220;wobbly&amp;#8221; for ages and can&amp;#8217;t quite be trusted. I&amp;#8217;ve been doing physio on it myself for about half a year now, and can finally run around for 5km or so without too much discomfort, although &lt;a href='http://www.camyoga.co.uk/'&gt;yoga&lt;/a&gt; and &lt;a href='http://www.capoeira-cambridge.co.uk/'&gt;Capoeria&lt;/a&gt; are perhaps a few more months away.&lt;/p&gt;

&lt;p&gt;But then, the Forrest Gump-class runner and ex-officemate &lt;a href='http://www.cl.cam.ac.uk/~ach61/'&gt;Alex Ho&lt;/a&gt; pointed out &lt;em&gt;&lt;a href='http://www.srcf.ucam.org/cuhh/linksandresources/core-stability.pdf'&gt;these amazing exercises&lt;/a&gt;&lt;/em&gt; by the captain of the &lt;a href='http://www.srcf.ucam.org/cuhh/'&gt;CUH&amp;amp;H&lt;/a&gt; running team in Cambridge. They all emphasise smooth movement and core strength without the need for heavy weights, so can be done while travelling as well. So highly recommended, that even little Ajay &lt;em&gt;(right)&lt;/em&gt; is trying them out!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Trac spamming is taking down Melange</title>
      <link>http://anil.recoil.org/2007/04/02/trac-spamming-is-taking-down-melange.html</link>
      <pubDate>2007-04-02T00:00:00+01:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2007/04/02/trac-spamming-is-taking-down-melange</guid>
      <description>&lt;p&gt;After loads of reports that the &lt;a href='http://melange.recoil.org/'&gt;Melange&lt;/a&gt; site keeps going 505 and crashing, I took at look at why. Turns out several spam crawlers were going mental and repeatedly adding tickets with spam links. Around 600 tickets and thousands of comments later, the process decided it had enough and terminated.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve deleted all tickets (even the valid ones were spammed into oblivion) and turned off comment creation and modification for anonymous users. A look on the &lt;a href='http://trac.edgewall.org/wiki'&gt;Trac Wiki&lt;/a&gt; shows that there are some &lt;a href='http://trac.edgewall.org/wiki/SpamFilter'&gt;SpamFilter&lt;/a&gt; extensions being developed which I&amp;#8217;ll investigate at some point.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Melange hits the euro-spotlight</title>
      <link>http://anil.recoil.org/2007/04/01/melange-hits-the-euro-spotlight.html</link>
      <pubDate>2007-04-01T00:00:00+01:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2007/04/01/melange-hits-the-euro-spotlight</guid>
      <description>&lt;p&gt;It&amp;#8217;s been a busy old March (release management of the new &lt;a href='http://www.xensource.com/products/xen_enterprise/index.html'&gt;XenEnterprise&lt;/a&gt; sucked up most of it). I did take a break and go over to &lt;a href='http://www.gsd.inesc-id.pt/conference/EuroSys2007/'&gt;EuroSys 2007&lt;/a&gt; in Portugal to present the language and compiler I &lt;a href='http://melange.recoil.org/'&gt;implemented&lt;/a&gt; as part of my PhD work (&lt;a href='http://anil.recoil.org/papers/2007-eurosys-melange.pdf'&gt;read it here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Although the talk I gave was was a bit underwhelming (more preparation and time-practise next time!), I met a whole bunch of really interesting people. My argument about rewriting whole applications also didn&amp;#8217;t get laughed out the room as I thought it might, as people recognise that retro-fitting safety enhancements on existing languages is a bit of a dead-end road to go down. It has definitely inspired me to make more time to spend on polishing up the &lt;a href='http://melange.recoil.org/'&gt;Melange&lt;/a&gt; applications for a proper release in 2007.&lt;/p&gt;

&lt;p&gt;In a pleasant surprise, it also won the &lt;em&gt;Best Student Paper&lt;/em&gt; award of the conference as well!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Hans Rosling at TED last year on global development</title>
      <link>http://anil.recoil.org/2007/04/01/hans-rosling-at-ted-last-year-on-global-development.html</link>
      <pubDate>2007-04-01T00:00:00+01:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2007/04/01/hans-rosling-at-ted-last-year-on-global-development</guid>
      <description>&lt;p&gt;Having coffee with &lt;a href='http://www.cl.cam.ac.uk/~arb33/'&gt;AliB&lt;/a&gt; and discussing lecturing reminded me of one of the best presentations I&amp;#8217;ve ever seen: &lt;a href='http://roslingsblogger.blogspot.com/'&gt;Hans Rosling&lt;/a&gt; at &lt;a href='http://tedblog.typepad.com/'&gt;TED&lt;/a&gt; and &lt;a href='http://tedblog.typepad.com/tedblog/2006/06/hans_rosling_on.html#'&gt;debunking myths about the developing world&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Even if you&amp;#8217;re not interested in the subject, it&amp;#8217;s worth checking out just to see how cool his presentation of otherwise rather boring statistics is. His company, &lt;a href='http://www.gapminder.org/'&gt;Gapminder&lt;/a&gt; also got &lt;a href='http://googleblog.blogspot.com/2007/03/world-in-motion.html'&gt;bought by Google&lt;/a&gt; a few weeks ago, so chances are &lt;a href='http://www.google.com/analytics/'&gt;Analytics&lt;/a&gt; will get more interesting soon.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Deens, welcome to the Internet!</title>
      <link>http://anil.recoil.org/2006/12/30/deens-welcome-to-the-internet.html</link>
      <pubDate>2006-12-30T00:00:00+00:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2006/12/30/deens-welcome-to-the-internet</guid>
      <description>&lt;p&gt;Inspired by finishing my PhD corrections (!) today, I decided to hook up the DNS server from our &lt;a href='http://melange.recoil.org/'&gt;Melange&lt;/a&gt; project up to the Internet. The authoritative server is called &lt;a href='http://melange.recoil.org/trac/browser/apps/deens/'&gt;deens&lt;/a&gt; (since the co-author is one &lt;a href='http://www.tjd.phlegethon.org/'&gt;Tim Deegan&lt;/a&gt;, geddit?), and is written in pure &lt;a href='http://caml.inria.fr/'&gt;OCaml&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is all rather experimental, to put it mildly, but I stuck in the zone file below, hooked it up as a delegate to our main name-servers, checked it against the &lt;a href='http://www.dnsreport.com/tools/dnsreport.ch?domain=deens.recoil.org'&gt;DNS Report&lt;/a&gt;, and it all seems to be working!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ORIGIN deens.recoil.org. ;
$TTL    240
deens.recoil.org. 604800 IN SOA  (
    deens.recoil.org. anil.recoil.org.
    2006122401 3600 1800 3024000 1800
)
        IN  NS     ns1.deens.recoil.org.
        IN  NS     deensns.recoil.org.
ns1     IN  A      194.70.3.132
dynamic IN  CNAME  dynamic.recoil.org.
static  IN  CNAME  static.recoil.org.
anil    IN  CNAME  dynamic
stats   IN  CNAME  dynamic&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I also modified &lt;a href='http://stats.recoil.org/'&gt;stats.recoil.org&lt;/a&gt; to be an alias to &lt;em&gt;stats.deens.recoil.org&lt;/em&gt;, so all the requests for that domain will go via the deens setup. You actually need a user/pass to access the site, but that doesn&amp;#8217;t matter; if it gets that far, the DNS bit has worked.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s still an awful lot of tedious work to get the server into a production-ready state, such as proper logging, more error handling and recovery, etc., but I really hope to find the time in 2007 to polish this up somewhat. Performance is excellent already; faster than &lt;a href='http://www.isc.org/bind/'&gt;BIND&lt;/a&gt; by quite a lot, and it can optionally use more memory to cache responses to shoot up to crazy levels.&lt;/p&gt;

&lt;p&gt;Incidentally, the &lt;a href='http://melange.recoil.org/trac/browser/apps/mldig/'&gt;dig replacement&lt;/a&gt; utility also seems to be working fairly well, and &lt;a href='http://dave.recoil.org/'&gt;David Scott&lt;/a&gt; has been messing around with a &lt;a href='http://www.apple.com/macosx/features/bonjour/'&gt;Bonjour&lt;/a&gt; implementation that will get finished sometime in 2007 as well (honest!).&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Google Webmaster tools</title>
      <link>http://anil.recoil.org/2006/12/28/google-webmaster-tools.html</link>
      <pubDate>2006-12-28T00:00:00+00:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2006/12/28/google-webmaster-tools</guid>
      <description>&lt;p&gt;The conversion of the Recoil web services to external FastCGI pinned our &lt;a href='http://trac.edgewall.org/'&gt;Trac&lt;/a&gt; installation at &lt;a href='http://melange.recoil.org/'&gt;Melange&lt;/a&gt; as the source of the CPU hogging. It turned out the Google crawler was indexing the entire source tree via Trac, causing it to go ballistic.&lt;/p&gt;

&lt;p&gt;I then stumbled on the latest cool Googlism: the &lt;a href='https://www.google.com/webmasters/tools/'&gt;Google Webmaster Tool&lt;/a&gt;, which lets you register your sites and displays options, diagnostics and statistics about how the Google crawler views your website. I turned down the frequency at which Google hits the Trac installation (as well as installing a suitable &lt;a href='http://melange.recoil.org/robots.txt'&gt;robots.txt&lt;/a&gt; file). This solved the immediate problem, but some of the search statistics were fun to check out as well.&lt;/p&gt;

&lt;p&gt;It turns out the &lt;a href='http://anil.recoil.org/gallery/'&gt;gallery&lt;/a&gt; is pretty highly ranked for &lt;a href='http://images.google.com/'&gt;image searches&lt;/a&gt;. My trips to Japan seems to have made it big, with popular searches including &amp;#8221;&lt;a href='http://images.google.com/images?q=shibuya&amp;amp;hl=en&amp;amp;ie=UTF-8&amp;amp;oe=UTF-8&amp;amp;sa=N&amp;amp;tab=wi'&gt;Shibuya&lt;/a&gt;&amp;#8221;, &amp;#8221;&lt;a href='http://images.google.com/images?q=tokyo%20at%20night&amp;amp;hl=en&amp;amp;ie=UTF-8&amp;amp;oe=UTF-8&amp;amp;sa=N&amp;amp;tab=wi'&gt;tokyo at night&lt;/a&gt;&amp;#8221;, and &amp;#8221;&lt;a href='http://images.google.com/images?q=japanese%20roof&amp;amp;hl=en&amp;amp;ie=UTF-8&amp;amp;oe=UTF-8&amp;amp;sa=N&amp;amp;tab=wi'&gt;japanese roof&lt;/a&gt;&amp;#8221;. My random pictures of &lt;a href='http://images.google.com/images?q=buffalo%20india&amp;amp;hl=en&amp;amp;ie=UTF-8&amp;amp;oe=UTF-8&amp;amp;sa=N&amp;amp;tab=wi'&gt;indian buffaloes&lt;/a&gt;, &lt;a href='http://images.google.com/images?svnum=10&amp;amp;hl=en&amp;amp;lr=&amp;amp;q=smoggy+skyline&amp;amp;btnG=Search'&gt;smoggy skylines&lt;/a&gt; and &lt;a href='http://images.google.com/images?q=fried%20ice%20cream&amp;amp;hl=en&amp;amp;ie=UTF-8&amp;amp;oe=UTF-8&amp;amp;sa=N&amp;amp;tab=wi'&gt;fried ice-cream&lt;/a&gt; seem especially popular as well. It&amp;#8217;s a wierd old Internet eh?&lt;/p&gt;

&lt;p&gt;The gallery has fallen a bit by the wayside in recent months. I&amp;#8217;ll update it when I get back to Cambridge!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Mercurial FastCGI module</title>
      <link>http://anil.recoil.org/2006/12/27/mercurial-fastcgi-module.html</link>
      <pubDate>2006-12-27T00:00:00+00:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2006/12/27/mercurial-fastcgi-module</guid>
      <description>&lt;p&gt;Our &lt;a href='http://www.lighttpd.net'&gt;lighttpd&lt;/a&gt; setup has been very unstable in recent months, probably brought on by the load of the large &lt;a href='http://www.selenic.com/mercurial'&gt;Mercurial&lt;/a&gt; repositories &lt;a href='http://hg.recoil.org/'&gt;hosted&lt;/a&gt; on Recoil since the Google &lt;a href='http://code.google.com/soc/'&gt;Summer of Code&lt;/a&gt; mentoring.&lt;/p&gt;

&lt;p&gt;The source of the instability was really hard to track down, but it seems to be the automatic spawning of &lt;a href='http://www.fastcgi.org/'&gt;FastCGI&lt;/a&gt; processes by the web-server, and lighttpd failing to handle a &lt;a href='http://en.wikipedia.org/wiki/SIGCHLD'&gt;SIGCHLD&lt;/a&gt; somewhere when a child process crashes. To sort this out, I just converted all the Ruby on Rails setups (this blog and &lt;a href='http://nick.recoil.org/'&gt;Nick&amp;#8217;s&lt;/a&gt;) to use an external spawn.&lt;/p&gt;

&lt;p&gt;This only leaves our Mercurial vhost &lt;a href='http://hg.recoil.org/'&gt;hg.recoil.org&lt;/a&gt; to switch to using FastCGI, and I couldn&amp;#8217;t find a module for this anywhere and so lashed up some Python glue to do the job.&lt;/p&gt;

&lt;p&gt;You can download the small distribution for Mercurial 0.9 (&lt;a href='http://anil.recoil.org/projects/hg-fcgi-0.9.tar.gz'&gt;hg-fcgi-0.9.tar.gz&lt;/a&gt;). It has a FastCGI library written by someone else, the Python files to glue the Mercurial and FastCGI libraries together, and a simple rc script to launch the external web process. Instructions are for lighttpd&amp;#8230; install the Python files somewhere, modify them to point to the Mercurial directory, run the rc script to start the daemon, and then add something similar to the following to your lighttpd config file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;fastcgi.server = (
  &amp;quot;.fcgi&amp;quot; =&amp;gt; ( &amp;quot;localhost&amp;quot; =&amp;gt;
    ( &amp;quot;socket&amp;quot; =&amp;gt; &amp;quot;/var/cache/fcgi/sites/hg.recoil.org/dirsock&amp;quot; )),
  &amp;quot;.hg&amp;quot; =&amp;gt; ( &amp;quot;localhost&amp;quot; =&amp;gt;
    ( &amp;quot;socket&amp;quot; =&amp;gt; &amp;quot;/var/cache/fcgi/sites/hg.recoil.org/sock&amp;quot; )),
)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also add &amp;#8220;index.fcgi&amp;#8221; to &lt;em&gt;index-file.names&lt;/em&gt; in the config file, and touch it in the vhost directory to create an empty file (this is to avoid getting a 404 error and instead pass it through to the FastCGI process). Similarly, touch a .hg file for every repository you want to serve. You could do this differently by passing through a URL prefix and modifying the Python appropriately, but I prefer finer control over what we&amp;#8217;re serving.&lt;/p&gt;

&lt;p&gt;Hope this is useful; I won&amp;#8217;t bother submitting it back to the Mercurial list as it looks like the &lt;a href='http://www.selenic.com/hg/'&gt;official hg repo&lt;/a&gt; has a different code layout; I&amp;#8217;ll check it out later on when I have a bit more time and integrate properly.&lt;/p&gt;

&lt;p&gt;I have no idea whether or not this will actually improve our stability, but it&amp;#8217;s at least easier to move onto a different web-server now that everything is FastCGI. All I need now is an OpenBSD/php5-fastcgi port, which doesn&amp;#8217;t seem to exist (yet).&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Looking my Spam statistics</title>
      <link>http://anil.recoil.org/2006/12/27/looking-my-spam-statistics.html</link>
      <pubDate>2006-12-27T00:00:00+00:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2006/12/27/looking-my-spam-statistics</guid>
      <description>&lt;p&gt;The switch to &lt;a href='http://smtpd.develooper.com/'&gt;qpsmtpd&lt;/a&gt; does seem to have reduced my spam intake somewhat, so out of curiousity I looked at the statistics from 2 years of &lt;a href='http://www.procmail.org/'&gt;procmail&lt;/a&gt; logs to see what&amp;#8217;s been happening in terms of filtering effectiveness.&lt;/p&gt;
&lt;a href='http://anil.recoil.org/blog/files/mailstats-dec2006.png' title='Ham/Spam stats for 2004-2006' rel='lightbox'&gt;&lt;img src='/blog/files/mailstats-dec2006-thumb.png' alt='mlgalleryedit' style='float:right' /&gt; &lt;/a&gt;
&lt;p&gt;A quick &lt;a href='http://www.openbsd.org/cgi-bin/cvsweb.cgi/ports/mail/p5-Log-Procmail'&gt;import and bug-fix&lt;/a&gt; of &lt;a href='http://search.cpan.org/dist/Log-Procmail/'&gt;Log::Procmail&lt;/a&gt; into OpenBSD, and some lashed up Perl and gnuplot later, the graph on the right showed up. The red and green are ham and spam respectively, as classified by &lt;a href='http://www.spamassassin.org/'&gt;SpamAssassin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The large amount of ham in 2004 was not actually real mail, but mostly postmaster bounces from forged spam; I am currently forced to destroy all domain bounces without even reading them due to the sheer volume. This is something that &lt;a href='http://www.openspf.org/'&gt;Sender Permitted From&lt;/a&gt; promises to help solve once we determine if any our users send &lt;code&gt;@recoil.org&lt;/code&gt; mail from sources other than our mail server.&lt;/p&gt;

&lt;p&gt;Since the turn of this year the amount of spam has jumped, but more concerningly, SpamAssassin has been missing increasing amounts, and it&amp;#8217;s been flowing through straight to my Inbox (despite &lt;a href='http://wiki.apache.org/spamassassin/RuleUpdates'&gt;sa-update&lt;/a&gt; running daily). I&amp;#8217;m going to do these graphs again in a few months and see just how much the switch to the new paranoid SMTP has helped.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Christmas Spam Cleanup</title>
      <link>http://anil.recoil.org/2006/12/25/christmas-spam-cleanup.html</link>
      <pubDate>2006-12-25T00:00:00+00:00</pubDate>
      <guid isPermaLink="true">http://anil.recoil.org/2006/12/25/christmas-spam-cleanup</guid>
      <description>&lt;p&gt;It&amp;#8217;s Christmas Day, I&amp;#8217;ve eaten far too much, and am lounging around doing the now-traditional Annual Recoil Cleanup as the year&amp;#8217;s todo list has grown ever larger. I&amp;#8217;ve been meaning to switch from our venerable &lt;a href='http://cr.yp.to/qmail.html'&gt;qmail-smtpd&lt;/a&gt; for some years now, and finally made the move over to &lt;a href='http://smtpd.develooper.com/'&gt;qpsmtpd&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;qpsmtpd is a drop-in replacement for the SMTP portion of qmail, and is written in Perl with a number of plug-ins which lets us increase our paranoia levels considerably. It&amp;#8217;s a pity we have to do this, but the policy of &amp;#8216;accept anything&amp;#8217; has been under increasing stress for the last few years, and when I looked at my e-mail stats last night, I realised over 99.99% of my incoming e-mail was some kind of virus or spam. Even a 1% miss rate on SpamAssassin is enough to chuck 100s of mails into my inbox!&lt;/p&gt;

&lt;p&gt;So now the new e-mail setup at Recoil includes virus scanning via the wonderful &lt;a href='http://www.clamav.net/'&gt;clamav&lt;/a&gt;, reverse DNS RBL looksup via &lt;a href='http://www.rfc-ignorant.org'&gt;rfc-ignorant.org&lt;/a&gt;, and even early-chatter detection of viruses which blindly blast messages before the initial SMTP greeting has completed. I&amp;#8217;m hoping to enable global &lt;a href='http://www.spamassassin.org/'&gt;SpamAssassin&lt;/a&gt; checking soon if all else is stable and I don&amp;#8217;t get bleating about missing mail from our users.&lt;/p&gt;

&lt;p&gt;I played with &lt;a href='http://greylisting.org/'&gt;Greylisting&lt;/a&gt; as well to see if it had improved from my &lt;a href='http://anil.recoil.org/blog/articles/2004/07/29/playing-with-spammers'&gt;earlier experiments&lt;/a&gt; a couple of years ago. Unfortunately, it still looks as if there are many broken MTAs out there which don&amp;#8217;t cope well with rejection, and manual whitelists are required, which sounds a bit unreliable for setups like ours which sometimes don&amp;#8217;t get looked at for years on end (ahem).&lt;/p&gt;

&lt;p&gt;So it&amp;#8217;s with a tear in my eye that I wave goodbye to &lt;em&gt;qmail-smtpd&lt;/em&gt;, the first ever network-facing service deployed on Recoil back in 1998, and incredibly, the only one I&amp;#8217;ve never had to upgrade in the 8 years since.&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>
