github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/storage/feed/handler.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 19:16:44</date> 10 //</624450118912839680> 11 12 13 //处理程序是源的API 14 //它支持创建、更新、同步和检索源更新及其数据 15 package feed 16 17 import ( 18 "bytes" 19 "context" 20 "fmt" 21 "sync" 22 23 "github.com/ethereum/go-ethereum/swarm/storage/feed/lookup" 24 25 "github.com/ethereum/go-ethereum/swarm/log" 26 "github.com/ethereum/go-ethereum/swarm/storage" 27 ) 28 29 type Handler struct { 30 chunkStore *storage.NetStore 31 HashSize int 32 cache map[uint64]*cacheEntry 33 cacheLock sync.RWMutex 34 } 35 36 //handlerParams将参数传递给处理程序构造函数newhandler 37 //签名者和时间戳提供程序是必需的参数 38 type HandlerParams struct { 39 } 40 41 //哈希池包含一个准备好的哈希器池 42 var hashPool sync.Pool 43 44 //init初始化包和哈希池 45 func init() { 46 hashPool = sync.Pool{ 47 New: func() interface{} { 48 return storage.MakeHashFunc(feedsHashAlgorithm)() 49 }, 50 } 51 } 52 53 //NewHandler创建了一个新的Swarm Feeds API 54 func NewHandler(params *HandlerParams) *Handler { 55 fh := &Handler{ 56 cache: make(map[uint64]*cacheEntry), 57 } 58 59 for i := 0; i < hasherCount; i++ { 60 hashfunc := storage.MakeHashFunc(feedsHashAlgorithm)() 61 if fh.HashSize == 0 { 62 fh.HashSize = hashfunc.Size() 63 } 64 hashPool.Put(hashfunc) 65 } 66 67 return fh 68 } 69 70 //setstore为swarm feeds api设置存储后端 71 func (h *Handler) SetStore(store *storage.NetStore) { 72 h.chunkStore = store 73 } 74 75 //validate是块验证方法 76 //如果它看起来像一个提要更新,那么块地址将根据更新签名的useraddr进行检查。 77 //它实现了storage.chunkvalidator接口 78 func (h *Handler) Validate(chunk storage.Chunk) bool { 79 if len(chunk.Data()) < minimumSignedUpdateLength { 80 return false 81 } 82 83 //检查它是否是格式正确的更新块 84 //所尝试的源的有效签名和所有权证明 85 //更新 86 87 //首先,反序列化块 88 var r Request 89 if err := r.fromChunk(chunk); err != nil { 90 log.Debug("Invalid feed update chunk", "addr", chunk.Address(), "err", err) 91 return false 92 } 93 94 //验证签名,并且签名者实际上拥有源 95 //如果失败,则表示签名无效,数据已损坏。 96 //或者有人试图更新其他人的订阅源。 97 if err := r.Verify(); err != nil { 98 log.Debug("Invalid feed update signature", "err", err) 99 return false 100 } 101 102 return true 103 } 104 105 //getContent检索源的上次同步更新的数据负载 106 func (h *Handler) GetContent(feed *Feed) (storage.Address, []byte, error) { 107 if feed == nil { 108 return nil, nil, NewError(ErrInvalidValue, "feed is nil") 109 } 110 feedUpdate := h.get(feed) 111 if feedUpdate == nil { 112 return nil, nil, NewError(ErrNotFound, "feed update not cached") 113 } 114 return feedUpdate.lastKey, feedUpdate.data, nil 115 } 116 117 //NewRequest准备一个请求结构,其中包含 118 //只需添加所需数据并签名即可。 119 //然后可以对生成的结构进行签名并将其传递给handler.update以进行验证并发送 120 func (h *Handler) NewRequest(ctx context.Context, feed *Feed) (request *Request, err error) { 121 if feed == nil { 122 return nil, NewError(ErrInvalidValue, "feed cannot be nil") 123 } 124 125 now := TimestampProvider.Now().Time 126 request = new(Request) 127 request.Header.Version = ProtocolVersion 128 129 query := NewQueryLatest(feed, lookup.NoClue) 130 131 feedUpdate, err := h.Lookup(ctx, query) 132 if err != nil { 133 if err.(*Error).code != ErrNotFound { 134 return nil, err 135 } 136 //找不到更新意味着存在网络错误 137 //或者订阅源确实没有更新 138 } 139 140 request.Feed = *feed 141 142 //如果我们已经有了更新,那么找到下一个时代 143 if feedUpdate != nil { 144 request.Epoch = lookup.GetNextEpoch(feedUpdate.Epoch, now) 145 } else { 146 request.Epoch = lookup.GetFirstEpoch(now) 147 } 148 149 return request, nil 150 } 151 152 //查找检索特定或最新的源更新 153 //根据“query”的配置,查找的工作方式不同 154 //请参阅“query”文档和帮助器函数: 155 //`newquerylatest`和'newquery` 156 func (h *Handler) Lookup(ctx context.Context, query *Query) (*cacheEntry, error) { 157 158 timeLimit := query.TimeLimit 159 if timeLimit == 0 { //如果时间限制设置为零,则用户希望获取最新更新 160 timeLimit = TimestampProvider.Now().Time 161 } 162 163 if query.Hint == lookup.NoClue { //尝试使用我们的缓存 164 entry := h.get(&query.Feed) 165 if entry != nil && entry.Epoch.Time <= timeLimit { //避免不良提示 166 query.Hint = entry.Epoch 167 } 168 } 169 170 //没有商店我们找不到任何东西 171 if h.chunkStore == nil { 172 return nil, NewError(ErrInit, "Call Handler.SetStore() before performing lookups") 173 } 174 175 var id ID 176 id.Feed = query.Feed 177 var readCount int 178 179 //调用查找引擎。 180 //每次查找算法需要猜测时都将调用回调 181 requestPtr, err := lookup.Lookup(timeLimit, query.Hint, func(epoch lookup.Epoch, now uint64) (interface{}, error) { 182 readCount++ 183 id.Epoch = epoch 184 ctx, cancel := context.WithTimeout(ctx, defaultRetrieveTimeout) 185 defer cancel() 186 187 chunk, err := h.chunkStore.Get(ctx, id.Addr()) 188 if err != nil { //TODO:未找到块以外的灾难性错误 189 return nil, nil 190 } 191 192 var request Request 193 if err := request.fromChunk(chunk); err != nil { 194 return nil, nil 195 } 196 if request.Time <= timeLimit { 197 return &request, nil 198 } 199 return nil, nil 200 }) 201 if err != nil { 202 return nil, err 203 } 204 205 log.Info(fmt.Sprintf("Feed lookup finished in %d lookups", readCount)) 206 207 request, _ := requestPtr.(*Request) 208 if request == nil { 209 return nil, NewError(ErrNotFound, "no feed updates found") 210 } 211 return h.updateCache(request) 212 213 } 214 215 //使用指定内容更新源更新缓存 216 func (h *Handler) updateCache(request *Request) (*cacheEntry, error) { 217 218 updateAddr := request.Addr() 219 log.Trace("feed cache update", "topic", request.Topic.Hex(), "updateaddr", updateAddr, "epoch time", request.Epoch.Time, "epoch level", request.Epoch.Level) 220 221 feedUpdate := h.get(&request.Feed) 222 if feedUpdate == nil { 223 feedUpdate = &cacheEntry{} 224 h.set(&request.Feed, feedUpdate) 225 } 226 227 //更新我们的RSRCS入口地图 228 feedUpdate.lastKey = updateAddr 229 feedUpdate.Update = request.Update 230 feedUpdate.Reader = bytes.NewReader(feedUpdate.data) 231 return feedUpdate, nil 232 } 233 234 //更新发布源更新 235 //请注意,提要更新不能跨越块,因此具有最大净长度4096,包括更新头数据和签名。 236 //这将导致最大负载为“maxupdatedatalength”(有关详细信息,请检查update.go) 237 //如果区块负载的总长度将超过此限制,则返回错误。 238 //更新只能检查调用方是否试图覆盖最新的已知版本,否则它只会将更新 239 //在网络上。 240 func (h *Handler) Update(ctx context.Context, r *Request) (updateAddr storage.Address, err error) { 241 242 //没有商店我们无法更新任何内容 243 if h.chunkStore == nil { 244 return nil, NewError(ErrInit, "Call Handler.SetStore() before updating") 245 } 246 247 feedUpdate := h.get(&r.Feed) 248 if feedUpdate != nil && feedUpdate.Epoch.Equals(r.Epoch) { //这是我们唯一能确定的便宜支票 249 return nil, NewError(ErrInvalidValue, "A former update in this epoch is already known to exist") 250 } 251 252 chunk, err := r.toChunk() //将更新序列化为块。如果数据太大则失败 253 if err != nil { 254 return nil, err 255 } 256 257 //发送块 258 h.chunkStore.Put(ctx, chunk) 259 log.Trace("feed update", "updateAddr", r.idAddr, "epoch time", r.Epoch.Time, "epoch level", r.Epoch.Level, "data", chunk.Data()) 260 //更新我们的feed更新映射缓存条目,如果新的更新比我们现有的更新旧,如果我们有。 261 if feedUpdate != nil && r.Epoch.After(feedUpdate.Epoch) { 262 feedUpdate.Epoch = r.Epoch 263 feedUpdate.data = make([]byte, len(r.data)) 264 feedUpdate.lastKey = r.idAddr 265 copy(feedUpdate.data, r.data) 266 feedUpdate.Reader = bytes.NewReader(feedUpdate.data) 267 } 268 269 return r.idAddr, nil 270 } 271 272 //检索给定名称哈希的源更新缓存值 273 func (h *Handler) get(feed *Feed) *cacheEntry { 274 mapKey := feed.mapKey() 275 h.cacheLock.RLock() 276 defer h.cacheLock.RUnlock() 277 feedUpdate := h.cache[mapKey] 278 return feedUpdate 279 } 280 281 //设置给定源的源更新缓存值 282 func (h *Handler) set(feed *Feed, feedUpdate *cacheEntry) { 283 mapKey := feed.mapKey() 284 h.cacheLock.Lock() 285 defer h.cacheLock.Unlock() 286 h.cache[mapKey] = feedUpdate 287 } 288