From 10d551cbba521857f3967968348fd107f32651df Mon Sep 17 00:00:00 2001 From: Tom Clegg Date: Mon, 18 Dec 2017 00:49:36 -0500 Subject: [PATCH] 13111: .arvados#collection special file. Arvados-DCO-1.1-Signed-off-by: Tom Clegg --- sdk/go/arvados/collection_fs.go | 20 ++++++++++ sdk/go/arvados/fs_getternode.go | 66 +++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 sdk/go/arvados/fs_getternode.go diff --git a/sdk/go/arvados/collection_fs.go b/sdk/go/arvados/collection_fs.go index 46470557a4..72ef49feec 100644 --- a/sdk/go/arvados/collection_fs.go +++ b/sdk/go/arvados/collection_fs.go @@ -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 index 0000000000..c9ffb387d3 --- /dev/null +++ b/sdk/go/arvados/fs_getternode.go @@ -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 +} -- 2.30.2