| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | // Copyright (c) 2015-2023 MinIO, Inc.
 | 
					
						
							| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | // This file is part of MinIO Object Storage stack
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2024-01-20 10:27:58 +08:00
										 |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2018-03-16 04:27:16 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2023-07-07 22:47:38 +08:00
										 |  |  | 	"math/rand" | 
					
						
							| 
									
										
										
										
											2020-09-26 10:21:52 +08:00
										 |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | 	"net/url" | 
					
						
							| 
									
										
										
										
											2024-01-23 04:16:36 +08:00
										 |  |  | 	"runtime" | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | 	"github.com/cespare/xxhash/v2" | 
					
						
							| 
									
										
										
										
											2019-09-26 14:08:24 +08:00
										 |  |  | 	"github.com/klauspost/compress/zip" | 
					
						
							| 
									
										
										
										
											2023-06-20 08:53:08 +08:00
										 |  |  | 	"github.com/minio/madmin-go/v3" | 
					
						
							| 
									
										
										
										
											2024-01-29 02:04:17 +08:00
										 |  |  | 	xioutil "github.com/minio/minio/internal/ioutil" | 
					
						
							| 
									
										
										
										
											2024-05-25 07:05:23 +08:00
										 |  |  | 	xnet "github.com/minio/pkg/v3/net" | 
					
						
							|  |  |  | 	"github.com/minio/pkg/v3/sync/errgroup" | 
					
						
							|  |  |  | 	"github.com/minio/pkg/v3/workers" | 
					
						
							| 
									
										
										
										
											2023-11-28 14:41:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/minio/minio/internal/bucket/bandwidth" | 
					
						
							|  |  |  | 	"github.com/minio/minio/internal/logger" | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-24 21:42:36 +08:00
										 |  |  | // This file contains peer related notifications. For sending notifications to
 | 
					
						
							|  |  |  | // external systems, see event-notification.go
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | // NotificationSys - notification system.
 | 
					
						
							|  |  |  | type NotificationSys struct { | 
					
						
							| 
									
										
										
										
											2022-08-24 21:42:36 +08:00
										 |  |  | 	peerClients    []*peerRESTClient // Excludes self
 | 
					
						
							|  |  |  | 	allPeerClients []*peerRESTClient // Includes nil client for self
 | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 02:25:38 +08:00
										 |  |  | // NotificationPeerErr returns error associated for a remote peer.
 | 
					
						
							|  |  |  | type NotificationPeerErr struct { | 
					
						
							|  |  |  | 	Host xnet.Host // Remote host on which the rpc call was initiated
 | 
					
						
							|  |  |  | 	Err  error     // Error returned by the remote peer for an rpc call
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | // A NotificationGroup is a collection of goroutines working on subtasks that are part of
 | 
					
						
							|  |  |  | // the same overall task.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // A zero NotificationGroup is valid and does not cancel on error.
 | 
					
						
							|  |  |  | type NotificationGroup struct { | 
					
						
							| 
									
										
										
										
											2024-01-23 04:16:36 +08:00
										 |  |  | 	workers    *workers.Workers | 
					
						
							| 
									
										
										
										
											2023-03-08 00:13:28 +08:00
										 |  |  | 	errs       []NotificationPeerErr | 
					
						
							|  |  |  | 	retryCount int | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // WithNPeers returns a new NotificationGroup with length of errs slice upto nerrs,
 | 
					
						
							|  |  |  | // upon Wait() errors are returned collected from all tasks.
 | 
					
						
							|  |  |  | func WithNPeers(nerrs int) *NotificationGroup { | 
					
						
							| 
									
										
										
										
											2024-01-23 04:16:36 +08:00
										 |  |  | 	if nerrs <= 0 { | 
					
						
							|  |  |  | 		nerrs = 1 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wk, _ := workers.New(nerrs) | 
					
						
							|  |  |  | 	return &NotificationGroup{errs: make([]NotificationPeerErr, nerrs), workers: wk, retryCount: 3} | 
					
						
							| 
									
										
										
										
											2023-03-08 00:13:28 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-27 00:40:13 +08:00
										 |  |  | // WithNPeersThrottled returns a new NotificationGroup with length of errs slice upto nerrs,
 | 
					
						
							|  |  |  | // upon Wait() errors are returned collected from all tasks, optionally allows for X workers
 | 
					
						
							|  |  |  | // only "per" parallel task.
 | 
					
						
							|  |  |  | func WithNPeersThrottled(nerrs, wks int) *NotificationGroup { | 
					
						
							|  |  |  | 	if nerrs <= 0 { | 
					
						
							|  |  |  | 		nerrs = 1 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-08-15 18:36:00 +08:00
										 |  |  | 	if wks > nerrs { | 
					
						
							|  |  |  | 		wks = nerrs | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-01-27 00:40:13 +08:00
										 |  |  | 	wk, _ := workers.New(wks) | 
					
						
							|  |  |  | 	return &NotificationGroup{errs: make([]NotificationPeerErr, nerrs), workers: wk, retryCount: 3} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 00:13:28 +08:00
										 |  |  | // WithRetries sets the retry count for all function calls from the Go method.
 | 
					
						
							|  |  |  | func (g *NotificationGroup) WithRetries(retryCount int) *NotificationGroup { | 
					
						
							|  |  |  | 	if g != nil { | 
					
						
							|  |  |  | 		g.retryCount = retryCount | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return g | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Wait blocks until all function calls from the Go method have returned, then
 | 
					
						
							|  |  |  | // returns the slice of errors from all function calls.
 | 
					
						
							|  |  |  | func (g *NotificationGroup) Wait() []NotificationPeerErr { | 
					
						
							| 
									
										
										
										
											2024-01-23 04:16:36 +08:00
										 |  |  | 	g.workers.Wait() | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 	return g.errs | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Go calls the given function in a new goroutine.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // The first call to return a non-nil error will be
 | 
					
						
							|  |  |  | // collected in errs slice and returned by Wait().
 | 
					
						
							|  |  |  | func (g *NotificationGroup) Go(ctx context.Context, f func() error, index int, addr xnet.Host) { | 
					
						
							| 
									
										
										
										
											2023-07-07 22:47:38 +08:00
										 |  |  | 	r := rand.New(rand.NewSource(time.Now().UnixNano())) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-23 04:16:36 +08:00
										 |  |  | 	g.workers.Take() | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	go func() { | 
					
						
							| 
									
										
										
										
											2024-01-23 04:16:36 +08:00
										 |  |  | 		defer g.workers.Give() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 		g.errs[index] = NotificationPeerErr{ | 
					
						
							|  |  |  | 			Host: addr, | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		retryCount := g.retryCount | 
					
						
							| 
									
										
										
										
											2025-05-27 23:19:03 +08:00
										 |  |  | 		for i := range retryCount { | 
					
						
							| 
									
										
										
										
											2023-11-28 14:41:03 +08:00
										 |  |  | 			g.errs[index].Err = nil | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 			if err := f(); err != nil { | 
					
						
							|  |  |  | 				g.errs[index].Err = err | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				if contextCanceled(ctx) { | 
					
						
							|  |  |  | 					// context already canceled no retries.
 | 
					
						
							|  |  |  | 					retryCount = 0 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 				// Last iteration log the error.
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 				if i == retryCount-1 { | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 					reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", addr.String()) | 
					
						
							|  |  |  | 					ctx := logger.SetReqInfo(ctx, reqInfo) | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 					peersLogOnceIf(ctx, err, addr.String()) | 
					
						
							| 
									
										
										
										
											2018-12-19 06:39:21 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-07 22:47:38 +08:00
										 |  |  | 				// Wait for a minimum of 100ms and dynamically increase this based on number of attempts.
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 				if i < retryCount-1 { | 
					
						
							| 
									
										
										
										
											2023-07-07 22:47:38 +08:00
										 |  |  | 					time.Sleep(100*time.Millisecond + time.Duration(r.Float64()*float64(time.Second))) | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 					continue | 
					
						
							| 
									
										
										
										
											2018-12-19 06:39:21 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-12-19 06:39:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | // DeletePolicy - deletes policy across all peers.
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | func (sys *NotificationSys) DeletePolicy(ctx context.Context, policyName string) []NotificationPeerErr { | 
					
						
							| 
									
										
										
										
											2023-03-08 00:13:28 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)).WithRetries(1) | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 		ng.Go(ctx, func() error { | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 			if client == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			return client.DeletePolicy(ctx, policyName) | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // LoadPolicy - reloads a specific modified policy across all peers
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | func (sys *NotificationSys) LoadPolicy(ctx context.Context, policyName string) []NotificationPeerErr { | 
					
						
							| 
									
										
										
										
											2023-03-08 00:13:28 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)).WithRetries(1) | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 		ng.Go(ctx, func() error { | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 			if client == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			return client.LoadPolicy(ctx, policyName) | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | // LoadPolicyMapping - reloads a policy mapping across all peers
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | func (sys *NotificationSys) LoadPolicyMapping(ctx context.Context, userOrGroup string, userType IAMUserType, isGroup bool) []NotificationPeerErr { | 
					
						
							| 
									
										
										
										
											2023-03-08 00:13:28 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)).WithRetries(1) | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 		ng.Go(ctx, func() error { | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 			if client == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			return client.LoadPolicyMapping(ctx, userOrGroup, userType, isGroup) | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | // DeleteUser - deletes a specific user across all peers
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | func (sys *NotificationSys) DeleteUser(ctx context.Context, accessKey string) []NotificationPeerErr { | 
					
						
							| 
									
										
										
										
											2023-03-08 00:13:28 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)).WithRetries(1) | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 		ng.Go(ctx, func() error { | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 			if client == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			return client.DeleteUser(ctx, accessKey) | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // LoadUser - reloads a specific user across all peers
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | func (sys *NotificationSys) LoadUser(ctx context.Context, accessKey string, temp bool) []NotificationPeerErr { | 
					
						
							| 
									
										
										
										
											2023-03-08 00:13:28 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)).WithRetries(1) | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 		ng.Go(ctx, func() error { | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 			if client == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			return client.LoadUser(ctx, accessKey, temp) | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | // LoadGroup - loads a specific group on all peers.
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | func (sys *NotificationSys) LoadGroup(ctx context.Context, group string) []NotificationPeerErr { | 
					
						
							| 
									
										
										
										
											2023-03-08 00:13:28 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)).WithRetries(1) | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 		ng.Go(ctx, func() error { | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 			if client == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			return client.LoadGroup(ctx, group) | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | // DeleteServiceAccount - deletes a specific service account across all peers
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | func (sys *NotificationSys) DeleteServiceAccount(ctx context.Context, accessKey string) []NotificationPeerErr { | 
					
						
							| 
									
										
										
										
											2023-03-08 00:13:28 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)).WithRetries(1) | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 		ng.Go(ctx, func() error { | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 			if client == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			return client.DeleteServiceAccount(ctx, accessKey) | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // LoadServiceAccount - reloads a specific service account across all peers
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | func (sys *NotificationSys) LoadServiceAccount(ctx context.Context, accessKey string) []NotificationPeerErr { | 
					
						
							| 
									
										
										
										
											2023-03-08 00:13:28 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)).WithRetries(1) | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 		ng.Go(ctx, func() error { | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 			if client == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			return client.LoadServiceAccount(ctx, accessKey) | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-26 07:42:24 +08:00
										 |  |  | // BackgroundHealStatus - returns background heal status of all peers
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | func (sys *NotificationSys) BackgroundHealStatus(ctx context.Context) ([]madmin.BgHealState, []NotificationPeerErr) { | 
					
						
							| 
									
										
										
										
											2020-08-08 04:22:53 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2019-06-26 07:42:24 +08:00
										 |  |  | 	states := make([]madmin.BgHealState, len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							| 
									
										
										
										
											2020-08-08 10:43:06 +08:00
										 |  |  | 		idx := idx | 
					
						
							| 
									
										
										
										
											2020-08-08 04:22:53 +08:00
										 |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 		ng.Go(ctx, func() error { | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 			if client == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			st, err := client.BackgroundHealStatus(ctx) | 
					
						
							| 
									
										
										
										
											2020-08-08 04:22:53 +08:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-06-26 07:42:24 +08:00
										 |  |  | 			states[idx] = st | 
					
						
							| 
									
										
										
										
											2020-08-08 04:22:53 +08:00
										 |  |  | 			return nil | 
					
						
							|  |  |  | 		}, idx, *client.host) | 
					
						
							| 
									
										
										
										
											2019-06-26 07:42:24 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-08 04:22:53 +08:00
										 |  |  | 	return states, ng.Wait() | 
					
						
							| 
									
										
										
										
											2019-06-26 07:42:24 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | // StartProfiling - start profiling on remote peers, by initiating a remote RPC.
 | 
					
						
							| 
									
										
										
										
											2024-08-15 18:36:00 +08:00
										 |  |  | func (sys *NotificationSys) StartProfiling(ctx context.Context, profiler string) []NotificationPeerErr { | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2024-08-15 18:36:00 +08:00
										 |  |  | 		ng.Go(ctx, func() error { | 
					
						
							|  |  |  | 			return client.StartProfiling(ctx, profiler) | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // DownloadProfilingData - download profiling data from all remote peers.
 | 
					
						
							| 
									
										
										
										
											2022-07-26 00:11:35 +08:00
										 |  |  | func (sys *NotificationSys) DownloadProfilingData(ctx context.Context, writer io.Writer) (profilingDataFound bool) { | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 	// Initialize a zip writer which will provide a zipped content
 | 
					
						
							|  |  |  | 	// of profiling data of all nodes
 | 
					
						
							|  |  |  | 	zipWriter := zip.NewWriter(writer) | 
					
						
							|  |  |  | 	defer zipWriter.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-15 18:36:00 +08:00
										 |  |  | 	// Start by embedding cluster info.
 | 
					
						
							|  |  |  | 	if b := getClusterMetaInfo(ctx); len(b) > 0 { | 
					
						
							|  |  |  | 		internalLogIf(ctx, embedFileInZip(zipWriter, "cluster.info", b, 0o600)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Profiles can be quite big, so we limit to max 16 concurrent downloads.
 | 
					
						
							|  |  |  | 	ng := WithNPeersThrottled(len(sys.peerClients), 16) | 
					
						
							|  |  |  | 	var writeMu sync.Mutex | 
					
						
							|  |  |  | 	for i, client := range sys.peerClients { | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-08-15 18:36:00 +08:00
										 |  |  | 		ng.Go(ctx, func() error { | 
					
						
							|  |  |  | 			// Give 15 seconds to each remote call.
 | 
					
						
							|  |  |  | 			// Errors are logged but not returned.
 | 
					
						
							|  |  |  | 			ctx, cancel := context.WithTimeout(ctx, 15*time.Second) | 
					
						
							|  |  |  | 			defer cancel() | 
					
						
							|  |  |  | 			data, err := client.DownloadProfileData(ctx) | 
					
						
							| 
									
										
										
										
											2022-07-26 00:11:35 +08:00
										 |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2020-01-11 09:19:58 +08:00
										 |  |  | 				reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", client.host.String()) | 
					
						
							|  |  |  | 				ctx := logger.SetReqInfo(ctx, reqInfo) | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 				peersLogOnceIf(ctx, err, client.host.String()) | 
					
						
							| 
									
										
										
										
											2024-08-15 18:36:00 +08:00
										 |  |  | 				return nil | 
					
						
							| 
									
										
										
										
											2020-01-11 09:19:58 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-08-15 18:36:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			for typ, data := range data { | 
					
						
							|  |  |  | 				// zip writer only handles one concurrent write
 | 
					
						
							|  |  |  | 				writeMu.Lock() | 
					
						
							|  |  |  | 				profilingDataFound = true | 
					
						
							|  |  |  | 				err := embedFileInZip(zipWriter, fmt.Sprintf("profile-%s-%s", client.host.String(), typ), data, 0o600) | 
					
						
							|  |  |  | 				writeMu.Unlock() | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", client.host.String()) | 
					
						
							|  |  |  | 					ctx := logger.SetReqInfo(ctx, reqInfo) | 
					
						
							|  |  |  | 					peersLogOnceIf(ctx, err, client.host.String()) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}, i, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ng.Wait() | 
					
						
							|  |  |  | 	if ctx.Err() != nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-11 09:19:58 +08:00
										 |  |  | 	// Local host
 | 
					
						
							| 
									
										
										
										
											2021-03-27 02:37:58 +08:00
										 |  |  | 	thisAddr, err := xnet.ParseHost(globalLocalNodeName) | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 		bugLogIf(ctx, err) | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 		return profilingDataFound | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data, err := getProfileData() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", thisAddr.String()) | 
					
						
							|  |  |  | 		ctx := logger.SetReqInfo(ctx, reqInfo) | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 		bugLogIf(ctx, err) | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 		return profilingDataFound | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	profilingDataFound = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Send profiling data to zip as file
 | 
					
						
							| 
									
										
										
										
											2020-01-11 09:19:58 +08:00
										 |  |  | 	for typ, data := range data { | 
					
						
							| 
									
										
										
										
											2023-09-07 00:24:01 +08:00
										 |  |  | 		err := embedFileInZip(zipWriter, fmt.Sprintf("profile-%s-%s", thisAddr, typ), data, 0o600) | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 		internalLogIf(ctx, err) | 
					
						
							| 
									
										
										
										
											2022-11-03 04:36:38 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-26 00:11:35 +08:00
										 |  |  | 	return | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-29 23:34:30 +08:00
										 |  |  | // VerifyBinary - asks remote peers to verify the checksum
 | 
					
						
							| 
									
										
										
										
											2024-01-20 10:27:58 +08:00
										 |  |  | func (sys *NotificationSys) VerifyBinary(ctx context.Context, u *url.URL, sha256Sum []byte, releaseInfo string, bin []byte) []NotificationPeerErr { | 
					
						
							| 
									
										
										
										
											2024-01-23 04:16:36 +08:00
										 |  |  | 	// FIXME: network calls made in this manner such as one goroutine per node,
 | 
					
						
							|  |  |  | 	// can easily eat into the internode bandwidth. This function would be mostly
 | 
					
						
							|  |  |  | 	// TX saturating, however there are situations where a RX might also saturate.
 | 
					
						
							|  |  |  | 	// To avoid these problems we must split the work at scale. With 1000 node
 | 
					
						
							|  |  |  | 	// setup becoming a reality we must try to shard the work properly such as
 | 
					
						
							|  |  |  | 	// pick 10 nodes that precisely can send those 100 requests the first node
 | 
					
						
							|  |  |  | 	// in the 10 node shard would coordinate between other 9 shards to get the
 | 
					
						
							|  |  |  | 	// rest of the `99*9` requests.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// This essentially splits the workload properly and also allows for network
 | 
					
						
							|  |  |  | 	// utilization to be optimal, instead of blindly throttling the way we are
 | 
					
						
							|  |  |  | 	// doing below. However the changes that are needed here are a bit involved,
 | 
					
						
							|  |  |  | 	// further discussion advised. Remove this comment and remove the worker model
 | 
					
						
							|  |  |  | 	// for this function in future.
 | 
					
						
							|  |  |  | 	maxWorkers := runtime.GOMAXPROCS(0) / 2 | 
					
						
							| 
									
										
										
										
											2024-01-27 00:40:13 +08:00
										 |  |  | 	ng := WithNPeersThrottled(len(sys.peerClients), maxWorkers) | 
					
						
							| 
									
										
										
										
											2019-08-29 06:04:43 +08:00
										 |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2020-07-23 23:03:31 +08:00
										 |  |  | 		ng.Go(ctx, func() error { | 
					
						
							| 
									
										
										
										
											2024-01-20 10:27:58 +08:00
										 |  |  | 			return client.VerifyBinary(ctx, u, sha256Sum, releaseInfo, bytes.NewReader(bin)) | 
					
						
							| 
									
										
										
										
											2022-07-26 08:49:47 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // CommitBinary - asks remote peers to overwrite the old binary with the new one
 | 
					
						
							|  |  |  | func (sys *NotificationSys) CommitBinary(ctx context.Context) []NotificationPeerErr { | 
					
						
							|  |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		client := client | 
					
						
							|  |  |  | 		ng.Go(ctx, func() error { | 
					
						
							|  |  |  | 			return client.CommitBinary(ctx) | 
					
						
							| 
									
										
										
										
											2019-08-29 06:04:43 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-17 07:10:51 +08:00
										 |  |  | // SignalConfigReload reloads requested sub-system on a remote peer dynamically.
 | 
					
						
							|  |  |  | func (sys *NotificationSys) SignalConfigReload(subSys string) []NotificationPeerErr { | 
					
						
							|  |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		client := client | 
					
						
							|  |  |  | 		ng.Go(GlobalContext, func() error { | 
					
						
							| 
									
										
										
										
											2024-06-20 22:49:22 +08:00
										 |  |  | 			return client.SignalService(serviceReloadDynamic, subSys, false, nil) | 
					
						
							| 
									
										
										
										
											2022-05-17 07:10:51 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | // SignalService - calls signal service RPC call on all peers.
 | 
					
						
							|  |  |  | func (sys *NotificationSys) SignalService(sig serviceSignal) []NotificationPeerErr { | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2020-04-10 00:30:02 +08:00
										 |  |  | 		ng.Go(GlobalContext, func() error { | 
					
						
							| 
									
										
										
										
											2024-01-20 06:22:36 +08:00
										 |  |  | 			// force == true preserves the current behavior
 | 
					
						
							| 
									
										
										
										
											2024-06-20 22:49:22 +08:00
										 |  |  | 			return client.SignalService(sig, "", false, nil) | 
					
						
							| 
									
										
										
										
											2024-01-20 06:22:36 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SignalServiceV2 - calls signal service RPC call on all peers with v2 API
 | 
					
						
							| 
									
										
										
										
											2024-06-20 22:49:22 +08:00
										 |  |  | func (sys *NotificationSys) SignalServiceV2(sig serviceSignal, dryRun bool, execAt *time.Time) []NotificationPeerErr { | 
					
						
							| 
									
										
										
										
											2024-01-20 06:22:36 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		client := client | 
					
						
							|  |  |  | 		ng.Go(GlobalContext, func() error { | 
					
						
							| 
									
										
										
										
											2024-06-20 22:49:22 +08:00
										 |  |  | 			return client.SignalService(sig, "", dryRun, execAt) | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							| 
									
										
										
										
											2019-01-14 14:44:20 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return ng.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | var errPeerNotReachable = errors.New("peer is not reachable") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 23:22:14 +08:00
										 |  |  | // GetLocks - makes GetLocks RPC call on all peers.
 | 
					
						
							| 
									
										
										
										
											2020-09-26 10:21:52 +08:00
										 |  |  | func (sys *NotificationSys) GetLocks(ctx context.Context, r *http.Request) []*PeerLocks { | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	locksResp := make([]*PeerLocks, len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2019-10-15 00:44:51 +08:00
										 |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	for index, client := range sys.peerClients { | 
					
						
							| 
									
										
										
										
											2019-10-15 00:44:51 +08:00
										 |  |  | 		index := index | 
					
						
							| 
									
										
										
										
											2024-02-09 04:28:05 +08:00
										 |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2019-10-15 00:44:51 +08:00
										 |  |  | 		g.Go(func() error { | 
					
						
							| 
									
										
										
										
											2020-09-26 10:21:52 +08:00
										 |  |  | 			if client == nil { | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 				return errPeerNotReachable | 
					
						
							| 
									
										
										
										
											2020-09-26 10:21:52 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			serverLocksResp, err := sys.peerClients[index].GetLocks(ctx) | 
					
						
							| 
									
										
										
										
											2020-09-26 10:21:52 +08:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			locksResp[index] = &PeerLocks{ | 
					
						
							|  |  |  | 				Addr:  sys.peerClients[index].host.String(), | 
					
						
							|  |  |  | 				Locks: serverLocksResp, | 
					
						
							| 
									
										
										
										
											2019-01-24 23:22:14 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-10-15 00:44:51 +08:00
										 |  |  | 			return nil | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", | 
					
						
							|  |  |  | 			sys.peerClients[index].host.String()) | 
					
						
							|  |  |  | 		ctx := logger.SetReqInfo(ctx, reqInfo) | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 		peersLogOnceIf(ctx, err, sys.peerClients[index].host.String()) | 
					
						
							| 
									
										
										
										
											2019-01-24 23:22:14 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-09-26 10:21:52 +08:00
										 |  |  | 	locksResp = append(locksResp, &PeerLocks{ | 
					
						
							|  |  |  | 		Addr:  getHostName(r), | 
					
						
							| 
									
										
										
										
											2020-12-10 23:28:37 +08:00
										 |  |  | 		Locks: globalLockServer.DupLockMap(), | 
					
						
							| 
									
										
										
										
											2020-09-26 10:21:52 +08:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2019-01-24 23:22:14 +08:00
										 |  |  | 	return locksResp | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | // LoadBucketMetadata - calls LoadBucketMetadata call on all peers
 | 
					
						
							|  |  |  | func (sys *NotificationSys) LoadBucketMetadata(ctx context.Context, bucketName string) { | 
					
						
							|  |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 		client := client | 
					
						
							|  |  |  | 		ng.Go(ctx, func() error { | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			return client.LoadBucketMetadata(ctx, bucketName) | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, nErr := range ng.Wait() { | 
					
						
							|  |  |  | 		reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", nErr.Host.String()) | 
					
						
							|  |  |  | 		if nErr.Err != nil { | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 			peersLogOnceIf(logger.SetReqInfo(ctx, reqInfo), nErr.Err, nErr.Host.String()) | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | // DeleteBucketMetadata - calls DeleteBucketMetadata call on all peers
 | 
					
						
							|  |  |  | func (sys *NotificationSys) DeleteBucketMetadata(ctx context.Context, bucketName string) { | 
					
						
							| 
									
										
										
										
											2024-08-15 20:04:40 +08:00
										 |  |  | 	globalReplicationStats.Load().Delete(bucketName) | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	globalBucketMetadataSys.Remove(bucketName) | 
					
						
							| 
									
										
										
										
											2021-06-24 23:39:58 +08:00
										 |  |  | 	globalBucketTargetSys.Delete(bucketName) | 
					
						
							| 
									
										
										
										
											2022-08-24 21:42:36 +08:00
										 |  |  | 	globalEventNotifier.RemoveNotification(bucketName) | 
					
						
							| 
									
										
										
										
											2022-06-15 06:14:24 +08:00
										 |  |  | 	globalBucketConnStats.delete(bucketName) | 
					
						
							| 
									
										
										
										
											2023-06-22 00:41:59 +08:00
										 |  |  | 	globalBucketHTTPStats.delete(bucketName) | 
					
						
							| 
									
										
										
										
											2020-11-01 00:46:18 +08:00
										 |  |  | 	if localMetacacheMgr != nil { | 
					
						
							|  |  |  | 		localMetacacheMgr.deleteBucketCache(bucketName) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-05 17:42:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2020-02-05 17:42:34 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 		client := client | 
					
						
							|  |  |  | 		ng.Go(ctx, func() error { | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			return client.DeleteBucketMetadata(ctx, bucketName) | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, nErr := range ng.Wait() { | 
					
						
							|  |  |  | 		reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", nErr.Host.String()) | 
					
						
							|  |  |  | 		if nErr.Err != nil { | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 			peersLogOnceIf(logger.SetReqInfo(ctx, reqInfo), nErr.Err, nErr.Host.String()) | 
					
						
							| 
									
										
										
										
											2018-05-10 06:11:51 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-24 00:15:30 +08:00
										 |  |  | // GetClusterAllBucketStats - returns bucket stats for all buckets from all remote peers.
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetClusterAllBucketStats(ctx context.Context) []BucketStatsMap { | 
					
						
							| 
									
										
										
										
											2023-03-08 00:13:28 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)).WithRetries(1) | 
					
						
							| 
									
										
										
										
											2022-05-24 00:15:30 +08:00
										 |  |  | 	replicationStats := make([]BucketStatsMap, len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		client := client | 
					
						
							|  |  |  | 		ng.Go(ctx, func() error { | 
					
						
							|  |  |  | 			if client == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			bsMap, err := client.GetAllBucketStats(ctx) | 
					
						
							| 
									
										
										
										
											2022-05-24 00:15:30 +08:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			replicationStats[index] = bsMap | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}, index, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, nErr := range ng.Wait() { | 
					
						
							|  |  |  | 		reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", nErr.Host.String()) | 
					
						
							|  |  |  | 		if nErr.Err != nil { | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 			peersLogOnceIf(logger.SetReqInfo(ctx, reqInfo), nErr.Err, nErr.Host.String()) | 
					
						
							| 
									
										
										
										
											2022-05-24 00:15:30 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-15 20:04:40 +08:00
										 |  |  | 	replicationStatsList := globalReplicationStats.Load().GetAll() | 
					
						
							| 
									
										
										
										
											2022-09-13 03:40:02 +08:00
										 |  |  | 	bucketStatsMap := BucketStatsMap{ | 
					
						
							|  |  |  | 		Stats:     make(map[string]BucketStats, len(replicationStatsList)), | 
					
						
							|  |  |  | 		Timestamp: UTCNow(), | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-05-24 00:15:30 +08:00
										 |  |  | 	for k, replicationStats := range replicationStatsList { | 
					
						
							| 
									
										
										
										
											2022-09-13 03:40:02 +08:00
										 |  |  | 		bucketStatsMap.Stats[k] = BucketStats{ | 
					
						
							| 
									
										
										
										
											2022-05-24 00:15:30 +08:00
										 |  |  | 			ReplicationStats: replicationStats, | 
					
						
							| 
									
										
										
										
											2024-08-15 20:04:40 +08:00
										 |  |  | 			ProxyStats:       globalReplicationStats.Load().getProxyStats(k), | 
					
						
							| 
									
										
										
										
											2022-05-24 00:15:30 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-13 03:40:02 +08:00
										 |  |  | 	replicationStats = append(replicationStats, bucketStatsMap) | 
					
						
							| 
									
										
										
										
											2022-05-24 00:15:30 +08:00
										 |  |  | 	return replicationStats | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | // GetClusterBucketStats - calls GetClusterBucketStats call on all peers for a cluster statistics view.
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetClusterBucketStats(ctx context.Context, bucketName string) []BucketStats { | 
					
						
							| 
									
										
										
										
											2023-03-08 00:13:28 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)).WithRetries(1) | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 	bucketStats := make([]BucketStats, len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		index := index | 
					
						
							| 
									
										
										
										
											2021-04-06 23:36:54 +08:00
										 |  |  | 		client := client | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 		ng.Go(ctx, func() error { | 
					
						
							|  |  |  | 			if client == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			bs, err := client.GetBucketStats(ctx, bucketName) | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			bucketStats[index] = bs | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}, index, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, nErr := range ng.Wait() { | 
					
						
							|  |  |  | 		reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", nErr.Host.String()) | 
					
						
							|  |  |  | 		if nErr.Err != nil { | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 			peersLogOnceIf(logger.SetReqInfo(ctx, reqInfo), nErr.Err, nErr.Host.String()) | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-08-15 20:04:40 +08:00
										 |  |  | 	if st := globalReplicationStats.Load(); st != nil { | 
					
						
							|  |  |  | 		bucketStats = append(bucketStats, BucketStats{ | 
					
						
							|  |  |  | 			ReplicationStats: st.Get(bucketName), | 
					
						
							|  |  |  | 			QueueStats:       ReplicationQueueStats{Nodes: []ReplQNodeStats{st.getNodeQueueStats(bucketName)}}, | 
					
						
							|  |  |  | 			ProxyStats:       st.getProxyStats(bucketName), | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 	return bucketStats | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-30 16:00:59 +08:00
										 |  |  | // GetClusterSiteMetrics - calls GetClusterSiteMetrics call on all peers for a cluster statistics view.
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetClusterSiteMetrics(ctx context.Context) []SRMetricsSummary { | 
					
						
							|  |  |  | 	ng := WithNPeers(len(sys.peerClients)).WithRetries(1) | 
					
						
							|  |  |  | 	siteStats := make([]SRMetricsSummary, len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		client := client | 
					
						
							|  |  |  | 		ng.Go(ctx, func() error { | 
					
						
							|  |  |  | 			if client == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			sm, err := client.GetSRMetrics(ctx) | 
					
						
							| 
									
										
										
										
											2023-08-30 16:00:59 +08:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			siteStats[index] = sm | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}, index, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, nErr := range ng.Wait() { | 
					
						
							|  |  |  | 		reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", nErr.Host.String()) | 
					
						
							|  |  |  | 		if nErr.Err != nil { | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 			peersLogOnceIf(logger.SetReqInfo(ctx, reqInfo), nErr.Err, nErr.Host.String()) | 
					
						
							| 
									
										
										
										
											2023-08-30 16:00:59 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-08-15 20:04:40 +08:00
										 |  |  | 	siteStats = append(siteStats, globalReplicationStats.Load().getSRMetricsForNode()) | 
					
						
							| 
									
										
										
										
											2023-08-30 16:00:59 +08:00
										 |  |  | 	return siteStats | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-11 01:07:49 +08:00
										 |  |  | // ReloadPoolMeta reloads on disk updates on pool metadata
 | 
					
						
							|  |  |  | func (sys *NotificationSys) ReloadPoolMeta(ctx context.Context) { | 
					
						
							|  |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		client := client | 
					
						
							|  |  |  | 		ng.Go(ctx, func() error { | 
					
						
							|  |  |  | 			return client.ReloadPoolMeta(ctx) | 
					
						
							|  |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, nErr := range ng.Wait() { | 
					
						
							|  |  |  | 		reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", nErr.Host.String()) | 
					
						
							|  |  |  | 		if nErr.Err != nil { | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 			peersLogOnceIf(logger.SetReqInfo(ctx, reqInfo), nErr.Err, nErr.Host.String()) | 
					
						
							| 
									
										
										
										
											2022-01-11 01:07:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-10 00:58:30 +08:00
										 |  |  | // DeleteUploadID notifies all the MinIO nodes to remove the
 | 
					
						
							|  |  |  | // given uploadID from cache
 | 
					
						
							|  |  |  | func (sys *NotificationSys) DeleteUploadID(ctx context.Context, uploadID string) { | 
					
						
							|  |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		client := client | 
					
						
							|  |  |  | 		ng.Go(ctx, func() error { | 
					
						
							|  |  |  | 			return client.DeleteUploadID(ctx, uploadID) | 
					
						
							|  |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, nErr := range ng.Wait() { | 
					
						
							|  |  |  | 		reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", nErr.Host.String()) | 
					
						
							|  |  |  | 		if nErr.Err != nil { | 
					
						
							|  |  |  | 			peersLogOnceIf(logger.SetReqInfo(ctx, reqInfo), nErr.Err, nErr.Host.String()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-26 03:36:57 +08:00
										 |  |  | // StopRebalance notifies all MinIO nodes to signal any ongoing rebalance
 | 
					
						
							|  |  |  | // goroutine to stop.
 | 
					
						
							|  |  |  | func (sys *NotificationSys) StopRebalance(ctx context.Context) { | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		internalLogIf(ctx, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-26 03:36:57 +08:00
										 |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		client := client | 
					
						
							|  |  |  | 		ng.Go(ctx, func() error { | 
					
						
							|  |  |  | 			return client.StopRebalance(ctx) | 
					
						
							|  |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, nErr := range ng.Wait() { | 
					
						
							|  |  |  | 		reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", nErr.Host.String()) | 
					
						
							|  |  |  | 		if nErr.Err != nil { | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 			peersLogOnceIf(logger.SetReqInfo(ctx, reqInfo), nErr.Err, nErr.Host.String()) | 
					
						
							| 
									
										
										
										
											2022-10-26 03:36:57 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-01-19 09:24:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if pools, ok := objAPI.(*erasureServerPools); ok { | 
					
						
							|  |  |  | 		pools.StopRebalance() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-10-26 03:36:57 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // LoadRebalanceMeta notifies all peers to load rebalance.bin from object layer.
 | 
					
						
							|  |  |  | // Note: Only peers participating in rebalance operation, namely the first node
 | 
					
						
							|  |  |  | // in each pool will load rebalance.bin.
 | 
					
						
							|  |  |  | func (sys *NotificationSys) LoadRebalanceMeta(ctx context.Context, startRebalance bool) { | 
					
						
							|  |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		client := client | 
					
						
							|  |  |  | 		ng.Go(ctx, func() error { | 
					
						
							|  |  |  | 			return client.LoadRebalanceMeta(ctx, startRebalance) | 
					
						
							|  |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, nErr := range ng.Wait() { | 
					
						
							|  |  |  | 		reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", nErr.Host.String()) | 
					
						
							|  |  |  | 		if nErr.Err != nil { | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 			peersLogOnceIf(logger.SetReqInfo(ctx, reqInfo), nErr.Err, nErr.Host.String()) | 
					
						
							| 
									
										
										
										
											2022-10-26 03:36:57 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | // LoadTransitionTierConfig notifies remote peers to load their remote tier
 | 
					
						
							|  |  |  | // configs from config store.
 | 
					
						
							|  |  |  | func (sys *NotificationSys) LoadTransitionTierConfig(ctx context.Context) { | 
					
						
							|  |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		client := client | 
					
						
							|  |  |  | 		ng.Go(ctx, func() error { | 
					
						
							|  |  |  | 			return client.LoadTransitionTierConfig(ctx) | 
					
						
							|  |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, nErr := range ng.Wait() { | 
					
						
							|  |  |  | 		reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", nErr.Host.String()) | 
					
						
							|  |  |  | 		if nErr.Err != nil { | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 			peersLogOnceIf(logger.SetReqInfo(ctx, reqInfo), nErr.Err, nErr.Host.String()) | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | // GetCPUs - Get all CPU information.
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetCPUs(ctx context.Context) []madmin.CPUs { | 
					
						
							|  |  |  | 	reply := make([]madmin.CPUs, len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			var err error | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 			reply[index], err = sys.peerClients[index].GetCPUs(ctx) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-13 09:58:40 +08:00
										 |  |  | 			sys.addNodeErr(&reply[index], sys.peerClients[index], err) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return reply | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-03 00:49:49 +08:00
										 |  |  | // GetNetInfo - Network information
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetNetInfo(ctx context.Context) []madmin.NetInfo { | 
					
						
							|  |  |  | 	reply := make([]madmin.NetInfo, len(sys.peerClients)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			var err error | 
					
						
							|  |  |  | 			reply[index], err = sys.peerClients[index].GetNetInfo(ctx) | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			sys.addNodeErr(&reply[index], sys.peerClients[index], err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return reply | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | // GetPartitions - Disk partition information
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetPartitions(ctx context.Context) []madmin.Partitions { | 
					
						
							|  |  |  | 	reply := make([]madmin.Partitions, len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			var err error | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 			reply[index], err = sys.peerClients[index].GetPartitions(ctx) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-13 09:58:40 +08:00
										 |  |  | 			sys.addNodeErr(&reply[index], sys.peerClients[index], err) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return reply | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | // GetOSInfo - Get operating system's information
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetOSInfo(ctx context.Context) []madmin.OSInfo { | 
					
						
							|  |  |  | 	reply := make([]madmin.OSInfo, len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			var err error | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 			reply[index], err = sys.peerClients[index].GetOSInfo(ctx) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 08:09:37 +08:00
										 |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			sys.addNodeErr(&reply[index], sys.peerClients[index], err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return reply | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | // GetMetrics - Get metrics from all peers.
 | 
					
						
							| 
									
										
										
										
											2022-10-03 17:10:15 +08:00
										 |  |  | func (sys *NotificationSys) GetMetrics(ctx context.Context, t madmin.MetricType, opts collectMetricsOpts) []madmin.RealtimeMetrics { | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 	reply := make([]madmin.RealtimeMetrics, len(sys.peerClients)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		host := client.host.String() | 
					
						
							| 
									
										
										
										
											2022-10-03 17:10:15 +08:00
										 |  |  | 		if len(opts.hosts) > 0 { | 
					
						
							|  |  |  | 			if _, ok := opts.hosts[host]; !ok { | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			var err error | 
					
						
							| 
									
										
										
										
											2022-10-03 17:10:15 +08:00
										 |  |  | 			reply[index], err = sys.peerClients[index].GetMetrics(ctx, t, opts) | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2023-10-10 08:27:11 +08:00
										 |  |  | 			reply[index].Errors = []string{fmt.Sprintf("%s: %s (rpc)", sys.peerClients[index].String(), err.Error())} | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return reply | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-01 04:40:20 +08:00
										 |  |  | // GetResourceMetrics - gets the resource metrics from all nodes excluding self.
 | 
					
						
							| 
									
										
										
										
											2024-03-10 17:15:15 +08:00
										 |  |  | func (sys *NotificationSys) GetResourceMetrics(ctx context.Context) <-chan MetricV2 { | 
					
						
							| 
									
										
										
										
											2023-10-01 04:40:20 +08:00
										 |  |  | 	if sys == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2024-03-10 17:15:15 +08:00
										 |  |  | 	peerChannels := make([]<-chan MetricV2, len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2023-10-01 04:40:20 +08:00
										 |  |  | 	for index := range sys.peerClients { | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			if sys.peerClients[index] == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			var err error | 
					
						
							|  |  |  | 			peerChannels[index], err = sys.peerClients[index].GetResourceMetrics(ctx) | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return sys.collectPeerMetrics(ctx, peerChannels, g) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 08:09:37 +08:00
										 |  |  | // GetSysConfig - Get information about system config
 | 
					
						
							|  |  |  | // (only the config that are of concern to minio)
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetSysConfig(ctx context.Context) []madmin.SysConfig { | 
					
						
							|  |  |  | 	reply := make([]madmin.SysConfig, len(sys.peerClients)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			var err error | 
					
						
							|  |  |  | 			reply[index], err = sys.peerClients[index].GetSysConfig(ctx) | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-30 14:05:34 +08:00
										 |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-13 09:58:40 +08:00
										 |  |  | 			sys.addNodeErr(&reply[index], sys.peerClients[index], err) | 
					
						
							| 
									
										
										
										
											2021-07-30 14:05:34 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return reply | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-13 09:58:40 +08:00
										 |  |  | // GetSysServices - Get information about system services
 | 
					
						
							|  |  |  | // (only the services that are of concern to minio)
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetSysServices(ctx context.Context) []madmin.SysServices { | 
					
						
							|  |  |  | 	reply := make([]madmin.SysServices, len(sys.peerClients)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			var err error | 
					
						
							|  |  |  | 			reply[index], err = sys.peerClients[index].GetSELinuxInfo(ctx) | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			sys.addNodeErr(&reply[index], sys.peerClients[index], err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return reply | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (sys *NotificationSys) addNodeErr(nodeInfo madmin.NodeInfo, peerClient *peerRESTClient, err error) { | 
					
						
							|  |  |  | 	addr := peerClient.host.String() | 
					
						
							|  |  |  | 	reqInfo := (&logger.ReqInfo{}).AppendTags("remotePeer", addr) | 
					
						
							|  |  |  | 	ctx := logger.SetReqInfo(GlobalContext, reqInfo) | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 	peersLogOnceIf(ctx, err, "add-node-err-"+addr) | 
					
						
							| 
									
										
										
										
											2021-08-13 09:58:40 +08:00
										 |  |  | 	nodeInfo.SetAddr(addr) | 
					
						
							|  |  |  | 	nodeInfo.SetError(err.Error()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-30 14:05:34 +08:00
										 |  |  | // GetSysErrors - Memory information
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetSysErrors(ctx context.Context) []madmin.SysErrors { | 
					
						
							|  |  |  | 	reply := make([]madmin.SysErrors, len(sys.peerClients)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			var err error | 
					
						
							|  |  |  | 			reply[index], err = sys.peerClients[index].GetSysErrors(ctx) | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-13 09:58:40 +08:00
										 |  |  | 			sys.addNodeErr(&reply[index], sys.peerClients[index], err) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return reply | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | // GetMemInfo - Memory information
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetMemInfo(ctx context.Context) []madmin.MemInfo { | 
					
						
							|  |  |  | 	reply := make([]madmin.MemInfo, len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			var err error | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 			reply[index], err = sys.peerClients[index].GetMemInfo(ctx) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-13 09:58:40 +08:00
										 |  |  | 			sys.addNodeErr(&reply[index], sys.peerClients[index], err) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return reply | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | // GetProcInfo - Process information
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetProcInfo(ctx context.Context) []madmin.ProcInfo { | 
					
						
							|  |  |  | 	reply := make([]madmin.ProcInfo, len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			var err error | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 			reply[index], err = sys.peerClients[index].GetProcInfo(ctx) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-16 09:02:54 +08:00
										 |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-13 09:58:40 +08:00
										 |  |  | 			sys.addNodeErr(&reply[index], sys.peerClients[index], err) | 
					
						
							| 
									
										
										
										
											2020-09-16 09:02:54 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return reply | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 00:10:02 +08:00
										 |  |  | // Construct a list of offline disks information for a given node.
 | 
					
						
							|  |  |  | // If offlineHost is empty, do it for the local disks.
 | 
					
						
							| 
									
										
										
										
											2021-03-05 02:07:05 +08:00
										 |  |  | func getOfflineDisks(offlineHost string, endpoints EndpointServerPools) []madmin.Disk { | 
					
						
							|  |  |  | 	var offlineDisks []madmin.Disk | 
					
						
							|  |  |  | 	for _, pool := range endpoints { | 
					
						
							|  |  |  | 		for _, ep := range pool.Endpoints { | 
					
						
							| 
									
										
										
										
											2023-04-25 00:10:02 +08:00
										 |  |  | 			if offlineHost == "" && ep.IsLocal || offlineHost == ep.Host { | 
					
						
							| 
									
										
										
										
											2021-03-05 02:07:05 +08:00
										 |  |  | 				offlineDisks = append(offlineDisks, madmin.Disk{ | 
					
						
							| 
									
										
										
										
											2023-12-09 00:13:04 +08:00
										 |  |  | 					Endpoint:  ep.String(), | 
					
						
							|  |  |  | 					State:     string(madmin.ItemOffline), | 
					
						
							|  |  |  | 					PoolIndex: ep.PoolIdx, | 
					
						
							|  |  |  | 					SetIndex:  ep.SetIdx, | 
					
						
							|  |  |  | 					DiskIndex: ep.DiskIdx, | 
					
						
							| 
									
										
										
										
											2021-03-05 02:07:05 +08:00
										 |  |  | 				}) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return offlineDisks | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 06:31:35 +08:00
										 |  |  | // StorageInfo returns disk information across all peers
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | func (sys *NotificationSys) StorageInfo(ctx context.Context, objLayer ObjectLayer, metrics bool) StorageInfo { | 
					
						
							| 
									
										
										
										
											2022-12-02 06:31:35 +08:00
										 |  |  | 	var storageInfo StorageInfo | 
					
						
							|  |  |  | 	replies := make([]StorageInfo, len(sys.peerClients)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var wg sync.WaitGroup | 
					
						
							|  |  |  | 	for i, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		wg.Add(1) | 
					
						
							|  |  |  | 		go func(client *peerRESTClient, idx int) { | 
					
						
							|  |  |  | 			defer wg.Done() | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			info, err := client.LocalStorageInfo(ctx, metrics) | 
					
						
							| 
									
										
										
										
											2022-12-02 06:31:35 +08:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				info.Disks = getOfflineDisks(client.host.String(), globalEndpoints) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			replies[idx] = info | 
					
						
							|  |  |  | 		}(client, i) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wg.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Add local to this server.
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 	replies = append(replies, objLayer.LocalStorageInfo(ctx, metrics)) | 
					
						
							| 
									
										
										
										
											2022-12-02 06:31:35 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	storageInfo.Backend = objLayer.BackendInfo() | 
					
						
							|  |  |  | 	for _, sinfo := range replies { | 
					
						
							|  |  |  | 		storageInfo.Disks = append(storageInfo.Disks, sinfo.Disks...) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return storageInfo | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-12 06:27:03 +08:00
										 |  |  | // ServerInfo - calls ServerInfo RPC call on all peers.
 | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | func (sys *NotificationSys) ServerInfo(ctx context.Context, metrics bool) []madmin.ServerProperties { | 
					
						
							| 
									
										
										
										
											2019-12-12 06:27:03 +08:00
										 |  |  | 	reply := make([]madmin.ServerProperties, len(sys.peerClients)) | 
					
						
							|  |  |  | 	var wg sync.WaitGroup | 
					
						
							|  |  |  | 	for i, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		wg.Add(1) | 
					
						
							|  |  |  | 		go func(client *peerRESTClient, idx int) { | 
					
						
							|  |  |  | 			defer wg.Done() | 
					
						
							| 
									
										
										
										
											2024-08-13 01:24:29 +08:00
										 |  |  | 			ctx, cancel := context.WithTimeout(ctx, 10*time.Second) | 
					
						
							|  |  |  | 			defer cancel() | 
					
						
							| 
									
										
										
										
											2024-05-16 06:19:00 +08:00
										 |  |  | 			info, err := client.ServerInfo(ctx, metrics) | 
					
						
							| 
									
										
										
										
											2019-12-12 06:27:03 +08:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				info.Endpoint = client.host.String() | 
					
						
							| 
									
										
										
										
											2021-03-03 09:28:04 +08:00
										 |  |  | 				info.State = string(madmin.ItemOffline) | 
					
						
							| 
									
										
										
										
											2021-03-05 02:07:05 +08:00
										 |  |  | 				info.Disks = getOfflineDisks(info.Endpoint, globalEndpoints) | 
					
						
							| 
									
										
										
										
											2019-12-12 06:27:03 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			reply[idx] = info | 
					
						
							|  |  |  | 		}(client, i) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wg.Wait() | 
					
						
							| 
									
										
										
										
											2021-03-01 13:26:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-12 06:27:03 +08:00
										 |  |  | 	return reply | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | // restClientFromHash will return a deterministic peerRESTClient based on s.
 | 
					
						
							|  |  |  | // Will return nil if client is local.
 | 
					
						
							|  |  |  | func (sys *NotificationSys) restClientFromHash(s string) (client *peerRESTClient) { | 
					
						
							|  |  |  | 	if len(sys.peerClients) == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-04-13 02:13:36 +08:00
										 |  |  | 	peerClients := sys.allPeerClients | 
					
						
							| 
									
										
										
										
											2021-01-21 05:13:05 +08:00
										 |  |  | 	if len(peerClients) == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-12-23 01:16:07 +08:00
										 |  |  | 	idx := xxhash.Sum64String(s) % uint64(len(peerClients)) | 
					
						
							|  |  |  | 	return peerClients[idx] | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-08 17:43:13 +08:00
										 |  |  | // GetPeerOnlineCount gets the count of online and offline nodes.
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetPeerOnlineCount() (nodesOnline, nodesOffline int) { | 
					
						
							|  |  |  | 	nodesOnline = 1 // Self is always online.
 | 
					
						
							|  |  |  | 	nodesOffline = 0 | 
					
						
							|  |  |  | 	nodesOnlineIndex := make([]bool, len(sys.peerClients)) | 
					
						
							|  |  |  | 	var wg sync.WaitGroup | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		wg.Add(1) | 
					
						
							|  |  |  | 		go func(idx int, client *peerRESTClient) { | 
					
						
							|  |  |  | 			defer wg.Done() | 
					
						
							|  |  |  | 			nodesOnlineIndex[idx] = client.restClient.HealthCheckFn() | 
					
						
							|  |  |  | 		}(idx, client) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wg.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, online := range nodesOnlineIndex { | 
					
						
							|  |  |  | 		if online { | 
					
						
							|  |  |  | 			nodesOnline++ | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			nodesOffline++ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | // NewNotificationSys - creates new notification system object.
 | 
					
						
							| 
									
										
										
										
											2020-12-02 05:50:33 +08:00
										 |  |  | func NewNotificationSys(endpoints EndpointServerPools) *NotificationSys { | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | 	remote, all := newPeerRestClients(endpoints) | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | 	return &NotificationSys{ | 
					
						
							| 
									
										
										
										
											2022-08-24 21:42:36 +08:00
										 |  |  | 		peerClients:    remote, | 
					
						
							|  |  |  | 		allPeerClients: all, | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-10-13 00:04:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // GetBandwidthReports - gets the bandwidth report from all nodes including self.
 | 
					
						
							| 
									
										
										
										
											2023-01-19 21:22:16 +08:00
										 |  |  | func (sys *NotificationSys) GetBandwidthReports(ctx context.Context, buckets ...string) bandwidth.BucketBandwidthReport { | 
					
						
							|  |  |  | 	reports := make([]*bandwidth.BucketBandwidthReport, len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2020-10-13 00:04:55 +08:00
										 |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2020-10-17 00:07:50 +08:00
										 |  |  | 	for index := range sys.peerClients { | 
					
						
							|  |  |  | 		if sys.peerClients[index] == nil { | 
					
						
							| 
									
										
										
										
											2020-10-13 00:04:55 +08:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			var err error | 
					
						
							| 
									
										
										
										
											2020-10-17 00:07:50 +08:00
										 |  |  | 			reports[index], err = sys.peerClients[index].MonitorBandwidth(ctx, buckets) | 
					
						
							| 
									
										
										
										
											2020-10-13 00:04:55 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", | 
					
						
							|  |  |  | 			sys.peerClients[index].host.String()) | 
					
						
							|  |  |  | 		ctx := logger.SetReqInfo(ctx, reqInfo) | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 		peersLogOnceIf(ctx, err, sys.peerClients[index].host.String()) | 
					
						
							| 
									
										
										
										
											2020-10-13 00:04:55 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-01-19 21:22:16 +08:00
										 |  |  | 	reports = append(reports, globalBucketMonitor.GetReport(bandwidth.SelectBuckets(buckets...))) | 
					
						
							|  |  |  | 	consolidatedReport := bandwidth.BucketBandwidthReport{ | 
					
						
							| 
									
										
										
										
											2023-09-06 11:21:59 +08:00
										 |  |  | 		BucketStats: make(map[bandwidth.BucketOptions]bandwidth.Details), | 
					
						
							| 
									
										
										
										
											2020-10-13 00:04:55 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	for _, report := range reports { | 
					
						
							|  |  |  | 		if report == nil || report.BucketStats == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-09-06 11:21:59 +08:00
										 |  |  | 		for opts := range report.BucketStats { | 
					
						
							|  |  |  | 			d, ok := consolidatedReport.BucketStats[opts] | 
					
						
							| 
									
										
										
										
											2020-10-13 00:04:55 +08:00
										 |  |  | 			if !ok { | 
					
						
							| 
									
										
										
										
											2023-09-06 11:21:59 +08:00
										 |  |  | 				d = bandwidth.Details{ | 
					
						
							|  |  |  | 					LimitInBytesPerSecond: report.BucketStats[opts].LimitInBytesPerSecond, | 
					
						
							| 
									
										
										
										
											2023-01-19 21:22:16 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-10-13 00:04:55 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-09-06 11:21:59 +08:00
										 |  |  | 			dt, ok := report.BucketStats[opts] | 
					
						
							|  |  |  | 			if ok { | 
					
						
							|  |  |  | 				d.CurrentBandwidthInBytesPerSecond += dt.CurrentBandwidthInBytesPerSecond | 
					
						
							| 
									
										
										
										
											2020-10-17 00:07:50 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-09-06 11:21:59 +08:00
										 |  |  | 			consolidatedReport.BucketStats[opts] = d | 
					
						
							| 
									
										
										
										
											2020-10-13 00:04:55 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return consolidatedReport | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-10 17:15:15 +08:00
										 |  |  | func (sys *NotificationSys) collectPeerMetrics(ctx context.Context, peerChannels []<-chan MetricV2, g *errgroup.Group) <-chan MetricV2 { | 
					
						
							|  |  |  | 	ch := make(chan MetricV2) | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 	var wg sync.WaitGroup | 
					
						
							|  |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			if sys.peerClients[index] != nil { | 
					
						
							|  |  |  | 				reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", | 
					
						
							|  |  |  | 					sys.peerClients[index].host.String()) | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 				peersLogOnceIf(logger.SetReqInfo(ctx, reqInfo), err, sys.peerClients[index].host.String()) | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 				peersLogOnceIf(ctx, err, "peer-offline") | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 		wg.Add(1) | 
					
						
							| 
									
										
										
										
											2024-03-10 17:15:15 +08:00
										 |  |  | 		go func(ctx context.Context, peerChannel <-chan MetricV2, wg *sync.WaitGroup) { | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 			defer wg.Done() | 
					
						
							|  |  |  | 			for { | 
					
						
							|  |  |  | 				select { | 
					
						
							|  |  |  | 				case m, ok := <-peerChannel: | 
					
						
							|  |  |  | 					if !ok { | 
					
						
							|  |  |  | 						return | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					select { | 
					
						
							|  |  |  | 					case ch <- m: | 
					
						
							|  |  |  | 					case <-ctx.Done(): | 
					
						
							|  |  |  | 						return | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				case <-ctx.Done(): | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}(ctx, peerChannels[index], &wg) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-03-10 17:15:15 +08:00
										 |  |  | 	go func(wg *sync.WaitGroup, ch chan MetricV2) { | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 		wg.Wait() | 
					
						
							| 
									
										
										
										
											2024-01-29 02:04:17 +08:00
										 |  |  | 		xioutil.SafeClose(ch) | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 	}(&wg, ch) | 
					
						
							|  |  |  | 	return ch | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-01 04:40:20 +08:00
										 |  |  | // GetBucketMetrics - gets the cluster level bucket metrics from all nodes excluding self.
 | 
					
						
							| 
									
										
										
										
											2024-03-10 17:15:15 +08:00
										 |  |  | func (sys *NotificationSys) GetBucketMetrics(ctx context.Context) <-chan MetricV2 { | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 	if sys == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2024-03-10 17:15:15 +08:00
										 |  |  | 	peerChannels := make([]<-chan MetricV2, len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 	for index := range sys.peerClients { | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							| 
									
										
										
										
											2023-07-19 13:25:12 +08:00
										 |  |  | 			if sys.peerClients[index] == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 			var err error | 
					
						
							| 
									
										
										
										
											2023-10-01 04:40:20 +08:00
										 |  |  | 			peerChannels[index], err = sys.peerClients[index].GetPeerBucketMetrics(ctx) | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-10-01 04:40:20 +08:00
										 |  |  | 	return sys.collectPeerMetrics(ctx, peerChannels, g) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-01 04:40:20 +08:00
										 |  |  | // GetClusterMetrics - gets the cluster metrics from all nodes excluding self.
 | 
					
						
							| 
									
										
										
										
											2024-03-10 17:15:15 +08:00
										 |  |  | func (sys *NotificationSys) GetClusterMetrics(ctx context.Context) <-chan MetricV2 { | 
					
						
							| 
									
										
										
										
											2023-10-01 04:40:20 +08:00
										 |  |  | 	if sys == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2024-03-10 17:15:15 +08:00
										 |  |  | 	peerChannels := make([]<-chan MetricV2, len(sys.peerClients)) | 
					
						
							| 
									
										
										
										
											2023-10-01 04:40:20 +08:00
										 |  |  | 	for index := range sys.peerClients { | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			if sys.peerClients[index] == nil { | 
					
						
							|  |  |  | 				return errPeerNotReachable | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-10-01 04:40:20 +08:00
										 |  |  | 			var err error | 
					
						
							|  |  |  | 			peerChannels[index], err = sys.peerClients[index].GetPeerMetrics(ctx) | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-10-01 04:40:20 +08:00
										 |  |  | 	return sys.collectPeerMetrics(ctx, peerChannels, g) | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-24 04:02:16 +08:00
										 |  |  | // ServiceFreeze freezes all S3 API calls when 'freeze' is true,
 | 
					
						
							|  |  |  | // 'freeze' is 'false' would resume all S3 API calls again.
 | 
					
						
							|  |  |  | // NOTE: once a tenant is frozen either two things needs to
 | 
					
						
							|  |  |  | // happen before resuming normal operations.
 | 
					
						
							| 
									
										
										
										
											2022-08-27 03:52:29 +08:00
										 |  |  | //   - Server needs to be restarted 'mc admin service restart'
 | 
					
						
							|  |  |  | //   - 'freeze' should be set to 'false' for this call
 | 
					
						
							|  |  |  | //     to resume normal operations.
 | 
					
						
							| 
									
										
										
										
											2021-11-24 04:02:16 +08:00
										 |  |  | func (sys *NotificationSys) ServiceFreeze(ctx context.Context, freeze bool) []NotificationPeerErr { | 
					
						
							|  |  |  | 	serviceSig := serviceUnFreeze | 
					
						
							|  |  |  | 	if freeze { | 
					
						
							|  |  |  | 		serviceSig = serviceFreeze | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ng := WithNPeers(len(sys.peerClients)) | 
					
						
							|  |  |  | 	for idx, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		client := client | 
					
						
							|  |  |  | 		ng.Go(GlobalContext, func() error { | 
					
						
							| 
									
										
										
										
											2024-06-20 22:49:22 +08:00
										 |  |  | 			return client.SignalService(serviceSig, "", false, nil) | 
					
						
							| 
									
										
										
										
											2021-11-24 04:02:16 +08:00
										 |  |  | 		}, idx, *client.host) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	nerrs := ng.Wait() | 
					
						
							|  |  |  | 	if freeze { | 
					
						
							|  |  |  | 		freezeServices() | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		unfreezeServices() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nerrs | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 01:54:38 +08:00
										 |  |  | // Netperf - perform mesh style network throughput test
 | 
					
						
							|  |  |  | func (sys *NotificationSys) Netperf(ctx context.Context, duration time.Duration) []madmin.NetperfNodeResult { | 
					
						
							|  |  |  | 	length := len(sys.allPeerClients) | 
					
						
							|  |  |  | 	if length == 0 { | 
					
						
							|  |  |  | 		// For single node erasure setup.
 | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	results := make([]madmin.NetperfNodeResult, length) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	scheme := "http" | 
					
						
							|  |  |  | 	if globalIsTLS { | 
					
						
							|  |  |  | 		scheme = "https" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var wg sync.WaitGroup | 
					
						
							|  |  |  | 	for index := range sys.peerClients { | 
					
						
							|  |  |  | 		if sys.peerClients[index] == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		wg.Add(1) | 
					
						
							|  |  |  | 		go func(index int) { | 
					
						
							|  |  |  | 			defer wg.Done() | 
					
						
							|  |  |  | 			r, err := sys.peerClients[index].Netperf(ctx, duration) | 
					
						
							|  |  |  | 			u := &url.URL{ | 
					
						
							|  |  |  | 				Scheme: scheme, | 
					
						
							|  |  |  | 				Host:   sys.peerClients[index].host.String(), | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				results[index].Error = err.Error() | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				results[index] = r | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			results[index].Endpoint = u.String() | 
					
						
							|  |  |  | 		}(index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wg.Add(1) | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		defer wg.Done() | 
					
						
							|  |  |  | 		r := netperf(ctx, duration) | 
					
						
							|  |  |  | 		u := &url.URL{ | 
					
						
							|  |  |  | 			Scheme: scheme, | 
					
						
							|  |  |  | 			Host:   globalLocalNodeName, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		results[len(results)-1] = r | 
					
						
							|  |  |  | 		results[len(results)-1].Endpoint = u.String() | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 	wg.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return results | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-13 01:12:47 +08:00
										 |  |  | // SpeedTest run GET/PUT tests at input concurrency for requested object size,
 | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | // optionally you can extend the tests longer with time.Duration.
 | 
					
						
							| 
									
										
										
										
											2022-07-13 01:12:47 +08:00
										 |  |  | func (sys *NotificationSys) SpeedTest(ctx context.Context, sopts speedTestOpts) []SpeedTestResult { | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 	length := len(sys.allPeerClients) | 
					
						
							|  |  |  | 	if length == 0 { | 
					
						
							|  |  |  | 		// For single node erasure setup.
 | 
					
						
							|  |  |  | 		length = 1 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-07-13 01:12:47 +08:00
										 |  |  | 	results := make([]SpeedTestResult, length) | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-30 08:51:30 +08:00
										 |  |  | 	scheme := "http" | 
					
						
							|  |  |  | 	if globalIsTLS { | 
					
						
							|  |  |  | 		scheme = "https" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	var wg sync.WaitGroup | 
					
						
							|  |  |  | 	for index := range sys.peerClients { | 
					
						
							|  |  |  | 		if sys.peerClients[index] == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		wg.Add(1) | 
					
						
							|  |  |  | 		go func(index int) { | 
					
						
							|  |  |  | 			defer wg.Done() | 
					
						
							| 
									
										
										
										
											2022-07-13 01:12:47 +08:00
										 |  |  | 			r, err := sys.peerClients[index].SpeedTest(ctx, sopts) | 
					
						
							| 
									
										
										
										
											2021-07-30 08:51:30 +08:00
										 |  |  | 			u := &url.URL{ | 
					
						
							|  |  |  | 				Scheme: scheme, | 
					
						
							|  |  |  | 				Host:   sys.peerClients[index].host.String(), | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				results[index].Error = err.Error() | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				results[index] = r | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 			results[index].Endpoint = u.String() | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 		}(index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wg.Add(1) | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		defer wg.Done() | 
					
						
							| 
									
										
										
										
											2022-07-13 01:12:47 +08:00
										 |  |  | 		r, err := selfSpeedTest(ctx, sopts) | 
					
						
							| 
									
										
										
										
											2021-08-03 12:50:20 +08:00
										 |  |  | 		u := &url.URL{ | 
					
						
							|  |  |  | 			Scheme: scheme, | 
					
						
							|  |  |  | 			Host:   globalLocalNodeName, | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			results[len(results)-1].Error = err.Error() | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			results[len(results)-1] = r | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 		results[len(results)-1].Endpoint = u.String() | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	}() | 
					
						
							|  |  |  | 	wg.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return results | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-10-07 07:36:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 14:38:05 +08:00
										 |  |  | // DriveSpeedTest - Drive performance information
 | 
					
						
							|  |  |  | func (sys *NotificationSys) DriveSpeedTest(ctx context.Context, opts madmin.DriveSpeedTestOpts) chan madmin.DriveSpeedTestResult { | 
					
						
							|  |  |  | 	ch := make(chan madmin.DriveSpeedTestResult) | 
					
						
							|  |  |  | 	var wg sync.WaitGroup | 
					
						
							|  |  |  | 	for _, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		wg.Add(1) | 
					
						
							|  |  |  | 		go func(client *peerRESTClient) { | 
					
						
							|  |  |  | 			defer wg.Done() | 
					
						
							|  |  |  | 			resp, err := client.DriveSpeedTest(ctx, opts) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				resp.Error = err.Error() | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-16 05:51:42 +08:00
										 |  |  | 			select { | 
					
						
							|  |  |  | 			case <-ctx.Done(): | 
					
						
							|  |  |  | 			case ch <- resp: | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-02-02 14:38:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			reqInfo := (&logger.ReqInfo{}).AppendTags("remotePeer", client.host.String()) | 
					
						
							|  |  |  | 			ctx := logger.SetReqInfo(GlobalContext, reqInfo) | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 			peersLogOnceIf(ctx, err, client.host.String()) | 
					
						
							| 
									
										
										
										
											2022-02-02 14:38:05 +08:00
										 |  |  | 		}(client) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-16 05:51:42 +08:00
										 |  |  | 	wg.Add(1) | 
					
						
							| 
									
										
										
										
											2022-02-02 14:38:05 +08:00
										 |  |  | 	go func() { | 
					
						
							| 
									
										
										
										
											2022-06-16 05:51:42 +08:00
										 |  |  | 		defer wg.Done() | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case <-ctx.Done(): | 
					
						
							|  |  |  | 		case ch <- driveSpeedTest(ctx, opts): | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	go func(wg *sync.WaitGroup, ch chan madmin.DriveSpeedTestResult) { | 
					
						
							| 
									
										
										
										
											2022-02-02 14:38:05 +08:00
										 |  |  | 		wg.Wait() | 
					
						
							| 
									
										
										
										
											2024-01-29 02:04:17 +08:00
										 |  |  | 		xioutil.SafeClose(ch) | 
					
						
							| 
									
										
										
										
											2022-06-16 05:51:42 +08:00
										 |  |  | 	}(&wg, ch) | 
					
						
							| 
									
										
										
										
											2022-02-02 14:38:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ch | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-07 07:36:31 +08:00
										 |  |  | // ReloadSiteReplicationConfig - tells all peer minio nodes to reload the
 | 
					
						
							|  |  |  | // site-replication configuration.
 | 
					
						
							|  |  |  | func (sys *NotificationSys) ReloadSiteReplicationConfig(ctx context.Context) []error { | 
					
						
							|  |  |  | 	errs := make([]error, len(sys.allPeerClients)) | 
					
						
							|  |  |  | 	var wg sync.WaitGroup | 
					
						
							|  |  |  | 	for index := range sys.peerClients { | 
					
						
							|  |  |  | 		if sys.peerClients[index] == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		wg.Add(1) | 
					
						
							|  |  |  | 		go func(index int) { | 
					
						
							|  |  |  | 			defer wg.Done() | 
					
						
							|  |  |  | 			errs[index] = sys.peerClients[index].ReloadSiteReplicationConfig(ctx) | 
					
						
							|  |  |  | 		}(index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wg.Wait() | 
					
						
							|  |  |  | 	return errs | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-01-27 06:33:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // GetLastDayTierStats fetches per-tier stats of the last 24hrs from all peers
 | 
					
						
							| 
									
										
										
										
											2022-04-14 05:21:55 +08:00
										 |  |  | func (sys *NotificationSys) GetLastDayTierStats(ctx context.Context) DailyAllTierStats { | 
					
						
							| 
									
										
										
										
											2022-01-27 06:33:10 +08:00
										 |  |  | 	errs := make([]error, len(sys.allPeerClients)) | 
					
						
							| 
									
										
										
										
											2022-04-14 05:21:55 +08:00
										 |  |  | 	lastDayStats := make([]DailyAllTierStats, len(sys.allPeerClients)) | 
					
						
							| 
									
										
										
										
											2022-01-27 06:33:10 +08:00
										 |  |  | 	var wg sync.WaitGroup | 
					
						
							|  |  |  | 	for index := range sys.peerClients { | 
					
						
							|  |  |  | 		if sys.peerClients[index] == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		wg.Add(1) | 
					
						
							|  |  |  | 		go func(index int) { | 
					
						
							|  |  |  | 			defer wg.Done() | 
					
						
							|  |  |  | 			lastDayStats[index], errs[index] = sys.peerClients[index].GetLastDayTierStats(ctx) | 
					
						
							|  |  |  | 		}(index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wg.Wait() | 
					
						
							|  |  |  | 	merged := globalTransitionState.getDailyAllTierStats() | 
					
						
							|  |  |  | 	for i, stat := range lastDayStats { | 
					
						
							|  |  |  | 		if errs[i] != nil { | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 			peersLogOnceIf(ctx, fmt.Errorf("failed to fetch last day tier stats: %w", errs[i]), sys.peerClients[i].host.String()) | 
					
						
							| 
									
										
										
										
											2022-01-27 06:33:10 +08:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		merged.merge(stat) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return merged | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-07-13 14:51:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // GetReplicationMRF - Get replication MRF from all peers.
 | 
					
						
							|  |  |  | func (sys *NotificationSys) GetReplicationMRF(ctx context.Context, bucket, node string) (mrfCh chan madmin.ReplicationMRF, err error) { | 
					
						
							|  |  |  | 	g := errgroup.WithNErrs(len(sys.peerClients)) | 
					
						
							|  |  |  | 	peerChannels := make([]<-chan madmin.ReplicationMRF, len(sys.peerClients)) | 
					
						
							|  |  |  | 	for index, client := range sys.peerClients { | 
					
						
							|  |  |  | 		if client == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		host := client.host.String() | 
					
						
							|  |  |  | 		if host != node && node != "all" { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							|  |  |  | 			var err error | 
					
						
							|  |  |  | 			peerChannels[index], err = sys.peerClients[index].GetReplicationMRF(ctx, bucket) | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	mrfCh = make(chan madmin.ReplicationMRF, 4000) | 
					
						
							|  |  |  | 	var wg sync.WaitGroup | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for index, err := range g.Wait() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			if sys.peerClients[index] != nil { | 
					
						
							|  |  |  | 				reqInfo := (&logger.ReqInfo{}).AppendTags("peerAddress", | 
					
						
							|  |  |  | 					sys.peerClients[index].host.String()) | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 				peersLogOnceIf(logger.SetReqInfo(ctx, reqInfo), err, sys.peerClients[index].host.String()) | 
					
						
							| 
									
										
										
										
											2023-07-13 14:51:33 +08:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2024-04-04 20:04:40 +08:00
										 |  |  | 				peersLogOnceIf(ctx, err, "peer-offline") | 
					
						
							| 
									
										
										
										
											2023-07-13 14:51:33 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		wg.Add(1) | 
					
						
							|  |  |  | 		go func(ctx context.Context, peerChannel <-chan madmin.ReplicationMRF, wg *sync.WaitGroup) { | 
					
						
							|  |  |  | 			defer wg.Done() | 
					
						
							|  |  |  | 			for { | 
					
						
							|  |  |  | 				select { | 
					
						
							|  |  |  | 				case m, ok := <-peerChannel: | 
					
						
							|  |  |  | 					if !ok { | 
					
						
							|  |  |  | 						return | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					select { | 
					
						
							|  |  |  | 					case <-ctx.Done(): | 
					
						
							|  |  |  | 						return | 
					
						
							|  |  |  | 					case mrfCh <- m: | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				case <-ctx.Done(): | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}(ctx, peerChannels[index], &wg) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wg.Add(1) | 
					
						
							|  |  |  | 	go func(ch chan madmin.ReplicationMRF) error { | 
					
						
							|  |  |  | 		defer wg.Done() | 
					
						
							|  |  |  | 		if node != "all" && node != globalLocalNodeName { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-08-15 20:04:40 +08:00
										 |  |  | 		mCh, err := globalReplicationPool.Get().getMRF(ctx, bucket) | 
					
						
							| 
									
										
										
										
											2023-07-13 14:51:33 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for e := range mCh { | 
					
						
							|  |  |  | 			select { | 
					
						
							|  |  |  | 			case <-ctx.Done(): | 
					
						
							|  |  |  | 				return err | 
					
						
							| 
									
										
										
										
											2023-08-22 07:44:50 +08:00
										 |  |  | 			case mrfCh <- e: | 
					
						
							| 
									
										
										
										
											2023-07-13 14:51:33 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}(mrfCh) | 
					
						
							|  |  |  | 	go func(wg *sync.WaitGroup) { | 
					
						
							|  |  |  | 		wg.Wait() | 
					
						
							| 
									
										
										
										
											2024-01-29 02:04:17 +08:00
										 |  |  | 		xioutil.SafeClose(mrfCh) | 
					
						
							| 
									
										
										
										
											2023-07-13 14:51:33 +08:00
										 |  |  | 	}(&wg) | 
					
						
							|  |  |  | 	return mrfCh, nil | 
					
						
							|  |  |  | } |