make keep_cache and direct_io settable filewise

This commit is contained in:
dzsekijo 2007-05-01 15:04:19 +00:00
parent 2aeccd0989
commit a03ce273b0
4 changed files with 108 additions and 3 deletions

View file

@ -1,3 +1,6 @@
2007-05-01 Csaba Henk <csaba.henk@creo.hu>
* Make keep_cache and direct_io settable filewise.
2007-03-13 Csaba Henk <csaba.henk@creo.hu>
* Check for float stat fields everywhere, not only on OS X.

View file

@ -267,9 +267,20 @@ and there are not that many of them (there is no `writedir`). You can
register a directory class by setting the ``dir_class`` ``Fuse``
attribute. I bet you don't wanna use this feature, though.
Another use of filehandles is that they can be used for adjusting some FUSE
tunables *filewise*. That is, if you return a py-filehandle object so that it
has a ``keep_cache`` or ``direct_io`` attribute of value ``True``, then the
respective option will be enabled for the given file by FUSE [#]_. As a special
case, if the returned py-filehandle is an instance of ``fuse.FuseFileInfo``, it
will be used for nothing else apart from testing the ``keep_cache`` /
``direct_io`` attributes (after which it will be disposed).
.. [#] although it should not be an integer, as integers are treated as
error values
.. [#] See the meaning of these options eg. in standard FUSE help message,
which you can read by, eg., running ``example/xmp.py -h`` from the root of
the FUSE Python bindings source tree.
Complete support for hi-lib
---------------------------

42
fuse.py
View file

@ -429,6 +429,16 @@ class Direntry(object):
self.ino = 0
class FuseFileInfo:
def __init__(self, keep = False, direct_io = False):
self.keep = keep
self.direct_io = direct_io
########## Interface for requiring certain features from your underlying FUSE library.
def feature_needs(*feas):
@ -468,6 +478,10 @@ def feature_needs(*feas):
fmap = {'stateful_files': 22,
'stateful_dirs': 23,
'stateful_io': ('stateful_files', 'stateful_dirs'),
'stateful_files_keep_cache': 23,
'stateful_files_direct_io': 23,
'keep_cache': ('stateful_files_keep_cache',),
'direct_io': ('stateful_files_direct_io',),
'has_opendir': ('stateful_dirs',),
'has_releasedir': ('stateful_dirs',),
'has_fsyncdir': ('stateful_dirs',),
@ -640,7 +654,7 @@ class Fuse(object):
c = ''
if get_compat_0_1() and hasattr(self, a + '_compat_0_1'):
c = '_compat_0_1'
d[a] = ErrnoWrapper(getattr(self, a + c))
d[a] = ErrnoWrapper(self.lowwrap(a + c))
try:
main(**d)
@ -648,6 +662,32 @@ class Fuse(object):
if args or self.fuse_args.mount_expected():
raise
def lowwrap(self, fname):
"""
Wraps the fname method when the C code expects a different kind of
callback than we have in the fusepy API. (The wrapper is usually for
performing some checks or transfromations which could be done in C but
is simpler if done in Python.)
Currently `open` and `create` are wrapped: a boolean flag is added
which indicates if the result is to be kept during the opened file's
lifetime or can be thrown away. Namely, it's considered disposable
if it's an instance of FuseFileInfo.
"""
fun = getattr(self, fname)
if not fname in ('open', 'create'):
return fun
def wrap(*a, **kw):
res = fun(*a, **kw)
if not res or type(res) == type(0):
return res
else:
return (res, type(res) != FuseFileInfo)
return wrap
def GetContext(self):
return FuseGetContext(self)

View file

@ -506,9 +506,31 @@ write_func(const char *path, const char *buf, size_t t, off_t off)
static int
open_func(const char *path, struct fuse_file_info *fi)
{
PyObject *pytmp, *pytmp1;
PROLOGUE( PyObject_CallFunction(open_cb, "si", path, fi->flags) )
fi->fh = (uintptr_t) v;
pytmp = PyTuple_GetItem(v, 0);
#if FUSE_VERSION >= 23
pytmp1 = PyObject_GetAttrString(pytmp, "keep_cache");
if (pytmp1) {
fi->keep_cache = PyObject_IsTrue(pytmp1);
Py_DECREF(pytmp1);
}
pytmp1 = PyObject_GetAttrString(pytmp, "direct_io");
if (pytmp1) {
fi->direct_io = PyObject_IsTrue(pytmp1);
Py_DECREF(pytmp1);
}
if (PyObject_IsTrue(PyTuple_GetItem(v, 1)))
#endif
{
Py_INCREF(pytmp);
fi->fh = (uintptr_t) pytmp;
}
ret = 0;
goto OUT;
@ -527,11 +549,30 @@ open_func(const char *path, int mode)
static int
create_func(const char *path, mode_t mode, struct fuse_file_info *fi)
{
PyObject *pytmp, *pytmp1;
PROLOGUE(
PyObject_CallFunction(create_cb, "sii", path, fi->flags, mode)
)
fi->fh = (uintptr_t) v;
pytmp = PyTuple_GetItem(v, 0);
pytmp1 = PyObject_GetAttrString(pytmp, "keep_cache");
if (pytmp1) {
fi->keep_cache = PyObject_IsTrue(pytmp1);
Py_DECREF(pytmp1);
}
pytmp1 = PyObject_GetAttrString(pytmp, "direct_io");
if (pytmp1) {
fi->direct_io = PyObject_IsTrue(pytmp1);
Py_DECREF(pytmp1);
}
if (PyObject_IsTrue(PyTuple_GetItem(v, 1))) {
Py_INCREF(pytmp);
fi->fh = (uintptr_t) pytmp;
}
ret = 0;
goto OUT;
@ -735,6 +776,16 @@ fsdestroy_func(void *param)
}
#endif
static int
lock_func(const char *path, struct fuse_file_info *fi, int cmd,
struct flock *lock)
{
(void) path;
return ulockmgr_op(fi->fh, cmd, lock, &fi->lock_owner,
sizeof(fi->lock_owner));
}
static int
pyfuse_loop_mt(struct fuse *f)
{