/// <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); }
/// <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); }
/// <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); }