internal SimpleTransactionLogger(XDocument m, SimpleTransaction t)
        {
            model = m;
            tx = t;
            undoCommands = new List<XmlModelCommand>();
            txCommands = new List<XmlModelCommand>();

            nodesAdded = new Dictionary<XObject, object>();
            var provider = tx.Provider as VanillaXmlModelProvider;
            if ((provider == null || provider.CommandFactory == null))
            {
                cmdFactory = new CommandFactory();
            }
            else
            {
                cmdFactory = provider.CommandFactory;
            }
        }
        internal SimpleTransaction(
            VanillaXmlModelProvider provider, string name, SimpleTransaction parent, SimpleTransactionManager mgr, object userState)
        {
            this.provider = provider;
            this.name = name;
            this.parent = parent;
            manager = mgr;
            DesignerTransaction = true;

            resources = new Dictionary<XDocument, SimpleTransactionLogger>();
            status = XmlTransactionStatus.Active;
            _userState = userState;
        }
        internal void AppendCommands(SimpleTransaction childTransaction)
        {
            foreach (var doc in childTransaction.resources.Keys)
            {
                var logger = resources[doc];
                foreach (var cmd in childTransaction.resources[doc].TxCommands)
                {
                    logger.AddCommand(cmd);
                }

                foreach (var cmd in childTransaction.resources[doc].UndoCommands)
                {
                    logger.AddCommand(cmd);
                }
            }
        }
 internal void FireTransactionCompleted(SimpleTransaction tx)
 {
     OnTransactionCompleted(new XmlTransactionEventArgs(tx, tx.DesignerTransaction));
 }
 public virtual bool CanRedo(SimpleTransaction tx)
 {
     return true;
 }
 public void LockForWrite(SimpleTransaction txId, object doc)
 {
     Lock(txId, doc, LockMode.Write);
 }
        public void UnlockAll(SimpleTransaction txId)
        {
            ResourceEntry lockTarget = null;
            lock (_resourceTable)
            {
                IDictionaryEnumerator resenum = _resourceTable.GetEnumerator();

                while (resenum.MoveNext())
                {
                    lockTarget = resenum.Value as ResourceEntry;
                    if (lockTarget == null)
                    {
                        continue;
                    }
                    lock (lockTarget)
                    {
                        for (var lockMode = (int)LockMode.Read; lockMode < (int)LockMode._Length; lockMode++)
                        {
                            lockTarget.Unregister(txId, (LockMode)lockMode);
                        }
                    }
                }
            }
        }
        public void Lock(SimpleTransaction txId, object resource, LockMode mode)
        {
            ResourceEntry lockTarget = null;

            lock (_resourceTable)
            {
                lockTarget = GetResoureEntry(resource);

                if (lockTarget == null)
                {
                    lockTarget = new ResourceEntry();
                    _resourceTable[resource] = lockTarget;
                }
            }

            for (var c = 0;; c++)
            {
                if (c > 0)
                {
                    if (!lockTarget.UnlockEvent.WaitOne(5000, false))
                    {
                        throw new XmlTransactionException("DeadLock Detected...");
                    }
                }

                lock (lockTarget)
                {
                    var oldLockMode = lockTarget.GetExistingLockMode(txId);
                    if (oldLockMode != LockMode.Null)
                    {
                        lockTarget.Unregister(txId, oldLockMode);
                    }
                    if (lockTarget.Compatible(mode))
                    {
                        lockTarget.Register(txId, mode);
                        return;
                    }
                    if (oldLockMode != LockMode.Null)
                    {
                        lockTarget.Register(txId, oldLockMode);
                    }
                }
            }
        }
 public void LockForRead(SimpleTransaction txId, object doc)
 {
     Lock(txId, doc, LockMode.Read);
 }
            /// <summary>
            /// Release a lock on the passed in transaction context with
            /// the specified mode. Return immediately if the context does
            /// not hold a lock for this mode.
            /// </summary>
            /// <param name="context">the context for which to remove the lock</param>
            /// <param name="request">the mode of the lock to be released</param>
            public void Unregister(SimpleTransaction context, LockMode request)
            {
                // First get the hash table for this lock mode
                var transactionList = GetTransactionList(request);

                if (transactionList == null
                    || !transactionList.ContainsKey(context))
                {
                    // This transaction wasn't registered, return immediately
                    return;
                }

                transactionList.Remove(context);

                for (var l = request; l > LockMode.Null; _lockMode = --l)
                {
                    // recalculate the strongest lock mode
                    var nextTransactionList = GetTransactionList(l);
                    if (nextTransactionList == null)
                    {
                        continue;
                    }
                    if (nextTransactionList.Count > 0)
                    {
                        break;
                    }
                }

                if (request > _lockMode)
                {
                    // if anyone was waiting for this lock, they should recheck
                    if (_autoResetEvent != null)
                    {
                        _autoResetEvent.Set();
                    }
                }
            }
 public LockMode GetExistingLockMode(SimpleTransaction txId)
 {
     for (var i = 0; i < (int)LockMode._Length; i++)
     {
         var tList = GetTransactionList((LockMode)i);
         if (tList != null
             && tList.ContainsKey(txId))
         {
             return (LockMode)i;
         }
     }
     return LockMode.Null;
 }
            public void Register(SimpleTransaction context, LockMode request)
            {
                var transactionList = GetTransactionList(request);
                if (transactionList == null)
                {
                    transactionList = new Dictionary<SimpleTransaction, SimpleTransaction>();
                    _transactions[request] = transactionList;
                }

                // Add the transaction to the list for _request_ lock mode
                transactionList[context] = context;

                // Update the strongest lock mode, if necessary	  
                if (request > _lockMode)
                {
                    _lockMode = request;
                }

                if (_autoResetEvent != null)
                {
                    _autoResetEvent.Reset();
                }
            }
 internal void SetCurrentTransaction(VanillaXmlModelProvider provider, SimpleTransaction tx)
 {
     if (_currentTransaction.ContainsKey(provider))
     {
         _currentTransaction[provider] = tx;
     }
     else
     {
         _currentTransaction.Add(provider, tx);
     }
 }
        internal void Rollback(SimpleTransaction tx)
        {
            tx.MakeInactive();
            var parent = tx.parent;

            // Unlock all resources held by this transaction
            if (parent != null)
            {
                parent.MakeActive();
            }
            _currentTransaction[tx.provider] = parent;

            // Unlock Store only when Top-most Tx Completes
            if (parent == null)
            {
                SimpleLockManager.UnlockAll(tx);
            }

            // In case of Rollback we fire off event even for nested Tx
            tx.FireCompleted();
        }
        internal void Commit(SimpleTransaction tx)
        {
            tx.MakeInactive();
            var parent = tx.parent;

            // Unlock all resources held by this transaction
            if (parent != null)
            {
                parent.MakeActive();
            }
            _currentTransaction[tx.provider] = parent;

            // Fire Events and unlock Store only when  Top-most Tx commits
            if (parent == null)
            {
                SimpleLockManager.UnlockAll(tx);
                tx.FireCompleted();
            }
        }
        internal SimpleTransaction BeginTransaction(
            VanillaXmlModelProvider provider, string name, SimpleTransaction parent, object userState)
        {
            var tx = new SimpleTransaction(provider, name, parent, this, userState);

            if (parent != null)
            {
                // Unsubscribe events on parent transaction
                parent.MakeInactive();

                // Create SimpleTransactionLogger for each document in VanillaXmlModelProvider
                foreach (var model in provider.OpenXmlModels)
                {
                    tx.EnlistResource(model as SimpleXmlModel);
                }
            }
            else
            {
                // This is the top level transaction, so acquire all locks to avoid deadlocks
                lock (this)
                {
                    foreach (var model in provider.OpenXmlModels)
                    {
                        tx.LockForWrite(model as SimpleXmlModel);
                    }
                }
            }

            // Make this the current Active transaction
            SetCurrentTransaction(provider, tx);
            tx.MakeActive();

            return tx;
        }