boost::once_flag DbConnection::m_OnceFlag = BOOST_ONCE_INIT;
DbConnection::DbConnection(void)
- : m_QueryStats(15 * 60)
+ : m_QueryStats(15 * 60), m_PendingQueries(0), m_PendingQueriesTimestamp(0)
{ }
void DbConnection::OnConfigLoaded(void)
ConfigObject::OnActiveChanged.connect(boost::bind(&DbConnection::UpdateObject, this, _1));
}
+void DbConnection::StatsLoggerTimerHandler(void)
+{
+ int pending = GetPendingQueryCount();
+
+ double now = Utility::GetTime();
+ double gradient = (pending - m_PendingQueries) / (now - m_PendingQueriesTimestamp);
+ double timeToZero = -pending / gradient;
+
+ String timeInfo;
+
+ if (pending > GetQueryCount(5)) {
+ timeInfo = " empty in ";
+ if (timeToZero < 0)
+ timeInfo += "infinite time, your database isn't able to keep up";
+ else
+ timeInfo += Utility::FormatDuration(timeToZero);
+ }
+
+ m_PendingQueries = pending;
+ m_PendingQueriesTimestamp = now;
+
+ Log(LogInformation, GetReflectionType()->GetName())
+ << "Query queue items: " << pending
+ << ", query rate: " << std::setw(2) << GetQueryCount(60) / 60.0 << "/s"
+ << " (" << GetQueryCount(60) << "/min " << GetQueryCount(5 * 60) << "/5min " << GetQueryCount(15 * 60) << "/15min);"
+ << timeInfo;
+}
+
void DbConnection::Resume(void)
{
ConfigObject::Resume();
m_CleanUpTimer->SetInterval(60);
m_CleanUpTimer->OnTimerExpired.connect(boost::bind(&DbConnection::CleanUpHandler, this));
m_CleanUpTimer->Start();
+
+ m_StatsLoggerTimer = new Timer();
+ m_StatsLoggerTimer->SetInterval(15);
+ m_StatsLoggerTimer->OnTimerExpired.connect(boost::bind(&DbConnection::StatsLoggerTimerHandler, this));
+ m_StatsLoggerTimer->Start();
}
void DbConnection::Pause(void)
static Timer::Ptr m_ProgramStatusTimer;
static boost::once_flag m_OnceFlag;
+ Timer::Ptr m_StatsLoggerTimer;
+ void StatsLoggerTimerHandler(void);
+
static void InsertRuntimeVariable(const String& key, const Value& value);
static void ProgramStatusHandler(void);
mutable boost::mutex m_StatsMutex;
RingBuffer m_QueryStats;
+ int m_PendingQueries;
+ double m_PendingQueriesTimestamp;
};
struct database_error : virtual std::exception, virtual boost::exception { };
ClearCustomVarTable("customvariables");
ClearCustomVarTable("customvariablestatus");
+ m_QueryQueue.Enqueue(boost::bind(&IdoMysqlConnection::FinishConnect, this, startTime), PriorityLow);
+}
+
+void IdoMysqlConnection::FinishConnect(double startTime)
+{
+ AssertOnWorkQueue();
+
+ if (!GetConnected())
+ return;
+
+ FinishAsyncQueries();
+
Log(LogInformation, "IdoMysqlConnection")
<< "Finished reconnecting to MySQL IDO database in " << std::setw(2) << Utility::GetTime() - startTime << " second(s).";
ClearCustomVarTable("customvariables");
ClearCustomVarTable("customvariablestatus");
+ m_QueryQueue.Enqueue(boost::bind(&IdoPgsqlConnection::FinishConnect, this, startTime), PriorityLow);
+}
+
+void IdoPgsqlConnection::FinishConnect(double startTime)
+{
+ AssertOnWorkQueue();
+
+ if (!GetConnected())
+ return;
+
Log(LogInformation, "IdoPgsqlConnection")
<< "Finished reconnecting to PostgreSQL IDO database in " << std::setw(2) << Utility::GetTime() - startTime << " second(s).";
void TxTimerHandler(void);
void ReconnectTimerHandler(void);
+ void StatsLoggerTimerHandler(void);
+
bool CanExecuteQuery(const DbQuery& query);
void InternalExecuteQuery(const DbQuery& query, DbQueryType *typeOverride = NULL);
void ClearCustomVarTable(const String& table);
void ExceptionHandler(boost::exception_ptr exp);
+
+ void FinishConnect(double startTime);
};
}