From 24adc1ca13cc0b3b32542191bb2c368f9a7b9c44 Mon Sep 17 00:00:00 2001 From: randomdan Date: Tue, 3 Dec 2013 13:31:25 +0000 Subject: Monitor tuner usage and close them if they go idle for a period of time --- p2pvr/carddaemon/carddaemon.cpp | 4 +++- p2pvr/daemon/daemon.cpp | 4 +++- p2pvr/ice/p2pvr.ice | 1 + p2pvr/lib/bindTimerTask.cpp | 13 +++++++++++++ p2pvr/lib/bindTimerTask.h | 18 ++++++++++++++++++ p2pvr/lib/localDevices.cpp | 31 +++++++++++++++++++++++++++++++ p2pvr/lib/localDevices.h | 10 ++++++++++ p2pvr/lib/tuner.cpp | 17 ++++++++++++++++- p2pvr/lib/tuner.h | 3 +++ 9 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 p2pvr/lib/bindTimerTask.cpp create mode 100644 p2pvr/lib/bindTimerTask.h diff --git a/p2pvr/carddaemon/carddaemon.cpp b/p2pvr/carddaemon/carddaemon.cpp index f75109e..1ea7e43 100644 --- a/p2pvr/carddaemon/carddaemon.cpp +++ b/p2pvr/carddaemon/carddaemon.cpp @@ -18,11 +18,13 @@ class P2PvrCardDaemon : public Daemon { void run() const { + IceUtil::TimerPtr timer = new IceUtil::Timer(); Logger()->messagebf(LOG_INFO, "Creating adapter (%s, %s)", Adapter, Endpoint); auto adapter = ic->createObjectAdapterWithEndpoints(Adapter, Endpoint); - P2PVR::LocalDevicesPrx::checkedCast(adapter->add(new LocalDevices(), ic->stringToIdentity(Identity))); + P2PVR::LocalDevicesPrx::checkedCast(adapter->add(new LocalDevices(adapter, timer), ic->stringToIdentity(Identity))); adapter->activate(); ic->waitForShutdown(); + timer->destroy(); } void shutdown() const diff --git a/p2pvr/daemon/daemon.cpp b/p2pvr/daemon/daemon.cpp index f3fe1ad..4f55685 100644 --- a/p2pvr/daemon/daemon.cpp +++ b/p2pvr/daemon/daemon.cpp @@ -23,9 +23,10 @@ class P2PvrDaemon : public Daemon { void run() const { + IceUtil::TimerPtr timer = new IceUtil::Timer(); Logger()->messagebf(LOG_INFO, "Creating adapter (%s, %s)", Adapter, Endpoint); auto adapter = ic->createObjectAdapterWithEndpoints(Adapter, Endpoint); - adapter->add(new LocalDevices(), ic->stringToIdentity("Devices")); + adapter->add(new LocalDevices(adapter, timer), ic->stringToIdentity("Devices")); adapter->add(new GlobalDevices(), ic->stringToIdentity("GlobalDevices")); adapter->add(new Maintenance(), ic->stringToIdentity("Maintenance")); adapter->add(new SI(), ic->stringToIdentity("SI")); @@ -39,6 +40,7 @@ class P2PvrDaemon : public Daemon { maint->UpdateEvents(FE_OFDM); //ic->waitForShutdown(); + timer->destroy(); } void shutdown() const diff --git a/p2pvr/ice/p2pvr.ice b/p2pvr/ice/p2pvr.ice index 15013de..bae39f8 100644 --- a/p2pvr/ice/p2pvr.ice +++ b/p2pvr/ice/p2pvr.ice @@ -200,6 +200,7 @@ module P2PVR { interface Tuner { idempotent int GetStatus(); + idempotent long GetLastUsedTime(); idempotent void SendNetworkInformation(RawDataClient * client); idempotent void SendBouquetAssociations(RawDataClient * client); diff --git a/p2pvr/lib/bindTimerTask.cpp b/p2pvr/lib/bindTimerTask.cpp new file mode 100644 index 0000000..b3a0150 --- /dev/null +++ b/p2pvr/lib/bindTimerTask.cpp @@ -0,0 +1,13 @@ +#include "bindTimerTask.h" + +BindTimerTask::BindTimerTask(const Event & e) : + event(e) +{ +} + +void +BindTimerTask::runTimerTask() +{ + event(); +} + diff --git a/p2pvr/lib/bindTimerTask.h b/p2pvr/lib/bindTimerTask.h new file mode 100644 index 0000000..8c82680 --- /dev/null +++ b/p2pvr/lib/bindTimerTask.h @@ -0,0 +1,18 @@ +#ifndef BINDTIMERTASK_H +#define BINDTIMERTASK_H + +#include +#include + +class BindTimerTask : public IceUtil::TimerTask { + public: + typedef boost::function Event; + BindTimerTask(const Event & event); + + void runTimerTask(); + private: + const Event event; +}; + +#endif + diff --git a/p2pvr/lib/localDevices.cpp b/p2pvr/lib/localDevices.cpp index b93adee..5bb2b61 100644 --- a/p2pvr/lib/localDevices.cpp +++ b/p2pvr/lib/localDevices.cpp @@ -1,6 +1,7 @@ #include "localDevices.h" #include #include "tuner.h" +#include "bindTimerTask.h" #include LocalDevices::Devices LocalDevices::devices; @@ -14,6 +15,36 @@ DECLARE_OPTIONS(LocalDevices, "P2PVR Devices") "Frontend of DVB devices to use (/dev/dvb/adapterX/frontendY)") END_OPTIONS(LocalDevices); +LocalDevices::LocalDevices(Ice::ObjectAdapterPtr adapter, IceUtil::TimerPtr t) : + timer(t), + clientCheck(new BindTimerTask(boost::bind(&LocalDevices::ClientCheck, this, adapter))) +{ + Logger()->message(LOG_DEBUG, __PRETTY_FUNCTION__); + timer->scheduleRepeated(clientCheck, IceUtil::Time::seconds(30)); +} + +LocalDevices::~LocalDevices() +{ + Logger()->message(LOG_DEBUG, __PRETTY_FUNCTION__); + timer->cancel(clientCheck); +} + +void +LocalDevices::ClientCheck(Ice::ObjectAdapterPtr adapter) +{ + std::lock_guard g(lock); + BOOST_FOREACH(auto & device, devices) { + if (device.second && device.second->tuner->GetLastUsedTime() < time(NULL) - 30) { + Logger()->messagebf(LOG_DEBUG, "%s: Device %s no longer in use", __PRETTY_FUNCTION__, device.first); + auto id = device.second->tuner->ice_getIdentity(); + if (adapter->find(id)) { + adapter->remove(id); + } + device.second.reset(); + } + } +} + P2PVR::TunerPrx LocalDevices::GetTunerSpecific(const DVBSI::DeliveryPtr & delivery, Ice::Long until, const Ice::Current & ice) { diff --git a/p2pvr/lib/localDevices.h b/p2pvr/lib/localDevices.h index a16443c..9e62525 100644 --- a/p2pvr/lib/localDevices.h +++ b/p2pvr/lib/localDevices.h @@ -10,6 +10,9 @@ class LocalDevices : public P2PVR::LocalDevices { public: + LocalDevices(Ice::ObjectAdapterPtr adapter, IceUtil::TimerPtr); + ~LocalDevices(); + P2PVR::TunerPrx GetTunerSpecific(const DVBSI::DeliveryPtr &, Ice::Long until, const Ice::Current &); P2PVR::TunerPrx GetTunerAny(short type, const DVBSI::DeliveryPtr &, Ice::Long until, const Ice::Current &); P2PVR::PrivateTunerPrx GetPrivateTuner(short type, Ice::Long until, const Ice::Current &); @@ -21,6 +24,13 @@ class LocalDevices : public P2PVR::LocalDevices { INITOPTIONS; private: + // Reference to global timer + IceUtil::TimerPtr timer; + IceUtil::TimerTaskPtr clientCheck; + + // Check that registered clients haven't silently gone away + void ClientCheck(Ice::ObjectAdapterPtr adapter); + class OpenTuner { public: OpenTuner(DVBSI::DeliveryPtr, P2PVR::PrivateTunerPrx, Ice::Long, bool); diff --git a/p2pvr/lib/tuner.cpp b/p2pvr/lib/tuner.cpp index 3cfb8a4..b20cc75 100644 --- a/p2pvr/lib/tuner.cpp +++ b/p2pvr/lib/tuner.cpp @@ -23,7 +23,8 @@ Tuner::Tuner(const boost::filesystem::path & df) : deviceFrontend(df), deviceRoot(df.branch_path()), timeout(20000), - backgroundThread(NULL) + backgroundThread(NULL), + lastUsedTime(time(NULL)) { int fd = open(deviceFrontend.string().c_str(), O_RDWR); if (fd < 0) { @@ -65,12 +66,14 @@ Tuner::TuneTo(const DVBSI::DeliveryPtr & mp, const Ice::Current&) int Tuner::GetStatus(const Ice::Current &) { + time(&lastUsedTime); return frontend->GetStatus(); } std::string Tuner::Device() const { + time(&lastUsedTime); return deviceRoot.string(); } @@ -87,6 +90,7 @@ Tuner::OpenDemux() const void Tuner::ScanAndSendNetworkInformation(const P2PVR::RawDataClientPrx & client, const Ice::Current & ice) { + time(&lastUsedTime); frontend->FrequencyScan([this, &client, &ice](long) { try { return (SendPID(0x10, client, ice) > 0); @@ -136,6 +140,7 @@ Tuner::SendEventInformation(const P2PVR::RawDataClientPrx & client, const Ice::C uint64_t Tuner::SendPID(int pid, const P2PVR::RawDataClientPrx & client, const Ice::Current & ice) const { + time(&lastUsedTime); Logger()->messagebf(LOG_DEBUG, "%s: pid = 0x%x", __PRETTY_FUNCTION__, pid); ice.con->createProxy(client->ice_getIdentity()); @@ -200,6 +205,7 @@ Tuner::ReadDemuxAndSend(int demux, const P2PVR::RawDataClientPrx & client) const asyncs.push_back(client->begin_NewData(buf)); packetsSent += 1; + time(&lastUsedTime); asyncs.erase(std::remove_if(asyncs.begin(), asyncs.end(), [&exitFlag, &client](const Ice::AsyncResultPtr & a) { if (a->isCompleted()) { @@ -219,6 +225,7 @@ Tuner::ReadDemuxAndSend(int demux, const P2PVR::RawDataClientPrx & client) const int Tuner::StartSendingTS(const P2PVR::PacketIds & pids, const P2PVR::RawDataClientPrx & client, const Ice::Current &) { + time(&lastUsedTime); Logger()->message(LOG_DEBUG, __PRETTY_FUNCTION__); if (pids.empty()) { throw P2PVR::DeviceError("demux", "Packet Id list cannot be empty", 0); @@ -265,6 +272,7 @@ Tuner::StartSendingTS(const P2PVR::PacketIds & pids, const P2PVR::RawDataClientP void Tuner::StopSendingTS(int handle, const Ice::Current &) { + time(&lastUsedTime); Logger()->message(LOG_DEBUG, __PRETTY_FUNCTION__); std::lock_guard g(lock); if (backgroundClients.find(handle) != backgroundClients.end()) { @@ -326,6 +334,7 @@ Tuner::senderThread() } // Clean up finished async requests asyncs.erase(std::remove_if(asyncs.begin(), asyncs.end(), [this](const AsyncCall & a) { + time(&lastUsedTime); try { if (a.get<1>()->isCompleted()) { if (!a.get<0>()->end_NewData(a.get<1>())) { @@ -357,6 +366,12 @@ Tuner::senderThread() backgroundThread = NULL; Logger()->messagebf(LOG_DEBUG, "%s: Unlocking", __PRETTY_FUNCTION__); lock.unlock(); +} + +Ice::Long +Tuner::GetLastUsedTime(const Ice::Current &) +{ + return lastUsedTime; } bool diff --git a/p2pvr/lib/tuner.h b/p2pvr/lib/tuner.h index 4efde20..08701eb 100644 --- a/p2pvr/lib/tuner.h +++ b/p2pvr/lib/tuner.h @@ -29,6 +29,8 @@ class Tuner : public P2PVR::PrivateTuner { int StartSendingTS(const P2PVR::PacketIds & pids, const P2PVR::RawDataClientPrx & client, const Ice::Current &); void StopSendingTS(int handle, const Ice::Current &); + Ice::Long GetLastUsedTime(const Ice::Current&); + private: static bool crc32(const P2PVR::Data &); int OpenDemux() const; @@ -45,6 +47,7 @@ class Tuner : public P2PVR::PrivateTuner { std::thread * backgroundThread; std::mutex lock; + mutable time_t lastUsedTime; FrontendPtr frontend; }; -- cgit v1.2.3