diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index 5fdfbd47e..d2998c580 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -36,14 +36,14 @@ type mgmtQueryKey string // Only valid query params for list/clear locks management APIs. const ( - mgmtBucket mgmtQueryKey = "bucket" - mgmtObject mgmtQueryKey = "object" - mgmtPrefix mgmtQueryKey = "prefix" - mgmtOlderThan mgmtQueryKey = "older-than" - mgmtDelimiter mgmtQueryKey = "delimiter" - mgmtMarker mgmtQueryKey = "marker" - mgmtMaxKey mgmtQueryKey = "max-key" - mgmtDryRun mgmtQueryKey = "dry-run" + mgmtBucket mgmtQueryKey = "bucket" + mgmtObject mgmtQueryKey = "object" + mgmtPrefix mgmtQueryKey = "prefix" + mgmtLockDuration mgmtQueryKey = "duration" + mgmtDelimiter mgmtQueryKey = "delimiter" + mgmtMarker mgmtQueryKey = "marker" + mgmtMaxKey mgmtQueryKey = "max-key" + mgmtDryRun mgmtQueryKey = "dry-run" ) // ServerVersion - server version @@ -185,7 +185,7 @@ func (adminAPI adminAPIHandlers) ServiceCredentialsHandler(w http.ResponseWriter func validateLockQueryParams(vars url.Values) (string, string, time.Duration, APIErrorCode) { bucket := vars.Get(string(mgmtBucket)) prefix := vars.Get(string(mgmtPrefix)) - relTimeStr := vars.Get(string(mgmtOlderThan)) + durationStr := vars.Get(string(mgmtLockDuration)) // N B empty bucket name is invalid if !IsValidBucketName(bucket) { @@ -198,24 +198,24 @@ func validateLockQueryParams(vars url.Values) (string, string, time.Duration, AP // If older-than parameter was empty then set it to 0s to list // all locks older than now. - if relTimeStr == "" { - relTimeStr = "0s" + if durationStr == "" { + durationStr = "0s" } - relTime, err := time.ParseDuration(relTimeStr) + duration, err := time.ParseDuration(durationStr) if err != nil { errorIf(err, "Failed to parse duration passed as query value.") return "", "", time.Duration(0), ErrInvalidDuration } - return bucket, prefix, relTime, ErrNone + return bucket, prefix, duration, ErrNone } -// ListLocksHandler - GET /?lock&bucket=mybucket&prefix=myprefix&older-than=rel_time +// ListLocksHandler - GET /?lock&bucket=mybucket&prefix=myprefix&duration=duration // - bucket is a mandatory query parameter // - prefix and older-than are optional query parameters // HTTP header x-minio-operation: list // --------- -// Lists locks held on a given bucket, prefix and relative time. +// Lists locks held on a given bucket, prefix and duration it was held for. func (adminAPI adminAPIHandlers) ListLocksHandler(w http.ResponseWriter, r *http.Request) { adminAPIErr := checkRequestAuthType(r, "", "", "") if adminAPIErr != ErrNone { @@ -224,15 +224,15 @@ func (adminAPI adminAPIHandlers) ListLocksHandler(w http.ResponseWriter, r *http } vars := r.URL.Query() - bucket, prefix, relTime, adminAPIErr := validateLockQueryParams(vars) + bucket, prefix, duration, adminAPIErr := validateLockQueryParams(vars) if adminAPIErr != ErrNone { writeErrorResponse(w, adminAPIErr, r.URL) return } // Fetch lock information of locks matching bucket/prefix that - // are available since relTime. - volLocks, err := listPeerLocksInfo(globalAdminPeers, bucket, prefix, relTime) + // are available for longer than duration. + volLocks, err := listPeerLocksInfo(globalAdminPeers, bucket, prefix, duration) if err != nil { writeErrorResponse(w, ErrInternalError, r.URL) errorIf(err, "Failed to fetch lock information from remote nodes.") @@ -248,16 +248,16 @@ func (adminAPI adminAPIHandlers) ListLocksHandler(w http.ResponseWriter, r *http } // Reply with list of locks held on bucket, matching prefix - // older than relTime supplied, as json. + // held longer than duration supplied, as json. writeSuccessResponseJSON(w, jsonBytes) } -// ClearLocksHandler - POST /?lock&bucket=mybucket&prefix=myprefix&older-than=relTime +// ClearLocksHandler - POST /?lock&bucket=mybucket&prefix=myprefix&duration=duration // - bucket is a mandatory query parameter // - prefix and older-than are optional query parameters // HTTP header x-minio-operation: clear // --------- -// Clear locks held on a given bucket, prefix and relative time. +// Clear locks held on a given bucket, prefix and duration it was held for. func (adminAPI adminAPIHandlers) ClearLocksHandler(w http.ResponseWriter, r *http.Request) { adminAPIErr := checkRequestAuthType(r, "", "", "") if adminAPIErr != ErrNone { @@ -266,15 +266,15 @@ func (adminAPI adminAPIHandlers) ClearLocksHandler(w http.ResponseWriter, r *htt } vars := r.URL.Query() - bucket, prefix, relTime, adminAPIErr := validateLockQueryParams(vars) + bucket, prefix, duration, adminAPIErr := validateLockQueryParams(vars) if adminAPIErr != ErrNone { writeErrorResponse(w, adminAPIErr, r.URL) return } // Fetch lock information of locks matching bucket/prefix that - // are available since relTime. - volLocks, err := listPeerLocksInfo(globalAdminPeers, bucket, prefix, relTime) + // are held for longer than duration. + volLocks, err := listPeerLocksInfo(globalAdminPeers, bucket, prefix, duration) if err != nil { writeErrorResponse(w, ErrInternalError, r.URL) errorIf(err, "Failed to fetch lock information from remote nodes.") @@ -289,7 +289,7 @@ func (adminAPI adminAPIHandlers) ClearLocksHandler(w http.ResponseWriter, r *htt return } - // Remove lock matching bucket/prefix older than relTime. + // Remove lock matching bucket/prefix held longer than duration. for _, volLock := range volLocks { globalNSMutex.ForceUnlock(volLock.Bucket, volLock.Object) } diff --git a/cmd/admin-handlers_test.go b/cmd/admin-handlers_test.go index dea04ef70..0a8a6c96f 100644 --- a/cmd/admin-handlers_test.go +++ b/cmd/admin-handlers_test.go @@ -334,12 +334,12 @@ func TestServiceSetCreds(t *testing.T) { } // mkLockQueryVal - helper function to build lock query param. -func mkLockQueryVal(bucket, prefix, relTimeStr string) url.Values { +func mkLockQueryVal(bucket, prefix, durationStr string) url.Values { qVal := url.Values{} qVal.Set("lock", "") qVal.Set(string(mgmtBucket), bucket) qVal.Set(string(mgmtPrefix), prefix) - qVal.Set(string(mgmtOlderThan), relTimeStr) + qVal.Set(string(mgmtLockDuration), durationStr) return qVal } @@ -364,41 +364,41 @@ func TestListLocksHandler(t *testing.T) { testCases := []struct { bucket string prefix string - relTime string + duration string expectedStatus int }{ // Test 1 - valid testcase { bucket: "mybucket", prefix: "myobject", - relTime: "1s", + duration: "1s", expectedStatus: http.StatusOK, }, // Test 2 - invalid duration { bucket: "mybucket", prefix: "myprefix", - relTime: "invalidDuration", + duration: "invalidDuration", expectedStatus: http.StatusBadRequest, }, // Test 3 - invalid bucket name { bucket: `invalid\\Bucket`, prefix: "myprefix", - relTime: "1h", + duration: "1h", expectedStatus: http.StatusBadRequest, }, // Test 4 - invalid prefix { bucket: "mybucket", prefix: `invalid\\Prefix`, - relTime: "1h", + duration: "1h", expectedStatus: http.StatusBadRequest, }, } for i, test := range testCases { - queryVal := mkLockQueryVal(test.bucket, test.prefix, test.relTime) + queryVal := mkLockQueryVal(test.bucket, test.prefix, test.duration) req, err := newTestRequest("GET", "/?"+queryVal.Encode(), 0, nil) if err != nil { t.Fatalf("Test %d - Failed to construct list locks request - %v", i+1, err) @@ -436,41 +436,41 @@ func TestClearLocksHandler(t *testing.T) { testCases := []struct { bucket string prefix string - relTime string + duration string expectedStatus int }{ // Test 1 - valid testcase { bucket: "mybucket", prefix: "myobject", - relTime: "1s", + duration: "1s", expectedStatus: http.StatusOK, }, // Test 2 - invalid duration { bucket: "mybucket", prefix: "myprefix", - relTime: "invalidDuration", + duration: "invalidDuration", expectedStatus: http.StatusBadRequest, }, // Test 3 - invalid bucket name { bucket: `invalid\\Bucket`, prefix: "myprefix", - relTime: "1h", + duration: "1h", expectedStatus: http.StatusBadRequest, }, // Test 4 - invalid prefix { bucket: "mybucket", prefix: `invalid\\Prefix`, - relTime: "1h", + duration: "1h", expectedStatus: http.StatusBadRequest, }, } for i, test := range testCases { - queryVal := mkLockQueryVal(test.bucket, test.prefix, test.relTime) + queryVal := mkLockQueryVal(test.bucket, test.prefix, test.duration) req, err := newTestRequest("POST", "/?"+queryVal.Encode(), 0, nil) if err != nil { t.Fatalf("Test %d - Failed to construct clear locks request - %v", i+1, err) diff --git a/cmd/admin-rpc-client.go b/cmd/admin-rpc-client.go index 5f22e6177..b963cbd6a 100644 --- a/cmd/admin-rpc-client.go +++ b/cmd/admin-rpc-client.go @@ -37,7 +37,7 @@ type remoteAdminClient struct { // commands like service stop and service restart. type adminCmdRunner interface { Restart() error - ListLocks(bucket, prefix string, relTime time.Duration) ([]VolumeLockInfo, error) + ListLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) ReInitDisks() error } @@ -49,8 +49,8 @@ func (lc localAdminClient) Restart() error { } // ListLocks - Fetches lock information from local lock instrumentation. -func (lc localAdminClient) ListLocks(bucket, prefix string, relTime time.Duration) ([]VolumeLockInfo, error) { - return listLocksInfo(bucket, prefix, relTime), nil +func (lc localAdminClient) ListLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) { + return listLocksInfo(bucket, prefix, duration), nil } // Restart - Sends restart command to remote server via RPC. @@ -61,11 +61,11 @@ func (rc remoteAdminClient) Restart() error { } // ListLocks - Sends list locks command to remote server via RPC. -func (rc remoteAdminClient) ListLocks(bucket, prefix string, relTime time.Duration) ([]VolumeLockInfo, error) { +func (rc remoteAdminClient) ListLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) { listArgs := ListLocksQuery{ - bucket: bucket, - prefix: prefix, - relTime: relTime, + bucket: bucket, + prefix: prefix, + duration: duration, } var reply ListLocksReply if err := rc.Call("Admin.ListLocks", &listArgs, &reply); err != nil { @@ -175,8 +175,8 @@ func sendServiceCmd(cps adminPeers, cmd serviceSignal) { } // listPeerLocksInfo - fetch list of locks held on the given bucket, -// matching prefix older than relTime from all peer servers. -func listPeerLocksInfo(peers adminPeers, bucket, prefix string, relTime time.Duration) ([]VolumeLockInfo, error) { +// matching prefix held longer than duration from all peer servers. +func listPeerLocksInfo(peers adminPeers, bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) { // Used to aggregate volume lock information from all nodes. allLocks := make([][]VolumeLockInfo, len(peers)) errs := make([]error, len(peers)) @@ -188,11 +188,11 @@ func listPeerLocksInfo(peers adminPeers, bucket, prefix string, relTime time.Dur go func(idx int, remotePeer adminPeer) { defer wg.Done() // `remotePeers` is right-shifted by one position relative to `peers` - allLocks[idx], errs[idx] = remotePeer.cmdRunner.ListLocks(bucket, prefix, relTime) + allLocks[idx], errs[idx] = remotePeer.cmdRunner.ListLocks(bucket, prefix, duration) }(i+1, remotePeer) } wg.Wait() - allLocks[0], errs[0] = localPeer.cmdRunner.ListLocks(bucket, prefix, relTime) + allLocks[0], errs[0] = localPeer.cmdRunner.ListLocks(bucket, prefix, duration) // Summarizing errors received for ListLocks RPC across all // nodes. N B the possible unavailability of quorum in errors diff --git a/cmd/admin-rpc-server.go b/cmd/admin-rpc-server.go index 470082fde..fa5d5e781 100644 --- a/cmd/admin-rpc-server.go +++ b/cmd/admin-rpc-server.go @@ -37,9 +37,9 @@ type adminCmd struct { // ListLocksQuery - wraps ListLocks API's query values to send over RPC. type ListLocksQuery struct { AuthRPCArgs - bucket string - prefix string - relTime time.Duration + bucket string + prefix string + duration time.Duration } // ListLocksReply - wraps ListLocks response over RPC. @@ -63,7 +63,7 @@ func (s *adminCmd) ListLocks(query *ListLocksQuery, reply *ListLocksReply) error if err := query.IsAuthenticated(); err != nil { return err } - volLocks := listLocksInfo(query.bucket, query.prefix, query.relTime) + volLocks := listLocksInfo(query.bucket, query.prefix, query.duration) *reply = ListLocksReply{volLocks: volLocks} return nil } diff --git a/cmd/api-errors.go b/cmd/api-errors.go index ed7529560..6ac5e7f06 100644 --- a/cmd/api-errors.go +++ b/cmd/api-errors.go @@ -483,7 +483,7 @@ var errorCodeResponse = map[APIErrorCode]APIError{ }, ErrInvalidDuration: { Code: "InvalidDuration", - Description: "Relative duration provided in the request is invalid.", + Description: "Duration provided in the request is invalid.", HTTPStatusCode: http.StatusBadRequest, }, diff --git a/cmd/lockinfo-handlers.go b/cmd/lockinfo-handlers.go index 9fd98a65f..3a9e093f9 100644 --- a/cmd/lockinfo-handlers.go +++ b/cmd/lockinfo-handlers.go @@ -68,8 +68,8 @@ type OpsLockState struct { Duration time.Duration `json:"duration"` // Duration since the lock was held. } -// listLocksInfo - Fetches locks held on bucket, matching prefix older than relTime. -func listLocksInfo(bucket, prefix string, relTime time.Duration) []VolumeLockInfo { +// listLocksInfo - Fetches locks held on bucket, matching prefix held for longer than duration. +func listLocksInfo(bucket, prefix string, duration time.Duration) []VolumeLockInfo { globalNSMutex.lockMapMutex.Lock() defer globalNSMutex.lockMapMutex.Unlock() @@ -95,11 +95,12 @@ func listLocksInfo(bucket, prefix string, relTime time.Duration) []VolumeLockInf } // Filter locks that are held on bucket, prefix. for opsID, lockInfo := range debugLock.lockInfo { + // filter locks that were held for longer than duration. elapsed := timeNow.Sub(lockInfo.since) - if elapsed < relTime { + if elapsed < duration { continue } - // Add locks that are older than relTime. + // Add locks that are held for longer than duration. volLockInfo.LockDetailsOnObject = append(volLockInfo.LockDetailsOnObject, OpsLockState{ OperationID: opsID, diff --git a/cmd/lockinfo-handlers_test.go b/cmd/lockinfo-handlers_test.go index 78c969151..ebb0f23d5 100644 --- a/cmd/lockinfo-handlers_test.go +++ b/cmd/lockinfo-handlers_test.go @@ -45,34 +45,34 @@ func TestListLocksInfo(t *testing.T) { testCases := []struct { bucket string prefix string - relTime time.Duration + duration time.Duration numLocks int }{ // Test 1 - Matches all the locks acquired above. { bucket: "bucket1", prefix: "prefix1", - relTime: time.Duration(0 * time.Second), + duration: time.Duration(0 * time.Second), numLocks: 20, }, // Test 2 - Bucket doesn't match. { bucket: "bucket", prefix: "prefix1", - relTime: time.Duration(0 * time.Second), + duration: time.Duration(0 * time.Second), numLocks: 0, }, // Test 3 - Prefix doesn't match. { bucket: "bucket1", prefix: "prefix11", - relTime: time.Duration(0 * time.Second), + duration: time.Duration(0 * time.Second), numLocks: 0, }, } for i, test := range testCases { - actual := listLocksInfo(test.bucket, test.prefix, test.relTime) + actual := listLocksInfo(test.bucket, test.prefix, test.duration) if len(actual) != test.numLocks { t.Errorf("Test %d - Expected %d locks but observed %d locks", i+1, test.numLocks, len(actual)) diff --git a/docs/admin-api/README.md b/docs/admin-api/README.md index 90f38b848..c8a045528 100644 --- a/docs/admin-api/README.md +++ b/docs/admin-api/README.md @@ -66,9 +66,9 @@ ### Lock Management APIs * ListLocks - - GET /?lock&bucket=mybucket&prefix=myprefix&older-than=rel_time + - GET /?lock&bucket=mybucket&prefix=myprefix&duration=duration - x-minio-operation: list - - Response: On success 200, json encoded response containing all locks held, older than rel_time. e.g, older than 3 hours. + - Response: On success 200, json encoded response containing all locks held, for longer than duration. - Possible error responses - ErrInvalidBucketName @@ -95,7 +95,7 @@ - ErrInvalidDuration InvalidDuration - Relative duration provided in the request is invalid. + Duration provided in the request is invalid. / @@ -105,9 +105,9 @@ * ClearLocks - - POST /?lock&bucket=mybucket&prefix=myprefix&older-than=rel_time + - POST /?lock&bucket=mybucket&prefix=myprefix&duration=duration - x-minio-operation: clear - - Response: On success 200, json encoded response containing all locks cleared, older than rel_time. e.g, older than 3 hours. + - Response: On success 200, json encoded response containing all locks cleared, for longer than duration. - Possible error responses, similar to errors listed in ListLocks. - ErrInvalidBucketName - ErrInvalidObjectName diff --git a/pkg/madmin/API.md b/pkg/madmin/API.md index 5d588db51..36c79b1a2 100644 --- a/pkg/madmin/API.md +++ b/pkg/madmin/API.md @@ -120,8 +120,8 @@ If successful restarts the running minio service, for distributed setup restarts ``` -### ListLocks(bucket, prefix string, olderThan time.Duration) ([]VolumeLockInfo, error) -If successful returns information on the list of locks held on ``bucket`` matching ``prefix`` older than ``olderThan`` seconds. +### ListLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) +If successful returns information on the list of locks held on ``bucket`` matching ``prefix`` for longer than ``duration`` seconds. __Example__ @@ -135,8 +135,8 @@ __Example__ ``` -### ClearLocks(bucket, prefix string, olderThan time.Duration) ([]VolumeLockInfo, error) -If successful returns information on the list of locks cleared on ``bucket`` matching ``prefix`` older than ``olderThan`` seconds. +### ClearLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) +If successful returns information on the list of locks cleared on ``bucket`` matching ``prefix`` for longer than ``duration`` seconds. __Example__ diff --git a/pkg/madmin/examples/lock-clear.go b/pkg/madmin/examples/lock-clear.go index 2f7a30de4..15fb2bfdf 100644 --- a/pkg/madmin/examples/lock-clear.go +++ b/pkg/madmin/examples/lock-clear.go @@ -37,7 +37,7 @@ func main() { log.Fatalln(err) } - // Clear locks held on mybucket/myprefix older than olderThan seconds. + // Clear locks held on mybucket/myprefix for longer than 30s. olderThan := time.Duration(30 * time.Second) locksCleared, err := madmClnt.ClearLocks("mybucket", "myprefix", olderThan) if err != nil { diff --git a/pkg/madmin/examples/lock-list.go b/pkg/madmin/examples/lock-list.go index bc1e9ff08..88023f4b4 100644 --- a/pkg/madmin/examples/lock-list.go +++ b/pkg/madmin/examples/lock-list.go @@ -37,7 +37,7 @@ func main() { log.Fatalln(err) } - // List locks held on mybucket/myprefix older than 30s. + // List locks held on mybucket/myprefix for longer than 30s. locksHeld, err := madmClnt.ListLocks("mybucket", "myprefix", time.Duration(30*time.Second)) if err != nil { log.Fatalln(err)