summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2013-12-03 13:31:25 +0000
committerrandomdan <randomdan@localhost>2013-12-03 13:31:25 +0000
commit24adc1ca13cc0b3b32542191bb2c368f9a7b9c44 (patch)
tree6bdb51c1bfa641323a4db49f87a8a149516771c9
parentChanges to add downloading program association table and program map (big mes... (diff)
downloadp2pvr-24adc1ca13cc0b3b32542191bb2c368f9a7b9c44.tar.bz2
p2pvr-24adc1ca13cc0b3b32542191bb2c368f9a7b9c44.tar.xz
p2pvr-24adc1ca13cc0b3b32542191bb2c368f9a7b9c44.zip
Monitor tuner usage and close them if they go idle for a period of time
-rw-r--r--p2pvr/carddaemon/carddaemon.cpp4
-rw-r--r--p2pvr/daemon/daemon.cpp4
-rw-r--r--p2pvr/ice/p2pvr.ice1
-rw-r--r--p2pvr/lib/bindTimerTask.cpp13
-rw-r--r--p2pvr/lib/bindTimerTask.h18
-rw-r--r--p2pvr/lib/localDevices.cpp31
-rw-r--r--p2pvr/lib/localDevices.h10
-rw-r--r--p2pvr/lib/tuner.cpp17
-rw-r--r--p2pvr/lib/tuner.h3
9 files changed, 98 insertions, 3 deletions
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 <boost/function.hpp>
+#include <IceUtil/Timer.h>
+
+class BindTimerTask : public IceUtil::TimerTask {
+ public:
+ typedef boost::function<void()> 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 <Ice/Ice.h>
#include "tuner.h"
+#include "bindTimerTask.h"
#include <logger.h>
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<std::mutex> 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<std::mutex> 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;
};