Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Added 5 min idle shutdown
When the last client (other than the logserver itself) disconnects, a 5min
timer is started.  If no clients connect during that time, the server will
shut down.  As it is automatically started up by a client that needs it, this
will keep it from running indefinitely when not needed, and also will allow
it to restart cleanly over upgrades.
  • Loading branch information
Beirdo committed May 1, 2012
1 parent a5ab063 commit c2132cf
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 11 deletions.
1 change: 0 additions & 1 deletion mythtv/libs/libmythbase/logging.cpp
Expand Up @@ -363,7 +363,6 @@ void LoggerThread::checkHeartBeat(void)
loggingGetTimeStamp(&epoch, NULL);
qlonglong age = (epoch - m_epoch) % 30;

cout << "age " << age << endl;
if (age == 5)
{
launchLogServer();
Expand Down
63 changes: 56 additions & 7 deletions mythtv/libs/libmythbase/loggingserver.cpp
Expand Up @@ -75,6 +75,8 @@ typedef QMap<LoggerBase *, ClientList *> RevClientMap;
static QMutex logClientMapMutex;
static ClientMap logClientMap;

static QAtomicInt logClientCount;

static QMutex logRevClientMapMutex;
static RevClientMap logRevClientMap;

Expand Down Expand Up @@ -642,9 +644,16 @@ void LogServerThread::run(void)
logThreadStarted.wakeAll();
locker.unlock();

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(checkHeartBeats()));
timer->start(1000);
m_heartbeatTimer = new QTimer(this);
connect(m_heartbeatTimer, SIGNAL(timeout()), this, SLOT(checkHeartBeats()));
m_heartbeatTimer->start(1000);

m_shutdownTimer = new QTimer(this);
m_shutdownTimer->setSingleShot(true);
connect(m_shutdownTimer, SIGNAL(timeout()),
this, SLOT(shutdownTimerExpired()));
LOG(VB_GENERAL, LOG_INFO, "Starting 5min shutdown timer");
m_shutdownTimer->start(5*60*1000);

while (!m_aborted)
{
Expand All @@ -669,8 +678,16 @@ void LogServerThread::run(void)

logThreadFinished = true;

timer->stop();
delete timer;
m_heartbeatTimer->stop();
delete m_heartbeatTimer;

if (m_shutdownTimer)
{
if (m_shutdownTimer->isActive())
m_shutdownTimer->stop();
delete m_shutdownTimer;
m_shutdownTimer = NULL;
}

m_zmqPubSock->setLinger(0);
m_zmqPubSock->close();
Expand Down Expand Up @@ -706,6 +723,19 @@ void LogServerThread::pingClient(QString clientId)
}


/// \brief Fires off when no clients are left (other than the current daemon)
/// for 5 minutes.
void LogServerThread::shutdownTimerExpired(void)
{
m_shutdownTimer->stop();
delete m_shutdownTimer;
m_shutdownTimer = NULL;

LOG(VB_GENERAL, LOG_INFO, "Shutting down because of idleness");
msleep(500);
qApp->quit();
}

/// \brief Handles heartbeat checking once a second. If a client is not heard
/// from for at least 1 second, send it a heartbeat message which it
/// should send back. If we haven't heard from it in 5s, shut down its
Expand Down Expand Up @@ -739,7 +769,9 @@ void LogServerThread::checkHeartBeats(void)
while (!toDel.isEmpty())
{
QString clientId = toDel.takeFirst();
LOG(VB_GENERAL, LOG_INFO, QString("Expiring client %1").arg(clientId));
logClientCount.deref();
LOG(VB_GENERAL, LOG_INFO, QString("Expiring client %1 (#%2)")
.arg(clientId).arg(logClientCount));
LoggerListItem *item = logClientMap.take(clientId);
LoggerList *list = item->list;
delete item;
Expand All @@ -763,6 +795,13 @@ void LogServerThread::checkHeartBeats(void)
}
delete list;
}

// just this daemon left
if (logClientCount == 1 && m_shutdownTimer && !m_shutdownTimer->isActive())
{
LOG(VB_GENERAL, LOG_INFO, "Starting 5min shutdown timer");
m_shutdownTimer->start(5*60*1000);
}
}

/// \brief Handles messages received from logging clients
Expand Down Expand Up @@ -826,7 +865,17 @@ void LogServerThread::forwardMessage(LogMessage *msg)
}
else
{
LOG(VB_GENERAL, LOG_INFO, QString("New Client: %1").arg(clientId));
logClientCount.ref();
LOG(VB_GENERAL, LOG_INFO, QString("New Client: %1 (#%2)")
.arg(clientId).arg(logClientCount));

if (logClientCount > 1 && m_shutdownTimer &&
m_shutdownTimer->isActive())
{
LOG(VB_GENERAL, LOG_INFO, "Aborting shutdown timer");
m_shutdownTimer->stop();
}

QMutexLocker lock2(&loggerMapMutex);
QMutexLocker lock3(&logRevClientMapMutex);

Expand Down
11 changes: 8 additions & 3 deletions mythtv/libs/libmythbase/loggingserver.h
Expand Up @@ -135,16 +135,21 @@ class LogServerThread : public QObject, public MThread
void stop(void);
nzmqt::ZMQContext *getZMQContext(void) { return m_zmqContext; };
private:
bool m_aborted; ///< Flag to abort the thread.
bool m_aborted; ///< Flag to abort the thread.
nzmqt::ZMQContext *m_zmqContext; ///< ZeroMQ context
nzmqt::ZMQSocket *m_zmqInSock; ///< ZeroMQ feeding socket
nzmqt::ZMQSocket *m_zmqPubSock; ///< ZeroMQ publishing socket
nzmqt::ZMQSocket *m_zmqInSock; ///< ZeroMQ feeding socket
nzmqt::ZMQSocket *m_zmqPubSock; ///< ZeroMQ publishing socket

QTimer *m_heartbeatTimer; ///< 1s repeating timer for client
/// heartbeats
QTimer *m_shutdownTimer; ///< 5 min timer to shut down if no clients

void forwardMessage(LogMessage *msg);
void pingClient(QString clientId);
protected slots:
void receivedMessage(const QList<QByteArray>&);
void checkHeartBeats(void);
void shutdownTimerExpired(void);
};

class QWaitCondition;
Expand Down

0 comments on commit c2132cf

Please sign in to comment.