Thursday, May 22, 2008

Any Updates?

The zero-bugs.com site is about to be revamped, and the side picture should give you a sense of the new look and feel.

I had tremendous fun indulging my artistic side and created the new design using Inkscape 0.45 and Gimp (except for the product box).

The new site's main goal is to better manage software releases. A new back end component allows users to check for software updates (the debugger UI now has a new menu entry: Help --> Check for Updates).

I have improved my uploading script (which I have been using for pushing the software to the site); meta information is updated on the server side each time a binary is uploaded. The meta information is used by the "check for updates" feature; it is also used by a CGI to dynamically generate the download pages, so that users always download the most up-to-date code.

The debugger program connects to the server every time a user clicks on the "check for update" menu, and consults the meta information. Because the format of the server files containing software meta information is dictated by my uploading script, I did not want to hard-code the way these are read. Instead, I created a new client-side Python program.

I wanted the update mechanism to be as generic as possible, and allow for plug-ins to be updated independently, should such a need arise (for example when plug-ins from third-parties are included in the distribution).

To this end, I added a couple of new interfaces which look something like this:

struct Update : public ZObject
{
/**
* URL of the package (DEB, RPM, etc.) that contains an update.
*/
virtual const char* url() const = 0;

/**
* Description of changes in this update.
*/
virtual const char* description() const = 0;

virtual void apply() = 0;

virtual Update* copy() const = 0;
};


struct Updateable : public ZObject
{
virtual size_t check_for_updates(Enumerator<update*>*) = 0;
};
(The ZObject and the Enumerator are building blocks from my ZDK -- Zero Developer Toolkit -- on which the ZeroBUGS is built. They are not essential for the purpose of this post).

The way the update works is very simple: the engine queries each plugin for the Updateable interface. If the interface is detected, the check_for_updates method is invoked; the Enumerator then populates a container of pointers to Update objects, and the URL of each update is displayed in a UI HTML control.

With this simple, generic mechanism, each pluggable component can implement the details for its own update.

My concrete implementation lives in the Python scripting module which acts as a gateway between the bulk of the debugger code, written in C++, and extension written in Python.

The client-side script is ridiculously simple:

from datetime import datetime
import httplib
import urllib
import zero

server="www.zero-bugs.com"
published_dir="/8001/published/"

def check_for_updates(sysid, date):
print "checking updates for:", sysid, date
conn = httplib.HTTPConnection(server)
url = urllib.quote(published_dir + sysid)
conn.request("GET", url)
r = conn.getresponse()
info = r.read().split("\n")
conn.close()
my_build_date = datetime.strptime(date, "%Y-%m-%d")
build_date = datetime.strptime(info[0], "%Y-%m-%d")

if my_build_date < build_date:
url = "http://" + server + info[1]
info.pop(0) #pop the date
info.pop(0) #pop the url
info[0] = info[0] + "<br/>"
desc = "\n".join(info)
#
# functions returns a list of available updates
#
return [ zero.Update(url, desc) ]


I plan to launch the new site after Memorial Day. And after that I plan to release a new feature: support for remote debugging. I have written a minimalistic server and a companion plug-in that will allow users to debug machines where resources scarcity does not permit a full-fledged ZeroBUGS installation (you did not think that I took a three week hiatus from my blog just to re-write a website, heh).