diff options
Diffstat (limited to 'src/common/db.c')
-rw-r--r-- | src/common/db.c | 386 |
1 files changed, 280 insertions, 106 deletions
diff --git a/src/common/db.c b/src/common/db.c index 99c758a8d..f414ca04d 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -3,7 +3,7 @@ * For more information, see LICENCE in the main folder * * This file is separated in five sections: - * (1) Private typedefs, enums, structures, defines and gblobal variables + * (1) Private typedefs, enums, structures, defines and global variables * (2) Private functions * (3) Protected functions used internally * (4) Protected functions used in the interface of the database @@ -47,6 +47,7 @@ * - create a db that organizes itself by splaying * * HISTORY: + * 2013/08/25 - Added int64/uint64 support for keys [Ind/Hercules] * 2013/04/27 - Added ERS to speed up iterator memory allocation [Ind/Hercules] * 2012/03/09 - Added enum for data types (int, uint, void*) * 2008/02/19 - Fixed db_obj_get not handling deleted entries correctly. @@ -66,14 +67,18 @@ * @encoding US-ASCII * @see #db.h \*****************************************************************************/ + +#define HERCULES_CORE + +#include "db.h" + #include <stdio.h> #include <stdlib.h> -#include "db.h" -#include "../common/mmo.h" +#include "../common/ers.h" #include "../common/malloc.h" +#include "../common/mmo.h" #include "../common/showmsg.h" -#include "../common/ers.h" #include "../common/strlib.h" /*****************************************************************************\ @@ -84,15 +89,15 @@ * DBNColor - Enumeration of colors of the nodes. * * DBNode - Structure of a node in RED-BLACK trees. * * struct db_free - Structure that holds a deleted node to be freed. * - * DBMap_impl - Struture of the database. * + * DBMap_impl - Structure of the database. * * stats - Statistics about the database system. * \*****************************************************************************/ /** - * If defined statistics about database nodes, database creating/destruction - * and function usage are keept and displayed when finalizing the database + * If defined statistics about database nodes, database creating/destruction + * and function usage are kept and displayed when finalizing the database * system. - * WARNING: This adds overhead to every database operation (not shure how much). + * WARNING: This adds overhead to every database operation (not sure how much). * @private * @see #DBStats * @see #stats @@ -140,7 +145,7 @@ typedef struct dbn { // Other node_color color; unsigned deleted : 1; -} *DBNode; +} DBNode; /** * Structure that holds a deleted node. @@ -150,8 +155,8 @@ typedef struct dbn { * @see DBMap_impl#free_list */ struct db_free { - DBNode node; - DBNode *root; + DBNode *node; + DBNode **root; }; /** @@ -188,12 +193,12 @@ typedef struct DBMap_impl { unsigned int free_max; unsigned int free_lock; // Other - ERS nodes; + ERS *nodes; DBComparator cmp; DBHasher hash; DBReleaser release; - DBNode ht[HASH_SIZE]; - DBNode cache; + DBNode *ht[HASH_SIZE]; + DBNode *cache; DBType type; DBOptions options; uint32 item_count; @@ -217,7 +222,7 @@ typedef struct DBIterator_impl { struct DBIterator vtable; DBMap_impl* db; int ht_index; - DBNode node; + DBNode *node; } DBIterator_impl; #if defined(DB_ENABLE_STATS) @@ -236,10 +241,14 @@ static struct db_stats { uint32 db_uint_alloc; uint32 db_string_alloc; uint32 db_istring_alloc; + uint32 db_int64_alloc; + uint32 db_uint64_alloc; uint32 db_int_destroy; uint32 db_uint_destroy; uint32 db_string_destroy; uint32 db_istring_destroy; + uint32 db_int64_destroy; + uint32 db_uint64_destroy; // Function usage counters uint32 db_rotate_left; uint32 db_rotate_right; @@ -256,10 +265,14 @@ static struct db_stats { uint32 db_uint_cmp; uint32 db_string_cmp; uint32 db_istring_cmp; + uint32 db_int64_cmp; + uint32 db_uint64_cmp; uint32 db_int_hash; uint32 db_uint_hash; uint32 db_string_hash; uint32 db_istring_hash; + uint32 db_int64_hash; + uint32 db_uint64_hash; uint32 db_release_nothing; uint32 db_release_key; uint32 db_release_data; @@ -298,6 +311,8 @@ static struct db_stats { uint32 db_i2key; uint32 db_ui2key; uint32 db_str2key; + uint32 db_i642key; + uint32 db_ui642key; uint32 db_i2data; uint32 db_ui2data; uint32 db_ptr2data; @@ -315,7 +330,7 @@ static struct db_stats { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -#define DB_COUNTSTAT(token) if (stats. ## token != UINT32_MAX) ++stats. ## token +#define DB_COUNTSTAT(token) do { if ((stats.token) != UINT32_MAX) ++(stats.token); } while(0) #else /* !defined(DB_ENABLE_STATS) */ #define DB_COUNTSTAT(token) #endif /* !defined(DB_ENABLE_STATS) */ @@ -346,12 +361,12 @@ struct eri *db_alloc_ers; * @param node Node to be rotated * @param root Pointer to the root of the tree * @private - * @see #db_rebalance(DBNode,DBNode *) - * @see #db_rebalance_erase(DBNode,DBNode *) + * @see #db_rebalance(DBNode *,DBNode **) + * @see #db_rebalance_erase(DBNode *,DBNode **) */ -static void db_rotate_left(DBNode node, DBNode *root) +static void db_rotate_left(DBNode *node, DBNode **root) { - DBNode y = node->right; + DBNode *y = node->right; DB_COUNTSTAT(db_rotate_left); // put the left of y at the right of node @@ -377,12 +392,12 @@ static void db_rotate_left(DBNode node, DBNode *root) * @param node Node to be rotated * @param root Pointer to the root of the tree * @private - * @see #db_rebalance(DBNode,DBNode *) - * @see #db_rebalance_erase(DBNode,DBNode *) + * @see #db_rebalance(DBNode *,DBNode **) + * @see #db_rebalance_erase(DBNode *,DBNode **) */ -static void db_rotate_right(DBNode node, DBNode *root) +static void db_rotate_right(DBNode *node, DBNode **root) { - DBNode y = node->left; + DBNode *y = node->left; DB_COUNTSTAT(db_rotate_right); // put the right of y at the left of node @@ -409,13 +424,13 @@ static void db_rotate_right(DBNode node, DBNode *root) * @param node Node to be rebalanced * @param root Pointer to the root of the tree * @private - * @see #db_rotate_left(DBNode,DBNode *) - * @see #db_rotate_right(DBNode,DBNode *) + * @see #db_rotate_left(DBNode *,DBNode **) + * @see #db_rotate_right(DBNode *,DBNode **) * @see #db_obj_put(DBMap*,DBKey,DBData) */ -static void db_rebalance(DBNode node, DBNode *root) +static void db_rebalance(DBNode *node, DBNode **root) { - DBNode y; + DBNode *y; DB_COUNTSTAT(db_rebalance); // Restore the RED-BLACK properties @@ -471,16 +486,16 @@ static void db_rebalance(DBNode node, DBNode *root) * @param node Node to be erased from the tree * @param root Root of the tree * @private - * @see #db_rotate_left(DBNode,DBNode *) - * @see #db_rotate_right(DBNode,DBNode *) + * @see #db_rotate_left(DBNode *,DBNode **) + * @see #db_rotate_right(DBNode *,DBNode **) * @see #db_free_unlock(DBMap_impl*) */ -static void db_rebalance_erase(DBNode node, DBNode *root) +static void db_rebalance_erase(DBNode *node, DBNode **root) { - DBNode y = node; - DBNode x = NULL; - DBNode x_parent = NULL; - DBNode w; + DBNode *y = node; + DBNode *x = NULL; + DBNode *x_parent = NULL; + DBNode *w; DB_COUNTSTAT(db_rebalance_erase); // Select where to change the tree @@ -496,7 +511,7 @@ static void db_rebalance_erase(DBNode node, DBNode *root) } // Remove the node from the tree - if (y != node) { // both childs existed + if (y != node) { // both child existed // put the left of 'node' in the left of 'y' node->left->parent = y; y->left = node->left; @@ -507,7 +522,7 @@ static void db_rebalance_erase(DBNode node, DBNode *root) x_parent = y->parent; if (x) x->parent = y->parent; y->parent->left = x; - // put the right of 'node' in 'y' + // put the right of 'node' in 'y' y->right = node->right; node->right->parent = y; // 'y' is a direct child of 'node' @@ -635,8 +650,8 @@ static int db_is_key_null(DBType type, DBKey key) * @param key Key to be duplicated * @param Duplicated key * @private - * @see #db_free_add(DBMap_impl*,DBNode,DBNode *) - * @see #db_free_remove(DBMap_impl*,DBNode) + * @see #db_free_add(DBMap_impl*,DBNode *,DBNode **) + * @see #db_free_remove(DBMap_impl*,DBNode *) * @see #db_obj_put(DBMap*,DBKey,void *) * @see #db_dup_key_free(DBMap_impl*,DBKey) */ @@ -695,9 +710,9 @@ static void db_dup_key_free(DBMap_impl* db, DBKey key) * @see DBMap_impl#free_count * @see DBMap_impl#free_max * @see #db_obj_remove(DBMap*,DBKey) - * @see #db_free_remove(DBMap_impl*,DBNode) + * @see #db_free_remove(DBMap_impl*,DBNode *) */ -static void db_free_add(DBMap_impl* db, DBNode node, DBNode *root) +static void db_free_add(DBMap_impl* db, DBNode *node, DBNode **root) { DBKey old_key; @@ -744,9 +759,9 @@ static void db_free_add(DBMap_impl* db, DBNode node, DBNode *root) * @see DBMap_impl#free_list * @see DBMap_impl#free_count * @see #db_obj_put(DBMap*,DBKey,DBData) - * @see #db_free_add(DBMap_impl*,DBNode*,DBNode) + * @see #db_free_add(DBMap_impl*,DBNode**,DBNode*) */ -static void db_free_remove(DBMap_impl* db, DBNode node) +static void db_free_remove(DBMap_impl* db, DBNode *node) { unsigned int i; @@ -795,7 +810,7 @@ static void db_free_lock(DBMap_impl* db) * @param db Target database * @private * @see DBMap_impl#free_lock - * @see #db_free_dbn(DBNode) + * @see #db_free_dbn(DBNode*) * @see #db_lock(DBMap_impl*) */ static void db_free_unlock(DBMap_impl* db) @@ -830,10 +845,14 @@ static void db_free_unlock(DBMap_impl* db) * db_uint_cmp - Default comparator for DB_UINT databases. * * db_string_cmp - Default comparator for DB_STRING databases. * * db_istring_cmp - Default comparator for DB_ISTRING databases. * + * db_int64_cmp - Default comparator for DB_INT64 databases. * + * db_uint64_cmp - Default comparator for DB_UINT64 databases. * * db_int_hash - Default hasher for DB_INT databases. * * db_uint_hash - Default hasher for DB_UINT databases. * * db_string_hash - Default hasher for DB_STRING databases. * * db_istring_hash - Default hasher for DB_ISTRING databases. * + * db_int64_hash - Default hasher for DB_INT64 databases. * + * db_uint64_hash - Default hasher for DB_UINT64 databases. * * db_release_nothing - Releaser that releases nothing. * * db_release_key - Releaser that only releases the key. * * db_release_data - Releaser that only releases the data. * @@ -921,6 +940,51 @@ static int db_istring_cmp(DBKey key1, DBKey key2, unsigned short maxlen) } /** + * Default comparator for DB_INT64 databases. + * Compares key1 to key2. + * Return 0 if equal, negative if lower and positive if higher. + * <code>maxlen</code> is ignored. + * @param key1 Key to be compared + * @param key2 Key being compared to + * @param maxlen Maximum length of the key to hash + * @return 0 if equal, negative if lower and positive if higher + * @see DBType#DB_INT64 + * @see #DBComparator + * @see #db_default_cmp(DBType) + */ +static int db_int64_cmp(DBKey key1, DBKey key2, unsigned short maxlen) +{ + (void)maxlen;//not used + DB_COUNTSTAT(db_int64_cmp); + if (key1.i64 < key2.i64) return -1; + if (key1.i64 > key2.i64) return 1; + return 0; +} + +/** + * Default comparator for DB_UINT64 databases. + * Compares key1 to key2. + * Return 0 if equal, negative if lower and positive if higher. + * <code>maxlen</code> is ignored. + * @param key1 Key to be compared + * @param key2 Key being compared to + * @param maxlen Maximum length of the key to hash + * @return 0 if equal, negative if lower and positive if higher + * @see DBType#DB_UINT64 + * @see #DBComparator + * @see #db_default_cmp(DBType) + */ +static int db_uint64_cmp(DBKey key1, DBKey key2, unsigned short maxlen) +{ + (void)maxlen;//not used + DB_COUNTSTAT(db_uint64_cmp); + if (key1.ui64 < key2.ui64) return -1; + if (key1.ui64 > key2.ui64) return 1; + return 0; +} + + +/** * Default hasher for DB_INT databases. * Returns the value of the key as an unsigned int. * <code>maxlen</code> is ignored. @@ -931,11 +995,11 @@ static int db_istring_cmp(DBKey key1, DBKey key2, unsigned short maxlen) * @see #DBHasher * @see #db_default_hash(DBType) */ -static unsigned int db_int_hash(DBKey key, unsigned short maxlen) +static uint64 db_int_hash(DBKey key, unsigned short maxlen) { (void)maxlen;//not used DB_COUNTSTAT(db_int_hash); - return (unsigned int)key.i; + return (uint64)key.i; } /** @@ -949,11 +1013,11 @@ static unsigned int db_int_hash(DBKey key, unsigned short maxlen) * @see #DBHasher * @see #db_default_hash(DBType) */ -static unsigned int db_uint_hash(DBKey key, unsigned short maxlen) +static uint64 db_uint_hash(DBKey key, unsigned short maxlen) { (void)maxlen;//not used DB_COUNTSTAT(db_uint_hash); - return key.ui; + return (uint64)key.ui; } /** @@ -965,7 +1029,7 @@ static unsigned int db_uint_hash(DBKey key, unsigned short maxlen) * @see #DBHasher * @see #db_default_hash(DBType) */ -static unsigned int db_string_hash(DBKey key, unsigned short maxlen) +static uint64 db_string_hash(DBKey key, unsigned short maxlen) { const char *k = key.str; unsigned int hash = 0; @@ -980,7 +1044,7 @@ static unsigned int db_string_hash(DBKey key, unsigned short maxlen) break; } - return hash; + return (uint64)hash; } /** @@ -991,7 +1055,7 @@ static unsigned int db_string_hash(DBKey key, unsigned short maxlen) * @see DBType#DB_ISTRING * @see #db_default_hash(DBType) */ -static unsigned int db_istring_hash(DBKey key, unsigned short maxlen) +static uint64 db_istring_hash(DBKey key, unsigned short maxlen) { const char *k = key.str; unsigned int hash = 0; @@ -1006,7 +1070,43 @@ static unsigned int db_istring_hash(DBKey key, unsigned short maxlen) break; } - return hash; + return (uint64)hash; +} + +/** + * Default hasher for DB_INT64 databases. + * Returns the value of the key as an unsigned int. + * <code>maxlen</code> is ignored. + * @param key Key to be hashed + * @param maxlen Maximum length of the key to hash + * @return hash of the key + * @see DBType#DB_INT64 + * @see #DBHasher + * @see #db_default_hash(DBType) + */ +static uint64 db_int64_hash(DBKey key, unsigned short maxlen) +{ + (void)maxlen;//not used + DB_COUNTSTAT(db_int64_hash); + return (uint64)key.i64; +} + +/** + * Default hasher for DB_UINT64 databases. + * Just returns the value of the key. + * <code>maxlen</code> is ignored. + * @param key Key to be hashed + * @param maxlen Maximum length of the key to hash + * @return hash of the key + * @see DBType#DB_UINT64 + * @see #DBHasher + * @see #db_default_hash(DBType) + */ +static uint64 db_uint64_hash(DBKey key, unsigned short maxlen) +{ + (void)maxlen;//not used + DB_COUNTSTAT(db_uint64_hash); + return key.ui64; } /** @@ -1055,7 +1155,10 @@ static void db_release_data(DBKey key, DBData data, DBRelease which) { (void)key;//not used DB_COUNTSTAT(db_release_data); - if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) aFree(data.u.ptr); + if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) { + aFree(data.u.ptr); + data.u.ptr = NULL; + } } /** @@ -1074,7 +1177,10 @@ static void db_release_both(DBKey key, DBData data, DBRelease which) { DB_COUNTSTAT(db_release_both); if (which&DB_RELEASE_KEY) aFree((char*)key.str); // needs to be a pointer - if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) aFree(data.u.ptr); + if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) { + aFree(data.u.ptr); + data.u.ptr = NULL; + } } /*****************************************************************************\ @@ -1167,8 +1273,8 @@ DBData* dbit_obj_last(DBIterator* self, DBKey* out_key) DBData* dbit_obj_next(DBIterator* self, DBKey* out_key) { DBIterator_impl* it = (DBIterator_impl*)self; - DBNode node; - DBNode parent; + DBNode *node; + DBNode *parent; struct dbn fake; DB_COUNTSTAT(dbit_next); @@ -1243,8 +1349,8 @@ DBData* dbit_obj_next(DBIterator* self, DBKey* out_key) DBData* dbit_obj_prev(DBIterator* self, DBKey* out_key) { DBIterator_impl* it = (DBIterator_impl*)self; - DBNode node; - DBNode parent; + DBNode *node; + DBNode *parent; struct dbn fake; DB_COUNTSTAT(dbit_prev); @@ -1309,7 +1415,7 @@ DBData* dbit_obj_prev(DBIterator* self, DBKey* out_key) /** * Returns true if the fetched entry exists. - * The databases entries might have NULL data, so use this to to test if + * The databases entries might have NULL data, so use this to to test if * the iterator is done. * @param self Iterator * @return true if the entry exists @@ -1326,9 +1432,9 @@ bool dbit_obj_exists(DBIterator* self) /** * Removes the current entry from the database. - * NOTE: {@link DBIterator#exists} will return false until another entry + * NOTE: {@link DBIterator#exists} will return false until another entry * is fetched - * Puts data of the removed entry in out_data, if out_data is not NULL. + * Puts data of the removed entry in out_data, if out_data is not NULL (unless data has been released) * @param self Iterator * @param out_data Data of the removed entry. * @return 1 if entry was removed, 0 otherwise @@ -1339,7 +1445,7 @@ bool dbit_obj_exists(DBIterator* self) int dbit_obj_remove(DBIterator* self, DBData *out_data) { DBIterator_impl* it = (DBIterator_impl*)self; - DBNode node; + DBNode *node; int retval = 0; DB_COUNTSTAT(dbit_remove); @@ -1349,10 +1455,10 @@ int dbit_obj_remove(DBIterator* self, DBData *out_data) DBMap_impl* db = it->db; if( db->cache == node ) db->cache = NULL; + db->release(node->key, node->data, DB_RELEASE_DATA); if( out_data ) memcpy(out_data, &node->data, sizeof(DBData)); retval = 1; - db->release(node->key, node->data, DB_RELEASE_DATA); db_free_add(db, node, &db->ht[it->ht_index]); } return retval; @@ -1377,7 +1483,7 @@ void dbit_obj_destroy(DBIterator* self) /** * Returns a new iterator for this database. * The iterator keeps the database locked until it is destroyed. - * The database will keep functioning normally but will only free internal + * The database will keep functioning normally but will only free internal * memory when unlocked, so destroy the iterator as soon as possible. * @param self Database * @return New iterator @@ -1418,7 +1524,7 @@ static DBIterator* db_obj_iterator(DBMap* self) static bool db_obj_exists(DBMap* self, DBKey key) { DBMap_impl* db = (DBMap_impl*)self; - DBNode node; + DBNode *node; int c; bool found = false; @@ -1469,7 +1575,7 @@ static bool db_obj_exists(DBMap* self, DBKey key) static DBData* db_obj_get(DBMap* self, DBKey key) { DBMap_impl* db = (DBMap_impl*)self; - DBNode node; + DBNode *node; int c; DBData *data = NULL; @@ -1515,7 +1621,7 @@ static DBData* db_obj_get(DBMap* self, DBKey key) * It puts a maximum of <code>max</code> entries into <code>buf</code>. * If <code>buf</code> is NULL, it only counts the matches. * Returns the number of entries that matched. - * NOTE: if the value returned is greater than <code>max</code>, only the + * NOTE: if the value returned is greater than <code>max</code>, only the * first <code>max</code> entries found are put into the buffer. * @param self Interface of the database * @param buf Buffer to put the data of the matched entries @@ -1530,8 +1636,8 @@ static unsigned int db_obj_vgetall(DBMap* self, DBData **buf, unsigned int max, { DBMap_impl* db = (DBMap_impl*)self; unsigned int i; - DBNode node; - DBNode parent; + DBNode *node; + DBNode *parent; unsigned int ret = 0; DB_COUNTSTAT(db_vgetall); @@ -1586,7 +1692,7 @@ static unsigned int db_obj_vgetall(DBMap* self, DBData **buf, unsigned int max, * It puts a maximum of <code>max</code> entries into <code>buf</code>. * If <code>buf</code> is NULL, it only counts the matches. * Returns the number of entries that matched. - * NOTE: if the value returned is greater than <code>max</code>, only the + * NOTE: if the value returned is greater than <code>max</code>, only the * first <code>max</code> entries found are put into the buffer. * @param self Interface of the database * @param buf Buffer to put the data of the matched entries @@ -1614,7 +1720,7 @@ static unsigned int db_obj_getall(DBMap* self, DBData **buf, unsigned int max, D /** * Get the data of the entry identified by the key. - * If the entry does not exist, an entry is added with the data returned by + * If the entry does not exist, an entry is added with the data returned by * <code>create</code>. * @param self Interface of the database * @param key Key that identifies the entry @@ -1627,8 +1733,8 @@ static unsigned int db_obj_getall(DBMap* self, DBData **buf, unsigned int max, D static DBData* db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_list args) { DBMap_impl* db = (DBMap_impl*)self; - DBNode node; - DBNode parent = NULL; + DBNode *node; + DBNode *parent = NULL; unsigned int hash; int c = 0; DBData *data = NULL; @@ -1696,7 +1802,7 @@ static DBData* db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_li if (db->options&DB_OPT_DUP_KEY) { node->key = db_dup_key(db, key); if (db->options&DB_OPT_RELEASE_KEY) - db->release(key, *data, DB_RELEASE_KEY); + db->release(key, node->data, DB_RELEASE_KEY); } else { node->key = key; } @@ -1713,7 +1819,7 @@ static DBData* db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_li /** * Just calls {@link DBMap#vensure}. * Get the data of the entry identified by the key. - * If the entry does not exist, an entry is added with the data returned by + * If the entry does not exist, an entry is added with the data returned by * <code>create</code>. * @param self Interface of the database * @param key Key that identifies the entry @@ -1740,7 +1846,7 @@ static DBData* db_obj_ensure(DBMap* self, DBKey key, DBCreateData create, ...) /** * Put the data identified by the key in the database. - * Puts the previous data in out_data, if out_data is not NULL. + * Puts the previous data in out_data, if out_data is not NULL. (unless data has been released) * NOTE: Uses the new key, the old one is released. * @param self Interface of the database * @param key Key that identifies the data @@ -1750,12 +1856,14 @@ static DBData* db_obj_ensure(DBMap* self, DBKey key, DBCreateData create, ...) * @protected * @see #db_malloc_dbn(void) * @see DBMap#put + * FIXME: If this method fails shouldn't it return another value? + * Other functions rely on this to know if they were able to put something [Panikon] */ static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data) { DBMap_impl* db = (DBMap_impl*)self; - DBNode node; - DBNode parent = NULL; + DBNode *node; + DBNode *parent = NULL; int c = 0, retval = 0; unsigned int hash; @@ -1846,20 +1954,20 @@ static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data) /** * Remove an entry from the database. - * Puts the previous data in out_data, if out_data is not NULL. - * NOTE: The key (of the database) is released in {@link #db_free_add(DBMap_impl*,DBNode,DBNode *)}. + * Puts the previous data in out_data, if out_data is not NULL. (unless data has been released) + * NOTE: The key (of the database) is released in {@link #db_free_add(DBMap_impl*,DBNode*,DBNode **)}. * @param self Interface of the database * @param key Key that identifies the entry * @param out_data Previous data if the entry exists * @return 1 if if the entry already exists, 0 otherwise * @protected - * @see #db_free_add(DBMap_impl*,DBNode,DBNode *) + * @see #db_free_add(DBMap_impl*,DBNode*,DBNode **) * @see DBMap#remove */ static int db_obj_remove(DBMap* self, DBKey key, DBData *out_data) { DBMap_impl* db = (DBMap_impl*)self; - DBNode node; + DBNode *node; unsigned int hash; int c = 0, retval = 0; @@ -1884,10 +1992,10 @@ static int db_obj_remove(DBMap* self, DBKey key, DBData *out_data) if (!(node->deleted)) { if (db->cache == node) db->cache = NULL; + db->release(node->key, node->data, DB_RELEASE_DATA); if (out_data) memcpy(out_data, &node->data, sizeof(*out_data)); retval = 1; - db->release(node->key, node->data, DB_RELEASE_DATA); db_free_add(db, node, &db->ht[hash]); } break; @@ -1916,8 +2024,8 @@ static int db_obj_vforeach(DBMap* self, DBApply func, va_list args) DBMap_impl* db = (DBMap_impl*)self; unsigned int i; int sum = 0; - DBNode node; - DBNode parent; + DBNode *node; + DBNode *parent; DB_COUNTSTAT(db_vforeach); if (db == NULL) return 0; // nullpo candidate @@ -1964,7 +2072,7 @@ static int db_obj_vforeach(DBMap* self, DBApply func, va_list args) * Apply <code>func</code> to every entry in the database. * Returns the sum of values returned by func. * @param self Interface of the database - * @param func Function to be applyed + * @param func Function to be applied * @param ... Extra arguments for func * @return Sum of the values returned by func * @protected @@ -2002,8 +2110,8 @@ static int db_obj_vclear(DBMap* self, DBApply func, va_list args) DBMap_impl* db = (DBMap_impl*)self; int sum = 0; unsigned int i; - DBNode node; - DBNode parent; + DBNode *node; + DBNode *parent; DB_COUNTSTAT(db_vclear); if (db == NULL) return 0; // nullpo candidate @@ -2061,7 +2169,7 @@ static int db_obj_vclear(DBMap* self, DBApply func, va_list args) * Before deleting an entry, func is applied to it. * Releases the key and the data. * Returns the sum of values returned by func, if it exists. - * NOTE: This locks the database globally. Any attempt to insert or remove + * NOTE: This locks the database globally. Any attempt to insert or remove * a database entry will give an error and be aborted (except for clearing). * @param self Interface of the database * @param func Function to be applied to every entry before deleting @@ -2089,7 +2197,7 @@ static int db_obj_clear(DBMap* self, DBApply func, ...) * Finalize the database, feeing all the memory it uses. * Before deleting an entry, func is applied to it. * Returns the sum of values returned by func, if it exists. - * NOTE: This locks the database globally. Any attempt to insert or remove + * NOTE: This locks the database globally. Any attempt to insert or remove * a database entry will give an error and be aborted (except for clearing). * @param self Interface of the database * @param func Function to be applied to every entry before deleting @@ -2122,6 +2230,8 @@ static int db_obj_vdestroy(DBMap* self, DBApply func, va_list args) case DB_UINT: DB_COUNTSTAT(db_uint_destroy); break; case DB_STRING: DB_COUNTSTAT(db_string_destroy); break; case DB_ISTRING: DB_COUNTSTAT(db_istring_destroy); break; + case DB_INT64: DB_COUNTSTAT(db_int64_destroy); break; + case DB_UINT64: DB_COUNTSTAT(db_uint64_destroy); break; } #endif /* DB_ENABLE_STATS */ db_free_lock(db); @@ -2142,7 +2252,7 @@ static int db_obj_vdestroy(DBMap* self, DBApply func, va_list args) * Before deleting an entry, func is applied to it. * Releases the key and the data. * Returns the sum of values returned by func, if it exists. - * NOTE: This locks the database globally. Any attempt to insert or remove + * NOTE: This locks the database globally. Any attempt to insert or remove * a database entry will give an error and be aborted. * @param self Database * @param func Function to be applied to every entry before deleting @@ -2241,11 +2351,13 @@ static DBOptions db_obj_options(DBMap* self) * db_default_cmp - Get the default comparator for a type of database. * db_default_hash - Get the default hasher for a type of database. * db_default_release - Get the default releaser for a type of database with the specified options. - * db_custom_release - Get a releaser that behaves a certains way. + * db_custom_release - Get a releaser that behaves a certain way. * db_alloc - Allocate a new database. * db_i2key - Manual cast from 'int' to 'DBKey'. * db_ui2key - Manual cast from 'unsigned int' to 'DBKey'. * db_str2key - Manual cast from 'unsigned char *' to 'DBKey'. + * db_i642key - Manual cast from 'int64' to 'DBKey'. + * db_ui642key - Manual cast from 'uin64' to 'DBKey'. * db_i2data - Manual cast from 'int' to 'DBData'. * db_ui2data - Manual cast from 'unsigned int' to 'DBData'. * db_ptr2data - Manual cast from 'void*' to 'DBData'. @@ -2272,7 +2384,9 @@ DBOptions db_fix_options(DBType type, DBOptions options) DB_COUNTSTAT(db_fix_options); switch (type) { case DB_INT: - case DB_UINT: // Numeric database, do nothing with the keys + case DB_UINT: + case DB_INT64: + case DB_UINT64: // Numeric database, do nothing with the keys return (DBOptions)(options&~(DB_OPT_DUP_KEY|DB_OPT_RELEASE_KEY)); default: @@ -2292,6 +2406,8 @@ DBOptions db_fix_options(DBType type, DBOptions options) * @see #db_uint_cmp(DBKey,DBKey,unsigned short) * @see #db_string_cmp(DBKey,DBKey,unsigned short) * @see #db_istring_cmp(DBKey,DBKey,unsigned short) + * @see #db_int64_cmp(DBKey,DBKey,unsigned short) + * @see #db_uint64_cmp(DBKey,DBKey,unsigned short) */ DBComparator db_default_cmp(DBType type) { @@ -2301,6 +2417,8 @@ DBComparator db_default_cmp(DBType type) case DB_UINT: return &db_uint_cmp; case DB_STRING: return &db_string_cmp; case DB_ISTRING: return &db_istring_cmp; + case DB_INT64: return &db_int64_cmp; + case DB_UINT64: return &db_uint64_cmp; default: ShowError("db_default_cmp: Unknown database type %u\n", type); return NULL; @@ -2316,6 +2434,8 @@ DBComparator db_default_cmp(DBType type) * @see #db_uint_hash(DBKey,unsigned short) * @see #db_string_hash(DBKey,unsigned short) * @see #db_istring_hash(DBKey,unsigned short) + * @see #db_int64_hash(DBKey,unsigned short) + * @see #db_uint64_hash(DBKey,unsigned short) */ DBHasher db_default_hash(DBType type) { @@ -2325,6 +2445,8 @@ DBHasher db_default_hash(DBType type) case DB_UINT: return &db_uint_hash; case DB_STRING: return &db_string_hash; case DB_ISTRING: return &db_istring_hash; + case DB_INT64: return &db_int64_hash; + case DB_UINT64: return &db_uint64_hash; default: ShowError("db_default_hash: Unknown database type %u\n", type); return NULL; @@ -2332,7 +2454,7 @@ DBHasher db_default_hash(DBType type) } /** - * Returns the default releaser for the specified type of database with the + * Returns the default releaser for the specified type of database with the * specified options. * NOTE: the options are fixed with {@link #db_fix_options(DBType,DBOptions)} * before choosing the releaser. @@ -2393,7 +2515,7 @@ DBReleaser db_custom_release(DBRelease which) * @param line Line of the file where the database is being allocated * @param type Type of database * @param options Options of the database - * @param maxlen Maximum length of the string to be used as key in string + * @param maxlen Maximum length of the string to be used as key in string * databases. If 0, the maximum number of maxlen is used (64K). * @return The interface of the database * @public @@ -2412,6 +2534,8 @@ DBMap* db_alloc(const char *file, const char *func, int line, DBType type, DBOpt case DB_UINT: DB_COUNTSTAT(db_uint_alloc); break; case DB_STRING: DB_COUNTSTAT(db_string_alloc); break; case DB_ISTRING: DB_COUNTSTAT(db_istring_alloc); break; + case DB_INT64: DB_COUNTSTAT(db_int64_alloc); break; + case DB_UINT64: DB_COUNTSTAT(db_uint64_alloc); break; } #endif /* DB_ENABLE_STATS */ db = ers_alloc(db_alloc_ers, struct DBMap_impl); @@ -2446,7 +2570,7 @@ DBMap* db_alloc(const char *file, const char *func, int line, DBType type, DBOpt db->free_lock = 0; /* Other */ snprintf(ers_name, 50, "db_alloc:nodes:%s:%s:%d",func,file,line); - db->nodes = ers_new(sizeof(struct dbn),ers_name,ERS_OPT_WAIT|ERS_OPT_FREE_NAME); + db->nodes = ers_new(sizeof(struct dbn),ers_name,ERS_OPT_WAIT|ERS_OPT_FREE_NAME|ERS_OPT_CLEAN); db->cmp = DB->default_cmp(type); db->hash = DB->default_hash(type); db->release = DB->default_release(type, options); @@ -2511,6 +2635,36 @@ DBKey db_str2key(const char *key) } /** + * Manual cast from 'int64' to the union DBKey. + * @param key Key to be casted + * @return The key as a DBKey union + * @public + */ +DBKey db_i642key(int64 key) +{ + DBKey ret; + + DB_COUNTSTAT(db_i642key); + ret.i64 = key; + return ret; +} + +/** + * Manual cast from 'uin64' to the union DBKey. + * @param key Key to be casted + * @return The key as a DBKey union + * @public + */ +DBKey db_ui642key(uint64 key) +{ + DBKey ret; + + DB_COUNTSTAT(db_ui642key); + ret.ui64 = key; + return ret; +} + +/** * Manual cast from 'int' to the struct DBData. * @param data Data to be casted * @return The data as a DBData struct @@ -2609,9 +2763,10 @@ void* db_data2ptr(DBData *data) * @see #db_final(void) */ void db_init(void) { - db_iterator_ers = ers_new(sizeof(struct DBIterator_impl),"db.c::db_iterator_ers",ERS_OPT_NONE); - db_alloc_ers = ers_new(sizeof(struct DBMap_impl),"db.c::db_alloc_ers",ERS_OPT_NONE); + db_iterator_ers = ers_new(sizeof(struct DBIterator_impl),"db.c::db_iterator_ers",ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK); + db_alloc_ers = ers_new(sizeof(struct DBMap_impl),"db.c::db_alloc_ers",ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK); ers_chunk_size(db_alloc_ers, 50); + ers_chunk_size(db_iterator_ers, 10); DB_COUNTSTAT(db_init); } @@ -2631,11 +2786,15 @@ void db_final(void) "DB_INT : allocated %10u, destroyed %10u\n" "DB_UINT : allocated %10u, destroyed %10u\n" "DB_STRING : allocated %10u, destroyed %10u\n" - "DB_ISTRING : allocated %10u, destroyed %10u\n", + "DB_ISTRING : allocated %10u, destroyed %10u\n" + "DB_INT64 : allocated %10u, destroyed %10u\n" + "DB_UINT64 : allocated %10u, destroyed %10u\n", stats.db_int_alloc, stats.db_int_destroy, stats.db_uint_alloc, stats.db_uint_destroy, stats.db_string_alloc, stats.db_string_destroy, - stats.db_istring_alloc, stats.db_istring_destroy); + stats.db_istring_alloc, stats.db_istring_destroy, + stats.db_int64_alloc, stats.db_int64_destroy, + stats.db_uint64_alloc, stats.db_uint64_destroy); ShowInfo(CL_WHITE"Database function counters"CL_RESET":\n" "db_rotate_left %10u, db_rotate_right %10u,\n" "db_rebalance %10u, db_rebalance_erase %10u,\n" @@ -2645,8 +2804,10 @@ void db_final(void) "db_free_lock %10u, db_free_unlock %10u,\n" "db_int_cmp %10u, db_uint_cmp %10u,\n" "db_string_cmp %10u, db_istring_cmp %10u,\n" + "db_int64_cmp %10u, db_uint64_cmp %10u,\n" "db_int_hash %10u, db_uint_hash %10u,\n" "db_string_hash %10u, db_istring_hash %10u,\n" + "db_int64_hash %10u, db_uint64_hash %10u,\n" "db_release_nothing %10u, db_release_key %10u,\n" "db_release_data %10u, db_release_both %10u,\n" "dbit_first %10u, dbit_last %10u,\n" @@ -2666,6 +2827,7 @@ void db_final(void) "db_default_release %10u, db_custom_release %10u,\n" "db_alloc %10u, db_i2key %10u,\n" "db_ui2key %10u, db_str2key %10u,\n" + "db_i642key %10u, db_ui642key %10u,\n" "db_i2data %10u, db_ui2data %10u,\n" "db_ptr2data %10u, db_data2i %10u,\n" "db_data2ui %10u, db_data2ptr %10u,\n" @@ -2678,8 +2840,10 @@ void db_final(void) stats.db_free_lock, stats.db_free_unlock, stats.db_int_cmp, stats.db_uint_cmp, stats.db_string_cmp, stats.db_istring_cmp, + stats.db_int64_cmp, stats.db_uint64_cmp, stats.db_int_hash, stats.db_uint_hash, stats.db_string_hash, stats.db_istring_hash, + stats.db_int64_hash, stats.db_uint64_hash, stats.db_release_nothing, stats.db_release_key, stats.db_release_data, stats.db_release_both, stats.dbit_first, stats.dbit_last, @@ -2699,6 +2863,7 @@ void db_final(void) stats.db_default_release, stats.db_custom_release, stats.db_alloc, stats.db_i2key, stats.db_ui2key, stats.db_str2key, + stats.db_i642key, stats.db_ui642key, stats.db_i2data, stats.db_ui2data, stats.db_ptr2data, stats.db_data2i, stats.db_data2ui, stats.db_data2ptr, @@ -2730,20 +2895,26 @@ void linkdb_insert( struct linkdb_node** head, void *key, void* data) node->data = data; } -void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... ) -{ +void linkdb_vforeach( struct linkdb_node** head, LinkDBFunc func, va_list ap) { struct linkdb_node *node; if( head == NULL ) return; node = *head; while ( node ) { - va_list args; - va_start(args, func); - func( node->key, node->data, args ); - va_end(args); + va_list argscopy; + va_copy(argscopy, ap); + func(node->key, node->data, argscopy); + va_end(argscopy); node = node->next; } } +void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ...) { + va_list ap; + va_start(ap, func); + linkdb_vforeach(head, func, ap); + va_end(ap); +} + void* linkdb_search( struct linkdb_node** head, void *key) { int n = 0; @@ -2849,4 +3020,7 @@ void db_defaults(void) { DB->str2key = db_str2key; DB->ui2data = db_ui2data; DB->ui2key = db_ui2key; + DB->i642key = db_i642key; + DB->ui642key = db_ui642key; + } |