Skip to content
Open
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b3770ed
zfs: reimplement Filesystem._exists using lzc_exists
Jun 25, 2015
d6cbfaf
zfs: add utility code for running lzc functions in a thread pool
Jul 17, 2015
e5531f6
zfs: switch snapshot creation to lzc
Jun 30, 2015
9a8d17c
zfs: switch filesystem creation to lzc
Jun 30, 2015
5f66c2d
zfs: convert set_maximum_size() to libzfs_core
Jul 9, 2015
fa0a0ff
zfs: delete a comment paragraph that was meant to be deleted earlier
Jun 30, 2015
9a80397
zfs: switch filesystem sending and receiving to lzc
Jun 30, 2015
a44576f
zfs: switch cloning, renaming and setting some properties to lzc
Jul 17, 2015
bcd8bf1
zfs: replace snapshot listing via 'zfs' with lzc_list_snaps()
Jul 17, 2015
8d8a6d8
zfs: make snapshot sorting more reliable by using createtxg property
Jul 8, 2015
1349bfd
zfs: convert filesystem listing to libzfs_core
Jul 9, 2015
35ce7c2
zfs: convert filesystem (with snapshots) destruction to libzfs_core
Jul 8, 2015
f4eb274
zfs: convert the initial setup of the pool root filesystem to libzfs_…
Jul 9, 2015
186eff4
zfs: fix a problem with unmounting of some filesystems
Jul 13, 2015
8308e8a
zfs: add basic docstrings for _AsyncLZC and the related code
Aug 7, 2015
3d8f9cb
zfs: catch up with lzc_create signature change
Aug 7, 2015
dcc914f
log lzc_send and lzc_receive exceptions
Aug 10, 2015
4d2bbdb
zfs backend: remove _FakeAsyncLZC that fell out of use
Aug 10, 2015
e387cf5
lzc_send/lzc_receive: log traceback in addition to exception
Aug 14, 2015
47dfab0
add pyzfs to requirements
Sep 29, 2015
3123937
Merge remote-tracking branch 'origin/master' into pyzfs-FLOC-2683
Sep 29, 2015
7cfdc3a
update pyzfs requirements
Oct 1, 2015
80c1a02
Merge remote-tracking branch 'origin/master' into pyzfs-FLOC-2683
Oct 5, 2015
05fb5d5
flocker-volume: ensure that the reactor is running
Oct 8, 2015
ead482e
Merge branch 'master' into pyzfs-FLOC-2683
Oct 8, 2015
3801ea8
Merge branch 'master' into pyzfs-FLOC-2683
Oct 30, 2015
8ba3807
use lzc_receive_with_header() instead of lzc_receive
Oct 30, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
zfs: add basic docstrings for _AsyncLZC and the related code
  • Loading branch information
Andriy Gapon committed Aug 7, 2015
commit 8308e8a1e4d839de9e0f93ccf1a9de28930b18b8
44 changes: 44 additions & 0 deletions flocker/volume/filesystems/zfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,40 @@ def connectionLost(self, reason):


class _AsyncLZC(object):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's early days, but a doc string here would help me understand the design of this wrapper.

Instead of wrapping every libzfs_core function with _async_wrapper consider creating an ILibZFSCore Zope Interface and using auto_threaded from https://github.com/ClusterHQ/flocker/blob/master/flocker/common/_thread.py

Or perhaps you'll have to create a slightly higher level abstraction in order to use that. eg IZFSClient which is wrapped to give IZFSClientAsync. That's how @exarkun organised the IBlockDeviceAPI .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds a little bit too advanced for my skills.
I can try to do that or it can be deferred to a more skilled developer.
In either case I will work on this item and see what I can do. At the very least I'll add documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least, I've added the docstrings now.

"""
A proxy class for the asynchronous execution using a given reactor and its
thread pool.

Primarily this class dispatches its method calls to the functions in
:mod:`libzfs_core`. But it can also be used for the asynchronous execution
of an arbitrary function.
"""

def __init__(self, reactor):
"""
:param reactor: the reactor that is to be used for the asynchronous
execution.
"""
self._reactor = reactor
self._cache = {}

def callDeferred(self, func, *args, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just move this into the nested _async_wrapper function below?
And it seems like it should be private?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's actually not private and is used in several places. The missing documentation would help, of course.
It turned out that in some cases it was insufficient to call a single lzc_ function in the asynchronous fashion.
For example, _list_snapshots calls _do_list_snapshots via callDeferred.
Perhaps there was a better way to do that...

"""
This is a thin wrapper around :func:`deferToThreadPool`.

Its primary advantage is that the reactor is already associated with
an instance of :class:`_AsyncLZC` and :meth:`getThreadPool` is called
to get the reactor's thread pool.
"""
return deferToThreadPool(self._reactor, self._reactor.getThreadPool(),
func, *args, **kwargs)

def __getattr__(self, name):
"""
Pretend that this class provides the same methods as the functions
in :mod:`libzfs_core`. The proxy methods execute the functions
in the asynchronous mode using the reactor and its thread pool.
"""
try:
return self._cache[name]
except KeyError:
Expand All @@ -95,6 +120,16 @@ def _async_wrapper(*args, **kwargs):


class _FakeAsyncLZC(object):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe move the Fake to a flocker.volume.zfs.testtools module.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_FakeAsyncLZC has been completely removed as it has become disused now, even by the tests.

"""
A proxy class that emulates the asynchronous execution.

This class simulates behavior of :class:`_AsyncLZC`, but all the calls
are actually synchronous and returned :class:`Deferred` objects already
have results.

This is useful for testing when a reactor used does not have a thread pool.
"""

def __init__(self):
self._cache = {}

Expand All @@ -119,6 +154,15 @@ def _async_wrapper(*args, **kwargs):


def _async_lzc(reactor):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this looks like a function that'd only be used in tests...returning FakeAsyncLZC for synchronous unit tests and AsyncLZC for async functional tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The missing documentation would help here as well :-(
The main purpose of this function is to associate an AsyncLZC instance with a given reactor and cache it.

"""
Return an instance of either :class:`_AsyncLZC` or :class:`_FakeAsyncLZC`
for the given reactor depending on its capabilities.

:param reactor: the reactor.

The instance gets associated with the reactor and the same instance will
be returned for subsequent calls with the same ``reactor`` argument.
"""
try:
return _reactor_to_alzc[reactor]
except KeyError:
Expand Down