diff options
author | Zahoor Mohamed <zahoor@zahoor.in> | 2017-04-12 08:06:02 +0800 |
---|---|---|
committer | Felix Lange <fjl@users.noreply.github.com> | 2017-04-12 08:06:02 +0800 |
commit | 1d1d988aa7caf60d6769bb474d4ec2f872eaaad4 (patch) | |
tree | 87ce615cd260871466fc1862994123848059b861 /swarm/api/api.go | |
parent | dd37064a151a1333b79f2fcde097ebc530d895a3 (diff) | |
download | go-tangerine-1d1d988aa7caf60d6769bb474d4ec2f872eaaad4.tar.gz go-tangerine-1d1d988aa7caf60d6769bb474d4ec2f872eaaad4.tar.zst go-tangerine-1d1d988aa7caf60d6769bb474d4ec2f872eaaad4.zip |
swarm/api: FUSE read-write support (#13872)
- Moved fuse related code in a new package, swarm/fuse
- Added write support
- Create new files
- Delete existing files
- Append to files (with limitations)
- More test coverage
Diffstat (limited to 'swarm/api/api.go')
-rw-r--r-- | swarm/api/api.go | 191 |
1 files changed, 190 insertions, 1 deletions
diff --git a/swarm/api/api.go b/swarm/api/api.go index ba1156f7e..f58b7a53d 100644 --- a/swarm/api/api.go +++ b/swarm/api/api.go @@ -25,9 +25,13 @@ import ( "strings" "sync" + "bytes" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/swarm/storage" + "mime" + "path/filepath" + "time" ) var ( @@ -59,6 +63,13 @@ func NewApi(dpa *storage.DPA, dns Resolver) (self *Api) { return } +// to be used only in TEST +func (self *Api) Upload(uploadDir, index string) (hash string, err error) { + fs := NewFileSystem(self) + hash, err = fs.Upload(uploadDir, index) + return hash, err +} + // DPA reader API func (self *Api) Retrieve(key storage.Key) storage.LazySectionReader { return self.dpa.Retrieve(key) @@ -111,7 +122,7 @@ func (self *Api) Put(content, contentType string) (storage.Key, error) { } // Get uses iterative manifest retrieval and prefix matching -// to resolve path to content using dpa retrieve +// to resolve basePath to content using dpa retrieve // it returns a section reader, mimeType, status and an error func (self *Api) Get(key storage.Key, path string) (reader storage.LazySectionReader, mimeType string, status int, err error) { trie, err := loadManifest(self.dpa, key, nil) @@ -160,3 +171,181 @@ func (self *Api) Modify(key storage.Key, path, contentHash, contentType string) } return trie.hash, nil } + +func (self *Api) AddFile(mhash, path, fname string, content []byte, nameresolver bool) (storage.Key, string, error) { + + uri, err := Parse("bzz:/" + mhash) + if err != nil { + return nil, "", err + } + mkey, err := self.Resolve(uri) + if err != nil { + return nil, "", err + } + + // trim the root dir we added + if path[:1] == "/" { + path = path[1:] + } + + entry := &ManifestEntry{ + Path: filepath.Join(path, fname), + ContentType: mime.TypeByExtension(filepath.Ext(fname)), + Mode: 0700, + Size: int64(len(content)), + ModTime: time.Now(), + } + + mw, err := self.NewManifestWriter(mkey, nil) + if err != nil { + return nil, "", err + } + + fkey, err := mw.AddEntry(bytes.NewReader(content), entry) + if err != nil { + return nil, "", err + } + + newMkey, err := mw.Store() + if err != nil { + return nil, "", err + + } + + return fkey, newMkey.String(), nil + +} + +func (self *Api) RemoveFile(mhash, path, fname string, nameresolver bool) (string, error) { + + uri, err := Parse("bzz:/" + mhash) + if err != nil { + return "", err + } + mkey, err := self.Resolve(uri) + if err != nil { + return "", err + } + + // trim the root dir we added + if path[:1] == "/" { + path = path[1:] + } + + mw, err := self.NewManifestWriter(mkey, nil) + if err != nil { + return "", err + } + + err = mw.RemoveEntry(filepath.Join(path, fname)) + if err != nil { + return "", err + } + + newMkey, err := mw.Store() + if err != nil { + return "", err + + } + + return newMkey.String(), nil +} + +func (self *Api) AppendFile(mhash, path, fname string, existingSize int64, content []byte, oldKey storage.Key, offset int64, addSize int64, nameresolver bool) (storage.Key, string, error) { + + buffSize := offset + addSize + if buffSize < existingSize { + buffSize = existingSize + } + + buf := make([]byte, buffSize) + + oldReader := self.Retrieve(oldKey) + io.ReadAtLeast(oldReader, buf, int(offset)) + + newReader := bytes.NewReader(content) + io.ReadAtLeast(newReader, buf[offset:], int(addSize)) + + if buffSize < existingSize { + io.ReadAtLeast(oldReader, buf[addSize:], int(buffSize)) + } + + combinedReader := bytes.NewReader(buf) + totalSize := int64(len(buf)) + + // TODO(jmozah): to append using pyramid chunker when it is ready + //oldReader := self.Retrieve(oldKey) + //newReader := bytes.NewReader(content) + //combinedReader := io.MultiReader(oldReader, newReader) + + uri, err := Parse("bzz:/" + mhash) + if err != nil { + return nil, "", err + } + mkey, err := self.Resolve(uri) + if err != nil { + return nil, "", err + } + + // trim the root dir we added + if path[:1] == "/" { + path = path[1:] + } + + mw, err := self.NewManifestWriter(mkey, nil) + if err != nil { + return nil, "", err + } + + err = mw.RemoveEntry(filepath.Join(path, fname)) + if err != nil { + return nil, "", err + } + + entry := &ManifestEntry{ + Path: filepath.Join(path, fname), + ContentType: mime.TypeByExtension(filepath.Ext(fname)), + Mode: 0700, + Size: totalSize, + ModTime: time.Now(), + } + + fkey, err := mw.AddEntry(io.Reader(combinedReader), entry) + if err != nil { + return nil, "", err + } + + newMkey, err := mw.Store() + if err != nil { + return nil, "", err + + } + + return fkey, newMkey.String(), nil + +} + +func (self *Api) BuildDirectoryTree(mhash string, nameresolver bool) (key storage.Key, manifestEntryMap map[string]*manifestTrieEntry, err error) { + + uri, err := Parse("bzz:/" + mhash) + if err != nil { + return nil, nil, err + } + key, err = self.Resolve(uri) + if err != nil { + return nil, nil, err + } + + quitC := make(chan bool) + rootTrie, err := loadManifest(self.dpa, key, quitC) + if err != nil { + return nil, nil, fmt.Errorf("can't load manifest %v: %v", key.String(), err) + } + + manifestEntryMap = map[string]*manifestTrieEntry{} + err = rootTrie.listWithPrefix(uri.Path, quitC, func(entry *manifestTrieEntry, suffix string) { + manifestEntryMap[suffix] = entry + }) + + return key, manifestEntryMap, nil +} |