- Added a 1-node cache to db. Removed party_cache and guild_cache since now the database has a cache.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@9545 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
FlavioJS 2006-12-21 02:32:51 +00:00
parent 15258dfdb0
commit a2021e550b
4 changed files with 106 additions and 110 deletions

View File

@ -4,6 +4,8 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2006/12/21
* Added a 1-node cache to db. Removed party_cache and guild_cache since
now the database has a cache.
* Fixed "warning: comparison is always false due to limited range of data type"
by restricting script words to ASCII characters only.
* Moved md5calc to common. [FlavioJS]

View File

@ -1,68 +1,68 @@
/*****************************************************************************\
* Copyright (c) Athena Dev Teams - Licensed under GNU GPL *
* 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 *
* (2) Private functions *
* (3) Protected functions used internally *
* (4) Protected functions used in the interface of the database *
* (5) Public functions *
* *
* The databases are structured as a hashtable of RED-BLACK trees. *
* *
* <B>Properties of the RED-BLACK trees being used:</B> *
* 1. The value of any node is greater than the value of its left child and *
* less than the value of its right child. *
* 2. Every node is colored either RED or BLACK. *
* 3. Every red node that is not a leaf has only black children. *
* 4. Every path from the root to a leaf contains the same number of black *
* nodes. *
* 5. The root node is black. *
* An <code>n</code> node in a RED-BLACK tree has the property that its *
* height is <code>O(lg(n))</code>. *
* Another important property is that after adding a node to a RED-BLACK *
* tree, the tree can be readjusted in <code>O(lg(n))</code> time. *
* Similarly, after deleting a node from a RED-BLACK tree, the tree can be *
* readjusted in <code>O(lg(n))</code> time. *
* {@link http://www.cs.mcgill.ca/~cs251/OldCourses/1997/topic18/} *
* *
* <B>How to add new database types:</B> *
* 1. Add the identifier of the new database type to the enum DBType *
* 2. If not already there, add the data type of the key to the union DBKey *
* 3. If the key can be considered NULL, update the function db_is_key_null *
* 4. If the key can be duplicated, update the functions db_dup_key and *
* db_dup_key_free *
* 5. Create a comparator and update the function db_default_cmp *
* 6. Create a hasher and update the function db_default_hash *
* 7. If the new database type requires or does not support some options, *
* update the function db_fix_options *
* *
* TODO: *
* - create test cases to test the database system thoroughly *
* - make data an enumeration *
* - finish this header describing the database system *
* - create custom database allocator *
* - make the system thread friendly *
* - change the structure of the database to T-Trees *
* - create a db that organizes itself by splaying *
* *
* HISTORY: *
* 2.1 (Athena build #???#) - Portability fix *
* - Fixed the portability of casting to union and added the functions *
* {@link DB#ensure(DB,DBKey,DBCreateData,...)} and *
* {@link DB#clear(DB,DBApply,...)}. *
* 2.0 (Athena build 4859) - Transition version *
* - Almost everything recoded with a strategy similar to objects, *
* database structure is maintained. *
* 1.0 (up to Athena build 4706) *
* - Previous database system. *
* *
* @version 2.1 (Athena build #???#) - Portability fix *
* @author (Athena build 4859) Flavio @ Amazon Project *
* @author (up to Athena build 4706) Athena Dev Teams *
* @encoding US-ASCII *
* @see common#db.h *
* Copyright (c) Athena Dev Teams - Licensed under GNU GPL
* 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
* (2) Private functions
* (3) Protected functions used internally
* (4) Protected functions used in the interface of the database
* (5) Public functions
*
* The databases are structured as a hashtable of RED-BLACK trees.
*
* <B>Properties of the RED-BLACK trees being used:</B>
* 1. The value of any node is greater than the value of its left child and
* less than the value of its right child.
* 2. Every node is colored either RED or BLACK.
* 3. Every red node that is not a leaf has only black children.
* 4. Every path from the root to a leaf contains the same number of black
* nodes.
* 5. The root node is black.
* An <code>n</code> node in a RED-BLACK tree has the property that its
* height is <code>O(lg(n))</code>.
* Another important property is that after adding a node to a RED-BLACK
* tree, the tree can be readjusted in <code>O(lg(n))</code> time.
* Similarly, after deleting a node from a RED-BLACK tree, the tree can be
* readjusted in <code>O(lg(n))</code> time.
* {@link http://www.cs.mcgill.ca/~cs251/OldCourses/1997/topic18/}
*
* <B>How to add new database types:</B>
* 1. Add the identifier of the new database type to the enum DBType
* 2. If not already there, add the data type of the key to the union DBKey
* 3. If the key can be considered NULL, update the function db_is_key_null
* 4. If the key can be duplicated, update the functions db_dup_key and
* db_dup_key_free
* 5. Create a comparator and update the function db_default_cmp
* 6. Create a hasher and update the function db_default_hash
* 7. If the new database type requires or does not support some options,
* update the function db_fix_options
*
* TODO:
* - create test cases to test the database system thoroughly
* - make data an enumeration
* - finish this header describing the database system
* - create custom database allocator
* - make the system thread friendly
* - change the structure of the database to T-Trees
* - create a db that organizes itself by splaying
*
* HISTORY:
* 2006/12/21 - Added 1-node cache to the database.
* 2.1 (Athena build #???#) - Portability fix
* - Fixed the portability of casting to union and added the functions
* {@link DB#ensure(DB,DBKey,DBCreateData,...)} and
* {@link DB#clear(DB,DBApply,...)}.
* 2.0 (Athena build 4859) - Transition version
* - Almost everything recoded with a strategy similar to objects,
* database structure is maintained.
* 1.0 (up to Athena build 4706)
* - Previous database system.
*
* @version 2006/12/21
* @author Athena Dev team
* @encoding US-ASCII
* @see #db.h
\*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
@ -182,9 +182,10 @@ typedef struct db {
DBHasher hash;
DBReleaser release;
DBNode ht[HASH_SIZE];
DBNode cache;
DBType type;
DBOptions options;
unsigned int item_count;
uint32 item_count;
unsigned short maxlen;
unsigned global_lock : 1;
} *DB_impl;
@ -1129,6 +1130,9 @@ static void *db_obj_get(DB self, DBKey key)
return NULL; // nullpo candidate
}
if (db->cache && db->cmp(key, db->cache->key, db->maxlen) == 0)
return db->cache->data; // cache hit
db_free_lock(db);
node = db->ht[db->hash(key, db->maxlen)%HASH_SIZE];
while (node) {
@ -1142,6 +1146,7 @@ static void *db_obj_get(DB self, DBKey key)
else
node = node->right;
}
db->cache = node;
db_free_unlock(db);
return data;
}
@ -1277,6 +1282,9 @@ static void *db_obj_vensure(DB self, DBKey key, DBCreateData create, va_list arg
return NULL; // nullpo candidate
}
if (db->cache && db->cmp(key, db->cache->key, db->maxlen) == 0)
return db->cache->data; // cache hit
db_free_lock(db);
hash = db->hash(key, db->maxlen)%HASH_SIZE;
node = db->ht[hash];
@ -1293,7 +1301,7 @@ static void *db_obj_vensure(DB self, DBKey key, DBCreateData create, va_list arg
}
// Create node if necessary
if (node == NULL) {
if (db->item_count == (unsigned int)~0) {
if (db->item_count == UINT32_MAX) {
ShowError("db_vensure: item_count overflow, aborting item insertion.\n"
"Database allocated at %s:%d",
db->alloc_file, db->alloc_line);
@ -1334,6 +1342,7 @@ static void *db_obj_vensure(DB self, DBKey key, DBCreateData create, va_list arg
node->data = create(key, args);
}
data = node->data;
db->cache = node;
db_free_unlock(db);
return data;
}
@ -1408,7 +1417,7 @@ static void *db_obj_put(DB self, DBKey key, void *data)
return NULL; // nullpo candidate
}
if (db->item_count == (unsigned int)~0) {
if (db->item_count == UINT32_MAX) {
ShowError("db_put: item_count overflow, aborting item insertion.\n"
"Database allocated at %s:%d",
db->alloc_file, db->alloc_line);
@ -1471,6 +1480,7 @@ static void *db_obj_put(DB self, DBKey key, void *data)
node->key = key;
}
node->data = data;
db->cache = node;
db_free_unlock(db);
return old_data;
}
@ -1515,6 +1525,8 @@ static void *db_obj_remove(DB self, DBKey key)
c = db->cmp(key, node->key, db->maxlen);
if (c == 0) {
if (!(node->deleted)) {
if (db->cache == node)
db->cache = NULL;
data = node->data;
db->release(node->key, node->data, DB_RELEASE_DATA);
db_free_add(db, node, &db->ht[hash]);
@ -1641,6 +1653,7 @@ static int db_obj_vclear(DB self, DBApply func, va_list args)
if (db == NULL) return 0; // nullpo candidate
db_free_lock(db);
db->cache = NULL;
for (i = 0; i < HASH_SIZE; i++) {
// Apply the func and delete in the order: left tree, right tree, current node
node = db->ht[i];
@ -1750,18 +1763,10 @@ static int db_obj_vdestroy(DB self, DBApply func, va_list args)
#ifdef DB_ENABLE_STATS
switch (db->type) {
case DB_INT:
COUNT(db_int_destroy);
break;
case DB_UINT:
COUNT(db_uint_destroy);
break;
case DB_STRING:
COUNT(db_string_destroy);
break;
case DB_ISTRING:
COUNT(db_istring_destroy);
break;
case DB_INT: COUNT(db_int_destroy); break;
case DB_UINT: COUNT(db_uint_destroy); break;
case DB_STRING: COUNT(db_string_destroy); break;
case DB_ISTRING: COUNT(db_istring_destroy); break;
}
#endif /* DB_ENABLE_STATS */
db_free_lock(db);
@ -2110,6 +2115,7 @@ DB db_alloc(const char *file, int line, DBType type, DBOptions options, unsigned
db->release = db_default_release(type, options);
for (i = 0; i < HASH_SIZE; i++)
db->ht[i] = NULL;
db->cache = NULL;
db->type = type;
db->options = options;
db->item_count = 0;

View File

@ -25,12 +25,11 @@
#include "skill.h"
#include "log.h"
static struct guild* guild_cache; //For fast retrieval of the same guild over and over. [Skotlex]
static struct dbt *guild_db;
static struct dbt *castle_db;
static struct dbt *guild_expcache_db;
static struct dbt *guild_infoevent_db;
static struct dbt *guild_castleinfoevent_db;
static DB guild_db;
static DB castle_db;
static DB guild_expcache_db;
static DB guild_infoevent_db;
static DB guild_castleinfoevent_db;
struct eventlist {
char name[50];
@ -225,10 +224,7 @@ void do_init_guild(void)
// ŒŸ<C592>õ
struct guild *guild_search(int guild_id)
{
if(guild_cache && guild_cache->guild_id == guild_id)
return guild_cache;
guild_cache = idb_get(guild_db,guild_id);
return guild_cache;
return idb_get(guild_db,guild_id);
}
int guild_searchname_sub(DBKey key,void *data,va_list ap)
{
@ -1576,8 +1572,6 @@ int guild_broken(int guild_id,int flag)
guild_db->foreach(guild_db,guild_broken_sub,guild_id);
castle_db->foreach(castle_db,castle_guild_broken_sub,guild_id);
if (guild_cache && guild_cache->guild_id == guild_id)
guild_cache = NULL;
guild_storage_delete(guild_id);
idb_remove(guild_db,guild_id);
return 0;

View File

@ -22,8 +22,7 @@
#include "skill.h"
#include "status.h"
static struct dbt* party_db;
static struct party_data* party_cache = NULL; //party in cache for skipping consecutive lookups. [Skotlex]
static DB party_db;
int party_share_level = 10;
int party_send_xy_timer(int tid,unsigned int tick,int id,int data);
@ -34,13 +33,13 @@ int party_send_xy_timer(int tid,unsigned int tick,int id,int data);
*/
static void party_fill_member(struct party_member *member, struct map_session_data *sd) {
member->account_id = sd->status.account_id;
member->char_id = sd->status.char_id;
memcpy(member->name,sd->status.name,NAME_LENGTH);
member->class_ = sd->status.class_;
member->map = sd->mapindex;
member->lv = sd->status.base_level;
member->online = 1;
member->leader = 0;
member->char_id = sd->status.char_id;
memcpy(member->name, sd->status.name, NAME_LENGTH);
member->class_ = sd->status.class_;
member->map = sd->mapindex;
member->lv = sd->status.base_level;
member->online = 1;
member->leader = 0;
}
/*==========================================
@ -55,19 +54,16 @@ void do_final_party(void)
void do_init_party(void)
{
party_db=db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int));
add_timer_func_list(party_send_xy_timer,"party_send_xy_timer");
add_timer_interval(gettick()+battle_config.party_update_interval,party_send_xy_timer,0,0,battle_config.party_update_interval);
add_timer_func_list(party_send_xy_timer, "party_send_xy_timer");
add_timer_interval(gettick()+battle_config.party_update_interval, party_send_xy_timer, 0, 0, battle_config.party_update_interval);
}
// ŒŸ<C592>õ
struct party_data *party_search(int party_id)
{
if(!party_id) return NULL;
if (party_cache && party_cache->party.party_id == party_id)
return party_cache;
party_cache = idb_get(party_db,party_id);
return party_cache;
if(!party_id)
return NULL;
return idb_get(party_db,party_id);
}
int party_searchname_sub(DBKey key,void *data,va_list ap)
{
@ -449,8 +445,6 @@ int party_broken(int party_id)
p->data[i].sd->state.party_sent=0;
}
}
if (party_cache && party_cache->party.party_id == party_id)
party_cache = NULL;
idb_remove(party_db,party_id);
return 0;
}