mirror of
https://github.com/minio/minio.git
synced 2024-12-25 22:55:54 -05:00
Tracing locking errors for better debugging (#3140)
This commit is contained in:
parent
f3c6c55719
commit
807cc3c28d
@ -88,13 +88,13 @@ func (l LockInfoOriginNotFound) Error() string {
|
|||||||
l.lockOrigin, l.volume, l.path, l.opsID)
|
l.lockOrigin, l.volume, l.path, l.opsID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LockInfoVolPathMssing - Error interface. Returned when the info the
|
// LockInfoVolPathMissing - Error interface. Returned when the info the
|
||||||
type LockInfoVolPathMssing struct {
|
type LockInfoVolPathMissing struct {
|
||||||
volume string
|
volume string
|
||||||
path string
|
path string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l LockInfoVolPathMssing) Error() string {
|
func (l LockInfoVolPathMissing) Error() string {
|
||||||
return fmt.Sprintf("No entry in debug Lock Map for Volume: %s, path: %s.", l.volume, l.path)
|
return fmt.Sprintf("No entry in debug Lock Map for Volume: %s, path: %s.", l.volume, l.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,26 +152,26 @@ func (n *nsLockMap) statusBlockedToRunning(param nsParam, lockOrigin, opsID stri
|
|||||||
debugLockMap, ok := n.debugLockMap[param]
|
debugLockMap, ok := n.debugLockMap[param]
|
||||||
if !ok {
|
if !ok {
|
||||||
// The lock state info foe given <volume, path> pair should already exist.
|
// The lock state info foe given <volume, path> pair should already exist.
|
||||||
// If not return `LockInfoVolPathMssing`.
|
// If not return `LockInfoVolPathMissing`.
|
||||||
return LockInfoVolPathMssing{param.volume, param.path}
|
return traceError(LockInfoVolPathMissing{param.volume, param.path})
|
||||||
}
|
}
|
||||||
// ``debugLockMap`` entry containing lock info for `param <volume, path>` is `nil`.
|
// ``debugLockMap`` entry containing lock info for `param <volume, path>` is `nil`.
|
||||||
if debugLockMap == nil {
|
if debugLockMap == nil {
|
||||||
return errLockNotInitialized
|
return traceError(errLockNotInitialized)
|
||||||
}
|
}
|
||||||
lockInfo, ok := n.debugLockMap[param].lockInfo[opsID]
|
lockInfo, ok := n.debugLockMap[param].lockInfo[opsID]
|
||||||
if !ok {
|
if !ok {
|
||||||
// The lock info entry for given `opsID` should already exist for given <volume, path> pair.
|
// The lock info entry for given `opsID` should already exist for given <volume, path> pair.
|
||||||
// If not return `LockInfoOpsIDNotFound`.
|
// If not return `LockInfoOpsIDNotFound`.
|
||||||
return LockInfoOpsIDNotFound{param.volume, param.path, opsID}
|
return traceError(LockInfoOpsIDNotFound{param.volume, param.path, opsID})
|
||||||
}
|
}
|
||||||
// The entry for the lock origined at `lockOrigin` should already exist. If not return `LockInfoOriginNotFound`.
|
// The entry for the lock origined at `lockOrigin` should already exist. If not return `LockInfoOriginNotFound`.
|
||||||
if lockInfo.lockOrigin != lockOrigin {
|
if lockInfo.lockOrigin != lockOrigin {
|
||||||
return LockInfoOriginNotFound{param.volume, param.path, opsID, lockOrigin}
|
return traceError(LockInfoOriginNotFound{param.volume, param.path, opsID, lockOrigin})
|
||||||
}
|
}
|
||||||
// Status of the lock should already be set to "Blocked". If not return `LockInfoStateNotBlocked`.
|
// Status of the lock should already be set to "Blocked". If not return `LockInfoStateNotBlocked`.
|
||||||
if lockInfo.status != blockedStatus {
|
if lockInfo.status != blockedStatus {
|
||||||
return LockInfoStateNotBlocked{param.volume, param.path, opsID}
|
return traceError(LockInfoStateNotBlocked{param.volume, param.path, opsID})
|
||||||
}
|
}
|
||||||
// All checks finished. Changing the status of the operation from blocked to running and updating the time.
|
// All checks finished. Changing the status of the operation from blocked to running and updating the time.
|
||||||
n.debugLockMap[param].lockInfo[opsID] = newLockInfo
|
n.debugLockMap[param].lockInfo[opsID] = newLockInfo
|
||||||
@ -230,7 +230,7 @@ func (n *nsLockMap) statusNoneToBlocked(param nsParam, lockOrigin, opsID string,
|
|||||||
func (n *nsLockMap) deleteLockInfoEntryForVolumePath(param nsParam) error {
|
func (n *nsLockMap) deleteLockInfoEntryForVolumePath(param nsParam) error {
|
||||||
// delete the lock info for the given operation.
|
// delete the lock info for the given operation.
|
||||||
if _, found := n.debugLockMap[param]; !found {
|
if _, found := n.debugLockMap[param]; !found {
|
||||||
return LockInfoVolPathMssing{param.volume, param.path}
|
return traceError(LockInfoVolPathMissing{param.volume, param.path})
|
||||||
}
|
}
|
||||||
// Remove from the map if there are no more references for the given (volume,path) pair.
|
// Remove from the map if there are no more references for the given (volume,path) pair.
|
||||||
delete(n.debugLockMap, param)
|
delete(n.debugLockMap, param)
|
||||||
@ -244,14 +244,14 @@ func (n *nsLockMap) deleteLockInfoEntryForOps(param nsParam, opsID string) error
|
|||||||
// delete the lock info for the given operation.
|
// delete the lock info for the given operation.
|
||||||
infoMap, found := n.debugLockMap[param]
|
infoMap, found := n.debugLockMap[param]
|
||||||
if !found {
|
if !found {
|
||||||
return LockInfoVolPathMssing{param.volume, param.path}
|
return traceError(LockInfoVolPathMissing{param.volume, param.path})
|
||||||
}
|
}
|
||||||
// The opertion finished holding the lock on the resource, remove
|
// The opertion finished holding the lock on the resource, remove
|
||||||
// the entry for the given operation with the operation ID.
|
// the entry for the given operation with the operation ID.
|
||||||
_, foundInfo := infoMap.lockInfo[opsID]
|
_, foundInfo := infoMap.lockInfo[opsID]
|
||||||
if !foundInfo {
|
if !foundInfo {
|
||||||
// Unlock request with invalid opertion ID not accepted.
|
// Unlock request with invalid opertion ID not accepted.
|
||||||
return LockInfoOpsIDNotFound{param.volume, param.path, opsID}
|
return traceError(LockInfoOpsIDNotFound{param.volume, param.path, opsID})
|
||||||
}
|
}
|
||||||
// Decrease the global running and lock reference counter.
|
// Decrease the global running and lock reference counter.
|
||||||
n.runningLockCounter--
|
n.runningLockCounter--
|
||||||
|
@ -278,7 +278,7 @@ func TestNsLockMapStatusBlockedToRunning(t *testing.T) {
|
|||||||
readLock: false,
|
readLock: false,
|
||||||
setBlocked: false,
|
setBlocked: false,
|
||||||
// expected metrics.
|
// expected metrics.
|
||||||
expectedErr: LockInfoVolPathMssing{"my-bucket", "my-object-2"},
|
expectedErr: LockInfoVolPathMissing{"my-bucket", "my-object-2"},
|
||||||
},
|
},
|
||||||
// Test case - 3.
|
// Test case - 3.
|
||||||
// Entry for the given operationID doesn't exist in the lock state info.
|
// Entry for the given operationID doesn't exist in the lock state info.
|
||||||
@ -325,8 +325,8 @@ func TestNsLockMapStatusBlockedToRunning(t *testing.T) {
|
|||||||
actualErr := nsMutex.statusBlockedToRunning(param, testCases[0].lockOrigin,
|
actualErr := nsMutex.statusBlockedToRunning(param, testCases[0].lockOrigin,
|
||||||
testCases[0].opsID, testCases[0].readLock)
|
testCases[0].opsID, testCases[0].readLock)
|
||||||
|
|
||||||
expectedErr := LockInfoVolPathMssing{testCases[0].volume, testCases[0].path}
|
expectedErr := LockInfoVolPathMissing{testCases[0].volume, testCases[0].path}
|
||||||
if actualErr != expectedErr {
|
if errorCause(actualErr) != expectedErr {
|
||||||
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", expectedErr, actualErr)
|
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", expectedErr, actualErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,7 +340,7 @@ func TestNsLockMapStatusBlockedToRunning(t *testing.T) {
|
|||||||
actualErr = nsMutex.statusBlockedToRunning(param, testCases[0].lockOrigin,
|
actualErr = nsMutex.statusBlockedToRunning(param, testCases[0].lockOrigin,
|
||||||
testCases[0].opsID, testCases[0].readLock)
|
testCases[0].opsID, testCases[0].readLock)
|
||||||
|
|
||||||
if actualErr != errLockNotInitialized {
|
if errorCause(actualErr) != errLockNotInitialized {
|
||||||
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", errLockNotInitialized, actualErr)
|
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", errLockNotInitialized, actualErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +356,7 @@ func TestNsLockMapStatusBlockedToRunning(t *testing.T) {
|
|||||||
testCases[0].opsID, testCases[0].readLock)
|
testCases[0].opsID, testCases[0].readLock)
|
||||||
|
|
||||||
expectedOpsErr := LockInfoOpsIDNotFound{testCases[0].volume, testCases[0].path, testCases[0].opsID}
|
expectedOpsErr := LockInfoOpsIDNotFound{testCases[0].volume, testCases[0].path, testCases[0].opsID}
|
||||||
if actualErr != expectedOpsErr {
|
if errorCause(actualErr) != expectedOpsErr {
|
||||||
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", expectedOpsErr, actualErr)
|
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", expectedOpsErr, actualErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,7 +381,7 @@ func TestNsLockMapStatusBlockedToRunning(t *testing.T) {
|
|||||||
testCases[0].opsID, testCases[0].readLock)
|
testCases[0].opsID, testCases[0].readLock)
|
||||||
|
|
||||||
expectedBlockErr := LockInfoStateNotBlocked{testCases[0].volume, testCases[0].path, testCases[0].opsID}
|
expectedBlockErr := LockInfoStateNotBlocked{testCases[0].volume, testCases[0].path, testCases[0].opsID}
|
||||||
if actualErr != expectedBlockErr {
|
if errorCause(actualErr) != expectedBlockErr {
|
||||||
t.Fatalf("Errors mismatch: Expected: \"%s\", got: \"%s\"", expectedBlockErr, actualErr)
|
t.Fatalf("Errors mismatch: Expected: \"%s\", got: \"%s\"", expectedBlockErr, actualErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,7 +402,7 @@ func TestNsLockMapStatusBlockedToRunning(t *testing.T) {
|
|||||||
}
|
}
|
||||||
// invoking the method under test.
|
// invoking the method under test.
|
||||||
actualErr = nsMutex.statusBlockedToRunning(param, testCase.lockOrigin, testCase.opsID, testCase.readLock)
|
actualErr = nsMutex.statusBlockedToRunning(param, testCase.lockOrigin, testCase.opsID, testCase.readLock)
|
||||||
if actualErr != testCase.expectedErr {
|
if errorCause(actualErr) != testCase.expectedErr {
|
||||||
t.Fatalf("Test %d: Errors mismatch: Expected: \"%s\", got: \"%s\"", i+1, testCase.expectedErr, actualErr)
|
t.Fatalf("Test %d: Errors mismatch: Expected: \"%s\", got: \"%s\"", i+1, testCase.expectedErr, actualErr)
|
||||||
}
|
}
|
||||||
// In case of no error proceed with validating the lock state information.
|
// In case of no error proceed with validating the lock state information.
|
||||||
@ -520,8 +520,8 @@ func TestNsLockMapStatusNoneToBlocked(t *testing.T) {
|
|||||||
actualErr := nsMutex.statusBlockedToRunning(param, testCases[0].lockOrigin,
|
actualErr := nsMutex.statusBlockedToRunning(param, testCases[0].lockOrigin,
|
||||||
testCases[0].opsID, testCases[0].readLock)
|
testCases[0].opsID, testCases[0].readLock)
|
||||||
|
|
||||||
expectedErr := LockInfoVolPathMssing{testCases[0].volume, testCases[0].path}
|
expectedErr := LockInfoVolPathMissing{testCases[0].volume, testCases[0].path}
|
||||||
if actualErr != expectedErr {
|
if errorCause(actualErr) != expectedErr {
|
||||||
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", expectedErr, actualErr)
|
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", expectedErr, actualErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,8 +564,8 @@ func TestNsLockMapDeleteLockInfoEntryForOps(t *testing.T) {
|
|||||||
|
|
||||||
actualErr := nsMutex.deleteLockInfoEntryForOps(param, testCases[0].opsID)
|
actualErr := nsMutex.deleteLockInfoEntryForOps(param, testCases[0].opsID)
|
||||||
|
|
||||||
expectedErr := LockInfoVolPathMssing{testCases[0].volume, testCases[0].path}
|
expectedErr := LockInfoVolPathMissing{testCases[0].volume, testCases[0].path}
|
||||||
if actualErr != expectedErr {
|
if errorCause(actualErr) != expectedErr {
|
||||||
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", expectedErr, actualErr)
|
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", expectedErr, actualErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,7 +584,7 @@ func TestNsLockMapDeleteLockInfoEntryForOps(t *testing.T) {
|
|||||||
actualErr = nsMutex.deleteLockInfoEntryForOps(param, "non-existent-OpsID")
|
actualErr = nsMutex.deleteLockInfoEntryForOps(param, "non-existent-OpsID")
|
||||||
|
|
||||||
expectedOpsIDErr := LockInfoOpsIDNotFound{param.volume, param.path, "non-existent-OpsID"}
|
expectedOpsIDErr := LockInfoOpsIDNotFound{param.volume, param.path, "non-existent-OpsID"}
|
||||||
if actualErr != expectedOpsIDErr {
|
if errorCause(actualErr) != expectedOpsIDErr {
|
||||||
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", expectedOpsIDErr, actualErr)
|
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", expectedOpsIDErr, actualErr)
|
||||||
}
|
}
|
||||||
// case - 4.
|
// case - 4.
|
||||||
@ -647,8 +647,8 @@ func TestNsLockMapDeleteLockInfoEntryForVolumePath(t *testing.T) {
|
|||||||
// Set the status of the lock to blocked and then to running.
|
// Set the status of the lock to blocked and then to running.
|
||||||
param := nsParam{testCases[0].volume, testCases[0].path}
|
param := nsParam{testCases[0].volume, testCases[0].path}
|
||||||
actualErr := nsMutex.deleteLockInfoEntryForVolumePath(param)
|
actualErr := nsMutex.deleteLockInfoEntryForVolumePath(param)
|
||||||
expectedNilErr := LockInfoVolPathMssing{param.volume, param.path}
|
expectedNilErr := LockInfoVolPathMissing{param.volume, param.path}
|
||||||
if actualErr != expectedNilErr {
|
if errorCause(actualErr) != expectedNilErr {
|
||||||
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", expectedNilErr, actualErr)
|
t.Fatalf("Errors mismatch: Expected \"%s\", got \"%s\"", expectedNilErr, actualErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user