From 27b6c30847988230ee078e0f7a8143aa19719c4e Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Sun, 21 Dec 2025 13:42:35 -0800 Subject: [PATCH] refactor: improve port detection logic and remove gRPC handling duplication - findAvailablePortOnIP now returns 0 on failure instead of unavailable port Allows callers to detect when port finding fails and handle appropriately - Remove duplicate gRPC port handling from ensureAllPortsAvailableOnIP All gRPC port logic is now centralized in initializeGrpcPortsOnIP - Log final port configuration only after all ports are finalized Both HTTP and gRPC ports are now correctly initialized before logging - Add error logging when port allocation fails Makes debugging easier when ports can't be found --- weed/command/mini.go | 74 ++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 48 deletions(-) diff --git a/weed/command/mini.go b/weed/command/mini.go index cb5ea8dca..cc7a32ee8 100644 --- a/weed/command/mini.go +++ b/weed/command/mini.go @@ -361,7 +361,7 @@ func findAvailablePort(startPort int, maxAttempts int) int { } // findAvailablePortOnIP finds the next available port on a specific IP starting from the given port -// It returns the first available port found within maxAttempts +// It returns the first available port found within maxAttempts, or 0 if none found func findAvailablePortOnIP(ip string, startPort int, maxAttempts int) int { for i := 0; i < maxAttempts; i++ { port := startPort + i @@ -370,8 +370,8 @@ func findAvailablePortOnIP(ip string, startPort int, maxAttempts int) int { return port } } - // If no port found, return the original (will fail during binding) - return startPort + // If no port found, return 0 to indicate failure + return 0 } // ensurePortAvailable ensures a port pointer points to an available port @@ -392,7 +392,9 @@ func ensurePortAvailableOnIP(portPtr *int, serviceName string, ip string) { if !isPortOpenOnIP(ip, original) || !isPortAvailable(original) { glog.Warningf("Port %d for %s is not available on %s, finding alternative port...", original, serviceName, ip) newPort := findAvailablePortOnIP(ip, original+1, 100) - if newPort != original { + if newPort == 0 { + glog.Errorf("Could not find available port for %s starting from %d, will use original %d and fail on binding", serviceName, original+1, original) + } else { glog.Infof("Port %d for %s is available, using it instead of %d", newPort, serviceName, original) *portPtr = newPort } @@ -438,56 +440,20 @@ func ensureAllPortsAvailableOnIP(bindIp string) { wg.Wait() - // Now handle gRPC ports sequentially after HTTP ports are finalized - // gRPC ports can be: - // 1. Explicitly set by user (any independent value) - // 2. Auto-calculated as httpPort + 10000 if set to 0 - // We need to check availability for both cases - for _, config := range portConfigs { - if config.grpcPtr == nil { - continue - } - - httpPort := *config.port - grpcPort := *config.grpcPtr - - // If gRPC port is 0, it will be auto-calculated later as httpPort + 10000 - // Pre-calculate and check if that value would be available - if grpcPort == 0 { - calculatedGrpcPort := httpPort + 10000 - // Check if the calculated port would be available (on both specific IP and all interfaces) - if !isPortOpenOnIP(bindIp, calculatedGrpcPort) || !isPortAvailable(calculatedGrpcPort) { - glog.Warningf("Calculated gRPC port %d for %s is not available, finding alternative port...", calculatedGrpcPort, config.name) - newPort := findAvailablePortOnIP(bindIp, calculatedGrpcPort+1, 100) - glog.Infof("gRPC port %d for %s is available, using it instead of calculated %d", newPort, config.name, calculatedGrpcPort) - *config.grpcPtr = newPort - } - } else { - // gRPC port was explicitly set by user, check if it's available (on both specific IP and all interfaces) - if !isPortOpenOnIP(bindIp, grpcPort) || !isPortAvailable(grpcPort) { - glog.Warningf("gRPC port %d for %s is not available, finding alternative port...", grpcPort, config.name) - newPort := findAvailablePortOnIP(bindIp, grpcPort+1, 100) - if newPort != grpcPort { - glog.Infof("gRPC port %d for %s is available, using it instead of %d", newPort, config.name, grpcPort) - *config.grpcPtr = newPort - } - } - } - } + // Initialize all gRPC ports before services start + // This ensures they won't be recalculated and cause conflicts + // gRPC port handling is done here, not duplicated in ensureAllPortsAvailableOnIP + initializeGrpcPortsOnIP(bindIp) // Log the final port configuration glog.Infof("Final port configuration - Master: %d, Filer: %d, Volume: %d, S3: %d, WebDAV: %d, Admin: %d", *miniMasterOptions.port, *miniFilerOptions.port, *miniOptions.v.port, *miniS3Options.port, *miniWebDavOptions.port, *miniAdminOptions.port) - // Log gRPC ports too + // Log gRPC ports too (now finalized) glog.Infof("gRPC port configuration - Master: %d, Filer: %d, Volume: %d, S3: %d, Admin: %d", *miniMasterOptions.portGrpc, *miniFilerOptions.portGrpc, *miniOptions.v.portGrpc, *miniS3Options.portGrpc, *miniAdminOptions.grpcPort) - - // Initialize all gRPC ports before services start - // This ensures they won't be recalculated and cause conflicts - initializeGrpcPortsOnIP(bindIp) } // initializeGrpcPortsOnIP initializes all gRPC ports based on their HTTP ports on a specific IP @@ -514,10 +480,17 @@ func initializeGrpcPortsOnIP(bindIp string) { // If gRPC port is 0, calculate it if *config.grpcPort == 0 { calculatedPort := *config.httpPort + 10000 - // Double-check if calculated port is available, find alternative if not (check on both specific IP and all interfaces) + // Check if calculated port is available (on both specific IP and all interfaces) if !isPortOpenOnIP(bindIp, calculatedPort) || !isPortAvailable(calculatedPort) { glog.Warningf("Calculated gRPC port %d for %s is not available, finding alternative...", calculatedPort, config.name) - calculatedPort = findAvailablePortOnIP(bindIp, calculatedPort+1, 100) + newPort := findAvailablePortOnIP(bindIp, calculatedPort+1, 100) + if newPort == 0 { + glog.Errorf("Could not find available gRPC port for %s starting from %d, will use calculated %d and fail on binding", config.name, calculatedPort+1, calculatedPort) + calculatedPort = calculatedPort + } else { + calculatedPort = newPort + glog.Infof("gRPC port %d for %s is available, using it instead of calculated %d", newPort, config.name, *config.httpPort+10000) + } } *config.grpcPort = calculatedPort glog.V(1).Infof("%s gRPC port initialized to %d", config.name, calculatedPort) @@ -526,7 +499,12 @@ func initializeGrpcPortsOnIP(bindIp string) { if !isPortOpenOnIP(bindIp, *config.grpcPort) || !isPortAvailable(*config.grpcPort) { glog.Warningf("Explicitly set gRPC port %d for %s is not available, finding alternative...", *config.grpcPort, config.name) newPort := findAvailablePortOnIP(bindIp, *config.grpcPort+1, 100) - *config.grpcPort = newPort + if newPort == 0 { + glog.Errorf("Could not find available gRPC port for %s starting from %d, will use original %d and fail on binding", config.name, *config.grpcPort+1, *config.grpcPort) + } else { + glog.Infof("gRPC port %d for %s is available, using it instead of %d", newPort, config.name, *config.grpcPort) + *config.grpcPort = newPort + } } } }