github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/support-perf-net.go (about) 1 // Copyright (c) 2022 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package cmd 19 20 import ( 21 "context" 22 "os" 23 "time" 24 25 tea "github.com/charmbracelet/bubbletea" 26 "github.com/minio/cli" 27 "github.com/minio/madmin-go/v3" 28 "github.com/minio/mc/pkg/probe" 29 ) 30 31 func mainAdminSpeedTestNetperf(ctx *cli.Context, aliasedURL string, outCh chan<- PerfTestResult) error { 32 client, perr := newAdminClient(aliasedURL) 33 if perr != nil { 34 fatalIf(perr.Trace(aliasedURL), "Unable to initialize admin client.") 35 return nil 36 } 37 38 ctxt, cancel := context.WithCancel(globalContext) 39 defer cancel() 40 41 duration, e := time.ParseDuration(ctx.String("duration")) 42 if e != nil { 43 fatalIf(probe.NewError(e), "Unable to parse duration") 44 return nil 45 } 46 if duration <= 0 { 47 fatalIf(errInvalidArgument(), "duration cannot be 0 or negative") 48 return nil 49 } 50 51 resultCh := make(chan madmin.NetperfResult) 52 errorCh := make(chan error) 53 go func() { 54 defer close(resultCh) 55 defer close(errorCh) 56 57 result, e := client.Netperf(ctxt, duration) 58 if e != nil { 59 errorCh <- e 60 } 61 resultCh <- result 62 }() 63 64 if globalJSON { 65 select { 66 case e := <-errorCh: 67 printMsg(convertPerfResult(PerfTestResult{ 68 Type: NetPerfTest, 69 Err: e.Error(), 70 Final: true, 71 })) 72 case result := <-resultCh: 73 printMsg(convertPerfResult(PerfTestResult{ 74 Type: NetPerfTest, 75 NetResult: &result, 76 Final: true, 77 })) 78 } 79 return nil 80 } 81 82 done := make(chan struct{}) 83 84 p := tea.NewProgram(initSpeedTestUI()) 85 go func() { 86 if _, e := p.Run(); e != nil { 87 os.Exit(1) 88 } 89 close(done) 90 }() 91 92 go func() { 93 for { 94 select { 95 case e := <-errorCh: 96 r := PerfTestResult{ 97 Type: NetPerfTest, 98 Err: e.Error(), 99 Final: true, 100 } 101 p.Send(r) 102 if outCh != nil { 103 outCh <- r 104 } 105 return 106 case result := <-resultCh: 107 r := PerfTestResult{ 108 Type: NetPerfTest, 109 NetResult: &result, 110 Final: true, 111 } 112 p.Send(r) 113 if outCh != nil { 114 outCh <- r 115 } 116 return 117 default: 118 p.Send(PerfTestResult{ 119 Type: NetPerfTest, 120 NetResult: &madmin.NetperfResult{}, 121 }) 122 time.Sleep(100 * time.Millisecond) 123 } 124 } 125 }() 126 127 <-done 128 129 return nil 130 }