Magma-Pier documentation
--------------------------------------------- Magma provides a virtually transparent persistency mechanism, in which the application, in this case Pier, need hardly be aware of the fact that not all of the objects which it uses are kept in memory all of the time. As far as Pier is concerned Magma will stub out objects in memory, and load them in, a process termed reifying, or reification, as needed, entirely transparently. Pier provides very controlled access to its model, including awareness of persistency issues, so it makes sense to make use of this in the Pier-Magma integration. However, Pier will have to curb its tendency to traverse its entire model for some of its operations (e.g. page removal) in order to play sensibly and scalably in a Pier-Magma installation. The Database Structure =============== The root of the Magma database is an instance of PRMagmaRepository. This is a minimal root object designed with the intention of being able to merge with root objects from other projects. For example GJallar will have a root object of its own. To adopt or merge with Pier's requirements, all that is needed is for their root object to have an accessor #pier, onto a standard Dictionary. PRMagmaRepository is a subclass of PRObject, and so has properties by default, if you can think of a reason or need to use them they are there but they are not currently used. When running Seaside-Magma-Pier, the aforementioned Dictionary in the root of the database is directly available from the Seaside session via the convenience method #pierPersistencies. (in the latest version, previously it was just #pier) "session pierPersistencies", yields a dictionary of, PRMagmaPersistency instances, keyed by PRKernel name, so to obtain the PRKernel instance of your choice: (session pierPersistencies at: 'MyPier') kernel This does the job fairly logically. ReadStrategies in Magma-Seaside ===================== The root object of the repository also provides the Magma read strategy for the repository via #buildReadStrategyOn: . A ReadStrategy tells Magma how many objects to load in simultaneously. For example, in Pier we tell Magma to reify all of the objects in a PRDocument structure in one database access/hit, since we will need them all to display or process the page. For more details about the Pier read strategy see below. This functionality, whereby the root object supplies the database read-strategy, is provided in WAReadStrategyDefault as a standard way of providing a read strategy for seaside applications in the package Magma-Seaside. There is an alternative WAMagmaReadStrategyWithLogging which provides some logging features, and this can be selected in the application configuration by over-riding the 'read strategy' setting. Logging is invaluable in fine-tuning Magma read strategies. Magma and Seaside Sessions ================== Since Pier manages its own model locking, it is perfectly ok to share a single Magma session between all seaside sessions. This functionality is provided by WAMagmaSharedSession. Other Seaside applications (Gjallar again!) have more complex arrangements using session-pools, but the basic WAMagmaSharedSession provided in the Magma-Seaside package is fine for Pier. When running using WAMagmaSharedSession a single Magma session is opened for each application (#obtainMagmaSession), and is available from the seaside session via #magmaSession. The root of the database from the magmaSession obtained via #root. The Pier-Magma package defines the convenience method #pierPersistencies as already mentioned. Pier-Magma Integration =============== The model locking performed by Pier is handled by the persistency scheme, PRPersistency and its subclasses. The default #execute: method is: PRPersistency-i-#execute: aCommand self mutex critical: [ self apply: aCommand ]. The change required to support Magma is minimal: PRMagmaPersistency-i-#execute: aCommand self mutex critical: [ self session commit: [ self apply: aCommand ] ] Thats it! What is In memory vs What is in the DB ========================= When using PRMagmaPersistency, the master list of PRKernel instances, kept in PRKernel-instances, contains a 'stub'. This is an instance of PRKernel, having #persistency as an instance of PRMagmaPersistency (also a stub), but no data, i.e. #root is nil. Whenever Pier wishes to obtain the real object, which is in the database, it calls, #realize on the stub, which calls #realizeKernel on its (stub) PRMagmaPersistency, returning the real PRKernel object, with a non-nil root, from the database. The real PRKernel object, also has a real #persistency, which is what is used to perform commands and logging etc. [The model locking mutex which is used at present is the one in the persisted PRMagmaPersistency, if this causes problems, then it will be possible to use the mutex in the memory resident (stub) PRMagmaPersistency instead]. Behind The Scenes - Saving The Model ======================== Before persisting some objects, Magma calls #maPreserialize. [ I am warned that this approach may be deprecated in the future! -- kph ]. This is used: 1) to remove the mutex from PRPersistency (Disabled at present. The mutex used to be in PRKernel and was lazily initialized, so removing it before persisting was fine, it would just be reinstated when next used. If it becomes necessary to re-enable this, then we will have to see about asking Lukas to lazily initialize the mutex once more) 2) To remove any decorations of PRChildren if they are empty. The current model implementation should not be creating empty PRChildren decorations anyway, but this is just in case. 3) Context's are tidied up before they are persisted. Properties are removed, and commands are copied, and command's answers are copied. This is to support logging. Behind the scenes - loading the model ======================== This is the read strategy that Magma-Pier uses at present: strategy minimumDepth: 0; "forVariableNamed: 'pier' onAny: PRMagmaRepository readToDepth: 2 ;" forVariableNamed: 'kernel' onAny: PRPersistency readToDepth: 1; onAny: PRKernel readToDepth: 1 ; forVariableNamed: 'decorations' onAny: PRDecorated readToDepth: 1; forVariableNamed: 'title' onAny: PRStructure readToDepth: 1; forVariableNamed: 'children' onAny: PRChildren readToDepth: (self readPathSkeletonInOneHit ifTrue: [ 1 ] ifFalse: [ 0 ]); onAny: PRDocumentItem readToDepth: 1; "reads all page items in one hit" onAny: PRComponent readToDepth: 1; yourself. If the flag #readPathSkeletonInOneHit is set, Magma, realizes all of the tree of objects necessary to resolve a url-path, in one database access cycle/hit. Depending upon other settings, this data may remain in memory. Otherwise, resolving a url-path occurs one level at a time. As you would expect the items required to display a page, are loaded in one hit. The ideal situation would be to have a path lookup cache which can perform the path look-up in one hit, and possibly obtain the whole page data in the same hit. This should be relatively straight forward, using an indexed MagmaCollection. Logging ===== The logging implementation used in PRImagePersistency has changed since the Pier-Magma integration was written, and so it follows the previous implementation. It stores a snapshot of the original data-structure, together with a collection of the context/commands that are applied to it. (it probably isnt working as intended at the moment, review required) ====== feedback comments to [hidden email] _______________________________________________ SmallWiki, Magritte, Pier and Related Tools ... https://www.iam.unibe.ch/mailman/listinfo/smallwiki |
This is great, Keith. Can we/you put this on the squeak wiki?
Keith Hodges wrote: > Magma-Pier documentation > --------------------------------------------- > > Magma provides a virtually transparent persistency mechanism, in which > the application, in this case Pier, need hardly be aware of the fact > that not all of the objects which it uses are kept in memory all of the > time. As far as Pier is concerned Magma will stub out objects in memory, > and load them in, a process termed reifying, or reification, as needed, > entirely transparently. > > Pier provides very controlled access to its model, including awareness > of persistency issues, so it makes sense to make use of this in the > Pier-Magma integration. > > However, Pier will have to curb its tendency to traverse its entire > model for some of its operations (e.g. page removal) in order to play > sensibly and scalably in a Pier-Magma installation. > > The Database Structure > =============== > The root of the Magma database is an instance of PRMagmaRepository. This > is a minimal root object designed with the intention of being able to > merge with root objects from other projects. For example GJallar will > have a root object of its own. To adopt or merge with Pier's > requirements, all that is needed is for their root object to have an > accessor #pier, onto a standard Dictionary. > > PRMagmaRepository is a subclass of PRObject, and so has properties by > default, if you can think of a reason or need to use them they are there > but they are not currently used. > > When running Seaside-Magma-Pier, the aforementioned Dictionary in the > root of the database is directly available from the Seaside session via > the convenience method #pierPersistencies. (in the latest version, > previously it was just #pier) > > "session pierPersistencies", yields a dictionary of, PRMagmaPersistency > instances, keyed by PRKernel name, so to obtain the PRKernel instance of > your choice: > > (session pierPersistencies at: 'MyPier') kernel > > This does the job fairly logically. > > ReadStrategies in Magma-Seaside > ===================== > The root object of the repository also provides the Magma read strategy > for the repository via #buildReadStrategyOn: . A ReadStrategy tells > Magma how many objects to load in simultaneously. > > For example, in Pier we tell Magma to reify all of the objects in a > PRDocument structure in one database access/hit, since we will need them > all to display or process the page. For more details about the Pier > read strategy see below. > > This functionality, whereby the root object supplies the database > read-strategy, is provided in WAReadStrategyDefault as a standard way of > providing a read strategy for seaside applications in the package > Magma-Seaside. > > There is an alternative WAMagmaReadStrategyWithLogging which provides > some logging features, and this can be selected in the application > configuration by over-riding the 'read strategy' setting. Logging is > invaluable in fine-tuning Magma read strategies. > > Magma and Seaside Sessions > ================== > Since Pier manages its own model locking, it is perfectly ok to share a > single Magma session between all seaside sessions. This functionality is > provided by WAMagmaSharedSession. > > Other Seaside applications (Gjallar again!) have more complex > arrangements using session-pools, but the basic WAMagmaSharedSession > provided in the Magma-Seaside package is fine for Pier. > > When running using WAMagmaSharedSession a single Magma session is opened > for each application (#obtainMagmaSession), and is available from the > seaside session via #magmaSession. The root of the database from the > magmaSession obtained via #root. > > The Pier-Magma package defines the convenience method #pierPersistencies > as already mentioned. > > Pier-Magma Integration > =============== > > The model locking performed by Pier is handled by the persistency > scheme, PRPersistency and its subclasses. The default #execute: method is: > > PRPersistency-i-#execute: aCommand > self mutex critical: [ self apply: aCommand ]. > > The change required to support Magma is minimal: > > PRMagmaPersistency-i-#execute: aCommand > self mutex critical: [ self session commit: [ self apply: aCommand ] ] > > Thats it! > > What is In memory vs What is in the DB > ========================= > When using PRMagmaPersistency, the master list of PRKernel instances, > kept in PRKernel-instances, contains a 'stub'. This is an instance of > PRKernel, having #persistency as an instance of PRMagmaPersistency (also > a stub), but no data, i.e. #root is nil. > > Whenever Pier wishes to obtain the real object, which is in the > database, it calls, #realize on the stub, which calls #realizeKernel on > its (stub) PRMagmaPersistency, returning the real PRKernel object, with > a non-nil root, from the database. The real PRKernel object, also has a > real #persistency, which is what is used to perform commands and logging > etc. > > [The model locking mutex which is used at present is the one in the > persisted PRMagmaPersistency, if this causes problems, then it will be > possible to use the mutex in the memory resident (stub) > PRMagmaPersistency instead]. > > Behind The Scenes - Saving The Model > ======================== > Before persisting some objects, Magma calls #maPreserialize. > [ I am warned that this approach may be deprecated in the future! -- kph ]. > > This is used: > 1) to remove the mutex from PRPersistency > (Disabled at present. The mutex used to be in PRKernel and was lazily > initialized, so removing it before persisting was fine, it would just be > reinstated when next used. > If it becomes necessary to re-enable this, then we will have to see > about asking Lukas to lazily initialize the mutex once more) > 2) To remove any decorations of PRChildren if they are empty. The > current model implementation should not be creating empty PRChildren > decorations anyway, but this is just in case. > 3) Context's are tidied up before they are persisted. Properties are > removed, and commands are copied, and command's answers are copied. This > is to support logging. > > Behind the scenes - loading the model > ======================== > > This is the read strategy that Magma-Pier uses at present: > > strategy minimumDepth: 0; > "forVariableNamed: 'pier' onAny: PRMagmaRepository readToDepth: 2 ;" > forVariableNamed: 'kernel' onAny: PRPersistency readToDepth: 1; > onAny: PRKernel readToDepth: 1 ; > forVariableNamed: 'decorations' onAny: PRDecorated readToDepth: 1; > forVariableNamed: 'title' onAny: PRStructure readToDepth: 1; > > forVariableNamed: 'children' onAny: PRChildren readToDepth: > (self readPathSkeletonInOneHit ifTrue: [ 1 ] ifFalse: [ 0 ]); > > onAny: PRDocumentItem readToDepth: 1; "reads all page items in > one hit" > > onAny: PRComponent readToDepth: 1; > yourself. > > If the flag #readPathSkeletonInOneHit is set, Magma, realizes all of the > tree of objects necessary to resolve a url-path, in one database access > cycle/hit. Depending upon other settings, this data may remain in > memory. Otherwise, resolving a url-path occurs one level at a time. > > As you would expect the items required to display a page, are loaded in > one hit. > > The ideal situation would be to have a path lookup cache which can > perform the path look-up in one hit, and possibly obtain the whole page > data in the same hit. This should be relatively straight forward, using > an indexed MagmaCollection. > > Logging > ===== > The logging implementation used in PRImagePersistency has changed since > the Pier-Magma integration was written, and so it follows the previous > implementation. > > It stores a snapshot of the original data-structure, together with a > collection of the context/commands that are applied to it. > > (it probably isnt working as intended at the moment, review required) > > ====== > feedback comments to [hidden email] > > > > > > > > > _______________________________________________ > SmallWiki, Magritte, Pier and Related Tools ... > https://www.iam.unibe.ch/mailman/listinfo/smallwiki > > -- brad fuller http://www.Sonaural.com/ +1 (408) 799-6124 _______________________________________________ SmallWiki, Magritte, Pier and Related Tools ... https://www.iam.unibe.ch/mailman/listinfo/smallwiki |
Free forum by Nabble | Edit this page |