6 changed files with 165 additions and 0 deletions
-
87weed/admin/dash/admin_lock_manager.go
-
38weed/admin/dash/admin_server.go
-
8weed/admin/dash/plugin_api.go
-
7weed/admin/plugin/lock_manager.go
-
10weed/admin/plugin/plugin.go
-
15weed/admin/plugin/plugin_scheduler.go
@ -0,0 +1,87 @@ |
|||||
|
package dash |
||||
|
|
||||
|
import ( |
||||
|
"sync" |
||||
|
|
||||
|
"github.com/seaweedfs/seaweedfs/weed/wdclient" |
||||
|
"github.com/seaweedfs/seaweedfs/weed/wdclient/exclusive_locks" |
||||
|
) |
||||
|
|
||||
|
const ( |
||||
|
adminLockName = "shell" |
||||
|
adminLockClientName = "admin-plugin" |
||||
|
) |
||||
|
|
||||
|
// AdminLockManager coordinates exclusive admin locks with reference counting.
|
||||
|
// It is safe for concurrent use.
|
||||
|
type AdminLockManager struct { |
||||
|
locker *exclusive_locks.ExclusiveLocker |
||||
|
clientName string |
||||
|
|
||||
|
mu sync.Mutex |
||||
|
cond *sync.Cond |
||||
|
acquiring bool |
||||
|
holdCount int |
||||
|
} |
||||
|
|
||||
|
func NewAdminLockManager(masterClient *wdclient.MasterClient, clientName string) *AdminLockManager { |
||||
|
if masterClient == nil { |
||||
|
return nil |
||||
|
} |
||||
|
if clientName == "" { |
||||
|
clientName = adminLockClientName |
||||
|
} |
||||
|
manager := &AdminLockManager{ |
||||
|
locker: exclusive_locks.NewExclusiveLocker(masterClient, adminLockName), |
||||
|
clientName: clientName, |
||||
|
} |
||||
|
manager.cond = sync.NewCond(&manager.mu) |
||||
|
return manager |
||||
|
} |
||||
|
|
||||
|
func (m *AdminLockManager) Acquire(reason string) (func(), error) { |
||||
|
if m == nil || m.locker == nil { |
||||
|
return func() {}, nil |
||||
|
} |
||||
|
|
||||
|
m.mu.Lock() |
||||
|
if reason != "" { |
||||
|
m.locker.SetMessage(reason) |
||||
|
} |
||||
|
for m.acquiring { |
||||
|
m.cond.Wait() |
||||
|
} |
||||
|
if m.holdCount == 0 { |
||||
|
m.acquiring = true |
||||
|
m.mu.Unlock() |
||||
|
m.locker.RequestLock(m.clientName) |
||||
|
m.mu.Lock() |
||||
|
m.acquiring = false |
||||
|
m.holdCount = 1 |
||||
|
m.cond.Broadcast() |
||||
|
m.mu.Unlock() |
||||
|
return m.Release, nil |
||||
|
} |
||||
|
m.holdCount++ |
||||
|
m.mu.Unlock() |
||||
|
return m.Release, nil |
||||
|
} |
||||
|
|
||||
|
func (m *AdminLockManager) Release() { |
||||
|
if m == nil || m.locker == nil { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
m.mu.Lock() |
||||
|
if m.holdCount <= 0 { |
||||
|
m.mu.Unlock() |
||||
|
return |
||||
|
} |
||||
|
m.holdCount-- |
||||
|
shouldRelease := m.holdCount == 0 |
||||
|
m.mu.Unlock() |
||||
|
|
||||
|
if shouldRelease { |
||||
|
m.locker.ReleaseLock() |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
package plugin |
||||
|
|
||||
|
// LockManager provides a shared exclusive lock for admin-managed detection/execution.
|
||||
|
// Acquire returns a release function that must be called when the protected work finishes.
|
||||
|
type LockManager interface { |
||||
|
Acquire(reason string) (release func(), err error) |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue