One of the key advantages of db4o is that it simply stores any object with just one line of code:
objectContainer.store(myObject);
...but how ?
In the past the magic to make this possible was hidden deep down in db4o core. The TypeHandler4 interface in the 6.1 sources consisted of 39 methods. Noone in the community was crazy enough to try to write one of these, or maybe some turned crazy when they tried. In either case we never heard about an attempt.
Our new revised TypeHandler interface speaks for itself:
public interface TypeHandler4 extends Comparable4 {
void delete(DeleteContext context);
void defragment(DefragmentContext context);
Object read(ReadContext context);
void write(WriteContext context, Object obj);
}
public interface Comparable4 {
PreparedComparison prepareComparison(Object obj);
}
It turned out to be a lot of work to refactor our code to use the new interface. Because we wanted to hide the internal indirection logic to compose slots with variable length entries, we basically had to rewrite all marshalling and unmarshalling logic.
We wanted to make 100% sure to stay compatible with old databases so we ended up writing a huge new test suite (code is in Db4oMigrationTestSuite). It loads all old db4o database engines from within a folder to generate, test and defragment tons of old database files on the fly. Obviously we are now sure that the backward compatibility of version 7.x to old databases really is excellent, because it's so well tested.
Finally the new TypeHandler interface is complete and it turns out to be fun to use. We already see it pay off for quality and development speed in our day-to-day work. Here are some examples where new TypeHandlers have already helped us to add support for constructs that we did not store well in the past:
In the near term we have plans to use the new Typehandlers for:
- Reengineering the handling of .NET generic collections to finally provide rocksolid support
- Writing a series of very fast collection handlers that operate on a lower level than before and scale much better for large collections
- Tuning type handling of all types. A UTF-8 string encoder is overdue. Now it's very easy to write one.
- Improving the handling of enums
- Fixing issues with primitive type wrappers (Java) and nullable types (.NET) in typed arrays
Because the interface is so simple now, we also expect people from the community to write own custom TypeHandlers to optimize the storage of their own constructs. That's why TypeHandlers are now pluggable from the outside, see Configuration#registerTypeHandler().
If you want to try to write your own TypeHandler, it will make sense to explore how the built-in ones work. Please also take a look at the type hierarchy of TypeHandler4. Access to extended functionality is available through the subclasses IndexableTypeHandler, SecondClassTypeHandler and VariableLengthTypeHandler. These interfaces may still change a little bit and there may be a couple more of them in the future.
A very cool aspect of new TypeHandlers is the integrated versioning: It is easily possible to change how specific types are treated in a specific db4o version. All update management is handled automatically by the framework. The migration test suite we have in place ensures that this really works perfectly. Accordingly we are no longer afraid at all of changing and improving our database file format. We will make progress much more quickly. We also expect people from the community to come up with smart Typehandlers and to submit them to us.
I am looking forward to all your great ideas of how to use this new interface to make db4o even more powerful and even faster.
Enjoy!