Permalink
Browse files

Allow a third argument to be passed to a QUERY_FILE_HASH denoting the

hostname.  The protocol server will now proxy the call through to
whatever backend is specified, if it is connected as a slave backend.
This fixes the issue where video content existing on a slave backend
will only ever have a NULL hash.

Bumping protocol version to 69.
  • Loading branch information...
wagnerrp committed Jul 10, 2011
1 parent 1ad69da commit fb34130d3a7d3c5991fae19c83e0aabb89166783
@@ -106,8 +106,8 @@ package MythTV;
# Note: as of July 21, 2010, this is actually a string, to account for proto
# versions of the form "58a". This will get used if protocol versions are
# changed on a fixes branch ongoing.
- our $PROTO_VERSION = "68";
- our $PROTO_TOKEN = "90094EAD";
+ our $PROTO_VERSION = "69";
+ our $PROTO_TOKEN = "63835135";
# currentDatabaseVersion is defined in libmythtv in
# mythtv/libs/libmythtv/dbcheck.cpp and should be the current MythTV core
@@ -11,8 +11,8 @@ class MythBackend {
// MYTH_PROTO_VERSION is defined in libmyth in mythtv/libs/libmyth/mythcontext.h
// and should be the current MythTV protocol version.
- static $protocol_version = '68';
- static $protocol_token = '90094EAD';
+ static $protocol_version = '69';
+ static $protocol_token = '63835135';
// The character string used by the backend to separate records
static $backend_separator = '[]:[]';
@@ -827,8 +827,8 @@ def getHash(self):
"""Video.getHash() -> file hash"""
if self.host is None:
return None
- be = FileOps(self.host)
- hash = be.getHash(self.filename, 'Videos')
+ be = FileOps(db=self._db)
+ hash = be.getHash(self.filename, 'Videos', self.host)
return hash
def parseFilename(self):
@@ -668,10 +668,12 @@ def deleteFile(self, file, sgroup):
return self.backendCommand(BACKEND_SEP.join(\
['DELETE_FILE',file,sgroup]))
- def getHash(self, file, sgroup):
- """FileOps.getHash(file, storagegroup) -> hash string"""
- return self.backendCommand(BACKEND_SEP.join((\
- 'QUERY_FILE_HASH',file, sgroup)))
+ def getHash(self, file, sgroup, host=None):
+ """FileOps.getHash(file, storagegroup, host) -> hash string"""
+ m = [file, sgroup]
+ if host:
+ m.append(host)
+ return self.backendCommand(BACKEND_SEP.join(m))
def reschedule(self, recordid=-1, wait=False):
"""FileOps.reschedule() -> None"""
@@ -8,8 +8,8 @@
SCHEMA_VERSION = 1278
NVSCHEMA_VERSION = 1007
MUSICSCHEMA_VERSION = 1018
-PROTO_VERSION = '68'
-PROTO_TOKEN = '90094EAD'
+PROTO_VERSION = '69'
+PROTO_TOKEN = '63835135'
BACKEND_SEP = '[]:[]'
INSTALL_PREFIX = '/usr/local'
@@ -35,8 +35,8 @@
* mythtv/bindings/python/MythTV/static.py (version number)
* mythtv/bindings/python/MythTV/mythproto.py (layout)
*/
-#define MYTH_PROTO_VERSION "68"
-#define MYTH_PROTO_TOKEN "90094EAD"
+#define MYTH_PROTO_VERSION "69"
+#define MYTH_PROTO_TOKEN "63835135"
MBASE_PUBLIC const char *GetMythSourceVersion();
#endif
@@ -306,6 +306,7 @@ QString RemoteFile::GetFileHash(const QString &url)
QString result;
QUrl qurl(url);
QString filename = qurl.path();
+ QString hostname = qurl.host();
QString sgroup = qurl.userName();
if (!qurl.fragment().isEmpty() || url.right(1) == "#")
@@ -320,6 +321,7 @@ QString RemoteFile::GetFileHash(const QString &url)
QStringList strlist("QUERY_FILE_HASH");
strlist << filename;
strlist << sgroup;
+ strlist << hostname;
gCoreContext->SendReceiveStringList(strlist);
result = strlist[0];
@@ -635,32 +635,83 @@ bool FileServerHandler::HandleQueryFileHash(SocketHandler *socket,
QStringList &slist)
{
QString storageGroup = "Default";
+ QString hostname = gCoreContext->GetHostName();
+ QString filename = "";
QStringList res;
- if (slist.size() == 3)
- {
+ switch (slist.size()) {
+ case 4:
+ if (!slist[3].isEmpty())
+ hostname = slist[3];
+ case 3:
if (!slist[2].isEmpty())
storageGroup = slist[2];
- }
- else if (slist.size() != 2)
+ case 2:
+ filename = slist[1];
+ if (filename.isEmpty() ||
+ filename.contains("/../") ||
+ filename.startsWith("../"))
+ {
+ LOG(VB_GENERAL, LOG_ERR,
+ QString("ERROR checking for file, filename '%1' "
+ "fails sanity checks").arg(filename));
+ res << "";
+ socket->SendStringList(res);
+ return true;
+ }
+ break;
+ default:
return false;
+ }
- QString filename = slist[1];
- if ((filename.isEmpty()) ||
- (filename.contains("/../")) ||
- (filename.startsWith("../")))
+ QString hash = "";
+
+ if (hostname == gCoreContext->GetHostName())
{
- LOG(VB_GENERAL, LOG_ERR,
- QString("ERROR checking for file, filename '%1' "
- "fails sanity checks").arg(filename));
- res << "";
- socket->SendStringList(res);
- return true;
+ // looking for file on me, return directly
+ StorageGroup sgroup(storageGroup, gCoreContext->GetHostName());
+ QString fullname = sgroup.FindFile(filename);
+ hash = FileHash(fullname);
+ }
+ else
+ {
+ QReadLocker rlock(&m_fsLock);
+ if (m_fsMap.contains(hostname))
+ {
+ // looking for file on connected host, query from it
+ if (m_fsMap[hostname]->SendReceiveStringList(slist))
+ hash = slist[0];
+ }
+ else
+ {
+ // looking for file on unknown host
+ // assume host is an IP address, and look for matching
+ // entry in database
+ MSqlQuery query(MSqlQuery::InitCon());
+ query.prepare("SELECT hostname FROM settings "
+ "WHERE value='BackendServerIP' "
+ "AND data=:HOSTNAME;");
+ query.bindValue(":HOSTNAME", hostname);
+
+ if (query.exec() && query.next())
+ {
+ // address matches an entry
+ hostname = query.value(0).toString();
+ if (m_fsMap.contains(hostname))
+ {
+ // entry matches a connection
+ slist.clear();
+ slist << "QUERY_FILE_HASH"
+ << filename
+ << storageGroup;
+
+ if (m_fsMap[hostname]->SendReceiveStringList(slist))
+ hash = slist[0];
+ }
+ }
+ }
}
- StorageGroup sgroup(storageGroup, gCoreContext->GetHostName());
- QString fullname = sgroup.FindFile(filename);
- QString hash = FileHash(fullname);
res << hash;
socket->SendStringList(res);
@@ -2877,36 +2877,78 @@ void MainServer::HandleQueryCheckFile(QStringList &slist, PlaybackSock *pbs)
*/
void MainServer::HandleQueryFileHash(QStringList &slist, PlaybackSock *pbs)
{
- QString filename = slist[1];
QString storageGroup = "Default";
- QStringList retlist;
-
- if (slist.size() > 2)
- storageGroup = slist[2];
-
- if ((filename.isEmpty()) ||
- (filename.contains("/../")) ||
- (filename.startsWith("../")))
- {
- LOG(VB_GENERAL, LOG_ERR,
- QString("ERROR checking for file, filename '%1' "
- "fails sanity checks").arg(filename));
- retlist << "";
- SendResponse(pbs->getSocket(), retlist);
+ QString hostname = gCoreContext->GetHostName();
+ QString filename = "";
+ QStringList res;
+
+ switch (slist.size()) {
+ case 4:
+ if (!slist[3].isEmpty())
+ hostname = slist[3];
+ case 3:
+ if (slist[2].isEmpty())
+ storageGroup = slist[2];
+ case 2:
+ filename = slist[1];
+ if (filename.isEmpty() ||
+ filename.contains("/../") ||
+ filename.startsWith("../"))
+ {
+ LOG(VB_GENERAL, LOG_ERR,
+ QString("ERROR checking for file, filename '%1' "
+ "fails sanity checks").arg(filename));
+ res << "";
+ SendResponse(pbs->getSocket(), res);
+ return;
+ }
+ break;
+ default:
+ LOG(VB_GENERAL, LOG_ERR, "ERROR, invalid input count for QUERY_FILE_HASH");
+ res << "";
+ SendResponse(pbs->getSocket(), res);
return;
}
- if (storageGroup.isEmpty())
- storageGroup = "Default";
+ QString hash = "";
- StorageGroup sgroup(storageGroup, gCoreContext->GetHostName());
-
- QString fullname = sgroup.FindFile(filename);
- QString hash = FileHash(fullname);
+ if (hostname == gCoreContext->GetHostName())
+ {
+ StorageGroup sgroup(storageGroup, gCoreContext->GetHostName());
+ QString fullname = sgroup.FindFile(filename);
+ hash = FileHash(fullname);
+ }
+ else
+ {
+ PlaybackSock *slave = GetSlaveByHostname(hostname);
+ if (slave)
+ {
+ hash = slave->GetFileHash(filename, storageGroup);
+ slave->DownRef();
+ }
+ else
+ {
+ MSqlQuery query(MSqlQuery::InitCon());
+ query.prepare("SELECT hostname FROM settings "
+ "WHERE value='BackendServerIP' "
+ "AND data=:HOSTNAME;");
+ query.bindValue(":HOSTNAME", hostname);
- retlist << hash;
+ if (query.exec() && query.next())
+ {
+ hostname = query.value(0).toString();
+ slave = GetSlaveByHostname(hostname);
+ if (slave)
+ {
+ hash = slave->GetFileHash(filename, storageGroup);
+ slave->DownRef();
+ }
+ }
+ }
+ }
- SendResponse(pbs->getSocket(), retlist);
+ res << hash;
+ SendResponse(pbs->getSocket(), res);
}
/**
@@ -263,6 +263,16 @@ QStringList PlaybackSock::GetSGFileQuery(QString &host, QString &groupname,
return strlist;
}
+QString PlaybackSock::GetFileHash(QString filename, QString storageGroup)
+{
+ QStringList strlist(QString("QUERY_FILE_HASH"));
+ strlist << filename
+ << storageGroup;
+
+ SendReceiveStringList(strlist);
+ return strlist[0];
+}
+
QStringList PlaybackSock::GenPreviewPixmap(const QString &token,
const ProgramInfo *pginfo)
{
@@ -69,6 +69,7 @@ class PlaybackSock
QString &directory, bool fileNamesOnly);
QStringList GetSGFileQuery(QString &host, QString &groupname,
QString &filename);
+ QString GetFileHash(QString filename, QString storageGroup);
QStringList GenPreviewPixmap(const QString &token,
const ProgramInfo *pginfo);

0 comments on commit fb34130

Please sign in to comment.