diff options
author | Machiavelli <none@none> | 2010-08-21 03:19:25 +0200 |
---|---|---|
committer | Machiavelli <none@none> | 2010-08-21 03:19:25 +0200 |
commit | 994186f2672547761392c71ed15ded2a83e8c20d (patch) | |
tree | 53eec0c7571642b9490d2a664671cb216a730993 /src/server/game/Mails/Mail.cpp | |
parent | a7498d2f560e24b2ae3b4f6cc46ea2223a41e16f (diff) |
DB Layer:
- Make SQL Transactions actual objects used in code. (Thanks to Derex for the idea)
* Uncommitted transactions will be automatically rolled back and cleaned up using ACE_Refcounted_Auto_Ptr, so no need to call Rollback() in the code.
* Prevents recursive transactions and makes developers aware of transactions going on.
* Gets rid of unneccesary overhead iterating over a concurrent map.
- Some cleanups in affected code, including better usage of transaction control in AH / mail related code to prevent data loss.
*** Experimental, use at own risk, recommended to backup your DBs. ***
--HG--
branch : trunk
Diffstat (limited to 'src/server/game/Mails/Mail.cpp')
-rw-r--r-- | src/server/game/Mails/Mail.cpp | 76 |
1 files changed, 38 insertions, 38 deletions
diff --git a/src/server/game/Mails/Mail.cpp b/src/server/game/Mails/Mail.cpp index beee96c0d91..00d82ca6860 100644 --- a/src/server/game/Mails/Mail.cpp +++ b/src/server/game/Mails/Mail.cpp @@ -245,6 +245,8 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) MailDraft draft(subject, body); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + if (items_count > 0 || money > 0) { if (items_count > 0) @@ -260,12 +262,11 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable pl->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true); - CharacterDatabase.BeginTransaction(); - item->DeleteFromInventoryDB(); // deletes item from character's inventory - item->SaveToDB(); // recursive and not have transaction guard into self, item not in inventory and can be save standalone + + item->DeleteFromInventoryDB(trans); // deletes item from character's inventory + item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone // owner in data will set at mail receive and item extracting - CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", GUID_LOPART(rc), item->GetGUIDLow()); - CharacterDatabase.CommitTransaction(); + trans->PAppend("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", GUID_LOPART(rc), item->GetGUIDLow()); draft.AddItem(item); } @@ -287,11 +288,10 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) draft .AddMoney(money) .AddCOD(COD) - .SendMailTo(MailReceiver(receive, GUID_LOPART(rc)), pl, body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); + .SendMailTo(trans, MailReceiver(receive, GUID_LOPART(rc)), pl, body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); - CharacterDatabase.BeginTransaction(); - pl->SaveInventoryAndGoldToDB(); - CharacterDatabase.CommitTransaction(); + pl->SaveInventoryAndGoldToDB(trans); + CharacterDatabase.CommitTransaction(trans); } //called when mail is read @@ -366,10 +366,10 @@ void WorldSession::HandleMailReturnToSender(WorldPacket & recv_data) } //we can return mail now //so firstly delete the old one - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", mailId); // needed? - CharacterDatabase.PExecute("DELETE FROM mail_items WHERE mail_id = '%u'", mailId); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM mail WHERE id = '%u'", mailId); // needed? + trans->PAppend("DELETE FROM mail_items WHERE mail_id = '%u'", mailId); + CharacterDatabase.CommitTransaction(trans); pl->RemoveMail(mailId); // only return mail if the player exists (and delete if not existing) @@ -436,6 +436,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket & recv_data) uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, it, false); if (msg == EQUIP_ERR_OK) { + SQLTransaction trans = CharacterDatabase.BeginTransaction(); m->RemoveItem(itemId); m->removedItems.push_back(itemId); @@ -473,7 +474,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket & recv_data) { MailDraft(m->subject, "") .AddMoney(m->COD) - .SendMailTo(MailReceiver(receive, m->sender), MailSender(MAIL_NORMAL, m->receiver), MAIL_CHECK_MASK_COD_PAYMENT); + .SendMailTo(trans, MailReceiver(receive, m->sender), MailSender(MAIL_NORMAL, m->receiver), MAIL_CHECK_MASK_COD_PAYMENT); } pl->ModifyMoney(-int32(m->COD)); @@ -486,10 +487,9 @@ void WorldSession::HandleMailTakeItem(WorldPacket & recv_data) uint32 count = it->GetCount(); // save counts before store and possible merge with deleting pl->MoveItemToInventory(dest,it,true); - CharacterDatabase.BeginTransaction(); - pl->SaveInventoryAndGoldToDB(); - pl->_SaveMail(); - CharacterDatabase.CommitTransaction(); + pl->SaveInventoryAndGoldToDB(trans); + pl->_SaveMail(trans); + CharacterDatabase.CommitTransaction(trans); pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_OK, 0, itemId, count); } @@ -524,10 +524,10 @@ void WorldSession::HandleMailTakeMoney(WorldPacket & recv_data) pl->m_mailsUpdated = true; // save money and mail to prevent cheating - CharacterDatabase.BeginTransaction(); - pl->SaveGoldToDB(); - pl->_SaveMail(); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + pl->SaveGoldToDB(trans); + pl->_SaveMail(trans); + CharacterDatabase.CommitTransaction(trans); } //called when player lists his received mails @@ -826,7 +826,7 @@ MailDraft& MailDraft::AddItem(Item* item) m_items[item->GetGUIDLow()] = item; return *this; } -void MailDraft::prepareItems(Player* receiver) +void MailDraft::prepareItems(Player* receiver, SQLTransaction& trans) { if (!m_mailTemplateId || !m_mailTemplateItemsNeed) return; @@ -845,21 +845,21 @@ void MailDraft::prepareItems(Player* receiver) { if (Item* item = Item::CreateItem(lootitem->itemid,lootitem->count,receiver)) { - item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted + item->SaveToDB(trans); // save for prevent lost at next mail load, if send fail then item will deleted AddItem(item); } } } } -void MailDraft::deleteIncludedItems(bool inDB /*= false*/) +void MailDraft::deleteIncludedItems(bool inDB /*= false*/, SQLTransaction& trans) { for (MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) { Item* item = mailItemIter->second; if (inDB) - CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid='%u'", item->GetGUIDLow()); + trans->PAppend("DELETE FROM item_instance WHERE guid='%u'", item->GetGUIDLow()); delete item; } @@ -875,9 +875,11 @@ void MailDraft::SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32 if (!receiver) rc_account = sObjectMgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(receiver_guid, 0, HIGHGUID_PLAYER)); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + if (!receiver && !rc_account) // sender not exist { - deleteIncludedItems(true); + deleteIncludedItems(true, trans); return; } @@ -890,30 +892,29 @@ void MailDraft::SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32 needItemDelay = sender_acc != rc_account; // set owner to new receiver (to prevent delete item with sender char deleting) - CharacterDatabase.BeginTransaction(); for (MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) { Item* item = mailItemIter->second; - item->SaveToDB(); // item not in inventory and can be save standalone + item->SaveToDB(trans); // item not in inventory and can be save standalone // owner in data will set at mail receive and item extracting - CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", receiver_guid, item->GetGUIDLow()); + trans->PAppend("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", receiver_guid, item->GetGUIDLow()); } - CharacterDatabase.CommitTransaction(); } // If theres is an item, there is a one hour delivery delay. uint32 deliver_delay = needItemDelay ? sWorld.getConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0; // will delete item or place to receiver mail list - SendMailTo(MailReceiver(receiver,receiver_guid), MailSender(MAIL_NORMAL, sender_guid), MAIL_CHECK_MASK_RETURNED, deliver_delay); + SendMailTo(trans,MailReceiver(receiver,receiver_guid), MailSender(MAIL_NORMAL, sender_guid), MAIL_CHECK_MASK_RETURNED, deliver_delay); + CharacterDatabase.CommitTransaction(trans); } -void MailDraft::SendMailTo(MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked, uint32 deliver_delay) +void MailDraft::SendMailTo(SQLTransaction& trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked, uint32 deliver_delay) { Player* pReceiver = receiver.GetPlayer(); // can be NULL if (pReceiver) - prepareItems(pReceiver); // generate mail template items + prepareItems(pReceiver, trans); // generate mail template items uint32 mailId = sObjectMgr.GenerateMailID(); @@ -937,20 +938,19 @@ void MailDraft::SendMailTo(MailReceiver const& receiver, MailSender const& sende // Add to DB std::string safe_subject = GetSubject(); std::string safe_body = GetBody(); - CharacterDatabase.BeginTransaction(); + CharacterDatabase.escape_string(safe_subject); CharacterDatabase.escape_string(safe_body); - CharacterDatabase.PExecute("INSERT INTO mail (id,messageType,stationery,mailTemplateId,sender,receiver,subject,body,has_items,expire_time,deliver_time,money,cod,checked) " + trans->PAppend("INSERT INTO mail (id,messageType,stationery,mailTemplateId,sender,receiver,subject,body,has_items,expire_time,deliver_time,money,cod,checked) " "VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%s', '%s', '%u', '" UI64FMTD "','" UI64FMTD "', '%u', '%u', '%d')", mailId, sender.GetMailMessageType(), sender.GetStationery(), GetMailTemplateId(), sender.GetSenderId(), receiver.GetPlayerGUIDLow(), safe_subject.c_str(), safe_body.c_str(),(m_items.empty() ? 0 : 1), (uint64)expire_time, (uint64)deliver_time, m_money, m_COD, checked); for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) { Item* item = mailItemIter->second; - CharacterDatabase.PExecute("INSERT INTO mail_items (mail_id,item_guid,item_template,receiver) VALUES ('%u', '%u', '%u','%u')", mailId, item->GetGUIDLow(), item->GetEntry(), receiver.GetPlayerGUIDLow()); + trans->PAppend("INSERT INTO mail_items (mail_id,item_guid,item_template,receiver) VALUES ('%u', '%u', '%u','%u')", mailId, item->GetGUIDLow(), item->GetEntry(), receiver.GetPlayerGUIDLow()); } - CharacterDatabase.CommitTransaction(); // For online receiver update in game mail status and data if (pReceiver) |