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  }