diff options
author | Prashanth Pai <ppai@redhat.com> | 2016-05-30 17:42:15 +0530 |
---|---|---|
committer | Prashanth Pai <ppai@redhat.com> | 2016-06-01 12:42:25 +0530 |
commit | 972c24f8b11d5a3e7e6fc341453d9733b2bb47b5 (patch) | |
tree | d38c5cdf723c1a029455147ddbb19cf126c3186e /gluster | |
parent | 123c2b7dc51d012f6d2924f680eeec748187a300 (diff) |
Implement os.utime() like API and zerofill
This patch:
* Implements Volume.utime() which is very similar to os.utime() present
in Python. https://docs.python.org/2/library/os.html#os.utime
* Implements File.zerofill() which exposes glfs_zerofill.
* Fixes function prototype of fallocate and discard. Adds functional
tests for the same.
Change-Id: Icb8d3a571998c31d6bf9b139ca253af59f6fc3f4
Signed-off-by: Prashanth Pai <ppai@redhat.com>
Diffstat (limited to 'gluster')
-rwxr-xr-x | gluster/api.py | 31 | ||||
-rwxr-xr-x | gluster/gfapi.py | 45 |
2 files changed, 67 insertions, 9 deletions
diff --git a/gluster/api.py b/gluster/api.py index 7163076..3fd9d91 100755 --- a/gluster/api.py +++ b/gluster/api.py @@ -115,6 +115,13 @@ class Dirent (ctypes.Structure): ] +class Timespec (ctypes.Structure): + _fields_ = [ + ('tv_sec', ctypes.c_long), + ('tv_nsec', ctypes.c_long) + ] + + # Here is the reference card of libgfapi library exported # apis with its different versions. # @@ -474,12 +481,22 @@ glfs_getcwd = gfapi_prototype('glfs_getcwd', ctypes.c_char_p, ctypes.c_char_p, ctypes.c_size_t) +glfs_fallocate = gfapi_prototype('glfs_fallocate', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_int, + ctypes.c_size_t) + +glfs_discard = gfapi_prototype('glfs_discard', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_int, + ctypes.c_size_t) -# TODO: # discard and fallocate fails with "AttributeError: /lib64/libgfapi.so.0: undefined symbol: glfs_discard", # noqa -# for time being, using it from api.* # noqa -# glfs_discard = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_ulong, ctypes.c_size_t)(('glfs_discard', client)) # noqa -# _glfs_fallocate = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_ulong, ctypes.c_size_t) # noqa -# (('glfs_fallocate', client)) # noqa +glfs_zerofill = gfapi_prototype('glfs_zerofill', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_int, + ctypes.c_size_t) -# glfs_discard = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_ulong, ctypes.c_size_t)(('glfs_discard', client)) # noqa -# glfs_fallocate = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_ulong, ctypes.c_size_t)(('glfs_fallocate', client)) # noqa +glfs_utimens = gfapi_prototype('glfs_utimens', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.POINTER(Timespec)) diff --git a/gluster/gfapi.py b/gluster/gfapi.py index c84b262..c409f62 100755 --- a/gluster/gfapi.py +++ b/gluster/gfapi.py @@ -11,6 +11,8 @@ import ctypes import os +import math +import time import stat import errno from gluster import api @@ -87,7 +89,7 @@ class File(object): self._closed = True def discard(self, offset, len): - ret = api.client.glfs_discard(self.fd, offset, len) + ret = api.glfs_discard(self.fd, offset, len) if ret < 0: err = ctypes.get_errno() raise OSError(err, os.strerror(err)) @@ -111,7 +113,7 @@ class File(object): :param offset: Starting offset :param length: Size in bytes, starting at offset """ - ret = api.client.glfs_fallocate(self.fd, mode, offset, length) + ret = api.glfs_fallocate(self.fd, mode, offset, length) if ret < 0: err = ctypes.get_errno() raise OSError(err, os.strerror(err)) @@ -370,6 +372,12 @@ class File(object): raise OSError(err, os.strerror(err)) return ret + def zerofill(self, offset, length): + ret = api.glfs_zerofill(self.fd, offset, length) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + class Dir(object): @@ -1036,6 +1044,39 @@ class Volume(object): err = ctypes.get_errno() raise OSError(err, os.strerror(err)) + def utime(self, path, times): + """ + Set the access and modified times of the file specified by path. If + times is None, then the file's access and modified times are set to + the current time. (The effect is similar to running the Unix program + touch on the path.) Otherwise, times must be a 2-tuple of numbers, + of the form (atime, mtime) which is used to set the access and + modified times, respectively. + """ + if times is None: + now = time.time() + times = (now, now) + else: + if type(times) is not tuple or len(times) != 2: + raise TypeError("utime() arg 2 must be a tuple (atime, mtime)") + + timespec_array = (api.Timespec * 2)() + + # Set atime + decimal, whole = math.modf(times[0]) + timespec_array[0].tv_sec = int(whole) + timespec_array[0].tv_nsec = int(decimal * 1e9) + + # Set mtime + decimal, whole = math.modf(times[1]) + timespec_array[1].tv_sec = int(whole) + timespec_array[1].tv_nsec = int(decimal * 1e9) + + ret = api.glfs_utimens(self.fs, path, timespec_array) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + def walk(self, top, topdown=True, onerror=None, followlinks=False): """ Directory tree generator. Yields a 3-tuple dirpath, dirnames, filenames |