示例#1
0
文件: test-hash.c 项目: Raffprta/core
static void test_hash_random_pool(pool_t pool)
{
#define KEYMAX 100000
	HASH_TABLE(void *, void *) hash;
	unsigned int *keys;
	unsigned int i, key, keyidx, delidx;

	keys = i_new(unsigned int, KEYMAX); keyidx = 0;
	hash_table_create_direct(&hash, pool, 0);
	for (i = 0; i < KEYMAX; i++) {
		key = (rand() % KEYMAX) + 1;
		if (rand() % 5 > 0) {
			if (hash_table_lookup(hash, POINTER_CAST(key)) == NULL) {
				hash_table_insert(hash, POINTER_CAST(key),
						  POINTER_CAST(1));
				keys[keyidx++] = key;
			}
		} else if (keyidx > 0) {
			delidx = rand() % keyidx;
			hash_table_remove(hash, POINTER_CAST(keys[delidx]));
			memmove(&keys[delidx], &keys[delidx+1],
				(keyidx-delidx-1) * sizeof(*keys));
			keyidx--;
		}
	}
	for (i = 0; i < keyidx; i++)
		hash_table_remove(hash, POINTER_CAST(keys[i]));
	hash_table_destroy(&hash);
	i_free(keys);
}
示例#2
0
void chirp_alloc_flush()
{
	char *path, *root;
	struct alloc_state *s;

	if(!alloc_enabled)
		return;

	debug(D_ALLOC, "flushing allocation states...");

	if(!alloc_table)
		alloc_table = hash_table_create(0, 0);

	hash_table_firstkey(alloc_table);
	while(hash_table_nextkey(alloc_table, &path, (void **) &s)) {
		alloc_state_save(path, s);
		hash_table_remove(alloc_table, path);
	}

	if(!root_table)
		root_table = hash_table_create(0, 0);

	hash_table_firstkey(root_table);
	while(hash_table_nextkey(root_table, &path, (void **) &root)) {
		free(root);
		hash_table_remove(root_table, path);
	}

	last_flush_time = time(0);
}
示例#3
0
void test_hash_table_remove(void)
{
	HashTable *hash_table;
	char buf[10];

	hash_table = generate_hash_table();

	assert(hash_table_num_entries(hash_table) == NUM_TEST_VALUES);
	sprintf(buf, "%i", 5000);
	assert(hash_table_lookup(hash_table, buf) != NULL);

	/* Remove an entry */

	hash_table_remove(hash_table, buf);

	/* Check entry counter */

	assert(hash_table_num_entries(hash_table) == 9999);

	/* Check that NULL is returned now */

	assert(hash_table_lookup(hash_table, buf) == NULL);

	/* Try removing a non-existent entry */

	sprintf(buf, "%i", -1);
	hash_table_remove(hash_table, buf);

	assert(hash_table_num_entries(hash_table) == 9999);

	hash_table_free(hash_table);
}
static int log_replay( struct nvpair_database *db, const char *filename, time_t snapshot)
{
	FILE *file = fopen(filename,"r");
	if(!file) return 0;
	
	time_t current = 0;
	struct nvpair *nv;

	char line[NVPAIR_LINE_MAX];
	char key[NVPAIR_LINE_MAX];
	char name[NVPAIR_LINE_MAX];
	char value[NVPAIR_LINE_MAX];
	char oper;
	
	while(fgets(line,sizeof(line),file)) {

		int n = sscanf(line,"%c %s %s %[^\n]",&oper,key,name,value);
		if(n<1) continue;

		switch(oper) {
			case 'C':
				nv = nvpair_create();
				nvpair_parse_stream(nv,file);
				nvpair_delete(hash_table_remove(db->table,name));
				hash_table_insert(db->table,key,nv);
				break;
			case 'D':
				nv = hash_table_remove(db->table,key);
				if(nv) nvpair_delete(nv);
				break;
			case 'U':
				nv = hash_table_lookup(db->table,key);
				if(nv) nvpair_insert_string(nv,name,value);
				break;
			case 'R':
				nv = hash_table_lookup(db->table,key);
				if(nv) nvpair_remove(nv,name);
				break;
			case 'T':
				current = atol(key);
				if(current>snapshot) break;
				break;
			default:
				debug(D_NOTICE,"corrupt log data in %s: %s",filename,line);
				break;
		}
	}
	
	fclose(file);

	return 1;
}
示例#5
0
static int server_table_load(time_t stoptime)
{
	struct catalog_query *q;
	struct jx *j;
	char *key;
	void *item;

	if((last_update + update_interval) > time(0)) {
		return 1;
	}

	if(!server_table) {
		server_table = hash_table_create(0, 0);
		if(!server_table)
			return 0;
	}

	if(inhibit_catalog_queries) {
		debug(D_CHIRP, "catalog queries disabled\n");
		return 1;
	}

	hash_table_firstkey(server_table);
	while(hash_table_nextkey(server_table, &key, &item)) {
		hash_table_remove(server_table, key);
		jx_delete(item);
	}

	debug(D_CHIRP, "querying catalog at %s:%d", CATALOG_HOST, CATALOG_PORT);

	q = catalog_query_create(CATALOG_HOST, CATALOG_PORT, stoptime);
	if(!q)
		return 0;

	while((j = catalog_query_read(q, stoptime))) {
		char name[CHIRP_PATH_MAX];
		const char *type, *hname;
		int port;

		type = jx_lookup_string(j, "type");
		if(type && !strcmp(type, "chirp")) {
			hname = jx_lookup_string(j, "name");
			if(hname) {
				port = jx_lookup_integer(j, "port");
				if(!port)
					port = CHIRP_PORT;
				sprintf(name, "%s:%d", hname, port);
				hash_table_insert(server_table, name, j);
			} else {
				jx_delete(j);
			}
		} else {
			jx_delete(j);
		}
	}
	catalog_query_delete(q);
	last_update = time(0);

	return 1;
}
示例#6
0
static void
trace_winsys_buffer_unmap(struct pipe_winsys *_winsys, 
                          struct pipe_buffer *buffer)
{
   struct trace_winsys *tr_ws = trace_winsys(_winsys);
   struct pipe_winsys *winsys = tr_ws->winsys;
   const void *map;
   
   map = hash_table_get(tr_ws->buffer_maps, buffer);
   if(map) {
      trace_dump_call_begin("pipe_winsys", "buffer_write");
      
      trace_dump_arg(ptr, winsys);
      
      trace_dump_arg(ptr, buffer);
      
      trace_dump_arg_begin("data");
      trace_dump_bytes(map, buffer->size);
      trace_dump_arg_end();

      trace_dump_arg_begin("size");
      trace_dump_uint(buffer->size);
      trace_dump_arg_end();
   
      trace_dump_call_end();

      hash_table_remove(tr_ws->buffer_maps, buffer);
   }
   
   winsys->buffer_unmap(winsys, buffer);
}
示例#7
0
/** Process pending wait requests */
void process_pending_wait(void)
{
	task_exit_t texit;
	
loop:
	list_foreach(pending_wait, cur) {
		pending_wait_t *pr = list_get_instance(cur, pending_wait_t, link);
		
		unsigned long keys[2] = {
			LOWER32(pr->id),
			UPPER32(pr->id)
		};
		
		link_t *link = hash_table_find(&task_hash_table, keys);
		if (!link)
			continue;
		
		hashed_task_t *ht = hash_table_get_instance(link, hashed_task_t, link);
		if (!ht->finished)
			continue;
		
		if (!(pr->callid & IPC_CALLID_NOTIFICATION)) {
			texit = ht->have_rval ? TASK_EXIT_NORMAL :
			    TASK_EXIT_UNEXPECTED;
			ipc_answer_2(pr->callid, EOK, texit,
			    ht->retval);
		}
		
		hash_table_remove(&task_hash_table, keys, 2);
		list_remove(cur);
		free(pr);
		goto loop;
	}
示例#8
0
static int compat_checkpoint_read( struct deltadb *db, const char *filename )
{
	FILE * file = fopen(filename,"r");
	if(!file) return 0;

	while(1) {
		struct nvpair *nv = nvpair_create();
		if(nvpair_parse_stream(nv,file)) {
			const char *key = nvpair_lookup_string(nv,"key");
			if(key) {
				nvpair_delete(hash_table_remove(db->table,key));
				struct jx *j = nvpair_to_jx(nv);
				/* skip objects that don't match the filter */
				if(deltadb_boolean_expr(db->filter_expr,j)) {
					hash_table_insert(db->table,key,j);
				} else {
					jx_delete(j);
				}
			}
			nvpair_delete(nv);
		} else {
			nvpair_delete(nv);
			break;
		}
	}

	fclose(file);

	return 1;
}
示例#9
0
文件: record.c 项目: hushouguo/zebra
/* void close_database(id) */
static int cc_close_database(lua_State* L)
{
	int id;
	database_handler_t* database_handler;
	worker_handler_t* handler = find_handler_by_stack(L);
	int args = lua_gettop(L);
	if (args < 1)
	{
		error_log("`%s` parameter lack:%d\n", __FUNCTION__, args);
		return 0;
	}
	if (!lua_isnumber(L, -args))
	{
		error_log("`%s` parameter error:%s\n", __FUNCTION__, lua_typename(L, lua_type(L, -args)));
		return 0;
	}
	id = lua_tointeger(L, -args);
	database_handler = hash_table_find(handler->database_table, id);
	if (!database_handler)
	{
		error_log("`%s` not found database:%d\n", __FUNCTION__, id);
		return 0;
	}
	hash_table_remove(handler->database_table, id);
	database_handler_delete(database_handler);
	return 0;
}
void auth_request_handler_abort_requests(struct auth_request_handler *handler)
{
	struct hash_iterate_context *iter;
	void *key;
	struct auth_request *auth_request;

	iter = hash_table_iterate_init(handler->requests);
	while (hash_table_iterate(iter, handler->requests, &key, &auth_request)) {
		switch (auth_request->state) {
		case AUTH_REQUEST_STATE_NEW:
		case AUTH_REQUEST_STATE_MECH_CONTINUE:
		case AUTH_REQUEST_STATE_FINISHED:
			auth_request_unref(&auth_request);
			hash_table_remove(handler->requests, key);
			break;
		case AUTH_REQUEST_STATE_PASSDB:
		case AUTH_REQUEST_STATE_USERDB:
			/* can't abort a pending passdb/userdb lookup */
			break;
		case AUTH_REQUEST_STATE_MAX:
			i_unreached();
		}
	}
	hash_table_iterate_deinit(&iter);
}
示例#11
0
static int compat_checkpoint_read( struct jx_database *db, const char *filename )
{
	FILE * file = fopen(filename,"r");
	if(!file) return 0;

	while(1) {
		struct nvpair *nv = nvpair_create();
		if(nvpair_parse_stream(nv,file)) {
			const char *key = nvpair_lookup_string(nv,"key");
			if(key) {
				nvpair_delete(hash_table_remove(db->table,key));
				struct jx *j = nvpair_to_jx(nv);
				hash_table_insert(db->table,key,j);
			}
			nvpair_delete(nv);
		} else {
			nvpair_delete(nv);
			break;
		}
	}

	fclose(file);

	return 1;
}
示例#12
0
static void mail_session_free(struct mail_session *session)
{
	i_assert(session->refcount == 0);

	global_memory_free(mail_session_memsize(session));

	if (session->to_idle != NULL)
		timeout_remove(&session->to_idle);
	if (!session->disconnected)
		hash_table_remove(mail_sessions_hash, session->id);
	DLLIST_REMOVE_FULL(&stable_mail_sessions, session,
			   stable_prev, stable_next);
	DLLIST2_REMOVE_FULL(&mail_sessions_head, &mail_sessions_tail, session,
			    sorted_prev, sorted_next);
	DLLIST_REMOVE_FULL(&session->user->sessions, session,
			   user_prev, user_next);
	mail_user_unref(&session->user);
	if (session->ip != NULL) {
		DLLIST_REMOVE_FULL(&session->ip->sessions, session,
				   ip_prev, ip_next);
		mail_ip_unref(&session->ip);
	}

	str_table_unref(services, &session->service);
	i_free(session->id);
	i_free(session);
}
示例#13
0
void service_process_destroy(struct service_process *process)
{
	struct service *service = process->service;
	struct service_list *service_list = service->list;

	DLLIST_REMOVE(&service->processes, process);
	hash_table_remove(service_pids, POINTER_CAST(process->pid));

	if (process->available_count > 0)
		service->process_avail--;
	service->process_count--;
	i_assert(service->process_avail <= service->process_count);

	if (process->to_status != NULL)
		timeout_remove(&process->to_status);
	if (process->to_idle != NULL)
		timeout_remove(&process->to_idle);
	if (service->list->log_byes != NULL)
		service_process_notify_add(service->list->log_byes, process);

	process->destroyed = TRUE;
	service_process_unref(process);

	if (service->process_count < service->process_limit &&
	    service->type == SERVICE_TYPE_LOGIN)
		service_login_notify(service, FALSE);

	service_list_unref(service_list);
}
示例#14
0
int ast_program_execute( struct ast_group *program, time_t stoptime )
{
	struct ast_group *g;
	struct ast_function *f, *old;

	/*
	First, fill up the function table with all of the functions
	in this entire syntax tree.
	*/

	ftable = hash_table_create(127,hash_string);
	if(!ftable) ftsh_fatal(0,"out of memory");

	for( g=program; g; g=g->next ) {
		if(g->command->type==AST_COMMAND_FUNCTION) {
			f = g->command->u.function;
			old = hash_table_remove(ftable,f->name->text);
			if(old) {
				ftsh_error(FTSH_ERROR_SYNTAX,f->function_line,"function %s is defined twice (first at line %d)",f->name->text,old->function_line);
				return 0;
			}
			if(!hash_table_insert(ftable,f->name->text,f)) {
				ftsh_fatal(f->function_line,"out of memory");
			}
		}
	}

	return ast_group_execute(program,stoptime);
}
示例#15
0
int
main (void)
{
  struct hash_table *ht = make_string_hash_table (0);
  char line[80];
  while ((fgets (line, sizeof (line), stdin)))
    {
      int len = strlen (line);
      if (len <= 1)
	continue;
      line[--len] = '\0';
      if (!hash_table_contains (ht, line))
	hash_table_put (ht, strdup (line), "here I am!");
#if 1
      if (len % 5 == 0)
	{
	  char *line_copy;
	  if (hash_table_get_pair (ht, line, &line_copy, NULL))
	    {
	      hash_table_remove (ht, line);
	      xfree (line_copy);
	    }
	}
#endif
    }
#if 0
  print_hash (ht);
#endif
#if 1
  printf ("%d %d\n", ht->count, ht->size);
#endif
  return 0;
}
示例#16
0
static void checkpassword_request_finish(struct chkpw_auth_request *request,
					 enum userdb_result result)
{
	struct userdb_module *_module = request->request->userdb->userdb;
	struct checkpassword_userdb_module *module =
		(struct checkpassword_userdb_module *)_module;
	userdb_callback_t *callback =
		(userdb_callback_t *)request->callback;

	hash_table_remove(module->clients, POINTER_CAST(request->pid));

	if (result == USERDB_RESULT_OK) {
		if (strchr(str_c(request->input_buf), '\n') != NULL) {
			auth_request_log_error(request->request,
				"userdb-checkpassword",
				"LF characters in checkpassword reply");
			result = USERDB_RESULT_INTERNAL_FAILURE;
		} else {
			auth_request_init_userdb_reply(request->request);
			auth_request_set_fields(request->request,
				t_strsplit(str_c(request->input_buf), "\t"),
				NULL);
		}
	}

	callback(result, request->request);

	auth_request_unref(&request->request);
	checkpassword_request_free(request);
}
示例#17
0
void test_hash_table_iterating_remove(void)
{
	HashTable *hash_table;
	HashTableIterator iterator;
	char buf[10];
	char *val;
	HashTablePair pair;
	int count;
	unsigned int removed;
	int i;

	hash_table = generate_hash_table();

	/* Iterate over all values in the table */

	count = 0;
	removed = 0;

	hash_table_iterate(hash_table, &iterator);

	while (hash_table_iter_has_more(&iterator)) {

		/* Read the next value */

		pair = hash_table_iter_next(&iterator);
		val = pair.value;

		/* Remove every hundredth entry */

		if ((atoi(val) % 100) == 0) {
			hash_table_remove(hash_table, val);
			++removed;
		}

		++count;
	}

	/* Check counts */

	assert(removed == 100);
	assert(count == NUM_TEST_VALUES);

	assert(hash_table_num_entries(hash_table)
	       == NUM_TEST_VALUES - removed);

	/* Check all entries divisible by 100 were really removed */

	for (i=0; i<NUM_TEST_VALUES; ++i) {
		sprintf(buf, "%i", i);

		if (i % 100 == 0) {
			assert(hash_table_lookup(hash_table, buf) == NULL);
		} else {
			assert(hash_table_lookup(hash_table, buf) != NULL);
		}
	}

	hash_table_free(hash_table);
}
示例#18
0
文件: nvpair.c 项目: LyonsLab/cctools
void nvpair_insert_string(struct nvpair *n, const char *name, const char *value)
{
	void *old;
	old = hash_table_remove(n->table, name);
	if(old)
		free(old);
	hash_table_insert(n->table, name, xxstrdup(value));
}
static void mail_session_disconnect(struct mail_session *session)
{
	uint8_t *guid_p = session->guid;

	hash_table_remove(mail_sessions_hash, guid_p);
	session->disconnected = TRUE;
	timeout_remove(&session->to_idle);
	mail_session_unref(&session);
}
示例#20
0
void delete_process_ht(hash_table_t * fd_mappings, int32_t pid) {
	item_t * process_ht_item;

	if ( (process_ht_item = hash_table_find(fd_mappings, &pid)) != NULL ) {
		hash_table_remove(fd_mappings, &pid);
	} else {
		ERRORPRINTF("Can not find pid %"PRIi32" when removing delete_process_ht\n", pid);
	}
}
示例#21
0
static void passwd_file_free(struct passwd_file *pw)
{
	if (hash_table_is_created(pw->db->files))
		hash_table_remove(pw->db->files, pw->path);

	passwd_file_close(pw);
	i_free(pw->path);
	i_free(pw);
}
示例#22
0
static void
dsync_mailbox_state_remove(struct dsync_brain *brain,
			   const guid_128_t mailbox_guid)
{
	const uint8_t *guid_p;

	guid_p = mailbox_guid;
	if (hash_table_lookup(brain->mailbox_states, guid_p) != NULL)
		hash_table_remove(brain->mailbox_states, guid_p);
}
示例#23
0
static void
auth_cache_node_destroy(struct auth_cache *cache, struct auth_cache_node *node)
{
	char *key = node->data;

	auth_cache_node_unlink(cache, node);

	cache->size_left += node->alloc_size;
	hash_table_remove(cache->hash, key);
	i_free(node);
}
示例#24
0
static void
init_interesting (void)
{
  /* Init the variables interesting_tags and interesting_attributes
     that are used by the HTML parser to know which tags and
     attributes we're interested in.  We initialize this only once,
     for performance reasons.

     Here we also make sure that what we put in interesting_tags
     matches the user's preferences as specified through --ignore-tags
     and --follow-tags.  */

  int i;
  interesting_tags = make_nocase_string_hash_table (countof (known_tags));

  /* First, add all the tags we know hot to handle, mapped to their
     respective entries in known_tags.  */
  for (i = 0; i < countof (known_tags); i++)
    hash_table_put (interesting_tags, known_tags[i].name, known_tags + i);

  /* Then remove the tags ignored through --ignore-tags.  */
  if (opt.ignore_tags)
    {
      char **ignored;
      for (ignored = opt.ignore_tags; *ignored; ignored++)
        hash_table_remove (interesting_tags, *ignored);
    }

  /* If --follow-tags is specified, use only those tags.  */
  if (opt.follow_tags)
    {
      /* Create a new table intersecting --follow-tags and known_tags,
         and use it as interesting_tags.  */
      struct hash_table *intersect = make_nocase_string_hash_table (0);
      char **followed;
      for (followed = opt.follow_tags; *followed; followed++)
        {
          struct known_tag *t = hash_table_get (interesting_tags, *followed);
          if (!t)
            continue;           /* ignore unknown --follow-tags entries. */
          hash_table_put (intersect, *followed, t);
        }
      hash_table_destroy (interesting_tags);
      interesting_tags = intersect;
    }

  /* Add the attributes we care about. */
  interesting_attributes = make_nocase_string_hash_table (10);
  for (i = 0; i < countof (additional_attributes); i++)
    hash_table_put (interesting_attributes, additional_attributes[i], "1");
  for (i = 0; i < countof (tag_url_attributes); i++)
    hash_table_put (interesting_attributes,
                    tag_url_attributes[i].attr_name, "1");
}
示例#25
0
static void test_remove(void)
{
    Hash_table table;

    hash_table_init(&table);
    populate(&table);

    #define VERIFY_REMOVE_NOT_EXISTS(key)              \
      {                                                \
          int v = 234;                                 \
                                                       \
          VERIFY(!hash_table_get(&table, key, &v));    \
          VERIFY(!hash_table_remove(&table, key, &v)); \
          VERIFY(!hash_table_get(&table, key, &v));    \
          VERIFY(v == 234);                            \
      }

    #define VERIFY_REMOVE_EXISTS(key)                    \
      {                                                  \
          int v1, v2;                                    \
                                                         \
          VERIFY(hash_table_get(&table, key, &v1));      \
          VERIFY(hash_table_remove(&table, key, &v2));   \
          VERIFY(!hash_table_get(&table, key, NULL));    \
          VERIFY(!hash_table_remove(&table, key, NULL)); \
          VERIFY(v1 == v2);                              \
      }

    VERIFY_REMOVE_NOT_EXISTS("foo");
    VERIFY_REMOVE_NOT_EXISTS("on");
    VERIFY_REMOVE_NOT_EXISTS("tw");
    VERIFY_REMOVE_EXISTS("negative one");
    VERIFY_REMOVE_EXISTS("zero");
    VERIFY_REMOVE_EXISTS("one");
    VERIFY_REMOVE_EXISTS("two");
    VERIFY_REMOVE_EXISTS("three");
    VERIFY_REMOVE_EXISTS("four");
    VERIFY_REMOVE_EXISTS("five");
    VERIFY_REMOVE_EXISTS("six");
    VERIFY_REMOVE_EXISTS("seven");
    VERIFY_REMOVE_EXISTS("eight");
    VERIFY_REMOVE_EXISTS("nine");
    VERIFY_REMOVE_EXISTS("ten");
    VERIFY_REMOVE_EXISTS("");

    #undef VERIFY_REMOVE_NOT_EXISTS
    #undef VERIFY_REMOVE_EXISTS

    // The case where the key exists and val is NULL
    hash_table_set(&table, "foo", 3, NULL);
    VERIFY(hash_table_remove(&table, "foo", NULL));

    hash_table_free(&table);
}
示例#26
0
struct jx * jx_database_remove( struct jx_database *db, const char *key )
{
	const char *nkey = strdup(key);

	struct jx *j = hash_table_remove(db->table,key);
	if(db->logdir && j) {
		log_delete(db,nkey);
		log_flush(db);
	}
	return j;
}
示例#27
0
struct nvpair * nvpair_database_remove( struct nvpair_database *db, const char *key )
{
	const char *nkey = strdup(key);

	struct nvpair *nv = hash_table_remove(db->table,nkey);
	if(db->logdir && nv) {
		log_delete(db,nkey);
		log_flush(db);
	}
	return nv;
} 
示例#28
0
文件: batch_job.c 项目: pbui/cctools
void batch_queue_set_feature (struct batch_queue *q, const char *what, const char *value)
{
    char *current = hash_table_remove(q->features, what);
    free(current);
    if(value) {
        hash_table_insert(q->features, what, xxstrdup(value));
        debug(D_BATCH, "set feature `%s' to `%s'", what, value);
    } else {
        debug(D_BATCH, "cleared feature `%s'", what);
    }
}
示例#29
0
文件: timer.c 项目: GNS3/dynamips
/* Free ressources used by a timer */
static inline void timer_free(timer_entry_t *timer,int take_lock)
{
   if (take_lock) TIMER_LOCK();

   /* Remove ID from hash table */
   hash_table_remove(timer_id_hash,&timer->id);

   if (take_lock) TIMER_UNLOCK();

   /* Free memory used by timer */
   free(timer);
}
示例#30
0
void test_hash_table_free_functions(void)
{
	HashTable *hash_table;
	int *key;
	int *value;
	int i;

	/* Create a hash table, fill it with values */

	hash_table = hash_table_new(int_hash, int_equal);

	hash_table_register_free_functions(hash_table, free_key, free_value);

	allocated_values = 0;

	for (i=0; i<NUM_TEST_VALUES; ++i) {
		key = new_key(i);
		value = new_value(99);

		hash_table_insert(hash_table, key, value);
	}

	assert(allocated_keys == NUM_TEST_VALUES);
	assert(allocated_values == NUM_TEST_VALUES);

	/* Check that removing a key works */

	i = NUM_TEST_VALUES / 2;
	hash_table_remove(hash_table, &i);

	assert(allocated_keys == NUM_TEST_VALUES - 1);
	assert(allocated_values == NUM_TEST_VALUES - 1);

	/* Check that replacing an existing key works */

	key = new_key(NUM_TEST_VALUES / 3);
	value = new_value(999);

	assert(allocated_keys == NUM_TEST_VALUES);
	assert(allocated_values == NUM_TEST_VALUES);

	hash_table_insert(hash_table, key, value);

	assert(allocated_keys == NUM_TEST_VALUES - 1);
	assert(allocated_values == NUM_TEST_VALUES - 1);

	/* A free of the hash table should free all of the keys and values */

	hash_table_free(hash_table);

	assert(allocated_keys == 0);
	assert(allocated_values == 0);
}