Ejemplo n.º 1
0
        /// <summary>
        /// Performs undo or redo
        /// </summary>
        /// <param name="storeSnapshot"></param>
        /// <param name="isUndo"></param>
        /// <returns></returns>
        private int Revert(StoreSnapshot storeSnapshot, TransactionType transactionType)
        {
            Debug.Assert(transactionType == TransactionType.Undo || transactionType == TransactionType.Redo);
            int originalVersion     = storeSnapshot.Version;
            int transactionToRevert = 0;

            try {
                transactionToRevert = this.StartTransaction(storeSnapshot, transactionType);
                if (0 < transactionToRevert)
                {
                    foreach (ISnapTable snapTable in this.Tables)
                    {
                        snapTable.Revert(transactionToRevert);
                    }
                    return(this.Commit(withOmit: false));
                }
            } catch {
                if (0 < transactionToRevert && storeSnapshot.IsEditor)
                {
                    this.Rollback();
                }
                throw;
            }
            return(originalVersion);
        }
Ejemplo n.º 2
0
        /// <summary>
        ///Commits current transaction. Optionally if <paramref name="withOmit"/> set to true erases transaction from undo history
        /// </summary>
        /// <param name="withOmit"></param>
        /// <returns></returns>
        public int Commit(bool withOmit)
        {
            this.ValidateModification();
            int v = this.Version;

            RuntimeHelpers.PrepareConstrainedRegions();
            try {} finally {
                if (withOmit)
                {
                    ValueList <TransactionType> .Address address = this.version.ItemAddress(this.version.Count - 1);
                    Debug.Assert(address.Page[address.Index] == TransactionType.Edit, "Only edit transactions can be omitted");
                    address.Page[address.Index] = TransactionType.Omit;
                }
                this.CompletedVersion = v;
                this.editorThread     = null;
                this.editor           = null;
                LockFreeSync.WriteBarrier();
            }
            EventHandler handler = this.Committed;

            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
            return(v);
        }
Ejemplo n.º 3
0
 public ChangeEnumerator(StoreSnapshot store, int oldVersion, int newVersion)
 {
     Debug.Assert(0 < oldVersion && oldVersion <= newVersion && newVersion <= store.SnapStore.CompletedVersion);
     this.enumerator = store.Tables.GetEnumerator();
     this.oldVersion = oldVersion;
     this.newVersion = newVersion;
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Constructs the table
 /// </summary>
 /// <param name="store"></param>
 /// <param name="name"></param>
 /// <param name="fields"></param>
 public TableSnapshot(StoreSnapshot store, string name, params IField <TRecord>[] fields)
 {
     if (fields == null)
     {
         throw new ArgumentNullException(nameof(fields));
     }
     this.StoreSnapshot = store ?? throw new ArgumentNullException(nameof(store));
     this.table         = new SnapTable <TRecord>(store.SnapStore, name, 0, fields, true);
     this.StoreSnapshot.Add(this, this.table);
 }
Ejemplo n.º 5
0
 public StoreSnapshot(StoreSnapshot store) : this(store.SnapStore.CheckFrozen())
 {
     foreach (ISnapTable snapTable in this.SnapStore.Tables)
     {
         if (snapTable.IsUserTable)
         {
             this.primaryKeyHolder.Add((IPrimaryKeyHolder)snapTable.CreateTableSnapshot(this));
         }
     }
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Starts new transaction. If successful then returns:
        /// - number of the started transaction if it is Edit transaction
        /// - number of transaction to revert if it is Undo/Redo transaction
        /// If transaction was not started then returns 0.
        /// </summary>
        /// <param name="newEditor">StoreSnapshot that owns the transaction</param>
        /// <param name="transactionType">Edit, Undo or Redo transaction</param>
        /// <returns></returns>
        private int StartTransaction(StoreSnapshot newEditor, TransactionType transactionType)
        {
            if (newEditor == null)
            {
                throw new ArgumentNullException("newEditor");
            }
            Debug.Assert(transactionType == TransactionType.Edit || transactionType == TransactionType.Undo || transactionType == TransactionType.Redo, "Wrong transaction type");
            this.CheckFrozen();

            int transaction = 0;
            // any value of oldEditor other then null means this thread does not own the transaction
            // null means this thread is exclusive owner of transaction
            StoreSnapshot oldEditor = newEditor;
            bool          success   = false;

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                RuntimeHelpers.PrepareConstrainedRegions();
                try {} finally {
                    oldEditor = Interlocked.CompareExchange <StoreSnapshot>(ref this.editor, newEditor, null);
                }
                if (oldEditor == null)
                {
                    Debug.Assert(this.editor == newEditor, "Expecting to be current editor");
                    Debug.Assert(this.editorThread == null, "Editor thread should be null here");
                    if (this.version.Count == int.MaxValue)
                    {
                        throw new InvalidOperationException(Properties.Resources.ErrorTooManyTransactions);
                    }
                    this.editorThread = Thread.CurrentThread;
                    transaction       = (transactionType == TransactionType.Edit) ? this.version.Count + 1 : this.RevertVersion(transactionType);
                    if (0 < transaction)
                    {
                        this.version.PrepareAdd();
                        success = true;
                    }
                }
            } finally {
                if (success)
                {
                    this.version.FixedAdd(ref transactionType);
                }
                else if (oldEditor == null)
                {
                    Debug.Assert(this.editor == newEditor, "newEditor expected to be current editor");
                    this.editorThread = null;                     // this should be the first assignment
                    this.editor       = null;
                }
            }
            return(transaction);
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Reverts current transaction
 /// </summary>
 public void Rollback()
 {
     this.ValidateModification();
     RuntimeHelpers.PrepareConstrainedRegions();
     try { } finally {
         foreach (ISnapTable snapTable in this.Tables)
         {
             snapTable.Rollback();
         }
         ValueList <TransactionType> .Address address = this.version.ItemAddress(this.version.Count - 1);
         address.Page[address.Index] = TransactionType.Omit;
         this.CompletedVersion       = this.Version;
         this.editorThread           = null;
         this.editor = null;
         LockFreeSync.WriteBarrier();
     }
 }
Ejemplo n.º 8
0
 /// <summary>
 /// Copy constructor
 /// </summary>
 /// <param name="storeSnapshot"></param>
 /// <param name="table"></param>
 internal TableSnapshot(StoreSnapshot storeSnapshot, SnapTable <TRecord> table)
 {
     this.StoreSnapshot = storeSnapshot;
     this.table         = table;
     this.StoreSnapshot.Add(this, this.table);
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Create TableSnapshot base on the TRecord.
 /// </summary>
 /// <param name="storeSnapshot"></param>
 /// <returns></returns>
 public ITableSnapshot CreateTableSnapshot(StoreSnapshot storeSnapshot)
 {
     Debug.Assert(this.IsUserTable);
     return(new TableSnapshot <TRecord>(storeSnapshot, this));
 }
Ejemplo n.º 10
0
 /// <summary>
 /// Starts new transaction, performs redo and commits.
 /// If transaction was started successfully return new version of the store, otherwise return version of editor.
 /// </summary>
 /// <param name="storeSnapshot"></param>
 /// <returns></returns>
 public int Redo(StoreSnapshot storeSnapshot)
 {
     return(this.Revert(storeSnapshot, TransactionType.Redo));
 }
Ejemplo n.º 11
0
 /// <summary>
 /// Starts new transaction
 /// </summary>
 /// <param name="storeSnapshot">Owner of the transaction</param>
 /// <returns>true if the transaction started, false if other transaction is in progress</returns>
 public bool StartTransaction(StoreSnapshot storeSnapshot)
 {
     return(0 < this.StartTransaction(storeSnapshot, TransactionType.Edit));
 }