github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/api/manifest.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 api 26 27 import ( 28 "bytes" 29 "context" 30 "encoding/json" 31 "errors" 32 "fmt" 33 "io" 34 "net/http" 35 "strings" 36 "time" 37 38 "github.com/ethereum/go-ethereum/common" 39 "github.com/ethereum/go-ethereum/swarm/log" 40 "github.com/ethereum/go-ethereum/swarm/storage" 41 ) 42 43 const ( 44 ManifestType = "application/bzz-manifest+json" 45 ResourceContentType = "application/bzz-resource" 46 47 manifestSizeLimit = 5 * 1024 * 1024 48 ) 49 50 // 51 type Manifest struct { 52 Entries []ManifestEntry `json:"entries,omitempty"` 53 } 54 55 // 56 type ManifestEntry struct { 57 Hash string `json:"hash,omitempty"` 58 Path string `json:"path,omitempty"` 59 ContentType string `json:"contentType,omitempty"` 60 Mode int64 `json:"mode,omitempty"` 61 Size int64 `json:"size,omitempty"` 62 ModTime time.Time `json:"mod_time,omitempty"` 63 Status int `json:"status,omitempty"` 64 Access *AccessEntry `json:"access,omitempty"` 65 } 66 67 // 68 type ManifestList struct { 69 CommonPrefixes []string `json:"common_prefixes,omitempty"` 70 Entries []*ManifestEntry `json:"entries,omitempty"` 71 } 72 73 // 74 func (a *API) NewManifest(ctx context.Context, toEncrypt bool) (storage.Address, error) { 75 var manifest Manifest 76 data, err := json.Marshal(&manifest) 77 if err != nil { 78 return nil, err 79 } 80 key, wait, err := a.Store(ctx, bytes.NewReader(data), int64(len(data)), toEncrypt) 81 wait(ctx) 82 return key, err 83 } 84 85 // 86 // 87 func (a *API) NewResourceManifest(ctx context.Context, resourceAddr string) (storage.Address, error) { 88 var manifest Manifest 89 entry := ManifestEntry{ 90 Hash: resourceAddr, 91 ContentType: ResourceContentType, 92 } 93 manifest.Entries = append(manifest.Entries, entry) 94 data, err := json.Marshal(&manifest) 95 if err != nil { 96 return nil, err 97 } 98 key, _, err := a.Store(ctx, bytes.NewReader(data), int64(len(data)), false) 99 return key, err 100 } 101 102 // 103 type ManifestWriter struct { 104 api *API 105 trie *manifestTrie 106 quitC chan bool 107 } 108 109 func (a *API) NewManifestWriter(ctx context.Context, addr storage.Address, quitC chan bool) (*ManifestWriter, error) { 110 trie, err := loadManifest(ctx, a.fileStore, addr, quitC, NOOPDecrypt) 111 if err != nil { 112 return nil, fmt.Errorf("error loading manifest %s: %s", addr, err) 113 } 114 return &ManifestWriter{a, trie, quitC}, nil 115 } 116 117 // 118 func (m *ManifestWriter) AddEntry(ctx context.Context, data io.Reader, e *ManifestEntry) (key storage.Address, err error) { 119 entry := newManifestTrieEntry(e, nil) 120 if data != nil { 121 key, _, err = m.api.Store(ctx, data, e.Size, m.trie.encrypted) 122 if err != nil { 123 return nil, err 124 } 125 entry.Hash = key.Hex() 126 } 127 if entry.Hash == "" { 128 return key, errors.New("missing entry hash") 129 } 130 m.trie.addEntry(entry, m.quitC) 131 return key, nil 132 } 133 134 // 135 func (m *ManifestWriter) RemoveEntry(path string) error { 136 m.trie.deleteEntry(path, m.quitC) 137 return nil 138 } 139 140 // 141 func (m *ManifestWriter) Store() (storage.Address, error) { 142 return m.trie.ref, m.trie.recalcAndStore() 143 } 144 145 // 146 // 147 type ManifestWalker struct { 148 api *API 149 trie *manifestTrie 150 quitC chan bool 151 } 152 153 func (a *API) NewManifestWalker(ctx context.Context, addr storage.Address, decrypt DecryptFunc, quitC chan bool) (*ManifestWalker, error) { 154 trie, err := loadManifest(ctx, a.fileStore, addr, quitC, decrypt) 155 if err != nil { 156 return nil, fmt.Errorf("error loading manifest %s: %s", addr, err) 157 } 158 return &ManifestWalker{a, trie, quitC}, nil 159 } 160 161 // 162 // 163 var ErrSkipManifest = errors.New("skip this manifest") 164 165 // 166 // 167 type WalkFn func(entry *ManifestEntry) error 168 169 // 170 // 171 func (m *ManifestWalker) Walk(walkFn WalkFn) error { 172 return m.walk(m.trie, "", walkFn) 173 } 174 175 func (m *ManifestWalker) walk(trie *manifestTrie, prefix string, walkFn WalkFn) error { 176 for _, entry := range &trie.entries { 177 if entry == nil { 178 continue 179 } 180 entry.Path = prefix + entry.Path 181 err := walkFn(&entry.ManifestEntry) 182 if err != nil { 183 if entry.ContentType == ManifestType && err == ErrSkipManifest { 184 continue 185 } 186 return err 187 } 188 if entry.ContentType != ManifestType { 189 continue 190 } 191 if err := trie.loadSubTrie(entry, nil); err != nil { 192 return err 193 } 194 if err := m.walk(entry.subtrie, entry.Path, walkFn); err != nil { 195 return err 196 } 197 } 198 return nil 199 } 200 201 type manifestTrie struct { 202 fileStore *storage.FileStore 203 entries [257]*manifestTrieEntry // 204 ref storage.Address // 205 encrypted bool 206 decrypt DecryptFunc 207 } 208 209 func newManifestTrieEntry(entry *ManifestEntry, subtrie *manifestTrie) *manifestTrieEntry { 210 return &manifestTrieEntry{ 211 ManifestEntry: *entry, 212 subtrie: subtrie, 213 } 214 } 215 216 type manifestTrieEntry struct { 217 ManifestEntry 218 219 subtrie *manifestTrie 220 } 221 222 func loadManifest(ctx context.Context, fileStore *storage.FileStore, hash storage.Address, quitC chan bool, decrypt DecryptFunc) (trie *manifestTrie, err error) { // 223 log.Trace("manifest lookup", "key", hash) 224 // 225 manifestReader, isEncrypted := fileStore.Retrieve(ctx, hash) 226 log.Trace("reader retrieved", "key", hash) 227 return readManifest(manifestReader, hash, fileStore, isEncrypted, quitC, decrypt) 228 } 229 230 func readManifest(mr storage.LazySectionReader, hash storage.Address, fileStore *storage.FileStore, isEncrypted bool, quitC chan bool, decrypt DecryptFunc) (trie *manifestTrie, err error) { // 231 232 // 233 size, err := mr.Size(mr.Context(), quitC) 234 if err != nil { // 235 // 236 log.Trace("manifest not found", "key", hash) 237 err = fmt.Errorf("Manifest not Found") 238 return 239 } 240 if size > manifestSizeLimit { 241 log.Warn("manifest exceeds size limit", "key", hash, "size", size, "limit", manifestSizeLimit) 242 err = fmt.Errorf("Manifest size of %v bytes exceeds the %v byte limit", size, manifestSizeLimit) 243 return 244 } 245 manifestData := make([]byte, size) 246 read, err := mr.Read(manifestData) 247 if int64(read) < size { 248 log.Trace("manifest not found", "key", hash) 249 if err == nil { 250 err = fmt.Errorf("Manifest retrieval cut short: read %v, expect %v", read, size) 251 } 252 return 253 } 254 255 log.Debug("manifest retrieved", "key", hash) 256 var man struct { 257 Entries []*manifestTrieEntry `json:"entries"` 258 } 259 err = json.Unmarshal(manifestData, &man) 260 if err != nil { 261 err = fmt.Errorf("Manifest %v is malformed: %v", hash.Log(), err) 262 log.Trace("malformed manifest", "key", hash) 263 return 264 } 265 266 log.Trace("manifest entries", "key", hash, "len", len(man.Entries)) 267 268 trie = &manifestTrie{ 269 fileStore: fileStore, 270 encrypted: isEncrypted, 271 decrypt: decrypt, 272 } 273 for _, entry := range man.Entries { 274 err = trie.addEntry(entry, quitC) 275 if err != nil { 276 return 277 } 278 } 279 return 280 } 281 282 func (mt *manifestTrie) addEntry(entry *manifestTrieEntry, quitC chan bool) error { 283 mt.ref = nil // 284 285 if entry.ManifestEntry.Access != nil { 286 if mt.decrypt == nil { 287 return errors.New("dont have decryptor") 288 } 289 290 err := mt.decrypt(&entry.ManifestEntry) 291 if err != nil { 292 return err 293 } 294 } 295 296 if len(entry.Path) == 0 { 297 mt.entries[256] = entry 298 return nil 299 } 300 301 b := entry.Path[0] 302 oldentry := mt.entries[b] 303 if (oldentry == nil) || (oldentry.Path == entry.Path && oldentry.ContentType != ManifestType) { 304 mt.entries[b] = entry 305 return nil 306 } 307 308 cpl := 0 309 for (len(entry.Path) > cpl) && (len(oldentry.Path) > cpl) && (entry.Path[cpl] == oldentry.Path[cpl]) { 310 cpl++ 311 } 312 313 if (oldentry.ContentType == ManifestType) && (cpl == len(oldentry.Path)) { 314 if mt.loadSubTrie(oldentry, quitC) != nil { 315 return nil 316 } 317 entry.Path = entry.Path[cpl:] 318 oldentry.subtrie.addEntry(entry, quitC) 319 oldentry.Hash = "" 320 return nil 321 } 322 323 commonPrefix := entry.Path[:cpl] 324 325 subtrie := &manifestTrie{ 326 fileStore: mt.fileStore, 327 encrypted: mt.encrypted, 328 } 329 entry.Path = entry.Path[cpl:] 330 oldentry.Path = oldentry.Path[cpl:] 331 subtrie.addEntry(entry, quitC) 332 subtrie.addEntry(oldentry, quitC) 333 334 mt.entries[b] = newManifestTrieEntry(&ManifestEntry{ 335 Path: commonPrefix, 336 ContentType: ManifestType, 337 }, subtrie) 338 return nil 339 } 340 341 func (mt *manifestTrie) getCountLast() (cnt int, entry *manifestTrieEntry) { 342 for _, e := range &mt.entries { 343 if e != nil { 344 cnt++ 345 entry = e 346 } 347 } 348 return 349 } 350 351 func (mt *manifestTrie) deleteEntry(path string, quitC chan bool) { 352 mt.ref = nil // 353 354 if len(path) == 0 { 355 mt.entries[256] = nil 356 return 357 } 358 359 b := path[0] 360 entry := mt.entries[b] 361 if entry == nil { 362 return 363 } 364 if entry.Path == path { 365 mt.entries[b] = nil 366 return 367 } 368 369 epl := len(entry.Path) 370 if (entry.ContentType == ManifestType) && (len(path) >= epl) && (path[:epl] == entry.Path) { 371 if mt.loadSubTrie(entry, quitC) != nil { 372 return 373 } 374 entry.subtrie.deleteEntry(path[epl:], quitC) 375 entry.Hash = "" 376 // 377 cnt, lastentry := entry.subtrie.getCountLast() 378 if cnt < 2 { 379 if lastentry != nil { 380 lastentry.Path = entry.Path + lastentry.Path 381 } 382 mt.entries[b] = lastentry 383 } 384 } 385 } 386 387 func (mt *manifestTrie) recalcAndStore() error { 388 if mt.ref != nil { 389 return nil 390 } 391 392 var buffer bytes.Buffer 393 buffer.WriteString(`{"entries":[`) 394 395 list := &Manifest{} 396 for _, entry := range &mt.entries { 397 if entry != nil { 398 if entry.Hash == "" { // 399 err := entry.subtrie.recalcAndStore() 400 if err != nil { 401 return err 402 } 403 entry.Hash = entry.subtrie.ref.Hex() 404 } 405 list.Entries = append(list.Entries, entry.ManifestEntry) 406 } 407 408 } 409 410 manifest, err := json.Marshal(list) 411 if err != nil { 412 return err 413 } 414 415 sr := bytes.NewReader(manifest) 416 ctx := context.TODO() 417 key, wait, err2 := mt.fileStore.Store(ctx, sr, int64(len(manifest)), mt.encrypted) 418 if err2 != nil { 419 return err2 420 } 421 err2 = wait(ctx) 422 mt.ref = key 423 return err2 424 } 425 426 func (mt *manifestTrie) loadSubTrie(entry *manifestTrieEntry, quitC chan bool) (err error) { 427 if entry.ManifestEntry.Access != nil { 428 if mt.decrypt == nil { 429 return errors.New("dont have decryptor") 430 } 431 432 err := mt.decrypt(&entry.ManifestEntry) 433 if err != nil { 434 return err 435 } 436 } 437 438 if entry.subtrie == nil { 439 hash := common.Hex2Bytes(entry.Hash) 440 entry.subtrie, err = loadManifest(context.TODO(), mt.fileStore, hash, quitC, mt.decrypt) 441 entry.Hash = "" // 442 } 443 return 444 } 445 446 func (mt *manifestTrie) listWithPrefixInt(prefix, rp string, quitC chan bool, cb func(entry *manifestTrieEntry, suffix string)) error { 447 plen := len(prefix) 448 var start, stop int 449 if plen == 0 { 450 start = 0 451 stop = 256 452 } else { 453 start = int(prefix[0]) 454 stop = start 455 } 456 457 for i := start; i <= stop; i++ { 458 select { 459 case <-quitC: 460 return fmt.Errorf("aborted") 461 default: 462 } 463 entry := mt.entries[i] 464 if entry != nil { 465 epl := len(entry.Path) 466 if entry.ContentType == ManifestType { 467 l := plen 468 if epl < l { 469 l = epl 470 } 471 if prefix[:l] == entry.Path[:l] { 472 err := mt.loadSubTrie(entry, quitC) 473 if err != nil { 474 return err 475 } 476 err = entry.subtrie.listWithPrefixInt(prefix[l:], rp+entry.Path[l:], quitC, cb) 477 if err != nil { 478 return err 479 } 480 } 481 } else { 482 if (epl >= plen) && (prefix == entry.Path[:plen]) { 483 cb(entry, rp+entry.Path[plen:]) 484 } 485 } 486 } 487 } 488 return nil 489 } 490 491 func (mt *manifestTrie) listWithPrefix(prefix string, quitC chan bool, cb func(entry *manifestTrieEntry, suffix string)) (err error) { 492 return mt.listWithPrefixInt(prefix, "", quitC, cb) 493 } 494 495 func (mt *manifestTrie) findPrefixOf(path string, quitC chan bool) (entry *manifestTrieEntry, pos int) { 496 log.Trace(fmt.Sprintf("findPrefixOf(%s)", path)) 497 498 if len(path) == 0 { 499 return mt.entries[256], 0 500 } 501 502 // 503 b := path[0] 504 entry = mt.entries[b] 505 if entry == nil { 506 return mt.entries[256], 0 507 } 508 509 epl := len(entry.Path) 510 log.Trace(fmt.Sprintf("path = %v entry.Path = %v epl = %v", path, entry.Path, epl)) 511 if len(path) <= epl { 512 if entry.Path[:len(path)] == path { 513 if entry.ContentType == ManifestType { 514 err := mt.loadSubTrie(entry, quitC) 515 if err == nil && entry.subtrie != nil { 516 subentries := entry.subtrie.entries 517 for i := 0; i < len(subentries); i++ { 518 sub := subentries[i] 519 if sub != nil && sub.Path == "" { 520 return sub, len(path) 521 } 522 } 523 } 524 entry.Status = http.StatusMultipleChoices 525 } 526 pos = len(path) 527 return 528 } 529 return nil, 0 530 } 531 if path[:epl] == entry.Path { 532 log.Trace(fmt.Sprintf("entry.ContentType = %v", entry.ContentType)) 533 // 534 if entry.ContentType == ManifestType && (strings.Contains(entry.Path, path) || strings.Contains(path, entry.Path)) { 535 err := mt.loadSubTrie(entry, quitC) 536 if err != nil { 537 return nil, 0 538 } 539 sub, pos := entry.subtrie.findPrefixOf(path[epl:], quitC) 540 if sub != nil { 541 entry = sub 542 pos += epl 543 return sub, pos 544 } else if path == entry.Path { 545 entry.Status = http.StatusMultipleChoices 546 } 547 548 } else { 549 // 550 if path != entry.Path { 551 return nil, 0 552 } 553 pos = epl 554 } 555 } 556 return nil, 0 557 } 558 559 // 560 // 561 func RegularSlashes(path string) (res string) { 562 for i := 0; i < len(path); i++ { 563 if (path[i] != '/') || ((i > 0) && (path[i-1] != '/')) { 564 res = res + path[i:i+1] 565 } 566 } 567 if (len(res) > 0) && (res[len(res)-1] == '/') { 568 res = res[:len(res)-1] 569 } 570 return 571 } 572 573 func (mt *manifestTrie) getEntry(spath string) (entry *manifestTrieEntry, fullpath string) { 574 path := RegularSlashes(spath) 575 var pos int 576 quitC := make(chan bool) 577 entry, pos = mt.findPrefixOf(path, quitC) 578 return entry, path[:pos] 579 }