Example #1
0
/**
 * Given a player dbref (For use with viewing permissions for attrs, etc),
 * list of keys, list of strings it maps to (sortkey()-style),
 * # of keys+strings and a list type info, build an array of
 * s_rec structures representing each item.
 * \param player the player executing the sort.
 * \param keys the array of items to sort.
 * \param strs If non-NULL, these are what to sort <keys> using.
 * \param n Number of items in <keys> and <strs>
 * \param lti List Type Info describing how it's sorted and built.
 * \retval A pointer to the first s_rec of an <n> s_rec array.
 */
s_rec *
slist_build(dbref player, char *keys[], char *strs[], int n, ListTypeInfo * lti)
{
  int i;
  s_rec *sp;

  sort_order = lti->sort_order;

  sp = mush_calloc(n, sizeof(s_rec), "do_gensort");

  for (i = 0; i < n; i++) {
    /* Elements are 0 by default thanks to calloc. Only need to touch
       those that need other values. */
    sp[i].val = keys[i];
    if (strs)
      sp[i].ptr = strs[i];
    if (lti->flags & IS_DB) {
      sp[i].db = parse_objid(keys[i]);
      if (!RealGoodObject(sp[i].db))
        sp[i].db = NOTHING;
    }
    genrecord(&sp[i], player, lti);
  }
  return sp;
}
Example #2
0
/** Return a list of all available locks
 * \param buff the buffer
 * \param bp a pointer to the current position in the buffer.
 * \param name if not NULL, only show locks with this prefix
 */
void
list_locks(char *buff, char **bp, const char *name)
{
  lock_list **locks, *lk;
  bool first = 1;
  int nlocks = 0, n;

  locks = mush_calloc(htab_locks.entries, sizeof(lock_list), "lock.list");

  for (lk = hash_firstentry(&htab_locks); lk; lk = hash_nextentry(&htab_locks)) {
    /* Skip those that don't match */
    if (name && !string_prefix(lk->type, name))
      continue;
    locks[nlocks++] = lk;
  }

  qsort(locks, nlocks, sizeof lk, lock_compare);

  for (n = 0; n < nlocks; n += 1) {
    if (first) {
      first = 0;
    } else {
      safe_chr(' ', buff, bp);
    }
    safe_str(strupper(locks[n]->type), buff, bp);
  }

  mush_free(locks, "lock.list");
}
Example #3
0
/** Initialize a hashtable.
 * \param htab pointer to hash table to initialize.
 * \param size size of hashtable.
 */
void
hash_init(HASHTAB *htab, int size, void (*free_data) (void *))
{
    size = next_prime_after(size);
    htab->last_index = -1;
    htab->free_data = free_data;
    htab->hashsize = size;
    htab->hashfunc_offset = 0;
    htab->entries = 0;
    htab->buckets = mush_calloc(size, sizeof(struct hash_bucket), "hash.buckets");
}
Example #4
0
/** Resize a hash table.
 * \param htab pointer to hashtable.
 * \param primesize new size.
 * \param hashindex Index of first hash function to use
 */
static bool
real_hash_resize(HASHTAB *htab, int newsize, int hashfunc_offset)
{
    HASHENT *oldarr;
    int oldsize, oldoffset, i;

    /* Massive overkill here */
    if (resize_calls > 150) {
        fputs("Ooops. Too many attempts to resize a hash table.\n", stderr);
        return false;
    }

    /* If all possible hash function combos have been exhausted,
       grow the array */
    if (hashfunc_offset == first_offset) {
        int newersize = next_prime_after(floor(newsize * 1.15));
        first_offset = -1;
        return real_hash_resize(htab, newersize, hashfunc_offset);
    }

    resize_calls += 1;

    /* Save the old data we need */
    oldsize = htab->hashsize;
    oldoffset = htab->hashfunc_offset;
    oldarr = htab->buckets;

    htab->buckets =
        mush_calloc(newsize, sizeof(struct hash_bucket), "hash.buckets");
    htab->hashsize = newsize;
    htab->hashfunc_offset = hashfunc_offset;
    for (i = 0; i < oldsize; i++) {
        if (oldarr[i].key) {
            if (!hash_insert(htab, oldarr[i].key, oldarr[i].keylen, oldarr[i].data)) {
                /* Couldn't fit an element in. Try with different hash functions. */
                mush_free(htab->buckets, "hash.buckets");
                htab->buckets = oldarr;
                htab->hashsize = oldsize;
                htab->hashfunc_offset = oldoffset;
                if (first_offset == -1)
                    first_offset = hashfunc_offset;
                return
                    real_hash_resize(htab, newsize, (hashfunc_offset + 1) % NHASH_MOD);
            }
        }
    }

    mush_free(oldarr, "hash.buckets");
    return true;
}
Example #5
0
/**
 * Given a string description of a sort type, generate and return a
 * ListTypeInfo that can be passed to slist_* functions.
 * \param sort_type A string describing a sort type.
 * \retval ListTypeInfo containing all generating and comparison information
 *         needed.
 */
ListTypeInfo *
get_list_type_info(SortType sort_type)
{
  int i, len;
  char *ptr = NULL;
  ListTypeInfo *lti;

  /* i is either the right one or the default, so we return it anyway. */
  lti = mush_calloc(1, sizeof(ListTypeInfo), "list_type_info");

  lti->sort_order = ASCENDING;

  if (*sort_type == '-') {
    lti->sort_order = DESCENDING;
    sort_type++;
  }
  if (!sort_type) {
    /* Advance i to the default */
    for (i = 0; ltypelist[i].name; i++) ;
  } else if ((ptr = strchr(sort_type, ':'))) {
    len = ptr - sort_type;
    ptr += 1;
    if (!*ptr)
      ptr = NULL;
    for (i = 0;
         ltypelist[i].name && strncasecmp(ltypelist[i].name, sort_type, len);
         i++) ;
  } else {
    for (i = 0; ltypelist[i].name && strcasecmp(ltypelist[i].name, sort_type);
         i++) ;
  }

  lti->name = ltypelist[i].name;
  if (ptr) {
    lti->attrname = mush_strdup(ptr, "list_type_info_attrname");
  } else {
    lti->attrname = NULL;
  }
  lti->make_record = ltypelist[i].make_record;
  lti->sorter = ltypelist[i].sorter;
  lti->flags = ltypelist[i].flags;
  return lti;
}
Example #6
0
/** Migrate some number of chunks.
 * The requested amount is only a guideline; the actual amount
 * migrated will be more or less due to always migrating all the
 * attributes, locks, and mail on any given object together.
 * \param amount the suggested number of attributes to migrate.
 */
static void
migrate_stuff(int amount)
{
  static int start_obj = 0;
  static chunk_reference_t **refs = NULL;
  static int refs_size = 0;
  int end_obj;
  int actual;
  ATTR *aptr;
  lock_list *lptr;
  MAIL *mp;

  if (db_top == 0)
    return;

  end_obj = start_obj;
  actual = 0;
  do {
    for (aptr = List(end_obj); aptr; aptr = AL_NEXT(aptr))
      if (aptr->data != NULL_CHUNK_REFERENCE)
        actual++;
    for (lptr = Locks(end_obj); lptr; lptr = L_NEXT(lptr))
      if (L_KEY(lptr) != NULL_CHUNK_REFERENCE)
        actual++;
    if (IsPlayer(end_obj)) {
      for (mp = find_exact_starting_point(end_obj); mp; mp = mp->next)
        if (mp->msgid != NULL_CHUNK_REFERENCE)
          actual++;
    }
    end_obj = (end_obj + 1) % db_top;
  } while (actual < amount && end_obj != start_obj);

  if (actual == 0)
    return;

  if (!refs || actual > refs_size) {
    if (refs)
      mush_free(refs, "migration reference array");
    refs =
      mush_calloc(actual, sizeof(chunk_reference_t *),
                  "migration reference array");
    refs_size = actual;
    if (!refs)
      mush_panic("Could not allocate migration reference array");
  }
#ifdef DEBUG_MIGRATE
  do_rawlog(LT_TRACE, "Migrate asked %d, actual objects #%d to #%d for %d",
            amount, start_obj, (end_obj + db_top - 1) % db_top, actual);
#endif

  actual = 0;
  do {
    for (aptr = List(start_obj); aptr; aptr = AL_NEXT(aptr))
      if (aptr->data != NULL_CHUNK_REFERENCE) {
        refs[actual] = &(aptr->data);
        actual++;
      }
    for (lptr = Locks(start_obj); lptr; lptr = L_NEXT(lptr))
      if (L_KEY(lptr) != NULL_CHUNK_REFERENCE) {
        refs[actual] = &(lptr->key);
        actual++;
      }
    if (IsPlayer(start_obj)) {
      for (mp = find_exact_starting_point(start_obj); mp; mp = mp->next)
        if (mp->msgid != NULL_CHUNK_REFERENCE) {
          refs[actual] = &(mp->msgid);
          actual++;
        }
    }
    start_obj = (start_obj + 1) % db_top;
  } while (start_obj != end_obj);

  chunk_migration(actual, refs);
}