Norbert Hartl

mostly brackets and pipes

Solving Class Version Trouble in Gemstone

Gemstone makes your life easier regarding persistence (the same as smalltalk does with programming) most of the time. It does not only automatically persist your data. At the same time it is a multi user environment. Changing/updating code in such an environment is a challenge. The list of things that can go wrong is just too big. If you have your session switched to automigration mode than every time you commit a new version of a class gemstone will migrate all existing instances for you.

If you don’t automigrate the class is updated but the instances are left alone. You can do this at a later time. How can this work? Gemstone does versioning of classes. On commit time your new class gets a new version but the existing objects point to a class with an older version. But it is possible that this powerful feature turns against you. Sometimes the migration isn’t finished fully. And your system state is not 100% sane. Things you might experience are:

  • You add an instance variable and an accessor to your class but everytime you try to access it gemstone complains about the accessor not being known. That means most of the time that the piece of code you are testing refers an older version of your class

  • You see a class multiple times in the class browser. Here the situation is that most of the subclasses (of the doubled class) refer to the newest class version while a few subclasses still refer to an older version. Therefor both class(version)s are shown.

In every case you need to get rid of the reference to the old class version. In the first scenario above you need to determine where this old reference can still be active. A prominent example is seaside development. In the configuration of seaside you add your component and session class to the configuration. If one of these classes changes than it can be that the reference to an old version is here. Re-register your web application will solve this.

The second scenario is easier to find because you see a doubled class in the browser. But it can be trickier to find the cause of the doubling. Here are some things that help solving this:

  • every class has its unique id. You can ask a class for this id with the message YourClass asOop
  • to find out the existing versions of a class you can ask for the class history: YourClass classHistory

Now we just need to find out how we can get the suspicious classes. Working with subclasses message won’t reliably work because of the version mismatch. But at least every of these classes must be a subclass of Object. The best results I got so far with

| doubledClass history |
doubledClass := WHComponent.
history := (doubledClass classHistory    
   collect: [:cl | cl asOop ]) allButLast.
Object allSubclasses    
   select: [:each| history includes: each superclass asOop ]

If I find many I lazily use the last line as

(Object allSubclasses 
   select: [:each| history includes: each superclass asOop ])      
      first browse

This way the browser opens on the right class I enter a space and remove it and press ctrl+s. Well, if there aren’t any left I get an exception. But at that time this exception pretty much welcomed, don’t you agree?Hope this helps!