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 }