Sunday, January 15, 2012

Space Wars Game

I've had a request to publish the space wars game.  You can download the parcel here.  I'll upload it to the Cincom Public Store repository as soon as I can.

Friday, January 6, 2012

GemStone 6.1.5 Time Bomb

Ok, let's see a show of hands - how many people have GemStone projects running on 6.1.5?  Ok, of those, how many encountered a mysterious crash yesterday?

It seems that RcQueue uses a timestamp for its records.  That timestamp is the number of seconds since January 1, 1995.  It's constrained to be a small integer.  Yesterday, it overflowed to a large integer, violated the constraint, and brought our production server to its knees.

Fortunately, there's a fix in GemStone 6.6 - it now records timestamps since January 1, 2005.  There, that fixes the problems.  Everybody set your watches for January 5, 2022.

Friday, December 16, 2011

Atomic Loading working with GemKit

After much pain mucking about in namespaces, I finally managed to load GemStone code saved in Store using atomic loading.

Atomic loading first loads code into a temporary namespace called the shadow namespace.  Once everything is compiled there and it looks good, the system is re-compiled into the real namespace and the shadow namespace disappears.

With GemStone code, I thought I had everything setup to compile the code into the shadow namespace but when I did the actual compile, the code ended up in the real namespace right away.  This is bad because in the shadow world, the system would add the compilerClass and classCompilerClass methods to tell the shadow class what the compiler is.  You don't want to move these methods into the real namespace because it would cause crashes - which it did.

To allow me to quickly see what was going on, I wrote a tool that simply showed a tree view with a portion of the namespace hierarchy that I was interested in along with the shadow hierarchy.  It also showed the identityHashes of the namespaces so I could quickly tell what namespace I was looking at in an inspector.  If the namespace contained shared variables or classes, it would show those in the tree and if the classes had methods, it would show those as well.  Here's what it looked like.

Now for the problem.  When you login to GemStone as a user (for example, David), GemKit creates a namespace for you called Root.GemStone.AllUsers.David.  It also aliases this as Root.GemStone.CurrentUser. You can see that in the above image.

When you create the shadow environment, Store creates a mimic of the namespace structure.  Since CurrentUser wasn't marked as a namespace link, Store didn't create it in Shadow. Ok, fair enough.  I augmented the system to create CurrentUser in the shadow namespace. Sadly, that wasn't enough to fix the problem.

Now when I try to compile, the system locates Root.GemStone in the shadow namespace (so far so good) and asks it to resolve the symbol #UserGlobals.  This is where it will put the class it's compiling.  UserGlobals isn't in GemStone directly but rather in CurrentUser which is in the imports of GemStone. The problem:  The imported namespace CurrentUser is coming from the real environment instead of the shadow environment.  It finds UserGlobals in the real world and compiles the class directly there.

Aaarg - ok, I go and smash the imports in the shadow GemStone namespace to point to the CurrentUser in the shadow.  Now it complains about a method conflict during the install.  When you try to move the shadow classes to the real environment, you must first move the class then move the methods.  When you move a GemStone class to the real world, you automatically get a class method called gsst_definition.  When we try to move the gsst_definition method from the shadow world to the real world, the system detects that there's a conflict and stops.

As it turns out, you have to change both imported namespaces in the shadow GemStone to point to the shadow and you also need to change the imported namespaces in the shadow GemStone.Globals to point back to the shadow GemStone instead of the real GemStone.

<sigh>  After all that, atomic loading works with GemStone code.  Yay!  I think I'll pop a bottle of bubbly and share it with my wife tonight.

For my next challenge:  Cincom switched Store to use Glorp instead of the older direct mechanism.  GemKit has tools which are coded for the old mechanism and need to be modified to work with Glorp.

Sunday, December 11, 2011

Space Wars game update

I did some more work on the game I described in my last post.  New features:
  • Multiple enemy ships
  • Ships disappear when hit
  • Sound effects on fire
  • Planets in the background
  • Display of number of ships left
  • When all ships are destroyed, a new round starts with 10 more ships
The video below is a low-resolution version.  Part of the game has been edited out for brevity.  To see a better version, go to the one on the Simberon web site.

Friday, December 9, 2011

Space Wars game in Smalltalk

My 11 year old son recently asked me to teach him how to program so he can write his own games.  Unfortunately, the kind of game he has in mind is a first-person shooter which isn't exactly the easiest way to teach an 11 year old how to program.

We talked about different kinds of games we could write.  He had no interest at all in text games like "20 questions" or "guess a number", so I told him about a game I wrote on my old 1802 computer back in the early 1980's.  It was based on the Battlestar Galactica TV series that I was watching at the time.  You would fly around a star field shooting at Cylon ships.  Tyler thought that sounded fun so we started writing it in Smalltalk.

The video below shows our progress so far.  I actually wrote most of it and I'm slowly explaining to him how it works.  It's piqued his curiosity, however.  So far, you can fly around and shoot at ships.  The ships don't explode yet, but it still shows some good progress.

Sunday, November 27, 2011

GemKit for VisualWorks 7.8 Preview

I have a GemKit for VisualWorks 7.8 preview available at the following URL:

    http://simberon.com/downloads/GemKit-VW78-Preview.zip

Follow the instructions in the readme.txt to load it.  Please report any issues to david@simberon.com.

Sunday, October 30, 2011

Subtleties of Atomic Loading

Most of the time, atomic loading works like a charm.  Every once in a while, though, it gives you very confusing results.

I ran into one of these with the GemKit upgrade to VisualWorks 7.8.  I'd already determined that the package defined a compiler along with a class that used that compiler in one package.  That's a no-no.  I was getting into infinite loops that way.  I split the methods compiled by the new compiler into another package and that seemed to fix the problem.

The key phrase there is "seemed to".  I started finding that I was getting Message Not Understood errors by things that were supposed to be references to classes but were references to namespaces instead.  For example, code that read Core.Array was being compiled as if it was just Core.  I looked at how it was being compiled and it turned out that it was using the new compiler defined in the previous package.  The problem was that it wasn't supposed to use that compiler.  It was supposed to use the standard Smalltalk compiler.

As it turns out, there's code in the compilerClass method of the class that enables the special compiler on subclasses of this class, not on this class itself.  The code looked like this:

GBC.GbcHierarchyRoot class method:

compilerClass
 ^self  == GBC.GbcHierarchyRoot
  ifTrue: [super compilerClass]
  ifFalse: [GBC.GbcCompiler]

So, if the method being compiled is in GbcHierarchyRoot itself use the default compiler, otherwise, use the GbcCompiler for the subclass methods.

The problem here is that when you're doing atomic loading, at the time that this method is run, the class is in a different namespace than GBC.GbcHierarchyRoot. As such, the test was failing and using the GbcCompiler even for the methods in GbcHierarchyRoot itself.

The solution to this problem was to change the method as follows:
compilerClass

 ^name = #GbcHierarchyRoot
  ifTrue: [super compilerClass]
  ifFalse: [GBC.GbcCompiler]

Now the test works properly and it uses the default compiler class for GbcHierarchyRoot methods.  There were several methods that used this pattern, so I changed them all.

I'm making some progress but it's slow and complicated working out the interactions between atomic loading and the GemKit code. My goal is to keep the atomic analysis loader turned on all the time and still be able to load GemStone code from Store.  So far, I seem to be able to at least load the GemKit code.  The next step is to load actual GemStone code from Store.