Esempio n. 1
0
 def __init__(self, assistant, doctor, control_period=None):
     labour.BaseLabour.__init__(self, IAssistant(assistant))
     self._doctor = IDoctor(doctor)
     self._patients = {} # {AGENT_ID: Patient}
     self._control_period = control_period or DEFAULT_CONTROL_PERIOD
     self._task = None
     self._last_check_epoch = None
     self._skip_checks = None
Esempio n. 2
0
class IntensiveCare(labour.BaseLabour):

    classProvides(IIntensiveCareFactory)
    implements(IIntensiveCare)

    def __init__(self, assistant, doctor, control_period=None):
        labour.BaseLabour.__init__(self, IAssistant(assistant))
        self._doctor = IDoctor(doctor)
        self._patients = {} # {AGENT_ID: Patient}
        self._control_period = control_period or DEFAULT_CONTROL_PERIOD
        self._task = None
        self._last_check_epoch = None
        self._skip_checks = None

    ### Public Methods ###

    @replay.side_effect
    def beat(self, agent_id):
        if agent_id in self._patients:
            self._patients[agent_id].beat(self.patron.get_time())

    ### IHeartMonitor Methods ###

    @replay.side_effect
    def startup(self):
        self.resume()

    @replay.side_effect
    def cleanup(self):
        self.pause()

    @replay.side_effect
    def pause(self):
        if self._task:
            self._task.cancel()
            self._task = None

    @replay.side_effect
    def resume(self):
        if self._task is None:
            agent = self.patron
            beat_time = agent.get_time()
            for patient in self._patients.itervalues():
                patient.reset(beat_time)
            agent.register_interest(HeartBeatCollector, self)
            self._task = agent.initiate_protocol(CheckPatientTask, self,
                                                 self._control_period)

    @replay.side_effect
    def has_patient(self, identifier):
        if IRecipient.providedBy(identifier):
            identifier = identifier.key
        return identifier in self._patients

    @replay.side_effect
    def add_patient(self, recipient, location,
                    period=None, dying_skips=None,
                    death_skips=None, patient_type=None):
        agent_id = recipient.key
        assert agent_id not in self._patients, \
               "Patient already added to intensive care"
        self.debug("Start agent's %s heart monitoring", agent_id)

        patient = Patient(recipient, location, self.patron.get_time(),
                          period=period, dying_skips=dying_skips,
                          death_skips=death_skips, patient_type=patient_type)
        self._patients[agent_id] = patient
        self._doctor.on_patient_added(patient)

    @replay.side_effect
    def remove_patient(self, identifier):
        if IRecipient.providedBy(identifier):
            identifier = identifier.key
        if identifier in self._patients:
            self.debug("Stop agent's %s heart monitoring", identifier)
            patient = self._patients[identifier]
            self._doctor.on_patient_removed(patient)
            del self._patients[identifier]

    def check_patients(self):
        ref_time = self.patron.get_time()

        # Detect wakeup from the suspend
        if (self._last_check_epoch is not None and
            ref_time - self._last_check_epoch > 2 * self._control_period):
            # when this happens skip checking patient state for 3 runs
            self.info("Detected monitor wakeup, I will skip next 3 checks")
            self._skip_checks = 3

        self._last_check_epoch = ref_time

        if self._skip_checks:
            self._skip_checks -= 1
            self.debug("Skipping check of intensive care, %d left to skip",
                       self._skip_checks)
            return

        for patient in self._patients.itervalues():
            recipient = patient.recipient
            agent_id = recipient.key
            before, after = patient.check(ref_time)

            if before == after:
                continue

            if before == PatientState.alive:
                if after == PatientState.dying:
                    self.log("Agent %s heart not responding", agent_id)
                    self._doctor.on_patient_dying(patient)
                    continue

            if after == PatientState.dead:
                self.log("Agent %s heart failed", agent_id)
                self._doctor.on_patient_died(patient)
                continue

            if after == PatientState.alive:
                self.log("Agent %s heart restarted", agent_id)
                self._doctor.on_patient_resurrected(patient)
                continue

    def get_patient(self, identifier):
        if IRecipient.providedBy(identifier):
            identifier = identifier.key
        return self._patients.get(identifier)

    def iter_patients(self):
        return self._patients.itervalues()