gitee.com/lh-her-team/common@v1.5.1/birdsnest/serialize.go (about) 1 // Package birdsnest serialize 2 package birdsnest 3 4 import ( 5 "encoding/json" 6 "reflect" 7 "time" 8 9 birdsnestpb "gitee.com/lh-her-team/common/birdsnest/pb" 10 11 "github.com/gogo/protobuf/proto" 12 ) 13 14 // TODO Split BirdsNestImpl and Serialize 15 16 // Start serialize monitor TODO Goroutinue should be turned off using context.Context here 17 func (b *BirdsNestImpl) Start() { 18 go b.serializeMonitor() 19 go b.serializeTimed() 20 } 21 22 // serializeMonitor 23 func (b *BirdsNestImpl) serializeMonitor() { 24 for { // nolint 25 select { 26 // Only signals for the current filter "serialized type" are received 27 case signal := <-b.serializeC: 28 t, ok := SerializeIntervalType_name[signal.typ] 29 if !ok { 30 b.log.Errorf("serialize type %v not support", t) 31 } 32 switch signal.typ { 33 case SerializeIntervalType_Height: 34 // current height - pre height < height interval does not serialize; otherwise, it serialize 35 // eg: 85 - 80 = 5 < 10 36 // 5 < 10 true does not serialize 37 if b.height-b.preHeight.Load() < b.config.Snapshot.BlockHeight.Interval { 38 continue 39 } 40 case SerializeIntervalType_Timed, SerializeIntervalType_Exit: 41 // common.SerializeIntervalType_Timed and common.SerializeIntervalType_Exit are handled directly 42 default: 43 continue 44 } 45 err := b.Serialize() 46 if err != nil { 47 b.log.Errorf("serialize error type: %v, error: %v", t, err) 48 } 49 } 50 } 51 } 52 53 // Serialize all cuckoos in the current BirdsNest 54 func (b *BirdsNestImpl) Serialize() error { 55 t := time.Now() 56 // Logs are print after the method is complete 57 defer func(log Logger) { 58 elapsed := time.Since(t) 59 log.Debugf("bird's nest serialize success elapsed: %v", elapsed) 60 }(b.log) 61 // convert []CuckooFilter to []*common.CuckooFilter 62 var filters []*birdsnestpb.CuckooFilter 63 filters, err := analysisCuckooFilters(b.filters) 64 if err != nil { 65 return err 66 } 67 marshal, err := json.Marshal(b.config) 68 if err != nil { 69 return err 70 } 71 birdsNest := &birdsnestpb.BirdsNest{ 72 Config: marshal, 73 Height: b.preHeight.Load(), 74 CurrentIndex: uint32(b.currentIndex), 75 Filters: filters, 76 } 77 data, err := proto.Marshal(birdsNest) 78 if err != nil { 79 return err 80 } 81 // Write to disk 82 err = b.snapshot.Write(data) 83 if err != nil { 84 return err 85 } 86 // Increase the height 87 b.preHeight.Store(b.height) 88 return nil 89 } 90 91 // Deserialize deserialize Bird's nest 92 func (b *BirdsNestImpl) Deserialize() error { 93 data, err := b.snapshot.Read() 94 if err != nil { 95 return err 96 } 97 if data == nil { 98 return nil 99 } 100 var bn = new(birdsnestpb.BirdsNest) 101 err = proto.Unmarshal(data, bn) 102 if err != nil { 103 return err 104 } 105 filters, err := newCuckooFiltersByDecode(bn.Filters) 106 if err != nil { 107 return err 108 } 109 var bnConfig BirdsNestConfig 110 err = json.Unmarshal(bn.Config, &bnConfig) 111 if err != nil { 112 return err 113 } 114 if !reflect.DeepEqual(bnConfig, b.config) { 115 err = ErrCannotModifyTheNestConfiguration 116 } 117 b.filters = filters 118 b.config = &bnConfig 119 b.height = bn.Height 120 b.currentIndex = int(bn.CurrentIndex) 121 return err 122 } 123 124 // serializeTimed send SerializeIntervalType_Timed sign 125 func (b *BirdsNestImpl) serializeTimed() { 126 if b.config.Snapshot.Type != SerializeIntervalType_Timed { 127 return 128 } 129 ticker := time.NewTicker(time.Second * time.Duration(b.config.Snapshot.Timed.Interval)) 130 // nolint 131 for { 132 select { 133 case <-ticker.C: 134 b.serializeC <- serializeSignal{typ: SerializeIntervalType_Timed} 135 } 136 } 137 } 138 139 // serializeExit send SerializeIntervalType_Exit sign 140 // nolint: unused 141 func (b *BirdsNestImpl) serializeExit() { 142 b.serializeC <- serializeSignal{typ: SerializeIntervalType_Exit} 143 } 144 145 // serializeHeight send SerializeIntervalType_Height sign 146 func (b *BirdsNestImpl) serializeHeight(height uint64) { 147 if b.config.Snapshot.Type != SerializeIntervalType_Height { 148 return 149 } 150 b.serializeC <- serializeSignal{typ: SerializeIntervalType_Height, height: height} 151 } 152 153 // Serialize signal 154 type serializeSignal struct { 155 typ SerializeIntervalType 156 height uint64 157 }