github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/function/ctl/cmd_rpc_version.go (about) 1 // Copyright 2023 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ctl 16 17 import ( 18 "context" 19 "fmt" 20 "strconv" 21 "strings" 22 "time" 23 24 "github.com/matrixorigin/matrixone/pkg/clusterservice" 25 "github.com/matrixorigin/matrixone/pkg/common/moerr" 26 "github.com/matrixorigin/matrixone/pkg/pb/metadata" 27 querypb "github.com/matrixorigin/matrixone/pkg/pb/query" 28 qclient "github.com/matrixorigin/matrixone/pkg/queryservice/client" 29 "github.com/matrixorigin/matrixone/pkg/vm/process" 30 ) 31 32 func handleGetProtocolVersion(proc *process.Process, 33 service serviceType, 34 parameter string, 35 sender requestSender) (Result, error) { 36 qt := proc.QueryClient 37 mc := clusterservice.GetMOCluster() 38 var addrs []string 39 var nodeIds []string 40 mc.GetCNService( 41 clusterservice.NewSelector(), 42 func(c metadata.CNService) bool { 43 addrs = append(addrs, c.QueryAddress) 44 nodeIds = append(nodeIds, c.ServiceID) 45 return true 46 }) 47 mc.GetTNService( 48 clusterservice.NewSelector(), 49 func(d metadata.TNService) bool { 50 if d.QueryAddress != "" { 51 addrs = append(addrs, d.QueryAddress) 52 nodeIds = append(nodeIds, d.ServiceID) 53 } 54 return true 55 }) 56 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 57 defer cancel() 58 59 versions := make([]string, 0, len(addrs)) 60 for i, addr := range addrs { 61 req := qt.NewRequest(querypb.CmdMethod_GetProtocolVersion) 62 req.GetProtocolVersion = &querypb.GetProtocolVersionRequest{} 63 resp, err := qt.SendMessage(ctx, addr, req) 64 if err != nil { 65 return Result{}, err 66 } 67 versions = append(versions, fmt.Sprintf("%s:%d", nodeIds[i], resp.GetProtocolVersion.Version)) 68 qt.Release(resp) 69 } 70 71 return Result{ 72 Method: GetProtocolVersionMethod, 73 Data: strings.Join(versions, ", "), 74 }, nil 75 } 76 77 // handleSetProtocolVersion sets the version of mo components' protocol versions 78 // 79 // the cmd format for CN service: 80 // 81 // mo_ctl("cn", "SetProtocolVersion" "uuids of cn:protocol version") 82 // 83 // examples as below: 84 // 85 // mo_ctl("cn", "SetProtocolVersion", "cn_uuid1:1") 86 // mo_ctl("cn", "SetProtocolVersion", "cn_uuid1,cn_uuid2,...:2") 87 // 88 // the cmd format for TN service: 89 // 90 // mo_ctl("dn", "SetProtocolVersion", "protocol version") 91 // 92 // (because there only exist one dn service, so we don't need to specify the uuid, 93 // 94 // but, the uuid will be ignored and will not check its validation even though it is specified.) 95 // 96 // examples as below: 97 // mo_ctl("dn", "SetProtocolVersion", "1") 98 func handleSetProtocolVersion(proc *process.Process, 99 service serviceType, 100 parameter string, 101 sender requestSender) (Result, error) { 102 qt := proc.QueryClient 103 targets, version, err := checkProtocolParameter(parameter) 104 if err != nil { 105 return Result{}, err 106 } 107 if service == tn && targets == nil { 108 // set protocol version for tn node 109 // there only exist one tn node, so we don't need to specify the uuid 110 return transferToTN(qt, version) 111 } 112 113 if service == cn && targets != nil { 114 versions := make([]string, 0, len(targets)) 115 for _, target := range targets { 116 resp, err := transferToCN(qt, target, version) 117 if err != nil { 118 return Result{}, err 119 } 120 if resp == nil { 121 return Result{}, moerr.NewInternalErrorNoCtx("no such cn service") 122 } 123 versions = append(versions, fmt.Sprintf("%s:%d", target, resp.SetProtocolVersion.Version)) 124 } 125 126 return Result{ 127 Method: SetProtocolVersionMethod, 128 Data: strings.Join(versions, ", "), 129 }, nil 130 } 131 132 return Result{}, moerr.NewInternalError(proc.Ctx, "unsupported cmd") 133 } 134 135 func checkProtocolParameter(param string) ([]string, int64, error) { 136 param = strings.ToLower(param) 137 // [uuids]:version 138 args := strings.Split(param, ":") 139 if len(args) > 2 { 140 return nil, 0, moerr.NewInternalErrorNoCtx("cmd invalid, too many ':'") 141 } 142 version, err := strconv.ParseInt(args[len(args)-1], 10, 64) 143 if err != nil { 144 return nil, 0, moerr.NewInternalErrorNoCtx("cmd invalid, expected version number") 145 } 146 147 if len(args) == 2 { 148 arg := args[0] 149 targets := strings.Split(arg, ",") 150 return targets, version, nil 151 } 152 153 return nil, version, nil 154 } 155 156 func transferToTN(qt qclient.QueryClient, version int64) (Result, error) { 157 var addr string 158 var resp *querypb.Response 159 var err error 160 clusterservice.GetMOCluster().GetTNService( 161 clusterservice.NewSelector(), 162 func(t metadata.TNService) bool { 163 if t.QueryAddress == "" { 164 return true 165 } 166 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 167 defer cancel() 168 req := qt.NewRequest(querypb.CmdMethod_SetProtocolVersion) 169 req.SetProtocolVersion = &querypb.SetProtocolVersionRequest{ 170 Version: version, 171 } 172 resp, err = qt.SendMessage(ctx, addr, req) 173 return true 174 }) 175 if err != nil { 176 return Result{}, err 177 } 178 if resp == nil { 179 return Result{}, moerr.NewInternalErrorNoCtx("no such tn service") 180 } 181 defer qt.Release(resp) 182 return Result{ 183 Method: SetProtocolVersionMethod, 184 Data: strconv.FormatInt(resp.SetProtocolVersion.Version, 10), 185 }, nil 186 } 187 188 func transferToCN(qt qclient.QueryClient, target string, version int64) (resp *querypb.Response, err error) { 189 clusterservice.GetMOCluster().GetCNService( 190 clusterservice.NewServiceIDSelector(target), 191 func(cn metadata.CNService) bool { 192 req := qt.NewRequest(querypb.CmdMethod_SetProtocolVersion) 193 req.SetProtocolVersion = &querypb.SetProtocolVersionRequest{ 194 Version: version, 195 } 196 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 197 defer cancel() 198 199 resp, err = qt.SendMessage(ctx, cn.QueryAddress, req) 200 return true 201 }) 202 if err != nil { 203 return nil, err 204 } 205 return resp, nil 206 }