mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-08 15:41:15 +02:00
noLock says "this invocation changes nothing" -- volume.balance, volume.move,
volume.copy, volume.merge and volume.fix.replication all set it for a dry run,
and none clears it. The CommandEnv is created once and reused by both
dispatchers, the interactive shell and the master's maintenance script runner,
so a simulation left every later command unlocked:
volume.balance -noLock # changes nothing
volume.move ... # mutates, and skips its lock
Reset before dispatch in both, where the invocation begins. forceNoLock is
untouched: that is set once, deliberately, for a trusted path.
49 lines
1.8 KiB
Go
49 lines
1.8 KiB
Go
package shell
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/cluster"
|
|
"github.com/seaweedfs/seaweedfs/weed/wdclient/exclusive_locks"
|
|
)
|
|
|
|
// noLock says "this invocation changes nothing" -- volume.balance,
|
|
// volume.fix.replication and others set it for a dry run. It is a property of
|
|
// the invocation, not of the session: the CommandEnv is reused across every
|
|
// command, so without a reset a simulation leaves later commands unlocked and a
|
|
// real mutation run straight after one skips its lock silently.
|
|
func TestNoLockDoesNotOutliveTheCommandThatSetIt(t *testing.T) {
|
|
env := &CommandEnv{locker: exclusive_locks.NewExclusiveLocker(nil, cluster.AdminShellLockName)}
|
|
|
|
env.SetNoLock(true)
|
|
if err := env.confirmIsLocked([]string{"volume.balance"}); err != nil {
|
|
t.Fatalf("a dry run needs no lock: %v", err)
|
|
}
|
|
|
|
env.SetNoLock(false)
|
|
|
|
if err := env.confirmIsLocked([]string{"volume.move"}); err == nil {
|
|
t.Error("the next command mutates and must require the lock again")
|
|
}
|
|
}
|
|
|
|
// Both dispatchers reuse one CommandEnv: the interactive shell across the lines
|
|
// an operator types, and the master's maintenance script runner across the lines
|
|
// of a script. Resetting has to restore the lock requirement however many
|
|
// invocations share the environment.
|
|
func TestNoLockResetRestoresTheRequirementForEveryInvocation(t *testing.T) {
|
|
env := &CommandEnv{locker: exclusive_locks.NewExclusiveLocker(nil, cluster.AdminShellLockName)}
|
|
|
|
for i := 0; i < 3; i++ {
|
|
env.SetNoLock(true)
|
|
if err := env.confirmIsLocked([]string{"dry run"}); err != nil {
|
|
t.Fatalf("run %d: a dry run needs no lock: %v", i, err)
|
|
}
|
|
|
|
env.SetNoLock(false)
|
|
if err := env.confirmIsLocked([]string{"mutation"}); err == nil {
|
|
t.Fatalf("run %d: the mutation after it must require the lock again", i)
|
|
}
|
|
}
|
|
}
|