[GemStone-Smalltalk] Transcient instance variable
Norm Green via GemStone-Smalltalk
gemstone-smalltalk at lists.gemtalksystems.com
Tue Nov 11 08:30:18 PST 2014
Just FYI, GemStone/64 v3 does support nested transactions. See methods
in class System. For example:
classmethod: System
beginNestedTransaction
"Enter a new nested transaction.
If session is outside of a transaction, equivalent to beginTransaction.
Signals a ImproperOperation exception if the begin would exceed16
levels of nested transactions."
Norm
On 11/11/2014 8:16 AM, Paul Baumann via GemStone-Smalltalk wrote:
>
> Bob,
>
> I'm familiar with that approach. When you have an object-oriented
> window style where you can open many editors on many objects at once
> then it is easy to lament the absence of nested transactions.
> Validation rules tend to be hard part; you want your object model to
> participate in validation but the window needs to make the changes to
> the domain for the domain to validate. Sometimes validation needs to
> happen in both GS and VW. If you have more than simple data structures
> (like a good object model) then validations are difficult. What you
> end up doing is creating a framework that simulates nested
> transactions. A different approach is to use a single managed window
> (like a notebook) through which all changes are made in a way that
> fits the traditional GS transaction model.
>
> The nested transaction functionality that I'd used (like 10 years ago)
> would feed changes to the change manager of the active window. The
> changes are applied to domain objects immediately for their
> validation. A save of changes can be an abort, replay of changes, and
> then commit. Each window is aware of its own pending changes and
> replays changes as necessary for transaction changes. There are
> probably many important details that I'm forgetting to describe, but
> this approach was able to work. It sounds like your approach tries let
> the window see changes on the domain objects that aren't quite there
> yet. You are creating a generic form of an action model that
> represents a future change. Like you said, large collections can be a
> problem because it is the actions made to the collections that you
> want to play and the generic means of capturing relies on observing
> differences. I recall collections being a tricky part with the
> approach that I'd used too. I suspect that collection changes were
> made with the help of the change manager so that the change manager
> could know the actions that caused the collection changes.
>
> Another way to simulate nested transactions is to use multiple gems. I
> haven't tried that approach. If you use any (cached) forwarders then
> GBS would throw errors. There was always too much risk of GBS bugs or
> cache use restrictions. The well-travelled path is easier to follow;
> unfortunately that means a window design that never has more than one
> ongoing set of changes to manage. Consider a window change coordinator
> that ensures that changes are either saved or aborted before you are
> able to start making changes in a different window.
>
> Regards,
>
> Paul Baumann
>
> *From:*GemStone-Smalltalk
> [mailto:gemstone-smalltalk-bounces at lists.gemtalksystems.com] *On
> Behalf Of *via GemStone-Smalltalk
> *Sent:* Tuesday, November 11, 2014 09:29
> *To:* gemstone-smalltalk at lists.gemtalksystems.com
> *Subject:* Re: [GemStone-Smalltalk] Transcient instance variable
>
> Paul,
>
> Interesting idea: we do need the stored values since we do have domain
> code that compares updated vs. original.
>
> I do have some concerns. Aside from having to deal with unintended
> commits (as you mentioned), we would also add some complexity to our
> development environment.
>
> Right now we're able use VW with an 'in-memory' domain model. Great
> for debugging and SUnit tests. The same domain code runs in the dev
> VW image as in GS (the deployed web server image has no domain code).
> If we update the domain instance in VW we'd have to unwind it in a
> pseudo-abort.
>
> Storing the updates in a data wrapper is working well for us, since
> the final 'save' is an explicit domain update. We can do a lot of
> pre-save model validation. Each GS call is a RESTful call that
> rebuilds the data wrapper model, makes updates, and sends the result.
> All of which is done with no updates to domain objects until a 'save'
> is done. Each call is wrapped in a 'current context' that holds all
> the data wrappers, keyed so that we can find a corresponding wrapper
> for a domain object.
>
> Most 'read' calls are now under 50ms. Read + pending updates are
> 100ms to 200ms, as are the saves. The problem is that some behaviours
> reference large collections. In the past we wrapped every referenced
> domain object if there were /any /pending updates. Now we only wrap
> those with known pending updates. This introduced a heterogeneous
> model with wrapped and unwrapped instances.
>
> Not a problem, but the code would be simpler if there were only domain
> objects in mix (assuming the impact on performance was minimal).
> That's the change I'm looking at. Right now I'm leaning towards a
> 'dataWrapper' instVar on the domain root class that we would clear
> prior to a commit. Having a notNil instVar during a read would be an
> error condition.
>
> Bob
>
> On Monday, November 10, 2014 6:01 PM, Paul Baumann via
> GemStone-Smalltalk <gemstone-smalltalk at lists.gemtalksystems.com
> <mailto:gemstone-smalltalk at lists.gemtalksystems.com>> wrote:
>
> Hi Bob,
>
> It seems like you are currently thinking of using the dataWrapper to
> note the new change. Consider if it will suit your needs better to use
> your dataWrapper to note the values before the first inst var change
> (like with a shallow copy), and allow the change to be made to the
> inst vars. The shallowCopy can be registered in some manager and the
> dataWrapper inst var of the copy can refer to the original object.
>
> assignDataWrapper
>
> dataWrapper isNil ifTrue: [
>
> dataWrapper := self copy.
>
> copy dataWrapper: self.
>
> (SessionTemps current at: #ChangeManager ifAbsentPut: [Array new])
>
> add: dataWrapper.
>
> ].
>
> ^dataWrapper
>
> foo: newValue
>
> self assignDataWrapper.
>
> foo := newValue
>
> foo
>
> ^foo
>
> This approach performs better because changes to objects are less
> frequent than access to variables. The cost of making a change is the
> creation of a copy and adding it to some managed collection. The code
> needs to make consistent use of the custom setter methods, or else
> you'd try to hook some generic object dirtying code.
>
> The ChangeManager can be defined however you want changes to survive.
> You can detect changes both at the object level and by the manager.
> You'd probably either do transaction changes through your
> ChangeManager or notify the manager afterwards (note that
> #continueTransaction has a notification bug). If your dataWrapper/copy
> is a committed object then you'd know that an unmanaged commit
> happened (the inst vars may now also contain changes from another
> session). If ChangeManager has copies that differ from what the
> originals noted for your session then you might have had an unmanaged
> begin/abort/continue transaction.
>
> Regards,
>
> Paul Baumann
>
> *From:*GemStone-Smalltalk
> [mailto:gemstone-smalltalk-bounces at lists.gemtalksystems.com] *On
> Behalf Of *via GemStone-Smalltalk
> *Sent:* Monday, November 10, 2014 16:52
> *To:* gemstone-smalltalk at lists.gemtalksystems.com
> <mailto:gemstone-smalltalk at lists.gemtalksystems.com>
> *Subject:* Re: [GemStone-Smalltalk] Transcient instance variable
>
> Paul,
>
> Thanks for the note on 'System rcValueCache'. I can see use using it
> for other cases.
>
> For the 'data wrapper' code change I'm considering performance is
> key. The check for updated values would be done on each in 'get'
> method, so anything that slows that down would be noticeable.
>
> I was thinking of code like... (we're still brainstorming this)
>
> foo
>
> ^self getUpdatedValueAt: #foo with: foo
>
> getUpdatedValueAt: aKey with: aValue
>
> self dataWrapper isNil ifTrue: [^aValue].
>
> ^self dataWrapper getUpdatedValueAt: aKey with: aValue "where aValue
> is answered if there are no updates for2 #foo"
>
> ...we may just do this and take responsibility for clearing the data
> wrapper instVar just prior to a commit.
>
> Bob
>
> On Monday, November 10, 2014 12:55 PM, Paul Baumann via
> GemStone-Smalltalk <gemstone-smalltalk at lists.gemtalksystems.com
> <mailto:gemstone-smalltalk at lists.gemtalksystems.com>> wrote:
>
> Re-send to list...
>
> *From:*Paul Baumann
> *Sent:* Monday, November 10, 2014 10:47
> ...
> *Subject:* RE: [GemStone-Smalltalk] Transcient instance variable
>
> Hi Bob,
>
> "System rcValueCache" is flushed with a view/transaction change
> (commitTransaction, abortTransaction, beginTransaction,
> continueTransaction). Here is an example that shows view-transient
> behavior:
>
> | anObject get0 get1 |
>
> System beginTransaction.
>
> anObject := Object new.
>
> System rcValueCacheAt: #plbTest put: #remembered for: anObject.
>
> get0 := System rcValueCacheAt: #plbTest for: anObject otherwise: nil.
>
> System commitTransaction.
>
> get1 := System rcValueCacheAt: #plbTest for: anObject otherwise: nil.
>
> Array with: get0 with: get1
>
> anArray( #'remembered', nil)
>
> Your domain object can use itself to retrieve by-reference attributes.
> A view-transient attribute would be like this:
>
> viewTransient_plbTest
>
> ^System rcValueCacheAt: #plbTest for: self otherwise: nil
>
> viewTransient_plbTest: anObject
>
> System rcValueCacheAt: #plbTest put: anObject for: self
>
> A session-transient attribute would be like this:
>
> sessionTransient_plbTest
>
> |dict |
>
> ^(dict := SessionTemps current at: #plbTest otherwise:
> nil) notNil
>
> ifTrue: [dict at: self otherwise: nil].
>
> sessionTransient_plbTest: anObject
>
> (SessionTemps current at: #plbTest ifAbsentPut:
> [IdentityDictionary new])
>
> at: self put: anObject.
>
> A wrapper object held in an object attribute can be used for better
> performance when needed. Your domain object would have an attribute
> that holds information that can find cached data quicker. If the
> attribute is nil then the no lookup is necessary (saving a search). If
> the attribute is not nil then it can be something like a reserved
> index position within a known location (not strongly referenced) that
> would contain the data. Years ago I had prototyped a cache framework
> that was able to use a special wrapper for weak references to related
> objects. It can be done--if you really need that level of performance.
>
> Paul Baumann
>
> *From:*GemStone-Smalltalk
> [mailto:gemstone-smalltalk-bounces at lists.gemtalksystems.com] *On
> Behalf Of *via GemStone-Smalltalk
> *Sent:* Monday, November 10, 2014 08:25
> *To:* gemstone-smalltalk at lists.gemtalksystems.com
> <mailto:gemstone-smalltalk at lists.gemtalksystems.com>
> *Subject:* [GemStone-Smalltalk] Transcient instance variable
>
> I'm considering some refactoring that would benefit from having access
> to transcient instance variables.
>
> Something like SessionTemps, but stored on an instance variable and
> cleared on each abort or commit.
>
> It would be used to store pending updates. We do that now with a
> wrapper object, which works fine,
>
> but the code would be cleaner if the domain object wrapped the pending
> updates instead.
>
> Anything like that available?
>
> Thanks for any suggestions,
>
> Bob Nemec
>
> HTS
>
> ------------------------------------------------------------------------
>
> This message may contain confidential information and is intended for
> specific recipients unless explicitly noted otherwise. If you have
> reason to believe you are not an intended recipient of this message,
> please delete it and notify the sender. This message may not represent
> the opinion of Intercontinental Exchange, Inc. (ICE), its subsidiaries
> or affiliates, and does not constitute a contract or guarantee.
> Unencrypted electronic mail is not secure and the recipient of this
> message is expected to provide safeguards from viruses and pursue
> alternate means of communication where privacy or a binding message is
> desired.
>
>
> _______________________________________________
> GemStone-Smalltalk mailing list
> GemStone-Smalltalk at lists.gemtalksystems.com
> <mailto:GemStone-Smalltalk at lists.gemtalksystems.com>
> http://lists.gemtalksystems.com/mailman/listinfo/gemstone-smalltalk
>
> ------------------------------------------------------------------------
>
> This message may contain confidential information and is intended for
> specific recipients unless explicitly noted otherwise. If you have
> reason to believe you are not an intended recipient of this message,
> please delete it and notify the sender. This message may not represent
> the opinion of Intercontinental Exchange, Inc. (ICE), its subsidiaries
> or affiliates, and does not constitute a contract or guarantee.
> Unencrypted electronic mail is not secure and the recipient of this
> message is expected to provide safeguards from viruses and pursue
> alternate means of communication where privacy or a binding message is
> desired.
>
> _______________________________________________
> GemStone-Smalltalk mailing list
> GemStone-Smalltalk at lists.gemtalksystems.com
> <mailto:GemStone-Smalltalk at lists.gemtalksystems.com>
> http://lists.gemtalksystems.com/mailman/listinfo/gemstone-smalltalk
>
>
> ------------------------------------------------------------------------
> This message may contain confidential information and is intended for
> specific recipients unless explicitly noted otherwise. If you have
> reason to believe you are not an intended recipient of this message,
> please delete it and notify the sender. This message may not represent
> the opinion of Intercontinental Exchange, Inc. (ICE), its subsidiaries
> or affiliates, and does not constitute a contract or guarantee.
> Unencrypted electronic mail is not secure and the recipient of this
> message is expected to provide safeguards from viruses and pursue
> alternate means of communication where privacy or a binding message is
> desired.
>
>
> _______________________________________________
> GemStone-Smalltalk mailing list
> GemStone-Smalltalk at lists.gemtalksystems.com
> http://lists.gemtalksystems.com/mailman/listinfo/gemstone-smalltalk
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.gemtalksystems.com/mailman/private/gemstone-smalltalk/attachments/20141111/94c5bf1a/attachment-0001.html>
More information about the GemStone-Smalltalk
mailing list