summaryrefslogtreecommitdiff
path: root/src/common/db.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/db.c')
-rw-r--r--src/common/db.c91
1 files changed, 68 insertions, 23 deletions
diff --git a/src/common/db.c b/src/common/db.c
index 595ed241d..c9b124455 100644
--- a/src/common/db.c
+++ b/src/common/db.c
@@ -67,13 +67,13 @@
\*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include "db.h"
#include "../common/mmo.h"
#include "../common/malloc.h"
#include "../common/showmsg.h"
#include "../common/ers.h"
+#include "../common/strlib.h"
/*****************************************************************************\
* (1) Private typedefs, enums, structures, defines and global variables of *
@@ -271,6 +271,7 @@ static struct db_stats {
uint32 dbit_remove;
uint32 dbit_destroy;
uint32 db_iterator;
+ uint32 db_exists;
uint32 db_get;
uint32 db_getall;
uint32 db_vgetall;
@@ -304,7 +305,7 @@ static struct db_stats {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 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
#else /* !defined(DB_ENABLE_STATS) */
@@ -630,19 +631,17 @@ static int db_is_key_null(DBType type, DBKey key)
static DBKey db_dup_key(DBMap_impl* db, DBKey key)
{
char *str;
+ size_t len;
DB_COUNTSTAT(db_dup_key);
switch (db->type) {
case DB_STRING:
case DB_ISTRING:
- if (db->maxlen) {
- CREATE(str, char, db->maxlen +1);
- strncpy(str, key.str, db->maxlen);
- str[db->maxlen] = '\0';
- key.str = str;
- } else {
- key.str = (char *)aStrdup(key.str);
- }
+ len = strnlen(key.str, db->maxlen);
+ str = (char*)aMalloc(len + 1);
+ memcpy(str, key.str, len);
+ str[len] = '\0';
+ key.str = str;
return key;
default:
@@ -888,8 +887,6 @@ static int db_uint_cmp(DBKey key1, DBKey key2, unsigned short maxlen)
static int db_string_cmp(DBKey key1, DBKey key2, unsigned short maxlen)
{
DB_COUNTSTAT(db_string_cmp);
- if (maxlen == 0)
- maxlen = UINT16_MAX;
return strncmp((const char *)key1.str, (const char *)key2.str, maxlen);
}
@@ -908,8 +905,6 @@ static int db_string_cmp(DBKey key1, DBKey key2, unsigned short maxlen)
static int db_istring_cmp(DBKey key1, DBKey key2, unsigned short maxlen)
{
DB_COUNTSTAT(db_istring_cmp);
- if (maxlen == 0)
- maxlen = UINT16_MAX;
return strncasecmp((const char *)key1.str, (const char *)key2.str, maxlen);
}
@@ -951,7 +946,6 @@ static unsigned int db_uint_hash(DBKey key, unsigned short maxlen)
/**
* Default hasher for DB_STRING databases.
- * If maxlen if 0, the maximum number of maxlen is used instead.
* @param key Key to be hashed
* @param maxlen Maximum length of the key to hash
* @return hash of the key
@@ -966,8 +960,6 @@ static unsigned int db_string_hash(DBKey key, unsigned short maxlen)
unsigned short i;
DB_COUNTSTAT(db_string_hash);
- if (maxlen == 0)
- maxlen = UINT16_MAX;
for (i = 0; *k; ++i) {
hash = (hash*33 + ((unsigned char)*k))^(hash>>24);
@@ -981,7 +973,6 @@ static unsigned int db_string_hash(DBKey key, unsigned short maxlen)
/**
* Default hasher for DB_ISTRING databases.
- * If maxlen if 0, the maximum number of maxlen is used instead.
* @param key Key to be hashed
* @param maxlen Maximum length of the key to hash
* @return hash of the key
@@ -995,8 +986,6 @@ static unsigned int db_istring_hash(DBKey key, unsigned short maxlen)
unsigned short i;
DB_COUNTSTAT(db_istring_hash);
- if (maxlen == 0)
- maxlen = UINT16_MAX;
for (i = 0; *k; i++) {
hash = (hash*33 + ((unsigned char)TOLOWER(*k)))^(hash>>24);
@@ -1087,6 +1076,7 @@ static void db_release_both(DBKey key, void *data, DBRelease which)
* dbit_obj_destroy - Destroys the iterator, unlocking the database and *
* freeing used memory. *
* db_obj_iterator - Return a new databse iterator. *
+ * db_obj_exists - Checks if an entry exists. *
* db_obj_get - Get the data identified by the key. *
* db_obj_vgetall - Get the data of the matched entries. *
* db_obj_getall - Get the data of the matched entries. *
@@ -1402,6 +1392,57 @@ static DBIterator* db_obj_iterator(DBMap* self)
}
/**
+ * Returns true if the entry exists.
+ * @param self Interface of the database
+ * @param key Key that identifies the entry
+ * @return true is the entry exists
+ * @protected
+ * @see DBMap#exists
+ */
+static bool db_obj_exists(DBMap* self, DBKey key)
+{
+ DBMap_impl* db = (DBMap_impl*)self;
+ DBNode node;
+ int c;
+ bool found = false;
+
+ DB_COUNTSTAT(db_exists);
+ if (db == NULL) return false; // nullpo candidate
+ if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) {
+ return false; // nullpo candidate
+ }
+
+ if (db->cache && db->cmp(key, db->cache->key, db->maxlen) == 0) {
+#if defined(DEBUG)
+ if (db->cache->deleted) {
+ ShowDebug("db_exists: Cache contains a deleted node. Please report this!!!\n");
+ return false;
+ }
+#endif
+ return true; // cache hit
+ }
+
+ db_free_lock(db);
+ node = db->ht[db->hash(key, db->maxlen)%HASH_SIZE];
+ while (node) {
+ c = db->cmp(key, node->key, db->maxlen);
+ if (c == 0) {
+ if (!(node->deleted)) {
+ db->cache = node;
+ found = true;
+ }
+ break;
+ }
+ if (c < 0)
+ node = node->left;
+ else
+ node = node->right;
+ }
+ db_free_unlock(db);
+ return found;
+}
+
+/**
* Get the data of the entry identifid by the key.
* @param self Interface of the database
* @param key Key that identifies the entry
@@ -2326,7 +2367,7 @@ DBReleaser db_custom_release(DBRelease which)
* @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
- * databases
+ * databases. If 0, the maximum number of maxlen is used (64K).
* @return The interface of the database
* @public
* @see #DBMap_impl
@@ -2351,6 +2392,7 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi
options = db_fix_options(type, options);
/* Interface of the database */
db->vtable.iterator = db_obj_iterator;
+ db->vtable.exists = db_obj_exists;
db->vtable.get = db_obj_get;
db->vtable.getall = db_obj_getall;
db->vtable.vgetall = db_obj_vgetall;
@@ -2389,6 +2431,9 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi
db->maxlen = maxlen;
db->global_lock = 0;
+ if( db->maxlen == 0 && (type == DB_STRING || type == DB_ISTRING) )
+ db->maxlen = UINT16_MAX;
+
return &db->vtable;
}
@@ -2493,7 +2538,7 @@ void db_final(void)
"dbit_next %10u, dbit_prev %10u,\n"
"dbit_exists %10u, dbit_remove %10u,\n"
"dbit_destroy %10u, db_iterator %10u,\n"
- "db_get %10u,\n"
+ "db_exits %10u, db_get %10u,\n"
"db_getall %10u, db_vgetall %10u,\n"
"db_ensure %10u, db_vensure %10u,\n"
"db_put %10u, db_remove %10u,\n"
@@ -2523,7 +2568,7 @@ void db_final(void)
stats.dbit_next, stats.dbit_prev,
stats.dbit_exists, stats.dbit_remove,
stats.dbit_destroy, stats.db_iterator,
- stats.db_get,
+ stats.db_exists, stats.db_get,
stats.db_getall, stats.db_vgetall,
stats.db_ensure, stats.db_vensure,
stats.db_put, stats.db_remove,