Exemple #1
0
xaset_t *xaset_union(pool *work_pool, xaset_t *set1, xaset_t *set2,
    size_t msize, XASET_MCOPY copyf) {
  xaset_t *newset;
  xasetmember_t *setp,*n;
  xaset_t *setv[3];
  xaset_t **setcp;

  setv[0] = set1; setv[1] = set2; setv[2] = NULL;

  if (!set1 || !set2 || (!msize && !copyf)) {
    errno = EINVAL;
    return NULL;
  }

  work_pool = (work_pool ? work_pool :
    (set1->pool ? set1->pool : set2->pool));

  if (!(newset = xaset_create(work_pool, set1->xas_compare)))
    return NULL;

  for (setcp = setv; *setcp; setcp++)
    for (setp = (*setcp)->xas_list; setp; setp=setp->next) {
      n = copyf ? copyf(setp) : (xasetmember_t*) palloc(work_pool, msize);
      if (!n)
        return NULL;			/* Could cleanup here */

      if (!copyf)
        memcpy(n, setp, msize);

      if (xaset_insert_sort(newset, n, 0) == -1)
        return NULL;
    }

  return newset;
}
Exemple #2
0
/* This function does the work of iterating through the list of registered
 * timers, checking to see if their callbacks should be invoked and whether
 * they should be removed from the registration list. Its return value is
 * the amount of time remaining on the first timer in the list.
 */
static int process_timers(int elapsed) {
  struct timer *t = NULL, *next = NULL;

  if (!recycled)
    recycled = xaset_create(timer_pool, NULL);

  if (!elapsed &&
      !recycled->xas_list) {

    if (!timers)
      return 0;

    return (timers->xas_list ? ((struct timer *) timers->xas_list)->count : 0);
  }

  /* Critical code, no interruptions please */
  if (_indispatch)
    return 0;

  pr_alarms_block();
  _indispatch++;

  if (elapsed) {
    for (t = (struct timer *) timers->xas_list; t; t = next) {
      /* If this timer has already been handled, skip */
      next = t->next;

      if (t->remove) {
        /* Move the timer onto the free_timers chain, for later reuse. */
        xaset_remove(timers, (xasetmember_t *) t);
        xaset_insert(free_timers, (xasetmember_t *) t);

      } else if ((t->count -= elapsed) <= 0) {
        /* This timer's interval has elapsed, so trigger its callback. */

        pr_trace_msg("timer", 4,
          "%ld %s for timer ID %d ('%s', for module '%s') elapsed, invoking "
          "callback (%p)", t->interval,
          t->interval != 1 ? "seconds" : "second", t->timerno,
          t->desc ? t->desc : "<unknown>",
          t->mod ? t->mod->name : "<none>", t->callback);

        if (t->callback(t->interval, t->timerno, t->interval - t->count,
            t->mod) == 0) {

          /* A return value of zero means this timer is done, and can be
           * removed.
           */
          xaset_remove(timers, (xasetmember_t *) t);
          xaset_insert(free_timers, (xasetmember_t *) t);

        } else {
          /* A non-zero return value from a timer callback signals that
           * the timer should be reused/restarted.
           */
          pr_trace_msg("timer", 6, "restarting timer ID %d ('%s'), as per "
            "callback", t->timerno, t->desc ? t->desc : "<unknown>");

          xaset_remove(timers, (xasetmember_t *) t);
          t->count = t->interval;
          xaset_insert(recycled, (xasetmember_t *) t);
        }
      }
    }
  }

  /* Put the recycled timers back into the main timer list. */
  while ((t = (struct timer *) recycled->xas_list) != NULL) {
    xaset_remove(recycled, (xasetmember_t *) t);
    xaset_insert_sort(timers, (xasetmember_t *) t, TRUE);
  }

  _indispatch--;
  pr_alarms_unblock();

  /* If no active timers remain in the list, there is no reason to set the
   * SIGALRM handle.
   */
  return (timers->xas_list ? ((struct timer *) timers->xas_list)->count : 0);
}
Exemple #3
0
int pr_timer_add(int seconds, int timerno, module *mod, callback_t cb,
    const char *desc) {
  struct timer *t = NULL;

  if (seconds <= 0 ||
      cb == NULL ||
      desc == NULL) {
    errno = EINVAL;
    return -1;
  }

  if (!timers)
    timers = xaset_create(timer_pool, (XASET_COMPARE) timer_cmp);

  /* Check to see that, if specified, the timerno is not already in use. */
  if (timerno >= 0) {
    for (t = (struct timer *) timers->xas_list; t; t = t->next) {
      if (t->timerno == timerno) {
        errno = EPERM;
        return -1;
      }
    }
  }

  if (!free_timers)
    free_timers = xaset_create(timer_pool, NULL);

  /* Try to use an old timer first */
  pr_alarms_block();
  t = (struct timer *) free_timers->xas_list;
  if (t != NULL) {
    xaset_remove(free_timers, (xasetmember_t *) t);

  } else {

    if (timer_pool == NULL) {
      timer_pool = make_sub_pool(permanent_pool);
      pr_pool_tag(timer_pool, "Timer Pool");
    }

    /* Must allocate a new one */
    t = palloc(timer_pool, sizeof(struct timer));
  }

  if (timerno < 0) {
    /* Dynamic timer */
    if (dynamic_timerno < PR_TIMER_DYNAMIC_TIMERNO) {
      dynamic_timerno = PR_TIMER_DYNAMIC_TIMERNO;
    }

    timerno = dynamic_timerno++;
  }

  t->timerno = timerno;
  t->count = t->interval = seconds;
  t->callback = cb;
  t->mod = mod;
  t->remove = 0;
  t->desc = desc;

  /* If called while _indispatch, add to the recycled list to prevent
   * list corruption
   */

  if (_indispatch) {
    if (!recycled)
      recycled = xaset_create(timer_pool, NULL);
    xaset_insert(recycled, (xasetmember_t *) t);

  } else {
    xaset_insert_sort(timers, (xasetmember_t *) t, TRUE);
    nalarms++;
    set_sig_alarm();

    /* The handle_alarm() function also readjusts the timers lists
     * as part of its processing, so it needs to be called when a timer
     * is added.
     */
    handle_alarm();
  }

  pr_alarms_unblock();

  pr_trace_msg("timer", 7, "added timer ID %d ('%s', for module '%s'), "
    "triggering in %ld %s", t->timerno, t->desc,
    t->mod ? t->mod->name : "[none]", t->interval,
    t->interval != 1 ? "seconds" : "second");
  return timerno;
}
Exemple #4
0
int pr_stash_add_symbol(pr_stash_type_t sym_type, void *data) {
  struct stash *sym = NULL;
  unsigned int hash;
  int idx = 0;
  xaset_t **symbol_table;
  size_t sym_namelen = 0;

  if (data == NULL) {
    errno = EINVAL;
    return -1;
  }

  switch (sym_type) {
    case PR_SYM_CONF:
      sym = sym_alloc();
      sym->sym_type = PR_SYM_CONF;
      sym->sym_name = ((conftable *) data)->directive;
      sym->sym_module = ((conftable *) data)->m;
      sym->ptr.sym_conf = data;
      symbol_table = conf_symbol_table;
      break;

    case PR_SYM_CMD:
      sym = sym_alloc();
      sym->sym_type = PR_SYM_CMD;
      sym->sym_name = ((cmdtable *) data)->command;
      sym->sym_module = ((cmdtable *) data)->m;
      sym->ptr.sym_cmd = data;
      symbol_table = cmd_symbol_table;
      break;

    case PR_SYM_AUTH:
      sym = sym_alloc();
      sym->sym_type = PR_SYM_AUTH;
      sym->sym_name = ((authtable *) data)->name;
      sym->sym_module = ((authtable *) data)->m;
      sym->ptr.sym_auth = data;
      symbol_table = auth_symbol_table;
      break;

    case PR_SYM_HOOK:
      sym = sym_alloc();
      sym->sym_type = PR_SYM_HOOK;
      sym->sym_name = ((cmdtable *) data)->command;
      sym->sym_module = ((cmdtable *) data)->m;
      sym->ptr.sym_hook = data;
      symbol_table = hook_symbol_table;
      break;

    default:
      errno = EINVAL;
      return -1;
  }

  /* XXX Should we check for null sym->sym_module as well? */
  if (sym->sym_name == NULL) {
    destroy_pool(sym->sym_pool);
    errno = EPERM;
    return -1;
  }

  sym_namelen = strlen(sym->sym_name);
  if (sym_namelen == 0) {
    destroy_pool(sym->sym_pool);
    errno = EPERM;
    return -1;
  }

  /* Don't forget to include one for the terminating NUL. */
  sym->sym_namelen = sym_namelen + 1;

  hash = sym_type_hash(sym_type, sym->sym_name, sym->sym_namelen);
  idx = hash % PR_TUNABLE_HASH_TABLE_SIZE;
  sym->sym_hash = hash;

  if (!symbol_table[idx]) {
    symbol_table[idx] = xaset_create(symbol_pool, (XASET_COMPARE) sym_cmp);
  }

  xaset_insert_sort(symbol_table[idx], (xasetmember_t *) sym, TRUE);
  return 0;
}