github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/netstore.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 storage
    26  
    27  import (
    28  	"context"
    29  	"time"
    30  
    31  	"github.com/ethereum/go-ethereum/swarm/log"
    32  	"github.com/ethereum/go-ethereum/swarm/spancontext"
    33  	opentracing "github.com/opentracing/opentracing-go"
    34  )
    35  
    36  var (
    37  //
    38  //
    39  //
    40  	netStoreRetryTimeout = 30 * time.Second
    41  //
    42  //
    43  //
    44  	netStoreMinRetryDelay = 3 * time.Second
    45  //
    46  //
    47  //
    48  	searchTimeout = 10 * time.Second
    49  )
    50  
    51  //
    52  //
    53  //
    54  //
    55  type NetStore struct {
    56  	localStore *LocalStore
    57  	retrieve   func(ctx context.Context, chunk *Chunk) error
    58  }
    59  
    60  func NewNetStore(localStore *LocalStore, retrieve func(ctx context.Context, chunk *Chunk) error) *NetStore {
    61  	return &NetStore{localStore, retrieve}
    62  }
    63  
    64  //
    65  //
    66  //
    67  //
    68  //
    69  //
    70  func (ns *NetStore) Get(ctx context.Context, addr Address) (chunk *Chunk, err error) {
    71  
    72  	var sp opentracing.Span
    73  	ctx, sp = spancontext.StartSpan(
    74  		ctx,
    75  		"netstore.get.global")
    76  	defer sp.Finish()
    77  
    78  	timer := time.NewTimer(netStoreRetryTimeout)
    79  	defer timer.Stop()
    80  
    81  //
    82  //
    83  	type result struct {
    84  		chunk *Chunk
    85  		err   error
    86  	}
    87  	resultC := make(chan result)
    88  
    89  //
    90  //
    91  	quitC := make(chan struct{})
    92  	defer close(quitC)
    93  
    94  //
    95  //
    96  	go func() {
    97  //
    98  //
    99  //
   100  //
   101  		limiter := time.NewTimer(netStoreMinRetryDelay)
   102  		defer limiter.Stop()
   103  
   104  		for {
   105  			chunk, err := ns.get(ctx, addr, 0)
   106  			if err != ErrChunkNotFound {
   107  //
   108  //
   109  				select {
   110  				case <-quitC:
   111  //
   112  //
   113  //
   114  				case resultC <- result{chunk: chunk, err: err}:
   115  //
   116  				}
   117  				return
   118  
   119  			}
   120  			select {
   121  			case <-quitC:
   122  //
   123  //
   124  //
   125  				return
   126  			case <-limiter.C:
   127  			}
   128  //
   129  			limiter.Reset(netStoreMinRetryDelay)
   130  			log.Debug("NetStore.Get retry chunk", "key", addr)
   131  		}
   132  	}()
   133  
   134  	select {
   135  	case r := <-resultC:
   136  		return r.chunk, r.err
   137  	case <-timer.C:
   138  		return nil, ErrChunkNotFound
   139  	}
   140  }
   141  
   142  //
   143  func (ns *NetStore) GetWithTimeout(ctx context.Context, addr Address, timeout time.Duration) (chunk *Chunk, err error) {
   144  	return ns.get(ctx, addr, timeout)
   145  }
   146  
   147  func (ns *NetStore) get(ctx context.Context, addr Address, timeout time.Duration) (chunk *Chunk, err error) {
   148  	if timeout == 0 {
   149  		timeout = searchTimeout
   150  	}
   151  
   152  	var sp opentracing.Span
   153  	ctx, sp = spancontext.StartSpan(
   154  		ctx,
   155  		"netstore.get")
   156  	defer sp.Finish()
   157  
   158  	if ns.retrieve == nil {
   159  		chunk, err = ns.localStore.Get(ctx, addr)
   160  		if err == nil {
   161  			return chunk, nil
   162  		}
   163  		if err != ErrFetching {
   164  			return nil, err
   165  		}
   166  	} else {
   167  		var created bool
   168  		chunk, created = ns.localStore.GetOrCreateRequest(ctx, addr)
   169  
   170  		if chunk.ReqC == nil {
   171  			return chunk, nil
   172  		}
   173  
   174  		if created {
   175  			err := ns.retrieve(ctx, chunk)
   176  			if err != nil {
   177  //
   178  				chunk.SetErrored(ErrChunkUnavailable)
   179  				return nil, err
   180  			}
   181  		}
   182  	}
   183  
   184  	t := time.NewTicker(timeout)
   185  	defer t.Stop()
   186  
   187  	select {
   188  	case <-t.C:
   189  //
   190  		chunk.SetErrored(ErrChunkNotFound)
   191  		return nil, ErrChunkNotFound
   192  	case <-chunk.ReqC:
   193  	}
   194  	chunk.SetErrored(nil)
   195  	return chunk, nil
   196  }
   197  
   198  //
   199  func (ns *NetStore) Put(ctx context.Context, chunk *Chunk) {
   200  	ns.localStore.Put(ctx, chunk)
   201  }
   202  
   203  //
   204  func (ns *NetStore) Close() {
   205  	ns.localStore.Close()
   206  }