job.h revision b30e2f4c18ad81b04e4314fd191a5d458553773c
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#ifndef foojobhfoo
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#define foojobhfoo
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/***
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen This file is part of systemd.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Copyright 2010 Lennart Poettering
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is free software; you can redistribute it and/or modify it
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen under the terms of the GNU General Public License as published by
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen the Free Software Foundation; either version 2 of the License, or
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (at your option) any later version.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is distributed in the hope that it will be useful, but
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen WITHOUT ANY WARRANTY; without even the implied warranty of
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen General Public License for more details.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen You should have received a copy of the GNU General Public License
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen***/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <stdbool.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <inttypes.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <errno.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersentypedef struct Job Job;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersentypedef struct JobDependency JobDependency;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersentypedef enum JobType JobType;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersentypedef enum JobState JobState;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersentypedef enum JobMode JobMode;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersentypedef enum JobResult JobResult;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "manager.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "unit.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "hashmap.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "list.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/* Be careful when changing the job types! Adjust job_merging_table[] accordingly! */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenenum JobType {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_START, /* if a unit does not support being started, we'll just wait until it becomes active */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_VERIFY_ACTIVE,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_STOP,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_RELOAD, /* if running reload */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_RELOAD_OR_START, /* if running reload, if not running start */
d5d8429a12c4b1ef0dcd226c0904f00f4fa4898aLennart Poettering
d5d8429a12c4b1ef0dcd226c0904f00f4fa4898aLennart Poettering /* Note that restarts are first treated like JOB_STOP, but
d5d8429a12c4b1ef0dcd226c0904f00f4fa4898aLennart Poettering * then instead of finishing are patched to become
d5d8429a12c4b1ef0dcd226c0904f00f4fa4898aLennart Poettering * JOB_START. */
d5d8429a12c4b1ef0dcd226c0904f00f4fa4898aLennart Poettering JOB_RESTART, /* if running stop, then start unconditionally */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_TRY_RESTART, /* if running stop and then start */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _JOB_TYPE_MAX,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _JOB_TYPE_INVALID = -1
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenenum JobState {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_WAITING,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_RUNNING,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _JOB_STATE_MAX,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _JOB_STATE_INVALID = -1
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen};
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmekenum JobMode {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_FAIL, /* Fail if a conflicting job is already queued */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_REPLACE, /* Replace an existing conflicting job */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_ISOLATE, /* Start a unit, and stop all others */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_IGNORE_DEPENDENCIES, /* Ignore both requirement and ordering dependencies */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_IGNORE_REQUIREMENTS, /* Ignore requirement dependencies */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _JOB_MODE_MAX,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _JOB_MODE_INVALID = -1
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersenenum JobResult {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_DONE,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_CANCELED,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_TIMEOUT,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_FAILED,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JOB_DEPENDENCY,
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek JOB_SKIPPED,
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek _JOB_RESULT_MAX,
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek _JOB_RESULT_INVALID = -1
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek};
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmekstruct JobDependency {
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek /* Encodes that the 'subject' job needs the 'object' job in
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek * some way. This structure is used only while building a transaction. */
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek Job *subject;
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek Job *object;
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek LIST_FIELDS(JobDependency, subject);
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek LIST_FIELDS(JobDependency, object);
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek bool matters;
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek bool conflicts;
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek};
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmekstruct Job {
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek Manager *manager;
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek Unit *unit;
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek LIST_FIELDS(Job, transaction);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen LIST_FIELDS(Job, run_queue);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen LIST_FIELDS(Job, dbus_queue);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen LIST_HEAD(JobDependency, subject_list);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen LIST_HEAD(JobDependency, object_list);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Used for graph algs as a "I have been here" marker */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Job* marker;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unsigned generation;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uint32_t id;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JobType type;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JobState state;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Watch timer_watch;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Note that this bus object is not ref counted here. */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen DBusConnection *bus;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char *bus_client;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen JobResult result;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool installed:1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool in_run_queue:1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool matters_to_anchor:1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool override:1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool in_dbus_queue:1;
b7e7184634d573fb73143210962acce205f37f61Michael Biebl bool sent_dbus_new_signal:1;
b7e7184634d573fb73143210962acce205f37f61Michael Biebl bool ignore_order:1;
b7e7184634d573fb73143210962acce205f37f61Michael Biebl};
b7e7184634d573fb73143210962acce205f37f61Michael Biebl
b7e7184634d573fb73143210962acce205f37f61Michael BieblJob* job_new(Manager *m, JobType type, Unit *unit);
b7e7184634d573fb73143210962acce205f37f61Michael Bieblvoid job_free(Job *job);
b7e7184634d573fb73143210962acce205f37f61Michael Bieblvoid job_dump(Job *j, FILE*f, const char *prefix);
b7e7184634d573fb73143210962acce205f37f61Michael Biebl
b7e7184634d573fb73143210962acce205f37f61Michael BieblJobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts);
b7e7184634d573fb73143210962acce205f37f61Michael Bieblvoid job_dependency_free(JobDependency *l);
b7e7184634d573fb73143210962acce205f37f61Michael Biebl
b7e7184634d573fb73143210962acce205f37f61Michael Bieblbool job_is_anchor(Job *j);
b7e7184634d573fb73143210962acce205f37f61Michael Biebl
b7e7184634d573fb73143210962acce205f37f61Michael Bieblint job_merge(Job *j, Job *other);
b7e7184634d573fb73143210962acce205f37f61Michael Biebl
b7e7184634d573fb73143210962acce205f37f61Michael BieblJobType job_type_lookup_merge(JobType a, JobType b);
b7e7184634d573fb73143210962acce205f37f61Michael Biebl
b7e7184634d573fb73143210962acce205f37f61Michael Bieblstatic inline int job_type_merge(JobType *a, JobType b) {
b7e7184634d573fb73143210962acce205f37f61Michael Biebl JobType t = job_type_lookup_merge(*a, b);
b7e7184634d573fb73143210962acce205f37f61Michael Biebl if (t < 0)
b7e7184634d573fb73143210962acce205f37f61Michael Biebl return -EEXIST;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen *a = t;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmekstatic inline bool job_type_is_mergeable(JobType a, JobType b) {
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek return job_type_lookup_merge(a, b) >= 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic inline bool job_type_is_conflicting(JobType a, JobType b) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return !job_type_is_mergeable(a, b);
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic inline bool job_type_is_superset(JobType a, JobType b) {
8fba1c8d4e3d05d2af2848b6570bdc09e725d06eZbigniew Jędrzejewski-Szmek /* Checks whether operation a is a "superset" of b in its actions */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return a == job_type_lookup_merge(a, b);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pittbool job_type_is_redundant(JobType a, UnitActiveState b);
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt
4e5589836c9e143796c3f3d81e67ab7a9209e2b0Martin Pittbool job_is_runnable(Job *j);
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt
9993ef2e9817b35b1d467707bef12b2a140b62dcLennart Poetteringvoid job_add_to_run_queue(Job *j);
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pittvoid job_add_to_dbus_queue(Job *j);
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint job_start_timer(Job *j);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidtvoid job_timer_event(Job *j, uint64_t n_elapsed, Watch *w);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint job_run_and_invalidate(Job *j);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint job_finish_and_invalidate(Job *j, JobResult result);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenchar *job_dbus_path(Job *j);
aad0a2c80097926757d4385e5f5492082d47f006Zbigniew Jędrzejewski-Szmek
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenconst char* job_type_to_string(JobType t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel AndersenJobType job_type_from_string(const char *s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenconst char* job_state_to_string(JobState t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel AndersenJobState job_state_from_string(const char *s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenconst char* job_mode_to_string(JobMode t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel AndersenJobMode job_mode_from_string(const char *s);
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersenconst char* job_result_to_string(JobResult t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel AndersenJobResult job_result_from_string(const char *s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#endif
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen