Commit c144b4a4 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 7203d7ab
...@@ -370,7 +370,6 @@ def test_zodb_onshutdown(): ...@@ -370,7 +370,6 @@ def test_zodb_onshutdown():
t1 = T() t1 = T()
t2 = T() t2 = T()
t3 = T()
# conn1 stays alive outside of db.pool # conn1 stays alive outside of db.pool
conn1 = db.open() conn1 = db.open()
......
...@@ -20,14 +20,14 @@ ...@@ -20,14 +20,14 @@
"""Module wcfs.py provides python gateway for spawning and interoperating with wcfs server. """Module wcfs.py provides python gateway for spawning and interoperating with wcfs server.
Serve(zurl) starts and runs WCFS server for ZODB at zurl.
Start(zurl) starts WCFS server for ZODB at zurl and returns corresponding Server object.
Join(zurl) joins wcfs server for ZODB at zurl and returns WCFS object that Join(zurl) joins wcfs server for ZODB at zurl and returns WCFS object that
represents filesystem-level connection to joined wcfs server. If wcfs server represents filesystem-level connection to joined wcfs server. If wcfs server
for zurl is not yet running, it will be automatically started if join is given for zurl is not yet running, it will be automatically started if join is given
`autostart=True` option. `autostart=True` option.
Serve(zurl) starts and runs WCFS server for ZODB at zurl.
Start(zurl) starts WCFS server for ZODB at zurl and returns corresponding Server object.
The rest of wcfs.py merely wraps C++ wcfs client package: The rest of wcfs.py merely wraps C++ wcfs client package:
- `WCFS` represents filesystem-level connection to wcfs server. - `WCFS` represents filesystem-level connection to wcfs server.
...@@ -61,7 +61,7 @@ The following environment variables can be used to control wcfs.py client: ...@@ -61,7 +61,7 @@ The following environment variables can be used to control wcfs.py client:
no join: don't spawn wcfs server unless explicitly requested via autostart=True no join: don't spawn wcfs server unless explicitly requested via autostart=True
$WENDELIN_CORE_WCFS_OPTIONS $WENDELIN_CORE_WCFS_OPTIONS
"" join/start: additional options to pass to wcfs server when spawning it "" serve/start/join: additional options to pass to wcfs server when spawning it
""" """
from __future__ import print_function, absolute_import from __future__ import print_function, absolute_import
...@@ -87,6 +87,17 @@ from .client._wcfs import \ ...@@ -87,6 +87,17 @@ from .client._wcfs import \
PyPinReq as PinReq \ PyPinReq as PinReq \
# Server represents running wcfs server.
#
# Use start to create it.
class Server:
# .mountpoint path to wcfs mountpoint
# ._proc wcfs process
# ._fuseabort opened /sys/fs/fuse/connections/X/abort for this server
# ._stopOnce
pass
# WCFS represents filesystem-level connection to wcfs server. # WCFS represents filesystem-level connection to wcfs server.
# #
# Use join to create it. # Use join to create it.
...@@ -107,17 +118,6 @@ class WCFS(_WCFS): ...@@ -107,17 +118,6 @@ class WCFS(_WCFS):
pass pass
# Server represents running wcfs server.
#
# Use start to create it.
class Server:
# .mountpoint path to wcfs mountpoint
# ._proc wcfs process
# ._fuseabort opened /sys/fs/fuse/connections/X/abort for this server
# ._stopOnce
pass
# ---- WCFS raw file access (primarily for tests) ---- # ---- WCFS raw file access (primarily for tests) ----
# _path returns path for object on wcfs. # _path returns path for object on wcfs.
...@@ -279,15 +279,20 @@ def start(zurl, *optv): # -> Server ...@@ -279,15 +279,20 @@ def start(zurl, *optv): # -> Server
fwcfs.close() fwcfs.close()
return wcsrv return wcsrv
# _optv_with_wcfs_defaults returns optv prepended with default WCFS options taken from environment.
def _optv_with_wcfs_defaults(optv): # -> optv
optv_defaults = os.environ.get("WENDELIN_CORE_WCFS_OPTIONS", "").split()
return tuple(optv_defaults) + tuple(optv)
# _start serves start and join. # _start serves start and join.
@func @func
def _start(zurl, *optv): # -> Server, fwcfs def _start(zurl, *optv): # -> Server, fwcfs
mntpt = _mntpt_4zurl(zurl) mntpt = _mntpt_4zurl(zurl)
optv = _optv_with_wcfs_defaults(optv)
log.info("wcfs: starting for %s ...", zurl) log.info("wcfs: starting for %s ...", zurl)
optv_defaults = os.environ.get("WENDELIN_CORE_WCFS_OPTIONS", "").split()
optv = tuple(optv_defaults) + optv
# XXX errctx "wcfs: start" # XXX errctx "wcfs: start"
# spawn wcfs and wait till filesystem-level access to it is ready # spawn wcfs and wait till filesystem-level access to it is ready
...@@ -412,6 +417,7 @@ def __stop(wcsrv, ctx, _onstuck): ...@@ -412,6 +417,7 @@ def __stop(wcsrv, ctx, _onstuck):
return tctx return tctx
# unmount and wait for wcfs to exit # unmount and wait for wcfs to exit
# kill wcfs and abort FUSE connection if clean unmount fails
def _(): def _():
if wcsrv._fuseabort is not None: if wcsrv._fuseabort is not None:
wcsrv._fuseabort.close() wcsrv._fuseabort.close()
...@@ -494,7 +500,7 @@ def _mntpt_4zurl(zurl): ...@@ -494,7 +500,7 @@ def _mntpt_4zurl(zurl):
if _mkdir_p(wcfsroot): if _mkdir_p(wcfsroot):
os.chmod(wcfsroot, wcfsmode) os.chmod(wcfsroot, wcfsmode)
else: else:
# migration workaround for the situation when /tmp/wcfs was created by # migration workaround for the situation when /dev/shm/wcfs was created by
# code that did not yet set sticky bit. # code that did not yet set sticky bit.
_ = os.stat(wcfsroot) _ = os.stat(wcfsroot)
if _.st_uid == os.getuid(): if _.st_uid == os.getuid():
...@@ -651,8 +657,8 @@ def _ready(ch): ...@@ -651,8 +657,8 @@ def _ready(ch):
# serve(zurl, exec_=False). # serve(zurl, exec_=False).
def serve(zurl, optv, exec_=False, _tstartingq=None): def serve(zurl, optv, exec_=False, _tstartingq=None):
mntpt = _mntpt_4zurl(zurl) mntpt = _mntpt_4zurl(zurl)
optv = _optv_with_wcfs_defaults(optv)
# XXX take $WENDELIN_CORE_WCFS_OPTIONS into account? log.info("wcfs: serving %s ...", zurl)
# try opening .wcfs - it is an error if we can do it. # try opening .wcfs - it is an error if we can do it.
fwcfs, trylockstartf = _try_attach_wcsrv(mntpt) fwcfs, trylockstartf = _try_attach_wcsrv(mntpt)
......
...@@ -122,12 +122,11 @@ class _ZSync: ...@@ -122,12 +122,11 @@ class _ZSync:
_zsync_releaseq.send(zsync.wconn) _zsync_releaseq.send(zsync.wconn)
""" """
# .zconn dealloc -> wconn.close; release zsync. # .zconn dealloc -> wconn.close; release zsync.
def on_zconn_dealloc(zsync, _): def on_zconn_dealloc(zsync, _):
zsync._release1() zsync._release1()
# DB.close tells us that .zconn is shut down -> wconn.close; release zsync. # DB.close -> wconn.close; release zsync.
def on_connection_shutdown(zsync): def on_connection_shutdown(zsync):
zsync._release1() zsync._release1()
......
...@@ -89,12 +89,12 @@ def test_zsync_zconn_gc(): ...@@ -89,12 +89,12 @@ def test_zsync_zconn_gc():
db, zconn, wconn = _zsync_setup(zstor) db, zconn, wconn = _zsync_setup(zstor)
defer(wconn.close) defer(wconn.close)
# del zconn/db -> zconn should disappear and ZSync should close wconn and wc # del zconn -> zconn should disappear and ZSync should close wconn and wc
zconn_weak = weakref.ref(zconn) zconn_weak = weakref.ref(zconn)
assert zconn_weak() is not None assert zconn_weak() is not None
wc_njoin0 = wconn.wc._njoin wc_njoin0 = wconn.wc._njoin
del zconn del zconn
del db # NOTE db stays alive and not closed
gc.collect() gc.collect()
assert zconn_weak() is None assert zconn_weak() is None
_zsync_wclose_wg.wait() _zsync_wclose_wg.wait()
......
...@@ -248,7 +248,6 @@ def test_serve_after_crash(): ...@@ -248,7 +248,6 @@ def test_serve_after_crash():
assert procmounts_lookup_wcfs(zurl) == mntpt assert procmounts_lookup_wcfs(zurl) == mntpt
# start_and_crash_wcfs starts wcfs and then kills it. # start_and_crash_wcfs starts wcfs and then kills it.
# it returns closed WCFS connection that was connected to the killed WCFS server. # it returns closed WCFS connection that was connected to the killed WCFS server.
def start_and_crash_wcfs(zurl, mntpt): # -> WCFS def start_and_crash_wcfs(zurl, mntpt): # -> WCFS
......
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