Example #1
0
STATIC void free_hash_table(hashtable *ht)
{
  hashelem *hp, *thp;

  hp = ht->first;
  while(hp != NULL) {
    thp = hp;
    hp = hp->nextelem;
    free_hash_item(&thp);
  }
  free(ht->table);
  free(ht);
}
Example #2
0
int
filehash_get(const unsigned char *path, unsigned char *val)
{
  unsigned long p_hash;
  unsigned int idx, i, min_i;
  struct hash_entry *p, *q;
  FILE *f = 0;
  unsigned min_tick;

  ASSERT(path);
  p_hash = get_hash(path);

  idx = p_hash % HASH_SIZE;
  while (hash_table[idx] && hash_table[idx]->path_hash == p_hash
         && strcmp(hash_table[idx]->path, path) != 0) {
    idx = (idx + HASH_STEP) % HASH_SIZE;
  }
  if (hash_table[idx] && hash_table[idx]->path_hash == p_hash) {
    // hit!
    if (!file_stamp_is_updated(path, hash_table[idx]->stamp)) {
      info("entry <%s> is in hash table and is not changed", path);
      memcpy(val, hash_table[idx]->sha1_hash, SHA1_SIZE);
      hash_table[idx]->tick = cur_tick++;
      return 0;
    }
    // update the hash code, maybe removing an item
    info("entry <%s> is in hash table and is CHANGED!", path);
    hash_table[idx]->stamp = file_stamp_update(path, hash_table[idx]->stamp);
    if (!hash_table[idx]->stamp || !(f = fopen(path, "rb"))
        || sha_stream(f, hash_table[idx]->sha1_hash)) {
      // file no longer exists or I/O error
      if (f) fclose(f);
      p = remove_hash_item(idx);
      free_hash_item(p);
      hash_use--;
      return -1;
    }
    // recalculate the hash
    fclose(f);
    memcpy(val, hash_table[idx]->sha1_hash, SHA1_SIZE);
    hash_table[idx]->tick = cur_tick++;
    return 0;
  }

  // no entry in the hash table
  XCALLOC(p, 1);
  if (!(p->stamp = file_stamp_get(path))
      || !(f = fopen(path, "rb"))
      || sha_stream(f, p->sha1_hash)) {
    if (f) fclose(f);
    free_hash_item(p);
    return -1;
  }
  fclose(f);
  p->path_hash = p_hash;
  p->path = xstrdup(path);
  p->tick = cur_tick++;
  memcpy(val, p->sha1_hash, SHA1_SIZE);
  if (hash_use < HASH_CAP) {
    info("entry <%s> is not in the hash table - adding", path);
    add_hash_item(p);
    hash_use++;
    return 0;
  }

  // find the least recently used entry and remove it
  info("entry <%s> is not in the hash table - REPLACING", path);
  min_i = -1;
  min_tick = cur_tick;
  for (i = 0; i < HASH_SIZE; i++)
    if (hash_table[i] && hash_table[i]->tick < min_tick) {
      min_i = i;
      min_tick = hash_table[i]->tick;
    }
  ASSERT(min_i >= 0);
  q = remove_hash_item(min_i);
  free_hash_item(q);
  add_hash_item(p);
  return 0;
}