storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/madmin/top-commands.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2019 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  
    18  package madmin
    19  
    20  import (
    21  	"context"
    22  	"encoding/json"
    23  	"io/ioutil"
    24  	"net/http"
    25  	"net/url"
    26  	"strconv"
    27  	"strings"
    28  	"time"
    29  )
    30  
    31  // LockEntry holds information about client requesting the lock,
    32  // servers holding the lock, source on the client machine,
    33  // ID, type(read or write) and time stamp.
    34  type LockEntry struct {
    35  	Timestamp  time.Time `json:"time"`       // When the lock was first granted
    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  }