github.com/minio/madmin-go@v1.7.5/top-commands.go (about)

     1  //
     2  // MinIO Object Storage (c) 2021 MinIO, Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //      http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package madmin
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"io/ioutil"
    23  	"net/http"
    24  	"net/url"
    25  	"strconv"
    26  	"strings"
    27  	"time"
    28  )
    29  
    30  // LockEntry holds information about client requesting the lock,
    31  // servers holding the lock, source on the client machine,
    32  // ID, type(read or write) and time stamp.
    33  type LockEntry struct {
    34  	Timestamp  time.Time     `json:"time"`       // When the lock was first granted
    35  	Elapsed    time.Duration `json:"elapsed"`    // Duration for which lock has been held
    36  	Resource   string        `json:"resource"`   // Resource contains info like bucket+object
    37  	Type       string        `json:"type"`       // Type indicates if 'Write' or 'Read' lock
    38  	Source     string        `json:"source"`     // Source at which lock was granted
    39  	ServerList []string      `json:"serverlist"` // List of servers participating in the lock.
    40  	Owner      string        `json:"owner"`      // Owner UUID indicates server owns the lock.
    41  	ID         string        `json:"id"`         // UID to uniquely identify request of client.
    42  	// Represents quorum number of servers required to hold this lock, used to look for stale locks.
    43  	Quorum int `json:"quorum"`
    44  }
    45  
    46  // LockEntries - To sort the locks
    47  type LockEntries []LockEntry
    48  
    49  func (l LockEntries) Len() int {
    50  	return len(l)
    51  }
    52  
    53  func (l LockEntries) Less(i, j int) bool {
    54  	return l[i].Timestamp.Before(l[j].Timestamp)
    55  }
    56  
    57  func (l LockEntries) Swap(i, j int) {
    58  	l[i], l[j] = l[j], l[i]
    59  }
    60  
    61  // TopLockOpts top lock options
    62  type TopLockOpts struct {
    63  	Count int
    64  	Stale bool
    65  }
    66  
    67  // ForceUnlock force unlocks input paths...
    68  func (adm *AdminClient) ForceUnlock(ctx context.Context, paths ...string) error {
    69  	// Execute POST on /minio/admin/v3/force-unlock
    70  	queryVals := make(url.Values)
    71  	queryVals.Set("paths", strings.Join(paths, ","))
    72  	resp, err := adm.executeMethod(ctx,
    73  		http.MethodPost,
    74  		requestData{
    75  			relPath:     adminAPIPrefix + "/force-unlock",
    76  			queryValues: queryVals,
    77  		},
    78  	)
    79  	defer closeResponse(resp)
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	if resp.StatusCode != http.StatusOK {
    85  		return httpRespToErrorResponse(resp)
    86  	}
    87  
    88  	return nil
    89  }
    90  
    91  // TopLocksWithOpts - returns the count number of oldest locks currently active on the server.
    92  // additionally we can also enable `stale` to get stale locks currently present on server.
    93  func (adm *AdminClient) TopLocksWithOpts(ctx context.Context, opts TopLockOpts) (LockEntries, error) {
    94  	// Execute GET on /minio/admin/v3/top/locks?count=10
    95  	// to get the 'count' number of oldest locks currently
    96  	// active on the server.
    97  	queryVals := make(url.Values)
    98  	queryVals.Set("count", strconv.Itoa(opts.Count))
    99  	queryVals.Set("stale", strconv.FormatBool(opts.Stale))
   100  	resp, err := adm.executeMethod(ctx,
   101  		http.MethodGet,
   102  		requestData{
   103  			relPath:     adminAPIPrefix + "/top/locks",
   104  			queryValues: queryVals,
   105  		},
   106  	)
   107  	defer closeResponse(resp)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	if resp.StatusCode != http.StatusOK {
   113  		return nil, httpRespToErrorResponse(resp)
   114  	}
   115  
   116  	response, err := ioutil.ReadAll(resp.Body)
   117  	if err != nil {
   118  		return LockEntries{}, err
   119  	}
   120  
   121  	var lockEntries LockEntries
   122  	err = json.Unmarshal(response, &lockEntries)
   123  	return lockEntries, err
   124  }
   125  
   126  // TopLocks - returns top '10' oldest locks currently active on the server.
   127  func (adm *AdminClient) TopLocks(ctx context.Context) (LockEntries, error) {
   128  	return adm.TopLocksWithOpts(ctx, TopLockOpts{Count: 10})
   129  }