aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Mails/Mail.cpp
diff options
context:
space:
mode:
authorMachiavelli <none@none>2010-08-21 03:19:25 +0200
committerMachiavelli <none@none>2010-08-21 03:19:25 +0200
commit994186f2672547761392c71ed15ded2a83e8c20d (patch)
tree53eec0c7571642b9490d2a664671cb216a730993 /src/server/game/Mails/Mail.cpp
parenta7498d2f560e24b2ae3b4f6cc46ea2223a41e16f (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.cpp76
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)