[Demi-commits] r68 - / lib
John Morrissey
jwm-guest at costa.debian.org
Mon Jan 30 18:05:18 UTC 2006
Author: jwm-guest
Date: 2006-01-30 18:05:18 +0000 (Mon, 30 Jan 2006)
New Revision: 68
Modified:
TODO
lib/agent.py
Log:
- make demi.agent._writeStatus() atomic; we'll write to
commandName-results-temp and rename it when finished
- improve agent lock handling by using O_EXCL when performing
locking
Modified: TODO
===================================================================
--- TODO 2006-01-27 20:27:51 UTC (rev 67)
+++ TODO 2006-01-30 18:05:18 UTC (rev 68)
@@ -1,4 +1,3 @@
-demi.agent _writeStatus() should be atomic; write to a temp file and rename()?
http://www.dscpl.com.au/projects/vampire/
autodetect demi web root
req.uri, req.filename, and/or req.path_info seem useful
Modified: lib/agent.py
===================================================================
--- lib/agent.py 2006-01-27 20:27:51 UTC (rev 67)
+++ lib/agent.py 2006-01-30 18:05:18 UTC (rev 68)
@@ -29,7 +29,7 @@
def processCommands():
"""Process commands queued on the current machine."""
- if not _lockCommandDir():
+ if not _lockAgentDir():
return
files = os.listdir(AGENT_ROOT + "/commands/")
@@ -38,7 +38,13 @@
try:
for filename in files:
- # Skip this command if it's already been executed.
+ # Skip temporary output files.
+ # FIXME: should we clean up after ourselves by removing this
+ # file? Only remove it after an interval (n days/weeks)?
+ if filename[-5:] == "-temp":
+ continue
+
+ # Skip commands that have already been executed.
if os.path.exists(AGENT_ROOT + "/commands/" + filename + "-results"):
continue
@@ -70,34 +76,37 @@
command.run()
_writeStatus(command, AGENT_ROOT + "/commands/" + filename + "-results")
finally:
- _unlockCommandDir()
+ _unlockAgentDir()
def _writeStatus(command, filename):
"""Write a command's status and output."""
- handle = open(filename, "w")
- handle.write(str(command.status) + " " + str(command.returnCode) + "\n")
- handle.write(join(command.output, ""))
- handle.close()
+ try:
+ # We're okay without O_EXCL here, since the agent directory is locked.
+ handle = open(filename + "-temp", "w")
+ handle.write(str(command.status) + " " + str(command.returnCode) + "\n")
+ handle.write(join(command.output, ""))
+ handle.close()
+ os.rename(filename + "-temp", filename)
+ except:
+ # FIXME: should we syslog the data, as an attempt to avoid losing
+ # it? Or should we just leave this, in case it's needed for
+ # troubleshooting?
+ os.unlink(filename + "-temp")
-def _lockCommandDir():
+def _lockAgentDir():
"""Lock the command directory.
Returns a boolean indicating whether the directory was successfully
locked. Will time out and override the lock file after LOCK_TIMEOUT
seconds.
-
- FIXME: should we use POSIX file locking or O_EXCL to further avoid a
- race condition? Currently, the cron job only runs once a minute, so only
- one process should be checking/manipulating the lock at once, but there
- may be other uses in the future.
"""
if not os.access(LOCKFILE, os.F_OK):
# Lock doesn't exist, create it.
- lockFile = file(LOCKFILE, "w+")
- lockFile.write(str(os.getpid()) + "\n")
- lockFile.close()
+ lockFd = os.open(LOCKFILE, os.O_CREAT | os.O_EXCL | os.O_WRONLY)
+ os.write(lockFd, str(os.getpid()) + "\n")
+ os.close(lockFd)
return True
info = os.stat(LOCKFILE)
@@ -106,11 +115,11 @@
return False
# FIXME: log that we're breaking this lock.
- lockFile = file(LOCKFILE, "w+")
- lockFile.write(str(os.getpid()) + "\n")
- lockFile.close()
+ lockFd = os.open(LOCKFILE, os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
+ os.write(lockFd, str(os.getpid()) + "\n")
+ os.close(lockFd)
return True
-def _unlockCommandDir():
+def _unlockAgentDir():
"""Unlock the command directory."""
os.remove(LOCKFILE)
More information about the Demi-commits
mailing list