github.com/matrixorigin/matrixone@v1.2.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(
    49  		ctx,
    50  		address,
    51  		respPool,
    52  		defaultMaxMessageSize,
    53  		false,
    54  		0,
    55  		"GetShardInfo",
    56  	)
    57  	if err != nil {
    58  		return ShardInfo{}, false, err
    59  	}
    60  	defer func() {
    61  		if err := cc.Close(); err != nil {
    62  			logutil.Error("failed to close client", zap.Error(err))
    63  		}
    64  	}()
    65  	ctx, span := trace.Debug(ctx, "GetShardInfo")
    66  	defer span.End()
    67  	req := pb.Request{
    68  		Method: pb.GET_SHARD_INFO,
    69  		LogRequest: pb.LogRequest{
    70  			ShardID: shardID,
    71  		},
    72  	}
    73  	rpcReq := &RPCRequest{
    74  		Request: req,
    75  	}
    76  	future, err := cc.Send(ctx, address, rpcReq)
    77  	if err != nil {
    78  		return ShardInfo{}, false, err
    79  	}
    80  	defer future.Close()
    81  	msg, err := future.Get()
    82  	if err != nil {
    83  		return ShardInfo{}, false, err
    84  	}
    85  	response, ok := msg.(*RPCResponse)
    86  	if !ok {
    87  		panic("unexpected response type")
    88  	}
    89  	resp := response.Response
    90  	defer response.Release()
    91  	err = toError(ctx, resp)
    92  	if err != nil {
    93  		return ShardInfo{}, false, err
    94  	}
    95  	si := *resp.ShardInfo
    96  	if reflect.DeepEqual(si, pb.ShardInfoQueryResult{}) {
    97  		return ShardInfo{}, false, nil
    98  	}
    99  	// leader address is unknown
   100  	if _, ok := si.Replicas[si.LeaderID]; !ok {
   101  		return ShardInfo{}, false, nil
   102  	}
   103  	result := ShardInfo{
   104  		ReplicaID: si.LeaderID,
   105  		Replicas:  make(map[uint64]string),
   106  	}
   107  	for replicaID, info := range si.Replicas {
   108  		result.Replicas[replicaID] = info.ServiceAddress
   109  	}
   110  	return result, true, nil
   111  }
   112  
   113  func (s *Service) getShardInfo(shardID uint64) (pb.ShardInfoQueryResult, bool) {
   114  	r, ok := s.store.nh.GetNodeHostRegistry()
   115  	if !ok {
   116  		panic(moerr.NewInvalidStateNoCtx("gossip registry not enabled"))
   117  	}
   118  	shard, ok := r.GetShardInfo(shardID)
   119  	if !ok {
   120  		return pb.ShardInfoQueryResult{}, false
   121  	}
   122  	result := pb.ShardInfoQueryResult{
   123  		ShardID:  shard.ShardID,
   124  		Epoch:    shard.ConfigChangeIndex,
   125  		LeaderID: shard.LeaderID,
   126  		Term:     shard.Term,
   127  		Replicas: make(map[uint64]pb.ReplicaInfo),
   128  	}
   129  	for nodeID, uuid := range shard.Nodes {
   130  		data, ok := r.GetMeta(uuid)
   131  		if !ok {
   132  			continue
   133  		}
   134  		var md storeMeta
   135  		md.unmarshal(data)
   136  		result.Replicas[nodeID] = pb.ReplicaInfo{
   137  			UUID:           uuid,
   138  			ServiceAddress: md.serviceAddress,
   139  		}
   140  	}
   141  	return result, true
   142  }