gitee.com/lh-her-team/common@v1.5.1/shardingbirdsnest/serialize.go (about)

     1  // Package shardingbirdsnest serialize
     2  package shardingbirdsnest
     3  
     4  import (
     5  	"encoding/json"
     6  	"reflect"
     7  	"time"
     8  
     9  	bn "gitee.com/lh-her-team/common/birdsnest"
    10  	"gitee.com/lh-her-team/common/shardingbirdsnest/pb"
    11  	"github.com/gogo/protobuf/proto"
    12  )
    13  
    14  // Start TODO Goroutinue should be turned off using context.Context here
    15  func (s *ShardingBirdsNest) Start() {
    16  	// start serialize monitor
    17  	go s.serializeMonitor()
    18  	// start serialize timed
    19  	go s.serializeTimed()
    20  	// start all bird's nest
    21  	for i := range s.bn {
    22  		s.bn[i].Start()
    23  	}
    24  }
    25  
    26  // Serialize serialize to wal
    27  func (s *ShardingBirdsNest) Serialize() error {
    28  	t := time.Now()
    29  	// Logs are print after the method is complete
    30  	defer func(log bn.Logger) {
    31  		elapsed := time.Since(t)
    32  		log.Infof("sharding bird's nest serialize success elapsed: %v", elapsed)
    33  	}(s.log)
    34  	// config to json
    35  	conf, err := json.Marshal(s.config)
    36  	if err != nil {
    37  		return err
    38  	}
    39  	// sharding bird's nest pb
    40  	sbn := &pb.ShardingBirdsNest{
    41  		Length: s.config.Length,
    42  		Height: s.height,
    43  		Config: conf,
    44  	}
    45  	// sharding bird's nest pb to byte
    46  	data, err := proto.Marshal(sbn)
    47  	if err != nil {
    48  		return err
    49  	}
    50  	// snapshot data
    51  	err = s.snapshot.Write(data)
    52  	if err != nil {
    53  		return err
    54  	}
    55  	// cover pre height
    56  	s.preHeight.Store(s.height)
    57  	return nil
    58  }
    59  
    60  // Deserialize deserialize configuration
    61  func (s *ShardingBirdsNest) Deserialize() error {
    62  	// read snapshot
    63  	data, err := s.snapshot.Read()
    64  	if err != nil {
    65  		return err
    66  	}
    67  	// If there is no data on the disk, the procedure ends
    68  	if data == nil {
    69  		return nil
    70  	}
    71  	sharding := new(pb.ShardingBirdsNest)
    72  	// unmarshal data to pb sharding bird's nest
    73  	err = proto.Unmarshal(data, sharding)
    74  	if err != nil {
    75  		return err
    76  	}
    77  	var sbnConfig ShardingBirdsNestConfig
    78  	err = json.Unmarshal(sharding.Config, &sbnConfig)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	// equal disk config and file config
    83  	if reflect.DeepEqual(sbnConfig, s.config) {
    84  		err = ErrCannotModifyTheNestConfiguration
    85  	}
    86  	s.height = sharding.Height
    87  	return err
    88  }
    89  
    90  // serializeMonitor start serialize monitor TODO Goroutinue should be turned off using context.Context here
    91  func (s *ShardingBirdsNest) serializeMonitor() {
    92  	for { // nolint
    93  		select {
    94  		// 只有当前"序列化类型"的信号才能过来
    95  		case signal := <-s.serializeC:
    96  			t, ok := bn.SerializeIntervalType_name[signal.typ]
    97  			if !ok {
    98  				s.log.Errorf("serialize type %v not support", t)
    99  			}
   100  			switch signal.typ {
   101  			case bn.SerializeIntervalType_Height:
   102  				// 并且 当前高度 - 上次持久化高度 < 高度间隔 则不做持久化 否则,执行持久化
   103  				// eg: 85 - 80 = 5 < 10
   104  				// 	   5 < 10 true 则不做持久化
   105  				if s.height-s.preHeight.Load() < s.config.Snapshot.BlockHeight.Interval {
   106  					continue
   107  				}
   108  			case bn.SerializeIntervalType_Timed, bn.SerializeIntervalType_Exit:
   109  				// "时间序列化类型"和"退出序列化类型"直接处理
   110  			default:
   111  				continue
   112  			}
   113  			// serialize
   114  			err := s.Serialize()
   115  			if err != nil {
   116  				s.log.Errorf("serialize error type: %v, error: %v", t, err)
   117  			}
   118  		}
   119  	}
   120  }
   121  
   122  // serializeTimed serialize by timed sign
   123  func (s *ShardingBirdsNest) serializeTimed() {
   124  	// The current serialization type terminates if it is not bn.SerializeIntervalType_Timed
   125  	if s.config.Snapshot.Type != bn.SerializeIntervalType_Timed {
   126  		return
   127  	}
   128  	// start Timing task
   129  	ticker := time.NewTicker(time.Second * time.Duration(s.config.Snapshot.Timed.Interval))
   130  	// nolint
   131  	for {
   132  		select {
   133  		case <-ticker.C:
   134  			// Timing signal
   135  			s.serializeC <- serializeSignal{typ: bn.SerializeIntervalType_Timed}
   136  		}
   137  	}
   138  }
   139  
   140  // serializeExit serialize by exit sign
   141  // nolint: unused
   142  func (s *ShardingBirdsNest) serializeExit() {
   143  	// send bn.SerializeIntervalType_Exit sign
   144  	s.serializeC <- serializeSignal{typ: bn.SerializeIntervalType_Exit}
   145  }
   146  
   147  // serializeHeight serialize by SerializeIntervalType_Height sign
   148  func (s *ShardingBirdsNest) serializeHeight(height uint64) {
   149  	if s.config.Snapshot.Type != bn.SerializeIntervalType_Height {
   150  		return
   151  	}
   152  	// send bn.SerializeIntervalType_Height sign
   153  	s.serializeC <- serializeSignal{typ: bn.SerializeIntervalType_Height, height: height}
   154  }
   155  
   156  // Serialize signal
   157  type serializeSignal struct {
   158  	// typ bn.SerializeIntervalType type
   159  	typ bn.SerializeIntervalType
   160  	// current height
   161  	height uint64
   162  }