github.com/matrixorigin/matrixone@v0.7.0/pkg/logservice/shardinfo.go (about) 1 // Copyright 2021 - 2022 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 logservice 16 17 import ( 18 "context" 19 "reflect" 20 "sync" 21 "time" 22 23 "github.com/matrixorigin/matrixone/pkg/logutil" 24 "github.com/matrixorigin/matrixone/pkg/util/trace" 25 "go.uber.org/zap" 26 27 "github.com/matrixorigin/matrixone/pkg/common/moerr" 28 pb "github.com/matrixorigin/matrixone/pkg/pb/logservice" 29 ) 30 31 type ShardInfo struct { 32 // ReplicaID is the ID of the replica recommended to use 33 ReplicaID uint64 34 // Replicas is a map of replica ID to their service addresses 35 Replicas map[uint64]string 36 } 37 38 // GetShardInfo is to be invoked when querying ShardInfo on a Log Service node. 39 // address is usually the reverse proxy that randomly redirect the request to 40 // a known Log Service node. 41 func GetShardInfo(address string, shardID uint64) (ShardInfo, bool, error) { 42 respPool := &sync.Pool{} 43 respPool.New = func() interface{} { 44 return &RPCResponse{pool: respPool} 45 } 46 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 47 defer cancel() 48 cc, err := getRPCClient(ctx, address, respPool, defaultMaxMessageSize, false, "GetShardInfo") 49 if err != nil { 50 return ShardInfo{}, false, err 51 } 52 defer func() { 53 if err := cc.Close(); err != nil { 54 logutil.Error("failed to close client", zap.Error(err)) 55 } 56 }() 57 ctx, span := trace.Debug(ctx, "GetShardInfo") 58 defer span.End() 59 req := pb.Request{ 60 Method: pb.GET_SHARD_INFO, 61 LogRequest: pb.LogRequest{ 62 ShardID: shardID, 63 }, 64 } 65 rpcReq := &RPCRequest{ 66 Request: req, 67 } 68 future, err := cc.Send(ctx, address, rpcReq) 69 if err != nil { 70 return ShardInfo{}, false, err 71 } 72 defer future.Close() 73 msg, err := future.Get() 74 if err != nil { 75 return ShardInfo{}, false, err 76 } 77 response, ok := msg.(*RPCResponse) 78 if !ok { 79 panic("unexpected response type") 80 } 81 resp := response.Response 82 defer response.Release() 83 err = toError(ctx, resp) 84 if err != nil { 85 return ShardInfo{}, false, err 86 } 87 si := *resp.ShardInfo 88 if reflect.DeepEqual(si, pb.ShardInfoQueryResult{}) { 89 return ShardInfo{}, false, nil 90 } 91 // leader address is unknown 92 if _, ok := si.Replicas[si.LeaderID]; !ok { 93 return ShardInfo{}, false, nil 94 } 95 result := ShardInfo{ 96 ReplicaID: si.LeaderID, 97 Replicas: make(map[uint64]string), 98 } 99 for replicaID, info := range si.Replicas { 100 result.Replicas[replicaID] = info.ServiceAddress 101 } 102 return result, true, nil 103 } 104 105 func (s *Service) getShardInfo(shardID uint64) (pb.ShardInfoQueryResult, bool) { 106 r, ok := s.store.nh.GetNodeHostRegistry() 107 if !ok { 108 panic(moerr.NewInvalidStateNoCtx("gossip registry not enabled")) 109 } 110 shard, ok := r.GetShardInfo(shardID) 111 if !ok { 112 return pb.ShardInfoQueryResult{}, false 113 } 114 result := pb.ShardInfoQueryResult{ 115 ShardID: shard.ShardID, 116 Epoch: shard.ConfigChangeIndex, 117 LeaderID: shard.LeaderID, 118 Term: shard.Term, 119 Replicas: make(map[uint64]pb.ReplicaInfo), 120 } 121 for nodeID, uuid := range shard.Nodes { 122 data, ok := r.GetMeta(uuid) 123 if !ok { 124 return pb.ShardInfoQueryResult{}, false 125 } 126 var md storeMeta 127 md.unmarshal(data) 128 result.Replicas[nodeID] = pb.ReplicaInfo{ 129 UUID: uuid, 130 ServiceAddress: md.serviceAddress, 131 } 132 } 133 return result, true 134 }