def wrapper(*args, **kwargs): # Locking in exclusive, blocking mode because there could be several # children running at the same time. Waiting up to 10 seconds. if _PrepareQueueLock() is not None: raise errors.JobQueueError("Job queue failed initialization," " cannot update jobs") queue_lock.Exclusive(blocking=True, timeout=QUEUE_LOCK_TIMEOUT) try: return fn(*args, **kwargs) finally: queue_lock.Unlock()
def _ReadNumericFile(file_name): """Reads a file containing a number. @rtype: None or int @return: None if file is not found, otherwise number """ try: contents = utils.ReadFile(file_name) except EnvironmentError as err: if err.errno in (errno.ENOENT, ): return None raise try: return int(contents) except (ValueError, TypeError) as err: # Couldn't convert to int raise errors.JobQueueError("Content of file '%s' is not numeric: %s" % (file_name, err))
def InitAndVerifyQueue(must_lock): """Open and lock job queue. If necessary, the queue is automatically initialized. @type must_lock: bool @param must_lock: Whether an exclusive lock must be held. @rtype: utils.FileLock @return: Lock object for the queue. This can be used to change the locking mode. """ getents = runtime.GetEnts() # Lock queue queue_lock = utils.FileLock.Open(pathutils.JOB_QUEUE_LOCK_FILE) try: # The queue needs to be locked in exclusive mode to write to the serial and # version files. if must_lock: queue_lock.Exclusive(blocking=True) holding_lock = True else: try: queue_lock.Exclusive(blocking=False) holding_lock = True except errors.LockError: # Ignore errors and assume the process keeping the lock checked # everything. holding_lock = False if holding_lock: # Verify version version = ReadVersion() if version is None: # Write new version file utils.WriteFile(pathutils.JOB_QUEUE_VERSION_FILE, uid=getents.masterd_uid, gid=getents.daemons_gid, mode=constants.JOB_QUEUE_FILES_PERMS, data="%s\n" % constants.JOB_QUEUE_VERSION) # Read again version = ReadVersion() if version != constants.JOB_QUEUE_VERSION: raise errors.JobQueueError( "Found job queue version %s, expected %s", version, constants.JOB_QUEUE_VERSION) serial = ReadSerial() if serial is None: # Write new serial file utils.WriteFile(pathutils.JOB_QUEUE_SERIAL_FILE, uid=getents.masterd_uid, gid=getents.daemons_gid, mode=constants.JOB_QUEUE_FILES_PERMS, data="%s\n" % 0) # Read again serial = ReadSerial() if serial is None: # There must be a serious problem raise errors.JobQueueError("Can't read/parse the job queue" " serial file") if not must_lock: # There's no need for more error handling. Closing the lock # file below in case of an error will unlock it anyway. queue_lock.Unlock() except: queue_lock.Close() raise return queue_lock
@rtype: None or int @return: None if file is not found, otherwise number """ try: contents = utils.ReadFile(file_name) except EnvironmentError, err: if err.errno in (errno.ENOENT, ): return None raise try: return int(contents) except (ValueError, TypeError), err: # Couldn't convert to int raise errors.JobQueueError("Content of file '%s' is not numeric: %s" % (file_name, err)) def ReadSerial(): """Read the serial file. The queue should be locked while this function is called. """ return _ReadNumericFile(pathutils.JOB_QUEUE_SERIAL_FILE) def ReadVersion(): """Read the queue version. The queue should be locked while this function is called.