13111: .arvados#collection special file.
authorTom Clegg <tclegg@veritasgenetics.com>
Mon, 18 Dec 2017 05:49:36 +0000 (00:49 -0500)
committerTom Clegg <tclegg@veritasgenetics.com>
Wed, 3 Jan 2018 05:24:19 +0000 (00:24 -0500)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg@veritasgenetics.com>

sdk/go/arvados/collection_fs.go
sdk/go/arvados/fs_getternode.go [new file with mode: 0644]

index 46470557a40c16838c42931da2eda5f34d922a6d..72ef49feec8a3a6e3fa0d85c67c9b81d2763d621 100644 (file)
@@ -5,6 +5,7 @@
 package arvados
 
 import (
+       "encoding/json"
        "errors"
        "fmt"
        "io"
@@ -144,6 +145,25 @@ type collectionFileSystem struct {
        fileSystem
 }
 
+func (fs collectionFileSystem) Child(name string, replace func(inode) inode) inode {
+       if name == ".arvados#collection" {
+               return &getternode{Getter: func() ([]byte, error) {
+                       var coll Collection
+                       var err error
+                       coll.ManifestText, err = fs.MarshalManifest(".")
+                       if err != nil {
+                               return nil, err
+                       }
+                       data, err := json.Marshal(&coll)
+                       if err == nil {
+                               data = append(data, 10)
+                       }
+                       return data, err
+               }}
+       }
+       return fs.fileSystem.Child(name, replace)
+}
+
 func (fs collectionFileSystem) MarshalManifest(prefix string) (string, error) {
        fs.fileSystem.inode.Lock()
        defer fs.fileSystem.inode.Unlock()
diff --git a/sdk/go/arvados/fs_getternode.go b/sdk/go/arvados/fs_getternode.go
new file mode 100644 (file)
index 0000000..c9ffb38
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package arvados
+
+import (
+       "bytes"
+       "os"
+       "time"
+)
+
+// A getternode is a read-only character device that returns whatever
+// data is returned by the supplied function.
+type getternode struct {
+       Getter func() ([]byte, error)
+
+       treenode
+       data *bytes.Reader
+}
+
+func (*getternode) IsDir() bool {
+       return false
+}
+
+func (*getternode) Child(string, func(inode) inode) inode {
+       return nil
+}
+
+func (gn *getternode) get() error {
+       if gn.data != nil {
+               return nil
+       }
+       data, err := gn.Getter()
+       if err != nil {
+               return err
+       }
+       gn.data = bytes.NewReader(data)
+       return nil
+}
+
+func (gn *getternode) Size() int64 {
+       return gn.FileInfo().Size()
+}
+
+func (gn *getternode) FileInfo() os.FileInfo {
+       gn.Lock()
+       defer gn.Unlock()
+       var size int64
+       if gn.get() == nil {
+               size = gn.data.Size()
+       }
+       return fileinfo{
+               modTime: time.Now(),
+               mode:    0444,
+               size:    size,
+       }
+}
+
+func (gn *getternode) Read(p []byte, ptr filenodePtr) (int, filenodePtr, error) {
+       if err := gn.get(); err != nil {
+               return 0, ptr, err
+       }
+       n, err := gn.data.ReadAt(p, ptr.off)
+       return n, filenodePtr{off: ptr.off + int64(n)}, err
+}