|  | #!/usr/bin/env python | 
|  |  | 
|  | ### Repository lock checker.  Gets an exclusive lock on the provided | 
|  | ### repository, then runs db_stat to see if the lock counts have been | 
|  | ### reset to 0.  If not, prints the timestamp of the run and a message | 
|  | ### about accumulation. | 
|  |  | 
|  | DB_STAT = 'db_stat' | 
|  |  | 
|  |  | 
|  | import sys | 
|  | import os | 
|  | import os.path | 
|  | import time | 
|  | import fcntl | 
|  | import getopt | 
|  | try: | 
|  | my_getopt = getopt.gnu_getopt | 
|  | except AttributeError: | 
|  | my_getopt = getopt.getopt | 
|  |  | 
|  | def usage_and_exit(retval): | 
|  | if retval: | 
|  | out = sys.stderr | 
|  | else: | 
|  | out = sys.stdout | 
|  | out.write("""Usage: %s [OPTIONS] REPOS-PATH | 
|  |  | 
|  | Options: | 
|  | --help (-h)    : Show this usage message | 
|  | --non-blocking : Don't wait for a lock that can't be immediately obtained | 
|  |  | 
|  | Obtain an exclusive lock (waiting for one unless --non-blocking is | 
|  | passed) on REPOS-PATH, then check its lock usage counts.  If there is | 
|  | any accumulation present, report that accumulation to stdout. | 
|  | """ % (os.path.basename(sys.argv[0]))) | 
|  | sys.exit(retval) | 
|  |  | 
|  | def main(): | 
|  | now_time = time.asctime() | 
|  | repos_path = None | 
|  | nonblocking = 0 | 
|  |  | 
|  | # Parse the options. | 
|  | optlist, args = my_getopt(sys.argv[1:], "h", ['non-blocking', 'help']) | 
|  | for opt, arg in optlist: | 
|  | if opt == '--help' or opt == '-h': | 
|  | usage_and_exit(0) | 
|  | if opt == '--non-blocking': | 
|  | nonblocking = 1 | 
|  | else: | 
|  | usage_and_exit(1) | 
|  |  | 
|  | # We need at least a path to work with, here. | 
|  | argc = len(args) | 
|  | if argc < 1 or argc > 1: | 
|  | usage_and_exit(1) | 
|  | repos_path = args[0] | 
|  |  | 
|  | fd = open(os.path.join(repos_path, 'locks', 'db.lock'), 'a') | 
|  | try: | 
|  | # Get an exclusive lock on the repository lock file, but maybe | 
|  | # don't wait for it. | 
|  | try: | 
|  | mode = fcntl.LOCK_EX | 
|  | if nonblocking: | 
|  | mode = mode | fcntl.LOCK_NB | 
|  | fcntl.lockf(fd, mode) | 
|  | except IOError: | 
|  | sys.stderr.write("Error obtaining exclusive lock.\n") | 
|  | sys.exit(1) | 
|  |  | 
|  | # Grab the db_stat results. | 
|  | lines = os.popen('%s -ch %s' % (DB_STAT, os.path.join(repos_path, 'db'))) | 
|  | log_lines = [] | 
|  | for line in lines: | 
|  | pieces = line.split('\t') | 
|  | if (pieces[1].find('current lock') != -1) and (int(pieces[0]) > 0): | 
|  | log = '' | 
|  | if not len(log_lines): | 
|  | log = log + "[%s] Lock accumulation for '%s'\n" \ | 
|  | % (now_time, repos_path) | 
|  | log = log + ' ' * 27 | 
|  | log = log + "%s\t%s" % (pieces[0], pieces[1]) | 
|  | log_lines.append(log) | 
|  | if len(log_lines): | 
|  | sys.stdout.write(''.join(log_lines)) | 
|  | finally: | 
|  | # Unlock the lockfile | 
|  | fcntl.lockf(fd, fcntl.LOCK_UN) | 
|  | fd.close() | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | main() |