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  }