mirror of https://github.com/minio/minio.git
				
				
				
			allow more than N number of locks in TopLocks (#9883)
This commit is contained in:
		
							parent
							
								
									67062840c1
								
							
						
					
					
						commit
						b8cb21c954
					
				|  | @ -1,5 +1,5 @@ | ||||||
| /* | /* | ||||||
|  * MinIO Cloud Storage, (C) 2016-2019 MinIO, Inc. |  * MinIO Cloud Storage, (C) 2016-2020 MinIO, Inc. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
|  | @ -328,7 +328,7 @@ func (a adminAPIHandlers) DataUsageInfoHandler(w http.ResponseWriter, r *http.Re | ||||||
| 	writeSuccessResponseJSON(w, dataUsageInfoJSON) | 	writeSuccessResponseJSON(w, dataUsageInfoJSON) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func newLockEntry(l lockRequesterInfo, resource, server string) *madmin.LockEntry { | func lriToLockEntry(l lockRequesterInfo, resource, server string) *madmin.LockEntry { | ||||||
| 	entry := &madmin.LockEntry{ | 	entry := &madmin.LockEntry{ | ||||||
| 		Timestamp:  l.Timestamp, | 		Timestamp:  l.Timestamp, | ||||||
| 		Resource:   resource, | 		Resource:   resource, | ||||||
|  | @ -337,14 +337,14 @@ func newLockEntry(l lockRequesterInfo, resource, server string) *madmin.LockEntr | ||||||
| 		ID:         l.UID, | 		ID:         l.UID, | ||||||
| 	} | 	} | ||||||
| 	if l.Writer { | 	if l.Writer { | ||||||
| 		entry.Type = "Write" | 		entry.Type = "WRITE" | ||||||
| 	} else { | 	} else { | ||||||
| 		entry.Type = "Read" | 		entry.Type = "READ" | ||||||
| 	} | 	} | ||||||
| 	return entry | 	return entry | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func topLockEntries(peerLocks []*PeerLocks) madmin.LockEntries { | func topLockEntries(peerLocks []*PeerLocks, count int) madmin.LockEntries { | ||||||
| 	entryMap := make(map[string]*madmin.LockEntry) | 	entryMap := make(map[string]*madmin.LockEntry) | ||||||
| 	for _, peerLock := range peerLocks { | 	for _, peerLock := range peerLocks { | ||||||
| 		if peerLock == nil { | 		if peerLock == nil { | ||||||
|  | @ -356,20 +356,19 @@ func topLockEntries(peerLocks []*PeerLocks) madmin.LockEntries { | ||||||
| 					if val, ok := entryMap[lockReqInfo.UID]; ok { | 					if val, ok := entryMap[lockReqInfo.UID]; ok { | ||||||
| 						val.ServerList = append(val.ServerList, peerLock.Addr) | 						val.ServerList = append(val.ServerList, peerLock.Addr) | ||||||
| 					} else { | 					} else { | ||||||
| 						entryMap[lockReqInfo.UID] = newLockEntry(lockReqInfo, k, peerLock.Addr) | 						entryMap[lockReqInfo.UID] = lriToLockEntry(lockReqInfo, k, peerLock.Addr) | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	var lockEntries = make(madmin.LockEntries, 0) | 	var lockEntries = make(madmin.LockEntries, 0, len(entryMap)) | ||||||
| 	for _, v := range entryMap { | 	for _, v := range entryMap { | ||||||
| 		lockEntries = append(lockEntries, *v) | 		lockEntries = append(lockEntries, *v) | ||||||
| 	} | 	} | ||||||
| 	sort.Sort(lockEntries) | 	sort.Sort(lockEntries) | ||||||
| 	const listCount int = 10 | 	if len(lockEntries) > count { | ||||||
| 	if len(lockEntries) > listCount { | 		lockEntries = lockEntries[:count] | ||||||
| 		lockEntries = lockEntries[:listCount] |  | ||||||
| 	} | 	} | ||||||
| 	return lockEntries | 	return lockEntries | ||||||
| } | } | ||||||
|  | @ -391,6 +390,16 @@ func (a adminAPIHandlers) TopLocksHandler(w http.ResponseWriter, r *http.Request | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	count := 10 // by default list only top 10 entries
 | ||||||
|  | 	if countStr := r.URL.Query().Get("count"); countStr != "" { | ||||||
|  | 		var err error | ||||||
|  | 		count, err = strconv.Atoi(countStr) | ||||||
|  | 		if err != nil { | ||||||
|  | 			writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	peerLocks := globalNotificationSys.GetLocks(ctx) | 	peerLocks := globalNotificationSys.GetLocks(ctx) | ||||||
| 	// Once we have received all the locks currently used from peers
 | 	// Once we have received all the locks currently used from peers
 | ||||||
| 	// add the local peer locks list as well.
 | 	// add the local peer locks list as well.
 | ||||||
|  | @ -398,12 +407,13 @@ func (a adminAPIHandlers) TopLocksHandler(w http.ResponseWriter, r *http.Request | ||||||
| 	for _, llocker := range globalLockServers { | 	for _, llocker := range globalLockServers { | ||||||
| 		getRespLocks = append(getRespLocks, llocker.DupLockMap()) | 		getRespLocks = append(getRespLocks, llocker.DupLockMap()) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	peerLocks = append(peerLocks, &PeerLocks{ | 	peerLocks = append(peerLocks, &PeerLocks{ | ||||||
| 		Addr:  getHostName(r), | 		Addr:  getHostName(r), | ||||||
| 		Locks: getRespLocks, | 		Locks: getRespLocks, | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	topLocks := topLockEntries(peerLocks) | 	topLocks := topLockEntries(peerLocks, count) | ||||||
| 
 | 
 | ||||||
| 	// Marshal API response
 | 	// Marshal API response
 | ||||||
| 	jsonBytes, err := json.Marshal(topLocks) | 	jsonBytes, err := json.Marshal(topLocks) | ||||||
|  |  | ||||||
|  | @ -22,6 +22,8 @@ import ( | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | 	"net/url" | ||||||
|  | 	"strconv" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -29,12 +31,11 @@ import ( | ||||||
| // servers holding the lock, source on the client machine,
 | // servers holding the lock, source on the client machine,
 | ||||||
| // ID, type(read or write) and time stamp.
 | // ID, type(read or write) and time stamp.
 | ||||||
| type LockEntry struct { | type LockEntry struct { | ||||||
| 	Timestamp  time.Time `json:"time"`       // Timestamp set at the time of initialization.
 | 	Timestamp  time.Time `json:"time"`       // When the lock was first granted
 | ||||||
| 	Resource   string    `json:"resource"`   // Resource contains info like bucket, object etc
 | 	Resource   string    `json:"resource"`   // Resource contains info like bucket+object
 | ||||||
| 	Type       string    `json:"type"`       // Bool whether write or read lock.
 | 	Type       string    `json:"type"`       // Type indicates if 'Write' or 'Read' lock
 | ||||||
| 	Source     string    `json:"source"`     // Source which created the lock
 | 	Source     string    `json:"source"`     // Source at which lock was granted
 | ||||||
| 	ServerList []string  `json:"serverlist"` // RPC path of servers issuing the lock.
 | 	ServerList []string  `json:"serverlist"` // List of servers participating in the lock.
 | ||||||
| 	Owner      string    `json:"owner"`      // RPC path of client claiming lock.
 |  | ||||||
| 	ID         string    `json:"id"`         // UID to uniquely identify request of client.
 | 	ID         string    `json:"id"`         // UID to uniquely identify request of client.
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -53,13 +54,19 @@ func (l LockEntries) Swap(i, j int) { | ||||||
| 	l[i], l[j] = l[j], l[i] | 	l[i], l[j] = l[j], l[i] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // TopLocks - returns the oldest locks in a minio setup.
 | // TopNLocks - returns the count number of oldest locks currently active on the server.
 | ||||||
| func (adm *AdminClient) TopLocks(ctx context.Context) (LockEntries, error) { | func (adm *AdminClient) TopNLocks(ctx context.Context, count int) (LockEntries, error) { | ||||||
| 	// Execute GET on /minio/admin/v3/top/locks
 | 	// Execute GET on /minio/admin/v3/top/locks?count=10
 | ||||||
| 	// to get the oldest locks in a minio setup.
 | 	// to get the 'count' number of oldest locks currently
 | ||||||
|  | 	// active on the server.
 | ||||||
|  | 	queryVals := make(url.Values) | ||||||
|  | 	queryVals.Set("count", strconv.Itoa(count)) | ||||||
| 	resp, err := adm.executeMethod(ctx, | 	resp, err := adm.executeMethod(ctx, | ||||||
| 		http.MethodGet, | 		http.MethodGet, | ||||||
| 		requestData{relPath: adminAPIPrefix + "/top/locks"}, | 		requestData{ | ||||||
|  | 			relPath:     adminAPIPrefix + "/top/locks", | ||||||
|  | 			queryValues: queryVals, | ||||||
|  | 		}, | ||||||
| 	) | 	) | ||||||
| 	defer closeResponse(resp) | 	defer closeResponse(resp) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | @ -79,3 +86,8 @@ func (adm *AdminClient) TopLocks(ctx context.Context) (LockEntries, error) { | ||||||
| 	err = json.Unmarshal(response, &lockEntries) | 	err = json.Unmarshal(response, &lockEntries) | ||||||
| 	return lockEntries, err | 	return lockEntries, err | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // TopLocks - returns top '10' oldest locks currently active on the server.
 | ||||||
|  | func (adm *AdminClient) TopLocks(ctx context.Context) (LockEntries, error) { | ||||||
|  | 	return adm.TopNLocks(ctx, 10) | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue