Commit 839a1f68 by rfkelly0

fix a locking bug in MountFS.getsize

parent 654209fd
#!/usr/bin/env python
from base import *
from objecttree import ObjectTree
from memoryfs import MemoryFS
from fs.base import *
from fs.objecttree import ObjectTree
class DirMount(object):
......@@ -53,204 +52,159 @@ class MountFS(FS):
return self, head_path, tail_path
@synchronize
def desc(self, path):
self._lock.acquire()
try:
fs, mount_path, delegate_path = self._delegate(path)
if fs is self:
if fs.isdir(path):
return "Mount dir"
else:
return "Mounted file"
return "Mounted dir, maps to path %s on %s" % (delegate_path, str(fs))
finally:
self._lock.release()
fs, mount_path, delegate_path = self._delegate(path)
if fs is self:
if fs.isdir(path):
return "Mount dir"
else:
return "Mounted file"
return "Mounted dir, maps to path %s on %s" % (delegate_path, str(fs))
@synchronize
def isdir(self, path):
self._lock.acquire()
try:
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
raise ResourceNotFoundError(path)
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
raise ResourceNotFoundError(path)
if fs is self:
object = self.mount_tree.get(path, None)
return isinstance(object, dict)
else:
return fs.isdir(delegate_path)
finally:
self._lock.release()
if fs is self:
object = self.mount_tree.get(path, None)
return isinstance(object, dict)
else:
return fs.isdir(delegate_path)
@synchronize
def isfile(self, path):
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
return ResourceNotFoundError(path)
self._lock.acquire()
try:
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
return ResourceNotFoundError(path)
if fs is self:
object = self.mount_tree.get(path, None)
return type(object) is MountFS.FileMount
else:
return fs.isfile(delegate_path)
finally:
self._lock.release()
if fs is self:
object = self.mount_tree.get(path, None)
return type(object) is MountFS.FileMount
else:
return fs.isfile(delegate_path)
@synchronize
def listdir(self, path="/", wildcard=None, full=False, absolute=False, dirs_only=False, files_only=False):
path = normpath(path)
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
raise ResourceNotFoundError(path)
if fs is self:
if files_only:
return []
paths = self.mount_tree[path].keys()
return self._listdir_helper(path,
paths,
wildcard,
full,
absolute,
dirs_only,
files_only)
else:
paths = fs.listdir(delegate_path,
wildcard=wildcard,
full=False,
absolute=False,
dirs_only=dirs_only,
files_only=files_only)
if full or absolute:
if full:
path = abspath(normpath(path))
else:
path = relpath(normpath(path))
paths = [pathjoin(path, p) for p in paths]
self._lock.acquire()
try:
path = normpath(path)
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
raise ResourceNotFoundError(path)
if fs is self:
if files_only:
return []
paths = self.mount_tree[path].keys()
return self._listdir_helper(path,
paths,
wildcard,
full,
absolute,
dirs_only,
files_only)
else:
paths = fs.listdir(delegate_path,
wildcard=wildcard,
full=False,
absolute=False,
dirs_only=dirs_only,
files_only=files_only)
if full or absolute:
if full:
path = abspath(normpath(path))
else:
path = relpath(normpath(path))
paths = [pathjoin(path, p) for p in paths]
return paths
finally:
self._lock.release()
return paths
@synchronize
def makedir(self, path, recursive=False, allow_recreate=False):
path = normpath(path)
self._lock.acquire()
try:
fs, mount_path, delegate_path = self._delegate(path)
if fs is self:
raise UnsupportedError("make directory", msg="Can only makedir for mounted paths" )
return fs.makedir(delegate_path, recursive=recursive, allow_recreate=allow_recreate)
finally:
self._lock.release()
fs, mount_path, delegate_path = self._delegate(path)
if fs is self:
raise UnsupportedError("make directory", msg="Can only makedir for mounted paths" )
return fs.makedir(delegate_path, recursive=recursive, allow_recreate=allow_recreate)
@synchronize
def open(self, path, mode="r", **kwargs):
path = normpath(path)
object = self.mount_tree.get(path, None)
if type(object) is MountFS.FileMount:
callable = object.open_callable
return callable(path, mode, **kwargs)
self._lock.acquire()
try:
path = normpath(path)
object = self.mount_tree.get(path, None)
if type(object) is MountFS.FileMount:
callable = object.open_callable
return callable(path, mode, **kwargs)
fs, mount_path, delegate_path = self._delegate(path)
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
raise ResourceNotFoundError(path)
if fs is None:
raise ResourceNotFoundError(path)
return fs.open(delegate_path, mode, **kwargs)
return fs.open(delegate_path, mode, **kwargs)
finally:
self._lock.release()
@synchronize
def exists(self, path):
self._lock.acquire()
try:
path = normpath(path)
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
return False
if fs is self:
return path in self.mount_tree
return fs.exists(delegate_path)
finally:
self._lock.release()
path = normpath(path)
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
return False
if fs is self:
return path in self.mount_tree
return fs.exists(delegate_path)
@synchronize
def remove(self, path):
self._lock.acquire()
try:
path = normpath(path)
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
raise ResourceNotFoundError(path)
if fs is self:
raise UnsupportedError("remove file", msg="Can only remove paths within a mounted dir")
return fs.remove(delegate_path)
finally:
self._lock.release()
path = normpath(path)
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
raise ResourceNotFoundError(path)
if fs is self:
raise UnsupportedError("remove file", msg="Can only remove paths within a mounted dir")
return fs.remove(delegate_path)
@synchronize
def removedir(self, path, recursive=False, force=False):
path = normpath(path)
fs, mount_path, delegate_path = self._delegate(path)
self._lock.acquire()
try:
path = normpath(path)
fs, mount_path, delegate_path = self._delegate(path)
if fs is None or fs is self:
raise ResourceInvalidError(path, msg="Can not removedir for an un-mounted path")
if not force and not fs.isdirempty(delegate_path):
raise DirectoryNotEmptyError("Directory is not empty: %(path)s")
if fs is None or fs is self:
raise ResourceInvalidError(path, msg="Can not removedir for an un-mounted path")
return fs.removedir(delegate_path, recursive, force)
if not force and not fs.isdirempty(delegate_path):
raise DirectoryNotEmptyError("Directory is not empty: %(path)s")
finally:
self._lock.release()
return fs.removedir(delegate_path, recursive, force)
@synchronize
def rename(self, src, dst):
if not issamedir(src, dst):
raise ValueError("Destination path must the same directory (use the move method for moving to a different directory)")
fs1, mount_path1, delegate_path1 = self._delegate(src)
fs2, mount_path2, delegate_path2 = self._delegate(dst)
self._lock.acquire()
try:
fs1, mount_path1, delegate_path1 = self._delegate(src)
fs2, mount_path2, delegate_path2 = self._delegate(dst)
if fs1 is not fs2:
raise OperationFailedError("rename resource", path=src)
if fs1 is not fs2:
raise OperationFailedError("rename resource", path=src)
if fs1 is not self:
return fs1.rename(delegate_path1, delegate_path2)
if fs1 is not self:
return fs1.rename(delegate_path1, delegate_path2)
path_src = normpath(src)
path_dst = normpath(dst)
path_src = normpath(src)
path_dst = normpath(dst)
object = self.mount_tree.get(path_src, None)
object2 = self.mount_tree.get(path_dst, None)
object = self.mount_tree.get(path_src, None)
object2 = self.mount_tree.get(path_dst, None)
if object1 is None:
raise ResourceNotFoundError(src)
if object1 is None:
raise ResourceNotFoundError(src)
# TODO!
raise UnsupportedError("rename resource", path=src)
finally:
self._lock.release()
# TODO!
raise UnsupportedError("rename resource", path=src)
@synchronize
def mountdir(self, path, fs):
"""Mounts a directory on a given path.
......@@ -258,60 +212,46 @@ class MountFS(FS):
fs -- A filesystem object to mount
"""
self._lock.acquire()
try:
path = normpath(path)
self.mount_tree[path] = MountFS.DirMount(path, fs)
finally:
self._lock.release()
path = normpath(path)
self.mount_tree[path] = MountFS.DirMount(path, fs)
mount = mountdir
@synchronize
def mountfile(self, path, open_callable=None, info_callable=None):
self._lock.acquire()
try:
path = normpath(path)
self.mount_tree[path] = MountFS.FileMount(path, callable, info_callable)
finally:
self._lock.release()
path = normpath(path)
self.mount_tree[path] = MountFS.FileMount(path, callable, info_callable)
@synchronize
def getinfo(self, path):
path = normpath(path)
self._lock.acquire()
try:
path = normpath(path)
fs, mount_path, delegate_path = self._delegate(path)
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
raise ResourceNotFoundError(path)
if fs is None:
raise ResourceNotFoundError(path)
if fs is self:
if self.isfile(path):
return self.mount_tree[path].info_callable(path)
return {}
return fs.getinfo(delegate_path)
finally:
self._lock.release()
if fs is self:
if self.isfile(path):
return self.mount_tree[path].info_callable(path)
return {}
return fs.getinfo(delegate_path)
@synchronize
def getsize(self, path):
self._lock.acquire()
try:
path = normpath(path)
fs, mount_path, delegate_path = self._delegate(path)
path = normpath(path)
fs, mount_path, delegate_path = self._delegate(path)
if fs is None:
raise ResourceNotFoundError(path)
if fs is None:
raise ResourceNotFoundError(path)
if fs is self:
object = self.mount_tree.get(path, None)
if fs is self:
object = self.mount_tree.get(path, None)
if object is None or isinstance(object, dict):
raise ResourceNotFoundError(path)
if object is None or isinstance(object, dict):
raise ResourceNotFoundError(path)
size = self.mount_tree[path].info_callable(path).get("size", None)
return size
size = self.mount_tree[path].info_callable(path).get("size", None)
return size
return fs.getinfo(delegate_path).get("size", None)
except:
self._lock.release()
return fs.getinfo(delegate_path).get("size", None)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment