Sunday, October 11, 2009

Inserting Data Using Preon

I started work on supporting encoding data the other day. There are quite a few complications, and I noticed that just jotting them down is not going to help or anyone else to come up with some solutions. First I need a better description of the problem.

So I decided I would add a couple of examples that are slightly more detailed, in order to be able to highlight the problems, and explain the solutions that I'm currently thinking of.

The first example is about a simple image format. (I'm just so grateful we have images. Where would I have been without them. They always seem to serve as be the best examples in cases like this.) It only defines a slot for the number of pixels and then defines the color values for those pixels.


The example above illustrates an instance of this model, based on a 400 pixel image. The orange region highlights the first pixel value in the byte stream. It shows the relation between the object instance and the corresponding location in the byte stream.

Now, if the above would have been decoded using Preon, then the code would have probably looked a little like this:

class Image {
@Bound int nrPixels;
@BoundList(size="nrPixels") List<Color> pixels;
}

class Color {
@Bound byte red;
@Bound byte green;
@Bound byte blue;
}

It clearly shows the link between the nrPixels attribute and the pixels attribute. Now, suppose that Preon would allow you to modify the data and then encode the data. What would that look like in this case? The image below is trying to capture it:


So, only inserting a single pixel would already require quite some changes. In fact, it would basically require a rewrite of the entire byte stream.
  • The nrPixels attribute would change from 0x190 to 0x191. (See pink region.)

  • The entire pixel array would have to be shifted to the right in order to allocate space for the new pixel to be inserted.

  • That new pixel would have to be inserted. (See orange region.)
The question that I'm trying to answer myself is how Preon should deal with this. There are a couple of challenges, given the way Preon works.
  • If the List pixel 'array' would have supported the insert operation, then the 'nrPixels' attribute is not automatically updated if you would insert a new pixel.

  • Changing the nrPixels attribute would not automatically allocate a new element in the list of pixels.

  • Given the fact that Preon writes to private fields of objects, it's going to be pretty hard to notice updates to any of these fields at all.
Now, that's quite a few challenges. My first thoughts on this:
  • Since the List pixels attribute will cause Preon to insert an instance of its own List class, it should be possible to intercept changes to that list. If the size of the list is based on an attribute value read upstream, then it should be possible to update that value with every change to the pixels list.

  • However, this would only work in case that attribute value is only defining an encoding/decoding attribute for that specific List. If there are other data elements read downstream that are based on that same attribute value, it would be impossible to update it automatically.

  • In cases like these, Preon could still be able to check the dependencies as a constraint and abort the encoding process if the constraints are violated.

2 comments:

ap_openid said...

The problem you describe with regard to not being able to automatically update nrPixels on an insert if downstream code depends on the original value seems like something that could be approached with a transaction-like model. The "read" transaction would maintain the old values whilst updates would be made to a "write" transaction and then committed once the changes are complete.

Wilfred said...

I've been thinking about that as well. In fact, I was wondering if the entire update functionality should be a copy on change into an STM and then overlaying the original data with the data in the STM when writing the data... It might be doable, but I'm afraid it would be too big to fit in a realistic time frame.