l2-unlegits/l2ooghelper/DBLayer.cpp
2012-02-01 05:25:08 +00:00

352 lines
9.1 KiB
C++

#include "stdafx.h"
#include "DBLayer.h"
#include "Logger.h"
// limits
//sqlite> select max(id) from items: 20062
//sqlite> select max(id) from skills: 26073
//sqlite> select max(id) from mobs: 36599
const unsigned int dbl_max_npc_id = 40000;
const unsigned int dbl_max_skill_id = 27000;
const unsigned int dbl_max_item_id = 25000;
TCHAR **dbl_npc_names = NULL;
TCHAR **dbl_npc_titles = NULL;
TCHAR **dbl_skill_names = NULL;
TCHAR **dbl_item_names = NULL;
int dbl_cache_hits = 0;
int dbl_cache_misses = 0;
int dbl_npcs_cached = 0;
int dbl_skills_cached = 0;
int dbl_items_cached = 0;
void DBLayer_init()
{
log_error( LOG_DEBUG, "DB Layer: init database...\n" );
//
char errmsg[256] = {0};
bool open_ok = L2Data_DB_Init( errmsg,
".\\data\\L2Detect_items.sqlite3db",
".\\data\\L2Detect_mobs.sqlite3db",
".\\data\\L2Detect_skills.sqlite3db" );
if( errmsg[0] )
{
log_error( LOG_ERROR, "L2Data_DB_Init(): says: %s\n", errmsg );
MessageBoxA( NULL, errmsg, "L2Data_DB_Init():", MB_ICONWARNING );
}
if( !open_ok )
{
log_error( LOG_ERROR, "DB Layer: database open error!\n" );
return;
}
//
log_error( LOG_OK, "DB Layer: database opened\n" );
//
dbl_cache_hits = 0;
dbl_cache_misses = 0;
dbl_npcs_cached = 0;
dbl_skills_cached = 0;
dbl_items_cached = 0;
// allocate mem
// NULL
dbl_npc_names = NULL;
dbl_npc_titles = NULL;
dbl_skill_names = NULL;
dbl_item_names = NULL;
// malloc npc names
dbl_npc_names = (TCHAR **)malloc( sizeof(TCHAR *) * dbl_max_npc_id );
if( !dbl_npc_names )
{
log_error( LOG_ERROR, "DB Layer: cannot allocate mem (1)\n" );
return;
}
// malloc npc titles
dbl_npc_titles = (TCHAR **)malloc( sizeof(TCHAR *) * dbl_max_npc_id );
if( !dbl_npc_titles )
{
free( dbl_npc_names );
dbl_npc_names = NULL;
log_error( LOG_ERROR, "DB Layer: cannot allocate mem (2)\n" );
return;
}
// malloc skill names
dbl_skill_names = (TCHAR **)malloc( sizeof(TCHAR *) * dbl_max_skill_id );
if( !dbl_skill_names )
{
free( dbl_npc_names );
free( dbl_npc_titles );
dbl_npc_names = NULL;
dbl_npc_titles = NULL;
log_error( LOG_ERROR, "DB Layer: cannot allocate mem (3)\n" );
return;
}
// malloc item names
dbl_item_names = (TCHAR **)malloc( sizeof(TCHAR *) * dbl_max_item_id );
if( !dbl_item_names )
{
free( dbl_npc_names );
free( dbl_npc_titles );
free( dbl_skill_names );
dbl_npc_names = NULL;
dbl_npc_titles = NULL;
dbl_skill_names = NULL;
log_error( LOG_ERROR, "DB Layer: cannot allocate mem (4)\n" );
return;
}
//
log_error( LOG_DEBUG, "DB cache created\n" );
int i;
for( i=0; i<dbl_max_npc_id; i++ )
{
dbl_npc_names[i] = NULL;
dbl_npc_titles[i] = NULL;
}
for( i=0; i<dbl_max_item_id; i++ ) dbl_item_names[i] = NULL;
for( i=0; i<dbl_max_skill_id; i++ ) dbl_skill_names[i] = NULL;
//
log_error( LOG_DEBUG, "DB Layer: init database end.\n" );
}
void DBLayer_free()
{
log_error( LOG_DEBUG, "DB Layer: closing database..\n" );
int i = 0;
int nfreed = 0;
// free npc names
if( dbl_npc_names )
{
nfreed = 0;
for( i=0; i<dbl_max_npc_id; i++ )
{
if( dbl_npc_names[i] )
{
free( dbl_npc_names[i] );
dbl_npc_names[i] = NULL;
nfreed++;
}
}
free( dbl_npc_names );
dbl_npc_names = NULL;
log_error( LOG_OK, "DB Layer: freed %d cached npc names\n", nfreed );
}
// free npc titles
if( dbl_npc_titles )
{
nfreed = 0;
for( i=0; i<dbl_max_npc_id; i++ )
{
if( dbl_npc_titles[i] )
{
free( dbl_npc_titles[i] );
dbl_npc_titles[i] = NULL;
nfreed++;
}
}
free( dbl_npc_titles );
dbl_npc_titles = NULL;
log_error( LOG_OK, "DB Layer: freed %d cached npc titles\n", nfreed );
}
// free skill names
if( dbl_skill_names )
{
nfreed = 0;
for( i=0; i<dbl_max_skill_id; i++ )
{
if( dbl_skill_names[i] )
{
free( dbl_skill_names[i] );
dbl_skill_names[i] = NULL;
nfreed++;
}
}
free( dbl_skill_names );
dbl_skill_names = NULL;
log_error( LOG_OK, "DB Layer: freed %d cached skill names\n", nfreed );
}
// free item names
if( dbl_item_names )
{
nfreed = 0;
for( i=0; i<dbl_max_item_id; i++ )
{
if( dbl_item_names[i] )
{
free( dbl_item_names[i] );
dbl_item_names[i] = NULL;
nfreed++;
}
}
free( dbl_item_names );
dbl_item_names = NULL;
log_error( LOG_OK, "DB Layer: freed %d cached item names\n", nfreed );
}
// close db files
L2Data_DB_Free();
log_error( LOG_DEBUG, "DB Layer: database files closed.\n" );
}
#if defined(UNICODE) || defined(_UNICODE)
// needed as analog to _strdup/_wcsdup but converting from ansi string to unicode
wchar_t *ansi_to_unicode_dup( const char *ansi )
{
if( !ansi ) return NULL;
size_t len = strlen( ansi );
wchar_t *wstr = (wchar_t *)malloc( len*2 + 2 );
if( !wstr ) return NULL;
swprintf( wstr, len*2 + 2, L"%S", ansi );
wstr[len] = 0;
return wstr;
}
#endif
void DBLayer_getItemName( unsigned int itemID, TCHAR *out, size_t maxCount )
{
if( itemID >= dbl_max_item_id )
{
log_error( LOG_ERROR, "DBLayer_getItemName(): item ID %u is above max limit %u\n",
itemID, dbl_max_item_id );
return;
}
if( dbl_item_names )
{
// check cache
if( dbl_item_names[itemID] )
{
// found in cache
_tcsncpy( out, dbl_item_names[itemID], maxCount );
out[maxCount-1] = 0;
dbl_cache_hits++;
return;
}
// not in cache :( request DB
char aname[256] = {0};
if( L2Data_DB_GetItemNamePicByID( itemID, aname, NULL ) )
{
dbl_cache_misses++;
dbl_items_cached++;
#if defined(UNICODE) || defined(_UNICODE)
dbl_item_names[itemID] = ansi_to_unicode_dup( aname );
#else
dbl_item_names[itemID] = _strdup( aname );
#endif
_tcsncpy( out, dbl_item_names[itemID], maxCount );
out[maxCount-1] = 0;
}
else log_error( LOG_ERROR, "DB: item %u not in DB!\n", itemID );
}
else log_error( LOG_ERROR, "DB Layer: no mem allocated for item names, DB init error?\n" );
}
void DBLayer_getSkillName( unsigned int skillID, TCHAR *out, size_t maxCount )
{
if( skillID >= dbl_max_skill_id )
{
log_error( LOG_ERROR, "DBLayer_getSkillName(): skill ID %u is above max limit %u\n",
skillID, dbl_max_skill_id );
return;
}
if( dbl_skill_names )
{
// check cache
if( dbl_skill_names[skillID] )
{
// found in cache
_tcsncpy( out, dbl_skill_names[skillID], maxCount );
out[maxCount-1] = 0;
dbl_cache_hits++;
return;
}
// not in cache :( request DB
char aname[256] = {0};
if( L2Data_DB_GetSkillNameByID( skillID, aname ) )
{
dbl_cache_misses++;
dbl_skills_cached++;
#if defined(UNICODE) || defined(_UNICODE)
dbl_skill_names[skillID] = ansi_to_unicode_dup( aname );
#else
dbl_skill_names[skillID] = _strdup( aname );
#endif
_tcsncpy( out, dbl_skill_names[skillID], maxCount );
out[maxCount-1] = 0;
}
else log_error( LOG_ERROR, "DB: skill %u not in DB!\n", skillID );
}
else log_error( LOG_ERROR, "DB Layer: no mem allocated for skill names, DB init error?\n" );
}
void DBLayer_getNpcNameTitle(
unsigned int npcID,
TCHAR *npcName, size_t npcNameMaxCount,
TCHAR *npcTitle, size_t npcTitleMaxCount )
{
if( npcID >= dbl_max_npc_id )
{
log_error( LOG_ERROR, "DBLayer_getNpcNameTitle(): npc ID %u is above max limit %u\n",
npcID, dbl_max_npc_id );
return;
}
if( dbl_npc_names && dbl_npc_titles )
{
// check cache
if( dbl_npc_names[npcID] )
{
// found in cache
_tcsncpy( npcName, dbl_npc_names[npcID], npcNameMaxCount );
npcName[npcNameMaxCount-1] = 0;
npcTitle[0] = 0;
// npc title can be NULL
if( dbl_npc_titles[npcID] )
{
_tcsncpy( npcTitle, dbl_npc_titles[npcID], npcTitleMaxCount );
npcTitle[npcTitleMaxCount-1] = 0;
}
dbl_cache_hits++;
return;
}
// not in cache :( request DB
char aname[256] = {0};
char atitle[256] = {0};
if( L2Data_DB_GetNPCNameTitleByID( npcID, aname, atitle ) )
{
dbl_cache_misses++;
dbl_npcs_cached++;
#if defined(UNICODE) || defined(_UNICODE)
dbl_npc_names[npcID] = ansi_to_unicode_dup( aname );
if( atitle[0] )
dbl_npc_titles[npcID] = ansi_to_unicode_dup( atitle );
#else
dbl_npc_names[npcID] = _strdup( aname );
if( atitle[0] )
dbl_npc_titles[npcID] = _strdup( atitle );
#endif
// out
_tcsncpy( npcName, dbl_npc_names[npcID], npcNameMaxCount );
npcName[npcNameMaxCount-1] = 0;
npcTitle[0] = 0;
// npc title can be NULL
if( dbl_npc_titles[npcID] )
{
_tcsncpy( npcTitle, dbl_npc_titles[npcID], npcTitleMaxCount );
npcTitle[npcTitleMaxCount-1] = 0;
}
}
else log_error( LOG_ERROR, "DB: NPC %u not in DB!\n", npcID );
}
else log_error( LOG_ERROR, "DB Layer: no mem allocated for "
"NPC names & titles, DB init error?\n" );
}
void DBLayer_printStats()
{
log_error_np( LOG_OK, "[DB] ===== Stats info: ======\n" );
log_error_np( LOG_OK, "[DB] cached (NPCs, Skills, Items) : %d, %d, %d\n",
dbl_npcs_cached, dbl_skills_cached, dbl_items_cached );
log_error_np( LOG_OK, "[DB] Cache: MISS / HIT : %d / %d\n",
dbl_cache_misses, dbl_cache_hits );
log_error_np( LOG_OK, "[DB] ===== Stats info end =====\n" );
}