From 9ba4639a27c45f5998e2e13651bbc92ae773a24f Mon Sep 17 00:00:00 2001 From: chrislu Date: Sat, 23 Sep 2023 11:53:44 -0700 Subject: [PATCH 1/6] adjust for better logs --- weed/util/lock_table.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weed/util/lock_table.go b/weed/util/lock_table.go index d10b51334..4aadf2880 100644 --- a/weed/util/lock_table.go +++ b/weed/util/lock_table.go @@ -89,7 +89,6 @@ func (lt *LockTable[T]) AcquireLock(intention string, key T, lockType LockType) entry.cond.Broadcast() } } - entry.activeLockOwnerCount++ // Otherwise, grant the lock entry.lockType = lockType @@ -102,6 +101,7 @@ func (lt *LockTable[T]) AcquireLock(intention string, key T, lockType LockType) fmt.Printf("\n") } } + entry.activeLockOwnerCount++ entry.mu.Unlock() return lock From 0414b68a4f89bcfe13d179fe54456fe79368f521 Mon Sep 17 00:00:00 2001 From: chrislu Date: Sat, 23 Sep 2023 12:08:23 -0700 Subject: [PATCH 2/6] if shared lock, still need to wait for exclusive lock to release --- weed/util/lock_table.go | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/weed/util/lock_table.go b/weed/util/lock_table.go index 4aadf2880..24a500caf 100644 --- a/weed/util/lock_table.go +++ b/weed/util/lock_table.go @@ -16,11 +16,12 @@ type LockTable[T comparable] struct { } type LockEntry struct { - mu sync.Mutex - waiters []*ActiveLock // ordered waiters that are blocked by exclusive locks - activeLockOwnerCount int32 - lockType LockType - cond *sync.Cond + mu sync.Mutex + waiters []*ActiveLock // ordered waiters that are blocked by exclusive locks + activeSharedLockOwnerCount int32 + activeExclusiveLockOwnerCount int32 + lockType LockType + cond *sync.Cond } type LockType int @@ -34,6 +35,7 @@ type ActiveLock struct { ID int64 isDeleted bool intention string // for debugging + lockType LockType } func NewLockTable[T comparable]() *LockTable[T] { @@ -42,9 +44,9 @@ func NewLockTable[T comparable]() *LockTable[T] { } } -func (lt *LockTable[T]) NewActiveLock(intention string) *ActiveLock { +func (lt *LockTable[T]) NewActiveLock(intention string, lockType LockType) *ActiveLock { id := atomic.AddInt64(<.lockIdSeq, 1) - l := &ActiveLock{ID: id, intention: intention} + l := &ActiveLock{ID: id, intention: intention, lockType: lockType} return l } @@ -65,7 +67,7 @@ func (lt *LockTable[T]) AcquireLock(intention string, key T, lockType LockType) entry.mu.Lock() if len(entry.waiters) > 0 || lockType == ExclusiveLock { if glog.V(4) { - fmt.Printf("ActiveLock %d %s wait for %+v type=%v with waiters %d active %d.\n", lock.ID, lock.intention, key, lockType, len(entry.waiters), entry.activeLockOwnerCount) + fmt.Printf("ActiveLock %d %s wait for %+v type=%v with waiters %d active r%d w%d.\n", lock.ID, lock.intention, key, lockType, len(entry.waiters), entry.activeSharedLockOwnerCount, entry.activeExclusiveLockOwnerCount) if len(entry.waiters) > 0 { for _, waiter := range entry.waiters { fmt.Printf(" %d", waiter.ID) @@ -75,11 +77,11 @@ func (lt *LockTable[T]) AcquireLock(intention string, key T, lockType LockType) } entry.waiters = append(entry.waiters, lock) if lockType == ExclusiveLock { - for !lock.isDeleted && ((len(entry.waiters) > 0 && lock.ID != entry.waiters[0].ID) || entry.activeLockOwnerCount > 0) { + for !lock.isDeleted && ((len(entry.waiters) > 0 && lock.ID != entry.waiters[0].ID) || entry.activeExclusiveLockOwnerCount > 0 || entry.activeSharedLockOwnerCount > 0) { entry.cond.Wait() } } else { - for !lock.isDeleted && (len(entry.waiters) > 0 && lock.ID != entry.waiters[0].ID) { + for !lock.isDeleted && (len(entry.waiters) > 0 && lock.ID != entry.waiters[0].ID) || entry.activeExclusiveLockOwnerCount > 0 { entry.cond.Wait() } } @@ -93,7 +95,7 @@ func (lt *LockTable[T]) AcquireLock(intention string, key T, lockType LockType) // Otherwise, grant the lock entry.lockType = lockType if glog.V(4) { - fmt.Printf("ActiveLock %d %s locked %+v type=%v with waiters %d active %d.\n", lock.ID, lock.intention, key, lockType, len(entry.waiters), entry.activeLockOwnerCount) + fmt.Printf("ActiveLock %d %s locked %+v type=%v with waiters %d active r%d w%d.\n", lock.ID, lock.intention, key, lockType, len(entry.waiters), entry.activeSharedLockOwnerCount, entry.activeExclusiveLockOwnerCount) if len(entry.waiters) > 0 { for _, waiter := range entry.waiters { fmt.Printf(" %d", waiter.ID) @@ -101,7 +103,11 @@ func (lt *LockTable[T]) AcquireLock(intention string, key T, lockType LockType) fmt.Printf("\n") } } - entry.activeLockOwnerCount++ + if lock.lockType == ExclusiveLock { + entry.activeExclusiveLockOwnerCount++ + } else { + entry.activeSharedLockOwnerCount++ + } entry.mu.Unlock() return lock @@ -134,7 +140,7 @@ func (lt *LockTable[T]) ReleaseLock(key T, lock *ActiveLock) { } if glog.V(4) { - fmt.Printf("ActiveLock %d %s unlocked %+v type=%v with waiters %d active %d.\n", lock.ID, lock.intention, key, entry.lockType, len(entry.waiters), entry.activeLockOwnerCount) + fmt.Printf("ActiveLock %d %s unlocked %+v type=%v with waiters %d active r%d w%d.\n", lock.ID, lock.intention, key, entry.lockType, len(entry.waiters), entry.activeSharedLockOwnerCount, entry.activeExclusiveLockOwnerCount) if len(entry.waiters) > 0 { for _, waiter := range entry.waiters { fmt.Printf(" %d", waiter.ID) @@ -142,7 +148,11 @@ func (lt *LockTable[T]) ReleaseLock(key T, lock *ActiveLock) { fmt.Printf("\n") } } - entry.activeLockOwnerCount-- + if lock.lockType == ExclusiveLock { + entry.activeExclusiveLockOwnerCount-- + } else { + entry.activeSharedLockOwnerCount-- + } // Notify the next waiter entry.cond.Broadcast() From 322af1fc0477c66c748d0e1f2195ad5bee5821a5 Mon Sep 17 00:00:00 2001 From: chrislu Date: Sat, 23 Sep 2023 12:13:32 -0700 Subject: [PATCH 3/6] fix compilation --- weed/util/lock_table.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weed/util/lock_table.go b/weed/util/lock_table.go index 24a500caf..b27104a11 100644 --- a/weed/util/lock_table.go +++ b/weed/util/lock_table.go @@ -61,7 +61,7 @@ func (lt *LockTable[T]) AcquireLock(intention string, key T, lockType LockType) } lt.mu.Unlock() - lock = lt.NewActiveLock(intention) + lock = lt.NewActiveLock(intention, lockType) // If the lock is held exclusively, wait entry.mu.Lock() From c43238b30a36ec2a2ac8d2060af5907be6b876c1 Mon Sep 17 00:00:00 2001 From: chrislu Date: Sat, 23 Sep 2023 12:28:02 -0700 Subject: [PATCH 4/6] fix waiting condition --- weed/util/lock_table.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weed/util/lock_table.go b/weed/util/lock_table.go index b27104a11..fd6e1987a 100644 --- a/weed/util/lock_table.go +++ b/weed/util/lock_table.go @@ -65,7 +65,7 @@ func (lt *LockTable[T]) AcquireLock(intention string, key T, lockType LockType) // If the lock is held exclusively, wait entry.mu.Lock() - if len(entry.waiters) > 0 || lockType == ExclusiveLock { + if len(entry.waiters) > 0 || lockType == ExclusiveLock || entry.activeExclusiveLockOwnerCount > 0 { if glog.V(4) { fmt.Printf("ActiveLock %d %s wait for %+v type=%v with waiters %d active r%d w%d.\n", lock.ID, lock.intention, key, lockType, len(entry.waiters), entry.activeSharedLockOwnerCount, entry.activeExclusiveLockOwnerCount) if len(entry.waiters) > 0 { From 10ac25f857655afe9a2397336d9abe7eb9338c66 Mon Sep 17 00:00:00 2001 From: chrislu Date: Sat, 23 Sep 2023 12:43:00 -0700 Subject: [PATCH 5/6] avoid deleting the entry too early --- weed/util/lock_table.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weed/util/lock_table.go b/weed/util/lock_table.go index fd6e1987a..8ec93f7e7 100644 --- a/weed/util/lock_table.go +++ b/weed/util/lock_table.go @@ -135,7 +135,7 @@ func (lt *LockTable[T]) ReleaseLock(key T, lock *ActiveLock) { } // If there are no waiters, release the lock - if len(entry.waiters) == 0 { + if len(entry.waiters) == 0 && entry.activeExclusiveLockOwnerCount <= 0 && entry.activeSharedLockOwnerCount <= 0 { delete(lt.locks, key) } From 1df42231952d7d9087d8dc476c02d388eda7e871 Mon Sep 17 00:00:00 2001 From: chrislu Date: Sun, 24 Sep 2023 09:54:57 -0700 Subject: [PATCH 6/6] minor --- weed/util/lock_table.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/weed/util/lock_table.go b/weed/util/lock_table.go index 8ec93f7e7..2e689d330 100644 --- a/weed/util/lock_table.go +++ b/weed/util/lock_table.go @@ -20,7 +20,6 @@ type LockEntry struct { waiters []*ActiveLock // ordered waiters that are blocked by exclusive locks activeSharedLockOwnerCount int32 activeExclusiveLockOwnerCount int32 - lockType LockType cond *sync.Cond } @@ -93,7 +92,6 @@ func (lt *LockTable[T]) AcquireLock(intention string, key T, lockType LockType) } // Otherwise, grant the lock - entry.lockType = lockType if glog.V(4) { fmt.Printf("ActiveLock %d %s locked %+v type=%v with waiters %d active r%d w%d.\n", lock.ID, lock.intention, key, lockType, len(entry.waiters), entry.activeSharedLockOwnerCount, entry.activeExclusiveLockOwnerCount) if len(entry.waiters) > 0 { @@ -140,7 +138,7 @@ func (lt *LockTable[T]) ReleaseLock(key T, lock *ActiveLock) { } if glog.V(4) { - fmt.Printf("ActiveLock %d %s unlocked %+v type=%v with waiters %d active r%d w%d.\n", lock.ID, lock.intention, key, entry.lockType, len(entry.waiters), entry.activeSharedLockOwnerCount, entry.activeExclusiveLockOwnerCount) + fmt.Printf("ActiveLock %d %s unlocked %+v type=%v with waiters %d active r%d w%d.\n", lock.ID, lock.intention, key, lock.lockType, len(entry.waiters), entry.activeSharedLockOwnerCount, entry.activeExclusiveLockOwnerCount) if len(entry.waiters) > 0 { for _, waiter := range entry.waiters { fmt.Printf(" %d", waiter.ID)