Finalized error propagation and debug level setting code.
This commit is contained in:
parent
75c5af4575
commit
1174773244
5 changed files with 91 additions and 38 deletions
|
@ -287,6 +287,7 @@ void createAccount (std::string account){
|
||||||
|
|
||||||
///\brief The main entry point for the controller.
|
///\brief The main entry point for the controller.
|
||||||
int main(int argc, char ** argv){
|
int main(int argc, char ** argv){
|
||||||
|
|
||||||
Controller::Storage = JSON::fromFile("config.json");
|
Controller::Storage = JSON::fromFile("config.json");
|
||||||
JSON::Value stored_port = JSON::fromString("{\"long\":\"port\", \"short\":\"p\", \"arg\":\"integer\", \"help\":\"TCP port to listen on.\"}");
|
JSON::Value stored_port = JSON::fromString("{\"long\":\"port\", \"short\":\"p\", \"arg\":\"integer\", \"help\":\"TCP port to listen on.\"}");
|
||||||
stored_port["default"] = Controller::Storage["config"]["controller"]["port"];
|
stored_port["default"] = Controller::Storage["config"]["controller"]["port"];
|
||||||
|
@ -353,6 +354,18 @@ int main(int argc, char ** argv){
|
||||||
//Input custom config here
|
//Input custom config here
|
||||||
Controller::Storage = JSON::fromFile(Controller::conf.getString("configFile"));
|
Controller::Storage = JSON::fromFile(Controller::conf.getString("configFile"));
|
||||||
|
|
||||||
|
{
|
||||||
|
//spawn thread that reads stderr of process
|
||||||
|
int pipeErr[2];
|
||||||
|
if (pipe(pipeErr) >= 0){
|
||||||
|
dup2(pipeErr[1], STDERR_FILENO);//cause stderr to write to the pipe
|
||||||
|
close(pipeErr[1]);//close the unneeded pipe file descriptor
|
||||||
|
tthread::thread msghandler(Controller::handleMsg, (void*)(((char*)0) + pipeErr[0]));
|
||||||
|
msghandler.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (Controller::conf.getOption("debug",true).size() > 1){
|
if (Controller::conf.getOption("debug",true).size() > 1){
|
||||||
Controller::Storage["config"]["debug"] = Controller::conf.getInteger("debug");
|
Controller::Storage["config"]["debug"] = Controller::conf.getInteger("debug");
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <mist/procs.h>
|
#include <mist/procs.h>
|
||||||
#include <mist/timing.h>
|
#include <mist/timing.h>
|
||||||
#include <mist/tinythread.h>
|
#include <mist/tinythread.h>
|
||||||
|
#include <mist/defines.h>
|
||||||
#include "controller_storage.h"
|
#include "controller_storage.h"
|
||||||
#include "controller_connectors.h"
|
#include "controller_connectors.h"
|
||||||
|
|
||||||
|
@ -38,18 +39,28 @@ namespace Controller {
|
||||||
|
|
||||||
static inline void builPipedPart(JSON::Value & p, char * argarr[], int & argnum, JSON::Value & argset){
|
static inline void builPipedPart(JSON::Value & p, char * argarr[], int & argnum, JSON::Value & argset){
|
||||||
for (JSON::ObjIter it = argset.ObjBegin(); it != argset.ObjEnd(); ++it){
|
for (JSON::ObjIter it = argset.ObjBegin(); it != argset.ObjEnd(); ++it){
|
||||||
if (it->second.isMember("option") && p.isMember(it->first)){
|
if (it->second.isMember("option")){
|
||||||
if (it->second.isMember("type")){
|
if (p.isMember(it->first)){
|
||||||
if (it->second["type"].asStringRef() == "str" && !p[it->first].isString()){
|
if (it->second.isMember("type")){
|
||||||
p[it->first] = p[it->first].asString();
|
if (it->second["type"].asStringRef() == "str" && !p[it->first].isString()){
|
||||||
|
p[it->first] = p[it->first].asString();
|
||||||
|
}
|
||||||
|
if ((it->second["type"].asStringRef() == "uint" || it->second["type"].asStringRef() == "int") && !p[it->first].isInt()){
|
||||||
|
p[it->first] = p[it->first].asString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((it->second["type"].asStringRef() == "uint" || it->second["type"].asStringRef() == "int") && !p[it->first].isInt()){
|
if (p[it->first].asStringRef().size() > 0){
|
||||||
p[it->first] = JSON::Value(p[it->first].asInt()).asString();
|
argarr[argnum++] = (char*)(it->second["option"].c_str());
|
||||||
|
argarr[argnum++] = (char*)(p[it->first].c_str());
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if (it->first == "debug"){
|
||||||
|
static std::string debugLvlStr;
|
||||||
|
debugLvlStr = JSON::Value((long long)Util::Config::printDebugLevel).asString();
|
||||||
|
argarr[argnum++] = (char*)(it->second["option"].c_str());
|
||||||
|
argarr[argnum++] = (char*)debugLvlStr.c_str();
|
||||||
|
DEVEL_MSG("Setting debug for %s to %s", p["connector"].asStringRef().c_str(), debugLvlStr.c_str());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (p[it->first].asStringRef().size() > 0){
|
|
||||||
argarr[argnum++] = (char*)(it->second["option"].c_str());
|
|
||||||
argarr[argnum++] = (char*)(p[it->first].c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,24 +84,6 @@ namespace Controller {
|
||||||
if (pipedCapa.isMember("optional")){builPipedPart(p, argarr, argnum, pipedCapa["optional"]);}
|
if (pipedCapa.isMember("optional")){builPipedPart(p, argarr, argnum, pipedCapa["optional"]);}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleMsg(void * err){
|
|
||||||
char buf[1024];
|
|
||||||
FILE * output = fdopen((long long int)err, "r");
|
|
||||||
while (fgets(buf, 1024, output)){
|
|
||||||
unsigned int i = 0;
|
|
||||||
while (i < 9 && buf[i] != ' '){
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
if(i < 9){
|
|
||||||
buf[i] = 0;
|
|
||||||
Log(buf,buf+i+1);
|
|
||||||
}else{
|
|
||||||
printf("%s\n",buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///\brief Checks current protocol coguration, updates state of enabled connectors if neccesary.
|
///\brief Checks current protocol coguration, updates state of enabled connectors if neccesary.
|
||||||
///\param p An object containing all protocols.
|
///\param p An object containing all protocols.
|
||||||
///\param capabilities An object containing the detected capabilities.
|
///\param capabilities An object containing the detected capabilities.
|
||||||
|
@ -109,14 +102,18 @@ namespace Controller {
|
||||||
long long counter = 0;
|
long long counter = 0;
|
||||||
|
|
||||||
for (JSON::ArrIter ait = p.ArrBegin(); ait != p.ArrEnd(); ait++){
|
for (JSON::ArrIter ait = p.ArrBegin(); ait != p.ArrEnd(); ait++){
|
||||||
( *ait).removeMember("online");
|
std::string prevOnline = ( *ait)["online"].asString();
|
||||||
#define connName (*ait)["connector"].asStringRef()
|
#define connName (*ait)["connector"].asStringRef()
|
||||||
if ( !(*ait).isMember("connector") || connName == ""){
|
if ( !(*ait).isMember("connector") || connName == ""){
|
||||||
|
( *ait)["online"] = "Missing connector name";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !capabilities["connectors"].isMember(connName)){
|
if ( !capabilities["connectors"].isMember(connName)){
|
||||||
Log("WARN", connName + " connector is enabled but doesn't exist on system! Ignoring connector.");
|
( *ait)["online"] = "Not installed";
|
||||||
|
if (( *ait)["online"].asString() != prevOnline){
|
||||||
|
Log("WARN", connName + " connector is enabled but doesn't exist on system! Ignoring connector.");
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,13 +123,17 @@ namespace Controller {
|
||||||
for (JSON::ObjIter it = connCapa["required"].ObjBegin(); it != connCapa["required"].ObjEnd(); ++it){
|
for (JSON::ObjIter it = connCapa["required"].ObjBegin(); it != connCapa["required"].ObjEnd(); ++it){
|
||||||
if ( !(*ait).isMember(it->first) || (*ait)[it->first].asStringRef().size() < 1){
|
if ( !(*ait).isMember(it->first) || (*ait)[it->first].asStringRef().size() < 1){
|
||||||
gotAll = false;
|
gotAll = false;
|
||||||
Log("WARN", connName + " connector is missing required parameter " + it->first + "! Ignoring connector.");
|
( *ait)["online"] = "Invalid configuration";
|
||||||
|
if (( *ait)["online"].asString() != prevOnline){
|
||||||
|
Log("WARN", connName + " connector is missing required parameter " + it->first + "! Ignoring connector.");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!gotAll){continue;}
|
if (!gotAll){continue;}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
( *ait).removeMember("online");
|
||||||
/// \todo Check dependencies?
|
/// \todo Check dependencies?
|
||||||
|
|
||||||
new_connectors[counter] = (*ait).toString();
|
new_connectors[counter] = (*ait).toString();
|
||||||
|
@ -164,9 +165,9 @@ namespace Controller {
|
||||||
err = -1;
|
err = -1;
|
||||||
Util::Procs::StartPiped(toConn(iter->first), argarr, &zero, &out, &err);//redirects output to out. Must make a new pipe, redirect std err
|
Util::Procs::StartPiped(toConn(iter->first), argarr, &zero, &out, &err);//redirects output to out. Must make a new pipe, redirect std err
|
||||||
if(err != -1){
|
if(err != -1){
|
||||||
//spawn new thread where err is read, it reads err until there is nothing more to be read
|
//spawn thread that reads stderr of process
|
||||||
tthread::thread * msghandler = new tthread::thread(handleMsg, (void*)err);
|
tthread::thread msghandler(Controller::handleMsg, (void*)(((char*)0) + err));
|
||||||
msghandler->detach();
|
msghandler.detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,5 +38,33 @@ namespace Controller {
|
||||||
File.close();
|
File.close();
|
||||||
return File.good();
|
return File.good();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handles output of a Mist application, detecting and catching debug messages.
|
||||||
|
/// Debug messages are automatically converted into Log messages.
|
||||||
|
/// Closes the file descriptor on read error.
|
||||||
|
/// \param err File descriptor of the stderr output of the process to monitor.
|
||||||
|
void handleMsg(void * err){
|
||||||
|
char buf[1024];
|
||||||
|
FILE * output = fdopen((long long int)err, "r");
|
||||||
|
while (fgets(buf, 1024, output)){
|
||||||
|
unsigned int i = 0;
|
||||||
|
while (i < 9 && buf[i] != '|' && buf[i] != 0){
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
unsigned int j = i;
|
||||||
|
while (j < 1024 && buf[j] != '\n' && buf[j] != 0){
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
buf[j] = 0;
|
||||||
|
if(i < 9){
|
||||||
|
buf[i] = 0;
|
||||||
|
Log(buf,buf+i+1);
|
||||||
|
}else{
|
||||||
|
printf("%s", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(output);
|
||||||
|
close((long long int)err);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,5 +13,7 @@ namespace Controller {
|
||||||
|
|
||||||
/// Write contents to Filename.
|
/// Write contents to Filename.
|
||||||
bool WriteFile(std::string Filename, std::string contents);
|
bool WriteFile(std::string Filename, std::string contents);
|
||||||
|
|
||||||
|
void handleMsg(void * err);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ namespace Controller {
|
||||||
///\param name The name of the stream
|
///\param name The name of the stream
|
||||||
///\param data The corresponding configuration values.
|
///\param data The corresponding configuration values.
|
||||||
void startStream(std::string name, JSON::Value & data){
|
void startStream(std::string name, JSON::Value & data){
|
||||||
|
std::string prevState = data["error"].asStringRef();
|
||||||
data["online"] = (std::string)"Checking...";
|
data["online"] = (std::string)"Checking...";
|
||||||
data.removeMember("error");
|
data.removeMember("error");
|
||||||
std::string URL;
|
std::string URL;
|
||||||
|
@ -45,8 +46,10 @@ namespace Controller {
|
||||||
URL = data["source"].asString();
|
URL = data["source"].asString();
|
||||||
}
|
}
|
||||||
if (URL == ""){
|
if (URL == ""){
|
||||||
Log("STRM", "Error for stream " + name + "! Source parameter missing.");
|
|
||||||
data["error"] = "Stream offline: Missing source parameter!";
|
data["error"] = "Stream offline: Missing source parameter!";
|
||||||
|
if (data["error"].asStringRef() != prevState){
|
||||||
|
Log("STRM", "Error for stream " + name + "! Source parameter missing.");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (URL.substr(0, 4) == "push"){
|
if (URL.substr(0, 4) == "push"){
|
||||||
|
@ -71,8 +74,10 @@ namespace Controller {
|
||||||
data.removeMember("error");
|
data.removeMember("error");
|
||||||
struct stat fileinfo;
|
struct stat fileinfo;
|
||||||
if (stat(URL.c_str(), &fileinfo) != 0 || S_ISDIR(fileinfo.st_mode)){
|
if (stat(URL.c_str(), &fileinfo) != 0 || S_ISDIR(fileinfo.st_mode)){
|
||||||
Log("BUFF", "Warning for VoD stream " + name + "! File not found: " + URL);
|
|
||||||
data["error"] = "Stream offline: Not found: " + URL;
|
data["error"] = "Stream offline: Not found: " + URL;
|
||||||
|
if (data["error"].asStringRef() != prevState){
|
||||||
|
Log("BUFF", "Warning for VoD stream " + name + "! File not found: " + URL);
|
||||||
|
}
|
||||||
data["online"] = 0;
|
data["online"] = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -89,8 +94,10 @@ namespace Controller {
|
||||||
}
|
}
|
||||||
if ( !getMeta && data.isMember("meta") && data["meta"].isMember("tracks")){
|
if ( !getMeta && data.isMember("meta") && data["meta"].isMember("tracks")){
|
||||||
if ( !data["meta"] || !data["meta"]["tracks"]){
|
if ( !data["meta"] || !data["meta"]["tracks"]){
|
||||||
Log("WARN", "Source file " + URL + " seems to be corrupt.");
|
|
||||||
data["error"] = "Stream offline: Corrupt file?";
|
data["error"] = "Stream offline: Corrupt file?";
|
||||||
|
if (data["error"].asStringRef() != prevState){
|
||||||
|
Log("WARN", "Source file " + URL + " seems to be corrupt.");
|
||||||
|
}
|
||||||
data["online"] = 0;
|
data["online"] = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -118,8 +125,10 @@ namespace Controller {
|
||||||
tmp_cmd[1] = (char*)URL.c_str();
|
tmp_cmd[1] = (char*)URL.c_str();
|
||||||
data["meta"] = JSON::fromString(Util::Procs::getOutputOf(tmp_cmd));
|
data["meta"] = JSON::fromString(Util::Procs::getOutputOf(tmp_cmd));
|
||||||
if ( !data["meta"] || !data["meta"].isMember("tracks") || !data["meta"]["tracks"]){
|
if ( !data["meta"] || !data["meta"].isMember("tracks") || !data["meta"]["tracks"]){
|
||||||
Log("WARN", "Source file " + URL + " seems to be corrupt.");
|
|
||||||
data["error"] = "Stream offline: Corrupt file?";
|
data["error"] = "Stream offline: Corrupt file?";
|
||||||
|
if (data["error"].asStringRef() != prevState){
|
||||||
|
Log("WARN", "Source file " + URL + " seems to be corrupt.");
|
||||||
|
}
|
||||||
data["online"] = 0;
|
data["online"] = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue