Re: [gentoo-portage-dev] [PATCH] BinpkgFetcher: use async lock (bug 614110)
On 04/21/2018 03:07 PM, Brian Dolbec wrote: > On Sat, 21 Apr 2018 12:27:28 -0700 > Zac Medicowrote: > >> In order to avoid event loop recursion, convert the >> _BinpkgFetcherProcess.lock() method to an async_lock >> method for use by BinpkgFetcher. >> >> Bug: https://bugs.gentoo.org/614110 >> --- >> pym/_emerge/BinpkgFetcher.py | 53 >> +++- 1 file changed, 33 >> insertions(+), 20 deletions(-) >> >> diff --git a/pym/_emerge/BinpkgFetcher.py >> b/pym/_emerge/BinpkgFetcher.py index 5ca7a45cf..2bbc0a26f 100644 >> --- a/pym/_emerge/BinpkgFetcher.py >> +++ b/pym/_emerge/BinpkgFetcher.py >> @@ -32,11 +32,24 @@ class BinpkgFetcher(CompositeTask): >> pkg.cpv) + ".partial" >> >> def _start(self): >> -self._start_task( >> - >> _BinpkgFetcherProcess(background=self.background, >> -logfile=self.logfile, pkg=self.pkg, >> pkg_path=self.pkg_path, >> -pretend=self.pretend, >> scheduler=self.scheduler), >> -self._fetcher_exit) >> +fetcher = >> _BinpkgFetcherProcess(background=self.background, >> +logfile=self.logfile, pkg=self.pkg, >> pkg_path=self.pkg_path, >> +pretend=self.pretend, >> scheduler=self.scheduler) + >> +if not self.pretend: >> + >> portage.util.ensure_dirs(os.path.dirname(self.pkg_path)) >> +if "distlocks" in >> self.pkg.root_config.settings.features: >> +self._start_task( >> + >> AsyncTaskFuture(future=fetcher.async_lock()), >> + >> functools.partial(self._start_locked, fetcher)) >> +return >> + >> +self._start_task(fetcher, self._fetcher_exit) >> + >> +def _start_locked(self, fetcher, lock_task): >> +self._assert_current(lock_task) >> +lock_task.future.result() >> +self._start_task(fetcher, self._fetcher_exit) >> >> def _fetcher_exit(self, fetcher): >> self._assert_current(fetcher) >> @@ -68,13 +81,8 @@ class _BinpkgFetcherProcess(SpawnProcess): >> pretend = self.pretend >> bintree = pkg.root_config.trees["bintree"] >> settings = bintree.settings >> -use_locks = "distlocks" in settings.features >> pkg_path = self.pkg_path >> >> -if not pretend: >> - >> portage.util.ensure_dirs(os.path.dirname(pkg_path)) >> -if use_locks: >> -self.lock() >> exists = os.path.exists(pkg_path) >> resume = exists and os.path.basename(pkg_path) in >> bintree.invalids if not (pretend or resume): >> @@ -184,7 +192,7 @@ class _BinpkgFetcherProcess(SpawnProcess): >> except >> OSError: pass >> >> -def lock(self): >> +def async_lock(self): >> """ >> This raises an AlreadyLocked exception if lock() is >> called while a lock is already held. In order to avoid this, call >> @@ -194,17 +202,22 @@ class _BinpkgFetcherProcess(SpawnProcess): >> if self._lock_obj is not None: >> raise self.AlreadyLocked((self._lock_obj,)) >> >> -async_lock = AsynchronousLock(path=self.pkg_path, >> -scheduler=self.scheduler) >> -async_lock.start() >> +result = self.scheduler.create_future() >> >> -if async_lock.wait() != os.EX_OK: >> -# TODO: Use CompositeTask for better >> handling, like in EbuildPhase. >> -raise AssertionError("AsynchronousLock >> failed with returncode %s" \ >> -% (async_lock.returncode,)) >> +def acquired_lock(async_lock): >> +if async_lock.wait() == os.EX_OK: >> +self.locked = True >> +result.set_result(None) >> +else: >> +result.set_exception(AssertionError( >> +"AsynchronousLock failed >> with returncode %s" >> +% (async_lock.returncode,))) >> >> -self._lock_obj = async_lock >> -self.locked = True >> +self._lock_obj = AsynchronousLock(path=self.pkg_path, >> +scheduler=self.scheduler) >> +self._lock_obj.addExitListener(acquired_lock) >> +self._lock_obj.start() >> +return result >> >> class AlreadyLocked(portage.exception.PortageException): >> pass > > > Looks fine to me :) > Thanks, merged: https://gitweb.gentoo.org/proj/portage.git/commit/?id=adf2e6dd57b5bcaa4a668e3085024ebc3224a2ca -- Thanks, Zac signature.asc Description: OpenPGP digital signature
Re: [gentoo-portage-dev] [PATCH] BinpkgFetcher: use async lock (bug 614110)
On Sat, 21 Apr 2018 12:27:28 -0700 Zac Medicowrote: > In order to avoid event loop recursion, convert the > _BinpkgFetcherProcess.lock() method to an async_lock > method for use by BinpkgFetcher. > > Bug: https://bugs.gentoo.org/614110 > --- > pym/_emerge/BinpkgFetcher.py | 53 > +++- 1 file changed, 33 > insertions(+), 20 deletions(-) > > diff --git a/pym/_emerge/BinpkgFetcher.py > b/pym/_emerge/BinpkgFetcher.py index 5ca7a45cf..2bbc0a26f 100644 > --- a/pym/_emerge/BinpkgFetcher.py > +++ b/pym/_emerge/BinpkgFetcher.py > @@ -32,11 +32,24 @@ class BinpkgFetcher(CompositeTask): > pkg.cpv) + ".partial" > > def _start(self): > - self._start_task( > - > _BinpkgFetcherProcess(background=self.background, > - logfile=self.logfile, pkg=self.pkg, > pkg_path=self.pkg_path, > - pretend=self.pretend, > scheduler=self.scheduler), > - self._fetcher_exit) > + fetcher = > _BinpkgFetcherProcess(background=self.background, > + logfile=self.logfile, pkg=self.pkg, > pkg_path=self.pkg_path, > + pretend=self.pretend, > scheduler=self.scheduler) + > + if not self.pretend: > + > portage.util.ensure_dirs(os.path.dirname(self.pkg_path)) > + if "distlocks" in > self.pkg.root_config.settings.features: > + self._start_task( > + > AsyncTaskFuture(future=fetcher.async_lock()), > + > functools.partial(self._start_locked, fetcher)) > + return > + > + self._start_task(fetcher, self._fetcher_exit) > + > + def _start_locked(self, fetcher, lock_task): > + self._assert_current(lock_task) > + lock_task.future.result() > + self._start_task(fetcher, self._fetcher_exit) > > def _fetcher_exit(self, fetcher): > self._assert_current(fetcher) > @@ -68,13 +81,8 @@ class _BinpkgFetcherProcess(SpawnProcess): > pretend = self.pretend > bintree = pkg.root_config.trees["bintree"] > settings = bintree.settings > - use_locks = "distlocks" in settings.features > pkg_path = self.pkg_path > > - if not pretend: > - > portage.util.ensure_dirs(os.path.dirname(pkg_path)) > - if use_locks: > - self.lock() > exists = os.path.exists(pkg_path) > resume = exists and os.path.basename(pkg_path) in > bintree.invalids if not (pretend or resume): > @@ -184,7 +192,7 @@ class _BinpkgFetcherProcess(SpawnProcess): > except > OSError: pass > > - def lock(self): > + def async_lock(self): > """ > This raises an AlreadyLocked exception if lock() is > called while a lock is already held. In order to avoid this, call > @@ -194,17 +202,22 @@ class _BinpkgFetcherProcess(SpawnProcess): > if self._lock_obj is not None: > raise self.AlreadyLocked((self._lock_obj,)) > > - async_lock = AsynchronousLock(path=self.pkg_path, > - scheduler=self.scheduler) > - async_lock.start() > + result = self.scheduler.create_future() > > - if async_lock.wait() != os.EX_OK: > - # TODO: Use CompositeTask for better > handling, like in EbuildPhase. > - raise AssertionError("AsynchronousLock > failed with returncode %s" \ > - % (async_lock.returncode,)) > + def acquired_lock(async_lock): > + if async_lock.wait() == os.EX_OK: > + self.locked = True > + result.set_result(None) > + else: > + result.set_exception(AssertionError( > + "AsynchronousLock failed > with returncode %s" > + % (async_lock.returncode,))) > > - self._lock_obj = async_lock > - self.locked = True > + self._lock_obj = AsynchronousLock(path=self.pkg_path, > + scheduler=self.scheduler) > + self._lock_obj.addExitListener(acquired_lock) > + self._lock_obj.start() > + return result > > class AlreadyLocked(portage.exception.PortageException): > pass Looks fine to me :) -- Brian Dolbec
[gentoo-portage-dev] [PATCH] BinpkgFetcher: use async lock (bug 614110)
In order to avoid event loop recursion, convert the _BinpkgFetcherProcess.lock() method to an async_lock method for use by BinpkgFetcher. Bug: https://bugs.gentoo.org/614110 --- pym/_emerge/BinpkgFetcher.py | 53 +++- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/pym/_emerge/BinpkgFetcher.py b/pym/_emerge/BinpkgFetcher.py index 5ca7a45cf..2bbc0a26f 100644 --- a/pym/_emerge/BinpkgFetcher.py +++ b/pym/_emerge/BinpkgFetcher.py @@ -32,11 +32,24 @@ class BinpkgFetcher(CompositeTask): pkg.cpv) + ".partial" def _start(self): - self._start_task( - _BinpkgFetcherProcess(background=self.background, - logfile=self.logfile, pkg=self.pkg, pkg_path=self.pkg_path, - pretend=self.pretend, scheduler=self.scheduler), - self._fetcher_exit) + fetcher = _BinpkgFetcherProcess(background=self.background, + logfile=self.logfile, pkg=self.pkg, pkg_path=self.pkg_path, + pretend=self.pretend, scheduler=self.scheduler) + + if not self.pretend: + portage.util.ensure_dirs(os.path.dirname(self.pkg_path)) + if "distlocks" in self.pkg.root_config.settings.features: + self._start_task( + AsyncTaskFuture(future=fetcher.async_lock()), + functools.partial(self._start_locked, fetcher)) + return + + self._start_task(fetcher, self._fetcher_exit) + + def _start_locked(self, fetcher, lock_task): + self._assert_current(lock_task) + lock_task.future.result() + self._start_task(fetcher, self._fetcher_exit) def _fetcher_exit(self, fetcher): self._assert_current(fetcher) @@ -68,13 +81,8 @@ class _BinpkgFetcherProcess(SpawnProcess): pretend = self.pretend bintree = pkg.root_config.trees["bintree"] settings = bintree.settings - use_locks = "distlocks" in settings.features pkg_path = self.pkg_path - if not pretend: - portage.util.ensure_dirs(os.path.dirname(pkg_path)) - if use_locks: - self.lock() exists = os.path.exists(pkg_path) resume = exists and os.path.basename(pkg_path) in bintree.invalids if not (pretend or resume): @@ -184,7 +192,7 @@ class _BinpkgFetcherProcess(SpawnProcess): except OSError: pass - def lock(self): + def async_lock(self): """ This raises an AlreadyLocked exception if lock() is called while a lock is already held. In order to avoid this, call @@ -194,17 +202,22 @@ class _BinpkgFetcherProcess(SpawnProcess): if self._lock_obj is not None: raise self.AlreadyLocked((self._lock_obj,)) - async_lock = AsynchronousLock(path=self.pkg_path, - scheduler=self.scheduler) - async_lock.start() + result = self.scheduler.create_future() - if async_lock.wait() != os.EX_OK: - # TODO: Use CompositeTask for better handling, like in EbuildPhase. - raise AssertionError("AsynchronousLock failed with returncode %s" \ - % (async_lock.returncode,)) + def acquired_lock(async_lock): + if async_lock.wait() == os.EX_OK: + self.locked = True + result.set_result(None) + else: + result.set_exception(AssertionError( + "AsynchronousLock failed with returncode %s" + % (async_lock.returncode,))) - self._lock_obj = async_lock - self.locked = True + self._lock_obj = AsynchronousLock(path=self.pkg_path, + scheduler=self.scheduler) + self._lock_obj.addExitListener(acquired_lock) + self._lock_obj.start() + return result class AlreadyLocked(portage.exception.PortageException): pass -- 2.13.6