4586: Fail database queries faster r=def- a=Zwelf

Makes ddos situations more bearable during tournaments. Redo of #4429, but this time the tested version. I somehow mixed my two git environments (Laptop and PC) last time and some changes were missing from the PR last time (the initialization of the shutdown variable and m_count variable).

Changed the logic a bit from last time to only go into FailMode if the query fails on all database servers.

## Checklist

- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [ ] Considered possible null pointers and out of bounds array indexing
- [x] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Zwelf <zwelf@strct.cc>
This commit is contained in:
bors[bot] 2022-01-09 22:00:26 +00:00 committed by GitHub
commit 1eac1bbb20
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 5 deletions

View file

@ -9,21 +9,21 @@ class CSemaphore
SEMAPHORE m_Sem;
// implement the counter seperatly, because the `sem_getvalue`-API is
// deprecated on macOS: https://stackoverflow.com/a/16655541
std::atomic_int count;
std::atomic_int m_Count{0};
public:
CSemaphore() { sphore_init(&m_Sem); }
~CSemaphore() { sphore_destroy(&m_Sem); }
CSemaphore(const CSemaphore &) = delete;
int GetApproximateValue() { return count.load(); }
int GetApproximateValue() { return m_Count.load(); }
void Wait()
{
sphore_wait(&m_Sem);
count.fetch_sub(1);
m_Count.fetch_sub(1);
}
void Signal()
{
count.fetch_add(1);
m_Count.fetch_add(1);
sphore_signal(&m_Sem);
}
};

View file

@ -127,8 +127,15 @@ void CDbConnectionPool::Worker()
// remember last working server and try to connect to it first
int ReadServer = 0;
int WriteServer = 0;
// enter fail mode when a sql request fails, skip read request during it and
// write to the backup database until all requests are handled
bool FailMode = false;
while(1)
{
if(FailMode && m_NumElem.GetApproximateValue() == 0)
{
FailMode = false;
}
m_NumElem.Wait();
auto pThreadData = std::move(m_aTasks[LastElem++]);
// work through all database jobs after OnShutdown is called before exiting the thread
@ -145,6 +152,16 @@ void CDbConnectionPool::Worker()
{
for(int i = 0; i < (int)m_aapDbConnections[Mode::READ].size(); i++)
{
if(m_Shutdown)
{
dbg_msg("sql", "%s dismissed read request during shutdown", pThreadData->m_pName);
break;
}
if(FailMode)
{
dbg_msg("sql", "%s dismissed read request during FailMode", pThreadData->m_pName);
break;
}
int CurServer = (ReadServer + i) % (int)m_aapDbConnections[Mode::READ].size();
if(ExecSqlFunc(m_aapDbConnections[Mode::READ][CurServer].get(), pThreadData.get(), false))
{
@ -154,12 +171,26 @@ void CDbConnectionPool::Worker()
break;
}
}
if(!Success)
{
FailMode = true;
}
}
break;
case CSqlExecData::WRITE_ACCESS:
{
for(int i = 0; i < (int)m_aapDbConnections[Mode::WRITE].size(); i++)
{
if(m_Shutdown && !m_aapDbConnections[Mode::WRITE_BACKUP].empty())
{
dbg_msg("sql", "%s skipped to backup database during shutdown", pThreadData->m_pName);
break;
}
if(FailMode && !m_aapDbConnections[Mode::WRITE_BACKUP].empty())
{
dbg_msg("sql", "%s skipped to backup database during FailMode", pThreadData->m_pName);
break;
}
int CurServer = (WriteServer + i) % (int)m_aapDbConnections[Mode::WRITE].size();
if(ExecSqlFunc(m_aapDbConnections[Mode::WRITE][i].get(), pThreadData.get(), false))
{
@ -171,6 +202,7 @@ void CDbConnectionPool::Worker()
}
if(!Success)
{
FailMode = true;
for(int i = 0; i < (int)m_aapDbConnections[Mode::WRITE_BACKUP].size(); i++)
{
if(ExecSqlFunc(m_aapDbConnections[Mode::WRITE_BACKUP][i].get(), pThreadData.get(), true))

View file

@ -75,7 +75,7 @@ private:
void Worker();
bool ExecSqlFunc(IDbConnection *pConnection, struct CSqlExecData *pData, bool Failure);
std::atomic_bool m_Shutdown;
std::atomic_bool m_Shutdown{false};
CSemaphore m_NumElem;
int FirstElem;
int LastElem;