/* * Minio Cloud Storage, (C) 2016 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package madmin import ( "encoding/json" "io" "io/ioutil" "net/http" "net/url" "time" ) type statusType string type lockType string // OpsLockState - represents lock specific details. type OpsLockState struct { OperationID string `json:"id"` // String containing operation ID. LockSource string `json:"source"` // Operation type (GetObject, PutObject...) LockType lockType `json:"type"` // Lock type (RLock, WLock) Status statusType `json:"status"` // Status can be Running/Ready/Blocked. Since time.Time `json:"since"` // Time when the lock was initially held. } // VolumeLockInfo - represents summary and individual lock details of all // locks held on a given bucket, object. type VolumeLockInfo struct { Bucket string `json:"bucket"` Object string `json:"object"` // All locks blocked + running for given pair. LocksOnObject int64 `json:"-"` // Count of operations which has successfully acquired the lock // but hasn't unlocked yet( operation in progress). LocksAcquiredOnObject int64 `json:"-"` // Count of operations which are blocked waiting for the lock // to be released. TotalBlockedLocks int64 `json:"-"` // Count of all read locks TotalReadLocks int64 `json:"readLocks"` // Count of all write locks TotalWriteLocks int64 `json:"writeLocks"` // State information containing state of the locks for all operations // on given pair. LockDetailsOnObject []OpsLockState `json:"lockOwners"` } // getLockInfos - unmarshal []VolumeLockInfo from a reader. func getLockInfos(body io.Reader) ([]VolumeLockInfo, error) { respBytes, err := ioutil.ReadAll(body) if err != nil { return nil, err } var lockInfos []VolumeLockInfo err = json.Unmarshal(respBytes, &lockInfos) if err != nil { return nil, err } return lockInfos, nil } // ListLocks - Calls List Locks Management API to fetch locks matching // bucket, prefix and held before the duration supplied. func (adm *AdminClient) ListLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) { queryVal := make(url.Values) queryVal.Set("lock", "") queryVal.Set("bucket", bucket) queryVal.Set("prefix", prefix) queryVal.Set("duration", duration.String()) hdrs := make(http.Header) hdrs.Set(minioAdminOpHeader, "list") reqData := requestData{ queryValues: queryVal, customHeaders: hdrs, } // Execute GET on /?lock to list locks. resp, err := adm.executeMethod("GET", reqData) defer closeResponse(resp) if err != nil { return nil, err } if resp.StatusCode != http.StatusOK { return nil, httpRespToErrorResponse(resp) } return getLockInfos(resp.Body) } // ClearLocks - Calls Clear Locks Management API to clear locks held // on bucket, matching prefix older than duration supplied. func (adm *AdminClient) ClearLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) { queryVal := make(url.Values) queryVal.Set("lock", "") queryVal.Set("bucket", bucket) queryVal.Set("prefix", prefix) queryVal.Set("duration", duration.String()) hdrs := make(http.Header) hdrs.Set(minioAdminOpHeader, "clear") reqData := requestData{ queryValues: queryVal, customHeaders: hdrs, } // Execute POST on /?lock to clear locks. resp, err := adm.executeMethod("POST", reqData) defer closeResponse(resp) if err != nil { return nil, err } if resp.StatusCode != http.StatusOK { return nil, httpRespToErrorResponse(resp) } return getLockInfos(resp.Body) }