FOSSology  3.2.0rc1
Open Source License Compliance by Open Source Software
Agent.php
Go to the documentation of this file.
1 <?php
2 /*
3 Author: Daniele Fognini
4 Copyright (C) 2014-2015, Siemens AG
5 
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 version 2 as published by the Free Software Foundation.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19 
31 namespace Fossology\Lib\Agent;
32 
36 
37 require_once(dirname(dirname(__FILE__))."/common-cli.php");
38 
43 define("ALARM_SECS", 30);
44 
51 abstract class Agent
52 {
55  private $agentName;
58  private $agentVersion;
61  private $agentRev;
64  private $agentDesc;
67  private $agentArs;
70  private $agentId;
71 
74  protected $userId;
77  protected $groupId;
80  protected $jobId;
81 
86  protected $agentSpecifOptions = "";
91  protected $agentSpecifLongOptions = array();
92 
95  protected $args = array();
96 
99  protected $dbManager;
100 
103  protected $agentDao;
104 
107  protected $container;
108 
111  protected $schedulerMode;
112 
119  function __construct($agentName, $version, $revision)
120  {
121  $this->agentName = $agentName;
122  $this->agentVersion = $version;
123  $this->agentDesc = $agentName. " agent";
124  $this->agentRev = $version.".".$revision;
125  $this->agentArs = strtolower( $agentName ) . "_ars";
126  $this->schedulerMode = false;
127 
128  $GLOBALS['processed'] = 0;
129  $GLOBALS['alive'] = false;
130 
131  /* initialize the environment */
132  cli_Init();
133 
134  global $container;
135  $this->container = $container;
136  $this->dbManager = $container->get('db.manager');
137  $this->agentDao = $container->get('dao.agent');
138 
139  $this->agentId = $this->agentDao->getCurrentAgentId($this->agentName, $this->agentDesc, $this->agentRev);
140  }
141 
150  function scheduler_connect()
151  {
152  $schedulerHandledOpts = "c:";
153  $schedulerHandledLongOpts = array("userID:","groupID:","jobId:","scheduler_start",'config:');
154 
155  $longOpts = array_merge($schedulerHandledLongOpts, $this->agentSpecifLongOptions);
156  $shortOpts = $schedulerHandledOpts . $this->agentSpecifOptions;
157 
158  $args = getopt($shortOpts, $longOpts);
159 
160  $this->schedulerMode = (array_key_exists("scheduler_start", $args));
161 
162  $this->userId = $args['userID'];
163  $this->groupId = $args['groupID'];
164  $this->jobId = $args['jobId'];
165 
166  unset ($args['jobId']);
167  unset ($args['userID']);
168  unset ($args['groupID']);
169 
170  $this->initArsTable();
171 
172  if ($this->schedulerMode) {
173  $this->scheduler_greet();
174 
175  pcntl_signal(SIGALRM, function($signo)
176  {
177  Agent::heartbeat_handler($signo);
178  });
179  pcntl_alarm(ALARM_SECS);
180  }
181 
182  $this->args = $args;
183  }
184 
195  static function heartbeat_handler($signo)
196  {
197  global $processed;
198  global $alive;
199 
200  echo "HEART: $processed ".($alive ? '1' : '0')."\n";
201  $alive = false;
202  pcntl_alarm(ALARM_SECS);
203  }
204 
214  function heartbeat($newProcessed)
215  {
216  if ($this->schedulerMode) {
217  global $processed;
218  global $alive;
219 
220  $processed += $newProcessed;
221 
222  $alive = true;
223  pcntl_signal_dispatch();
224  }
225  }
226 
232  function bail($exitvalue)
233  {
234  debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
235  $this->scheduler_disconnect($exitvalue);
236  throw new \Exception('agent fail in '.__FILE__.':'.__LINE__,$exitvalue);
237  }
238 
247  function scheduler_disconnect($exitvalue)
248  {
249  if ($this->schedulerMode) {
250  Agent::heartbeat_handler(SIGALRM);
251  echo "BYE $exitvalue\n";
252  }
253  }
254 
260  function scheduler_greet()
261  {
262  echo "VERSION: ".$this->agentVersion."\n";
263  echo "OK\n";
264  }
265 
269  function initArsTable()
270  {
271  if (!$this->agentDao->arsTableExists($this->agentName)) {
272  $this->agentDao->createArsTable($this->agentName);
273  }
274  }
275 
283  abstract protected function processUploadId($uploadId);
284 
294  private function scheduler_current()
295  {
296  ($line = fgets(STDIN));
297  if ("CLOSE\n" === $line) {
298  return false;
299  }
300  if ("END\n" === $line) {
301  return false;
302  }
303 
304  return $line;
305  }
306 
322  {
323  while (false !== ($line = $this->scheduler_current())) {
324  $this->heartbeat(0);
325 
326  $uploadId = intval($line);
327  if ($uploadId <= 0) {
328  continue;
329  }
330 
331  $arsId = $this->agentDao->writeArsRecord($this->agentName, $this->agentId, $uploadId);
332  if ($arsId<0) {
333  print "cannot insert ars record";
334  $this->bail(2);
335  }
336 
337  try {
338  $success = $this->processUploadId($uploadId);
339  } catch(\Exception $e) {
340  print "Caught exception while processing uploadId=$uploadId: ".$e->getMessage();
341  print $e->getTraceAsString();
342  $success = false;
343  }
344 
345  $this->agentDao->writeArsRecord($this->agentName, $this->agentId, $uploadId, $arsId, $success);
346 
347  if (!$success) {
348  print "agent failed on uploadId=$uploadId";
349  $this->bail(1);
350  }
351  }
352  }
353 }
__construct($agentName, $version, $revision)
Definition: Agent.php:119
scheduler_disconnect($exitvalue)
Closes connection from scheduler.
Definition: Agent.php:247
heartbeat($newProcessed)
Send hear beat to the scheduler.
Definition: Agent.php:214
static heartbeat_handler($signo)
Function to handle hear beats from the agent and send them to the scheduler from STDOUT.
Definition: Agent.php:195
initArsTable()
Initialize ARS table.
Definition: Agent.php:269
int schedulerMode
Definition: nomos.c:40
const ALARM_SECS
Definition: Agent.php:43
Structure of an Agent with all required parameters.
Definition: Agent.php:51
bail($exitvalue)
Bail the agent, print the stack and disconnect from scheduler.
Definition: Agent.php:232
int jobId
The id of the job.
run_scheduler_event_loop()
Runs a loop to read commands from scheduler and process them.
Definition: Agent.php:321
cli_Init()
Initialize the fossology environment for CLI use. This routine loads the plugins so they can be use b...
Definition: common-cli.php:36
scheduler_connect()
Connect with scheduler and initialize options.
Definition: Agent.php:150
scheduler_greet()
Greet the scheduler at the beginning of connection.
Definition: Agent.php:260
processUploadId($uploadId)
Given an upload ID, process the items in it.
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:28
Fossology exception.
Definition: Exception.php:25
scheduler_current()
Read the commands from scheduler.
Definition: Agent.php:294