December 12, 2004

out for a spin

I took a couple of friends flying yesterday. It was a beatiful day, after a few weeks of bad weather. That meant, of course, that everybody had to come up with the same idea.

The airport was extremely crowded. We were 3rd in the takeoff sequence, with at least 4 airplanes waiting after us. 3 airplanes landed in the short period before our turn came up.

We left the airport to the north and got a "traffic 9 o'clock, 1 mile" advise from the tower before leaving Addison's airspace. Figuring the friendly skies would be as crowded as the ground, I turned my radio to the approach frequency to listen for nearby traffic as soon as we were clear of Class D airspace.

We cruised around for a bit, keeping a watchful 3 sets of eyes (it's always a good idea to have your passengers look out for traffic as well) on the space around us. When flying under VFR (visual flight rules), it's the pilot's responsibility to see and avoid other aircraft, even when talking to ground-based controllers. The may occasionally advise about nearby traffic, but they are not required to do so. After all, they are not liable if you have an intimate encounter with another plane.

We did, indeed, come across a few other airplanes and had to maneuver to avoid getting too close to them. Other than that, our short trip was peaceful and uneventful.

As always, I really enjoyed the flight, which was a welcome break from the more demanding aerobatic training I've been working on for the past couple of months.

December 09, 2004

learning to cherish

I took this picture a few months ago. Needless to say, it's one of my favorites.



backing up digital pictures

I have a 6 megapixel digital camera. Each picture I take uses up around 6 mb of disk space (at the highest quality, RAW format) and I've already shot almost a thousand.

Backing up that amount of data is becoming a royal pain in the butt. CDs are already too small. DVDs will soon be, too, at the rate at which I'm taking pictures. As a temporary measure, I'm storing all the images in my iPod and I will probably have to get an external drive.

My main concern is that soon I'm not going to be able to keep all my pictures in my puny laptop hard drive. I may need to get two external drives, instead, for primary and backup storage.

Or how does a RAID-5 disk array sound?

December 08, 2004

the great playlist meme of '04

Here are the instructions:
  1. Open up the music player on your computer.
  2. Set it to play your entire music collection.
  3. Hit the "shuffle" command.
  4. Tell us the title of the next ten songs that show up (with their musicians), no matter how embarrassing. That's right, no skipping that Carpenters tune that will totally destroy your hip credibility. It's time for total musical honesty. Write it up in your blog or journal and link back to at least a couple of the other sites where you saw this.
  5. If you get the same artist twice, you may skip the second (or third, or etc.) occurrences. You don't have to, but since randomness could mean you end up with a list of ten song with five artists, you can if you'd like.
Here's my list:
  1. Down To The Waterline - Dire Straits
  2. Cerca De La Revolución - Charly García
  3. Entre Caníbales - Soda Stereo
  4. I Can't Tell You Why - The Eagles
  5. Englishman In New York - Sting
  6. Stuck In A Moment You Can't Get Out Of - U2
  7. Quizas Porque - Sui Generis
  8. Big Shot - Billy Joel
  9. Que Hago Ahora (Dónde Pongo Lo Hallado) - Silvio Rodriguez
  10. Pennyroyal Tea - Nirvana
via Diego

Stack trace translation using annotations

Code generators and compilers that use Java as an intermediate language (e.g, JSP compilers) can take advantage of the new Java annotations feature for translating stack traces.

Why is this necessary? Any runtime error in the form of an exception will have its stack trace expressed in terms of the intermediate java code. Troubleshooting the problem could become a nightmare, unless the line and number information is presented in the context of the components and methods originally written by the developer.

In simple terms, the idea is to place line number information in metadata blocks in every class generated by the compiler. This information is accessed during runtime to interpret and translate stack traces back into something the developer will understand.

Let's consider a hypothetical component called "MyObj" that has two methods: "methodA" and "methodB". Here's an example of what the intermediate Java code might look like:

@TranslationTable(lines = {
  @Entry(line=11,component="MyObj",method="methodA",sourceLine=241),
  @Entry(line=12,component="MyObj",method="methodA",sourceLine=247),
  @Entry(line=13,component="MyObj",method="methodA",sourceLine=249),
  @Entry(line=18,component="MyObj",method="methodB",sourceLine=340)
})
public class AutogeneratedObject
{
  void autogeneratedMethod1()
  {
     int a = 1;
     int b = 2;
     autogeneratedMethod2();
  }

  void autogeneratedMethod2()
  {
     throw new RuntimeException();
  }
}


The metadata block is made of a tag (@TranslationTable) that contains a list of sub-tags (@Entry). Each entry represents a line of significant code in the generated class. Information about the line number in the generated class and the name of the original component, method and line number it maps to are stored in each entry.

Here's the definition of the Entry tag:

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
public @interface Entry
{
  int line();

  String component();
  String method() default "[unknown]";
  int sourceLine();
}


And here's the TranslationTable tag:

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TranslationTable
{
  Entry[] lines();
}


The stack trace translator takes each stack frame, obtains the associated class, queries the class for it's TranslationTable metadata and looks up the TranslationTableEntry for the line reported by the stack frame.

This is what the stack trace translator might look like. I know, I know, the implementation very inefficient (linear traversals of the translation tables, no caching)... I'm just trying to make a point here :)

StackTraceElement[] translate(StackTraceElement[] elements)
{
  List result = new ArrayList();

  for (StackTraceElement element : elements) {
     try {
       Class clazz = Class.forName(element.getClassName());
       TranslationTable table = (TranslationTable) clazz.getAnnotation(TranslationTable.class);

       boolean found = false;
       if (table != null) {
         for (Entry line : table.lines()) {
           if (line.line() == element.getLineNumber()) {
             result.add(new StackTraceElement(line.component(), line.method(), line.component(), line.sourceLine()));
             found = true;
             break;
           }
         }
       }

       if (table == null || !found) {
         result.add(element);
       }
     }
     catch (ClassNotFoundException e) {
       e.printStackTrace();
     }

  }

  return result.toArray(new StackTraceElement[0]);
}


If you're not in the mood for trying out the code, I already did it for you :). Here's a regular Java stack trace:

java.lang.RuntimeException
  at AutogeneratedObject.autogeneratedMethod2(Test.java:18)
  at AutogeneratedObject.autogeneratedMethod1(Test.java:13)
  at Test.main(Test.java:25)


And the translated version:

MyObj.methodB(340)
MyObj.methodA(249)
Test.main(25)

split-s

... just make sure you're high enough



Photo by SSgt Bennie J. Davis III
Still Photographer, USAF