7 from fresh import FreshBase, convertTime
9 _logger = logging.getLogger('arvados.arvados_fuse')
11 class File(FreshBase):
12 """Base for file objects."""
14 def __init__(self, parent_inode, _mtime=0):
15 super(File, self).__init__()
17 self.parent_inode = parent_inode
23 def readfrom(self, off, size, num_retries=0):
26 def writeto(self, off, size, num_retries=0):
27 raise Exception("Not writable")
42 class FuseArvadosFile(File):
43 """Wraps a ArvadosFile."""
45 def __init__(self, parent_inode, arvfile, _mtime):
46 super(FuseArvadosFile, self).__init__(parent_inode, _mtime)
47 self.arvfile = arvfile
50 with llfuse.lock_released:
51 return self.arvfile.size()
53 def readfrom(self, off, size, num_retries=0):
54 with llfuse.lock_released:
55 return self.arvfile.readfrom(off, size, num_retries, exact=True)
57 def writeto(self, off, buf, num_retries=0):
58 with llfuse.lock_released:
59 return self.arvfile.writeto(off, buf, num_retries)
65 return self.arvfile.writable()
68 with llfuse.lock_released:
70 self.arvfile.parent.root_collection().save()
73 class StringFile(File):
74 """Wrap a simple string as a file"""
75 def __init__(self, parent_inode, contents, _mtime):
76 super(StringFile, self).__init__(parent_inode, _mtime)
77 self.contents = contents
80 return len(self.contents)
82 def readfrom(self, off, size, num_retries=0):
83 return self.contents[off:(off+size)]
86 class ObjectFile(StringFile):
87 """Wrap a dict as a serialized json object."""
89 def __init__(self, parent_inode, obj):
90 super(ObjectFile, self).__init__(parent_inode, "", 0)
91 self.object_uuid = obj['uuid']
95 return self.object_uuid
97 def update(self, obj=None):
99 # TODO: retrieve the current record for self.object_uuid
100 # from the server. For now, at least don't crash when
101 # someone tells us it's a good time to update but doesn't
102 # pass us a fresh obj. See #8345
104 self._mtime = convertTime(obj['modified_at']) if 'modified_at' in obj else 0
105 self.contents = json.dumps(obj, indent=4, sort_keys=True) + "\n"
111 class FuncToJSONFile(StringFile):
112 """File content is the return value of a given function, encoded as JSON.
114 The function is called at the time the file is read. The result is
115 cached until invalidate() is called.
117 def __init__(self, parent_inode, func):
118 super(FuncToJSONFile, self).__init__(parent_inode, "", 0)
121 # invalidate_inode() and invalidate_entry() are asynchronous
122 # with no callback to wait for. In order to guarantee
123 # userspace programs don't get stale data that was generated
124 # before the last invalidate(), we must disallow dirent
126 self.allow_dirent_cache = False
130 return super(FuncToJSONFile, self).size()
132 def readfrom(self, *args, **kwargs):
134 return super(FuncToJSONFile, self).readfrom(*args, **kwargs)
139 self._mtime = time.time()
141 self.contents = json.dumps(obj, indent=4, sort_keys=True) + "\n"