﻿<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="../scheduler.xsl" type="text/xsl"?>

<!--$Id: job.xml 5822 2008-07-07 10:28:53Z jz $-->

<xml_element name     = "job"
             title    = "Definition eines Jobs"
             category = "Konfiguration"
             base_dir = "../"
             parent_page = "../konfiguration.xml"
             author   = "$Author: jz $"
             date     = "$Date: 2008-07-07 12:28:53 +0200 (Mo, 07 Jul 2008) $">

    <xml_parent_elements>
        <xml_parent_element name="jobs">
        </xml_parent_element>
    </xml_parent_elements>

    <xml_attributes>
        <xml_attribute name="spooler_id" same_as_element="config"/>
<!--
            <description>
                <p>
                    Kennung des <span class="sos_name">Schedulers</span>,
                    für den der Job bestimmt ist. Der Job wird vom <span class="sos_name">Scheduler</span>
                    nur berücksichtigt, wenn dieses Attribut nicht leer ist und mit der Option
                    <scheduler_option name="spooler-id"/> vom <span class="sos_name">Scheduler</span>-Start übereinstimmt.
                </p>
            </description>
        </xml_attribute>
-->

        <xml_attribute name="name" type="jobname">
            <description>
                <p>
                    Jeder Job hat einen eigenen Namen.
                </p>
                <p>
                    Wenn ein Job mit demselben Namen in einer Basiskonfiguration bereit definiert worden ist,
                    können hier die Einstellungen des Jobs geändert oder ergänzt werden.
                </p>
            </description>
        </xml_attribute>

        <xml_attribute name="title" type="text">
            <description>
                Eine einzeilige Beschreibung des Jobs.
            </description>
        </xml_attribute>

        <xml_attribute name="order" type="yes_no" title="Auftragsgesteuerter Job">
            <description>
                <p>
                    Bei <code>order="yes"</code> ist der Job auftragsgesteuert. Der Scheduler startet diesen Job nur, wenn ein Auftrag vorliegt.
                </p>
                <p>
                    Ein Skript kann mit <scheduler_method class="Job" property="order_queue"/> das Attribut prüfen.
                </p>
            </description>
        </xml_attribute>

        <xml_attribute name="process_class" type="prozessklasse">
            <description>
                Gibt den Namen der Prozessklasse an, in der Tasks dieses Jobs laufen sollen.
                Die Prozessklassen werden mit <scheduler_element name="process_classes"/> definiert.
            </description>
        </xml_attribute>

        <xml_attribute name="tasks" type="zahl" initial="1" title="Maximale Anzahl Tasks">
            <description>
                <p>
                    Von einem Job können mehrere Tasks gleichzeitig laufen. Dieses Attribut begrenzt deren Anzahl.
                </p>
                <p>
                    <scheduler_element name="lock.use"/>: Zusammen mit einer exklusiven Sperre ist nur <code>tasks="1"</code> sinnvoll,
                    sie erlaubt nur eine Task.
                </p>
            </description>
        </xml_attribute>

        <xml_attribute name="min_tasks" type="zahl" initial="0" title="Mindeste Anzahl der stets laufenden Tasks">
            <description>
                <p>
                    Der Scheduler sorgt dafür, das wenigstens die angegebene Anzahl Tasks läuft.
                    So lassen sich auftragsgesteuerte Tasks in Bereitschaft bringen,
                    die sehr lange für ihre Initialisierung brauchen.
                </p>
                <p>
                    <scheduler_element name="job" attribute="tasks"/> muss groß genug sein.
                </p>
                <p>
                    Der Scheduler startet weitere Tasks, wenn
                </p>
                <ul>
                    <li>
                        der Scheduler startet
                    </li>
                    <li>
                        oder eine Task sich beendet hat
                    </li>
                    <li>
                        oder eine neue Periode (<scheduler_element name="run_time"/>) beginnt
                    </li>
                    <li>
                        oder bei <scheduler_element name="modify_job" attribute="cmd" value="unstop"/>: der Job wird entstoppt
                    </li>
                    <li>
                        oder bei <scheduler_element name="modify_job" attribute="cmd" value="continue"/>: alle Tasks des Jobs werden fortgesetzt
                    </li>
                    <li>
                        oder bei <scheduler_element name="modify_job" attribute="cmd" value="wake"/>: der Job wird geweckt
                    </li>
                </ul>
                <ul>
                    <li>
                        und weniger Tasks laufen als mit <code>min_tasks</code> verlangt
                    </li>
                    <li>
                        und die <scheduler_element name="run_time"/> mit einer Periode den Start zulässt
                    </li>
                    <li>
                        und der Job im Zustand <code>pending</code> oder <code>running</code> ist 
                        (also nicht gestoppt wird oder gestoppt ist).
                    </li>
                </ul>
                <p>
                    Um ein Heißlaufen zu verhindern, startet der Scheduler keine neuen Tasks,
                    nachdem sich eine sofort beendet hat.
                    Nur in folgenden Fällen führt das Ende einer Task zum Start einer neuen:
                </p>
                <ul>
                    <li>
                        <scheduler_method class="Job_impl" method="spooler_process"/> wurde aufgerufen.
                    </li>
                    <li>
                        Die Task wartete eine Zeitlang auf einen Auftrag 
                        (Zustand <code>running_waiting_for_order</code>, 
                        nicht wenn <scheduler_element name="job" attribute="idle_timeout" value="0"/>).
                    </li>
                    <li>
                        Die Task startete, wurde aber mit
                        <scheduler_method class="Task" property="delay_spooler_process"/> verzögert.
                        <!-- Diesen Fall gibt es nicht, weil delay_spooler_process nur im spooler_process() wirkt, also spooler_process() gerufen worden ist. Stand 25.5.2006 -->
                    </li>
                    <li>
                        Die Task ist ein Prozess 
                        (<scheduler_element name="process"/> oder 
                        <scheduler_element name="script" attribute="language" value="shell"/>)
                        und der Prozess hat sich nicht sofort nach Start beendet.
                    </li>
                </ul>
            </description>

            <messages>
                <message code="SCHEDULER-322" level="error"/>
                <message code="SCHEDULER-969" level="debug3"/>
                <message code="SCHEDULER-970" level="warn"/>
            </messages>

        </xml_attribute>

        <xml_attribute name="timeout" type="dauer" title="Frist für eine Operation">
            <description>
                <p>
                    Befristet eine Task-Operation (spooler_open, spooler_process etc.)
                    oder bei einer Nicht-API-Task 
                    (<scheduler_element name="process"/> oder <scheduler_element name="script" attribute="language" value="shell"/>)
                    die ganze Task.
                    Nach Ablauf der Frist bricht der Scheduler die Task ab.
                </p>
                <p>
                    <i>dauer</i> kann in Sekunden oder im Format <code>HH:MM</code> oder <code>HH:MM:SS</code> angegeben werden.
                </p>
            </description>
        </xml_attribute>

        <xml_attribute name="idle_timeout" type="dauer" initial="5" title="Frist für den Zustand waiting_for_order">
            <description>
                <p>
                    Begrenzt den Leerlauf eines auftragsgesteuerten Jobs (<code>order="yes"</code>).
                    Wenn eine Task auf den nächsten Auftrag wartet und in der Frist kein Auftrag
                    eintrifft, beendet der Scheduler sie.
                </p>
                <p>
                    <i>dauer</i> kann in Sekunden oder im Format <code>HH:MM</code> oder <code>HH:MM:SS</code> angegeben werden.
                </p>
                <p>
                    <code>idle_timeout="never"</code> lässt den Job unbegrenzt laufen, 
                    nur noch abhängig von <scheduler_element name="run_time"/>.
                </p>
                <p>
                    Siehe auch <scheduler_element name="job" attribute="force_idle_timeout"/>.
                </p>
            </description>
        </xml_attribute>


        <xml_attribute name="force_idle_timeout" type="yes_no" initial="no" title="idle_timeout beendet Task trotz min_task">
            <description>
                <p>
                    Nur wirksam mit <scheduler_element name="job" attribute="min_tasks" value="0" relation="≥"/>
                    und <scheduler_element name="job" attribute="idle_timeout"/>.
                </p>
                <p>
                    <code>force_idle_timeout="yes"</code> beendet nach Ablauf von 
                    <code>idle_timeout</code> die Task,
                    auch wenn daraufhin <code>min_tasks</code> unterschritten wird.
                    Erst anschließend führt <code>min_tasks</code> zum Start einer neuen Task.
                </p>
                <p>
                    Damit lassen sich Tasks beenden,
                    die im Leerlauf eine Ressource (z.B. eine Datenbank) nicht zu lange belegen dürfen,
                    weil diese sich sonst abkoppelt.
                </p>
            </description>
        </xml_attribute>


        <xml_attribute name="priority" type="process_priority">
            <description>
                <p>
                    Eingestellt können die Werte 
                    <code>idle</code>,
                    <code>below_normal</code>,
                    <code>normal</code>,
                    <code>above_normal</code> und
                    <code>high</code>
                    oder die numerischen Werte des Betriebsystems.
                </p>
                <p>
                    Wenn die Priorität nicht gesetzt werden kann, führt das nicht zu einem Fehler.
                </p>
                <p>
                    Ein Prozess mit hoher Priorität kann Ihren Rechner blockieren.
                </p>
                <p>
                    Siehe
                    <scheduler_method class="Task" property="priority_class"/>.
                </p>
            </description>
        </xml_attribute>


        <xml_attribute name="temporary" type="yes_no">
            <description>
                <p>
                    Bei <code>temporary="yes"</code> ist der Job temporär.
                    Nur für <scheduler_element name="add_jobs"/>.
                    Nach der Ausführung wird der Job gelöscht und ist dann unbekannt.
                </p>
            </description>
        </xml_attribute>


        <xml_attribute name="java_options" type="string">
            <description>
                <p>
                    Wirkt nur, wenn der Job als eigener Prozess ausgeführt wird 
                    (s. <scheduler_element name="process_classes"/>) und der Job oder der Monitor in Java implementiert ist.
                    Die Optionen werden zusammen mit den Optionen aus 
                    <scheduler_element name="config" attribute="java_options"/> Java übergeben.
                    Wie gleichnamige Optionen interpretiert werden, hängt von Java ab.
                </p>
            </description>
        </xml_attribute>


        <xml_attribute name="visible" type="yes|no|never" initial="yes">
            <description>
                <p>
                    <code>visible="no"</code> und <code>visible="never"</code> lassen den Job im Ergebnis von 
                    <scheduler_element name="show_jobs"/> und
                    <scheduler_element name="show_state"/> 
                    unsichtbar.
                </p>
                <p>
                    Bei <code>visible="no"</code> setzt der Scheduler den Job sichtbar, sobald eine Task eingereiht wird.
                    Bei <code>visible="never"</code> ist das nicht der Fall.
                </p>
            </description>
        </xml_attribute>

        
        <xml_attribute name="ignore_signals" type="all|signalnames" initial="no">
            <description>
                <p>
                    Wirksam nur unter Unix.
                </p>
                <p>
                    Ein Job, dessen Task-Prozess mit Signal abbricht, führt zum Stopp des Jobs.
                    Ursache eines Signals ist ein Abbruch der Task durch das System-Kommando <code>kill</code> oder
                    durch einen Programmabbruch.
                </p>
                <p>
                    Wenn <code>ignore_signals</code> nicht angegeben ist, 
                    stoppt eine mit Signal abbrechene Task den Job (mit Meldung <scheduler_message code="SCHEDULER-279"/>).
                </p>
                <p>
                    <code>ignore_signals="all"</code> lässt den Job nicht stoppen.
                </p>
                <p>
                    Statt <code>"all"</code> können Sie auch eine Liste von Signalnamen angeben (durch Leerzeichen getrennt).
                    Dabei sind, abhängig vom Betriebssystem, diese Signalnamen bekannt:
                    <code>SIGHUP</code>,
                    <code>SIGINT</code>,
                    <code>SIGQUIT</code>,
                    <code>SIGILL</code>,
                    <code>SIGTRAP</code>,
                    <code>SIGABRT</code>,
                    <code>SIGIOT</code>,
                    <code>SIGBUS</code>,
                    <code>SIGFPE</code>,
                    <code>SIGKILL</code>,
                    <code>SIGUSR1</code>,
                    <code>SIGSEGV</code>,
                    <code>SIGUSR2</code>,
                    <code>SIGPIPE</code>,
                    <code>SIGALRM</code>,
                    <code>SIGTERM</code>,
                    <code>SIGSTKFLT</code>,
                    <code>SIGCHLD</code>,
                    <code>SIGCONT</code>,
                    <code>SIGSTOP</code>,
                    <code>SIGTSTP</code>,
                    <code>SIGTTIN</code>,
                    <code>SIGTTOU</code>,
                    <code>SIGURG</code>,
                    <code>SIGXCPU</code>,
                    <code>SIGXFSZ</code>,
                    <code>SIGVTALRM</code>,
                    <code>SIGPROF</code>,
                    <code>SIGWINCH</code>,
                    <code>SIGPOLL</code>,
                    <code>SIGIO</code>,
                    <code>SIGPWR</code> und
                    <code>SIGSYS</code>.
                    Signal-Namen, die das Betriebsystem nicht kennt, werden mit Warnung ignoriert.
                </p>
                <p>
                    Weil eine mit einem zu ignorierenden Signal abbrechende Task 
                    trotzdem zuerst einen TCP-Verbindungsfehler (<code>ECONNRESET</code>) hervorruft,
                    führen TCP-Verbindungsfehler nur dann zum Stopp des Jobs, wenn
                    <code>ignore_signals="…"</code> nicht zutrifft.
                    Der Scheduler weist mit der Meldung <scheduler_message code="SCHEDULER-974"/> darauf hin.
                </p>
                <p>
                    Siehe auch <scheduler_element name="commands" attribute="on_exit_code" value="SIGTERM"/> 
                    und das Gnu-Kommando <code>man 7 signal</code>.
                </p>
            </description>

            <example>
                <pre>&lt;job name="my_job" ignore_signals="SIGTERM SIGKILL"></pre>
            </example>

            <messages>
                <message level="warn" code="SCHEDULER-279"/>
                <message level="warn" code="SCHEDULER-337"/>
                <message level="info" code="SCHEDULER-974"/>
            </messages>
        </xml_attribute>

        <xml_attribute name="stop_on_error" type="yes|no" initial="yes">
            <description>
                <p>
                    Die Voreinstellung <code>stop_on_error="yes"</code> stoppt den Job,
                    wenn eine Task mit Exception oder 
                    mit einer Fehlermeldung "<code>[ERROR]</code>" in ihrem Task-Protokoll endet.
                    Eine Fehlermeldung kann z.B. mit <scheduler_method class="Log" object="spooler_log" method="error"/> 
                    geschrieben werden.
                </p>
                <p>
                    <code>stop_on_error="no"</code> lässt den Job in diesen Fällen nicht stoppen.
                    Endet 
                    <scheduler_method class="Job_impl" method="spooler_process"/> mit Exception,
                    versetzt der Scheduler den Auftrag in den Fehlerzustand
                    (<scheduler_element name="job_chain_node" attribute="error_state"/>).
                </p>
                <p>
                    Die Einstellung hat keine Wirkung, wenn 
                    <scheduler_element name="delay_after_error"/> oder
                    <scheduler_method class="Job" property="delay_after_error"/> verwendet wird.
                </p>
            </description>
            
            <messages>
                <message level="debug3" code="SCHEDULER-977"/>
                <message level="debug3" code="SCHEDULER-978"/>
                <message level="warn"   code="SCHEDULER-846"/>
            </messages>
        </xml_attribute>

        <xml_attribute name="replace" type="yes|no" initial="yes">
            <description>
                <p>
                    <code>replace="yes"</code> lässt diese Job-Definition eine evtl. bereits vorhandene ersetzen.
                    Wenn das nicht möglich ist, weil z.B. gerade eine Task läuft,
                    dann ersetzt der Scheduler den Job später.
                </p>
                <p>
                    Ein auftragsgesteuerte Job (<scheduler_element name="job" attribute="order" value="yes"/>)
                    kann nicht ersetzt werden.
                </p>
            </description>

            <messages>
            <!--<message level="error" code="SCHEDULER-229"/>-->
            <!--<message level="info" code="SCHEDULER-988"/>-->
            </messages>
        </xml_attribute>

    </xml_attributes>

    <xml_child_elements>
        <xml_child_element name="description"/>
        <xml_child_element name="lock.use"                     multiple="yes"/>
        <xml_child_element name="environment"/>
        <xml_child_element name="params"/>
        <xml_child_element name="script"/>
        <xml_child_element name="process"/>
        <xml_child_element name="monitor"/>
        <xml_child_element name="start_when_directory_changed" multiple="yes"/>
        <xml_child_element name="delay_after_error"            multiple="yes"/>
        <xml_child_element name="delay_order_after_setback"    multiple="yes"/>
        <xml_child_element name="run_time"/>
        <xml_child_element name="commands"                     multiple="yes" title="Nach Ende der Task auszuführende Kommandos"/>
    </xml_child_elements>


    <behavior_with_xml_element element="base" complete_attribute="name"/>

    <description>
        <p>
            Definiert einen Job mit Programmcode, Laufzeit usw.
        </p>
    </description>


</xml_element>
