def test_remove_not_running(self): not_running = None for pid in range(1000, 20000): if not EnforceSingleTask.check_pid(pid): not_running = pid break self.assertIsNotNone(not_running) ## # Create an entry 'owned' by PID of 'not_running' ## task_id = "test_remove_not_running_task_id" entry = SingleTaskInfo(task_id=task_id, owner_pid=not_running) entry.save() self.assertEquals(1, SingleTaskInfo.objects(task_id=task_id).count()) retval = EnforceSingleTask.remove_not_running(task_id) self.assertIsNotNone(retval) # verify it has been removed self.assertEquals(0, SingleTaskInfo.objects(task_id=task_id).count()) ## # Create an entry 'owned' by running PID, verify it is not removed ## entry = SingleTaskInfo(task_id=task_id, owner_pid=os.getpid()) entry.save() self.assertEquals(1, SingleTaskInfo.objects(task_id=task_id).count()) retval = EnforceSingleTask.remove_not_running(task_id) # verify it has _not_ been removed self.assertIsNone(retval) self.assertEquals(1, SingleTaskInfo.objects(task_id=task_id).count())
def test_release_from_diff_pid(self): # Create an entry from a dummy pid task_id = "test_release_from_diff_pid_task_id" pid = os.getpid() + 1 entry = SingleTaskInfo(task_id=task_id, owner_pid=pid) entry.save() self.assertEquals(1, SingleTaskInfo.objects(task_id=task_id).count()) self.assertIsNone(EnforceSingleTask.release(task_id)) # Verify the remove did nothing because our 'pid' didn't match the entrie's pid self.assertEquals(1, SingleTaskInfo.objects(task_id=task_id).count())
def test_remove_by_owner(self): task_id = "test_remove_by_owner_task_id" pid = os.getpid() entry = SingleTaskInfo(task_id=task_id, owner_pid=pid) entry.save() self.assertEquals(1, SingleTaskInfo.objects(task_id=task_id).count()) retval = EnforceSingleTask.remove_by_owner(task_id, pid) self.assertIsNotNone(retval) self.assertEquals(0, SingleTaskInfo.objects(task_id=task_id).count()) ## # Simulate how another process that used there own pid wouldn't # delete the entry ## pid = os.getpid() + 1 entry = SingleTaskInfo(task_id=task_id, owner_pid=pid) entry.save() self.assertEquals(1, SingleTaskInfo.objects(task_id=task_id).count()) retval = EnforceSingleTask.remove_by_owner(task_id, os.getpid()) self.assertIsNone(retval) self.assertEquals(1, SingleTaskInfo.objects(task_id=task_id).count())
def remove_not_running(cls, task_id): existing_task = SingleTaskInfo.objects(task_id=task_id).first() if existing_task: if not cls.check_pid(existing_task.owner_pid): # Rationale for why this is safe from race conditions. # 'remove_by_owner' will only delete the task if the entry is still 'owned' by the dead PID # if another process cleans this up then the entry will be owned by a different PID and # the findAndModify will not find the entry and results in no change. ret_val = cls.remove_by_owner(task_id, existing_task.owner_pid) if not ret_val: _LOG.warning("Unsuccessful in removing a task info entry on '%s' from pid '%s' created on '%s'." % \ (task_id, existing_task.owner_pid, existing_task.created)) return ret_val
def test_remove_expired(self): # Create an 'expired' entry threshold=5 task_id = "test_remove_expored_task_id" created = datetime.now(tzutc()) - timedelta(seconds=threshold+1) entry = SingleTaskInfo(task_id=task_id, owner_pid=os.getpid(), created=created) entry.save() self.assertEquals(1, SingleTaskInfo.objects(task_id=task_id).count()) retval = EnforceSingleTask.remove_expired(task_id, seconds_expire=threshold) # Verify it is removed self.assertIsNotNone(retval) self.assertEquals(0, SingleTaskInfo.objects(task_id=task_id).count()) ## # Create an entry that is not expired ## created = datetime.now(tzutc()) entry = SingleTaskInfo(task_id=task_id, owner_pid=os.getpid(), created=created) entry.save() self.assertEquals(1, SingleTaskInfo.objects(task_id=task_id).count()) retval = EnforceSingleTask.remove_expired(task_id, seconds_expire=threshold) # Verify it is _not_ removed self.assertIsNone(retval) self.assertEquals(1, SingleTaskInfo.objects(task_id=task_id).count())