Changing objects in Magma #2
Last updated at 2:03 pm UTC on 22 July 2002
Magma utilizes a simple transaction protocol to isolate a batch of object changes that can be saved as a whole or canceled as a whole.
The three important messages of the transaction protocol are:
These messages are sent to a Magma session.
- begin - begin recording object changes.
- commit - save object changes made since the last begin and make them available to others.
- abort - cancel object changes made since the last begin.
Essentials of transactions
When a program executes any of these three messages, it is said to be "crossing a transaction boundary," and is the time when the objects in the local image are sync'ed up with the Magma repository. All individual changes made in your image are saved to the repository (only if you are performing a commit), and will become visible to all other users as soon as they cross their next transaction boundary. Additionally all changes committed by other users immediately become visible to your program.
It may seem evident that, with correct timing of events, one user would be able to overlay changes made by another user. For example, consider the following scenario:
- User 1 begins a transaction.
- User 2 begins a transaction.
- User 1 changes Object A.
- User 1 commits his transaction.
- User 2, cannot yet see User 1's changes, because she has not crossed a transaction boundary since the commit.
- User 2 changes Object A.
- User 2 commits.
Thankfully, Magma will detect this conflict and answer a commit conflict object back to user 2, indicating to her program that her commit attempt failed. This is because user 2 tried to change an object that was changed since she began her transaction, thus invalidating her changes. The failed result object has the challenging objects that were in conflict (Object A) and the name of each user who changed them (User 1). Additionally, User 2 can now see the new Object A, as changed by User 1, because her commit attempt caused a crossing of a transaction boundary.
At this point, User 2 no longer has a transaction. She must reapply her changes under a new transaction, if appropriate.
Minimizing concurrency, the importance of keeping transactions short
If concurrency is defined as the frequency of commit failures, the best way to minimize concurrency is to minimize the size and duration of transactions. Long transactions increase concurrency not only by potentially changing more objects, but by allowing more time for "challengers," objects changed by other users, to accumulate. When many users are all running long transactions, it can compound the concurrency problem and, eventually, place undue burden on the Magma server.
Because of the dynamic nature of Magma, frequent crossing of transaction boundaries is also important even if you aren't committing transactions. For example, it is important to abort frequently (say, every 30 seconds) while you are connected to a Magma server, even if you don't have a transaction. That's because the Magma server keeps track of every object changed by other users, called a "challenger," since you last crossed. As other users continue to commit transactions, their challengers are buffered into a list exclusively for your session. The longer your session waits to refresh, the more challengers will accumulate into this list.
When your session finally does cross (via a begin, commit or abort), the entire list of challengers is faulted down over the network and applied in your local image. It is then emptied on the server, freeing memory, and begins to accept new challengers for each transaction committed by other sessions.
Each sessions list of challengers consumes some memory in the Magma server. Magma will attempt to protect the machine its running on from running out of memory by terminating any session which accumulates too many challengers. The maximum number of challengers to allow is settable when you administrate the repository, and may be customized when connecting an individual sessions.