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