github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/network/stream/syncer.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:48</date>
    10  //</624342676291981312>
    11  
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  //
    25  //
    26  //
    27  
    28  package stream
    29  
    30  import (
    31  	"context"
    32  	"math"
    33  	"strconv"
    34  	"time"
    35  
    36  	"github.com/ethereum/go-ethereum/metrics"
    37  	"github.com/ethereum/go-ethereum/swarm/log"
    38  	"github.com/ethereum/go-ethereum/swarm/storage"
    39  )
    40  
    41  const (
    42  //
    43  	BatchSize = 128
    44  )
    45  
    46  //
    47  //
    48  //
    49  //
    50  type SwarmSyncerServer struct {
    51  	po        uint8
    52  	db        *storage.DBAPI
    53  	sessionAt uint64
    54  	start     uint64
    55  	quit      chan struct{}
    56  }
    57  
    58  //
    59  func NewSwarmSyncerServer(live bool, po uint8, db *storage.DBAPI) (*SwarmSyncerServer, error) {
    60  	sessionAt := db.CurrentBucketStorageIndex(po)
    61  	var start uint64
    62  	if live {
    63  		start = sessionAt
    64  	}
    65  	return &SwarmSyncerServer{
    66  		po:        po,
    67  		db:        db,
    68  		sessionAt: sessionAt,
    69  		start:     start,
    70  		quit:      make(chan struct{}),
    71  	}, nil
    72  }
    73  
    74  func RegisterSwarmSyncerServer(streamer *Registry, db *storage.DBAPI) {
    75  	streamer.RegisterServerFunc("SYNC", func(p *Peer, t string, live bool) (Server, error) {
    76  		po, err := ParseSyncBinKey(t)
    77  		if err != nil {
    78  			return nil, err
    79  		}
    80  		return NewSwarmSyncerServer(live, po, db)
    81  	})
    82  //
    83  //
    84  //
    85  }
    86  
    87  //
    88  func (s *SwarmSyncerServer) Close() {
    89  	close(s.quit)
    90  }
    91  
    92  //
    93  func (s *SwarmSyncerServer) GetData(ctx context.Context, key []byte) ([]byte, error) {
    94  	chunk, err := s.db.Get(ctx, storage.Address(key))
    95  	if err == storage.ErrFetching {
    96  		<-chunk.ReqC
    97  	} else if err != nil {
    98  		return nil, err
    99  	}
   100  	return chunk.SData, nil
   101  }
   102  
   103  //
   104  func (s *SwarmSyncerServer) SetNextBatch(from, to uint64) ([]byte, uint64, uint64, *HandoverProof, error) {
   105  	var batch []byte
   106  	i := 0
   107  	if from == 0 {
   108  		from = s.start
   109  	}
   110  	if to <= from || from >= s.sessionAt {
   111  		to = math.MaxUint64
   112  	}
   113  	var ticker *time.Ticker
   114  	defer func() {
   115  		if ticker != nil {
   116  			ticker.Stop()
   117  		}
   118  	}()
   119  	var wait bool
   120  	for {
   121  		if wait {
   122  			if ticker == nil {
   123  				ticker = time.NewTicker(1000 * time.Millisecond)
   124  			}
   125  			select {
   126  			case <-ticker.C:
   127  			case <-s.quit:
   128  				return nil, 0, 0, nil, nil
   129  			}
   130  		}
   131  
   132  		metrics.GetOrRegisterCounter("syncer.setnextbatch.iterator", nil).Inc(1)
   133  		err := s.db.Iterator(from, to, s.po, func(addr storage.Address, idx uint64) bool {
   134  			batch = append(batch, addr[:]...)
   135  			i++
   136  			to = idx
   137  			return i < BatchSize
   138  		})
   139  		if err != nil {
   140  			return nil, 0, 0, nil, err
   141  		}
   142  		if len(batch) > 0 {
   143  			break
   144  		}
   145  		wait = true
   146  	}
   147  
   148  	log.Trace("Swarm syncer offer batch", "po", s.po, "len", i, "from", from, "to", to, "current store count", s.db.CurrentBucketStorageIndex(s.po))
   149  	return batch, from, to, nil, nil
   150  }
   151  
   152  //
   153  type SwarmSyncerClient struct {
   154  	sessionAt     uint64
   155  	nextC         chan struct{}
   156  	sessionRoot   storage.Address
   157  	sessionReader storage.LazySectionReader
   158  	retrieveC     chan *storage.Chunk
   159  	storeC        chan *storage.Chunk
   160  	db            *storage.DBAPI
   161  //
   162  	currentRoot           storage.Address
   163  	requestFunc           func(chunk *storage.Chunk)
   164  	end, start            uint64
   165  	peer                  *Peer
   166  	ignoreExistingRequest bool
   167  	stream                Stream
   168  }
   169  
   170  //
   171  func NewSwarmSyncerClient(p *Peer, db *storage.DBAPI, ignoreExistingRequest bool, stream Stream) (*SwarmSyncerClient, error) {
   172  	return &SwarmSyncerClient{
   173  		db:   db,
   174  		peer: p,
   175  		ignoreExistingRequest: ignoreExistingRequest,
   176  		stream:                stream,
   177  	}, nil
   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  
   216  //
   217  //
   218  func RegisterSwarmSyncerClient(streamer *Registry, db *storage.DBAPI) {
   219  	streamer.RegisterClientFunc("SYNC", func(p *Peer, t string, live bool) (Client, error) {
   220  		return NewSwarmSyncerClient(p, db, true, NewStream("SYNC", t, live))
   221  	})
   222  }
   223  
   224  //
   225  func (s *SwarmSyncerClient) NeedData(ctx context.Context, key []byte) (wait func()) {
   226  	chunk, _ := s.db.GetOrCreateRequest(ctx, key)
   227  //
   228  
   229  //
   230  //
   231  if chunk.ReqC == nil { //
   232  		return nil
   233  	}
   234  //
   235  	return func() {
   236  		chunk.WaitToStore()
   237  	}
   238  }
   239  
   240  //
   241  func (s *SwarmSyncerClient) BatchDone(stream Stream, from uint64, hashes []byte, root []byte) func() (*TakeoverProof, error) {
   242  //
   243  //
   244  //
   245  //
   246  	return nil
   247  }
   248  
   249  func (s *SwarmSyncerClient) TakeoverProof(stream Stream, from uint64, hashes []byte, root storage.Address) (*TakeoverProof, error) {
   250  //
   251  //
   252  //
   253  //
   254  //
   255  //
   256  //
   257  //
   258  //
   259  //
   260  //
   261  //
   262  //
   263  //
   264  //
   265  //
   266  //
   267  //
   268  //
   269  //
   270  //
   271  //
   272  //
   273  //
   274  //
   275  	s.end += uint64(len(hashes)) / HashSize
   276  	takeover := &Takeover{
   277  		Stream: stream,
   278  		Start:  s.start,
   279  		End:    s.end,
   280  		Root:   root,
   281  	}
   282  //
   283  	return &TakeoverProof{
   284  		Takeover: takeover,
   285  		Sig:      nil,
   286  	}, nil
   287  }
   288  
   289  func (s *SwarmSyncerClient) Close() {}
   290  
   291  //
   292  //
   293  const syncBinKeyBase = 36
   294  
   295  //
   296  //
   297  func FormatSyncBinKey(bin uint8) string {
   298  	return strconv.FormatUint(uint64(bin), syncBinKeyBase)
   299  }
   300  
   301  //
   302  //
   303  func ParseSyncBinKey(s string) (uint8, error) {
   304  	bin, err := strconv.ParseUint(s, syncBinKeyBase, 8)
   305  	if err != nil {
   306  		return 0, err
   307  	}
   308  	return uint8(bin), nil
   309  }
   310