1 |
/* |
2 |
** Copyright (C) 2002 by Kevin L. Mitchell <klmitch@mit.edu> |
3 |
** |
4 |
** This library is free software; you can redistribute it and/or |
5 |
** modify it under the terms of the GNU Library General Public |
6 |
** License as published by the Free Software Foundation; either |
7 |
** version 2 of the License, or (at your option) any later version. |
8 |
** |
9 |
** This library is distributed in the hope that it will be useful, |
10 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 |
** Library General Public License for more details. |
13 |
** |
14 |
** You should have received a copy of the GNU Library General Public |
15 |
** License along with this library; if not, write to the Free |
16 |
** Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
17 |
** MA 02111-1307, USA |
18 |
** |
19 |
** @(#)$Id: ht_add.c,v 1.2 2003/06/12 01:10:04 klmitch Exp $ |
20 |
*/ |
21 |
#include "dbprim.h" |
22 |
#include "dbprim_int.h" |
23 |
|
24 |
RCSTAG("@(#)$Id: ht_add.c,v 1.2 2003/06/12 01:10:04 klmitch Exp $"); |
25 |
|
26 |
/** \ingroup dbprim_hash |
27 |
* \brief Add an entry to a hash table. |
28 |
* |
29 |
* This function adds an entry to a hash table. |
30 |
* |
31 |
* \param table A pointer to a #hash_table_t. |
32 |
* \param entry A pointer to a #hash_entry_t to be added to the |
33 |
* table. |
34 |
* \param key A pointer to a #db_key_t containing the key for the |
35 |
* entry. |
36 |
* |
37 |
* \retval DB_ERR_BADARGS An invalid argument was given. |
38 |
* \retval DB_ERR_BUSY The entry is already in a table. |
39 |
* \retval DB_ERR_FROZEN The table is currently frozen. |
40 |
* \retval DB_ERR_NOTABLE The bucket table has not been |
41 |
* allocated and automatic growth is not |
42 |
* enabled. |
43 |
* \retval DB_ERR_DUPLICATE The entry is a duplicate of an |
44 |
* existing entry. |
45 |
* \retval DB_ERR_UNRECOVERABLE An unrecoverable error occurred while |
46 |
* resizing the table. |
47 |
*/ |
48 |
unsigned long |
49 |
ht_add(hash_table_t *table, hash_entry_t *entry, db_key_t *key) |
50 |
{ |
51 |
unsigned long retval; |
52 |
|
53 |
initialize_dbpr_error_table(); /* initialize error table */ |
54 |
|
55 |
if (!ht_verify(table) || !he_verify(entry) || !key) /* verify arguments */ |
56 |
return DB_ERR_BADARGS; |
57 |
|
58 |
if (entry->he_table) /* it's already in a table... */ |
59 |
return DB_ERR_BUSY; |
60 |
|
61 |
if (table->ht_flags & HASH_FLAG_FREEZE) /* don't add to frozen tables */ |
62 |
return DB_ERR_FROZEN; |
63 |
|
64 |
if (!table->ht_table && !(table->ht_flags & HASH_FLAG_AUTOGROW)) |
65 |
return DB_ERR_NOTABLE; |
66 |
|
67 |
/* It looks like we could optimize here, but don't be deceived--the table |
68 |
* may grow between here and when we fill in the entry's hash value, and |
69 |
* that would change the hash value. |
70 |
*/ |
71 |
if (!ht_find(table, 0, key)) /* don't permit duplicates */ |
72 |
return DB_ERR_DUPLICATE; |
73 |
|
74 |
/* increment element count and grow the table if necessary and allowed */ |
75 |
if (++table->ht_count > table->ht_rollover && |
76 |
(table->ht_flags & HASH_FLAG_AUTOGROW) && |
77 |
(retval = ht_resize(table, 0))) |
78 |
return retval; |
79 |
|
80 |
/* Force the link element to point to the entry */ |
81 |
le_object(&entry->he_elem) = entry; |
82 |
|
83 |
/* copy key value into the hash entry */ |
84 |
entry->he_key = *key; /* thank goodness for structure copy! */ |
85 |
|
86 |
/* get the hash value for the entry */ |
87 |
entry->he_hash = |
88 |
(*table->ht_func)(table, &entry->he_key) % table->ht_modulus; |
89 |
|
90 |
/* Now add the entry to the table... */ |
91 |
if ((retval = ll_add(&table->ht_table[entry->he_hash], &entry->he_elem, |
92 |
LINK_LOC_HEAD, 0))) { |
93 |
table->ht_count--; /* decrement the count--don't worry about shrinking */ |
94 |
return retval; |
95 |
} |
96 |
|
97 |
entry->he_table = table; /* point entry at table */ |
98 |
|
99 |
return 0; |
100 |
} |