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  }