예제 #1
0
파일: LockManager.cs 프로젝트: zuvys/Vicuna
        /// <summary>
        /// create a new table-lock
        /// </summary>
        /// <param name="ctx"></param>
        /// <returns></returns>
        private LockEntry CreateTabLock(ref LockContext ctx)
        {
            if (!TabLocks.TryGetValue(ctx.Index, out var list))
            {
                list = new LinkedList <LockEntry>();
                TabLocks[ctx.Index] = list;;
            }

            var tx    = ctx.Transaction;
            var entry = new LockEntry(ctx.Page, ctx.Flags, ctx.RecordCount);

            if (entry.IsWaiting)
            {
                tx.WaitLock = entry;
            }

            list.AddLast(entry);
            tx.Locks.AddLast(entry);

            entry.GNode       = list.Last;
            entry.TNode       = tx.Locks.Last;
            entry.Index       = ctx.Index;
            entry.Transaction = ctx.Transaction;
            entry.Thread      = Thread.CurrentThread.ManagedThreadId;

            return(entry);
        }
예제 #2
0
파일: LockManager.cs 프로젝트: zuvys/Vicuna
        /// <summary>
        /// check current transaction has held the table's lock >=ctx-lock-level and not been in wait state
        /// </summary>
        /// <param name="ctx"></param>
        /// <returns></returns>
        private bool IsHeldTabLock(ref LockContext ctx, out LockEntry entry)
        {
            var locks = TabLocks.GetValueOrDefault(ctx.Index);

            if (locks == null)
            {
                entry = null;
                return(false);
            }

            for (var node = locks.First; node != null; node = node.Next)
            {
                var lockEntry = node.Value;
                if (lockEntry.Transaction != ctx.Transaction)
                {
                    continue;
                }

                if (lockEntry.IsExclusive || !ctx.Flags.IsExclusive())
                {
                    entry = lockEntry;
                    return(true);
                }
            }

            entry = null;
            return(false);
        }
예제 #3
0
파일: LockManager.cs 프로젝트: zuvys/Vicuna
        /// <summary>
        /// is other's transaction has held the table's lock and conflict with the ctx-lock
        /// </summary>
        /// <param name="ctx"></param>
        /// <returns></returns>
        private bool IsOthersHeldOrWaitConflictTabLock(Transaction tx, TableIndex index, LockFlags flags, LockEntry endEntry = null)
        {
            var locks = TabLocks.GetValueOrDefault(index);

            if (locks == null)
            {
                return(false);
            }

            for (var node = locks.First; node != null; node = node.Next)
            {
                var entry = node.Value;
                if (entry == endEntry)
                {
                    break;
                }

                if (entry.Transaction == tx)
                {
                    continue;
                }

                if (entry.IsExclusive || flags.IsExclusive())
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #4
0
파일: LockManager.cs 프로젝트: zuvys/Vicuna
        /// <summary>
        /// lock a table
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="entry"></param>
        /// <returns></returns>
        public DBResult LockTab(ref LockContext ctx, out LockEntry entry)
        {
            var locks = TabLocks.GetValueOrDefault(ctx.Index);

            if (locks == null || locks.Count == 0)
            {
                entry = CreateTabLock(ref ctx);
                return(DBResult.Success);
            }

            if (IsHeldTabLock(ref ctx, out entry))
            {
                return(DBResult.Success);
            }

            if (IsOthersHeldOrWaitConflictTabLock(ctx.Transaction, ctx.Index, ctx.Flags))
            {
                ctx.Flags |= LockFlags.Waiting;
                return(CreateTabLockForWait(ref ctx, out entry));
            }

            entry = CreateTabLock(ref ctx);
            return(DBResult.Success);
        }
예제 #5
0
파일: LockManager.cs 프로젝트: zuvys/Vicuna
 internal LockEntry FindFirstTabLockEntry(TableIndex index)
 {
     return(TabLocks.TryGetValue(index, out var list) ? list.First.Value : null);
 }