Skip to content

Commit

Permalink
WOA - wake on access
Browse files Browse the repository at this point in the history
just-in-time wake-on-lan of mysql or file-server
  • Loading branch information
t4-ravenbird committed Jul 18, 2012
1 parent b4c6016 commit cadd92d
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 0 deletions.
106 changes: 106 additions & 0 deletions xbmc/Util.cpp
Expand Up @@ -96,6 +96,7 @@
#ifdef HAVE_LIBCAP
#include <sys/capability.h>
#endif
#include "dialogs/GUIDialogBusy.h"

using namespace std;
using namespace XFILE;
Expand Down Expand Up @@ -2580,3 +2581,108 @@ bool CUtil::CanBindPrivileged()
#endif //_LINUX
}

//

static void WaitWithBusyDialog (unsigned wait_ms)
{
CGUIDialogBusy* dialog = 0;

if (g_application.IsCurrentThread() && wait_ms > 600)
dialog = (CGUIDialogBusy*) g_windowManager.GetWindow(WINDOW_DIALOG_BUSY);

if (dialog)
{
CSingleExit ex(g_graphicsContext);

dialog->Show();

while (wait_ms > 300)
{
CSingleLock lock(g_graphicsContext);

g_windowManager.ProcessRenderLoop();

if (dialog->IsCanceled())
{
wait_ms = 0;
}
else
{
Sleep (20);

wait_ms -= 20;
}
}

dialog->Close();
}

Sleep (wait_ms);
}

void CUtil::WakeUpHost (const CStdString& hostName, const CStdString& targetName)
{
for (CAdvancedSettings::OnAccessWakeup::Map::iterator i = g_advancedSettings.m_onAccessWakeUp.entrymap.begin();
i != g_advancedSettings.m_onAccessWakeUp.entrymap.end(); ++i)
{
CAdvancedSettings::OnAccessWakeup::WakeUpEntry& entry = *i;

if (hostName.CompareNoCase(entry.host) == 0)
{
// concurrency ; even if we have multiple threads coming here the worst thing
// that can happen is that we accidentally issue 2 wakeups

bool dowake = entry.nextWake.IsTimePast();

entry.nextWake.Set (entry.timeout_ms);

if (dowake)
{
CLog::Log(LOGDEBUG,"WakeOnAccess [%s] trigged by accessing : %s", entry.host.c_str(), targetName.c_str());

CNetwork& network = g_application.getNetwork();

{ // loop until network connected before sending wake-on-lan

int retry_ms = g_advancedSettings.m_onAccessWakeUp.netinit_ms;

while (retry_ms > 0)
{
if (network.IsConnected())
{
retry_ms = 0;
}
else
{
WaitWithBusyDialog (800);

retry_ms -= 800;
}
}
}

if (network.WakeOnLan(entry.mac.c_str()))
{
WaitWithBusyDialog (entry.wait_ms);
}
}

return; // done
}
}
}

void CUtil::WakeUpFileHost(const CURL& url)
{
CStdString hostName = url.GetHostName();

if (!hostName.IsEmpty())
WakeUpHost (hostName, url.Get());
}

void CUtil::WakeUpFileHost(const CStdString& realFilePath)
{
CURL url = realFilePath;

WakeUpFileHost(url);
}
4 changes: 4 additions & 0 deletions xbmc/Util.h
Expand Up @@ -186,6 +186,10 @@ class CUtil
static CStdString GetFrameworksPath(bool forPython = false);

static bool CanBindPrivileged();

static void WakeUpHost(const CStdString& hostName, const CStdString& targetName);
static void WakeUpFileHost(const CURL& realFilePath);
static void WakeUpFileHost(const CStdString& realFilePath);
};


2 changes: 2 additions & 0 deletions xbmc/dbwrappers/Database.cpp
Expand Up @@ -404,6 +404,8 @@ bool CDatabase::Connect(const CStdString &dbName, const DatabaseSettings &dbSett
m_pDS.reset(m_pDB->CreateDataset());
m_pDS2.reset(m_pDB->CreateDataset());

CUtil::WakeUpHost (dbSettings.host, "DataBase:" + dbSettings.name); // in case of mysql or other remote db

if (m_pDB->connect(create) != DB_CONNECTION_OK)
return false;

Expand Down
6 changes: 6 additions & 0 deletions xbmc/filesystem/Directory.cpp
Expand Up @@ -34,6 +34,7 @@
#include "dialogs/GUIDialogBusy.h"
#include "threads/SingleLock.h"
#include "utils/URIUtils.h"
#include "Util.h"

using namespace std;
using namespace XFILE;
Expand Down Expand Up @@ -138,6 +139,8 @@ bool CDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items, c
items.SetPath(strPath);
else
{
CUtil::WakeUpFileHost(realPath);

// need to clear the cache (in case the directory fetch fails)
// and (re)fetch the folder
if (!(hints.flags & DIR_FLAG_BYPASS_CACHE))
Expand Down Expand Up @@ -230,6 +233,7 @@ bool CDirectory::Create(const CStdString& strPath)
try
{
CStdString realPath = URIUtils::SubstitutePath(strPath);
CUtil::WakeUpFileHost(realPath);
auto_ptr<IDirectory> pDirectory(CDirectoryFactory::Create(realPath));
if (pDirectory.get())
if(pDirectory->Create(realPath.c_str()))
Expand All @@ -249,6 +253,7 @@ bool CDirectory::Exists(const CStdString& strPath)
try
{
CStdString realPath = URIUtils::SubstitutePath(strPath);
CUtil::WakeUpFileHost(realPath);
auto_ptr<IDirectory> pDirectory(CDirectoryFactory::Create(realPath));
if (pDirectory.get())
return pDirectory->Exists(realPath.c_str());
Expand All @@ -267,6 +272,7 @@ bool CDirectory::Remove(const CStdString& strPath)
try
{
CStdString realPath = URIUtils::SubstitutePath(strPath);
CUtil::WakeUpFileHost(realPath);
auto_ptr<IDirectory> pDirectory(CDirectoryFactory::Create(realPath));
if (pDirectory.get())
if(pDirectory->Remove(realPath.c_str()))
Expand Down
7 changes: 7 additions & 0 deletions xbmc/filesystem/File.cpp
Expand Up @@ -224,6 +224,7 @@ bool CFile::Open(const CStdString& strFileName, unsigned int flags)
}

CURL url(URIUtils::SubstitutePath(strFileName));
CUtil::WakeUpFileHost(url);
if ( (flags & READ_NO_CACHE) == 0 && URIUtils::IsInternetStream(url, true) && !CUtil::IsPicture(strFileName) )
m_flags |= READ_CACHED;

Expand Down Expand Up @@ -310,6 +311,7 @@ bool CFile::OpenForWrite(const CStdString& strFileName, bool bOverWrite)
try
{
CURL url(URIUtils::SubstitutePath(strFileName));
CUtil::WakeUpFileHost(url);

m_pFile = CFileFactory::CreateLoader(url);
if (m_pFile && m_pFile->OpenForWrite(url, bOverWrite))
Expand Down Expand Up @@ -348,6 +350,7 @@ bool CFile::Exists(const CStdString& strFileName, bool bUseCache /* = true */)
}

url = URIUtils::SubstitutePath(strFileName);
CUtil::WakeUpFileHost(url);
auto_ptr<IFile> pFile(CFileFactory::CreateLoader(url));
if (!pFile.get())
return false;
Expand Down Expand Up @@ -402,6 +405,7 @@ int CFile::Stat(const CStdString& strFileName, struct __stat64* buffer)
try
{
url = URIUtils::SubstitutePath(strFileName);
CUtil::WakeUpFileHost(url);

auto_ptr<IFile> pFile(CFileFactory::CreateLoader(url));
if (!pFile.get())
Expand Down Expand Up @@ -680,6 +684,7 @@ bool CFile::Delete(const CStdString& strFileName)
try
{
CURL url(URIUtils::SubstitutePath(strFileName));
CUtil::WakeUpFileHost(url);

auto_ptr<IFile> pFile(CFileFactory::CreateLoader(url));
if (!pFile.get())
Expand Down Expand Up @@ -707,6 +712,7 @@ bool CFile::Rename(const CStdString& strFileName, const CStdString& strNewFileNa
{
CURL url(URIUtils::SubstitutePath(strFileName));
CURL urlnew(URIUtils::SubstitutePath(strNewFileName));
CUtil::WakeUpFileHost(url);

auto_ptr<IFile> pFile(CFileFactory::CreateLoader(url));
if (!pFile.get())
Expand All @@ -733,6 +739,7 @@ bool CFile::SetHidden(const CStdString& fileName, bool hidden)
try
{
CURL url(URIUtils::SubstitutePath(fileName));
CUtil::WakeUpFileHost(url);

auto_ptr<IFile> pFile(CFileFactory::CreateLoader(url));
if (!pFile.get())
Expand Down
69 changes: 69 additions & 0 deletions xbmc/settings/AdvancedSettings.cpp
Expand Up @@ -880,6 +880,75 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file)
}
}

// on access - wake on lan
TiXmlElement* pOnAccessWakeUp = pRootElement->FirstChildElement("onaccesswakeup");
if (pOnAccessWakeUp)
{
CLog::Log(LOGDEBUG,"Configuring OnAccess wakeup");

m_onAccessWakeUp.entrymap.clear();

int netinit = 10 ; //seconds .. 10 default
{
const int _min = 0, _max = 2*60; // 2 minutes ..

XMLUtils::GetInt(pOnAccessWakeUp, "netinittimeout", netinit, _min, _max);
}
m_onAccessWakeUp.netinit_ms = netinit * 1000;

CLog::Log(LOGDEBUG,"Network init timeout : [%d] sec", m_onAccessWakeUp.netinit_ms / 1000);

TiXmlNode* pWakeUp = pOnAccessWakeUp->FirstChildElement("wakeup");
while (pWakeUp)
{
CStdString strHost, strMac;
TiXmlNode* pHost = pWakeUp->FirstChild("host");
if (pHost)
strHost = pHost->FirstChild()->Value();
TiXmlNode* pMac = pWakeUp->FirstChild("mac");
if (pMac)
strMac = pMac->FirstChild()->Value();

if (strHost.IsEmpty())
CLog::Log(LOGERROR," Missing <host> tag");
else if (strMac.IsEmpty())
CLog::Log(LOGERROR," Missing <mac> tag");
else
{
int tmout = 600 ; //seconds .. 10 min default
{
const int _min = 10, _max = 12*60*60;

XMLUtils::GetInt(pWakeUp, "tmout", tmout, _min, _max);
}
int wait = 0 ; //seconds .. 0 default
{
const int _min = 0, _max = 2*60; // 2 minutes ..

XMLUtils::GetInt(pWakeUp, "wait", wait, _min, _max);
}

CAdvancedSettings::OnAccessWakeup::WakeUpEntry entry;

entry.host = strHost;
entry.mac = strMac;
entry.timeout_ms = tmout * 1000;
entry.wait_ms = wait * 1000;

CLog::Log(LOGDEBUG," Registering wakeup entry:");
CLog::Log(LOGDEBUG," HostName : [%s]", entry.host.c_str());
CLog::Log(LOGDEBUG," MacAddress : [%s]", entry.mac.c_str());
CLog::Log(LOGDEBUG," Timeout (sec) : [%d]", entry.timeout_ms / 1000);
CLog::Log(LOGDEBUG," WaitTime (sec) : [%d]", entry.wait_ms / 1000);

m_onAccessWakeUp.entrymap.push_back (entry);
}

// get next one
pWakeUp = pWakeUp->NextSiblingElement("wakeup");
}
}

XMLUtils::GetInt(pRootElement, "remotedelay", m_remoteDelay, 1, 20);
XMLUtils::GetFloat(pRootElement, "controllerdeadzone", m_controllerDeadzone, 0.0f, 1.0f);
XMLUtils::GetInt(pRootElement, "fanartres", m_fanartRes, 0, 1080);
Expand Down
17 changes: 17 additions & 0 deletions xbmc/settings/AdvancedSettings.h
Expand Up @@ -23,6 +23,7 @@
#include <vector>
#include "utils/StdString.h"
#include "utils/GlobalsHandling.h"
#include "threads/SystemClock.h"

class TiXmlElement;

Expand Down Expand Up @@ -207,6 +208,22 @@ class CAdvancedSettings
CStdString m_tvshowMultiPartEnumRegExp;
typedef std::vector< std::pair<CStdString, CStdString> > StringMapping;
StringMapping m_pathSubstitutions;

struct OnAccessWakeup
{
unsigned netinit_ms; //time to wait for network connection

struct WakeUpEntry
{
CStdString host, mac;
unsigned timeout_ms, wait_ms;
XbmcThreads::EndTime nextWake;
};
typedef std::vector<WakeUpEntry> Map;
Map entrymap; //list of 'onaccesswake' hosts

} m_onAccessWakeUp;

int m_remoteDelay; ///< \brief number of remote messages to ignore before repeating
float m_controllerDeadzone;

Expand Down

0 comments on commit cadd92d

Please sign in to comment.