Persisting IdentityDictionary

Elliot Finley efinley.lists at gmail.com
Tue Apr 26 22:03:10 UTC 2011


On Tue, Apr 26, 2011 at 9:12 AM, Chris Muller <ma.chris.m at gmail.com> wrote:
>> Aida/Web uses a huge IdentityDictionary to keep a stable obj -> url
>> relationship and a huge Dictionary to keep a stable url -> obj
>> relationship.  This is how it accomplishes one of it's nicest features
>> - simple obj to obj refs in code translate to urls in the webpage.
>>
>> so when I say:
>>
>> e addLinkTo: address text: address lastName.
>>
>> it checks the IdentityDictionary to see what URL was used for
>> 'address' last time, and it uses it again.  If this is the first time,
>> then it creates the entries in the dictionaries.  There are also some
>> checks to make sure duplicate URLs aren't used, etc... but that's the
>> jest of it.
>
> Ok.  I still don't understand why an IdentityDictionary would be used
> in this case; maybe Janko knows.  1) What if the user supplied a new,
> equivalent-but-not-identical address?  Objects that don't override #=
> will be found by identity anyway in a standard Dictionary, and objects
> that do override #= WANT to be found by equivalence, not identity.

If you read 5, 5.1 and 5.2 in the Aida Tutorial, this becomes clear.
The link is http://www.aidaweb.si/tutorial.html#h-10 and it's less
than a single page of reading.  Basically if Aida generates a URL like
/object/o4899057.html for a specific object, then forever after if the
user enters that URL, then we want THAT SPECIFIC object to be
accessed.  I don't see any way to do it other than identity.

> So, I'm still confused as to the "why" Aida uses an IdentityDictionary
> in this case but nevertheless, I see no reason Magma can't or
> shouldn't support it.
>
>> If I were to subclass MagmaPreallocatedDictionary and change:
>>
>> MagmaPreallocatedDictionary>>keyHash: key
>>     ^ (key hash \\ maxBuckets) + 1
>>
>> to this:
>>
>> MagmaPreallocatedDictionary>>keyHash: key
>>     ^ (key aSelectorThatAnswersMagmaOID \\ maxBuckets) + 1
>
> aSelectorThatAnswersMagmaOID is already implemented, it's called
> #magmaOid, implemented on Object.
>
> But that won't work, because when you have new, uncommitted objects
> that you attach to the persistent model (before commit), they will not
> have a magmaOid yet (it would be nil).
>
> The way to do it would be to do the same thing that the standard
> IdentityDictionary overrides Dictionary:  Override
> MagmaPreallocatedDictionary>>#at: key ifAbsent: aBlock with:
>
> 1       | bucket |
> 2       bucket := self bucketAt: (self keyHash: key).
> 3       [bucket notNil] whileTrue: [ bucket key == key ifTrue: [^ bucket
> value]. bucket := bucket next ].
> 4       ^ aBlock value
>
> Note the change on line 3, to an identity compare.

This is in addition to overriding
MagmaPreallocatedDictionary>>keyHash: key - right?  From the Magma
documentation:

-=-=-
It is absolutely _essential_ that you do not allow any identityHash to
be part of your hash-calculation. Otherwise, it won't work;
identityHash'es differ between image sessions.
-=-=-

This is why I was asking about using the MagmaOID.  I think that is
the only thing that stays stable between image sessions and across
different images.  Thus it would seem to be the only thing you could
base an IdentityDictionary on.

You're using 'self keyHash: key' to find a specific bucket that should
contain that object.  But 'self keyHash: key' may (and probably will)
answer a different number for the same object each time it is
materialized from the database unless it is somehow using the MagmaOID
in place of the identityHash.

Thanks,
Elliot

P.S.  I appreciate your time on this.  Hopefully I can become familiar
enough with Magma that I'll be able to answer some questions on the
list rather than just ask them.


More information about the Magma mailing list