Permalink
Browse files

Refs #6516. One of several patches for the myth socket timeout problem.

This one is the least important, it just handles ANN error conditions and some timeouts better. However, it is the only one of the patches that changes the protocol slightly, so I'm applying this first.

The protocol change is simply that ANN handling returns "ERROR" followed by the reason for the error instead of nothing for certain error conditions.

Because of the protocol change all backends and frontends must be recompiled.



git-svn-id: http://svn.mythtv.org/svn/trunk@21445 7dbf422c-18fa-0310-86e9-fd20926502f2
  • Loading branch information...
1 parent 78ae555 commit 2fdeb3fc4acf89989a5db341002ecc5d623f572a @daniel-kristjansson daniel-kristjansson committed Aug 23, 2009
@@ -101,7 +101,7 @@ package MythTV;
# MYTH_PROTO_VERSION is defined in libmyth in mythtv/libs/libmyth/mythcontext.h
# and should be the current MythTV protocol version.
- our $PROTO_VERSION = 47;
+ our $PROTO_VERSION = 48;
# NUMPROGRAMLINES is defined in mythtv/libs/libmythtv/programinfo.h and is
# the number of items in a ProgramInfo QStringList group used by
@@ -46,7 +46,7 @@
}
BACKEND_SEP = '[]:[]'
-PROTO_VERSION = 47
+PROTO_VERSION = 48
PROGRAM_FIELDS = 47
class MythTV:
@@ -1452,7 +1452,20 @@ MythSocket *MythContext::ConnectServer(MythSocket *eventSock,
.arg(d->m_localhostname).arg(false);
QStringList strlist(str);
serverSock->writeStringList(strlist);
- serverSock->readStringList(strlist, true);
+ if (!serverSock->readStringList(strlist, true) || strlist.empty() ||
+ (strlist[0] == "ERROR"))
+ {
+ if (strlist[0] == "ERROR")
+ VERBOSE(VB_IMPORTANT, LOC_ERR + "Problem connecting "
+ "server socket to master backend");
+ else
+ VERBOSE(VB_IMPORTANT, LOC_ERR + "Timeout connecting "
+ "server socket to master backend");
+
+ serverSock->DownRef();
+ serverSock = NULL;
+ return NULL;
+ }
if (eventSock && eventSock->state() == MythSocket::Idle)
{
@@ -27,7 +27,7 @@
* mythtv/bindings/python/MythTV/MythTV.py (version number)
* mythtv/bindings/python/MythTV/MythTV.py (layout)
*/
-#define MYTH_PROTO_VERSION "47"
+#define MYTH_PROTO_VERSION "48"
#endif
@@ -65,6 +65,8 @@ MythSocket *RemoteFile::openSocket(bool control)
MythSocket *lsock = new MythSocket();
QString stype = (control) ? "control socket" : "file data socket";
+ QString loc_err = QString("RemoteFile::openSocket(%1), Error: ").arg(stype);
+
if (port <= 0)
{
port = GetMythDB()->GetSettingOnHost("BackendServerPort", host).toInt();
@@ -76,10 +78,9 @@ MythSocket *RemoteFile::openSocket(bool control)
if (!lsock->connect(host, port))
{
- VERBOSE(VB_IMPORTANT,
- QString("RemoteFile::openSocket(%1): \n"
- "\t\t\tCould not connect to server \"%2\" @ port %3")
- .arg(stype).arg(host).arg(port));
+ VERBOSE(VB_IMPORTANT, loc_err +
+ QString("\n\t\t\tCould not connect to server %1:%2")
+ .arg(host).arg(port));
lsock->DownRef();
return NULL;
}
@@ -108,23 +109,43 @@ MythSocket *RemoteFile::openSocket(bool control)
lsock->writeStringList(strlist);
lsock->readStringList(strlist, true);
- if (strlist.size() < 4)
+ if (strlist.size() >= 4)
{
- VERBOSE(VB_IMPORTANT,
- QString("RemoteFile::openSocket(%1): "
- "Did not get proper response from %3:%4")
- .arg(stype).arg(dir).arg(host).arg(port));
-
- return NULL;
+ it = strlist.begin(); ++it;
+ recordernum = (*it).toInt(); ++it;
+ filesize = decodeLongLong(strlist, it);
+ for (; it != strlist.end(); ++it)
+ auxfiles << *it;
+ }
+ else if (0 < strlist.size() && strlist.size() < 4 &&
+ strlist[0] != "ERROR")
+ {
+ VERBOSE(VB_IMPORTANT, loc_err +
+ QString("Did not get proper response from %1:%2")
+ .arg(host).arg(port));
+ strlist.clear();
+ strlist.push_back("ERROR");
+ strlist.push_back("invalid response");
}
+ }
- it = strlist.begin(); ++it;
- recordernum = (*it).toInt(); ++it;
- filesize = decodeLongLong(strlist, it);
- for (; it != strlist.end(); ++it)
- auxfiles << *it;
+ if (strlist.empty() || strlist[0] == "ERROR")
+ {
+ lsock->DownRef();
+ lsock = NULL;
+ if (strlist.empty())
+ {
+ VERBOSE(VB_IMPORTANT, loc_err + "Failed to open socket, timeout");
+ }
+ else
+ {
+ VERBOSE(VB_IMPORTANT, loc_err + "Failed to open socket" +
+ ((strlist.size() >= 2) ?
+ QString(", error was %1").arg(strlist[1]) :
+ QString(", remote error")));
+ }
}
-
+
return lsock;
}
@@ -31,12 +31,34 @@ RemoteEncoder::~RemoteEncoder()
controlSock->DownRef();
}
-void RemoteEncoder::Setup(void)
+bool RemoteEncoder::Setup(void)
{
if (!controlSock)
{
- controlSock = openControlSocket(remotehost, remoteport);
+ VERBOSE(VB_NETWORK|VB_EXTRA, "RemoteEncoder::Setup(): Connecting...");
+
+ QString ann = QString("ANN Playback %1 %2")
+ .arg(gContext->GetHostName()).arg(false);
+
+ controlSock = ConnectCommandSocket(
+ remotehost, remoteport, ann);
+
+ if (controlSock)
+ {
+ VERBOSE(VB_NETWORK|VB_EXTRA, "RemoteEncoder::Setup(): Connected");
+ }
+ else
+ {
+ VERBOSE(VB_IMPORTANT,
+ "RemoteEncoder::Setup(): Failed to connect to backend");
+ }
}
+ else
+ {
+ VERBOSE(VB_NETWORK|VB_EXTRA,
+ "RemoteEncoder::Setup(): Already connected");
+ }
+ return controlSock;
}
bool RemoteEncoder::IsValidRecorder(void)
@@ -54,30 +76,55 @@ bool RemoteEncoder::SendReceiveStringList(
{
QMutexLocker locker(&lock);
if (!controlSock)
- return false;
+ Setup();
backendError = false;
- controlSock->writeStringList(strlist);
- if (!controlSock->readStringList(strlist, true))
+ if (!controlSock)
{
VERBOSE(VB_IMPORTANT,
- "RemoteEncoder::SendReceiveStringList(): No response.");
+ "RemoteEncoder::SendReceiveStringList(): "
+ "Failed to reconnect with backend.");
backendError = true;
return false;
}
- if (min_reply_length && ((uint)strlist.size() < min_reply_length))
+ if (!controlSock->writeStringList(strlist))
+ {
+ VERBOSE(VB_IMPORTANT,
+ "RemoteEncoder::SendReceiveStringList(): "
+ "Failed to write data.");
+ backendError = true;
+ }
+
+ if (!backendError &&
+ !controlSock->readStringList(strlist, true))
+ {
+ VERBOSE(VB_IMPORTANT,
+ "RemoteEncoder::SendReceiveStringList(): No response.");
+ backendError = true;
+ }
+
+ if (!backendError &&
+ min_reply_length && ((uint)strlist.size() < min_reply_length))
{
VERBOSE(VB_IMPORTANT,
"RemoteEncoder::SendReceiveStringList(): Response too short");
+ backendError = true;
+ }
+
+ if (backendError)
+ {
+ controlSock->DownRef();
+ controlSock = NULL;
return false;
}
return true;
}
-MythSocket *RemoteEncoder::openControlSocket(const QString &host, short port)
+MythSocket *RemoteEncoder::ConnectCommandSocket(
+ const QString &host, int port, const QString &ann)
{
MythSocket *sock = new MythSocket();
if (!sock->connect(host, port))
@@ -91,10 +138,16 @@ MythSocket *RemoteEncoder::openControlSocket(const QString &host, short port)
{
if (gContext->CheckProtoVersion(sock))
{
- QString hostname = gContext->GetHostName();
- QStringList strlist( QString("ANN Playback %1 %2").arg(hostname).arg(false) );
- sock->writeStringList(strlist);
- sock->readStringList(strlist, true);
+ QStringList strlist(ann);
+ if (!sock->writeStringList(strlist) ||
+ !sock->readStringList(strlist, true))
+ {
+ VERBOSE(VB_IMPORTANT,
+ "RemoteEncoder::ConnectCommandSocket(): "
+ "Failed to announce ourselves to server");
+ sock->DownRef();
+ sock = NULL;
+ }
}
else
{
@@ -18,7 +18,7 @@ class MPUBLIC RemoteEncoder
RemoteEncoder(int num, const QString &host, short port);
~RemoteEncoder(void);
- void Setup(void);
+ bool Setup(void);
bool IsValidRecorder(void);
int GetRecorderNumber(void);
@@ -69,7 +69,8 @@ class MPUBLIC RemoteEncoder
return v; }
private:
- MythSocket *openControlSocket(const QString &host, short port);
+ MythSocket *ConnectCommandSocket(
+ const QString &host, int port, const QString &ann);
bool SendReceiveStringList(QStringList &strlist, uint min_reply_length = 0);
int recordernum;
@@ -908,10 +908,32 @@ int main(int argc, char **argv)
QStringList tempMonitorAnnounce("ANN Monitor tzcheck 0");
tempMonitorConnection->writeStringList(tempMonitorAnnounce);
tempMonitorConnection->readStringList(tempMonitorAnnounce);
+ if (tempMonitorAnnounce.empty() ||
+ tempMonitorAnnounce[0] == "ERROR")
+ {
+ tempMonitorConnection->DownRef();
+ tempMonitorConnection = NULL;
+ if (tempMonitorAnnounce.empty())
+ {
+ VERBOSE(VB_IMPORTANT, LOC_ERR +
+ "Failed to open event socket, timeout");
+ }
+ else
+ {
+ VERBOSE(VB_IMPORTANT, LOC_ERR +
+ "Failed to open event socket" +
+ ((tempMonitorAnnounce.size() >= 2) ?
+ QString(", error was %1").arg(tempMonitorAnnounce[1]) :
+ QString(", remote error")));
+ }
+ }
QStringList tzCheck("QUERY_TIME_ZONE");
- tempMonitorConnection->writeStringList(tzCheck);
- tempMonitorConnection->readStringList(tzCheck);
+ if (tempMonitorConnection)
+ {
+ tempMonitorConnection->writeStringList(tzCheck);
+ tempMonitorConnection->readStringList(tzCheck);
+ }
if (tzCheck.size() && !checkTimeZone(tzCheck))
{
// Check for different time zones, different offsets, different
@@ -933,9 +955,11 @@ int main(int argc, char **argv)
QString("Backend is running in %1 time zone.")
.arg(getTimeZoneID()));
}
- tempMonitorConnection->writeStringList(tempMonitorDone);
+ if (tempMonitorConnection)
+ tempMonitorConnection->writeStringList(tempMonitorDone);
}
- tempMonitorConnection->DownRef();
+ if (tempMonitorConnection)
+ tempMonitorConnection->DownRef();
}
if (!UpgradeTVDatabaseSchema(true, true))
Oops, something went wrong.

0 comments on commit 2fdeb3f

Please sign in to comment.