def schedule(self, interval):
        """
        The schedule method starts the underlying BugEx instance.
        Also it sets up a periodic task to check for completion.

        The interval specifies the time in seconds between executing the
        run() method.

        """
        # start process
        self._bug_ex_instance.start()

        # create timer task
        self._task = PeriodicTask(interval, self._run)

        # start task
        self._task.start()
        self._log.info('Scheduled to run every %s seconds.', str(interval))
    def schedule(self, interval):
        """
        The schedule method starts the underlying BugEx instance.
        Also it sets up a periodic task to check for completion.

        The interval specifies the time in seconds between executing the
        run() method.

        """
        # start process
        self._bug_ex_instance.start()

        # create timer task
        self._task = PeriodicTask(interval, self._run)

        # start task
        self._task.start()
        self._log.info('Scheduled to run every %s seconds.', str(interval))
class BugExMonitorJob(object):
    """
    The BugExMonitorJob monitors one BugExInstance.

    If the instance terminates in time, it stores the result to the database.
    """

    def __init__(self, bug_ex_instance, user_request):
        """
        A BugExMonitorJob needs a BugExInstance to monitor and a UserRequest
        for status update and notifications.

        """
        # members
        self._bug_ex_instance = bug_ex_instance
        self._user_request = user_request
        self._task = None # no task yet
        self._tries = 0
        self._creation_date = datetime.now()

        # job name
        self.name = 'job-' + user_request.token

        # logging
        self._log = logging.getLogger(self.name)

        if core_config.DEBUG:
            self._log.setLevel('DEBUG')
        else:
            self._log.setLevel('INFO')

        # done!
        self._log.info('Created BugExMonitorJob \'%s\'', self.name)


    def _run(self):
        """
        The run() method checks if
        - a stop criteria of the job has been met. This can either be the
          maxmimum execution time, or an unexpected BugEx exit code.
          In this case the job is being canceled.
        - BugEx finished successfully. In this case it tries to parse
          and persist the resulting XML file to the database.

        The run() method should be called periodically by a PeriodicTask.
        Calling the schedule() method will take care of scheduling and
        running the task.

        """
        self._log.debug('running the job.. (try %s)', str(self._tries))

        # increase try count
        self._tries += 1

        # check stop criteria

        # (1) life time
        time_diff = datetime.now() - self._creation_date    #timedelta
        if (time_diff.total_seconds() > core_config.MAX_LIFE_TIME):
            self.cancel(UserRequestStatus.FAILED, 'Maximum life time exceeded (%s seconds)',
                str(time_diff.total_seconds()))
            return

        # (2) check process status
        status = self._bug_ex_instance.status

        if status == -1:
            self._log.debug('BugEx is not ready yet..')
            return
        elif not status == 0:
            self.cancel(UserRequestStatus.FAILED, 
                ("BugEx terminated unsuccessfully (status code %s)! " +
                "Please check bugex.log in the request directory for more " +
                "details."), status)
            return

        # check result file
        if not self._bug_ex_instance.result_file.exists():
            self.cancel(UserRequestStatus.FAILED, 'Result file should exist, but does not.')
            return

        xml_content = self._bug_ex_instance.result_file.read()

        self._log.debug('Processing XML: \n%s',xml_content)

        # convert and store this to database
        try:
            # defered import to avoid circular dependency problems
            from bugex_webapp.models import BugExResult
            BugExResult.new(xml_content, self._user_request)
        except Exception as e:
            traceback.print_exc(file=sys.stdout)
            self.cancel(UserRequestStatus.FAILED, 'Could not store the BugExResult: %s',e)
            return

        # success
        self.cancel(UserRequestStatus.FINISHED, 'Success!')


    def schedule(self, interval):
        """
        The schedule method starts the underlying BugEx instance.
        Also it sets up a periodic task to check for completion.

        The interval specifies the time in seconds between executing the
        run() method.

        """
        # start process
        self._bug_ex_instance.start()

        # create timer task
        self._task = PeriodicTask(interval, self._run)

        # start task
        self._task.start()
        self._log.info('Scheduled to run every %s seconds.', str(interval))


    def cancel(self, status, message, *args):
        """
        This method cancels the underlying task and updates the status of the
        user request.
        """
        self._user_request.update_status(status)
        self._log.info(message, *args)
        self._task.cancel()
class BugExMonitorJob(object):
    """
    The BugExMonitorJob monitors one BugExInstance.

    If the instance terminates in time, it stores the result to the database.
    """
    def __init__(self, bug_ex_instance, user_request):
        """
        A BugExMonitorJob needs a BugExInstance to monitor and a UserRequest
        for status update and notifications.

        """
        # members
        self._bug_ex_instance = bug_ex_instance
        self._user_request = user_request
        self._task = None  # no task yet
        self._tries = 0
        self._creation_date = datetime.now()

        # job name
        self.name = 'job-' + user_request.token

        # logging
        self._log = logging.getLogger(self.name)

        if core_config.DEBUG:
            self._log.setLevel('DEBUG')
        else:
            self._log.setLevel('INFO')

        # done!
        self._log.info('Created BugExMonitorJob \'%s\'', self.name)

    def _run(self):
        """
        The run() method checks if
        - a stop criteria of the job has been met. This can either be the
          maxmimum execution time, or an unexpected BugEx exit code.
          In this case the job is being canceled.
        - BugEx finished successfully. In this case it tries to parse
          and persist the resulting XML file to the database.

        The run() method should be called periodically by a PeriodicTask.
        Calling the schedule() method will take care of scheduling and
        running the task.

        """
        self._log.debug('running the job.. (try %s)', str(self._tries))

        # increase try count
        self._tries += 1

        # check stop criteria

        # (1) life time
        time_diff = datetime.now() - self._creation_date  #timedelta
        if (time_diff.total_seconds() > core_config.MAX_LIFE_TIME):
            self.cancel(UserRequestStatus.FAILED,
                        'Maximum life time exceeded (%s seconds)',
                        str(time_diff.total_seconds()))
            return

        # (2) check process status
        status = self._bug_ex_instance.status

        if status == -1:
            self._log.debug('BugEx is not ready yet..')
            return
        elif not status == 0:
            self.cancel(
                UserRequestStatus.FAILED,
                ("BugEx terminated unsuccessfully (status code %s)! " +
                 "Please check bugex.log in the request directory for more " +
                 "details."), status)
            return

        # check result file
        if not self._bug_ex_instance.result_file.exists():
            self.cancel(UserRequestStatus.FAILED,
                        'Result file should exist, but does not.')
            return

        xml_content = self._bug_ex_instance.result_file.read()

        self._log.debug('Processing XML: \n%s', xml_content)

        # convert and store this to database
        try:
            # defered import to avoid circular dependency problems
            from bugex_webapp.models import BugExResult
            BugExResult.new(xml_content, self._user_request)
        except Exception as e:
            traceback.print_exc(file=sys.stdout)
            self.cancel(UserRequestStatus.FAILED,
                        'Could not store the BugExResult: %s', e)
            return

        # success
        self.cancel(UserRequestStatus.FINISHED, 'Success!')

    def schedule(self, interval):
        """
        The schedule method starts the underlying BugEx instance.
        Also it sets up a periodic task to check for completion.

        The interval specifies the time in seconds between executing the
        run() method.

        """
        # start process
        self._bug_ex_instance.start()

        # create timer task
        self._task = PeriodicTask(interval, self._run)

        # start task
        self._task.start()
        self._log.info('Scheduled to run every %s seconds.', str(interval))

    def cancel(self, status, message, *args):
        """
        This method cancels the underlying task and updates the status of the
        user request.
        """
        self._user_request.update_status(status)
        self._log.info(message, *args)
        self._task.cancel()