summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2013-05-04 20:36:29 -0300
committershennetsind <ind@henn.et>2013-05-04 20:36:29 -0300
commit3bfadf4d2329da54f2097e1f0fafba371347465f (patch)
tree6164b506bb8591979c77d459ad3b7d6f521d424b
parent18b1965ce16909613f0a53515d40553742082ce2 (diff)
downloadhercules-3bfadf4d2329da54f2097e1f0fafba371347465f.tar.gz
hercules-3bfadf4d2329da54f2097e1f0fafba371347465f.tar.bz2
hercules-3bfadf4d2329da54f2097e1f0fafba371347465f.tar.xz
hercules-3bfadf4d2329da54f2097e1f0fafba371347465f.zip
Mapreg saving overhaul
Server only saves variables that were changed, not all of them. Special Thanks to Yommy <3~! Signed-off-by: shennetsind <ind@henn.et>
-rw-r--r--src/common/console.c19
-rw-r--r--src/map/mapreg.h14
-rw-r--r--src/map/mapreg_sql.c291
3 files changed, 208 insertions, 116 deletions
diff --git a/src/common/console.c b/src/common/console.c
index c228ab790..248dd7b45 100644
--- a/src/common/console.c
+++ b/src/common/console.c
@@ -337,15 +337,16 @@ int console_parse_timer(int tid, unsigned int tick, int id, intptr_t data) {
return 0;
}
void console_parse_final(void) {
- InterlockedDecrement(&console->ptstate);
- racond_signal(console->ptcond);
-
- /* wait for thread to close */
- rathread_wait(console->pthread, NULL);
-
- racond_destroy(console->ptcond);
- ramutex_destroy(console->ptmutex);
-
+ if( console->ptstate ) {
+ InterlockedDecrement(&console->ptstate);
+ racond_signal(console->ptcond);
+
+ /* wait for thread to close */
+ rathread_wait(console->pthread, NULL);
+
+ racond_destroy(console->ptcond);
+ ramutex_destroy(console->ptmutex);
+ }
}
void console_parse_init(void) {
cinput.count = 0;
diff --git a/src/map/mapreg.h b/src/map/mapreg.h
index d5fadafc5..e83f9e053 100644
--- a/src/map/mapreg.h
+++ b/src/map/mapreg.h
@@ -1,9 +1,19 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
#ifndef _MAPREG_H_
#define _MAPREG_H_
+struct mapreg_save {
+ int uid;
+ union {
+ int i;
+ char *str;
+ } u;
+ bool save;
+};
+
void mapreg_reload(void);
void mapreg_final(void);
void mapreg_init(void);
diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c
index 7782f7f02..bac3cea13 100644
--- a/src/map/mapreg_sql.c
+++ b/src/map/mapreg_sql.c
@@ -1,8 +1,10 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
#include "../common/cbasetypes.h"
#include "../common/db.h"
+#include "../common/ers.h"
#include "../common/malloc.h"
#include "../common/showmsg.h"
#include "../common/sql.h"
@@ -10,54 +12,69 @@
#include "../common/timer.h"
#include "map.h" // mmysql_handle
#include "script.h"
+#include "mapreg.h"
#include <stdlib.h>
#include <string.h>
static DBMap* mapreg_db = NULL; // int var_id -> int value
static DBMap* mapregstr_db = NULL; // int var_id -> char* value
+static struct eri *mapreg_ers; //[Ind/Hercules]
static char mapreg_table[32] = "mapreg";
-static bool mapreg_dirty = false;
+static bool mapreg_i_dirty = false;
+static bool mapreg_str_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 idb_iget(mapreg_db, uid);
+int mapreg_readreg(int uid) {
+ struct mapreg_save *m = idb_get(mapreg_db, uid);
+ return m?m->u.i:0;
}
/// Looks up the value of a string variable using its uid.
-char* mapreg_readregstr(int uid)
-{
- return idb_get(mapregstr_db, uid);
+char* mapreg_readregstr(int uid) {
+ struct mapreg_save *m = idb_get(mapregstr_db, uid);
+ return m?m->u.str:NULL;
}
/// Modifies the value of an integer variable.
-bool mapreg_setreg(int uid, int val)
-{
+bool mapreg_setreg(int uid, int val) {
+ struct mapreg_save *m;
int num = (uid & 0x00ffffff);
int i = (uid & 0xff000000) >> 24;
const char* name = get_str(num);
- if( val != 0 )
- {
- if( idb_iput(mapreg_db,uid,val) )
- mapreg_dirty = true; // already exists, delay write
- else if(name[1] != '@')
- {// write new variable 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);
+ if( val != 0 ) {
+ if( (m = idb_get(mapreg_db,uid)) ) {
+ m->u.i = val;
+ if(name[1] != '@') {
+ m->save = true;
+ mapreg_i_dirty = true;
+ }
+ } else {
+ m = ers_alloc(mapreg_ers, struct mapreg_save);
+
+ m->u.i = val;
+ m->uid = uid;
+ m->save = false;
+
+ if(name[1] != '@') {// write new variable 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);
+ }
+ idb_put(mapreg_db, uid, m);
+ }
+ } else { // val == 0
+ if( (m = idb_get(mapreg_db,uid)) ) {
+ ers_free(mapreg_ers, m);
}
- }
- else // val == 0
- {
idb_remove(mapreg_db,uid);
- if( name[1] != '@' )
- {// Remove from database because it is unused.
+ if( name[1] != '@' ) {// 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);
}
@@ -67,32 +84,48 @@ bool mapreg_setreg(int uid, int val)
}
/// Modifies the value of a string variable.
-bool mapreg_setregstr(int uid, const char* str)
-{
+bool mapreg_setregstr(int uid, const char* str) {
+ struct mapreg_save *m;
int num = (uid & 0x00ffffff);
int i = (uid & 0xff000000) >> 24;
const char* name = get_str(num);
- if( str == NULL || *str == 0 )
- {
+ 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);
}
+ if( (m = idb_get(mapregstr_db,uid)) ) {
+ if( m->u.str != NULL )
+ aFree(m->u.str);
+ ers_free(mapreg_ers, m);
+ }
idb_remove(mapregstr_db,uid);
- }
- else
- {
- if (idb_put(mapregstr_db,uid, aStrdup(str)))
- mapreg_dirty = true;
- 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);
+ } else {
+ if( (m = idb_get(mapregstr_db,uid)) ) {
+ if( m->u.str != NULL )
+ aFree(m->u.str);
+ m->u.str = aStrdup(str);
+ if(name[1] != '@') {
+ mapreg_str_dirty = true;
+ m->save = true;
+ }
+ } else {
+ m = ers_alloc(mapreg_ers, struct mapreg_save);
+
+ m->uid = uid;
+ m->u.str = aStrdup(str);
+ m->save = false;
+
+ if(name[1] != '@') { //put returned null, so we must insert.
+ 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);
+ }
+ idb_put(mapregstr_db, uid, m);
}
}
@@ -100,8 +133,7 @@ bool mapreg_setregstr(int uid, const char* str)
}
/// Loads permanent variables from database
-static void script_load_mapreg(void)
-{
+static void script_load_mapreg(void) {
/*
0 1 2
+-------------------------+
@@ -126,97 +158,147 @@ static void script_load_mapreg(void)
SqlStmt_BindColumn(stmt, 1, SQLDT_INT, &index, 0, NULL, NULL);
SqlStmt_BindColumn(stmt, 2, SQLDT_STRING, &value[0], sizeof(value), NULL, NULL);
- while ( SQL_SUCCESS == SqlStmt_NextRow(stmt) )
- {
+ while ( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) {
+ struct mapreg_save *m = NULL;
int s = add_str(varname);
int i = index;
- if( varname[length-1] == '$' )
- idb_put(mapregstr_db, (i<<24)|s, aStrdup(value));
- else
- idb_iput(mapreg_db, (i<<24)|s, atoi(value));
+ if( varname[length-1] == '$' ) {
+ if( idb_exists(mapregstr_db, (i<<24)|s) ) {
+ ShowWarning("load_mapreg: duplicate! '%s' => '%s' skipping...\n",varname,value);
+ continue;
+ }
+ } else {
+ if( idb_exists(mapreg_db, (i<<24)|s) ) {
+ ShowWarning("load_mapreg: duplicate! '%s' => '%s' skipping...\n",varname,value);
+ continue;
+ }
+ }
+
+ m = ers_alloc(mapreg_ers, struct mapreg_save);
+ m->uid = (i<<24)|s;
+ m->save = false;
+ if( varname[length-1] == '$' ) {
+ m->u.str = aStrdup(value);
+ idb_put(mapregstr_db, m->uid, m);
+ } else {
+ m->u.i = atoi(value);
+ idb_put(mapreg_db, m->uid, m);
+ }
}
SqlStmt_Free(stmt);
- mapreg_dirty = false;
+ mapreg_i_dirty = false;
+ mapreg_str_dirty = false;
}
/// Saves permanent variables to database
-static void script_save_mapreg(void)
-{
+static void script_save_mapreg(void) {
DBIterator* iter;
- DBData *data;
- DBKey key;
-
- iter = 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, db_data2i(data), name, i) )
- Sql_ShowDebug(mmysql_handle);
+ struct mapreg_save *m = NULL;
+
+ if( mapreg_i_dirty ) {
+ iter = db_iterator(mapreg_db);
+ for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) {
+ if( m->save ) {
+ int num = (m->uid & 0x00ffffff);
+ int i = (m->uid & 0xff000000) >> 24;
+ const char* name = get_str(num);
+
+ if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `value`='%d' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg_table, m->u.i, name, i) )
+ Sql_ShowDebug(mmysql_handle);
+ m->save = false;
+ }
+ }
+ dbi_destroy(iter);
+ mapreg_i_dirty = false;
}
- dbi_destroy(iter);
- iter = 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, db_data2ptr(data), safestrnlen(db_data2ptr(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);
+ if( mapreg_str_dirty ) {
+ iter = db_iterator(mapregstr_db);
+ for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) {
+ if( m->save ) {
+ int num = (m->uid & 0x00ffffff);
+ int i = (m->uid & 0xff000000) >> 24;
+ const char* name = get_str(num);
+ char tmp_str2[2*255+1];
+
+ Sql_EscapeStringLen(mmysql_handle, tmp_str2, m->u.str, safestrnlen(m->u.str, 255));
+ if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `value`='%s' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg_table, tmp_str2, name, i) )
+ Sql_ShowDebug(mmysql_handle);
+ m->save = false;
+ }
+ }
+ dbi_destroy(iter);
+ mapreg_str_dirty = false;
}
- dbi_destroy(iter);
-
- mapreg_dirty = false;
}
-static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr_t data)
-{
- if( mapreg_dirty )
- script_save_mapreg();
-
+static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr_t data) {
+ script_save_mapreg();
return 0;
}
-void mapreg_reload(void)
-{
- if( mapreg_dirty )
- script_save_mapreg();
+void mapreg_reload(void) {
+ DBIterator* iter;
+ struct mapreg_save *m = NULL;
+ script_save_mapreg();
+
+ iter = db_iterator(mapreg_db);
+ for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) {
+ ers_free(mapreg_ers, m);
+ }
+ dbi_destroy(iter);
+
+ iter = db_iterator(mapregstr_db);
+ for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) {
+ if( m->u.str != NULL ) {
+ aFree(m->u.str);
+ }
+ ers_free(mapreg_ers, m);
+ }
+ dbi_destroy(iter);
+
db_clear(mapreg_db);
db_clear(mapregstr_db);
script_load_mapreg();
}
-void mapreg_final(void)
-{
- if( mapreg_dirty )
- script_save_mapreg();
+void mapreg_final(void) {
+ DBIterator* iter;
+ struct mapreg_save *m = NULL;
+
+ script_save_mapreg();
+ iter = db_iterator(mapreg_db);
+ for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) {
+ ers_free(mapreg_ers, m);
+ }
+ dbi_destroy(iter);
+
+ iter = db_iterator(mapregstr_db);
+ for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) {
+ if( m->u.str != NULL ) {
+ aFree(m->u.str);
+ }
+ ers_free(mapreg_ers, m);
+ }
+ dbi_destroy(iter);
+
db_destroy(mapreg_db);
db_destroy(mapregstr_db);
+
+ ers_destroy(mapreg_ers);
}
-void mapreg_init(void)
-{
+void mapreg_init(void) {
mapreg_db = idb_alloc(DB_OPT_BASE);
- mapregstr_db = idb_alloc(DB_OPT_RELEASE_DATA);
+ mapregstr_db = idb_alloc(DB_OPT_BASE);
+ mapreg_ers = ers_new(sizeof(struct mapreg_save), "mapreg_sql.c::mapreg_ers", ERS_OPT_NONE);
script_load_mapreg();
@@ -224,8 +306,7 @@ void mapreg_init(void)
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)
-{
+bool mapreg_config_read(const char* w1, const char* w2) {
if(!strcmpi(w1, "mapreg_db"))
safestrncpy(mapreg_table, w2, sizeof(mapreg_table));
else