Schema Generation in ORMs

When Storm was released, one of the comments made was that it did not include the ability to generate a database schema from the Python classes used to represent the tables while this feature is available in a number of competing ORMs. The simple reason for this is that we haven’t used schema generation in any of our ORM-using projects.

Furthermore I’d argue that schema generation is not really appropriate for long lived projects where the data stored in the database is important. Imagine developing an application along these lines:

  1. Write the initial version of the application.
  2. Generate a schema from the code.
  3. Deploy one or more instances of the application in production, and accumulate some data.
  4. Do further development on the application, that involves modifications to the schema.
  5. Deploy the new version of the application.

In order to perform step 5, it will be necessary to modify the existing database to match the new schema. These changes might be in a number of forms, including:

  • adding or removing a table
  • adding or removing a column from a table
  • changing the way data is represented in a particular column
  • refactoring one table into two related tables or vice versa
  • adding or removing an index

Assuming that you want to keep the existing data, it isn’t enough to simply represent the new schema in the updated application: we need to know how that new schema relates to the old one in order to migrate the existing data.

For some changes like addition of tables, it is pretty easy to update the schema given knowledge of the new schema. For others it is more difficult, and will often require custom migration logic. So it is likely that you will need to write a custom script to migrate the schema and data.

Now we have two methods of building the database schema for the application:

  1. generate a schema from the new version of the application.
  2. generate a schema from the old version of the application, then run the migration script.

Are you sure that the two methods will result in the same schema? How about if we iterate the process another 10 times or so? As a related question, are you sure that the database environment your tests are running under match the production environment?

The approach we settled on with Launchpad development was to only deal with migration scripts and not generate schemas from the code. The migration scripts are formulated as a sequence of SQL commands to migrate the schema and data as needed. So to set up a new instance, a base schema is loaded then patched up to the current schema. Each patch leaves a record in the database that it has been applied so it is trivial to bring a database up to date, or check that an application is in sync with the database.

When the schema is not generated from the code, it also means that the code can be simpler. As far as Python ORM layer is concerned, does it matter what type of integer a field contains? Does the Python code care what indexes or constraints are defined for the table? By only specifying what is needed to effectively map data to Python objects, we end up with easy to understand code without annotations that probably can’t specify everything we want anyway.

Upgrading to Ubuntu Gutsy

I got round to upgrading my desktop system to Gutsy today. I’d upgraded my laptop the previous week, so was not expecting much in the way of problems.

I’d done the original install on my desktop back in the Warty days, and the root partition was a bit too small to perform the upgrade. As there was a fair bit of accumulated crud, I decided to do a clean install. Things mostly worked, but there were a few problems, which I detail below:

Dual Head Configuration

With previous releases, I was using the Radeon driver’s MergedFB mode, as it gives a better user experience than the traditional Xinerama code (3D acceleration on both heads, better performance, etc). After moving adding the MergedFB options to xorg.conf, I was just getting the same image cloned on both displays.

Looking at the X server log file, there was a message saying that MergedFB support had been removed in favour of RandR 1.2 support. And it was possible to get dual head working with the xrandr command line tool:

xrandr --output VGA-0 --right-of DVI-0

It was good to know that dual-head still worked, but I didn’t want to reconfigure this every time I restarted the machine. I didn’t find much information on how to configure the initial RandR configuration on the X.org website, but did find a useful guide on the Intel Linux Graphics website. While the guide was aimed at the Intel driver, it had enough information to get things configured for the Radeon driver. The main difference was in the naming of the outputs. Below is a an excerpt of my configuration file that configures things the way I had them previously:

Section "Device"
        Identifier      "ATI Technologies Inc RV280 [Radeon 9200 SE]"
        Driver          "ati"
        BusID           "PCI:1:0:0"
        Option          "monitor-DVI-0" "Sony SDM-S74 [1]"
        Option          "monitor-VGA-0" "Sony SDM-S74 [2]"
EndSection

Section "Monitor"
        Identifier      "Sony SDM-S74 [1]"
        Option          "DPMS"
        HorizSync       30-65
        VertRefresh     50-75
        Option          "LeftOf"        "Sony SDM-S74 [2]"
EndSection

Section "Monitor"
        Identifier      "Sony SDM-S74 [2]"
        Option          "DPMS"
        HorizSync       30-65
        VertRefresh     50-75
EndSection

Section "Screen"
        Identifier      "Default Screen"
        Device          "ATI Technologies Inc RV280 [Radeon 9200 SE]"
        Monitor         "Sony SDM-S74 [1]"
        DefaultDepth    16
        SubSection "Display"
                Modes           "1280x1024" "1024x768" "800x600" "640x480"
                Virtual         2560 1024
        EndSubSection
EndSection

I had originally tried setting the VGA monitor to be “RightOf” the monitor connected to the DVI, but that left me with the desktop in clone mode. The main difference I’ve noticed with this configuration compared to my previous one is that the GDM login prompt displays on the right hand head (VGA) rather than the left hand head (DVI).

Window Shadows Don’t Render

Desktop Effects were enabled by default after the install (and on the live CD). While some effects seemed to work, the shadows on the panel and drop down menus were rendered as opaque grey boxes around the windows. I ended up just disabling the effects to clear up the problem.

This bug had already been reported as bug 141304 (which may be the same as bug 116808).

Firefox Crashes on Startup

When I tried to start firefox, it would momentarily display a window and then crash. This appears to be bug 133124, and seems to only occur on AMD64 systems. The problem appears to be in the ubuntulooks theme engine, and switching to a different control theme makes the problem go away, but hopefully it’ll get fixed for the final release.

Problems Rendering Ligatures in Firefox

The problems rendering ligatures in firefox seem to be back again. This problem was never really fixed, but was worked around by removing the ligature table entries from the DejaVu fonts. With the ligature table entries back, the symptoms have returned. This is bug 37828.

Canonical Shop Open

The new Canonical Shop was opened recently which allows you to buy anything from Ubuntu tshirts and DVDs up to a 24/7 support contract for your server.

One thing to note is that this is the first site using our new Launchpad single sign-on infrastructure. We will be rolling this out to other sites in time, which should give a better user experience to the existing shared authentication system currently in place for the wikis.

gnome-vfs-obexftp 0.4

It hasn’t been long since the last gnome-vfs-obexftp release, but I thought it’d be good to get these fixes out before undertaking more invasive development. The new version is available from:

http://download.gnome.org/sources/gnome-vfs-obexftp/0.4/

The highlights of this release are:

  • If the phone does not provide free space values in the OBEX capability object, do not report this as zero free space. This fixes Nautilus file copy behaviour on a number of Sony Ericsson phones.
  • Fix date parsing when the phone returns UTC timestamps in the folder listings.
  • Add some tests for the capability object and folder listing XML parsers. Currently has sample data for Nokia 6230, Motorola KRZR K1, and Sony K800i, Z530i and Z710i phones.

These fixes should improve the user experience for owners of some Sony Ericsson phones by letting them copy files to the phone, rather than Nautilus just telling them that there is no free space. Unfortunately, if there isn’t enough free space you’ll get an error part way through the copy. This is the best that can be done with the information provided by the phone.

Test Suite

As noted in the third point, I’ve started to build up a collection of capability and folder listing XML documents produced by various phone models. This serves a dual purpose:

  1. Ensure that the capability object and folder listing XML parsers don’t regress between releases. It is impractical for me to test gnome-vfs-obexftp against all these phone models since I don’t have the hardware or time.
  2. Give an idea of what information the different phone models provide, which should be useful when planning new features.

If you have an OBEX FTP capable phone that is not already in the test suite, it’d be useful if you could collect the data and file a bug. The information can be collected using the command line “obexftp” program (part of the “obexftp” package on Ubuntu). The following commands will give the capability object and root folder listing:

obexftp --bluetooth $BDADDR --capability
obexftp --bluetooth $BDADDR --list

It’d also be useful to get a listing for one or two other directories. If there is a memory card, it’d be useful to get that folder. For example:

obexftp --bluetooth $BDADDR --list "Memory card/"

It’d be most useful if the transcript of the various commands were included as an attachment. Feel free to censor personal information if you want (e.g. the phone serial number in the capability object, some non-default file names).

In particular, I wouldn’t mind getting information on phones with brands other than than Nokia or Sony to see what info they provide.

Investigating OBEX over USB

I’ve had a number of requests for USB support in gnome-vfs-obexftp. At first I didn’t have much luck talking to my phone via USB. Running the obex_test utility from OpenOBEX gave the following results:

$ obex_test -u
Using USB transport, querying available interfaces
Interface 0:   (null)
Interface 1:   (null)
Interface 2:   (null)
Use 'obex_test -u interface_number' to run interactive OBEX test client

Trying to talk via any of these interface numbers failed. After reading up a bit, it turned out that I needed to add a udev rule to give permissions on my phone. After doing so, I got a better result:

$ obex_test -u
Using USB transport, querying available interfaces
Interface 0: Nokia Nokia 6230 (null)
Interface 1: Nokia Nokia 6230 (null)
Interface 2: Nokia Nokia 6230 (null)
Use 'obex_test -u interface_number' to run interactive OBEX test client

With the change, I was also able to access the phone using the obexftp command line client. This seemed enough to start investigating a bit further. The OpenOBEX API for setting up USB connections goes something like this:

  1. The app calls OBEX_FindInterfaces(), which returns a list of obex_interface_t structures that represent the different discovered interfaces.
  2. The app picks one of the discovered interfaces (based on the manufacturer, product and serial number strings), then connects to it using OBEX_InterfaceConnect().

There are a number of issues with this interface though.

  • If the phone doesn’t provide a serial number via its USB interface (like my 6230 doesn’t), the obex_interface_t structure is not enough to identify a particular phone.
  • If the phone exposes multiple OBEX USB interfaces for some reason, OpenOBEX lists it multiple times. In the obex_test output shown above, there was a single phone attached – not three.
  • There is no way to tell when phones are connected or disconnected. While HAL can do that job for us, there is no way to map from the device information provided by HAL to one of the discovered interfaces provided by OpenOBEX.

To sum up, it shouldn’t be difficult to hack support for USB connections into gnome-vfs-obexftp with URLs like obex://usb-N/ (where N is the number of the discovered interface), but there are a number of features I’d need to provide a good user experience:

  1. The ability to ask OpenOBEX to connect to a particular USB device, rather than having to deal with its discovery interface.
  2. A good set of udev rules to grant the needed permissions on common phones so they don’t need to find out why things only work as root.

gnome-vfs-obexftp 0.3

I’ve just released a new version of gnome-vfs-obexftp, which includes the features discussed previously. It can be downloaded from:

http://download.gnome.org/sources/gnome-vfs-obexftp/0.3/

The highlights of the release include:

  • Sync osso-gwobex and osso-gnome-vfs-extras changes from Maemo Subversion.
  • Instead of asking hcid to set up the RFCOMM device for communication, use an RFCOMM socket directly. This is both faster and doesn’t require enabling experimental hcid interfaces. Based on work from Bastien Nocera.
  • Improve free space calculation for Nokia phones with multiple memory types (e.g. phone memory and a memory card). Now the free space for the correct memory type for a given directory should be returned. This fixes various free-space dependent operations in Nautilus such as copying files.

Any bug reports should be filed in Launchpad at:

https://bugs.launchpad.net/gnome-vfs-obexftp/

FM Radio in Rhythmbox – The Code

Previously, I posted about the FM radio plugin I was working on. I just posted the code to bug 168735. A few notes about the implementation:

  • The code only supports Video4Linux 2 radio tuners (since that’s the interface my device supports, and the V4L1 compatibility layer doesn’t work for it). It should be possible to port it support both protocols if someone is interested.
  • It does not pass the audio through the GStreamer pipeline. Instead, you need to configure your mixer settings to pass the audio through (e.g. unmute the Line-in source and set the volume appropriately). It plugs in a GStreamer source that generates silence to work with the rest of the Rhythmbox infrastructure. This does mean that the volume control and visualisations won’t work
  • No properties dialog yet. If you want to set titles on the stations, you’ll need to edit rhythmdb.xml directly at the moment.
  • The code assumes that the radio device is /dev/radio0.

Other than that, it all works quite well (I’ve been using it for the last few weeks).

Development

I developed this plugin in Bazaar using Jelmer‘s bzr-svn plugin. It produces a repeatable import, so I should be able to cross merge with anyone else producing branches with it.

It is also possible to use bzr-svn to merge Bazaar branches back into the original Subversion repository through the use of a lightweight checkout.

For anyone wanting to play with my Bazaar branch, it is published in Launchpad and can be grabbed with the following command:

bzr branch lp:~jamesh/rhythmbox/fmradio rhythmbox

FM Radio in Rhythmbox

I’ve been working on some FM radio support in Rhythmbox in my spare time. Below is screenshot

At the moment, the basic tuning and mute/unmute works fine with my DSB-R100. I don’t have any UI for adding/removing stations at the moment though, so it is necessary to edit ~/.gnome2/rhythmbox/rhythmdb.xml to add them.

FM Radio Tuners in Feisty

I upgraded to Feisty about a month or so ago, and it has been a nice improvement so far. One regression I noticed though was that my USB FM radio tuner had stopped working (or at least, Gnomeradio could no longer tune it).

It turns out that some time between the kernel release found in Edgy and the one found in Feisty, the dsbr100 driver had been upgraded from the Video4Linux 1 API to Video4Linux 2. Now the driver nominally supports the V4L1 ioctls through the v4l1_compat, but it doesn’t seem to implement enough V4L2 ioctls to make it usable (the VIDIOCGAUDIO ioctl fails).

To work around this, I ported the tuner code in Gnomeradio over to V4L2. The patch can be found attached to bug 429005. I don’t know if this patch will go in as is though, since it only works for drivers supporting V4L2. Perhaps it’d be worth supporting both APIs, using V4L2 if both are supported.

Launchpad 1.0 Public Beta

Today we unveiled the Launchpad 1.0 User Interface, which has been in private beta for the last few months. As well as the improved visual appearance, there are a number of new features such as the ability to add your own branding to Launchpad pages associated with your project (for example, Ubuntu’s pages).

As mentioned in the press release, we’ve got two new high profile projects using us for bug tracking: The Zope 3 Project and The Silva Content Management System. As part of their migration, we imported all their old bug reports (for Zope 3, and for Silva). This was done using the same import process that we used for the SchoolTool import. Getting this process documented so that other projects can more easily switch to Launchpad is still on my todo list.

As Launchpad is a user of Zope 3 technology, it is great being able to provide the bug tracking infrastructure for the project. It should also make it easier to collaborate on bugs that affect both Launchpad and Zope.