mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-22 17:35:59 +03:00
20b21f4fd8
When a client is doing a wait on a job, any other clients will hang when trying to do anything with the service. This is caused by the wait code which was placing the thread that handles incoming dbus requests to sleep until either the timeout expired or the job operation completed. This change creates a thread for the wait request, so that the thread processing incoming requests can continue to run.
173 lines
3.8 KiB
Python
173 lines
3.8 KiB
Python
# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
|
|
#
|
|
# This copyrighted material is made available to anyone wishing to use,
|
|
# modify, copy, or redistribute it subject to the terms and conditions
|
|
# of the GNU General Public License v.2.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
from .automatedproperties import AutomatedProperties
|
|
from .utils import job_obj_path_generate
|
|
from . import cfg
|
|
from .cfg import JOB_INTERFACE
|
|
import dbus
|
|
import threading
|
|
from . import background
|
|
|
|
|
|
# noinspection PyPep8Naming
|
|
class JobState(object):
|
|
def __init__(self, request=None):
|
|
self.rlock = threading.RLock()
|
|
|
|
self._percent = 0
|
|
self._complete = False
|
|
self._request = request
|
|
self._cond = threading.Condition(self.rlock)
|
|
self._ec = 0
|
|
self._stderr = ''
|
|
|
|
# This is an lvm command that is just taking too long and doesn't
|
|
# support background operation
|
|
if self._request:
|
|
# Faking the percentage when we don't have one
|
|
self._percent = 1
|
|
|
|
@property
|
|
def Percent(self):
|
|
with self.rlock:
|
|
return self._percent
|
|
|
|
@Percent.setter
|
|
def Percent(self, value):
|
|
with self.rlock:
|
|
self._percent = value
|
|
|
|
@property
|
|
def Complete(self):
|
|
with self.rlock:
|
|
if self._request:
|
|
self._complete = self._request.is_done()
|
|
if self._complete:
|
|
self._percent = 100
|
|
|
|
return self._complete
|
|
|
|
@Complete.setter
|
|
def Complete(self, value):
|
|
with self.rlock:
|
|
self._complete = value
|
|
self._cond.notify_all()
|
|
|
|
@property
|
|
def GetError(self):
|
|
with self.rlock:
|
|
if self.Complete:
|
|
if self._request:
|
|
(rc, error) = self._request.get_errors()
|
|
return (rc, str(error))
|
|
else:
|
|
return (self._ec, self._stderr)
|
|
else:
|
|
return (-1, 'Job is not complete!')
|
|
|
|
def set_result(self, ec, msg):
|
|
with self.rlock:
|
|
self.Complete = True
|
|
self._ec = ec
|
|
self._stderr = msg
|
|
|
|
def dtor(self):
|
|
with self.rlock:
|
|
self._request = None
|
|
|
|
def Wait(self, timeout):
|
|
try:
|
|
with self._cond:
|
|
# Check to see if we are done, before we wait
|
|
if not self.Complete:
|
|
if timeout != -1:
|
|
self._cond.wait(timeout)
|
|
else:
|
|
self._cond.wait()
|
|
return self.Complete
|
|
except RuntimeError:
|
|
return False
|
|
|
|
@property
|
|
def Result(self):
|
|
with self.rlock:
|
|
if self._request:
|
|
return self._request.result()
|
|
return '/'
|
|
|
|
|
|
# noinspection PyPep8Naming
|
|
class Job(AutomatedProperties):
|
|
_Percent_meta = ('y', JOB_INTERFACE)
|
|
_Complete_meta = ('b', JOB_INTERFACE)
|
|
_Result_meta = ('o', JOB_INTERFACE)
|
|
_GetError_meta = ('(is)', JOB_INTERFACE)
|
|
|
|
def __init__(self, request, job_state=None):
|
|
super(Job, self).__init__(job_obj_path_generate())
|
|
self.set_interface(JOB_INTERFACE)
|
|
|
|
if job_state:
|
|
self.state = job_state
|
|
else:
|
|
self.state = JobState(request)
|
|
|
|
@property
|
|
def Percent(self):
|
|
return self.state.Percent
|
|
|
|
@Percent.setter
|
|
def Percent(self, value):
|
|
self.state.Percent = value
|
|
|
|
@property
|
|
def Complete(self):
|
|
return self.state.Complete
|
|
|
|
@Complete.setter
|
|
def Complete(self, value):
|
|
self.state.Complete = value
|
|
|
|
@property
|
|
def GetError(self):
|
|
return self.state.GetError
|
|
|
|
def set_result(self, ec, msg):
|
|
self.state.set_result(ec, msg)
|
|
|
|
@dbus.service.method(dbus_interface=JOB_INTERFACE)
|
|
def Remove(self):
|
|
if self.state.Complete:
|
|
cfg.om.remove_object(self, True)
|
|
self.state.dtor()
|
|
else:
|
|
raise dbus.exceptions.DBusException(
|
|
JOB_INTERFACE, 'Job is not complete!')
|
|
|
|
@dbus.service.method(dbus_interface=JOB_INTERFACE,
|
|
in_signature='i',
|
|
out_signature='b',
|
|
async_callbacks=('cb', 'cbe'))
|
|
def Wait(self, timeout, cb, cbe):
|
|
background.add_wait(self, timeout, cb, cbe)
|
|
|
|
@property
|
|
def Result(self):
|
|
return self.state.Result
|
|
|
|
@property
|
|
def lvm_id(self):
|
|
return str(id(self))
|
|
|
|
@property
|
|
def Uuid(self):
|
|
import uuid
|
|
return uuid.uuid1()
|