2021-04-19 03:41:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Copyright (c) 2015-2021 MinIO, Inc.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// 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-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								package  cmd  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"errors" 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"net/url" 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-23 18:54:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"runtime" 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-29 10:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"slices" 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/cespare/xxhash/v2" 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-15 00:38:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio-go/v7/pkg/set" 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-02 05:59:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio/internal/config" 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-25 07:05:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/pkg/v3/ellipses" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/minio/pkg/v3/env" 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This file implements and supports ellipses pattern for
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// `minio server` command line arguments.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Endpoint set represents parsed ellipses values, also provides
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// methods to get the sets of endpoints.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  endpointSet  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									argPatterns  [ ] ellipses . ArgPattern 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									endpoints    [ ] string    // Endpoints saved from previous GetEndpoints().
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									setIndexes   [ ] [ ] uint64  // All the sets.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Supported set sizes this is used to find the optimal
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// single set size.
  
						 
					
						
							
								
									
										
										
										
											2022-06-28 11:22:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								var  setSizes  =  [ ] uint64 { 2 ,  3 ,  4 ,  5 ,  6 ,  7 ,  8 ,  9 ,  10 ,  11 ,  12 ,  13 ,  14 ,  15 ,  16 }  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// getDivisibleSize - returns a greatest common divisor of
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// all the ellipses sizes.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  getDivisibleSize ( totalSizes  [ ] uint64 )  ( result  uint64 )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									gcd  :=  func ( x ,  y  uint64 )  uint64  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  y  !=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											x ,  y  =  y ,  x % y 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  x 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									result  =  totalSizes [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  1 ;  i  <  len ( totalSizes ) ;  i ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										result  =  gcd ( result ,  totalSizes [ i ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  result 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-11-20 09:42:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// isValidSetSize - checks whether given count is a valid set size for erasure coding.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  isValidSetSize  =  func ( count  uint64 )  bool  {  
						 
					
						
							
								
									
										
										
										
											2020-04-01 00:32:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  ( count  >=  setSizes [ 0 ]  &&  count  <=  setSizes [ len ( setSizes ) - 1 ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-20 09:42:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-28 05:39:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  commonSetDriveCount ( divisibleSize  uint64 ,  setCounts  [ ] uint64 )  ( setSize  uint64 )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// prefers setCounts to be sorted for optimal behavior.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  divisibleSize  <  setCounts [ len ( setCounts ) - 1 ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  divisibleSize 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Figure out largest value of total_drives_in_erasure_set which results
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// in least number of total_drives/total_drives_erasure_set ratio.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									prevD  :=  divisibleSize  /  setCounts [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  cnt  :=  range  setCounts  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  divisibleSize % cnt  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											d  :=  divisibleSize  /  cnt 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  d  <=  prevD  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												prevD  =  d 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												setSize  =  cnt 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  setSize 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// possibleSetCountsWithSymmetry returns symmetrical setCounts based on the
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// input argument patterns, the symmetry calculation is to ensure that
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// we also use uniform number of drives common across all ellipses patterns.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  possibleSetCountsWithSymmetry ( setCounts  [ ] uint64 ,  argPatterns  [ ] ellipses . ArgPattern )  [ ] uint64  {  
						 
					
						
							
								
									
										
										
										
											2022-01-03 01:15:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									newSetCounts  :=  make ( map [ uint64 ] struct { } ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-28 05:39:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  _ ,  ss  :=  range  setCounts  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  symmetry  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  argPattern  :=  range  argPatterns  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  _ ,  p  :=  range  argPattern  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  uint64 ( len ( p . Seq ) )  >  ss  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													symmetry  =  uint64 ( len ( p . Seq ) ) % ss  ==  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													symmetry  =  ss % uint64 ( len ( p . Seq ) )  ==  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// With no arg patterns, it is expected that user knows
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// the right symmetry, so either ellipses patterns are
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// provided (recommended) or no ellipses patterns.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  _ ,  ok  :=  newSetCounts [ ss ] ;  ! ok  &&  ( symmetry  ||  argPatterns  ==  nil )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											newSetCounts [ ss ]  =  struct { } { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									setCounts  =  [ ] uint64 { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  setCount  :=  range  newSetCounts  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										setCounts  =  append ( setCounts ,  setCount ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Not necessarily needed but it ensures to the readers
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// eyes that we prefer a sorted setCount slice for the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// subsequent function to figure out the right common
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// divisor, it avoids loops.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-29 10:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									slices . Sort ( setCounts ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-28 05:39:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  setCounts 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// getSetIndexes returns list of indexes which provides the set size
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// on each index, this function also determines the final set size
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The final set size has the affinity towards choosing smaller
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// indexes (total sets)
  
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  getSetIndexes ( args  [ ] string ,  totalSizes  [ ] uint64 ,  setDriveCount  uint64 ,  argPatterns  [ ] ellipses . ArgPattern )  ( setIndexes  [ ] [ ] uint64 ,  err  error )  {  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  len ( totalSizes )  ==  0  ||  len ( args )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  errInvalidArgument 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									setIndexes  =  make ( [ ] [ ] uint64 ,  len ( totalSizes ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 10:04:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  _ ,  totalSize  :=  range  totalSizes  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// Check if totalSize has minimum range upto setSize
 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  totalSize  <  setSizes [ 0 ]  ||  totalSize  <  setDriveCount  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-08 01:13:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											msg  :=  fmt . Sprintf ( "Incorrect number of endpoints provided %s" ,  args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  config . ErrInvalidNumberOfErasureEndpoints ( nil ) . Msg ( msg ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									commonSize  :=  getDivisibleSize ( totalSizes ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-16 07:35:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									possibleSetCounts  :=  func ( setSize  uint64 )  ( ss  [ ] uint64 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  s  :=  range  setSizes  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  setSize % s  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ss  =  append ( ss ,  s ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ss 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-09 04:30:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									setCounts  :=  possibleSetCounts ( commonSize ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  len ( setCounts )  ==  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-05 07:10:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										msg  :=  fmt . Sprintf ( "Incorrect number of endpoints provided %s, number of drives %d is not divisible by any supported erasure set sizes %d" ,  args ,  commonSize ,  setSizes ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-09 04:30:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  config . ErrInvalidNumberOfErasureEndpoints ( nil ) . Msg ( msg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-28 05:39:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  setSize  uint64 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Custom set drive count allows to override automatic distribution.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// only meant if you want to further optimize drive distribution.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  setDriveCount  >  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-09 04:30:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										msg  :=  fmt . Sprintf ( "Invalid set drive count. Acceptable values for %d number drives are %d" ,  commonSize ,  setCounts ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  found  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  ss  :=  range  setCounts  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ss  ==  setDriveCount  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-09 04:30:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												found  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! found  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-05 01:35:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  nil ,  config . ErrInvalidErasureSetSize ( nil ) . Msg ( msg ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-16 07:35:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-28 05:39:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// No automatic symmetry calculation expected, user is on their own
 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										setSize  =  setDriveCount 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-28 05:39:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Returns possible set counts with symmetry.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										setCounts  =  possibleSetCountsWithSymmetry ( setCounts ,  argPatterns ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 13:13:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  len ( setCounts )  ==  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-05 07:10:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											msg  :=  fmt . Sprintf ( "No symmetric distribution detected with input endpoints provided %s, drives %d cannot be spread symmetrically by any supported erasure set sizes %d" ,  args ,  commonSize ,  setSizes ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 13:13:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  nil ,  config . ErrInvalidNumberOfErasureEndpoints ( nil ) . Msg ( msg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-28 05:39:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Final set size with all the symmetry accounted for.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										setSize  =  commonSetDriveCount ( commonSize ,  setCounts ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Check whether setSize is with the supported range.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! isValidSetSize ( setSize )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-05 07:10:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										msg  :=  fmt . Sprintf ( "Incorrect number of endpoints provided %s, number of drives %d is not divisible by any supported erasure set sizes %d" ,  args ,  commonSize ,  setSizes ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-08 01:13:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  config . ErrInvalidNumberOfErasureEndpoints ( nil ) . Msg ( msg ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  range  totalSizes  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  j  :=  uint64 ( 0 ) ;  j  <  totalSizes [ i ] / setSize ;  j ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											setIndexes [ i ]  =  append ( setIndexes [ i ] ,  setSize ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  setIndexes ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Returns all the expanded endpoints, each argument is expanded separately.
  
						 
					
						
							
								
									
										
										
										
											2022-12-06 03:18:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( s  * endpointSet )  getEndpoints ( )  ( endpoints  [ ] string )  {  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  len ( s . endpoints )  !=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  s . endpoints 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  argPattern  :=  range  s . argPatterns  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  lbls  :=  range  argPattern . Expand ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											endpoints  =  append ( endpoints ,  strings . Join ( lbls ,  "" ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s . endpoints  =  endpoints 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  endpoints 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Get returns the sets representation of the endpoints
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// this function also intelligently decides on what will
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// be the right set size etc.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( s  endpointSet )  Get ( )  ( sets  [ ] [ ] string )  {  
						 
					
						
							
								
									
										
										
										
											2022-01-03 01:15:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									k  :=  uint64 ( 0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									endpoints  :=  s . getEndpoints ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  range  s . setIndexes  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  j  :=  range  s . setIndexes [ i ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											sets  =  append ( sets ,  endpoints [ k : s . setIndexes [ i ] [ j ] + k ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											k  =  s . setIndexes [ i ] [ j ]  +  k 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  sets 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Return the total size for each argument patterns.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  getTotalSizes ( argPatterns  [ ] ellipses . ArgPattern )  [ ] uint64  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  totalSizes  [ ] uint64 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  argPattern  :=  range  argPatterns  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  totalSize  uint64  =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  p  :=  range  argPattern  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-17 01:28:29 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											totalSize  *=  uint64 ( len ( p . Seq ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										totalSizes  =  append ( totalSizes ,  totalSize ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  totalSizes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Parses all arguments and returns an endpointSet which is a collection
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// of endpoints following the ellipses pattern, this is what is used
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// by the object layer for initializing itself.
  
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  parseEndpointSet ( setDriveCount  uint64 ,  args  ... string )  ( ep  endpointSet ,  err  error )  {  
						 
					
						
							
								
									
										
										
										
											2022-01-03 01:15:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									argPatterns  :=  make ( [ ] ellipses . ArgPattern ,  len ( args ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  i ,  arg  :=  range  args  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-01 06:30:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										patterns ,  perr  :=  ellipses . FindEllipsesPatterns ( arg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  perr  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-05 01:35:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  endpointSet { } ,  config . ErrInvalidErasureEndpoints ( nil ) . Msg ( perr . Error ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										argPatterns [ i ]  =  patterns 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ep . setIndexes ,  err  =  getSetIndexes ( args ,  getTotalSizes ( argPatterns ) ,  setDriveCount ,  argPatterns ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-05 01:35:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  endpointSet { } ,  config . ErrInvalidErasureEndpoints ( nil ) . Msg ( err . Error ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ep . argPatterns  =  argPatterns 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ep ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-06-10 22:57:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// GetAllSets - parses all ellipses input arguments, expands them into
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// corresponding list of endpoints chunked evenly in accordance with a
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// specific set size.
  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// For example: {1...64} is divided into 4 sets each of size 16.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This applies to even distributed setup syntax as well.
  
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  GetAllSets ( setDriveCount  uint64 ,  args  ... string )  ( [ ] [ ] string ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									var  setArgs  [ ] [ ] string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! ellipses . HasEllipses ( args ... )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  setIndexes  [ ] [ ] uint64 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Check if we have more one args.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( args )  >  1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											var  err  error 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											setIndexes ,  err  =  getSetIndexes ( args ,  [ ] uint64 { uint64 ( len ( args ) ) } ,  setDriveCount ,  nil ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// We are in FS setup, proceed forward.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-27 02:22:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											setIndexes  =  [ ] [ ] uint64 { { uint64 ( len ( args ) ) } } 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										s  :=  endpointSet { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											endpoints :   args , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											setIndexes :  setIndexes , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										setArgs  =  s . Get ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										s ,  err  :=  parseEndpointSet ( setDriveCount ,  args ... ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										setArgs  =  s . Get ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uniqueArgs  :=  set . NewStringSet ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  sargs  :=  range  setArgs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  arg  :=  range  sargs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  uniqueArgs . Contains ( arg )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 01:11:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												return  nil ,  config . ErrInvalidErasureEndpoints ( nil ) . Msgf ( "Input args (%s) has duplicate ellipses" ,  args ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											uniqueArgs . Add ( arg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  setArgs ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-28 05:39:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Override set drive count for manual distribution.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									EnvErasureSetDriveCount  =  "MINIO_ERASURE_SET_DRIVE_COUNT" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								type  node  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									nodeName  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									disks     [ ] string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  endpointsList  [ ] node  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( el  * endpointsList )  add ( arg  string )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u ,  err  :=  url . Parse ( arg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									found  :=  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									list  :=  * el 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  range  list  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  list [ i ] . nodeName  ==  u . Host  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											list [ i ] . disks  =  append ( list [ i ] . disks ,  u . String ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											found  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! found  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										list  =  append ( list ,  node { nodeName :  u . Host ,  disks :  [ ] string { u . String ( ) } } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									* el  =  list 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								type  poolArgs  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									args           [ ] string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									setDriveCount  uint64 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// buildDisksLayoutFromConfFile supports with and without ellipses transparently.
  
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  buildDisksLayoutFromConfFile ( pools  [ ] poolArgs )  ( layout  disksLayout ,  err  error )  {  
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  len ( pools )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  layout ,  errInvalidArgument 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  list  :=  range  pools  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  endpointsList  endpointsList 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  _ ,  arg  :=  range  list . args  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  ellipses . HasList ( arg ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												patterns ,  err  :=  ellipses . FindListPatterns ( arg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  layout ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												for  _ ,  exp  :=  range  patterns . Expand ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													for  _ ,  ep  :=  range  exp  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														if  err  :=  endpointsList . add ( ep ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															return  layout ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  ellipses . HasEllipses ( arg ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												patterns ,  err  :=  ellipses . FindEllipsesPatterns ( arg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  layout ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												for  _ ,  exp  :=  range  patterns . Expand ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  err  :=  endpointsList . add ( strings . Join ( exp ,  "" ) ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														return  layout ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err  :=  endpointsList . add ( arg ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  layout ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  stopping  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  singleNode  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  eps  [ ] string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  i  :=  0 ;  ;  i ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  _ ,  node  :=  range  endpointsList  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  node . nodeName  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													singleNode  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  len ( node . disks )  <=  i  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													stopping  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  stopping  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  layout ,  errors . New ( "number of disks per node does not match" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												eps  =  append ( eps ,  node . disks [ i ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  stopping  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  node  :=  range  endpointsList  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  node . nodeName  !=  ""  &&  singleNode  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  layout ,  errors . New ( "all arguments must but either single node or distributed" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										setArgs ,  err  :=  GetAllSets ( list . setDriveCount ,  eps ... ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  layout ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										h  :=  xxhash . New ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  s  :=  range  setArgs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  _ ,  d  :=  range  s  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												h . WriteString ( d ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										layout . pools  =  append ( layout . pools ,  poolDisksLayout { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cmdline :  fmt . Sprintf ( "hash:%x" ,  h . Sum ( nil ) ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											layout :   setArgs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// mergeDisksLayoutFromArgs supports with and without ellipses transparently.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  mergeDisksLayoutFromArgs ( args  [ ] string ,  ctxt  * serverCtxt )  ( err  error )  {  
						 
					
						
							
								
									
										
										
										
											2019-11-20 09:42:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  len ( args )  ==  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  errInvalidArgument 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-02 07:41:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ok  :=  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  arg  :=  range  args  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ok  =  ok  &&  ! ellipses . HasEllipses ( arg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  setArgs  [ ] [ ] string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									v ,  err  :=  env . GetInt ( EnvErasureSetDriveCount ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									setDriveCount  :=  uint64 ( v ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-02 07:41:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// None of the args have ellipses use the old style.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										setArgs ,  err  =  GetAllSets ( setDriveCount ,  args ... ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-20 09:42:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-20 09:42:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ctxt . Layout  =  disksLayout { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											legacy :  true , 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-12 05:22:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											pools :   [ ] poolDisksLayout { { layout :  setArgs ,  cmdline :  strings . Join ( args ,  " " ) } } , 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-24 02:48:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-11-20 09:42:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  _ ,  arg  :=  range  args  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-02 07:41:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ! ellipses . HasEllipses ( arg )  &&  len ( args )  >  1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// TODO: support SNSD deployments to be decommissioned in future
 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  fmt . Errorf ( "all args must have ellipses for pool expansion (%w) args: %s" ,  errInvalidArgument ,  args ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-02 07:41:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 23:54:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										setArgs ,  err  =  GetAllSets ( setDriveCount ,  arg ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-20 09:42:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-20 09:42:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ctxt . Layout . pools  =  append ( ctxt . Layout . pools ,  poolDisksLayout { cmdline :  arg ,  layout :  setArgs } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2021-01-17 04:08:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// CreateServerEndpoints - validates and creates new endpoints from input args, supports
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// both ellipses and without ellipses transparently.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  createServerEndpoints ( serverAddr  string ,  poolArgs  [ ] poolDisksLayout ,  legacy  bool )  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									endpointServerPools  EndpointServerPools ,  setupType  SetupType ,  err  error , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  len ( poolArgs )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  - 1 ,  errInvalidArgument 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 08:41:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									poolEndpoints ,  setupType ,  err  :=  CreatePoolEndpoints ( serverAddr ,  poolArgs ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  - 1 ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i ,  endpointList  :=  range  poolEndpoints  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-27 12:47:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  =  endpointServerPools . Add ( PoolEndpoints { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											Legacy :        legacy , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											SetCount :      len ( poolArgs [ i ] . layout ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											DrivesPerSet :  len ( poolArgs [ i ] . layout [ 0 ] ) , 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-20 09:42:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											Endpoints :     endpointList , 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-23 18:54:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											Platform :      fmt . Sprintf ( "OS: %s | Arch: %s" ,  runtime . GOOS ,  runtime . GOARCH ) , 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 17:33:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											CmdLine :       poolArgs [ i ] . cmdline , 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-08 01:13:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-06 04:31:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  nil ,  - 1 ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-08 01:13:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-20 09:42:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-27 03:42:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-02 05:50:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  endpointServerPools ,  setupType ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}