aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-10-16 01:35:10 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-10-16 01:46:10 -0300
commit95022ca95b1d2792bae447d90694dcc0d67b9de2 (patch)
tree3a23505d31c48188f537a6da95239215a6487297
parentb49d7de51cf14632a5768f292b870e647cf39bf5 (diff)
downloadquerymanager-95022ca95b1d2792bae447d90694dcc0d67b9de2.tar.gz
querymanager-95022ca95b1d2792bae447d90694dcc0d67b9de2.zip
lower monotonic uptime resolution from MILLISECONDS to SECONDS
The monotonic uptime was used exclusively with caches and having a resolution of SECONDS allows it to be stored as an int without risk of wrapping (~68 years). Using MILLISECONDS meant that it would wrap after ~25 days which is totally possible and EXPECTED. Just as an example, the small test server I ran for about 1 month had ZERO downtime on the QueryManager except for when I manually restarted it. It was probably very close to wrapping when I took it down.
-rw-r--r--src/connections.cc10
-rw-r--r--src/database_postgres.cc4
-rw-r--r--src/database_sqlite.cc4
-rw-r--r--src/hostcache.cc2
-rw-r--r--src/querymanager.cc18
-rw-r--r--src/querymanager.hh2
6 files changed, 22 insertions, 18 deletions
diff --git a/src/connections.cc b/src/connections.cc
index 0760514..b851954 100644
--- a/src/connections.cc
+++ b/src/connections.cc
@@ -141,7 +141,7 @@ TConnection *AssignConnection(int Socket, uint32 Addr, uint16 Port){
Connection = &g_Connections[ConnectionIndex];
Connection->State = CONNECTION_READING;
Connection->Socket = Socket;
- Connection->LastActive = GetMonotonicUptimeMS();
+ Connection->LastActive = GetMonotonicUptime();
snprintf(Connection->RemoteAddress,
sizeof(Connection->RemoteAddress),
"%d.%d.%d.%d:%d",
@@ -215,7 +215,7 @@ void CheckConnectionInput(TConnection *Connection, int Events){
if(Connection->RWPosition >= ReadSize){
if(Connection->RWSize != 0){
Connection->State = CONNECTION_REQUEST;
- Connection->LastActive = GetMonotonicUptimeMS();
+ Connection->LastActive = GetMonotonicUptime();
Connection->Query->Request = TReadBuffer(Buffer, Connection->RWSize);
break;
}else if(Connection->RWPosition == 2){
@@ -510,8 +510,12 @@ void CheckConnection(TConnection *Connection, int Events){
CloseConnection(Connection);
}
+ // NOTE(fusion): Idle connection could linger for more than expected because
+ // the polling thread now blocks on `poll`. It shouldn't be a problem tho, as
+ // it could only happen on periods of absolutely NO traffic, so there is ZERO
+ // load on the query manager outside of used memory (which is already limited).
if(g_Config.MaxConnectionIdleTime > 0){
- int IdleTime = (GetMonotonicUptimeMS() - Connection->LastActive);
+ int IdleTime = (GetMonotonicUptime() - Connection->LastActive);
if(IdleTime >= g_Config.MaxConnectionIdleTime){
LOG_WARN("Dropping connection %s due to inactivity",
Connection->RemoteAddress);
diff --git a/src/database_postgres.cc b/src/database_postgres.cc
index 4638851..bcadcea 100644
--- a/src/database_postgres.cc
+++ b/src/database_postgres.cc
@@ -1051,7 +1051,7 @@ const char *PrepareQuery(TDatabase *Database, const char *Text){
if(Entry->Text != NULL && Entry->Hash == Hash){
if(StringEq(Entry->Text, Text)){
Stmt = Entry;
- Entry->LastUsed = GetMonotonicUptimeMS();
+ Entry->LastUsed = GetMonotonicUptime();
break;
}
}
@@ -1085,7 +1085,7 @@ const char *PrepareQuery(TDatabase *Database, const char *Text){
}
- Stmt->LastUsed = GetMonotonicUptimeMS();
+ Stmt->LastUsed = GetMonotonicUptime();
Stmt->Hash = Hash;
Stmt->Text = strdup(Text);
ASSERT(Stmt->Text != NULL);
diff --git a/src/database_sqlite.cc b/src/database_sqlite.cc
index b50c6df..bcc4914 100644
--- a/src/database_sqlite.cc
+++ b/src/database_sqlite.cc
@@ -94,7 +94,7 @@ static sqlite3_stmt *PrepareQuery(TDatabase *Database, const char *Text){
ASSERT(EntryText != NULL);
if(StringEq(EntryText, Text)){
Stmt = Entry->Stmt;
- Entry->LastUsed = GetMonotonicUptimeMS();
+ Entry->LastUsed = GetMonotonicUptime();
break;
}
}
@@ -113,7 +113,7 @@ static sqlite3_stmt *PrepareQuery(TDatabase *Database, const char *Text){
}
Entry->Stmt = Stmt;
- Entry->LastUsed = GetMonotonicUptimeMS();
+ Entry->LastUsed = GetMonotonicUptime();
Entry->Hash = Hash;
}else{
if(sqlite3_stmt_busy(Stmt) != 0){
diff --git a/src/hostcache.cc b/src/hostcache.cc
index f32b0f7..23be08f 100644
--- a/src/hostcache.cc
+++ b/src/hostcache.cc
@@ -62,7 +62,7 @@ bool ResolveHostName(const char *HostName, int *OutAddr){
THostCacheEntry *Entry = NULL;
int LeastRecentlyUsedIndex = 0;
int LeastRecentlyUsedTime = g_CachedHostNames[0].ResolveTime;
- int TimeNow = GetMonotonicUptimeMS();
+ int TimeNow = GetMonotonicUptime();
for(int i = 0; i < g_Config.MaxCachedHostNames; i += 1){
THostCacheEntry *Current = &g_CachedHostNames[i];
diff --git a/src/querymanager.cc b/src/querymanager.cc
index 350b708..4f68d5e 100644
--- a/src/querymanager.cc
+++ b/src/querymanager.cc
@@ -101,8 +101,8 @@ int64 GetClockMonotonicMS(void){
#endif
}
-int GetMonotonicUptimeMS(void){
- return (int)(GetClockMonotonicMS() - g_StartTimeMS);
+int GetMonotonicUptime(void){
+ return (int)((GetClockMonotonicMS() - g_StartTimeMS) / 1000);
}
void SleepMS(int DurationMS){
@@ -342,11 +342,11 @@ bool ParseDuration(int *Dest, const char *String){
}
if(Suffix[0] == 'S' || Suffix[0] == 's'){
- *Dest *= (1000);
+ *Dest *= (1);
}else if(Suffix[0] == 'M' || Suffix[0] == 'm'){
- *Dest *= (60 * 1000);
+ *Dest *= (60);
}else if(Suffix[0] == 'H' || Suffix[0] == 'h'){
- *Dest *= (60 * 60 * 1000);
+ *Dest *= (60 * 60);
}
return true;
@@ -592,7 +592,7 @@ int main(int argc, const char **argv){
// HostCache Config
g_Config.MaxCachedHostNames = 100;
- g_Config.HostNameExpireTime = 30 * 60 * 1000; // milliseconds
+ g_Config.HostNameExpireTime = 60 * 30; // seconds
// Database Config
#if DATABASE_SQLITE
@@ -627,7 +627,7 @@ int main(int argc, const char **argv){
g_Config.QueryBufferSize = (int)MB(1);
g_Config.QueryMaxAttempts = 3;
g_Config.MaxConnections = 25;
- g_Config.MaxConnectionIdleTime = 60 * 1000; // milliseconds
+ g_Config.MaxConnectionIdleTime = 60 * 5; // seconds
LOG("Tibia Query Manager v0.2 (%s)", DATABASE_SYSTEM_NAME);
if(!ReadConfig("config.cfg", &g_Config)){
@@ -636,7 +636,7 @@ int main(int argc, const char **argv){
// NOTE(fusion): Print config values for debugging purposes.
LOG("Max cached host names: %d", g_Config.MaxCachedHostNames);
- LOG("Host name expire time: %dms", g_Config.HostNameExpireTime);
+ LOG("Host name expire time: %ds", g_Config.HostNameExpireTime);
#if DATABASE_SQLITE
LOG("SQLite file: \"%s\"", g_Config.SQLite.File);
LOG("SQLite max cached statements: %d", g_Config.SQLite.MaxCachedStatements);
@@ -664,7 +664,7 @@ int main(int argc, const char **argv){
LOG("Query buffer size: %dB", g_Config.QueryBufferSize);
LOG("Query max attempts: %d", g_Config.QueryMaxAttempts);
LOG("Max connections: %d", g_Config.MaxConnections);
- LOG("Max connection idle time: %dms", g_Config.MaxConnectionIdleTime);
+ LOG("Max connection idle time: %ds", g_Config.MaxConnectionIdleTime);
if(!CheckSHA256()){
return EXIT_FAILURE;
diff --git a/src/querymanager.hh b/src/querymanager.hh
index 46ea80d..220f69a 100644
--- a/src/querymanager.hh
+++ b/src/querymanager.hh
@@ -148,7 +148,7 @@ void LogAddVerbose(const char *Prefix, const char *Function,
struct tm GetLocalTime(time_t t);
struct tm GetGMTime(time_t t);
int64 GetClockMonotonicMS(void);
-int GetMonotonicUptimeMS(void);
+int GetMonotonicUptime(void);
void SleepMS(int DurationMS);
void CryptoRandom(uint8 *Buffer, int Count);
int RoundSecondsToDays(int Seconds);