FOSSology  4.7.1
Open Source License Compliance by Open Source Software
job.c
Go to the documentation of this file.
1 /*
2  SPDX-FileCopyrightText: © 2010, 2011, 2012 Hewlett-Packard Development Company, L.P.
3  SPDX-FileCopyrightText: © 2015 Siemens AG
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
12 /* local includes */
13 #include <libfossrepo.h>
14 #include <agent.h>
15 #include <database.h>
16 #include <job.h>
17 #include <scheduler.h>
18 
19 /* std library includes */
20 #include <stdlib.h>
21 
22 /* unix library includes */
23 #include <sys/types.h>
24 #include <unistd.h>
25 #include <sys/time.h>
26 #include <sys/resource.h>
27 
28 /* other library includes */
29 #include <glib.h>
30 #include <gio/gio.h>
31 
32 #define TEST_NULV(j) if(!j) { errno = EINVAL; ERROR("job passed is NULL, cannot proceed"); return; }
33 #define TEST_NULL(j, ret) if(!j) { errno = EINVAL; ERROR("job passed is NULL, cannot proceed"); return ret; }
34 #define MAX_SQL 512;JOB_STATUS_TYPES
35 
36 /* ************************************************************************** */
37 /* **** Locals ************************************************************** */
38 /* ************************************************************************** */
39 
44 #define SELECT_STRING(passed) MK_STRING_LIT(JOB_##passed),
45 const char* job_status_strings[] = { JOB_STATUS_TYPES(SELECT_STRING) };
46 #undef SELECT_STRING
47 
60 static int is_active(int* job_id, job_t* job, int* counter)
61 {
62  if((job->running_agents != NULL || job->failed_agents != NULL) || job->id < 0)
63  ++(*counter);
64  return 0;
65 }
66 
80 static int job_sstatus(int* job_id, job_t* job, GOutputStream* ostr)
81 {
82  gchar* status_str = g_strdup_printf(
83  "job:%d status:%s type:%s, priority:%d running:%d finished:%d failed:%d\n",
84  job->id,
85  job_status_strings[job->status],
86  job->agent_type,
87  job->priority,
88  g_list_length(job->running_agents),
89  g_list_length(job->finished_agents),
90  g_list_length(job->failed_agents));
91 
92  V_JOB("JOB_STATUS: %s", status_str);
93  g_output_stream_write(ostr, status_str, strlen(status_str), NULL, NULL);
94 
95  if(*job_id == 0)
96  g_list_foreach(job->running_agents, (GFunc)agent_print_status, ostr);
97 
98  g_free(status_str);
99  return 0;
100 }
101 
109 static void job_transition(scheduler_t* scheduler, job_t* job, job_status new_status)
110 {
111  /* book keeping */
112  TEST_NULV(job);
113  V_JOB("JOB[%d]: job status changed: %s => %s\n",
114  job->id, job_status_strings[job->status], job_status_strings[new_status]);
115 
116  /* change the job status */
117  job->status = new_status;
118 
119  /* only update database for real jobs */
120  if(job->id >= 0)
121  database_update_job(scheduler, job, new_status);
122 }
123 
135 gint job_compare(gconstpointer a, gconstpointer b, gpointer user_data)
136 {
137  return ((job_t*)a)->priority - ((job_t*)b)->priority;
138 }
139 
140 /* ************************************************************************** */
141 /* **** Constructor Destructor ********************************************** */
142 /* ************************************************************************** */
143 
164 job_t* job_init(GTree* job_list, GSequence* job_queue,
165  char* type, char* host, int id, int parent_id, int user_id, int group_id, int priority, char *jq_cmd_args)
166 {
167  job_t* job = g_new0(job_t, 1);
168 
169  job->agent_type = g_strdup(type);
170  job->required_host = g_strdup(host);
171  job->running_agents = NULL;
172  job->finished_agents = NULL;
173  job->failed_agents = NULL;
174  job->log = NULL;
175  job->status = JB_CHECKEDOUT;
176  job->data = NULL;
177  job->db_result = NULL;
178  job->lock = NULL;
179  job->idx = 0;
180  job->message = NULL;
181  job->priority = priority;
182  job->verbose = 0;
183  job->parent_id = parent_id;
184  job->id = id;
185  job->user_id = user_id;
186  job->group_id = group_id;
187  job->jq_cmd_args = g_strdup(jq_cmd_args);
188  job->checkedout_at = time(NULL);
189 
190  g_tree_insert(job_list, &job->id, job);
191  if(id >= 0) g_sequence_insert_sorted(job_queue, job, job_compare, NULL);
192  return job;
193 }
194 
202 void job_destroy(job_t* job)
203 {
204  TEST_NULV(job);
205 
206  if(job->db_result != NULL)
207  {
208  SafePQclear(job->db_result);
209 
210  /* lock may be NULL if job_set_data(sql=1) was never called. */
211  if(job->lock != NULL)
212  {
213  g_mutex_lock(job->lock);
214  g_mutex_unlock(job->lock);
215 #if GLIB_CHECK_VERSION(2, 32, 0)
216  g_mutex_clear(job->lock);
217 #else
218  g_mutex_free(job->lock);
219 #endif
220  g_free(job->lock);
221  job->lock = NULL;
222  }
223  }
224 
225  if(job->log)
226  log_destroy(job->log);
227 
228  g_list_free(job->running_agents);
229  g_list_free(job->finished_agents);
230  g_list_free(job->failed_agents);
231  g_free(job->message);
232  g_free(job->agent_type);
233  g_free(job->required_host);
234  g_free(job->data);
235  if (job->jq_cmd_args) g_free(job->jq_cmd_args);
236  g_free(job);
237 }
238 
239 /* ************************************************************************** */
240 /* **** Events ************************************************************** */
241 /* ************************************************************************** */
242 
250 void job_verbose_event(scheduler_t* scheduler, job_t* job)
251 {
252  GList* iter;
253 
254  TEST_NULV(job);
255  for(iter = job->running_agents; iter != NULL; iter = iter->next)
256  aprintf(iter->data, "VERBOSE %d\n", job->verbose);
257 }
258 
272 void job_status_event(scheduler_t* scheduler, arg_int* params)
273 {
274  const char end[] = "end\n";
275  GError* error = NULL;
276 
277  int tmp = 0;
278  char buf[1024];
279 
280  if(!params->second)
281  {
282  memset(buf, '\0', sizeof(buf));
283  sprintf(buf, "scheduler:%d revision:%s daemon:%d jobs:%d log:%s port:%d verbose:%d\n",
284  scheduler->s_pid, fo_config_get(scheduler->sysconfig, "BUILD", "COMMIT_HASH", &error),
285  scheduler->s_daemon, g_tree_nnodes(scheduler->job_list), main_log->log_name,
286  scheduler->i_port, verbose);
287 
288  g_output_stream_write(params->first, buf, strlen(buf), NULL, NULL);
289  g_tree_foreach(scheduler->job_list, (GTraverseFunc)job_sstatus, params->first);
290  }
291  else
292  {
293  job_t* stat = g_tree_lookup(scheduler->job_list, &params->second);
294  if(stat)
295  {
296  job_sstatus(&tmp, g_tree_lookup(scheduler->job_list, &params->second), params->first);
297  }
298  else
299  {
300  sprintf(buf, "ERROR: invalid job id = %d\n", params->second);
301  g_output_stream_write(params->first, buf, strlen(buf), NULL, NULL);
302  }
303  }
304 
305  g_output_stream_write(params->first, end, sizeof(end), NULL, NULL);
306  g_free(params);
307 }
308 
318 void job_pause_event(scheduler_t* scheduler, arg_int* params)
319 {
320  job_t tmp_job;
321  job_t* job = params->first;
322  GList* iter;
323 
324  // if the job doesn't exist, create a fake
325  if(params->first == NULL)
326  {
327  tmp_job.id = params->second;
328  tmp_job.status = JB_NOT_AVAILABLE;
329  tmp_job.running_agents = NULL;
330  tmp_job.message = NULL;
331 
332  job = &tmp_job;
333  }
334 
335  job_transition(scheduler, job, JB_PAUSED);
336  for(iter = job->running_agents; iter != NULL; iter = iter->next)
337  agent_pause(iter->data);
338 
339  g_free(params);
340 }
341 
348 void job_restart_event(scheduler_t* scheduler, arg_int* params)
349 {
350  job_t tmp_job;
351  job_t* job = params->first;
352  GList* iter;
353 
354  // if the job doesn't exist, create a fake
355  if(job == NULL)
356  {
357  tmp_job.id = params->second;
358  tmp_job.status = JB_PAUSED;
359  tmp_job.running_agents = NULL;
360  tmp_job.message = NULL;
361 
362  event_signal(database_update_event, NULL);
363  job = &tmp_job;
364  }
365 
366  if(job->status != JB_PAUSED)
367  {
368  ERROR("attempt to restart job %d failed, job status was %s",
369  job->id, job_status_strings[job->status]);
370  g_free(params);
371  return;
372  }
373 
374  for(iter = job->running_agents; iter != NULL; iter = iter->next)
375  {
376  if(job->db_result != NULL) agent_write(iter->data, "OK\n", 3);
377  agent_unpause(iter->data);
378  }
379 
380  job_transition(scheduler, job, JB_RESTART);
381  g_free(params);
382 }
383 
391 void job_priority_event(scheduler_t* scheduler, arg_int* params)
392 {
393  GList* iter;
394  job_t* job = (job_t*)params->first;
395 
396  if(!job)
397  {
398  ERROR("job_priority_event: NULL job passed, ignoring");
399  g_free(params);
400  return;
401  }
402 
403  database_job_priority(scheduler, job, params->second);
404  job->priority = params->second;
405 
406  /* re-sort in the queue. g_sequence_search() is unsafe once the key changed,
407  * so find the job by pointer and let g_sequence_sort_changed() move it */
408  {
409  GSequenceIter* it = g_sequence_get_begin_iter(scheduler->job_queue);
410  while(!g_sequence_iter_is_end(it))
411  {
412  if(g_sequence_get(it) == job)
413  {
414  g_sequence_sort_changed(it, job_compare, NULL);
415  break;
416  }
417  it = g_sequence_iter_next(it);
418  }
419  }
420 
421  for(iter = job->running_agents; iter; iter = iter->next)
422  setpriority(PRIO_PROCESS, ((agent_t*)iter->data)->pid, params->second);
423 
424  g_free(params);
425 }
426 
437 void job_fail_event(scheduler_t* scheduler, job_t* job)
438 {
439  GList* iter;
440 
441  if(job->status != JB_FAILED)
442  {
443  job_transition(scheduler, job, JB_FAILED);
444  }
445 
446  for(iter = job->running_agents; iter != NULL; iter = iter->next)
447  {
448  V_JOB("JOB[%d]: job failed, killing agent\n", job->id);
449  agent_kill(iter->data);
450  }
451 
452  /* Also kill the finished (AG_PAUSED) agents, which still hold a process slot
453  * and pipes until the watchdog would fire. They were already accounted at the
454  * PAUSED transition, so kill() directly (return_code=0) rather than agent_kill()
455  * to avoid a double-decrement. */
456  for(iter = job->finished_agents; iter != NULL; iter = iter->next)
457  {
458  agent_t* a = (agent_t*)iter->data;
459  V_JOB("JOB[%d]: job failed, killing finished agent pid %d\n", job->id, a->pid);
460  a->return_code = 0;
461  kill(-a->pid, SIGKILL); /* process group, so child processes die too */
462  }
463 }
464 
465 /* ************************************************************************** */
466 /* **** Functions *********************************************************** */
467 /* ************************************************************************** */
468 
479 void job_add_agent(job_t* job, void* agent)
480 {
481  TEST_NULV(job);
482  TEST_NULV(agent);
483  job->running_agents = g_list_append(job->running_agents, agent);
484 }
485 
494 void job_remove_agent(job_t* job, GTree* job_list, void* agent)
495 {
496  GList* curr;
497  TEST_NULV(job);
498 
499  if(job->finished_agents && agent)
500  job->finished_agents = g_list_remove(job->finished_agents, agent);
501 
502  if(job->finished_agents == NULL && job->running_agents == NULL &&
503  (job->status == JB_COMPLETE || job->status == JB_FAILED))
504  {
505  V_JOB("JOB[%d]: job removed from system\n", job->id);
506 
507  for(curr = job->failed_agents; curr != NULL; curr = curr->next)
508  ((agent_t*)curr->data)->owner = NULL;
509 
510  g_tree_remove(job_list, &job->id);
511  }
512 }
513 
520 void job_finish_agent(job_t* job, void* agent)
521 {
522  TEST_NULV(job);
523  TEST_NULV(agent);
524 
525  job->running_agents = g_list_remove(job->running_agents, agent);
526  job->finished_agents = g_list_append(job->finished_agents, agent);
527 }
528 
535 void job_fail_agent(job_t* job, void* agent)
536 {
537  TEST_NULV(job);
538  TEST_NULV(agent);
539  job->running_agents = g_list_remove(job->running_agents, agent);
540  job->failed_agents = g_list_append(job->failed_agents, agent);
541 }
542 
553 void job_set_data(scheduler_t* scheduler, job_t* job, char* data, int sql)
554 {
555  g_free(job->data);
556  job->data = g_strdup(data);
557  job->idx = 0;
558 
559  if(sql)
560  {
561  // TODO
562  //j->db_result = PQexec(db_conn, j->data);
563  //j->lock = g_mutex_new();
564  }
565 }
566 
574 void job_update(scheduler_t* scheduler, job_t* job)
575 {
576  GList* iter;
577  int finished = 1;
578 
579  TEST_NULV(job)
580 
581  for(iter = job->running_agents; iter != NULL; iter = iter->next)
582  if(((agent_t*)iter->data)->status != AG_PAUSED)
583  finished = 0;
584 
585  if(job->status != JB_PAUSED && job->status != JB_COMPLETE && finished)
586  {
587  if(job->failed_agents == NULL)
588  {
589  /* don't mark an already-failed job complete: a finished agent killed by
590  * job_fail_event() can reach here after the job is already JB_FAILED */
591  if(job->status != JB_FAILED)
592  {
593  job_transition(scheduler, job, JB_COMPLETE);
594  for(iter = job->finished_agents; iter != NULL; iter = iter->next)
595  {
596  aprintf(iter->data, "CLOSE\n");
597  }
598  }
599  }
600  /* this indicates a failed agent */
601  else
602  {
603  /* free the failed-agent list before failing the job, and skip if it is
604  * already failed */
605  if(job->status != JB_FAILED)
606  {
607  g_list_free(job->failed_agents);
608  job->failed_agents = NULL;
609  g_free(job->message);
610  job->message = NULL;
611  job_fail_event(scheduler, job);
612  }
613  }
614  }
615 }
616 
624 int job_is_open(scheduler_t* scheduler, job_t* job)
625 {
626  /* local */
627  int retval = 0;
628 
629  TEST_NULL(job, -1);
630 
631  /* check to make sure that the job status is correct */
632  if(job->status == JB_CHECKEDOUT)
633  job_transition(scheduler, job, JB_STARTED);
634 
635  /* check to see if we even need to worry about sql stuff */
636  if(job->db_result == NULL)
637  return (job->idx == 0 && job->data != NULL);
638 
639  g_mutex_lock(job->lock);
640  if(job->idx < PQntuples(job->db_result))
641  {
642  retval = 1;
643  }
644  else
645  {
646  SafePQclear(job->db_result);
647  job->db_result = database_exec(scheduler, job->data);
648  job->idx = 0;
649 
650  /* database_exec() can return NULL (lost connection, failed query). Guard so
651  * PQntuples() is never called on NULL, which would crash the scheduler. */
652  if(job->db_result == NULL)
653  {
654  g_mutex_unlock(job->lock);
655  ERROR("JOB[%d]: database_exec returned NULL, marking job as failed", job->id);
656  return -1;
657  }
658 
659  retval = PQntuples(job->db_result) != 0;
660  }
661 
662  g_mutex_unlock(job->lock);
663  return retval;
664 }
665 
673 char* job_next(job_t* job)
674 {
675  char* retval = NULL;
676 
677  TEST_NULL(job, NULL);
678  if(job->db_result == NULL)
679  {
680  job->idx = 1;
681  return job->data;
682  }
683 
684  g_mutex_lock(job->lock);
685 
686  if(job->idx < PQntuples(job->db_result))
687  retval = PQgetvalue(job->db_result, job->idx++, 0);
688 
689  g_mutex_unlock(job->lock);
690  return retval;
691 }
692 
701 {
702  FILE* file;
703  gchar* file_name;
704  gchar* file_path;
705 
706  if(job->id < 0)
707  return main_log;
708 
709  if(job->log)
710  return job->log;
711 
712  file_name = g_strdup_printf("%06d", job->id);
713  file_path = fo_RepMkPath("logs", file_name);
714 
715  if((file = fo_RepFwrite("logs", file_name)) == NULL)
716  {
717  ERROR("JOB[%d]: job unable to create log file: %s\n", job->id, file_path);
718  g_free(file_name);
719  free(file_path);
720  return NULL;
721  }
722 
723  V_JOB("JOB[%d]: job created log file:\n %s\n", job->id, file_path);
724  database_job_log(job->id, file_path);
725  job->log = log_new_FILE(file, file_name, job->agent_type, 0);
726 
727  g_free(file_name);
728  free(file_path);
729  return job->log;
730 }
731 
732 /* ************************************************************************** */
733 /* **** Job list Functions ************************************************** */
734 /* ************************************************************************** */
735 
744 job_t* next_job(GSequence* job_queue)
745 {
746  job_t* retval = NULL;
747  GSequenceIter* beg = g_sequence_get_begin_iter(job_queue);
748 
749  if(g_sequence_get_length(job_queue) != 0)
750  {
751  retval = g_sequence_get(beg);
752  g_sequence_remove(beg);
753  }
754 
755  return retval;
756 }
757 
764 job_t* peek_job(GSequence* job_queue)
765 {
766  GSequenceIter* beg;
767 
768  if(g_sequence_get_length(job_queue) == 0)
769  {
770  return NULL;
771  }
772 
773  beg = g_sequence_get_begin_iter(job_queue);
774  return g_sequence_get(beg);
775 }
776 
783 uint32_t active_jobs(GTree* job_list)
784 {
785  int count = 0;
786  g_tree_foreach(job_list, (GTraverseFunc)is_active, &count);
787  return count;
788 }
789 
int aprintf(agent_t *agent, const char *fmt,...)
Definition: agent.c:1617
ssize_t agent_write(agent_t *agent, const void *buf, int count)
Definition: agent.c:1653
void agent_kill(agent_t *agent)
Unclean kill of an agent whose job should fail.
Definition: agent.c:1601
void agent_pause(agent_t *agent)
Definition: agent.c:1536
#define TEST_NULL(a, ret)
Test if paramater is NULL.
Definition: agent.c:57
void agent_unpause(agent_t *agent)
Definition: agent.c:1549
#define TEST_NULV(a)
Test if paramater is NULL.
Definition: agent.c:47
void agent_print_status(agent_t *agent, GOutputStream *ostr)
Prints the status of the agent to the output stream provided.
Definition: agent.c:1565
Header file with agent related operations.
int verbose
The verbose flag for the cli.
Definition: fo_cli.c:38
char * fo_config_get(fo_conf *conf, const char *group, const char *key, GError **error)
Gets an element based on its group name and key name. If the group or key is not found,...
Definition: fossconfig.c:336
void job_fail_agent(job_t *job, void *agent)
Definition: job.c:535
void job_fail_event(scheduler_t *scheduler, job_t *job)
Events that causes a job to be marked a failed.
Definition: job.c:437
void job_restart_event(scheduler_t *scheduler, arg_int *params)
Definition: job.c:348
job_t * job_init(GTree *job_list, GSequence *job_queue, char *type, char *host, int id, int parent_id, int user_id, int group_id, int priority, char *jq_cmd_args)
Create a new job.
Definition: job.c:164
job_t * next_job(GSequence *job_queue)
Gets the next job from the job queue.
Definition: job.c:744
void job_update(scheduler_t *scheduler, job_t *job)
Definition: job.c:574
static int is_active(int *job_id, job_t *job, int *counter)
Tests if a job is active.
Definition: job.c:60
static void job_transition(scheduler_t *scheduler, job_t *job, job_status new_status)
Definition: job.c:109
int job_is_open(scheduler_t *scheduler, job_t *job)
Tests to see if there is still data available for this job.
Definition: job.c:624
void job_set_data(scheduler_t *scheduler, job_t *job, char *data, int sql)
Definition: job.c:553
char * job_next(job_t *job)
Definition: job.c:673
job_t * peek_job(GSequence *job_queue)
Gets the job that is at the top of the queue if there is one.
Definition: job.c:764
void job_remove_agent(job_t *job, GTree *job_list, void *agent)
Definition: job.c:494
void job_verbose_event(scheduler_t *scheduler, job_t *job)
Definition: job.c:250
void job_pause_event(scheduler_t *scheduler, arg_int *params)
Event to pause a job.
Definition: job.c:318
void job_status_event(scheduler_t *scheduler, arg_int *params)
Event to get the status of the scheduler or a specific job.
Definition: job.c:272
gint job_compare(gconstpointer a, gconstpointer b, gpointer user_data)
Used to compare two different jobs in the priority queue.
Definition: job.c:135
void job_destroy(job_t *job)
Definition: job.c:202
log_t * job_log(job_t *job)
Definition: job.c:700
void job_add_agent(job_t *job, void *agent)
Adds a new agent to the jobs list of agents.
Definition: job.c:479
void job_priority_event(scheduler_t *scheduler, arg_int *params)
Definition: job.c:391
void job_finish_agent(job_t *job, void *agent)
Definition: job.c:520
static int job_sstatus(int *job_id, job_t *job, GOutputStream *ostr)
Prints the jobs status to the output stream.
Definition: job.c:80
#define SELECT_STRING(passed)
Definition: job.c:44
uint32_t active_jobs(GTree *job_list)
Gets the number of jobs that are not paused.
Definition: job.c:783
FILE * fo_RepFwrite(char *Type, char *Filename)
Perform an fwrite. Also creates directories.
Definition: libfossrepo.c:710
char * fo_RepMkPath(const char *Type, char *Filename)
Given a filename, construct the full path to the file.
Definition: libfossrepo.c:352
log_t * main_log
Definition: logging.c:33
log_t * log_new_FILE(FILE *log_file, gchar *log_name, gchar *pro_name, pid_t pro_pid)
Creates a log file structure based on an already created FILE*.
Definition: logging.c:126
void log_destroy(log_t *log)
Free memory associated with the log file.
Definition: logging.c:150
#define ERROR(...)
Definition: logging.h:79
PGresult * database_exec(scheduler_t *scheduler, const char *sql)
Executes an sql statement for the scheduler.
Definition: database.c:804
void database_job_priority(scheduler_t *scheduler, job_t *job, int priority)
Changes the priority of a job queue entry in the database.
Definition: database.c:1028
void database_update_job(scheduler_t *scheduler, job_t *job, job_status status)
Change the status of a job in the database.
Definition: database.c:946
void database_update_event(scheduler_t *scheduler, void *unused)
Checks the job queue for any new entries.
Definition: database.c:846
void database_job_log(int j_id, char *log_name)
Enters the name of the log file for a job into the database.
Definition: database.c:1013
Header file for the scheduler.
#define SafePQclear(pgres)
Definition: scheduler.h:129
Definition: agent.h:100
gchar * data
the data that has been sent to the agent for analysis
Definition: agent.h:122
uint8_t return_code
what was returned by the agent when it disconnected
Definition: agent.h:126
pid_t pid
the pid of the process this agent is running in
Definition: agent.h:110
Definition: event.h:46
The job structure.
Definition: job.h:52
int32_t id
The identifier for this job.
Definition: job.h:74
GMutex * lock
Lock to maintain data integrity.
Definition: job.h:66
job_status status
The current status for the job.
Definition: job.h:62
uint32_t idx
The current index into the sql results.
Definition: job.h:67
int32_t group_id
The id of the group that created the job.
Definition: job.h:76
char * required_host
If not NULL, this job must run on a specific host machine.
Definition: job.h:55
GList * finished_agents
The list of agents that have completed their tasks.
Definition: job.h:57
gchar * message
Message that will be sent with job notification email.
Definition: job.h:70
gchar * jq_cmd_args
Command line arguments for this job.
Definition: job.h:64
time_t checkedout_at
Timestamp when job entered JB_CHECKEDOUT (for stale detection grace period)
Definition: job.h:77
int32_t user_id
The id of the user that created the job.
Definition: job.h:75
GList * failed_agents
The list of agents that failed while working.
Definition: job.h:58
char * agent_type
The type of agent used to analyze the data.
Definition: job.h:54
gchar * data
The data associated with this job (jq_args)
Definition: job.h:63
int32_t priority
Importance of the job, maps directory to unix priority.
Definition: job.h:71
int32_t parent_id
The identifier for the parent of this job (its queue id)
Definition: job.h:73
GList * running_agents
The list of agents assigned to this job that are still working.
Definition: job.h:56
PGresult * db_result
Results from the sql query (if any)
Definition: job.h:65
log_t * log
The log to print any agent logging messages to.
Definition: job.h:59
int32_t verbose
The verbose level for all of the agents in this job.
Definition: job.h:72
Definition: logging.h:35
gchar * log_name
The name of the log file that will be printed to.
Definition: logging.h:36
GTree * job_list
List of jobs that have been created.
Definition: scheduler.h:172
gboolean s_pid
The pid of the scheduler process.
Definition: scheduler.h:143
GSequence * job_queue
heap of jobs that still need to be started
Definition: scheduler.h:173
gboolean s_daemon
Is the scheduler being run as a daemon.
Definition: scheduler.h:144
fo_conf * sysconfig
Configuration information loaded from the configuration file.
Definition: scheduler.h:149
uint16_t i_port
The port that the scheduler is listening on.
Definition: scheduler.h:166