summaryrefslogtreecommitdiff
path: root/tools/dev/lock-check.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/dev/lock-check.py')
-rwxr-xr-xtools/dev/lock-check.py114
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()