Beispiel #1
0
char* del_option(bucketmap* bucket)
{
    char* input = read();
    char* output = concat(input, " returned ");

    return concat(output, remove_from_bucket(bucket, input));
}
Beispiel #2
0
/** Split a bucket.
 *  Returns the newly created bucket on success
 *  Returns NULL on failure (likely cause being out of memory)
 */
static ginthash_bucket *ginthash_splitbucket(void *db, ext_ginthash *tbl,
  ginthash_bucket *bucket)
{
  gint msbmask, lowbits;
  int i;
  ginthash_bucket *newbucket;

  if(bucket->level == tbl->level) {
    /* can't split at this level anymore, extend directory */
    /*printf("grow: curr level %d\n", tbl->level);*/
    if(grow_ginthash(db, (ext_ginthash *) tbl))
      return NULL;
  }

  /* Hash values for the new level (0+lowbits, msb+lowbits) */
  msbmask = (1<<(bucket->level++));
  lowbits = GINTHASH_SCRAMBLE(bucket->key[0]) & (msbmask - 1);

  /* Create a bucket to split into */
  newbucket = ginthash_newbucket(db, tbl);
  if(!newbucket)
    return NULL;
  newbucket->level = bucket->level;

  /* Split the entries based on the most significant
   * bit for the local level hash (the ones with msb set are relocated)
   */
  for(i=bucket->fill-1; i>=0; i--) {
    gint k_i = bucket->key[i];
    if(GINTHASH_SCRAMBLE(k_i) & msbmask) {
      add_to_bucket(newbucket, k_i, remove_from_bucket(bucket, i));
      /* printf("reassign: %d hash %d --> %d\n",
        k_i, lowbits, msbmask | lowbits); */
    }
  }

  /* Update the directory */
  if(bucket->level == tbl->level) {
    /* There are just two pointers pointing to bucket,
     * we can compute the location of the one that has the index
     * with msb set. The other one's contents do not need to be
     * modified.
     */
    tbl->directory[msbmask | lowbits] = newbucket;
  } else {
    /* The pointers that need to be updated have indexes
     * of xxx1yyyy where 1 is the msb in the index of the new
     * bucket, yyyy is the hash value of the bucket masked
     * by the previous level and xxx are all combinations of
     * bits that still remain masked by the local level after
     * the split. The pointers xxx0yyyy will remain pointing
     * to the old bucket.
     */
    size_t msbbuckets = 1<<(tbl->level - bucket->level), j;
    for(j=0; j<msbbuckets; j++) {
      size_t k = (j<<bucket->level) | msbmask | lowbits;
      /* XXX: paranoia check, remove in production */
      if(tbl->directory[k] != bucket)
        return NULL;
      tbl->directory[k] = newbucket;
    }
  }
  return newbucket;
}