Exemplo n.º 1
0
void machine_t::process_transition_queue()
{
  if(transition_in_progress())
  {
    log_debug("process_transition_queue() is already in progress, returning") ;
    return ; // never do it recursively
  }
  // log_debug("begin processing, states: %s tqueue: %s" , s_states().c_str(), s_transition_queue().c_str()) ;
  transition_start_time = ticker_t(now()) ;
  bool queue_changed = false ;
  for(; not transition_queue.empty(); queue_changed = true, transition_queue.pop_front())
  {
#define state_name(p) (p?p->name():"null")
    event_t *e = transition_queue.front().first ;
    abstract_state_t *new_state = transition_queue.front().second ;
    if (not is_event_registered(e))
    {
      log_error("requested to move destroyed event %p to state '%s'", e, state_name(new_state)) ;
      continue ;
    }
    abstract_state_t *old_state = e->get_state() ;
    log_notice("State transition %d:'%s'->'%s'", e->cookie.value(), state_name(old_state), state_name(new_state)) ;
    if (new_state==old_state)
      log_critical("Event %d: new_state=old_state='%s'", e->cookie.value(), old_state->name()) ;
#undef state_name
    if(old_state)
      old_state->leave(e) ;
    e->set_state(new_state) ;
    if(new_state)
    {
      new_state->enter(e) ;
      e->sort_and_run_actions(new_state->get_action_mask()) ;
    }
    else
    {
      log_notice("Destroying the event %u (event object %p)", e->cookie.value(), e) ;
      unregister_event(e) ;
      delete e ;
    }
  }
  // log_debug("processing done,  states: %s tqueue: %s" , s_states().c_str(), s_transition_queue().c_str()) ;
  transition_start_time = ticker_t(0) ;
  transition_time_adjustment.set(0) ;
  if(queue_changed)
    emit queue_to_be_saved() ;
  if(context_changed)
    send_queue_context() ;
  send_bootup_signal() ;
}
Exemplo n.º 2
0
void state_recurred_t::enter(event_t *e)
{
  abstract_state_t::enter(e) ;
  switch_timezone x(e->tz) ;
  broken_down_t now ;
  int now_wday ;
  now.from_time_t(machine->transition_started(), &now_wday) ;
  ticker_t best_ticker = ticker_t(0) ;
  for(unsigned i=0; i<e->recrs.size(); ++i)
  {
    ticker_t res = apply_pattern(now, now_wday, &e->recrs[i]) ;
    if(res.is_valid() && (!best_ticker.is_valid() || res<best_ticker))
      best_ticker = res ;
  }
  abstract_state_t *next_state = machine->state_qentry ;
  if(best_ticker.is_valid())
  {
    e->flags &= ~ EventFlags::Empty_Recurring ;
    e->trigger = best_ticker ;
  }
  else
  {
    e->flags |= EventFlags::Empty_Recurring ;
    e->t.year = now.year+1, e->t.month = 12, e->t.day = 31, e->t.hour = 0, e->t.minute = 42 ;
    if(e->t.is_valid()) // it valid from until 2036
      next_state = machine->state_scheduler ; // back to scheduler
    else
      next_state = machine->state_aborted ; // TODO: FAILED is better here
  }
  machine->request_state(e, next_state) ;
}
Exemplo n.º 3
0
ticker_t state_queued_t::next_bootup()
{
  if (not bootup.empty())
    return bootup.begin()->first ;
  else
    return ticker_t() ;
}
Exemplo n.º 4
0
void machine_t::load_events(const iodata::array *events_data, bool trusted_source, bool use_cookies)
{
  for(unsigned i=0; i < events_data->size(); ++i)
  {
    const iodata::record *ee = events_data->get(i)->rec() ;
    unsigned cookie = use_cookies ? ee->get("cookie")->value() : next_cookie++ ;
    event_t *e = new event_t ;
    e->cookie = cookie_t(cookie) ;

    e->ticker = ticker_t(ee->get("ticker")->value()) ;
    e->t.load(ee->get("t")->rec()) ;

    e->tz = ee->get("tz")->str() ;

    e->attr.load(ee->get("attr")->arr()) ;
    e->flags = ee->get("flags")->decode(event_t::codec) ;
    iodata::load(e->recrs, ee->get("recrs")->arr()) ;
    iodata::load_int_array(e->snooze, ee->get("snooze")->arr()) ;

    if (e->recrs.size() > 0)
      e->trigger_if_missed = true;

    const iodata::array *a = ee->get("b_attr")->arr() ;
    unsigned nb = a->size() ;
    e->b_attr.resize(nb) ;
    for(unsigned i=0; i<nb; ++i)
      e->b_attr[i].load(a->get(i)->rec()->get("attr")->arr()) ;

    e->last_triggered = ticker_t(ee->get("dialog_time")->value()) ;
    e->tsz_max = ee->get("tsz_max")->value() ;
    e->tsz_counter = ee->get("tsz_counter")->value() ;
    if(trusted_source)
    {
      iodata::load(e->actions, ee->get("actions")->arr()) ;
      if (e->actions.size()>0)
        e->client_creds = new credentials_t(ee->get("client_creds")->rec()) ;
      const iodata::array *cred_modifier = ee->get("cred_modifier")->arr() ;
      if (cred_modifier->size()>0)
        e->cred_modifier = new cred_modifier_t(cred_modifier) ;
    }

    if(e->flags & EventFlags::Empty_Recurring)
      e->invalidate_t() ;

    register_event(e) ;
  }
}
Exemplo n.º 5
0
static ticker_t recur_regular_day(const broken_down_t &day, const recurrence_pattern_t *p, time_t threshold)
{
  log_debug("day=%s, p->mins=0x%llx, threshold=%lld", day.str().c_str(), p->mins, (long long)threshold) ;
  broken_down_t d = day ;
  for (bool inc_flag = false; d.find_a_good_minute_with_increment(p, inc_flag); inc_flag = true)
  {
    struct tm tm ;
    d.to_struct_tm(&tm) ;
    time_t t = mktime(&tm) ;
    if (t<0 or t<=threshold or not d.same_struct_tm(&tm))
      continue ;
    log_debug("returning t=%lld", (long long)t) ;
    return ticker_t(t) ;
  }
  log_debug("returning t=null") ;
  return ticker_t() ;
}
Exemplo n.º 6
0
ticker_t state_recurred_t::apply_pattern(broken_down_t &t, int wday, const recurrence_pattern_t *p)
{
  unsigned nxt_year = t.year + 1 ;
  if(broken_down_t::YEARX <= nxt_year)
    -- nxt_year ;
  broken_down_t started = t ;
  for(bool today_flag=true;  t.find_a_good_day(p, wday, today_flag, nxt_year) ; today_flag=false)
  {
    log_debug() ;
    broken_down_t td = t ;
    if(!today_flag)
      td.hour = td.minute = 0 ;
    while(td.find_a_good_minute(p))
    {
      struct tm tm ;
      td.to_struct_tm(&tm) ;
      log_debug("td=(%s)", td.str().c_str()) ;
      log_debug("tm=%s", tm_str(&tm).c_str()) ;
      time_t time = mktime(&tm) ;
      log_debug("time=%d", (int)time) ;
      if(time==time_t(-1))
        continue ;
      log_debug() ;
      if(time <= machine->transition_started().value())
      {
        log_debug() ;
        td.increment_min(1) ;
        log_debug() ;
        continue ;
      }
      log_debug() ;
      if(!td.same_struct_tm(&tm))
      {
        td.increment_min(1) ;
        continue ;
      }
      log_debug() ;
      t = td ;
      return ticker_t(time) ;
    }
  }
  log_debug() ;
  return ticker_t(0) ;
}
Exemplo n.º 7
0
static ticker_t recur_irregular_day(const broken_down_t &day, const recurrence_pattern_t *p, time_t threshold)
{
  broken_down_t d = day ;
  d.hour = d.minute = 0 ;
  set<time_t> found ;
  for (bool inc_flag = false; d.find_a_good_minute_with_increment(p, inc_flag); inc_flag = true)
  {
    bool time_is_valid = false ;
    for (int dst=0; dst<=1; ++dst)
    {
      time_t t = d.mktime_strict(dst) ;
      if (t>0)
        time_is_valid = true ;
      if (t>threshold)
        found.insert(t) ;
    }
    if (time_is_valid)
      continue ;
    if (not (p->flags & RecurrenceFlags::Fill_Gaps))
      continue ;
    // now flicking the gap (usually caused by entering DST)
    log_notice("starting search to fill the gap: %s", d.str().c_str()) ;
    for(unsigned day = d.day; day==d.day; d.increment_min(1))
    {
      time_t t = d.mktime_strict() ; // dst is set to -1 here
      log_info("trying '%s' (t=%lld)", d.str().c_str(), (long long)t) ;
      if (t<0)
        continue ;
      log_notice("found a valid minute while flicking the gap: %s", d.str().c_str()) ;
      if (t>threshold)
        found.insert(t) ;
      break ;
    }
  }
  set<time_t>::const_iterator it = found.begin() ;
  if (it==found.end())
    return ticker_t() ;
  else
    return ticker_t(*it) ;
}
Exemplo n.º 8
0
ticker_t state_recurred_t::apply_pattern(const broken_down_t &start, int wday, const recurrence_pattern_t *p)
{
  broken_down_t day = start ;
  unsigned nxt_year = day.year + 1 ;
  if(broken_down_t::YEARX <= nxt_year)
    -- nxt_year ;
  time_t threshold = machine->transition_started().value() ;
  for(bool today_flag=true;  day.find_a_good_day(p, wday, today_flag, nxt_year) ; today_flag=false)
  {
    if (not today_flag)
      day.hour = day.minute = 0 ;
    ticker_t t = (day.is_a_regular_day() ? recur_regular_day : recur_irregular_day) (day, p, threshold) ;
    if (t.is_valid())
      return t ;
  }
  return ticker_t() ;
}
Exemplo n.º 9
0
void state_triggered_t::enter(event_t *e)
{
  abstract_state_t::enter(e) ;

  // Frist get rid of one time trigger info:
  e->ticker = ticker_t() ;
  e->invalidate_t() ;

  if(e->flags & EventFlags::Single_Shot)
    e->recrs.resize(0) ; // no recurrence anymore

  if (e->flags & EventFlags::Reminder)
    machine->state_dlg_wait->go_to(e) ;
  else
    machine->state_served->go_to(e) ;

  machine->process_transition_queue() ;
}
Exemplo n.º 10
0
void state_scheduler_t::enter(event_t *e)
{
  abstract_state_t::enter(e) ;
  log_debug() ;
  abstract_state_t *next_state = machine->state_qentry ;
  if(e->has_ticker())
    e->trigger = ticker_t(e->ticker) ;
  else if(e->has_time())
  {
    struct tm T;
    T.tm_sec = 0 ;
    T.tm_min = e->t.minute ;
    T.tm_hour = e->t.hour ;
    T.tm_mday = e->t.day ;
    T.tm_mon = e->t.month - 1 ;
    T.tm_year = e->t.year - 1900 ;
    T.tm_isdst = -1 ;
    log_debug("%d-%d-%d %d:%d", e->t.year, e->t.month, e->t.day, e->t.hour, e->t.minute) ;
    if (not e->has_timezone())
      e->trigger = mktime_local(&T) ;
    else if(Maemo::Timed::is_tz_name(e->tz))
      e->trigger = mktime_oversea(&T, e->tz) ;
    else
      log_error("can't schedule an event for an unknown time zone '%s'", e->tz.c_str()) ;

    log_debug("now=%ld e->trigger=%ld diff=%ld", time(NULL), e->trigger.value(), e->trigger.value()-time(NULL)) ;
    log_debug("e->has_timezone()=%d", e->has_timezone()) ;
    if(!e->trigger.is_valid())
    {
      log_error("Failed to calculate trigger time for %s", e->t.str().c_str()) ;
      next_state = machine->state_aborted ; // TODO: make a new state "FAILED" for this case
    }
  }
  else if(e->has_recurrence())
    next_state = machine->state_recurred ;
  log_debug() ;
  machine->request_state(e, next_state) ;
  log_debug() ;
}
Exemplo n.º 11
0
machine_t::machine_t(const Timed *daemon) : timed(daemon)
{
  log_debug() ;
  // T = transition state
  // IO = waiting for i/o state
  // G = gate state
  // C = concentrating gate state
  // F = filtering state
  // A = actions allowed
  // -->NEW loaded as new
  // -->DUE loaded as due
  abstract_state_t *S[] =
  {
    state_start = new state_start_t(this),                     // T
    state_epoch = new state_epoch_t(this),                     // T
    state_waiting = new state_waiting_t(this),                 // IO G
    state_new = new state_new_t(this),                         // T
    state_scheduler = new state_scheduler_t(this),             // T
    state_qentry = new state_qentry_t(this),                   // T
    state_flt_conn = new state_flt_conn_t(this),               // IO G F -->NEW
    state_flt_alrm = new state_flt_alrm_t(this),               // IO G F -->NEW
    state_flt_user = new state_flt_user_t(this),               // IO G F -->NEW
    state_queued = new state_queued_t(this),                   // IO A   -->NEW

    state_due = new state_due_t(this),                         // T

    state_missed = new state_missed_t(this),                   // T A
    state_skipped = new state_skipped_t(this),                 // T

    state_armed = new state_armed_t(this),                     // IO G
    state_triggered = new state_triggered_t(this),             // T A

    state_dlg_wait = new state_dlg_wait_t(this),               // IO G   -->DUE
    state_dlg_cntr = new state_dlg_cntr_t(this),               // IO C   -->DUE
    state_dlg_requ = new state_dlg_requ_t(this),               // IO G   -->DUE
    state_dlg_user = new state_dlg_user_t(this),               // IO G   -->DUE
    state_dlg_resp = new state_dlg_resp_t(this),               // T

   /* state_buttons: below */                                  // T A

    state_snoozed = new state_snoozed_t(this),                 // T
    state_recurred = new state_recurred_t(this),               // T
    state_served = new state_served_t(this),                   // T
    state_tranquil = new state_tranquil_t(this),               // IO A -->DUE

    state_removed = new state_removed_t(this),                 // T
    state_aborted = new state_aborted_t(this),                 // T
    state_finalized = new state_finalized_t(this),             // T A
    NULL
  } ;
  log_debug() ;
  for(int i=0; S[i]; ++i)
    states.insert(S[i]) ;

  log_debug() ;
  for(int i=0; i<=Maemo::Timed::Number_of_Sys_Buttons; ++i)
    states.insert(buttons[-i] = new state_button_t(this, -i)) ;

  log_debug() ;
  for(int i=1; i<=Maemo::Timed::Max_Number_of_App_Buttons; ++i)
    states.insert(buttons[i] = new state_button_t(this, i)) ;

  for (set<abstract_state_t*>::iterator it=states.begin(); it!=states.end(); ++it)
    (*it)->resolve_names() ;

  log_debug() ;
  state_triggered->set_action_mask(ActionFlags::State_Triggered) ;
  state_queued->set_action_mask(ActionFlags::State_Queued) ;
  state_missed->set_action_mask(ActionFlags::State_Missed) ;
  state_tranquil->set_action_mask(ActionFlags::State_Tranquil) ;
  state_finalized->set_action_mask(ActionFlags::State_Finalized) ;
  state_due->set_action_mask(ActionFlags::State_Due) ;
  state_snoozed->set_action_mask(ActionFlags::State_Snoozed) ;
  state_served->set_action_mask(ActionFlags::State_Served) ;
  state_aborted->set_action_mask(ActionFlags::State_Aborted) ;
  // states_failed->set_action_mask(ActionFlags::State_Failed) ;

#if 0
  log_debug() ;
  io_state *queued = dynamic_cast<io_state*> (states["QUEUED"]) ;
  log_assert(queued!=NULL) ;

  gate_state *armed = dynamic_cast<gate_state*> (states["ARMED"]) ;
  log_assert(armed!=NULL) ;
  armed->open() ; // will be closed in some very special situations

  log_debug() ;
  gate_state *dlg_wait = dynamic_cast<gate_state*> (states["DLG_WAIT"]) ;
  gate_state *dlg_requ = dynamic_cast<gate_state*> (states["DLG_REQU"]) ;
  gate_state *dlg_user = dynamic_cast<gate_state*> (states["DLG_USER"]) ;
  gate_state *dlg_cntr = dynamic_cast<gate_state*> (states["DLG_CNTR"]) ;
  log_assert(dlg_wait!=NULL) ;
  log_assert(dlg_requ!=NULL) ;
  log_assert(dlg_user!=NULL) ;
  log_assert(dlg_cntr!=NULL) ;
#endif

  state_armed->open() ;

  QObject::connect(state_dlg_wait, SIGNAL(voland_needed()), this, SIGNAL(voland_needed())) ;

  QObject::connect(state_dlg_wait, SIGNAL(closed()), state_dlg_requ, SLOT(open())) ;
  QObject::connect(state_dlg_wait, SIGNAL(closed()), state_dlg_user, SLOT(open())) ;
  QObject::connect(state_dlg_requ, SIGNAL(closed()), state_dlg_wait, SLOT(open())) ;

  QObject::connect(this, SIGNAL(voland_registered()), state_dlg_requ, SLOT(close())) ;
  QObject::connect(this, SIGNAL(voland_registered()), state_dlg_user, SLOT(close())) ;
  QObject::connect(this, SIGNAL(voland_unregistered()), state_dlg_wait, SLOT(close())) ;
  QObject::connect(this, SIGNAL(voland_unregistered()), state_dlg_cntr, SLOT(send_back())) ;

  QObject::connect(state_queued, SIGNAL(sleep()), state_dlg_cntr, SLOT(open()), Qt::QueuedConnection) ;
  QObject::connect(state_dlg_wait, SIGNAL(opened()), state_dlg_cntr, SLOT(open()), Qt::QueuedConnection) ;

#if 0
  log_debug() ;
  filter_state *flt_conn = dynamic_cast<filter_state*> (states["FLT_CONN"]) ;
  filter_state *flt_alrm = dynamic_cast<filter_state*> (states["FLT_ALRM"]) ;
  filter_state *flt_user = dynamic_cast<filter_state*> (states["FLT_USER"]) ;
  log_assert(flt_conn) ;
  log_assert(flt_alrm) ;
  log_assert(flt_user) ;
#endif

  QObject::connect(state_flt_conn, SIGNAL(closed(abstract_filter_state_t*)), state_queued, SLOT(filter_closed(abstract_filter_state_t*))) ;
  QObject::connect(state_flt_alrm, SIGNAL(closed(abstract_filter_state_t*)), state_queued, SLOT(filter_closed(abstract_filter_state_t*))) ;
  QObject::connect(state_flt_user, SIGNAL(closed(abstract_filter_state_t*)), state_queued, SLOT(filter_closed(abstract_filter_state_t*))) ;

  log_debug() ;
  QObject::connect(this, SIGNAL(engine_pause(int)), state_queued, SLOT(engine_pause(int))) ;
  log_debug() ;
  initial_pause = new pause_t(this) ;
  log_debug() ;

  cluster_queue = new cluster_queue_t(this) ;
  log_debug() ;
  clusters[cluster_queue->bit] = cluster_queue ;
  log_debug() ;

  cluster_dialog = new cluster_dialog_t(this) ;
  log_debug() ;
  clusters[cluster_dialog->bit] = cluster_dialog ;
  log_debug() ;
  signalled_bootup = -1 ; // no signal sent yet
  signalled_non_boot_event = -1;
  log_debug() ;

  log_debug("machine->settings->alarms_are_enabled=%d", timed->settings->alarms_are_enabled) ;
  log_debug() ;
  alarm_gate(timed->settings->alarms_are_enabled) ;
  log_debug() ;

  transition_start_time = ticker_t(0) ;
  transition_time_adjustment.set(0) ;
  log_debug() ;
  next_cookie = 1 ;
  log_debug() ;
  context_changed = false ;
  log_debug("last line") ;
}
Exemplo n.º 12
0
ticker_t machine_t::calculate_bootup()
{
  if (cluster_dialog->has_bootup_events())
    return ticker_t(1) ; // right now
  return state_queued->next_bootup() ;
}