// ---------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------
//
//
// ---------------------------------------------------------------------
namespace Microsoft.Database.Isam
{
using System;
///
/// A IsamTransaction object represents a single save point of a transaction
/// that is begun on a Session object. This object is not required to
/// begin, commit, or abort a transaction as this can be done directly
/// on the Session object. However, this object is very useful for making
/// convenient code constructs involving transactions with the "using"
/// keyword in C# like this:
///
/// using( IsamTransaction t = new IsamTransaction( session ) )
/// {
/// /* do some work */
///
/// /* save the work */
/// t.Commit();
/// }
///
///
public class IsamTransaction : IDisposable
{
///
/// The session
///
private readonly IsamSession isamSession;
///
/// The transaction level
///
private readonly long transactionLevel;
///
/// The transaction level identifier
///
private readonly long transactionLevelID;
///
/// The cleanup
///
private bool cleanup = false;
///
/// The disposed
///
private bool disposed = false;
///
/// Initializes a new instance of the class.
/// Begin a transaction on the given session.
///
///
/// The session we will use for the transaction.
///
///
/// If this transaction is not committed before this object is disposed
/// then the transaction will automatically be aborted.
///
public IsamTransaction(IsamSession isamSession)
{
lock (isamSession)
{
this.isamSession = isamSession;
this.isamSession.BeginTransaction();
this.transactionLevel = isamSession.TransactionLevel;
this.transactionLevelID = isamSession.TransactionLevelID(isamSession.TransactionLevel);
this.cleanup = true;
}
}
///
/// Initializes a new instance of the class.
/// Joins the current transaction on the given session. If the session
/// is not currently in a transaction then a new transaction will be
/// begun.
///
///
/// The session we will use for the transaction.
///
///
/// If true, the current transaction on the session will be joined. If false or if there is no current transaction then a new transaction will be begun.
///
///
/// If an existing transaction is joined, then committing or aborting
/// this transaction will have no effect on the joined transaction. If
/// a new transaction was begun then these actions will work normally.
///
/// If this transaction is not committed before this object is disposed
/// then the transaction will automatically be aborted.
///
///
public IsamTransaction(IsamSession isamSession, bool join)
{
lock (isamSession)
{
this.isamSession = isamSession;
if (!join || isamSession.TransactionLevel == 0)
{
this.isamSession.BeginTransaction();
this.transactionLevel = isamSession.TransactionLevel;
this.transactionLevelID = isamSession.TransactionLevelID(isamSession.TransactionLevel);
this.cleanup = true;
}
}
}
///
/// Finalizes an instance of the IsamTransaction class
///
~IsamTransaction()
{
this.Dispose(false);
}
///
/// Gets the save point (level) for this transaction.
///
public long TransactionLevel
{
get
{
this.CheckDisposed();
return this.transactionLevel;
}
}
///
/// Gets or sets a value indicating whether [disposed].
///
///
/// true if [disposed]; otherwise, false.
///
internal bool Disposed
{
get
{
return this.disposed || this.isamSession.Disposed || (this.cleanup && this.isamSession.TransactionLevelID(this.transactionLevel) != this.transactionLevelID);
}
set
{
this.disposed = value;
}
}
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///
public void Dispose()
{
lock (this)
{
this.Dispose(true);
}
GC.SuppressFinalize(this);
}
///
/// Commits the save point (level) represented by this transaction on
/// this session. All changes made to the database for this save point
/// (level) will be kept.
///
///
/// Changes made to the database will become permanent if and only if
/// those changes are committed to save point (level) zero.
///
/// A commit to save point (level) zero is guaranteed to be persisted
/// to the database upon completion of this method.
///
///
/// The transaction object will be disposed as a side effect of this
/// call.
///
///
public void Commit()
{
this.Commit(true);
}
///
/// Commits the save point (level) represented by this transaction on
/// this session. All changes made to the database for this save point
/// (level) will be kept.
///
/// When true, a commit to save point (level) zero is guaranteed to be persisted to the database upon completion of this method.
///
/// Changes made to the database will become permanent if and only if
/// those changes are committed to save point (level) zero.
///
/// A commit to save point (level) zero is guaranteed to be persisted
/// to the database upon completion of this method only if
/// durableCommit is true. If durableCommit is false then the changes
/// will only be persisted to the database if their transaction log
/// entries happen to be written to disk before a crash or if the
/// database is shut down cleanly.
///
///
/// The transaction object will be disposed as a side effect of this
/// call.
///
///
public void Commit(bool durableCommit)
{
lock (this.isamSession)
{
this.CheckDisposed();
if (this.cleanup)
{
this.isamSession.CommitTransaction(durableCommit);
this.cleanup = false;
}
this.Dispose();
}
}
///
/// Aborts the save point (level) represented by this transaction on
/// this session. All changes made to the database for this save point
/// (level) will be discarded.
///
///
/// The transaction object will be disposed as a side effect of this
/// call.
///
public void Rollback()
{
lock (this.isamSession)
{
this.CheckDisposed();
this.Dispose();
}
}
///
/// Aborts the save point (level) represented by this transaction on
/// this session. All changes made to the database for this save point
/// (level) will be discarded.
///
///
/// The transaction object will be disposed as a side effect of this
/// call.
///
/// IsamTransaction.Abort is an alias for .
///
///
public void Abort()
{
this.Rollback();
}
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///
void IDisposable.Dispose()
{
this.Dispose();
}
///
/// Checks whether this object is disposed.
///
/// If the object has already been disposed.
internal void CheckDisposed()
{
if (this.Disposed)
{
throw new ObjectDisposedException(this.GetType().Name);
}
}
///
/// Releases unmanaged and - optionally - managed resources.
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected virtual void Dispose(bool disposing)
{
lock (this.isamSession)
{
if (!this.Disposed)
{
if (this.cleanup)
{
this.isamSession.RollbackTransaction();
this.cleanup = false;
}
this.Disposed = true;
}
}
}
}
}