summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt2
-rw-r--r--src/char_sql/char.c85
2 files changed, 63 insertions, 24 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index 13cd831fa..0c62e3882 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -1,5 +1,7 @@
Date Added
+2011/08/30
+ * Corrected SQL saving so that the server won't update the 'saved' data if there is an SQL error. It should fix possible dupes and other data synch issues when the SQL server is temporarily down during save. [Skotlex]
2011/08/23
* Rewrote the combo logic. Now it uses packet 0x7e1 to signal skill state changes rather than resending the whole skill list. [Skotlex]
2011/08/21
diff --git a/src/char_sql/char.c b/src/char_sql/char.c
index 535338177..f7c9e0fa0 100644
--- a/src/char_sql/char.c
+++ b/src/char_sql/char.c
@@ -409,6 +409,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
int diff = 0;
char save_status[128]; //For displaying save information. [Skotlex]
struct mmo_charstatus *cp;
+ int errors = 0; //If there are any errors while saving, "cp" will not be updated at the end.
StringBuf buf;
if (char_id!=p->char_id) return 0;
@@ -425,22 +426,28 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
//map inventory data
if( memcmp(p->inventory, cp->inventory, sizeof(p->inventory)) )
{
- memitemdata_to_sql(p->inventory, MAX_INVENTORY, p->char_id, TABLE_INVENTORY);
- strcat(save_status, " inventory");
+ if (!memitemdata_to_sql(p->inventory, MAX_INVENTORY, p->char_id, TABLE_INVENTORY))
+ strcat(save_status, " inventory");
+ else
+ errors++;
}
//map cart data
if( memcmp(p->cart, cp->cart, sizeof(p->cart)) )
{
- memitemdata_to_sql(p->cart, MAX_CART, p->char_id, TABLE_CART);
- strcat(save_status, " cart");
+ if (!memitemdata_to_sql(p->cart, MAX_CART, p->char_id, TABLE_CART))
+ strcat(save_status, " cart");
+ else
+ errors++;
}
//map storage data
if( memcmp(p->storage.items, cp->storage.items, sizeof(p->storage.items)) )
{
- memitemdata_to_sql(p->storage.items, MAX_STORAGE, p->account_id, TABLE_STORAGE);
- strcat(save_status, " storage");
+ if (!memitemdata_to_sql(p->storage.items, MAX_STORAGE, p->account_id, TABLE_STORAGE))
+ strcat(save_status, " storage");
+ else
+ errors++;
}
#ifdef TXT_SQL_CONVERT
@@ -452,9 +459,9 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
char_db, p->char_id, p->account_id, p->slot, esc_name) )
{
Sql_ShowDebug(sql_handle);
- }
-
- strcat(save_status, " creation");
+ errors++;
+ } else
+ strcat(save_status, " creation");
}
#endif
@@ -499,8 +506,9 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
p->account_id, p->char_id) )
{
Sql_ShowDebug(sql_handle);
- }
- strcat(save_status, " status");
+ errors++;
+ } else
+ strcat(save_status, " status");
}
//Values that will seldom change (to speed up saving)
@@ -525,9 +533,9 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
p->account_id, p->char_id) )
{
Sql_ShowDebug(sql_handle);
- }
-
- strcat(save_status, " status2");
+ errors++;
+ } else
+ strcat(save_status, " status2");
}
/* Mercenary Owner */
@@ -536,8 +544,10 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
(p->spear_calls != cp->spear_calls) || (p->spear_faith != cp->spear_faith) ||
(p->sword_calls != cp->sword_calls) || (p->sword_faith != cp->sword_faith) )
{
- mercenary_owner_tosql(char_id, p);
- strcat(save_status, " mercenary");
+ if (mercenary_owner_tosql(char_id, p))
+ strcat(save_status, " mercenary");
+ else
+ errors++;
}
//memo points
@@ -547,7 +557,10 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
//`memo` (`memo_id`,`char_id`,`map`,`x`,`y`)
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", memo_db, p->char_id) )
+ {
Sql_ShowDebug(sql_handle);
+ errors++;
+ }
//insert here.
StringBuf_Clear(&buf);
@@ -566,9 +579,11 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
if( count )
{
if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
+ {
Sql_ShowDebug(sql_handle);
+ errors++;
+ }
}
-
strcat(save_status, " memo");
}
@@ -583,7 +598,10 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
{
//`skill` (`char_id`, `id`, `lv`)
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, p->char_id) )
+ {
Sql_ShowDebug(sql_handle);
+ errors++;
+ }
StringBuf_Clear(&buf);
StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`) VALUES ", skill_db);
@@ -601,7 +619,10 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
if( count )
{
if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
+ {
Sql_ShowDebug(sql_handle);
+ errors++;
+ }
}
strcat(save_status, " skills");
@@ -619,7 +640,10 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
if(diff == 1)
{ //Save friends
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", friend_db, char_id) )
+ {
Sql_ShowDebug(sql_handle);
+ errors++;
+ }
StringBuf_Clear(&buf);
StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `friend_account`, `friend_id`) VALUES ", friend_db);
@@ -636,12 +660,12 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
if( count )
{
if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
+ {
Sql_ShowDebug(sql_handle);
- else
- strcat(save_status, " friends");
+ errors++;
+ }
}
- else //Friend list cleared.
- strcat(save_status, " friends");
+ strcat(save_status, " friends");
}
#ifdef HOTKEY_SAVING
@@ -660,8 +684,10 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
}
if(diff) {
if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
+ {
Sql_ShowDebug(sql_handle);
- else
+ errors++;
+ } else
strcat(save_status, " hotkeys");
}
#endif
@@ -669,7 +695,8 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
if (save_status[0]!='\0' && save_log)
ShowInfo("Saved char %d - %s:%s.\n", char_id, p->name, save_status);
#ifndef TXT_SQL_CONVERT
- memcpy(cp, p, sizeof(struct mmo_charstatus));
+ if (!errors)
+ memcpy(cp, p, sizeof(struct mmo_charstatus));
#else
aFree(cp);
#endif
@@ -688,6 +715,7 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit
struct item item; // temp storage variable
bool* flag; // bit array for inventory matching
bool found;
+ int errors = 0;
switch (tableswitch) {
case TABLE_INVENTORY: tablename = inventory_db; selectoption = "char_id"; break;
@@ -770,7 +798,10 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit
StringBuf_Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id);
if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
+ {
Sql_ShowDebug(sql_handle);
+ errors++;
+ }
}
found = flag[i] = true; //Item dealt with,
@@ -780,7 +811,10 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit
if( !found )
{// Item not present in inventory, remove it.
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `id`='%d'", tablename, item.id) )
+ {
Sql_ShowDebug(sql_handle);
+ errors++;
+ }
}
}
SqlStmt_Free(stmt);
@@ -812,12 +846,15 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit
}
if( found && SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
+ {
Sql_ShowDebug(sql_handle);
+ errors++;
+ }
StringBuf_Destroy(&buf);
aFree(flag);
- return 0;
+ return errors;
}
int mmo_char_tobuf(uint8* buf, struct mmo_charstatus* p);