mirror of
https://github.com/mangosfour/server.git
synced 2025-12-18 19:37:01 +00:00
[10970] Implement mass mail send infrastructure.
It expected to be used in 2 case: some gameevent must send mails at start/end,
and this can be useful in game commands. Both case wil implemented in later commits.
* New MassMailMgr can accept tasks for send mass mails in safe way for map update threads context/etc.
* It work in way:
- By provided race mask or more generic SQL query string in async query selected affected characters
- At query result ready at next world tick update in safe common part of tick code some from mails
from queued mas mail tasks send.
- Amount mails limited MassMailer.SendPerTick confir option (10 by default). This done for prevent
high server load/lags at send too many mails in one tick (mail send all existed characters in DB
who match to seelction criteria)
- Manager not persistant for server shutdowns so any not send mails in queue lost at shutdown.
But with default setting 10K mail send in 20 secs (10000/50/10). Adding more safe execution
for this case will make related code lot more slow and req. many DB tables and code support.
This commit is contained in:
parent
231c6d77ce
commit
5f2aef756a
13 changed files with 331 additions and 2 deletions
|
|
@ -918,6 +918,33 @@ void MailDraft::deleteIncludedItems( bool inDB /**= false*/ )
|
|||
|
||||
m_items.clear();
|
||||
}
|
||||
/**
|
||||
* Clone MailDraft from another MailDraft.
|
||||
*
|
||||
* @param draft Point to source for draft cloning.
|
||||
*/
|
||||
void MailDraft::CloneFrom(MailDraft const& draft)
|
||||
{
|
||||
m_mailTemplateId = draft.GetMailTemplateId();
|
||||
m_mailTemplateItemsNeed = draft.m_mailTemplateItemsNeed;
|
||||
|
||||
m_subject = draft.GetSubject();
|
||||
m_body = draft.GetBody();
|
||||
m_money = draft.GetMoney();
|
||||
m_COD = draft.GetCOD();
|
||||
|
||||
for(MailItemMap::const_iterator mailItemIter = draft.m_items.begin(); mailItemIter != draft.m_items.end(); ++mailItemIter)
|
||||
{
|
||||
Item* item = mailItemIter->second;
|
||||
|
||||
if(Item* newitem = item->CloneItem(item->GetCount()))
|
||||
{
|
||||
newitem->SaveToDB();
|
||||
AddItem(newitem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a mail to its sender.
|
||||
* @param sender_acc The id of the account of the sender.
|
||||
|
|
|
|||
|
|
@ -18,9 +18,11 @@
|
|||
|
||||
/**
|
||||
* @addtogroup mailing The mail system
|
||||
* The mailing system in MaNGOS consists of mostly two files:
|
||||
* The mailing system in MaNGOS consists of mostly 4 files:
|
||||
* - Mail.h
|
||||
* - Mail.cpp
|
||||
* - MassMailMgr.h
|
||||
* - MassMailMgr.cpp
|
||||
*
|
||||
* @{
|
||||
*
|
||||
|
|
@ -237,6 +239,8 @@ class MailDraft
|
|||
* @param COD the amount to which the cod should be set.
|
||||
*/
|
||||
MailDraft& SetCOD(uint32 COD) { m_COD = COD; return *this; }
|
||||
|
||||
void CloneFrom(MailDraft const& draft);
|
||||
public: // finishers
|
||||
void SendReturnToSender(uint32 sender_acc, ObjectGuid sender_guid, ObjectGuid receiver_guid);
|
||||
void SendMailTo(MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked = MAIL_CHECK_MASK_NONE, uint32 deliver_delay = 0);
|
||||
|
|
|
|||
|
|
@ -183,6 +183,8 @@ libmangosgame_a_SOURCES = \
|
|||
MapManager.h \
|
||||
MapReference.h \
|
||||
MapRefManager.h \
|
||||
MassMailMgr.cpp \
|
||||
MassMailMgr.h \
|
||||
MiscHandler.cpp \
|
||||
MotionMaster.cpp \
|
||||
MotionMaster.h \
|
||||
|
|
|
|||
134
src/game/MassMailMgr.cpp
Normal file
134
src/game/MassMailMgr.cpp
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup mailing
|
||||
* @{
|
||||
*
|
||||
* @file MassMailMgr.cpp
|
||||
* This file contains the the code needed for MaNGOS to handle mass mails send in safe and perfomence not affecting way.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MassMailMgr.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "Database/DatabaseImpl.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "World.h"
|
||||
#include "ObjectMgr.h"
|
||||
|
||||
INSTANTIATE_SINGLETON_1(MassMailMgr);
|
||||
|
||||
void MassMailMgr::AddMassMailTask(MailDraft* mailProto, MailSender sender, uint32 raceMask)
|
||||
{
|
||||
if (RACEMASK_ALL_PLAYABLE & ~raceMask) // have races not included in mask
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "SELECT guid FROM characters WHERE (1 << (race - 1)) & " << raceMask << " AND deleteDate IS NULL";
|
||||
AddMassMailTask(mailProto, sender, ss.str().c_str());
|
||||
}
|
||||
else
|
||||
AddMassMailTask(mailProto, sender, "SELECT guid FROM characters WHERE deleteDate IS NULL");
|
||||
}
|
||||
|
||||
struct MassMailerQueryHandler
|
||||
{
|
||||
void HandleQueryCallback(QueryResult * result, MailDraft* mailProto, MailSender sender)
|
||||
{
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
MassMailMgr::ReceiversList& recievers = sMassMailMgr.AddMassMailTask(mailProto, sender);
|
||||
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
recievers.insert(fields[0].GetUInt32());
|
||||
|
||||
} while (result->NextRow());
|
||||
delete result;
|
||||
}
|
||||
} massMailerQueryHandler;
|
||||
|
||||
void MassMailMgr::AddMassMailTask(MailDraft* mailProto, MailSender sender, char const* query)
|
||||
{
|
||||
CharacterDatabase.AsyncPQuery(&massMailerQueryHandler, &MassMailerQueryHandler::HandleQueryCallback, mailProto, sender, query);
|
||||
}
|
||||
|
||||
void MassMailMgr::Update()
|
||||
{
|
||||
if (m_massMails.empty())
|
||||
return;
|
||||
|
||||
uint32 maxcount = sWorld.getConfig(CONFIG_UINT32_MASS_MAILER_SEND_PER_TICK);
|
||||
|
||||
do
|
||||
{
|
||||
MassMail& task = m_massMails.front();
|
||||
|
||||
while (!task.m_recivers.empty() && maxcount > 0)
|
||||
{
|
||||
uint32 receiver_lowguid = *task.m_recivers.begin();
|
||||
task.m_recivers.erase(task.m_recivers.begin());
|
||||
|
||||
ObjectGuid receiver_guid = ObjectGuid(HIGHGUID_PLAYER, receiver_lowguid);
|
||||
Player *receiver = sObjectMgr.GetPlayer(receiver_guid);
|
||||
|
||||
// last case. can be just send
|
||||
if (task.m_recivers.empty())
|
||||
{
|
||||
// prevent mail return
|
||||
task.m_protoMail->SendMailTo(MailReceiver(receiver, receiver_guid), task.m_sender, MAIL_CHECK_MASK_RETURNED);
|
||||
|
||||
--maxcount;
|
||||
break;
|
||||
}
|
||||
|
||||
// need clone draft
|
||||
MailDraft draft;
|
||||
draft.CloneFrom(*task.m_protoMail);
|
||||
|
||||
// prevent mail return
|
||||
draft.SendMailTo(MailReceiver(receiver, receiver_guid), task.m_sender, MAIL_CHECK_MASK_RETURNED);
|
||||
|
||||
--maxcount;
|
||||
}
|
||||
|
||||
if (task.m_recivers.empty())
|
||||
m_massMails.pop_front();
|
||||
}
|
||||
while(!m_massMails.empty() && maxcount > 0);
|
||||
}
|
||||
|
||||
void MassMailMgr::GetStatistic(uint32& tasks, uint32& mails, uint32& needTime) const
|
||||
{
|
||||
tasks = m_massMails.size();
|
||||
|
||||
uint32 mailsCount = 0;
|
||||
for (MassMailList::const_iterator mailItr = m_massMails.begin(); mailItr != m_massMails.end(); ++mailItr)
|
||||
mailsCount += mailItr->m_recivers.size();
|
||||
|
||||
mails = mailsCount;
|
||||
|
||||
// 50 msecs is tick length
|
||||
needTime = 50 * mailsCount / sWorld.getConfig(CONFIG_UINT32_MASS_MAILER_SEND_PER_TICK) / IN_MILLISECONDS;
|
||||
}
|
||||
|
||||
|
||||
/*! @} */
|
||||
125
src/game/MassMailMgr.h
Normal file
125
src/game/MassMailMgr.h
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup mailing The mail system
|
||||
* The mailing system in MaNGOS consists of mostly 4 files:
|
||||
* - Mail.h
|
||||
* - Mail.cpp
|
||||
* - MassMailMgr.h
|
||||
* - MassMailMgr.cpp
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file MassMailMgr.h
|
||||
* This file contains the the headers needed for MaNGOS to handle mass mails send in safe and perfomence not affecting way.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MANGOS_MASS_MAIL_MGR_H
|
||||
#define MANGOS_MASS_MAIL_MGR_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Mail.h"
|
||||
#include "Policies/Singleton.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* A class to represent the mail send factory to multiply (often all existed) characters.
|
||||
*
|
||||
* Note: implementation not persistence for server shutdowns
|
||||
*/
|
||||
class MassMailMgr
|
||||
{
|
||||
public: // Constructors
|
||||
MassMailMgr() {}
|
||||
|
||||
public: // Accessors
|
||||
void GetStatistic(uint32& tasks, uint32& mails, uint32& needTime) const;
|
||||
|
||||
public: // modifiers
|
||||
typedef UNORDERED_SET<uint32> ReceiversList;
|
||||
|
||||
/**
|
||||
* And new mass mail task for raceMask filter applied to characters list.
|
||||
*
|
||||
* @param mailProto prepared mail for clone and send to characters, will deleted in result call.
|
||||
* @param raceMask mask of races that must receive mail.
|
||||
*
|
||||
* Note: this function safe to be called from Map::Update content/etc, real data add will executed in next tick after query resultrs ready
|
||||
*/
|
||||
void AddMassMailTask(MailDraft* mailProto, MailSender sender, uint32 raceMask);
|
||||
|
||||
/**
|
||||
* And new mass mail task with SQL query text for fill receivers list.
|
||||
*
|
||||
* @param mailProto prepared mail for clone and send to characters, will deleted in result call
|
||||
* @param queryStr SQL query for get guid list of receivers, first field in query result must be uint32 low guids list.
|
||||
*
|
||||
* Note: this function safe to be called from Map::Update content/etc, real data add will executed in next tick after query resultrs ready
|
||||
*/
|
||||
void AddMassMailTask(MailDraft* mailProto, MailSender sender, char const* queryStr);
|
||||
|
||||
/**
|
||||
* And new mass mail task and let fill receivers list returned as result.
|
||||
*
|
||||
* @param mailProto prepared mail for clone and send to characters, will deleted in result call
|
||||
* @returns reference to receivers list for it fill in caller code.
|
||||
*
|
||||
* Note: this function NOT SAFE for call from Map::Update content/etc
|
||||
*/
|
||||
ReceiversList& AddMassMailTask(MailDraft* mailProto, MailSender sender)
|
||||
{
|
||||
m_massMails.push_back(MassMail(mailProto, sender));
|
||||
return m_massMails.rbegin()->m_recivers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Next step in mass mail activity, send some amount mails from queued tasks
|
||||
*/
|
||||
void Update();
|
||||
|
||||
private:
|
||||
|
||||
/// Mass mail task store mail prototype and receivers list who not get mail yet
|
||||
struct MassMail
|
||||
{
|
||||
explicit MassMail(MailDraft* mailProto, MailSender sender)
|
||||
: m_protoMail(mailProto), m_sender(sender)
|
||||
{
|
||||
MANGOS_ASSERT(mailProto);
|
||||
}
|
||||
|
||||
/// m_protoMail is owned by MassMail, so at copy original MassMail field set to NULL
|
||||
std::auto_ptr<MailDraft> m_protoMail;
|
||||
|
||||
MailSender m_sender;
|
||||
ReceiversList m_recivers;
|
||||
};
|
||||
|
||||
typedef std::list<MassMail> MassMailList;
|
||||
|
||||
/// List of current queued mass mail tasks
|
||||
MassMailList m_massMails;
|
||||
};
|
||||
|
||||
#define sMassMailMgr MaNGOS::Singleton<MassMailMgr>::Instance()
|
||||
|
||||
#endif
|
||||
/*! @} */
|
||||
|
|
@ -42,6 +42,7 @@
|
|||
#include "SpellMgr.h"
|
||||
#include "Chat.h"
|
||||
#include "DBCStores.h"
|
||||
#include "MassMailMgr.h"
|
||||
#include "LootMgr.h"
|
||||
#include "ItemEnchantmentMgr.h"
|
||||
#include "MapManager.h"
|
||||
|
|
@ -618,6 +619,8 @@ void World::LoadConfigSettings(bool reload)
|
|||
|
||||
setConfig(CONFIG_UINT32_MAIL_DELIVERY_DELAY, "MailDeliveryDelay", HOUR);
|
||||
|
||||
setConfigMin(CONFIG_UINT32_MASS_MAILER_SEND_PER_TICK, "MassMailer.SendPerTick", 10, 1);
|
||||
|
||||
setConfigPos(CONFIG_UINT32_UPTIME_UPDATE, "UpdateUptimeInterval", 10);
|
||||
if (reload)
|
||||
{
|
||||
|
|
@ -1404,6 +1407,9 @@ void World::Update(uint32 diff)
|
|||
///- Update the game time and check for shutdown time
|
||||
_UpdateGameTime();
|
||||
|
||||
///-Update mass mailer tasks if any
|
||||
sMassMailMgr.Update();
|
||||
|
||||
/// Handle daily quests reset time
|
||||
if (m_gameTime > m_NextDailyQuestReset)
|
||||
ResetDailyQuests();
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ enum eConfigUInt32Values
|
|||
CONFIG_UINT32_START_GM_LEVEL,
|
||||
CONFIG_UINT32_GROUP_VISIBILITY,
|
||||
CONFIG_UINT32_MAIL_DELIVERY_DELAY,
|
||||
CONFIG_UINT32_MASS_MAILER_SEND_PER_TICK,
|
||||
CONFIG_UINT32_UPTIME_UPDATE,
|
||||
CONFIG_UINT32_AUCTION_DEPOSIT_MIN,
|
||||
CONFIG_UINT32_SKILL_CHANCE_ORANGE,
|
||||
|
|
|
|||
|
|
@ -661,6 +661,11 @@ LogColors = ""
|
|||
# Mail delivery delay time for item sending
|
||||
# Default: 3600 sec (1 hour)
|
||||
#
|
||||
# MassMailer.SendPerTick
|
||||
# Max amount mail send each tick from mails list scheduled for mass mailer proccesing.
|
||||
# More mails increase server load but speedup mass mail proccess. Normal tick length: 50 msecs, so 20 ticks in sec and 200 mails in sec by default.
|
||||
# Default: 10
|
||||
#
|
||||
# SkillChance.Prospecting
|
||||
# For prospecting skillup impossible by default, but can be allowed as custom setting
|
||||
# Default: 0 - no skilups
|
||||
|
|
@ -759,6 +764,7 @@ MaxPrimaryTradeSkill = 2
|
|||
MinPetitionSigns = 9
|
||||
MaxGroupXPDistance = 74
|
||||
MailDeliveryDelay = 3600
|
||||
MassMailer.SendPerTick = 10
|
||||
SkillChance.Prospecting = 0
|
||||
SkillChance.Milling = 0
|
||||
OffhandCheckAtTalentsReset = 0
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "10969"
|
||||
#define REVISION_NR "10970"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
|
|
@ -436,6 +436,7 @@
|
|||
<ClCompile Include="..\..\src\game\Mail.cpp" />
|
||||
<ClCompile Include="..\..\src\game\Map.cpp" />
|
||||
<ClCompile Include="..\..\src\game\MapManager.cpp" />
|
||||
<ClCompile Include="..\..\src\game\MassMailMgr.cpp" />
|
||||
<ClCompile Include="..\..\src\game\MiscHandler.cpp" />
|
||||
<ClCompile Include="..\..\src\game\MotionMaster.cpp" />
|
||||
<ClCompile Include="..\..\src\game\MovementGenerator.cpp" />
|
||||
|
|
@ -592,6 +593,7 @@
|
|||
<ClInclude Include="..\..\src\game\MapManager.h" />
|
||||
<ClInclude Include="..\..\src\game\MapReference.h" />
|
||||
<ClInclude Include="..\..\src\game\MapRefManager.h" />
|
||||
<ClInclude Include="..\..\src\game\MassMailMgr.h" />
|
||||
<ClInclude Include="..\..\src\game\MotionMaster.h" />
|
||||
<ClInclude Include="..\..\src\game\MovementGenerator.h" />
|
||||
<ClInclude Include="..\..\src\game\NPCHandler.h" />
|
||||
|
|
|
|||
|
|
@ -165,6 +165,9 @@
|
|||
<ClCompile Include="..\..\src\game\MapManager.cpp">
|
||||
<Filter>World/Handlers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\game\MassMailMgr.cpp">
|
||||
<Filter>World/Handlers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\game\MiscHandler.cpp">
|
||||
<Filter>World/Handlers</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -579,6 +582,9 @@
|
|||
<ClInclude Include="..\..\src\game\MapManager.h">
|
||||
<Filter>World/Handlers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\game\MassMailMgr.h">
|
||||
<Filter>World/Handlers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\game\NPCHandler.h">
|
||||
<Filter>World/Handlers</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -849,6 +849,14 @@
|
|||
RelativePath="..\..\src\game\MapManager.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\game\MassMailMgr.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\game\MassMailMgr.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\game\MiscHandler.cpp"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -842,6 +842,14 @@
|
|||
RelativePath="..\..\src\game\MapManager.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\game\MassMailMgr.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\game\MassMailMgr.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\game\MiscHandler.cpp"
|
||||
>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue