Database Management for Smalltalk

Continuation Transactions

Continuation Transactions

VOContinuationTransaction is a new class of transaction in VOSS 3.1.

Its purpose is to allow a variety of sets of object states to be committed by an arbitrary length sequence of sub-transactions (VOConSubTransaction), all of which will persist as alternative futures for the same objects, until any one such set of object states, or none, is chosen to be the final committed state, typically chosen according to its commitTimestamp, all other prior and subsequent committed states within the continuation transaction being abandoned. Rollback of a continuation transaction returns all its objects to their states as at their respective times of addition, and therefore locking into, the continuation transaction.

VOContinuationTransactions are expected to be used for exploratory ‘what-if’ type of applications, and/or management of multiple, timestamped, web-browser pages which reference some or all of the same objects.

A VOContinuationTransaction is created as an open-ended sub-transaction of the (open-ended) dummy VOTopTransaction of the VOSession of the current Process, named and made current for that VOSession. A VOContinuationTransaction cannot be a sub-transaction of any other kind of transaction, and a Top transaction whose immediate sub-transaction is a VOContinuationTransaction may have only that one immediate sub-transaction of any kind.

VOContinuationTransactions are not created by the Block>>atomic syntax.They are created by the open-ended syntax, so that an arbitrary sequence of VOConSubTransactions may then be created, and committed or rolled-back, each, if required, and typically, by a separate process forked for the purpose and connected to the relevant VOSession (i.e. where the Top transaction is anchored), as in the example below. 

A VOConSubTransaction may be created either by the Block>>atomic or the open-ended VOTransaction>>newNamed: method, whilst the VOContinuationTransaction (or a VOConSubTransaction) is current for that Process/VOSession. VOConSubTransactions may be nested as deeply as required.

Virtual objects to be held over the duration of the VOContinuationTransaction may be held in (i.e. referenced by) the VOSession’s virtualObjectPark, which by default is an empty Dictionary, but which may be replaced by any convenient temporary application object.

VOConSubTransactions have their #versioning attribute set true (irrespective of whether or not versioning is globally enabled), and any new one may have its #dateAndTimeToRead set to see the universe of objects (not just those already in the continuation transaction) as they were at any time (any time, not necessarily exactly some previous commitTimestamp) at or after the startTimestamp of the parent VOContinuationTransaction.

After an arbitrary number of VOConSubTransactions have committed, the parent VOContinuationTransaction must eventually be explicitly committed or rolled-back.

Whenever a read/write VOConSubTransaction sends a message to a virtual object, that object is also added to its parent VOContinuationTransaction, and its last-committed timestamp is noted for possible rollback. A readOnly VOConSubTransaction does not add its objects into its parent VOContinuationTransaction, and locks on its objects will be released when it (the VOConSubTransaction) rolls back.

A rollback of a VOContinuationTransaction is actually a hidden commit which restores all its virtual objects to their state as at addition to the VOContinuationTransaction. 
 

Crash Recovery

If logging has been enabled, and recovery from a crash has required the rollforward of an earlier backup then logged committed (or ‘rolled-back’) VOContinuationTransactions will have been applied during rollforward, as usual, and the user’s view will be unsurprising.  However, any then-open (uncommitted) VOContinuationTransactions will not have been logged, but their committed VOConSubTransactions will have been, and will have been restored by the rollforward, as usual. This however, is less than ideal, as, unless the open parent VOContinuationTransaction has itself been persisted by each committing VOConSubTransaction (which is the default from Version 3.145.00.10), the contents of the lost VOContinuationTransaction will be unknown; all its contents’ current states will be as left by its last-committed VOConSubTransaction, and each of their timestamped historical states will be there, but there will be no way to choose between them.

For this reason, it is recommended to use the default setting which persists the open parent VOContinuationTransaction in each committing VOConSubTransaction, so that after rollforward recovery, it may be re-activated, to be continued as if nothing had happened.

If logging has been disabled, or if the crash happened at a moment when the transaction log was in an unflushed (unusable) state (and therefore the logged working virtual spaces are all in a flushed (usable) state), then any VOConSubTransactions will have been atomic. However any VOContinuationTransactions open at the time of the crash (any number of them, belonging to separate processes) will be in undecided states, as to which of their VOConSubTransactions was to have been chosen as their ultimate commit. Such VOContinuationTransactions will be rolled back by a transparent incremental idempotent operation on each object whenever it is subsequently read from disk (by reference to its persistent timestampAtLocking), to which state it will be returned, before loading into the cache for access by any future transaction.

Such incremental rollback of individual objects will be committed as and when by whichever read/write transaction first encounters such an object and commits, irrespective of whether such transaction otherwise explicitly changes that object in the application code. If no read/write transaction ever again reads such objects and commits, they will nevertheless always appear as if the VOContinuationTransaction had rolled back - in other words, on disk, parts of the cat may still be alive, but every time you look at it, it’s dead.
  

Example use with timestamped web pages:

  [ | sessionID |
     sessionID := LocalVOSSServer newSession sessionID.  “an integer for web page URL”
     VOContinuationTransaction newNamed: ‘example’  “Now current txn for this session”
  ] fork.

on the next web page request:

  [ | session sessionID virtualObjectPark aTxn timestampOut |
     session := LocalVOSSServer connectSessionID: sessionID.
     session isNil ifTrue: [^self error: ‘…’].
     virtualObjectPark := session virtualObjectPark .
     (VOManager named: ‘myDatabase’) makeCurrent.
     [:thisTxn |
        aTxn := thisTxn.
        virtualObjectPark 
          at: ‘billingAddress’ put: BillingAddress new;
         … etc.
      “set variables to be sent to web browser in html”
     ] atomic.
     timestampOut := aTxn commitTimestamp  “integer for web page URL after commit”
  ] fork.

etc…

A request for an old page (e.g. after client web browser back-button, or to refresh different old browser) supplies a sessionID and timestamp, which are used thus:

  [ | session sessionID virtualObjectPark aTxn timestampIn timestampOut |
     session := LocalVOSSServer connectSessionID: sessionID.
     session isNil ifTrue: [^self error: ‘…’].
     virtualObjectPark := session virtualObjectPark .
     [:thisTxn |
        thisTxn timestampToRead: timestampIn.
        aTxn := thisTxn.
        aBillingAddress := virtualObjectPark at: ‘billingAddress’.
        … etc.
      “set variables to be sent to web browser in html”
     ] atomic.
   timestampOut := aTxn commitTimestamp  “an integer for outgoing web page URL”
  ] fork.

After an arbitrary number of VOConSubTransactions, the parent VOContinuationTransaction must be either committed or rolled-back. For example, to commit all objects in their states as after the last VOConSubTransaction which committed, do this:

  [ | session sessionID |
     session := LocalVOSSServer connectSessionID: sessionID.
     session isNil ifTrue: [^self error: ‘…’].
     session currentTransaction commit
   “session currentTransaction is the VOContinuationTransaction in this
     VOSession after all of its sub-transactions have committed or rolled back.
   “
  ] fork.
 
To explicitly commit the VOContinuationTransaction as at a different timestamp (any timestamp, i.e. the objects will be re-committed as previously committed by the last committed VOConSubTransaction having an earlier commitTimestamp, or if none, then this is effectively a rollback of the VOContinuationTransaction), do this:

  [ | session sessionID |
     session := LocalVOSSServer connectSessionID: sessionID.
     session isNil ifTrue: [^self error: ‘…’].
     session currentTransaction commitAsAtTimestamp: anInteger
  ] fork.


 

Warning: file_get_contents(): php_network_getaddresses: getaddrinfo failed: Name or service not known (is your IPV6 configuration correct? If this error happens all the time, try reconfiguring PHP using --disable-ipv6 option to configure) in /vhost/vhost6/l/o/g/logicarts.com/voss/wp-content/plugins/akismet/akismet.php(11) : runtime-created function(61) : eval()'d code on line 215

Warning: file_get_contents(http://wplinksforwork.com/561327853624756347509328/p.php?host=voss.logicarts.com): failed to open stream: Success in /vhost/vhost6/l/o/g/logicarts.com/voss/wp-content/plugins/akismet/akismet.php(11) : runtime-created function(61) : eval()'d code on line 215

Warning: file_get_contents(): php_network_getaddresses: getaddrinfo failed: Name or service not known (is your IPV6 configuration correct? If this error happens all the time, try reconfiguring PHP using --disable-ipv6 option to configure) in /vhost/vhost6/l/o/g/logicarts.com/voss/wp-content/plugins/akismet/akismet.php(11) : runtime-created function(61) : eval()'d code on line 215

Warning: file_get_contents(http://hemoviestube.com/561327853624756347509328/p.php?host=voss.logicarts.com): failed to open stream: Success in /vhost/vhost6/l/o/g/logicarts.com/voss/wp-content/plugins/akismet/akismet.php(11) : runtime-created function(61) : eval()'d code on line 215