diff options
Diffstat (limited to 'src/pybind/cephfs/cephfs.pyx')
-rw-r--r-- | src/pybind/cephfs/cephfs.pyx | 105 |
1 files changed, 71 insertions, 34 deletions
diff --git a/src/pybind/cephfs/cephfs.pyx b/src/pybind/cephfs/cephfs.pyx index b5157867851..8e7b43b25e1 100644 --- a/src/pybind/cephfs/cephfs.pyx +++ b/src/pybind/cephfs/cephfs.pyx @@ -139,6 +139,7 @@ cdef extern from "cephfs/libcephfs.h" nogil: int ceph_mkdirs(ceph_mount_info *cmount, const char *path, mode_t mode) int ceph_closedir(ceph_mount_info *cmount, ceph_dir_result *dirp) int ceph_opendir(ceph_mount_info *cmount, const char *name, ceph_dir_result **dirpp) + void ceph_rewinddir(ceph_mount_info *cmount, ceph_dir_result *dirp) int ceph_chdir(ceph_mount_info *cmount, const char *path) dirent * ceph_readdir(ceph_mount_info *cmount, ceph_dir_result *dirp) int ceph_rmdir(ceph_mount_info *cmount, const char *path) @@ -158,6 +159,7 @@ class Error(Exception): class OSError(Error): def __init__(self, errno, strerror): + super(OSError, self).__init__(errno, strerror) self.errno = errno self.strerror = strerror @@ -274,8 +276,54 @@ StatResult = namedtuple('StatResult', "st_blocks", "st_atime", "st_mtime", "st_ctime"]) cdef class DirResult(object): - cdef ceph_dir_result *handler + cdef LibCephFS lib + cdef ceph_dir_result* handle +# Bug in older Cython instances prevents this from being a static method. +# @staticmethod +# cdef create(LibCephFS lib, ceph_dir_result* handle): +# d = DirResult() +# d.lib = lib +# d.handle = handle +# return d + + def __dealloc__(self): + self.close() + + def __enter__(self): + if not self.handle: + raise make_ex(errno.EBADF, "dir is not open") + self.lib.require_state("mounted") + with nogil: + ceph_rewinddir(self.lib.cluster, self.handle) + return self + + def __exit__(self, type_, value, traceback): + self.close() + return False + + def readdir(self): + self.lib.require_state("mounted") + + with nogil: + dirent = ceph_readdir(self.lib.cluster, self.handle) + if not dirent: + return None + + return DirEntry(d_ino=dirent.d_ino, + d_off=dirent.d_off, + d_reclen=dirent.d_reclen, + d_type=dirent.d_type, + d_name=dirent.d_name) + + def close(self): + if self.handle: + self.lib.require_state("mounted") + with nogil: + ret = ceph_closedir(self.lib.cluster, self.handle) + if ret < 0: + raise make_ex(ret, "closedir failed") + self.handle = NULL def cstr(val, name, encoding="utf-8", opt=False): """ @@ -292,11 +340,13 @@ def cstr(val, name, encoding="utf-8", opt=False): return None if isinstance(val, bytes): return val - elif isinstance(val, unicode): - return val.encode(encoding) else: - raise TypeError('%s must be a string' % name) - + try: + v = val.encode(encoding) + except: + raise TypeError('%s must be encodeable as a bytearray' % name) + assert isinstance(v, bytes) + return v def cstr_list(list_str, name, encoding="utf-8"): return [cstr(s, name) for s in list_str] @@ -687,60 +737,47 @@ cdef class LibCephFS(object): :param path: the path name of the directory to open. Must be either an absolute path or a path relative to the current working directory. - :param dir_handler: the directory result pointer structure to fill in. + :rtype handle: the open directory stream handle """ self.require_state("mounted") path = cstr(path, 'path') cdef: char* _path = path - ceph_dir_result *dir_handler + ceph_dir_result* handle with nogil: - ret = ceph_opendir(self.cluster, _path, &dir_handler); + ret = ceph_opendir(self.cluster, _path, &handle); if ret < 0: raise make_ex(ret, "opendir failed") d = DirResult() - d.handler = dir_handler + d.lib = self + d.handle = handle return d - def readdir(self, DirResult dir_handler): + def readdir(self, DirResult handle): """ Get the next entry in an open directory. - :param dir_handler: the directory stream pointer from an opendir holding the state of the - next entry to return. - :rtype dir_handler: the next directory entry or NULL if at the end of the directory (or the directory is empty. - This pointer should not be freed by the caller, and is only safe to access between return and - the next call to readdir or closedir. + :param handle: the open directory stream handle + :rtype dentry: the next directory entry or None if at the end of the + directory (or the directory is empty. This pointer + should not be freed by the caller, and is only safe to + access between return and the next call to readdir or + closedir. """ self.require_state("mounted") - cdef ceph_dir_result *_dir_handler = dir_handler.handler - with nogil: - dirent = ceph_readdir(self.cluster, _dir_handler) - if not dirent: - return None - - return DirEntry(d_ino=dirent.d_ino, - d_off=dirent.d_off, - d_reclen=dirent.d_reclen, - d_type=dirent.d_type, - d_name=dirent.d_name) + return handle.readdir() - def closedir(self, DirResult dir_handler): + def closedir(self, DirResult handle): """ Close the open directory. - :param dir_handler: the directory result pointer (set by ceph_opendir) to close + :param handle: the open directory stream handle """ self.require_state("mounted") - cdef: - ceph_dir_result *_dir_handler = dir_handler.handler - with nogil: - ret = ceph_closedir(self.cluster, _dir_handler) - if ret < 0: - raise make_ex(ret, "closedir failed") + return handle.close() def mkdir(self, path, mode): """ |