File: lock-check.py

package info (click to toggle)
subversion 1.4.2dfsg1-3
  • links: PTS
  • area: main
  • in suites: etch
  • size: 37,284 kB
  • ctags: 32,888
  • sloc: ansic: 406,472; python: 38,378; sh: 15,438; cpp: 9,604; ruby: 8,313; perl: 5,308; java: 4,576; lisp: 3,860; xml: 3,298; makefile: 856
file content (90 lines) | stat: -rwxr-xr-x 2,473 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#!/usr/bin/env python

### Repository lock checker.  Gets and 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

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 = getopt.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()