void treatRequestForOfflineService(uint32 rid, const string& serviceName, const string& viewStr) { CVarPath subvarpath(viewStr); addRequestWaitingNb(rid); TAdminViewVarNames varNames; TAdminViewValues values; // add default row varNames.push_back("service"); values.push_back(serviceName); for (uint k = 0; k < subvarpath.Destination.size(); k++) { size_t pos = subvarpath.Destination[k].first.find("="); if (pos != string::npos) varNames.push_back(subvarpath.Destination[k].first.substr(0, pos)); else varNames.push_back(subvarpath.Destination[k].first); string val = "???"; // handle special case of non running service if (subvarpath.Destination[k].first == "State") { // lookup the alias, command to execute, execution path and defined command args for the given service string alias, command, path, arg; getServiceLaunchInfo(serviceName,alias,command,path,arg); val = getOfflineServiceState(alias,path); } else if (subvarpath.Destination[k].first == "State=1" || subvarpath.Destination[k].first == "State=2" || subvarpath.Destination[k].first == "State=3") { // we want to start the service if (startService(serviceName)) val = "Launching"; else val = "Failed"; } else if (subvarpath.Destination[k].first == "State=0" || subvarpath.Destination[k].first == "State=-1" || subvarpath.Destination[k].first == "State=-2") { // lookup the alias, command to execute, execution path and defined command args for the given service string alias, command, path, arg; bool ok= getServiceLaunchInfo(serviceName,alias,command,path,arg); if (ok) writeServiceLaunchCtrl(alias,path,true,LaunchCtrlStop); if (ok) writeServiceLaunchCtrl(alias,path,false,LaunchCtrlStop); val= "Stopping"; } values.push_back(val); } aesAddRequestAnswer(rid, varNames, values); nlinfo("REQUEST: Sent and received view '%s' to offline service '%s'", viewStr.c_str(), serviceName.c_str()); }
static void cbView(CMessage &msgin, const std::string &serviceName, TServiceId sid) { // receive an view answer from the service TServices::iterator sit = findService(sid); uint32 rid; msgin.serial(rid); TAdminViewResult answer; TAdminViewVarNames varNames; TAdminViewValues values; while ((uint32)msgin.getPos() < msgin.length()) { varNames.clear(); values.clear(); // adding default row uint32 i, nb; string var, val; msgin.serial(nb); for (i = 0; i < nb; i++) { msgin.serial(var); varNames.push_back(var); } msgin.serial(nb); for (i = 0; i < nb; i++) { msgin.serial(val); values.push_back(val); } answer.push_back(SAdminViewRow(varNames,values)); } aesAddRequestAnswer(rid, answer); // remove the waiting request for (uint i = 0; i < (*sit).WaitingRequestId.size();) { if ((*sit).WaitingRequestId[i] == rid) { (*sit).WaitingRequestId.erase((*sit).WaitingRequestId.begin()+i); } else { i++; } } }
void aesAddRequestAnswer(uint32 rid, TAdminViewVarNames& varNames, const TAdminViewValues& values) { if (!varNames.empty() && varNames[0] == "__log") { nlassert(varNames.size() == 1); } else { nlassert(varNames.size() == values.size()); } for (uint i = 0 ; i < Requests.size(); i++) { if (Requests[i].Id == rid) { Requests[i].Answers.push_back(SAdminViewRow(varNames, values)); Requests[i].NbReceived++; nldebug("REQUEST: ++ i %d rid %d NbWaiting %d NbReceived+ %d", i, Requests[i].Id, Requests[i].NbWaiting, Requests[i].NbReceived); return; } } // we received an unknown request, forget it nlwarning("Receive an answer for unknown request %d", rid); }
void cleanRequests() { uint32 currentTime = CTime::getSecondsSince1970(); // just a debug check for (uint t = 0 ; t < Requests.size(); t++) { uint32 NbWaiting = Requests[t].NbWaiting; uint32 NbReceived = Requests[t].NbReceived; uint32 NbRef = 0; for (uint j = 0; j < Services.size(); j++) { if (Services[j].Connected) { for (uint k = 0; k < Services[j].WaitingRequestId.size(); k++) { if(Services[j].WaitingRequestId[k] == Requests[t].Id) { NbRef++; } } } } nlinfo("REQUEST: Waiting request %d: NbRef %d NbWaiting %d NbReceived %d", Requests[t].Id, NbRef, NbWaiting, NbReceived); if (NbRef != NbWaiting - NbReceived) { nlwarning("REQUEST: **** i %d rid %d -> NbRef(%d) != NbWaiting(%d) - NbReceived(%d) ", t, Requests[t].Id, NbRef, NbWaiting, NbReceived); } } for (uint i = 0 ; i < Requests.size();) { // timeout if (currentTime >= Requests[i].Time+RequestTimeout) { nlwarning("REQUEST: Request %d timeouted, only %d on %d services have replied", Requests[i].Id, Requests[i].NbReceived, Requests[i].NbWaiting); TAdminViewVarNames varNames; TAdminViewValues values; varNames.push_back("service"); for (uint j = 0; j < Services.size(); j++) { if (Services[j].Connected) { for (uint k = 0; k < Services[j].WaitingRequestId.size(); k++) { if(Services[j].WaitingRequestId[k] == Requests[i].Id) { // this services didn't answer string s; if(Services[j].AliasName.empty()) s = Services[j].ShortName; else s = Services[j].AliasName; s += "-"+toString(Services[j].ServiceId); s += "((TIMEOUT))"; values.clear(); values.push_back(s); aesAddRequestAnswer(Requests[i].Id, varNames, values); break; } } } } if (Requests[i].NbWaiting != Requests[i].NbReceived) { nlwarning("REQUEST: **** i %d rid %d -> Requests[i].NbWaiting(%d) != Requests[i].NbReceived(%d)", i, Requests[i].Id, Requests[i].NbWaiting, Requests[i].NbReceived); nlwarning("REQUEST: Need to add dummy answer"); values.clear(); values.push_back("UnknownService"); while (Requests[i].NbWaiting != Requests[i].NbReceived) aesAddRequestAnswer(Requests[i].Id, varNames, values); } } if (Requests[i].NbWaiting <= Requests[i].NbReceived) { // the request is over, send to the php CMessage msgout("VIEW"); msgout.serial(Requests[i].Id); for (uint j = 0; j < Requests[i].Answers.size(); j++) { msgout.serialCont(Requests[i].Answers[j].VarNames); msgout.serialCont(Requests[i].Answers[j].Values); } if (Requests[i].SId == TServiceId(0)) { nlinfo("REQUEST: Receive an answer for the fake request %d with %d answers", Requests[i].Id, Requests[i].Answers.size()); for (uint j = 0; j < Requests[i].Answers.size(); j++) { uint k; for (k = 0; k < Requests[i].Answers[j].VarNames.size(); k++) { InfoLog->displayRaw("%-20s ", Requests[i].Answers[j].VarNames[k].c_str()); } InfoLog->displayRawNL(""); for (k = 0; k < Requests[i].Answers[j].Values.size(); k++) { InfoLog->displayRaw("%-20s", Requests[i].Answers[j].Values[k].c_str()); } InfoLog->displayRawNL(""); InfoLog->displayRawNL("----------------------------------------------"); } } else CUnifiedNetwork::getInstance()->send(Requests[i].SId, msgout); // set to 0 to erase it Requests[i].NbWaiting = 0; nldebug("REQUEST: ++ i %d rid %d NbWaiting0 %d NbReceived %d", i, Requests[i].Id, Requests[i].NbWaiting, Requests[i].NbReceived); } if (Requests[i].NbWaiting == 0) { Requests.erase(Requests.begin()+i); } else { i++; } } }
// this callback is used to create a view for the admin system void serviceGetView (uint32 rid, const string &rawvarpath, TAdminViewResult &answer, bool async) { string str; CLog logDisplayVars; CLightMemDisplayer mdDisplayVars; logDisplayVars.addDisplayer (&mdDisplayVars); mdDisplayVars.setParam (4096); CVarPath varpath(rawvarpath); if (varpath.empty()) return; // special case for named command handler if (CCommandRegistry::getInstance().isNamedCommandHandler(varpath.Destination[0].first)) { varpath.Destination[0].first += "."+varpath.Destination[0].second; varpath.Destination[0].second = ""; } if (varpath.isFinal()) { TAdminViewVarNames varNames; TAdminViewValues values; // add default row varNames.push_back ("service"); values.push_back (IService::getInstance ()->getServiceUnifiedName()); for (uint j = 0; j < varpath.Destination.size (); j++) { string cmd = varpath.Destination[j].first; // replace = with space to execute the command string::size_type eqpos = cmd.find("="); if (eqpos != string::npos) { cmd[eqpos] = ' '; varNames.push_back(cmd.substr(0, eqpos)); } else varNames.push_back(cmd); mdDisplayVars.clear (); ICommand::execute(cmd, logDisplayVars, !ICommand::isCommand(cmd)); const std::deque<std::string> &strs = mdDisplayVars.lockStrings(); if (ICommand::isCommand(cmd)) { // we want the log of the command if (j == 0) { varNames.clear (); varNames.push_back ("__log"); values.clear (); } values.push_back ("----- Result from "+IService::getInstance()->getServiceUnifiedName()+" of command '"+cmd+"'\n"); for (uint k = 0; k < strs.size(); k++) { values.push_back (strs[k]); } } else { if (strs.size()>0) { str = strs[0].substr(0,strs[0].size()-1); // replace all spaces into udnerscore because space is a reserved char for (uint i = 0; i < str.size(); i++) if (str[i] == ' ') str[i] = '_'; } else { str = "???"; } values.push_back (str); nlinfo ("ADMIN: Add to result view '%s' = '%s'", varpath.Destination[j].first.c_str(), str.c_str()); } mdDisplayVars.unlockStrings(); } if (!async) answer.push_back (SAdminViewRow(varNames, values)); else { addRequestWaitingNb (rid); addRequestAnswer (rid, varNames, values); } } else { // there s an entity in the varpath, manage this case TAdminViewVarNames *varNames=0; TAdminViewValues *values=0; // varpath.Destination contains the entity number // subvarpath.Destination contains the command name for (uint i = 0; i < varpath.Destination.size (); i++) { CVarPath subvarpath(varpath.Destination[i].second); for (uint j = 0; j < subvarpath.Destination.size (); j++) { // set the variable name string cmd = subvarpath.Destination[j].first; if (isRemoteCommand(cmd)) { if (async && RemoteClientCallback != 0) { // ok we have to send the request to another side, just send and wait addRequestWaitingNb (rid); RemoteClientCallback (rid, cmd, varpath.Destination[i].first); } } else { // replace = with space to execute the command string::size_type eqpos = cmd.find("="); if (eqpos != string::npos) { cmd[eqpos] = ' '; // add the entity cmd.insert(eqpos, " "+varpath.Destination[i].first); } else { // add the entity cmd += " "+varpath.Destination[i].first; } mdDisplayVars.clear (); ICommand::execute(cmd, logDisplayVars, true); const std::deque<std::string> &strs = mdDisplayVars.lockStrings(); for (uint k = 0; k < strs.size(); k++) { const string &str = strs[k]; string::size_type pos = str.find(" "); if(pos == string::npos) continue; string entity = str.substr(0, pos); string value = str.substr(pos+1, str.size()-pos-2); for (uint u = 0; u < value.size(); u++) if (value[u] == ' ') value[u] = '_'; // look in the array if we already have something about this entity if (!async) { uint y; for (y = 0; y < answer.size(); y++) { if (answer[y].Values[1] == entity) { // ok we found it, just push_back new stuff varNames = &(answer[y].VarNames); values = &(answer[y].Values); break; } } if (y == answer.size ()) { answer.push_back (SAdminViewRow()); varNames = &(answer[answer.size()-1].VarNames); values = &(answer[answer.size()-1].Values); // don't add service if we want an entity // todo when we work on entity, we don't need service name and server so we should remove them and collapse all var for the same entity varNames->push_back ("service"); string name = IService::getInstance ()->getServiceUnifiedName(); values->push_back (name); // add default row varNames->push_back ("entity"); values->push_back (entity); } varNames->push_back (cmd.substr(0, cmd.find(" "))); values->push_back (value); } else { addRequestWaitingNb (rid); TAdminViewVarNames varNames; TAdminViewValues values; varNames.push_back ("service"); string name = IService::getInstance ()->getServiceUnifiedName(); values.push_back (name); // add default row varNames.push_back ("entity"); values.push_back (entity); varNames.push_back (cmd.substr(0, cmd.find(" "))); values.push_back (value); addRequestAnswer (rid, varNames, values); } nlinfo ("ADMIN: Add to result view for entity '%s', '%s' = '%s'", varpath.Destination[i].first.c_str(), subvarpath.Destination[j].first.c_str(), str.c_str()); } mdDisplayVars.unlockStrings(); } } } } }