Commit 5ea7432b authored by Daniel Armbruster's avatar Daniel Armbruster Committed by thomas.forbriger
Browse files

Working directory locking implemented. Not tested yet.

This is a legacy commit from before 2015-05-18.
It may be incomplete as well as inconsistent.
See COPYING.legacy and README.history for details.


SVN Path:     http://gpitrsvn.gpi.uni-karlsruhe.de/repos/TFSoftware/trunk
SVN Revision: 4388
SVN UUID:     67feda4a-a26e-11df-9d6e-31afc202ad0c
parent 600f5be1
......@@ -71,8 +71,7 @@ class Usage(Error):
"\n"+__subversion__+"\nAuthor: "+__author__+ """
Usage: csbackchk [-v|--verbose] [-e REGEX [-e REGEX [...]]]
[-R|--notrecursive] [-d|--debug] [-f|--followlinks]
[-t|--tolerant] [-l|--logging] [-a|--announce] [SOURCEPATH]
PATH
[-t|--tolerant] [-l|--logging] [-L|--lock] [SOURCEPATH] PATH
or: csbackchk -h|--help\n"""
sys.stderr.write("csbackchk [line "+self.line+"]: "+self.msg+"\n")
sys.stderr.write(usage_text)
......@@ -86,8 +85,7 @@ def help():
__subversion__+"\nAuthor: "+__author__+"""
Usage: csbackchk [-v|--verbose] [-e REGEX [-e REGEX [...]]]
[-R|--notrecursive] [-d|--debug] [-f|--followlinks]
[-t|--tolerant] [-l|--logging] [-a|--announce] [SOURCEPATH]
PATH
[-t|--tolerant] [-l|--logging] [-L|--lock] [SOURCEPATH] PATH
or: csbackchk -h|--help
-------------------------------------------------------------------------------
-v|--verbose Be verbose.
......@@ -105,10 +103,10 @@ def help():
e.g. as a ring buffer.
-l|--logging Switch on logging to files. Logfiles will be located in
~/.csback/log/.
-a|--announce Announce csbackchk to the csback pid lockfilehandler. This
flag is neccessary if several csback processes were run
simultaneously and the '-l|--logging' option is enabled.
Otherwise problems with the logging mechanism could
-L|--lock Lock the directories working at. This flag is useful in
case csbackchk was run simultaneously with other csback
processes working in the same directory. Setting this
option avoids checksumfile access problems which might
occur.
SOURCEPATH Optional sourcepath for comparison with files backed up in
PATH. PATH and its subdirectories (if option '-R' had not
......@@ -138,18 +136,18 @@ def main(argv=None):
argv = sys.argv
try:
try:
opts, args = getopt.getopt(argv[1:], "vhe:Rdftla", ["help", "verbose", \
opts, args = getopt.getopt(argv[1:], "vhe:RdftlL", ["help", "verbose", \
"notrecursive", "debug", "followlinks", "tolerant", "logging", \
"announce"])
"lock"])
except getopt.GetoptError as err:
raise Usage(145,err.msg)
raise Usage(143,err.msg)
verbose = False
debugMode = False
notRecursive = False
followLinks = False
beTolerant = False
regexes = []
pidAnnounce = False
pidLock = False
# collect arguments
for opt, arg in opts:
if opt in ("-v", "--verbose"):
......@@ -171,10 +169,10 @@ def main(argv=None):
beTolerant = True
elif opt in ("-l", "--logging"):
logger.configure()
elif opt in ("-a", "--announce"):
pidAnnounce = True
elif opt in ("-L", "--lock"):
pidLock = True
else:
raise Usage(177,"Unhandled option chosen.")
raise Usage(175,"Unhandled option chosen.")
if verbose or debugMode:
logger.addHandler(console)
......@@ -191,12 +189,7 @@ def main(argv=None):
inputpath = str(args[1]).rstrip(os.sep)+os.sep
inputDirs = [inputpath]
else:
raise Usage(194,"Invalid argument(s).")
# announce to pidlock
if pidAnnounce:
pidhandler = pidlock.PidHandler()
pidhandler.announce(os.getpid())
raise Usage(192,"Invalid argument(s).")
# major part
logger.getLogger().debug("Collecting subdirectories ...")
......@@ -209,22 +202,29 @@ def main(argv=None):
csfile.getSubDirectories(inputpath, regexes, followLinks))
if len(sourceDirs) != len(inputDirs):
raise Error(212, \
raise Error(205, \
"Directory structure of inputpath and sourcepath different.")
if not csfile.hasCsFile(inputpath):
raise Error(216,"PATH does not contain a checksumfile.")
paths = list(zip(inputDirs, sourceDirs))
logger.getLogger().info("Start checking checksums ...")
for path in paths:
if not csfile.hasCsFile(path[0]):
raise Error(213,"PATH does not contain a checksumfile.")
lock = pidlock.PidLocker(path[0])
checksumfile = csfile.CsFile(path[0], path[1])
checksumfile.read()
checksumfile.check(regexes, beTolerant)
# remove from pidlock
if pidAnnounce:
pidhandler.cancel(os.getpid())
if lock.lockValid():
raise pidlock.PidLockError(-1, \
"Directory '{0}' locked.".format(path[0]))
elif pidLock:
lock.announce(os.getpid())
checksumfile.read()
checksumfile.check(regexes, beTolerant)
lock.cancel(os.getpid())
else:
checksumfile.read()
checksumfile.check(regexes, beTolerant)
except Usage as err:
err.display()
return 2
......
......@@ -71,7 +71,7 @@ class Usage(Error):
Usage: csbackgen [-v|--verbose] [-e REGEX [-e REGEX [...]]]
[-R|--notrecursive] [-d|--debug] [-f|--followlinks]
[-t|--target DIR] [-l|--logging] [--hash ARG]
[-a|--announce] PATH
[-L|--lock] PATH
or: csbackgen -h|--help\n"""
sys.stderr.write("csbackgen: " + self.msg + "\n")
sys.stderr.write(usage_text)
......@@ -86,7 +86,7 @@ def help():
Usage: csbackgen [-v|--verbose] [-e REGEX [-e REGEX [...]]]
[-R|--notrecursive] [-d|--debug] [-f|--followlinks]
[-t|--target ROOTDIR] [-l|--logging] [--hash ARG]
[-a|--announce] PATH
[-L|--lock] PATH
or: csbackgen -h|--help
-------------------------------------------------------------------------------
-v|--verbose Be verbose.
......@@ -106,11 +106,11 @@ def help():
~/.csback/log/.
--hash ARG Set the hash function algorithm. Valid values are:
sha224, sha256, sha384, sha512. (default: sha256)
-a|--announce Announce csbackgen to the csback pid lockfilehandler.
This flag is neccessary if several csback processes were
run simultaneously and the '-l|--logging' option is
enabled. Otherwise problems with the logging mechanism
could occur.
-L|--lock Lock the directories working at. This flag is useful in
case csbackgen was run simultaneously with other csback
processes working in the same directory. Setting this
option avoids checksumfile access problems which might
occur.
PATH Path to generate checksumfile(s) for including its
subdirectories if option '-R' is not set.
-------------------------------------------------------------------------------
......@@ -140,9 +140,9 @@ def main(argv=None):
argv = sys.argv
try:
try:
opts, args = getopt.getopt(argv[1:], "vhe:Rdft:la", ["help", "verbose", \
opts, args = getopt.getopt(argv[1:], "vhe:Rdft:lL", ["help", "verbose", \
"notrecursive", "debug", "followlinks", "target=", "logging", \
"hash=", "announce"])
"hash=", "lock"])
except getopt.GetoptError as err:
raise Usage(err.msg)
verbose = False
......@@ -153,7 +153,7 @@ def main(argv=None):
targetSet = False
enableLogging = False
hashfunc = 'sha256'
pidAnnounce = False
pidLock = False
for opt, arg in opts:
if opt in ("-v", "--verbose"):
verbose = True
......@@ -179,8 +179,8 @@ def main(argv=None):
hashfunc = arg
else:
raise Usage("Invalid argument (hash).")
elif opt in ("-a", "--announce"):
pidAnnounce = True
elif opt in ("-L", "--lock"):
pidLock = True
else:
raise Usage("Unhandled option chosen.")
......@@ -195,9 +195,6 @@ def main(argv=None):
if not os.path.isdir(srcpath):
raise Usage("PATH not a valid directory.")
# announce to pidlock
if pidAnnounce:
pidhandler = pidlock.PidHandler()
pidhandler.announce(os.getpid())
# major part
......@@ -225,17 +222,23 @@ def main(argv=None):
logger.getLogger().debug( \
"Updating checksumfile in '{0}' with files from '{1}' ...".format( \
path[0], path[1]))
csfile.CsFile(path[0], path[1], hashfunc=hashfunc).update(regexes)
lock = pidlock.PidLocker(path[0])
checksumfile = csfile.CsFile(path[0], path[1], hashfunc=hashfunc)
if lock.lockValid():
raise pidlock.PidLockError(-1, \
"Directory '{0}' locked.".format(path[0]))
elif pidLock:
lock.announce(os.getpid())
checksumfile.update(regexes)
lock.cancel(os.getpid())
else:
checksumfile.update(regexes)
# remove from pidlock
if pidAnnounce:
pidhandler.cancel(os.getpid())
except Usage as err:
err.display()
return 2
except pidlock.PidLockError as err:
logger.getLogger().error("{0}".format(err.msg))
logger.getLogger().critical("{0}".format(err.msg))
err.display()
return 2
except csfile.CsFileError as err:
......
......@@ -37,7 +37,7 @@
# 04/01/2012 V0.1.3 implemented a debug mode using the python logging module
#
# =============================================================================
""" CsFile module to handle checksum files. """
""" CsFile module to handle checksumfiles. """
import os
import re
......
......@@ -37,12 +37,8 @@ Module to handle process IDs (pid) by using a lockfile mechanism. The module
comes along with a PidHandler class. Additionally there is a Exception class
PidLockError which might be caught while announcing a pid.
The path of the lockfile should be configured using the global variables.
Default values are:
---
path = os.path.expanduser("~/.csback")
lockfilename = ".lock"
---
The name of the lockfile could be configured using the global variable
lockfilename.
"""
import os
......@@ -57,7 +53,7 @@ __copyright__ = "Copyright (c) 2012 by Daniel Armbruster"
# -----------------------------------------------------------------------------
# variables
path = os.path.expanduser("~/.csback")
lockfilename = ".lock"
# -----------------------------------------------------------------------------
......@@ -71,10 +67,11 @@ class PidLockError(Exception):
def display(self):
sys.stderr.write("pidlock (ERROR): " + str(self.msg) + "\n")
sys.stderr.write("triggered in line: " + str(self.line) + "\n")
if -1 =! line:
sys.stderr.write("triggered in line: " + str(self.line) + "\n")
# -----------------------------------------------------------------------------
class PidHandler:
class PidLocker:
"""
Implements a handler for a pid. This handler uses a pidlockfile mechanism to
keep a log of the announced pids. Because of using a lockfile the handler
......@@ -83,32 +80,25 @@ class PidHandler:
Note that this handler does its work only on *nix platforms properly. Use
inheritance to overload the corresponding functions.
"""
def __init__(self):
self.path = os.path.join(path,lockfilename)
self.notCanceled = True
def __init__(self, directory):
self.path = os.path.join(directory,lockfilename)
self.directory = directory
def announce(self, pid):
"""
Announce a process with pid to the handler.
"""
# create directories if not available
if not os.access(path, os.F_OK):
try:
os.makedirs(path, mode='0755')
except OSError:
pass
# remove file if pid not valid anymore
if self.__access() and not self.__pidValid():
if not self.lockValid():
os.remove(self.path)
# wait until pid is not valid anymore
while (self.__pidValid()):
pass
else:
raise PidLockError(93, "Directory '{0}'locked.".format(self.directory))
# create a new pidlockfile
try:
pidfile = open(self.path, 'w')
pidfile.write("{0}".format(pid))
except IOError as err:
raise PidLockError(111, "[Errno "+str(err.errno)+"] "+err.strerror+": " \
raise PidLockError(100, "[Errno "+str(err.errno)+"] "+err.strerror+": " \
+err.filename)
else:
pidfile.close()
......@@ -122,7 +112,7 @@ class PidHandler:
if self.__getlockpid() == str(pid):
os.remove(self.path)
def __pidValid(self):
def lockValid(self):
"""
Check if the process with the pid in the pid lockfile is still active.
"""
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment