1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "nel/net/service.h"
25 #include "nel/net/admin.h"
26 #include "nel/net/varpath.h"
34 using namespace NLMISC
;
35 using namespace NLNET
;
47 CRequest (uint32 id
, TServiceId sid
) : Id(id
), NbWaiting(0), NbReceived(0), SId(sid
)
49 nldebug ("ADMIN: ++ NbWaiting %d NbReceived %d", NbWaiting
, NbReceived
);
50 Time
= CTime::getSecondsSince1970 ();
57 uint32 Time
; // when the request was ask
59 TAdminViewResult Answers
;
67 TRemoteClientCallback RemoteClientCallback
= 0;
69 vector
<CAlarm
> Alarms
;
71 vector
<CGraphUpdate
> GraphUpdates
;
73 // check alarms every 5 seconds
74 const uint32 AlarmCheckDelay
= 5;
76 vector
<CRequest
> Requests
;
78 uint32 RequestTimeout
= 4; // in second
85 static void cbInfo (CMessage
&msgin
, const std::string
&/* serviceName */, TServiceId
/* sid */)
87 nlinfo ("ADMIN: Updating admin information");
89 vector
<string
> alarms
;
90 msgin
.serialCont (alarms
);
91 vector
<string
> graphupdate
;
92 msgin
.serialCont (graphupdate
);
94 setInformation (alarms
, graphupdate
);
97 static void cbServGetView (CMessage
&msgin
, const std::string
&/* serviceName */, TServiceId sid
)
103 msgin
.serial (rawvarpath
);
105 Requests
.push_back (CRequest(rid
, sid
));
107 TAdminViewResult answer
;
108 // just send the view in async mode, don't retrieve the answer
109 serviceGetView (rid
, rawvarpath
, answer
, true);
110 nlassert (answer
.empty());
113 static void cbExecCommand (CMessage
&msgin
, const std::string
&/* serviceName */, TServiceId sid
)
115 // create a displayer to gather the output of the command
116 class CStringDisplayer
: public IDisplayer
119 void serial(NLMISC::IStream
&stream
)
121 stream
.serial(_Data
);
125 virtual void doDisplay( const CLog::TDisplayInfo
& /* args */, const char *message
)
132 CStringDisplayer stringDisplayer
;
133 IService::getInstance()->CommandLog
.addDisplayer(&stringDisplayer
);
135 // retreive the command from the input message and execute it
137 msgin
.serial (command
);
138 nlinfo ("ADMIN: Executing command from network : '%s'", command
.c_str());
139 ICommand::execute (command
, IService::getInstance()->CommandLog
);
141 // unhook our displayer as it's work is now done
142 IService::getInstance()->CommandLog
.removeDisplayer(&stringDisplayer
);
144 // send a reply message to the originating service
145 CMessage
msgout("EXEC_COMMAND_RESULT");
146 stringDisplayer
.serial(msgout
);
147 CUnifiedNetwork::getInstance()->send(sid
, msgout
);
151 // AES wants to know if i'm not dead, I have to answer faster as possible or i'll be killed
152 static void cbAdminPing (CMessage
&/* msgin */, const std::string
&/* serviceName */, TServiceId sid
)
154 // Send back a pong to say to the AES that I'm alive
155 CMessage
msgout("ADMIN_PONG");
156 CUnifiedNetwork::getInstance()->send(sid
, msgout
);
159 static void cbStopService (CMessage
&/* msgin */, const std::string
&serviceName
, TServiceId sid
)
161 nlinfo ("ADMIN: Receive a stop from service %s-%hu, need to quit", serviceName
.c_str(), sid
.get());
162 IService::getInstance()->exit (0xFFFF);
166 void cbAESConnection (const string
&/* serviceName */, TServiceId
/* sid */, void * /* arg */)
168 // established a connection to the AES, identify myself
171 // Sends the identification message with the name of the service and all commands available on this service
174 nlinfo("cbAESConnection: Identifying self as: AliasName='%s' LongName='%s' PId=%u",
175 IService::getInstance()->_AliasName
.c_str(),
176 IService::getInstance()->_LongName
.c_str(),
178 CMessage
msgout ("SID");
179 uint32 pid
= getpid ();
180 msgout
.serial (IService::getInstance()->_AliasName
, IService::getInstance()->_LongName
, pid
);
181 ICommand::serialCommands (msgout
);
182 CUnifiedNetwork::getInstance()->send("AES", msgout
);
184 if (IService::getInstance()->_Initialized
)
186 CMessage
msgout2 ("SR");
187 CUnifiedNetwork::getInstance()->send("AES", msgout2
);
192 static void cbAESDisconnection (const std::string
&serviceName
, TServiceId sid
, void * /* arg */)
194 nlinfo("Lost connection to the %s-%hu", serviceName
.c_str(), sid
.get());
198 static TUnifiedCallbackItem CallbackArray
[] =
201 { "GET_VIEW", cbServGetView
},
202 { "STOPS", cbStopService
},
203 { "EXEC_COMMAND", cbExecCommand
},
204 { "ADMIN_PING", cbAdminPing
},
212 void setRemoteClientCallback (TRemoteClientCallback cb
)
214 RemoteClientCallback
= cb
;
222 static void addRequestWaitingNb (uint32 rid
)
224 for (uint i
= 0 ; i
< Requests
.size (); i
++)
226 if (Requests
[i
].Id
== rid
)
228 Requests
[i
].NbWaiting
++;
229 nldebug ("ADMIN: ++ i %d rid %d NbWaiting+ %d NbReceived %d", i
, Requests
[i
].Id
, Requests
[i
].NbWaiting
, Requests
[i
].NbReceived
);
230 // if we add a waiting, reset the timer
231 Requests
[i
].Time
= CTime::getSecondsSince1970 ();
235 nlwarning ("ADMIN: addRequestWaitingNb: can't find the rid %d", rid
);
239 static void subRequestWaitingNb (uint32 rid)
241 for (uint i = 0 ; i < Requests.size (); i++)
243 if (Requests[i].Id == rid)
245 Requests[i].NbWaiting--;
246 nldebug ("ADMIN: ++ i %d rid %d NbWaiting- %d NbReceived %d", i, Requests[i].Id, Requests[i].NbWaiting, Requests[i].NbReceived);
250 nlwarning ("ADMIN: subRequestWaitingNb: can't find the rid %d", rid);
254 void addRequestAnswer (uint32 rid
, const TAdminViewVarNames
& varNames
, const TAdminViewValues
& values
)
256 if (!varNames
.empty() && varNames
[0] == "__log")
257 { nlassert (varNames
.size() == 1); }
259 { nlassert (varNames
.size() == values
.size()); }
261 for (uint i
= 0 ; i
< Requests
.size (); i
++)
263 if (Requests
[i
].Id
== rid
)
265 Requests
[i
].Answers
.push_back (SAdminViewRow(varNames
, values
));
267 Requests
[i
].NbReceived
++;
268 nldebug ("ADMIN: ++ i %d rid %d NbWaiting %d NbReceived+ %d", i
, Requests
[i
].Id
, Requests
[i
].NbWaiting
, Requests
[i
].NbReceived
);
273 // we received an unknown request, forget it
274 nlwarning ("ADMIN: Receive an answer for unknown request %d", rid
);
278 static bool emptyRequest (uint32 rid)
280 for (uint i = 0 ; i < Requests.size (); i++)
282 if (Requests[i].Id == rid && Requests[i].NbWaiting != 0)
291 static void cleanRequest ()
293 uint32 currentTime
= CTime::getSecondsSince1970 ();
295 for (uint i
= 0 ; i
< Requests
.size ();)
298 if (currentTime
>= Requests
[i
].Time
+RequestTimeout
)
300 nlwarning ("ADMIN: **** i %d rid %d -> Requests[i].NbWaiting (%d) != Requests[i].NbReceived (%d)", i
, Requests
[i
].Id
, Requests
[i
].NbWaiting
, Requests
[i
].NbReceived
);
301 Requests
[i
].NbWaiting
= Requests
[i
].NbReceived
;
304 if (Requests
[i
].NbWaiting
<= Requests
[i
].NbReceived
)
306 // the request is over, send to the php
308 CMessage
msgout("VIEW");
309 msgout
.serial (Requests
[i
].Id
);
311 for (uint j
= 0; j
< Requests
[i
].Answers
.size (); j
++)
313 msgout
.serialCont (Requests
[i
].Answers
[j
].VarNames
);
314 msgout
.serialCont (Requests
[i
].Answers
[j
].Values
);
317 if (Requests
[i
].SId
.get() == 0)
319 nlinfo ("ADMIN: Receive an answer for the fake request %d with %d answers", Requests
[i
].Id
, Requests
[i
].Answers
.size ());
320 for (uint j
= 0; j
< Requests
[i
].Answers
.size (); j
++)
323 for (k
= 0; k
< Requests
[i
].Answers
[j
].VarNames
.size(); k
++)
325 InfoLog
->displayRaw ("%-10s", Requests
[i
].Answers
[j
].VarNames
[k
].c_str());
327 InfoLog
->displayRawNL("");
328 for (k
= 0; k
< Requests
[i
].Answers
[j
].Values
.size(); k
++)
330 InfoLog
->displayRaw ("%-10s", Requests
[i
].Answers
[j
].Values
[k
].c_str());
332 InfoLog
->displayRawNL("");
333 InfoLog
->displayRawNL("-------------------------");
338 nlinfo ("ADMIN: The request is over, send the result to AES");
339 CUnifiedNetwork::getInstance ()->send (Requests
[i
].SId
, msgout
);
342 // set to 0 to erase it
343 Requests
[i
].NbWaiting
= 0;
344 nldebug ("ADMIN: ++ i %d rid %d NbWaiting0 %d NbReceived %d", i
, Requests
[i
].Id
, Requests
[i
].NbWaiting
, Requests
[i
].NbReceived
);
347 if (Requests
[i
].NbWaiting
== 0)
349 Requests
.erase (Requests
.begin ()+i
);
358 // all remote command start with rc or RC
359 bool isRemoteCommand(string
&str
)
361 if (str
.size()<2) return false;
362 return tolower(str
[0]) == 'r' && tolower(str
[1]) == 'c';
366 // this callback is used to create a view for the admin system
367 void serviceGetView (uint32 rid
, const string
&rawvarpath
, TAdminViewResult
&answer
, bool async
)
371 CLightMemDisplayer mdDisplayVars
;
372 logDisplayVars
.addDisplayer (&mdDisplayVars
);
373 mdDisplayVars
.setParam (4096);
375 CVarPath
varpath(rawvarpath
);
380 // special case for named command handler
381 if (CCommandRegistry::getInstance().isNamedCommandHandler(varpath
.Destination
[0].first
))
383 varpath
.Destination
[0].first
+= "."+varpath
.Destination
[0].second
;
384 varpath
.Destination
[0].second
.clear();
387 if (varpath
.isFinal())
389 TAdminViewVarNames varNames
;
390 TAdminViewValues values
;
393 varNames
.push_back ("service");
394 values
.push_back (IService::getInstance ()->getServiceUnifiedName());
396 for (uint j
= 0; j
< varpath
.Destination
.size (); j
++)
398 string cmd
= varpath
.Destination
[j
].first
;
400 // replace = with space to execute the command
401 string::size_type eqpos
= cmd
.find("=");
402 if (eqpos
!= string::npos
)
405 varNames
.push_back(cmd
.substr(0, eqpos
));
408 varNames
.push_back(cmd
);
410 mdDisplayVars
.clear ();
411 ICommand::execute(cmd
, logDisplayVars
, !ICommand::isCommand(cmd
));
412 const std::deque
<std::string
> &strs
= mdDisplayVars
.lockStrings();
414 if (ICommand::isCommand(cmd
))
416 // we want the log of the command
420 varNames
.push_back ("__log");
424 values
.push_back ("----- Result from "+IService::getInstance()->getServiceUnifiedName()+" of command '"+cmd
+"'\n");
425 for (uint k
= 0; k
< strs
.size(); k
++)
427 values
.push_back (strs
[k
]);
435 str
= strs
[0].substr(0,strs
[0].size()-1);
436 // replace all spaces into udnerscore because space is a reserved char
437 for (uint i
= 0; i
< str
.size(); i
++) if (str
[i
] == ' ') str
[i
] = '_';
443 values
.push_back (str
);
444 nlinfo ("ADMIN: Add to result view '%s' = '%s'", varpath
.Destination
[j
].first
.c_str(), str
.c_str());
446 mdDisplayVars
.unlockStrings();
450 answer
.push_back (SAdminViewRow(varNames
, values
));
453 addRequestWaitingNb (rid
);
454 addRequestAnswer (rid
, varNames
, values
);
459 // there s an entity in the varpath, manage this case
461 TAdminViewVarNames
*varNames
=0;
462 TAdminViewValues
*values
=0;
464 // varpath.Destination contains the entity number
465 // subvarpath.Destination contains the command name
467 for (uint i
= 0; i
< varpath
.Destination
.size (); i
++)
469 CVarPath
subvarpath(varpath
.Destination
[i
].second
);
471 for (uint j
= 0; j
< subvarpath
.Destination
.size (); j
++)
473 // set the variable name
474 string cmd
= subvarpath
.Destination
[j
].first
;
476 if (isRemoteCommand(cmd
))
478 if (async
&& RemoteClientCallback
!= 0)
480 // ok we have to send the request to another side, just send and wait
481 addRequestWaitingNb (rid
);
482 RemoteClientCallback (rid
, cmd
, varpath
.Destination
[i
].first
);
487 // replace = with space to execute the command
488 string::size_type eqpos
= cmd
.find("=");
489 if (eqpos
!= string::npos
)
493 cmd
.insert(eqpos
, " "+varpath
.Destination
[i
].first
);
498 cmd
+= " "+varpath
.Destination
[i
].first
;
501 mdDisplayVars
.clear ();
502 ICommand::execute(cmd
, logDisplayVars
, true);
503 const std::deque
<std::string
> &strs
= mdDisplayVars
.lockStrings();
504 for (uint k
= 0; k
< strs
.size(); k
++)
506 const string
&str
= strs
[k
];
508 string::size_type pos
= str
.find(" ");
509 if(pos
== string::npos
)
512 string entity
= str
.substr(0, pos
);
513 string value
= str
.substr(pos
+1, str
.size()-pos
-2);
514 for (uint u
= 0; u
< value
.size(); u
++) if (value
[u
] == ' ') value
[u
] = '_';
516 // look in the array if we already have something about this entity
521 for (y
= 0; y
< answer
.size(); y
++)
523 if (answer
[y
].Values
[1] == entity
)
525 // ok we found it, just push_back new stuff
526 varNames
= &(answer
[y
].VarNames
);
527 values
= &(answer
[y
].Values
);
531 if (y
== answer
.size ())
533 answer
.push_back (SAdminViewRow());
535 varNames
= &(answer
[answer
.size()-1].VarNames
);
536 values
= &(answer
[answer
.size()-1].Values
);
538 // don't add service if we want an entity
539 // 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
540 varNames
->push_back ("service");
541 string name
= IService::getInstance ()->getServiceUnifiedName();
542 values
->push_back (name
);
545 varNames
->push_back ("entity");
546 values
->push_back (entity
);
549 varNames
->push_back (cmd
.substr(0, cmd
.find(" ")));
550 values
->push_back (value
);
554 addRequestWaitingNb (rid
);
556 TAdminViewVarNames varNames
;
557 TAdminViewValues values
;
558 varNames
.push_back ("service");
559 string name
= IService::getInstance ()->getServiceUnifiedName();
560 values
.push_back (name
);
563 varNames
.push_back ("entity");
564 values
.push_back (entity
);
566 varNames
.push_back (cmd
.substr(0, cmd
.find(" ")));
567 values
.push_back (value
);
569 addRequestAnswer (rid
, varNames
, values
);
571 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());
573 mdDisplayVars
.unlockStrings();
585 void sendAdminEmail (const char *format
, ...)
588 NLMISC_CONVERT_VARGS (text
, format
, 4096);
590 time_t t
= time (&t
);
593 str
= asctime (localtime (&t
));
594 str
+= " Server " + IService::getInstance()->getHostName();
595 str
+= " service " + IService::getInstance()->getServiceUnifiedName();
599 CMessage
msgout("ADMIN_EMAIL");
601 if(IService::getInstance ()->getServiceShortName()=="AES")
602 CUnifiedNetwork::getInstance ()->send ("AS", msgout
);
604 CUnifiedNetwork::getInstance ()->send ("AES", msgout
);
606 nlinfo ("ADMIN: Forwarded email to AS with '%s'", str
.c_str());
609 void initAdmin (bool dontUseAES
)
613 CUnifiedNetwork::getInstance()->setServiceUpCallback ("AES", cbAESConnection
, NULL
);
614 CUnifiedNetwork::getInstance()->setServiceDownCallback ("AES", cbAESDisconnection
, NULL
);
615 CUnifiedNetwork::getInstance()->addService ("AES", CInetAddress("localhost:49997"));
617 CUnifiedNetwork::getInstance()->addCallbackArray (CallbackArray
, sizeof(CallbackArray
)/sizeof(CallbackArray
[0]));
623 uint32 CurrentTime
= CTime::getSecondsSince1970();
627 // check admin requests
634 // Check graph updates
637 static uint32 lastGraphUpdateCheck
= 0;
639 if (CurrentTime
>= lastGraphUpdateCheck
+1)
643 CLightMemDisplayer mdDisplayVars
;
644 logDisplayVars
.addDisplayer (&mdDisplayVars
);
646 lastGraphUpdateCheck
= CurrentTime
;
648 CMessage
msgout ("GRAPH_UPDATE");
650 for (uint j
= 0; j
< GraphUpdates
.size(); j
++)
652 if (CurrentTime
>= GraphUpdates
[j
].LastUpdate
+ GraphUpdates
[j
].Update
)
654 // have to send a new update for this var
655 ICommand::execute(GraphUpdates
[j
].Name
, logDisplayVars
, true, false);
656 const std::deque
<std::string
> &strs
= mdDisplayVars
.lockStrings();
658 if (strs
.size() != 1)
660 nlwarning ("ADMIN: The graph update command execution not return exactly 1 line but %d", strs
.size());
661 for (uint i
= 0; i
< strs
.size(); i
++)
662 nlwarning ("ADMIN: line %d: '%s'", i
, strs
[i
].c_str());
667 fromString(strs
[0], val
);
669 mdDisplayVars
.unlockStrings ();
670 mdDisplayVars
.clear ();
672 string name
= IService::getInstance()->getServiceAliasName();
674 name
= IService::getInstance()->getServiceShortName();
677 msgout
.serial (CurrentTime
);
679 msgout
.serial (name
);
680 msgout
.serial (GraphUpdates
[j
].Name
);
685 GraphUpdates
[j
].LastUpdate
= CurrentTime
;
691 if(IService::getInstance ()->getServiceShortName()=="AES")
692 CUnifiedNetwork::getInstance ()->send ("AS", msgout
);
694 CUnifiedNetwork::getInstance ()->send ("AES", msgout
);
703 static uint32 lastAlarmsCheck
= 0;
705 if (CurrentTime
>= lastAlarmsCheck
+AlarmCheckDelay
)
709 CLightMemDisplayer mdDisplayVars
;
710 logDisplayVars
.addDisplayer (&mdDisplayVars
);
712 lastAlarmsCheck
= CTime::getSecondsSince1970();
714 for (uint i
= 0; i
< Alarms
.size(); )
716 mdDisplayVars
.clear ();
717 ICommand::execute(Alarms
[i
].Name
, logDisplayVars
, true, false);
718 const std::deque
<std::string
> &strs
= mdDisplayVars
.lockStrings();
722 str
= strs
[0].substr(0,strs
[0].size()-1);
729 mdDisplayVars
.unlockStrings();
733 // variable doesn't exist, remove it from alarms
734 nlwarning ("ADMIN: Alarm problem: variable '%s' returns ??? instead of a good value", Alarms
[i
].Name
.c_str());
735 Alarms
.erase (Alarms
.begin()+i
);
740 uint32 err
= Alarms
[i
].Limit
;
741 uint32 val
= humanReadableToBytes(str
);
742 if (Alarms
[i
].GT
&& val
>= err
)
744 if (!Alarms
[i
].Activated
)
746 nlinfo ("ADMIN: VARIABLE TOO BIG '%s' %u >= %u", Alarms
[i
].Name
.c_str(), val
, err
);
747 Alarms
[i
].Activated
= true;
748 sendAdminEmail ("Alarm: Variable %s is %u that is greater or equal than the limit %u", Alarms
[i
].Name
.c_str(), val
, err
);
751 else if (!Alarms
[i
].GT
&& val
<= err
)
753 if (!Alarms
[i
].Activated
)
755 nlinfo ("ADMIN: VARIABLE TOO LOW '%s' %u <= %u", Alarms
[i
].Name
.c_str(), val
, err
);
756 Alarms
[i
].Activated
= true;
757 sendAdminEmail ("Alarm: Variable %s is %u that is lower or equal than the limit %u", Alarms
[i
].Name
.c_str(), val
, err
);
762 if (Alarms
[i
].Activated
)
764 nlinfo ("ADMIN: variable is ok '%s' %u %s %u", Alarms
[i
].Name
.c_str(), val
, (Alarms
[i
].GT
?"<":">"), err
);
765 Alarms
[i
].Activated
= false;
775 void setInformation (const vector
<string
> &alarms
, const vector
<string
> &graphupdate
)
780 // add only commands that I understand
782 for (i
= 0; i
< alarms
.size(); i
+=3)
784 CVarPath
shardvarpath (alarms
[i
]);
785 if(shardvarpath
.Destination
.empty() || shardvarpath
.Destination
[0].second
.empty())
787 CVarPath
servervarpath (shardvarpath
.Destination
[0].second
);
788 if(servervarpath
.Destination
.empty() || servervarpath
.Destination
[0].second
.empty())
790 CVarPath
servicevarpath (servervarpath
.Destination
[0].second
);
791 if(servicevarpath
.Destination
.empty() || servicevarpath
.Destination
[0].second
.empty())
794 string name
= servicevarpath
.Destination
[0].second
;
796 if (IService::getInstance()->getServiceUnifiedName().find(servicevarpath
.Destination
[0].first
) != string::npos
&& ICommand::exists(name
))
798 fromString(alarms
[i
+1], tmp
);
799 nlinfo ("ADMIN: Adding alarm '%s' limit %d order %s (varpath '%s')", name
.c_str(), tmp
, alarms
[i
+2].c_str(), alarms
[i
].c_str());
800 Alarms
.push_back(CAlarm(name
, tmp
, alarms
[i
+2]=="gt"));
804 if (IService::getInstance()->getServiceUnifiedName().find(servicevarpath
.Destination
[0].first
) == string::npos
)
806 nlinfo ("ADMIN: Skipping alarm '%s' limit %d order %s (varpath '%s') (not for my service, i'm '%s')", name
.c_str(), fromString(alarms
[i
+1], tmp
) ? tmp
:tmp
, alarms
[i
+2].c_str(), alarms
[i
].c_str(), IService::getInstance()->getServiceUnifiedName().c_str());
810 nlinfo ("ADMIN: Skipping alarm '%s' limit %d order %s (varpath '%s') (var not exist)", name
.c_str(), fromString(alarms
[i
+1], tmp
) ? tmp
:tmp
, alarms
[i
+2].c_str(), alarms
[i
].c_str());
815 // do the same with graph update
816 GraphUpdates
.clear ();
817 for (i
= 0; i
< graphupdate
.size(); i
+=2)
819 CVarPath
shardvarpath (graphupdate
[i
]);
820 if(shardvarpath
.Destination
.empty() || shardvarpath
.Destination
[0].second
.empty())
822 CVarPath
servervarpath (shardvarpath
.Destination
[0].second
);
823 if(servervarpath
.Destination
.empty() || servervarpath
.Destination
[0].second
.empty())
825 CVarPath
servicevarpath (servervarpath
.Destination
[0].second
);
826 if(servicevarpath
.Destination
.empty() || servicevarpath
.Destination
[0].second
.empty())
829 string VarName
= servicevarpath
.Destination
[0].second
;
830 string ServiceName
= servicevarpath
.Destination
[0].first
;
832 if (ICommand::exists(VarName
) && (ServiceName
== "*" || IService::getInstance()->getServiceShortName() == ServiceName
))
834 fromString(graphupdate
[i
+1], tmp
);
835 nlinfo ("ADMIN: Adding graphupdate '%s' update %d (varpath '%s')", VarName
.c_str(), tmp
, graphupdate
[i
].c_str());
836 GraphUpdates
.push_back(CGraphUpdate(VarName
, tmp
));
840 if (IService::getInstance()->getServiceShortName() != ServiceName
)
842 nlinfo ("ADMIN: Skipping graphupdate '%s' limit %d (varpath '%s') (not for my service, i'm '%s')", VarName
.c_str(), fromString(graphupdate
[i
+1], tmp
) ? tmp
:tmp
, graphupdate
[i
].c_str(), IService::getInstance()->getServiceUnifiedName().c_str());
846 nlinfo ("ADMIN: Skipping graphupdate '%s' limit %d (varpath '%s') (var not exist)", VarName
.c_str(), fromString(graphupdate
[i
+1], tmp
) ? tmp
:tmp
, graphupdate
[i
].c_str());
856 NLMISC_CATEGORISED_COMMAND(nel
, displayInformation
, "displays all admin information", "")
858 nlunreferenced(rawCommandString
);
859 nlunreferenced(args
);
860 nlunreferenced(quiet
);
861 nlunreferenced(human
);
865 log
.displayNL("There're %d alarms:", Alarms
.size());
866 for (i
= 0; i
< Alarms
.size(); i
++)
868 log
.displayNL(" %d %s %d %s %s", i
, Alarms
[i
].Name
.c_str(), Alarms
[i
].Limit
, (Alarms
[i
].GT
?"gt":"lt"), (Alarms
[i
].Activated
?"on":"off"));
870 log
.displayNL("There're %d graphupdate:", GraphUpdates
.size());
871 for (i
= 0; i
< GraphUpdates
.size(); i
++)
873 log
.displayNL(" %d %s %d %d", i
, GraphUpdates
[i
].Name
.c_str(), GraphUpdates
[i
].Update
, GraphUpdates
[i
].LastUpdate
);
878 NLMISC_CATEGORISED_COMMAND(nel
, getView
, "send a view and receive an array as result", "<varpath>")
880 nlunreferenced(rawCommandString
);
881 nlunreferenced(quiet
);
882 nlunreferenced(human
);
884 if(args
.size() != 1) return false;
886 TAdminViewResult answer
;
887 serviceGetView (0, args
[0], answer
);
889 log
.displayNL("have %d answer", answer
.size());
890 for (uint i
= 0; i
< answer
.size(); i
++)
892 log
.displayNL(" have %d value", answer
[i
].VarNames
.size());
894 nlassert (answer
[i
].VarNames
.size() == answer
[i
].Values
.size());
896 for (uint j
= 0; j
< answer
[i
].VarNames
.size(); j
++)
898 log
.displayNL(" %s -> %s", answer
[i
].VarNames
[j
].c_str(), answer
[i
].Values
[j
].c_str());