コード例 #1
0
ファイル: hash.c プロジェクト: Cfretz244/b2fs
// Function handles the rehash process encountered when a hash reaches
// 80% capacity. Hate locking the entire function, but we're rehashing, so it's
// pretty much unavoidable.
void rehash(hash_t *table) {
  // Acquire write-lock for hash.
  pthread_rwlock_wrlock(&table->lock);

  // Abort rehash if we're frozen.
  if (table->frozen) {
    pthread_rwlock_unlock(&table->lock);
    return;
  }

  // Allocate new table with calloc to allow for NULL checks.
  hash_node_t **new_data = calloc(table->size * 2, sizeof(hash_node_t *));

  // Copy all previous data into new, larger, hash.
  hash_node_t **old_data = table->data;
  for(int i = 0; i < table->size; i++) {
    hash_node_t *current = old_data[i];
    while (current) {
      hash_node_t *tmp = current->next;
      current->next = NULL;

      // Calculate new hash value and insert.
      unsigned int hash = (unsigned int) XXH64(current->key, strlen(current->key), 0) % (table->size * 2);
      new_data[hash] = insert_hash_node(new_data[hash], current);
      current = tmp;
    }
  }

  // Update hash struct with changes.
  table->data = new_data;
  table->size *= 2;
  free(old_data);
}
コード例 #2
0
ファイル: No1009_3.c プロジェクト: ainehanta/J3program
void hash_insert(HASH_NODE** table,int value)
{
	int hash_value;

	hash_value = hash(value);
	insert_hash_node(&table[hash_value],value);
}
コード例 #3
0
ファイル: hash.c プロジェクト: Cfretz244/b2fs
// Insert data into a hash for a specific key.
int hash_put(hash_t *table, char *key, void *data) {
  // Verify parameters.
  if (!table || !key || !data) return HASH_INVAL_ERROR;

  // Check if table needs a rehash.
  int rehashed = 0;
  if (table->count / (float) table->size > 0.8) {
    rehash(table);
    rehashed = 1;
  }

  // Acquire read lock if we didn't rehash the table.
  if (!rehashed) pthread_rwlock_rdlock(&table->lock);

  // Cache the table size so that we can detect rehashes in the future.
  int orig_size = table->size;

  // Generate hash value and insert.
  unsigned int hash = (unsigned int) XXH64(key, strlen(key), 0) % table->size;

  // Abort if we're frozen.
  if (table->frozen) {
    pthread_rwlock_unlock(&table->lock);
    return HASH_FROZEN_ERROR;
  }

  // Verify that table does not already contain given key.
  // Check if we're dealing with a hash collision, or a repeat key.
  if (!find_hash_node(table->data[hash], key)) {
    // If we didn't need to rehash the table, grab the write-lock now.
    // If we didn't rehash, means that we've gotten to this point with only a read-lock.
    // Possible for two threads to attempt to insert the same key at the same time and
    // both make it here. After acquiring the write-lock, double check that the key
    // doesn't exist in the list.
    if (!rehashed) {
      pthread_rwlock_unlock(&table->lock);
      pthread_rwlock_wrlock(&table->lock);

      // It's possible, since read-locks can't be converted to write-locks atomically,
      // that someone rehashed the table while we were unlocked. Update the hash value
      // if this happened.
      if (table->size != orig_size) hash = (unsigned int) XXH64(key, strlen(key), 0) % table->size;

      // Recheck for the key.
      if (find_hash_node(table->data[hash], key)) {
        // Contention on duplicate key insert.
        pthread_rwlock_unlock(&table->lock);
        return HASH_EXISTS_ERROR;
      }
    }

    // Data is new.
    hash_node_t *node = create_hash_node(key, data, table->elem_size);

    // We have exclusive write access to the hash, and are the only thread attempting to insert this
    // key. Do the deed.
    table->data[hash] = insert_hash_node(table->data[hash], node);
    table->count++;
    pthread_rwlock_unlock(&table->lock);
    return HASH_SUCCESS;
  } else {
    // Key already exists in table.
    pthread_rwlock_unlock(&table->lock);
    return HASH_EXISTS_ERROR;
  }
}