From 0d67a194537e8e69426c8f55ced61b0a8701e90a Mon Sep 17 00:00:00 2001 From: ultramage Date: Fri, 15 Aug 2008 11:14:45 +0000 Subject: Split off mapreg code from script.c * new mapserver files, mapreg.h, mapreg_txt.c, mapreg_sql.c * removed MAPREGSQL from project files / makefiles * mapreg storage engine is now fully dependent on the server type * added config settings mapreg_txt and mapreg_db to inter config * added get_str() function to complement add_str() * fixed txt mapreg code allowing too long variable names git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@13081 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/mapreg_sql.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 src/map/mapreg_sql.c (limited to 'src/map/mapreg_sql.c') diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c new file mode 100644 index 000000000..401367611 --- /dev/null +++ b/src/map/mapreg_sql.c @@ -0,0 +1,242 @@ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "../common/cbasetypes.h" +#include "../common/db.h" +#include "../common/malloc.h" +#include "../common/showmsg.h" +#include "../common/sql.h" +#include "../common/strlib.h" +#include "../common/timer.h" +#include "map.h" // mmysql_handle +#include "script.h" +#include +#include + +static DBMap* mapreg_db = NULL; // int var_id -> int value +static DBMap* mapregstr_db = NULL; // int var_id -> char* value + +static char mapreg_table[32] = "mapreg"; +static bool mapreg_dirty = false; +#define MAPREG_AUTOSAVE_INTERVAL (300*1000) + + +/// Looks up the value of an integer variable using its uid. +int mapreg_readreg(int uid) +{ + return (int)idb_get(mapreg_db, uid); +} + +/// Looks up the value of a string variable using its uid. +char* mapreg_readregstr(int uid) +{ + return (char*)idb_get(mapregstr_db, uid); +} + +/// Modifies the value of an integer variable. +bool mapreg_setreg(int uid, int val) +{ + int num = uid & 0x00ffffff; + int i = uid & 0xff000000 >> 24; + const char* name = get_str(num); + + if( val != 0 ) + { + if( idb_put(mapreg_db,uid,(void*)val) ) + ; // already exists, delay write + else + if( name[1] == '@' ) + ; // nothing more to do + else + {// write new wariable to database + char tmp_str[32*2+1]; + Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32)); + if( SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%d')", mapreg_table, tmp_str, i, val) ) + Sql_ShowDebug(mmysql_handle); + } + } + else // val == 0 + { + idb_remove(mapreg_db,uid); + + if( name[1] == '@' ) + ; // nothing more to do + else + {// Remove from database because it is unused. + if( SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i) ) + Sql_ShowDebug(mmysql_handle); + } + } + + mapreg_dirty = true; + return true; +} + +/// Modifies the value of a string variable. +bool mapreg_setregstr(int uid, const char* str) +{ + int num = uid & 0x00ffffff; + int i = uid & 0xff000000 >> 24; + const char* name = get_str(num); + + if( str == NULL || *str == 0 ) + { + if(name[1] != '@') { + if( SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i) ) + Sql_ShowDebug(mmysql_handle); + } + idb_remove(mapregstr_db,uid); + } + else + { + if (idb_put(mapregstr_db,uid, aStrdup(str))) + ; + else if(name[1] != '@') { //put returned null, so we must insert. + // Someone is causing a database size infinite increase here without name[1] != '@' [Lance] + char tmp_str[32*2+1]; + char tmp_str2[255*2+1]; + Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32)); + Sql_EscapeStringLen(mmysql_handle, tmp_str2, str, strnlen(str, 255)); + if( SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%s')", mapreg_table, tmp_str, i, tmp_str2) ) + Sql_ShowDebug(mmysql_handle); + } + } + + mapreg_dirty = true; + return true; +} + +/// Loads permanent variables from database +static void script_load_mapreg(void) +{ + /* + 0 1 2 + +-------------------------+ + | varname | index | value | + +-------------------------+ + */ + SqlStmt* stmt = SqlStmt_Malloc(mmysql_handle); + char varname[32+1]; + int index; + char value[255+1]; + uint32 length; + + if ( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `varname`, `index`, `value` FROM `%s`", mapreg_table) + || SQL_ERROR == SqlStmt_Execute(stmt) + ) { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + return; + } + + SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &varname[0], 32, &length, NULL); + SqlStmt_BindColumn(stmt, 1, SQLDT_INT, &index, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 2, SQLDT_STRING, &value[0], 255, NULL, NULL); + + while ( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) + { + int s = add_str(varname); + int i = index; + + if( varname[length-1] == '$' ) + idb_put(mapregstr_db, (i<<24)|s, aStrdup(value)); + else + idb_put(mapreg_db, (i<<24)|s, (void *)atoi(value)); + } + + SqlStmt_Free(stmt); + + mapreg_dirty = false; +} + +/// Saves permanent variables to database +static void script_save_mapreg(void) +{ + DBIterator* iter; + void* data; + DBKey key; + + iter = mapreg_db->iterator(mapreg_db); + for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) + { + int num = key.i & 0x00ffffff; + int i = key.i & 0xff000000 >> 24; + const char* name = get_str(num); + + if( name[1] == '@' ) + continue; + + if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `value`='%d' WHERE `varname`='%s' AND `index`='%d'", mapreg_table, (int)data, name, i) ) + Sql_ShowDebug(mmysql_handle); + } + iter->destroy(iter); + + iter = mapregstr_db->iterator(mapregstr_db); + for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) + { + int num = key.i & 0x00ffffff; + int i = key.i & 0xff000000 >> 24; + const char* name = get_str(num); + char tmp_str2[2*255+1]; + + if( name[1] == '@' ) + continue; + + Sql_EscapeStringLen(mmysql_handle, tmp_str2, (char*)data, safestrnlen((char*)data, 255)); + if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `value`='%s' WHERE `varname`='%s' AND `index`='%d'", mapreg_table, tmp_str2, name, i) ) + Sql_ShowDebug(mmysql_handle); + } + iter->destroy(iter); + + mapreg_dirty = false; +} + +static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr data) +{ + if( mapreg_dirty ) + script_save_mapreg(); + + return 0; +} + + +void mapreg_reload(void) +{ + if( mapreg_dirty ) + script_save_mapreg(); + + mapreg_db->clear(mapreg_db, NULL); + mapregstr_db->clear(mapregstr_db, NULL); + + script_load_mapreg(); +} + +void mapreg_final(void) +{ + if( mapreg_dirty ) + script_save_mapreg(); + + mapreg_db->destroy(mapreg_db,NULL); + mapregstr_db->destroy(mapregstr_db,NULL); +} + +void mapreg_init(void) +{ + mapreg_db = idb_alloc(DB_OPT_BASE); + mapregstr_db = idb_alloc(DB_OPT_RELEASE_DATA); + + script_load_mapreg(); + + add_timer_func_list(script_autosave_mapreg, "script_autosave_mapreg"); + add_timer_interval(gettick() + MAPREG_AUTOSAVE_INTERVAL, script_autosave_mapreg, 0, 0, MAPREG_AUTOSAVE_INTERVAL); +} + +bool mapreg_config_read(const char* w1, const char* w2) +{ + if(!strcmpi(w1, "mapreg_db")) + safestrncpy(mapreg_table, w2, sizeof(mapreg_table)); + else + return false; + + return true; +} -- cgit v1.2.3-60-g2f50