Commit d467c6d88506d48fb0c8e3af2dd76d107b522de1

Authored by Etienne Pallier
1 parent 4ba41afb
Exists in dev

Optimisation log_agent_status() (ex update_survey())

+ bugfix import celme
+ activity diag
README.md
... ... @@ -73,9 +73,7 @@ Author: E. Pallier
73 73  
74 74 VERSION: 0.20.31
75 75  
76   -Comment: AgentM
77   -
78   - - routine_process() : envoi commande n'est plus bloquant
  76 +Comment: Optimisation log_agent_status() (ex update_survey())
79 77  
80 78 - Scenario de test :
81 79 - lancer agents A et B en mode simu (option -t): ./pyros.py -t start agentA,agentB
... ... @@ -89,7 +87,9 @@ Comment: AgentM
89 87 (ou encore: activer l'environnement virtuel, puis lancer "cd src/agent/ ; ./AgentA.py configfile")
90 88 - pour utiliser thread ou processus : il suffit de mettre la constante RUN_IN_THREAD de AgentA (ou AgentB ou AgentX) à False ou True
91 89  
92   - - Autres remarques:
  90 + - Historique des nouveautés :
  91 + - AgentM (début) pour remplacer progressivement l'agent monitoring
  92 + - routine_process() : envoi commande n'est plus bloquant
93 93 - pyros.py peut lancer plusieurs agents (A et B) en même temps
94 94 - run(N) : run only N iterations
95 95 - send_command() implemented
... ...
src/agent/Agent.py
... ... @@ -72,12 +72,12 @@ print()
72 72  
73 73 # --- GENERAL PURPOSE IMPORT ---
74 74 #from __future__ import absolute_import
  75 +import utils.Logger as L
75 76 import platform
76 77 import random
77 78 from threading import Thread
78 79 import threading, multiprocessing
79 80 import time
80   -import utils.Logger as L
81 81 import socket
82 82 #import ctypes
83 83 #import copy
... ... @@ -185,19 +185,82 @@ class StoppableThreadEvenWhenSleeping(threading.Thread):
185 185 class Agent:
186 186 """
187 187 Behavior of an agent:
  188 + - If idle :
  189 + - still does routine_process() and general_process()
  190 + - does not do specific_process()
188 191 - Once a command has been sent to another agent :
189   - - It waits for the end of execution of the command and get its result
190   - - If command is timed out or has been skipped or killed, then same command will be re-executed at next iteration
191   - - Then only, it goes to next iteration
  192 + - It waits (non blocking) for the end of execution of the command and get its result
  193 + - If command is timed out or has been skipped or killed, then it is NOT re-executed at next iteration (except if needed explicitely)
192 194 """
193 195  
  196 + """
  197 + PLANTUML ACTIVITY DIAGRAM
  198 + # (http://plantuml.com/fr/activity-diagram-legacy)
  199 + """
  200 +
  201 + """
  202 + @startuml
  203 + version
  204 + @enduml
  205 + """
  206 +
  207 + """
  208 + @startuml
  209 +
  210 + title
  211 + __** Agent.run() function activity diagram **__
  212 + end title
  213 +
  214 + skinparam activity {
  215 + StartColor red
  216 + EndColor Silver
  217 + BackgroundColor Peru
  218 + BackgroundColor<< Begin >> Olive
  219 + BorderColor Peru
  220 + FontName Impact
  221 + }
  222 +
  223 + (*) --> load_config()
  224 +
  225 + --> init()
  226 +
  227 + partition infinite_loop {
  228 + ---> "reload_config()"
  229 + note right
  230 + only if changed
  231 + end note
  232 +
  233 + --> log_agent_status()
  234 + note right
  235 + Log this agent status in DB
  236 + end note
  237 +
  238 + --> routine_process()
  239 +
  240 + --> cmd = get_next_valid_command()
  241 + --> cmd = command_process(cmd)
  242 + note right
  243 + only if there is a command
  244 + end note
  245 + }
  246 +
  247 + If "NEW ITERATION ?" then
  248 + --> [Yes] "reload_config()"
  249 + else
  250 + --> (*)
  251 + Endif
  252 +
  253 + @enduml
  254 + """
  255 +
  256 +
194 257  
195 258 # Maximum duration of this agent (only for SIMULATION mode)
196 259 # If set to None, it will never exit except if asked (or CTRL-C)
197 260 # If set to 20, it will exit after 20s
198 261 SIMULATOR_MAX_DURATION_SEC = None
199 262 #SIMULATOR_MAX_DURATION_SEC = 30
200   -
  263 +
201 264 # FOR TEST ONLY
202 265 # Run this agent in simulator mode
203 266 SIMULATOR_MODE = True
... ... @@ -345,10 +408,10 @@ class Agent:
345 408 self.RUN_IN_THREAD = RUN_IN_THREAD
346 409 self.set_status(self.STATUS_LAUNCH)
347 410 self.set_idle()
348   -
  411 +
349 412 self._log = LogPyros()
350 413 self._log.set_agent_alias(self.name)
351   -
  414 +
352 415 #self.set_mode(self.MODE_IDLE)
353 416 if not config_filename:
354 417 config_filename = self.DEFAULT_CONFIG_FILE_NAME
... ... @@ -379,11 +442,11 @@ class Agent:
379 442 #if len(tmp) == 0:
380 443 #nb_agents = AgentSurvey.objects.filter(name=self.name).count()
381 444 #if nb_agents == 0:
382   - if not AgentSurvey.objects.filter(name=self.name).exists():
  445 + if AgentSurvey.objects.filter(name=self.name).exists():
  446 + self._agent_survey = AgentSurvey.objects.get(name=self.name)
  447 + else:
383 448 self._agent_survey = AgentSurvey.objects.create(name=self.name, validity_duration_sec=60, mode=self.mode, status=self.status)
384   - self.printd("Agent survey is", self._agent_survey)
385   - #self._agent_survey = AgentSurvey(name=self.name, validity_duration_sec=60, mode=self.mode, status=self.status)
386   - #self._agent_survey.save()
  449 + self.printd("Agent survey is", self._agent_survey)
387 450  
388 451 def __repr__(self):
389 452 return "I am agent " + self.name
... ... @@ -417,7 +480,7 @@ class Agent:
417 480 """
418 481  
419 482 self.load_config()
420   -
  483 +
421 484 if self.SIMULATOR_MODE:
422 485 self._log.print("[IN SIMULATOR MODE]")
423 486 else:
... ... @@ -440,11 +503,6 @@ class Agent:
440 503 Command.delete_pending_commands_for_agent(self.name)
441 504  
442 505 '''
443   - self.printd()
444   - self.printd(self)
445   - self.printd("FOR REAL ?", self.FOR_REAL)
446   - self.printd("DB3 used is:", djangosettings.DATABASES["default"]["NAME"])
447   -
448 506 # SETUP
449 507 try:
450 508 self.config = get_object_or_404(Config, id=1)
... ... @@ -467,7 +525,7 @@ class Agent:
467 525  
468 526 # Bad number of iterations, so exit
469 527 if nb_iter is not None:
470   - if nb_iter <= 0: break
  528 + if nb_iter <= 0: break
471 529 # Number of iterations asked is reached, so exit
472 530 if self._iter_num > nb_iter:
473 531 print(f"Exit because number of iterations asked ({nb_iter}) has been reached")
... ... @@ -488,8 +546,8 @@ class Agent:
488 546  
489 547 self.load_config() # only if changed
490 548  
491   - # Update my current mode and status in DB
492   - self.update_survey()
  549 + # Log this agent status (update my current mode and status in DB)
  550 + self.log_agent_status()
493 551  
494 552 self.printd("------START COMMMAND PROCESSING------")
495 553  
... ... @@ -500,18 +558,17 @@ class Agent:
500 558 #Command.purge_old_commands_for_agent(self.name)
501 559 self.purge_old_commands_sent_to_me()
502 560  
  561 + # ROUTINE process
  562 + #if self.is_active():
  563 + self.routine_process()
  564 + #self.printd("I am IDLE, so I bypass the routine_process (do not send any new command)")
  565 +
503 566 # Get next command to execute
504 567 cmd = self.get_next_valid_command()
505 568 #if cmd: cmd = self.general_process(cmd)
506   -
507 569 # Process this (next) command (if exists)
508 570 if cmd: cmd = self.command_process(cmd)
509 571  
510   - # ROUTINE process
511   - #if self.is_active():
512   - self.routine_process()
513   - #self.printd("I am IDLE, so I bypass the routine_process (do not send any new command)")
514   -
515 572 self.printd("------END COMMMAND PROCESSING------")
516 573  
517 574 #self.waitfor(self.mainloop_waittime)
... ... @@ -519,7 +576,7 @@ class Agent:
519 576 self.print("-"*20, "MAIN LOOP ITERATION (END)", "-"*20)
520 577 #self.do_log(LOG_DEBUG, "Ending main loop iteration")
521 578  
522   - # Exit if max duration is reached
  579 + # (simulator only) Exit if max duration is reached
523 580 if self.SIMULATOR_MAX_DURATION_SEC and (time.time()-start_time > self.SIMULATOR_MAX_DURATION_SEC):
524 581 self.print("Exit because of max duration set to ", self.SIMULATOR_MAX_DURATION_SEC, "s")
525 582 self.kill_running_specific_cmd_if_exists()
... ... @@ -782,15 +839,21 @@ class Agent:
782 839 self._log.set_home(home)
783 840  
784 841  
785   - def update_survey(self):
786   - self.printd("Updating the survey database table...")
  842 + #def update_survey(self):
  843 + def log_agent_status(self):
  844 + """
  845 + Save (update) this agent current mode and status in DB
  846 + """
  847 + self.printd("Updating the agent survey database table...")
787 848 #self.printd("- fetching table line for agent", self.name)
788 849 # only necessary when using process (not necessary with threads)
789 850 #with transaction.atomic():
790   - self._agent_survey = AgentSurvey.objects.get(name=self.name)
  851 + #self._agent_survey = AgentSurvey.objects.get(name=self.name)
791 852 self._agent_survey.mode = self.mode
792 853 self._agent_survey.status = self.status
793   - self._agent_survey.save()
  854 + #self._agent_survey.save()
  855 + self._agent_survey.save(update_fields=["mode", "status"])
  856 +
794 857  
795 858 """
796 859 def send_command(self, cmd_name):
... ...
src/agent/AgentA.py
... ... @@ -69,6 +69,7 @@ class AgentA(Agent):
69 69 def __init__(self, name:str=None, config_filename=None, RUN_IN_THREAD=True):
70 70 if name is None: name = self.__class__.__name__
71 71 super().__init__(name, config_filename, RUN_IN_THREAD)
  72 + self._log.print(f"init done for {name}")
72 73  
73 74 # @override
74 75 def init(self):
... ...
src/agent/Agent_run_activitydiag.png 0 → 100644

39.4 KB

src/agent/logpyros.py
... ... @@ -9,8 +9,8 @@ py_pwd = os.getcwd() + &quot;/../utils&quot;
9 9 if (py_pwd not in py_path):
10 10 (os.sys.path).append(py_pwd)
11 11  
12   -#import utils.celme as celme
13   -import celme
  12 +import utils.celme as celme
  13 +#import celme
14 14  
15 15 class LogPyros:
16 16  
... ...