diff options
Diffstat (limited to 'tools/dev/lock-check.py')
-rwxr-xr-x | tools/dev/lock-check.py | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/tools/dev/lock-check.py b/tools/dev/lock-check.py new file mode 100755 index 0000000..710bf48 --- /dev/null +++ b/tools/dev/lock-check.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# + +### 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() |