- add the Fedora Extras pushscript lock - change the Repo.py locking and exception handling [and add debug output to investigate a mysterious exception in _update_repo() shutil.copy()] diff -Nur plague-0.4.4.1-orig/server/PackageJob.py plague-0.4.4.1/server/PackageJob.py --- plague-0.4.4.1-orig/server/PackageJob.py 2006-03-13 05:10:49.000000000 +0100 +++ plague-0.4.4.1/server/PackageJob.py 2007-12-30 23:13:50.000000000 +0100 @@ -701,6 +701,7 @@ def _stage_repodone(self): resultstring = " %s (%s): Build on target %s succeeded." % (self.uid, self.name, self._target_str) + log(resultstring) self.result = 'success' self._set_cur_stage('needsign', resultstring) diff -Nur plague-0.4.4.1-orig/server/Repo.py plague-0.4.4.1/server/Repo.py --- plague-0.4.4.1-orig/server/Repo.py 2005-11-29 07:17:07.000000000 +0100 +++ plague-0.4.4.1/server/Repo.py 2007-12-30 21:55:34.000000000 +0100 @@ -25,6 +25,9 @@ import EmailUtils from plague import DebugUtils +# Lockfile used by external scripts to ensure mutual exclusion +# from concurrent access to the repository's directory +REPO_LOCKFILE_NAME = ".repo-update.lock" class Repo(threading.Thread): """ Represents an on-disk repository of RPMs and manages updates to the repo. """ @@ -41,6 +44,7 @@ self._repodir = os.path.join(repodir, target_str) if not os.path.exists(self._repodir): os.makedirs(self._repodir) + self._lockfile_path = os.path.join(self._repodir, REPO_LOCKFILE_NAME) self._repo_cache_dir = os.path.join(repodir, "cache", target_str) if not os.path.exists(self._repo_cache_dir): @@ -87,8 +91,29 @@ return True return False + def _update_repo_with_pushlock(self): + lockfile = None + try: + lockfile = open(self._lockfile_path, 'w') + rc = fcntl.flock(lockfile, fcntl.LOCK_EX) + except IOError, (errno, strerr): + print "Repo Error (%s): opening lockfile %s failed. Output: (errno %d) '%s'" % (target_string, self._lockfile_path, errno, strerr) + + try: + self._update_repo() + except: + if lockfile: + fcntl.flock(lockfile, fcntl.LOCK_UN) + lockfile.close() + raise + if lockfile: + fcntl.flock(lockfile, fcntl.LOCK_UN) + lockfile.close() + def _update_repo(self): """ Copy new RPMS to each repo, and update each repo at the end """ + target_string = self._target_cfg.target_string() + for buildjob in self._repo_additions: # Ensure all the files are accessible success = True @@ -97,6 +122,9 @@ if not os.path.exists(src) or not os.access(src, os.R_OK): success = False bad_file = src + print "Repo: %s is inaccessible." % src + else: + print "Repo: %s is accessible." % src if success: for src in buildjob.repofiles.keys(): @@ -199,7 +229,12 @@ if self._lock_count == 2: target_str = self._target_cfg.target_string() print "Repo '%s': updating repository metadata..." % target_str - self._update_repo() + try: + self._update_repo_with_pushlock() + except IOError, (err, strerr): + print "Repo '%s': %s (%d)" % (target_str, strerr, err) + except OSError, e: + print "Repo '%s': %s" % (target_str, e) print "Repo '%s': Done updating." % target_str # If there's a repo script for this target, enter level 3