manifest.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. // Copyright 2016 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package api
  17. import (
  18. "bytes"
  19. "encoding/json"
  20. "errors"
  21. "fmt"
  22. "io"
  23. "sync"
  24. "time"
  25. "github.com/ethereum/go-ethereum/common"
  26. "github.com/ethereum/go-ethereum/log"
  27. "github.com/ethereum/go-ethereum/swarm/storage"
  28. )
  29. const (
  30. ManifestType = "application/bzz-manifest+json"
  31. )
  32. // Manifest represents a swarm manifest
  33. type Manifest struct {
  34. Entries []ManifestEntry `json:"entries,omitempty"`
  35. }
  36. // ManifestEntry represents an entry in a swarm manifest
  37. type ManifestEntry struct {
  38. Hash string `json:"hash,omitempty"`
  39. Path string `json:"path,omitempty"`
  40. ContentType string `json:"contentType,omitempty"`
  41. Mode int64 `json:"mode,omitempty"`
  42. Size int64 `json:"size,omitempty"`
  43. ModTime time.Time `json:"mod_time,omitempty"`
  44. Status int `json:"status,omitempty"`
  45. }
  46. // ManifestList represents the result of listing files in a manifest
  47. type ManifestList struct {
  48. CommonPrefixes []string `json:"common_prefixes,omitempty"`
  49. Entries []*ManifestEntry `json:"entries,omitempty"`
  50. }
  51. // NewManifest creates and stores a new, empty manifest
  52. func (a *Api) NewManifest() (storage.Key, error) {
  53. var manifest Manifest
  54. data, err := json.Marshal(&manifest)
  55. if err != nil {
  56. return nil, err
  57. }
  58. return a.Store(bytes.NewReader(data), int64(len(data)), nil)
  59. }
  60. // ManifestWriter is used to add and remove entries from an underlying manifest
  61. type ManifestWriter struct {
  62. api *Api
  63. trie *manifestTrie
  64. quitC chan bool
  65. }
  66. func (a *Api) NewManifestWriter(key storage.Key, quitC chan bool) (*ManifestWriter, error) {
  67. trie, err := loadManifest(a.dpa, key, quitC)
  68. if err != nil {
  69. return nil, fmt.Errorf("error loading manifest %s: %s", key, err)
  70. }
  71. return &ManifestWriter{a, trie, quitC}, nil
  72. }
  73. // AddEntry stores the given data and adds the resulting key to the manifest
  74. func (m *ManifestWriter) AddEntry(data io.Reader, e *ManifestEntry) (storage.Key, error) {
  75. key, err := m.api.Store(data, e.Size, nil)
  76. if err != nil {
  77. return nil, err
  78. }
  79. entry := newManifestTrieEntry(e, nil)
  80. entry.Hash = key.String()
  81. m.trie.addEntry(entry, m.quitC)
  82. return key, nil
  83. }
  84. // RemoveEntry removes the given path from the manifest
  85. func (m *ManifestWriter) RemoveEntry(path string) error {
  86. m.trie.deleteEntry(path, m.quitC)
  87. return nil
  88. }
  89. // Store stores the manifest, returning the resulting storage key
  90. func (m *ManifestWriter) Store() (storage.Key, error) {
  91. return m.trie.hash, m.trie.recalcAndStore()
  92. }
  93. // ManifestWalker is used to recursively walk the entries in the manifest and
  94. // all of its submanifests
  95. type ManifestWalker struct {
  96. api *Api
  97. trie *manifestTrie
  98. quitC chan bool
  99. }
  100. func (a *Api) NewManifestWalker(key storage.Key, quitC chan bool) (*ManifestWalker, error) {
  101. trie, err := loadManifest(a.dpa, key, quitC)
  102. if err != nil {
  103. return nil, fmt.Errorf("error loading manifest %s: %s", key, err)
  104. }
  105. return &ManifestWalker{a, trie, quitC}, nil
  106. }
  107. // SkipManifest is used as a return value from WalkFn to indicate that the
  108. // manifest should be skipped
  109. var SkipManifest = errors.New("skip this manifest")
  110. // WalkFn is the type of function called for each entry visited by a recursive
  111. // manifest walk
  112. type WalkFn func(entry *ManifestEntry) error
  113. // Walk recursively walks the manifest calling walkFn for each entry in the
  114. // manifest, including submanifests
  115. func (m *ManifestWalker) Walk(walkFn WalkFn) error {
  116. return m.walk(m.trie, "", walkFn)
  117. }
  118. func (m *ManifestWalker) walk(trie *manifestTrie, prefix string, walkFn WalkFn) error {
  119. for _, entry := range trie.entries {
  120. if entry == nil {
  121. continue
  122. }
  123. entry.Path = prefix + entry.Path
  124. err := walkFn(&entry.ManifestEntry)
  125. if err != nil {
  126. if entry.ContentType == ManifestType && err == SkipManifest {
  127. continue
  128. }
  129. return err
  130. }
  131. if entry.ContentType != ManifestType {
  132. continue
  133. }
  134. if err := trie.loadSubTrie(entry, nil); err != nil {
  135. return err
  136. }
  137. if err := m.walk(entry.subtrie, entry.Path, walkFn); err != nil {
  138. return err
  139. }
  140. }
  141. return nil
  142. }
  143. type manifestTrie struct {
  144. dpa *storage.DPA
  145. entries [257]*manifestTrieEntry // indexed by first character of path, entries[256] is the empty path entry
  146. hash storage.Key // if hash != nil, it is stored
  147. }
  148. func newManifestTrieEntry(entry *ManifestEntry, subtrie *manifestTrie) *manifestTrieEntry {
  149. return &manifestTrieEntry{
  150. ManifestEntry: *entry,
  151. subtrie: subtrie,
  152. }
  153. }
  154. type manifestTrieEntry struct {
  155. ManifestEntry
  156. subtrie *manifestTrie
  157. }
  158. func loadManifest(dpa *storage.DPA, hash storage.Key, quitC chan bool) (trie *manifestTrie, err error) { // non-recursive, subtrees are downloaded on-demand
  159. log.Trace(fmt.Sprintf("manifest lookup key: '%v'.", hash.Log()))
  160. // retrieve manifest via DPA
  161. manifestReader := dpa.Retrieve(hash)
  162. return readManifest(manifestReader, hash, dpa, quitC)
  163. }
  164. func readManifest(manifestReader storage.LazySectionReader, hash storage.Key, dpa *storage.DPA, quitC chan bool) (trie *manifestTrie, err error) { // non-recursive, subtrees are downloaded on-demand
  165. // TODO check size for oversized manifests
  166. size, err := manifestReader.Size(quitC)
  167. if err != nil { // size == 0
  168. // can't determine size means we don't have the root chunk
  169. err = fmt.Errorf("Manifest not Found")
  170. return
  171. }
  172. manifestData := make([]byte, size)
  173. read, err := manifestReader.Read(manifestData)
  174. if int64(read) < size {
  175. log.Trace(fmt.Sprintf("Manifest %v not found.", hash.Log()))
  176. if err == nil {
  177. err = fmt.Errorf("Manifest retrieval cut short: read %v, expect %v", read, size)
  178. }
  179. return
  180. }
  181. log.Trace(fmt.Sprintf("Manifest %v retrieved", hash.Log()))
  182. var man struct {
  183. Entries []*manifestTrieEntry `json:"entries"`
  184. }
  185. err = json.Unmarshal(manifestData, &man)
  186. if err != nil {
  187. err = fmt.Errorf("Manifest %v is malformed: %v", hash.Log(), err)
  188. log.Trace(fmt.Sprintf("%v", err))
  189. return
  190. }
  191. log.Trace(fmt.Sprintf("Manifest %v has %d entries.", hash.Log(), len(man.Entries)))
  192. trie = &manifestTrie{
  193. dpa: dpa,
  194. }
  195. for _, entry := range man.Entries {
  196. trie.addEntry(entry, quitC)
  197. }
  198. return
  199. }
  200. func (self *manifestTrie) addEntry(entry *manifestTrieEntry, quitC chan bool) {
  201. self.hash = nil // trie modified, hash needs to be re-calculated on demand
  202. if len(entry.Path) == 0 {
  203. self.entries[256] = entry
  204. return
  205. }
  206. b := byte(entry.Path[0])
  207. if (self.entries[b] == nil) || (self.entries[b].Path == entry.Path) {
  208. self.entries[b] = entry
  209. return
  210. }
  211. oldentry := self.entries[b]
  212. cpl := 0
  213. for (len(entry.Path) > cpl) && (len(oldentry.Path) > cpl) && (entry.Path[cpl] == oldentry.Path[cpl]) {
  214. cpl++
  215. }
  216. if (oldentry.ContentType == ManifestType) && (cpl == len(oldentry.Path)) {
  217. if self.loadSubTrie(oldentry, quitC) != nil {
  218. return
  219. }
  220. entry.Path = entry.Path[cpl:]
  221. oldentry.subtrie.addEntry(entry, quitC)
  222. oldentry.Hash = ""
  223. return
  224. }
  225. commonPrefix := entry.Path[:cpl]
  226. subtrie := &manifestTrie{
  227. dpa: self.dpa,
  228. }
  229. entry.Path = entry.Path[cpl:]
  230. oldentry.Path = oldentry.Path[cpl:]
  231. subtrie.addEntry(entry, quitC)
  232. subtrie.addEntry(oldentry, quitC)
  233. self.entries[b] = newManifestTrieEntry(&ManifestEntry{
  234. Path: commonPrefix,
  235. ContentType: ManifestType,
  236. }, subtrie)
  237. }
  238. func (self *manifestTrie) getCountLast() (cnt int, entry *manifestTrieEntry) {
  239. for _, e := range self.entries {
  240. if e != nil {
  241. cnt++
  242. entry = e
  243. }
  244. }
  245. return
  246. }
  247. func (self *manifestTrie) deleteEntry(path string, quitC chan bool) {
  248. self.hash = nil // trie modified, hash needs to be re-calculated on demand
  249. if len(path) == 0 {
  250. self.entries[256] = nil
  251. return
  252. }
  253. b := byte(path[0])
  254. entry := self.entries[b]
  255. if entry == nil {
  256. return
  257. }
  258. if entry.Path == path {
  259. self.entries[b] = nil
  260. return
  261. }
  262. epl := len(entry.Path)
  263. if (entry.ContentType == ManifestType) && (len(path) >= epl) && (path[:epl] == entry.Path) {
  264. if self.loadSubTrie(entry, quitC) != nil {
  265. return
  266. }
  267. entry.subtrie.deleteEntry(path[epl:], quitC)
  268. entry.Hash = ""
  269. // remove subtree if it has less than 2 elements
  270. cnt, lastentry := entry.subtrie.getCountLast()
  271. if cnt < 2 {
  272. if lastentry != nil {
  273. lastentry.Path = entry.Path + lastentry.Path
  274. }
  275. self.entries[b] = lastentry
  276. }
  277. }
  278. }
  279. func (self *manifestTrie) recalcAndStore() error {
  280. if self.hash != nil {
  281. return nil
  282. }
  283. var buffer bytes.Buffer
  284. buffer.WriteString(`{"entries":[`)
  285. list := &Manifest{}
  286. for _, entry := range self.entries {
  287. if entry != nil {
  288. if entry.Hash == "" { // TODO: paralellize
  289. err := entry.subtrie.recalcAndStore()
  290. if err != nil {
  291. return err
  292. }
  293. entry.Hash = entry.subtrie.hash.String()
  294. }
  295. list.Entries = append(list.Entries, entry.ManifestEntry)
  296. }
  297. }
  298. manifest, err := json.Marshal(list)
  299. if err != nil {
  300. return err
  301. }
  302. sr := bytes.NewReader(manifest)
  303. wg := &sync.WaitGroup{}
  304. key, err2 := self.dpa.Store(sr, int64(len(manifest)), wg, nil)
  305. wg.Wait()
  306. self.hash = key
  307. return err2
  308. }
  309. func (self *manifestTrie) loadSubTrie(entry *manifestTrieEntry, quitC chan bool) (err error) {
  310. if entry.subtrie == nil {
  311. hash := common.Hex2Bytes(entry.Hash)
  312. entry.subtrie, err = loadManifest(self.dpa, hash, quitC)
  313. entry.Hash = "" // might not match, should be recalculated
  314. }
  315. return
  316. }
  317. func (self *manifestTrie) listWithPrefixInt(prefix, rp string, quitC chan bool, cb func(entry *manifestTrieEntry, suffix string)) error {
  318. plen := len(prefix)
  319. var start, stop int
  320. if plen == 0 {
  321. start = 0
  322. stop = 256
  323. } else {
  324. start = int(prefix[0])
  325. stop = start
  326. }
  327. for i := start; i <= stop; i++ {
  328. select {
  329. case <-quitC:
  330. return fmt.Errorf("aborted")
  331. default:
  332. }
  333. entry := self.entries[i]
  334. if entry != nil {
  335. epl := len(entry.Path)
  336. if entry.ContentType == ManifestType {
  337. l := plen
  338. if epl < l {
  339. l = epl
  340. }
  341. if prefix[:l] == entry.Path[:l] {
  342. err := self.loadSubTrie(entry, quitC)
  343. if err != nil {
  344. return err
  345. }
  346. err = entry.subtrie.listWithPrefixInt(prefix[l:], rp+entry.Path[l:], quitC, cb)
  347. if err != nil {
  348. return err
  349. }
  350. }
  351. } else {
  352. if (epl >= plen) && (prefix == entry.Path[:plen]) {
  353. cb(entry, rp+entry.Path[plen:])
  354. }
  355. }
  356. }
  357. }
  358. return nil
  359. }
  360. func (self *manifestTrie) listWithPrefix(prefix string, quitC chan bool, cb func(entry *manifestTrieEntry, suffix string)) (err error) {
  361. return self.listWithPrefixInt(prefix, "", quitC, cb)
  362. }
  363. func (self *manifestTrie) findPrefixOf(path string, quitC chan bool) (entry *manifestTrieEntry, pos int) {
  364. log.Trace(fmt.Sprintf("findPrefixOf(%s)", path))
  365. if len(path) == 0 {
  366. return self.entries[256], 0
  367. }
  368. b := byte(path[0])
  369. entry = self.entries[b]
  370. if entry == nil {
  371. return self.entries[256], 0
  372. }
  373. epl := len(entry.Path)
  374. log.Trace(fmt.Sprintf("path = %v entry.Path = %v epl = %v", path, entry.Path, epl))
  375. if (len(path) >= epl) && (path[:epl] == entry.Path) {
  376. log.Trace(fmt.Sprintf("entry.ContentType = %v", entry.ContentType))
  377. if entry.ContentType == ManifestType {
  378. err := self.loadSubTrie(entry, quitC)
  379. if err != nil {
  380. return nil, 0
  381. }
  382. entry, pos = entry.subtrie.findPrefixOf(path[epl:], quitC)
  383. if entry != nil {
  384. pos += epl
  385. }
  386. } else {
  387. pos = epl
  388. }
  389. }
  390. return
  391. }
  392. // file system manifest always contains regularized paths
  393. // no leading or trailing slashes, only single slashes inside
  394. func RegularSlashes(path string) (res string) {
  395. for i := 0; i < len(path); i++ {
  396. if (path[i] != '/') || ((i > 0) && (path[i-1] != '/')) {
  397. res = res + path[i:i+1]
  398. }
  399. }
  400. if (len(res) > 0) && (res[len(res)-1] == '/') {
  401. res = res[:len(res)-1]
  402. }
  403. return
  404. }
  405. func (self *manifestTrie) getEntry(spath string) (entry *manifestTrieEntry, fullpath string) {
  406. path := RegularSlashes(spath)
  407. var pos int
  408. quitC := make(chan bool)
  409. entry, pos = self.findPrefixOf(path, quitC)
  410. return entry, path[:pos]
  411. }