github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/network/stream/syncer.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 // 10 // 11 // 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 25 package stream 26 27 import ( 28 "context" 29 "math" 30 "strconv" 31 "time" 32 33 "github.com/ethereum/go-ethereum/metrics" 34 "github.com/ethereum/go-ethereum/swarm/log" 35 "github.com/ethereum/go-ethereum/swarm/storage" 36 ) 37 38 const ( 39 // 40 BatchSize = 128 41 ) 42 43 // 44 // 45 // 46 // 47 type SwarmSyncerServer struct { 48 po uint8 49 db *storage.DBAPI 50 sessionAt uint64 51 start uint64 52 quit chan struct{} 53 } 54 55 // 56 func NewSwarmSyncerServer(live bool, po uint8, db *storage.DBAPI) (*SwarmSyncerServer, error) { 57 sessionAt := db.CurrentBucketStorageIndex(po) 58 var start uint64 59 if live { 60 start = sessionAt 61 } 62 return &SwarmSyncerServer{ 63 po: po, 64 db: db, 65 sessionAt: sessionAt, 66 start: start, 67 quit: make(chan struct{}), 68 }, nil 69 } 70 71 func RegisterSwarmSyncerServer(streamer *Registry, db *storage.DBAPI) { 72 streamer.RegisterServerFunc("SYNC", func(p *Peer, t string, live bool) (Server, error) { 73 po, err := ParseSyncBinKey(t) 74 if err != nil { 75 return nil, err 76 } 77 return NewSwarmSyncerServer(live, po, db) 78 }) 79 // 80 // 81 // 82 } 83 84 // 85 func (s *SwarmSyncerServer) Close() { 86 close(s.quit) 87 } 88 89 // 90 func (s *SwarmSyncerServer) GetData(ctx context.Context, key []byte) ([]byte, error) { 91 chunk, err := s.db.Get(ctx, storage.Address(key)) 92 if err == storage.ErrFetching { 93 <-chunk.ReqC 94 } else if err != nil { 95 return nil, err 96 } 97 return chunk.SData, nil 98 } 99 100 // 101 func (s *SwarmSyncerServer) SetNextBatch(from, to uint64) ([]byte, uint64, uint64, *HandoverProof, error) { 102 var batch []byte 103 i := 0 104 if from == 0 { 105 from = s.start 106 } 107 if to <= from || from >= s.sessionAt { 108 to = math.MaxUint64 109 } 110 var ticker *time.Ticker 111 defer func() { 112 if ticker != nil { 113 ticker.Stop() 114 } 115 }() 116 var wait bool 117 for { 118 if wait { 119 if ticker == nil { 120 ticker = time.NewTicker(1000 * time.Millisecond) 121 } 122 select { 123 case <-ticker.C: 124 case <-s.quit: 125 return nil, 0, 0, nil, nil 126 } 127 } 128 129 metrics.GetOrRegisterCounter("syncer.setnextbatch.iterator", nil).Inc(1) 130 err := s.db.Iterator(from, to, s.po, func(addr storage.Address, idx uint64) bool { 131 batch = append(batch, addr[:]...) 132 i++ 133 to = idx 134 return i < BatchSize 135 }) 136 if err != nil { 137 return nil, 0, 0, nil, err 138 } 139 if len(batch) > 0 { 140 break 141 } 142 wait = true 143 } 144 145 log.Trace("Swarm syncer offer batch", "po", s.po, "len", i, "from", from, "to", to, "current store count", s.db.CurrentBucketStorageIndex(s.po)) 146 return batch, from, to, nil, nil 147 } 148 149 // 150 type SwarmSyncerClient struct { 151 sessionAt uint64 152 nextC chan struct{} 153 sessionRoot storage.Address 154 sessionReader storage.LazySectionReader 155 retrieveC chan *storage.Chunk 156 storeC chan *storage.Chunk 157 db *storage.DBAPI 158 // 159 currentRoot storage.Address 160 requestFunc func(chunk *storage.Chunk) 161 end, start uint64 162 peer *Peer 163 ignoreExistingRequest bool 164 stream Stream 165 } 166 167 // 168 func NewSwarmSyncerClient(p *Peer, db *storage.DBAPI, ignoreExistingRequest bool, stream Stream) (*SwarmSyncerClient, error) { 169 return &SwarmSyncerClient{ 170 db: db, 171 peer: p, 172 ignoreExistingRequest: ignoreExistingRequest, 173 stream: stream, 174 }, nil 175 } 176 177 // 178 // 179 // 180 // 181 // 182 // 183 // 184 // 185 // 186 // 187 // 188 // 189 // 190 // 191 // 192 // 193 // 194 // 195 // 196 // 197 // 198 199 // 200 // 201 // 202 // 203 // 204 // 205 // 206 // 207 // 208 // 209 // 210 // 211 // 212 213 // 214 // 215 func RegisterSwarmSyncerClient(streamer *Registry, db *storage.DBAPI) { 216 streamer.RegisterClientFunc("SYNC", func(p *Peer, t string, live bool) (Client, error) { 217 return NewSwarmSyncerClient(p, db, true, NewStream("SYNC", t, live)) 218 }) 219 } 220 221 // 222 func (s *SwarmSyncerClient) NeedData(ctx context.Context, key []byte) (wait func()) { 223 chunk, _ := s.db.GetOrCreateRequest(ctx, key) 224 // 225 226 // 227 // 228 if chunk.ReqC == nil { // 229 return nil 230 } 231 // 232 return func() { 233 chunk.WaitToStore() 234 } 235 } 236 237 // 238 func (s *SwarmSyncerClient) BatchDone(stream Stream, from uint64, hashes []byte, root []byte) func() (*TakeoverProof, error) { 239 // 240 // 241 // 242 // 243 return nil 244 } 245 246 func (s *SwarmSyncerClient) TakeoverProof(stream Stream, from uint64, hashes []byte, root storage.Address) (*TakeoverProof, error) { 247 // 248 // 249 // 250 // 251 // 252 // 253 // 254 // 255 // 256 // 257 // 258 // 259 // 260 // 261 // 262 // 263 // 264 // 265 // 266 // 267 // 268 // 269 // 270 // 271 // 272 s.end += uint64(len(hashes)) / HashSize 273 takeover := &Takeover{ 274 Stream: stream, 275 Start: s.start, 276 End: s.end, 277 Root: root, 278 } 279 // 280 return &TakeoverProof{ 281 Takeover: takeover, 282 Sig: nil, 283 }, nil 284 } 285 286 func (s *SwarmSyncerClient) Close() {} 287 288 // 289 // 290 const syncBinKeyBase = 36 291 292 // 293 // 294 func FormatSyncBinKey(bin uint8) string { 295 return strconv.FormatUint(uint64(bin), syncBinKeyBase) 296 } 297 298 // 299 // 300 func ParseSyncBinKey(s string) (uint8, error) { 301 bin, err := strconv.ParseUint(s, syncBinKeyBase, 8) 302 if err != nil { 303 return 0, err 304 } 305 return uint8(bin), nil 306 }