You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
471 lines
36 KiB
HTML
471 lines
36 KiB
HTML
2 years ago
|
<!DOCTYPE html>
|
||
|
|
||
|
<html >
|
||
|
<head>
|
||
|
<meta charset="utf-8" />
|
||
|
<title>seiscomp.client — SeisComP Release documentation</title>
|
||
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||
|
<link rel="stylesheet" href="../_static/seiscomp.css" type="text/css" />
|
||
|
<link rel="stylesheet" type="text/css" href="../_static/graphviz.css" />
|
||
|
<script type="text/javascript" src="../_static/seiscomp.js"></script>
|
||
|
<script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||
|
<script src="../_static/jquery.js"></script>
|
||
|
<script src="../_static/underscore.js"></script>
|
||
|
<script src="../_static/doctools.js"></script>
|
||
|
<script src="../_static/language_data.js"></script>
|
||
|
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||
|
<link rel="index" title="Index" href="../genindex.html" />
|
||
|
<link rel="search" title="Search" href="../search.html" />
|
||
|
<link rel="next" title="Examples" href="sdk-python-examples.html" />
|
||
|
<link rel="prev" title="seiscomp.datamodel" href="api-python.html" />
|
||
|
</head>
|
||
|
<body>
|
||
|
<div class="header">
|
||
|
<div class="container">
|
||
|
<div class="brand">
|
||
|
<img class="logo" src="../_static/brands/seiscomp/text/white.svg"/>
|
||
|
<!-- span class="title">SeisComP Release</span -->
|
||
|
<span class="version">5.3.0</span>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="nav">
|
||
|
<div class="container">
|
||
|
<div class="content"><a class="pull-right" id="sidebar-toggle">TOC</a>
|
||
|
|
||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||
|
<ul>
|
||
|
<li class="right">
|
||
|
<a href="../genindex.html" title="General Index"
|
||
|
accesskey="I">
|
||
|
index
|
||
|
</a>
|
||
|
</li>
|
||
|
<li class="right">
|
||
|
<a href="sdk-python-examples.html" title="Examples"
|
||
|
accesskey="N">
|
||
|
next
|
||
|
</a>
|
||
|
</li>
|
||
|
<li class="right">
|
||
|
<a href="api-python.html" title="seiscomp.datamodel"
|
||
|
accesskey="P">
|
||
|
previous
|
||
|
</a>
|
||
|
</li>
|
||
|
<li class="nav-item nav-item-0">
|
||
|
<a href="../index.html">Home</a>
|
||
|
</li>
|
||
|
<li class="nav-item nav-item-1">
|
||
|
<a href="sdk.html" >Software Development Kit</a>
|
||
|
</li>
|
||
|
<li class="nav-item nav-item-2">
|
||
|
<a href="sdk-python.html" >Python</a>
|
||
|
</li>
|
||
|
<li class="nav-item nav-item-3">
|
||
|
<a href="sdk-python-packages.html" accesskey="U">Packages</a>
|
||
|
</li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="container">
|
||
|
<div class="fitted content" id="anchors-container">
|
||
|
<div class="body" role="main">
|
||
|
|
||
|
<div class="section" id="module-seiscomp.client">
|
||
|
<span id="seiscomp-client"></span><span id="api-client-python"></span><h1>seiscomp.client<a class="headerlink" href="#module-seiscomp.client" title="Permalink to this headline">¶</a></h1>
|
||
|
<p>Modules are meant to be standalone programs doing a particular job. The
|
||
|
seiscomp.client package focuses on three main aspects:</p>
|
||
|
<ul class="simple">
|
||
|
<li><p>Communicate with other modules</p></li>
|
||
|
<li><p>Access station- and event metadata through a database</p></li>
|
||
|
<li><p>Fetch waveform data</p></li>
|
||
|
</ul>
|
||
|
<p>Therefore a client package has been developed combining these concepts in an
|
||
|
easy way with only a couple of API calls. Since <cite>SeisComP</cite> has been developed in
|
||
|
C++ and uses the object oriented paradigm forcefully, modules build on the
|
||
|
Application (C++: <code class="xref py py-class docutils literal notranslate"><span class="pre">Seiscomp::Client::Application</span></code>, Python:
|
||
|
<code class="xref py py-class docutils literal notranslate"><span class="pre">seiscomp.client.Application</span></code>) class. It manages the messaging connection
|
||
|
and waveform sources in a transparent way.</p>
|
||
|
<p>The class <code class="xref py py-class docutils literal notranslate"><span class="pre">Seiscomp::Client::Application</span></code> is the base class for
|
||
|
all <cite>SeisComP</cite> applications. It manages messaging and database
|
||
|
connections, provides access to command line options and configuration
|
||
|
parameters and also handles and interprets notifier messages.</p>
|
||
|
<p>Blocking network operations like reading messages are moved into threads that
|
||
|
are synchronized in a single blocking message queue. This queue allows pushing
|
||
|
elements from different threads and unblocks when a new element is ready to be
|
||
|
popped. If the queue is full (currently 10 elements are allowed) the pushing
|
||
|
threads also block until an element can be pushed again.</p>
|
||
|
<p>This way applications do not have to poll and thus do not burn CPU cycles.</p>
|
||
|
<p>The application class is event driven. It runs the event loop which pops the
|
||
|
message queue and dispatches events with their handlers. Handler methods are
|
||
|
prefixed with <em>handle</em>, e.g. <code class="xref py py-func docutils literal notranslate"><span class="pre">handleMessage()</span></code>.</p>
|
||
|
<div class="admonition note">
|
||
|
<p class="admonition-title">Note</p>
|
||
|
<p>When overriding handlers it is always good practise to call the base
|
||
|
handlers before running custom code.</p>
|
||
|
</div>
|
||
|
<div class="section" id="application-class">
|
||
|
<h2>Application class<a class="headerlink" href="#application-class" title="Permalink to this headline">¶</a></h2>
|
||
|
<p>The application class is part of the seiscomp.client package. It needs to
|
||
|
be imported first.</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">seiscomp.client</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>A common strategy to write a module with that class is to derive from it and
|
||
|
run it in a Python main method.</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
|
||
|
<span class="kn">import</span> <span class="nn">seiscomp.client</span>
|
||
|
|
||
|
<span class="c1"># Class definition</span>
|
||
|
<span class="k">class</span> <span class="nc">MyApp</span><span class="p">(</span><span class="n">seiscomp</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">Application</span><span class="p">):</span>
|
||
|
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">):</span>
|
||
|
<span class="n">seiscomp</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">Application</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">)</span>
|
||
|
|
||
|
<span class="c1"># Main method to call the app</span>
|
||
|
<span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">):</span>
|
||
|
<span class="n">app</span> <span class="o">=</span> <span class="n">MyApp</span><span class="p">(</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">)</span>
|
||
|
<span class="k">return</span> <span class="n">app</span><span class="p">()</span>
|
||
|
|
||
|
<span class="c1"># Call the main method if run as script</span>
|
||
|
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</span><span class="p">:</span>
|
||
|
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="n">main</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">),</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">))</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>An application can be called with the parenthesis operator <code class="xref py py-func docutils literal notranslate"><span class="pre">()</span></code> which
|
||
|
returns the applications result code and serves as input to <code class="xref py py-func docutils literal notranslate"><span class="pre">sys.exit()</span></code>.
|
||
|
Operator() is a wrapper for <code class="xref py py-func docutils literal notranslate"><span class="pre">Application.exec()</span></code>.</p>
|
||
|
<p>The workflow of <code class="xref py py-func docutils literal notranslate"><span class="pre">Application.exec()</span></code> looks as follows:</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">exec</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
|
<span class="bp">self</span><span class="o">.</span><span class="n">returnCode</span> <span class="o">=</span> <span class="mi">1</span>
|
||
|
|
||
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">init</span><span class="p">()</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">run</span><span class="p">():</span>
|
||
|
<span class="bp">self</span><span class="o">.</span><span class="n">returnCode</span> <span class="o">=</span> <span class="mi">0</span>
|
||
|
|
||
|
<span class="bp">self</span><span class="o">.</span><span class="n">done</span><span class="p">()</span>
|
||
|
|
||
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">returnCode</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p><code class="xref py py-func docutils literal notranslate"><span class="pre">init()</span></code>, <code class="xref py py-func docutils literal notranslate"><span class="pre">run()</span></code> and <code class="xref py py-func docutils literal notranslate"><span class="pre">done()</span></code> are explained in more detail in
|
||
|
the next sections.</p>
|
||
|
<div class="section" id="constructor">
|
||
|
<h3>Constructor<a class="headerlink" href="#constructor" title="Permalink to this headline">¶</a></h3>
|
||
|
<p>To create an application, derive from the seiscomp.client.Application class
|
||
|
and configure it in the constructor.</p>
|
||
|
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
|
2
|
||
|
3
|
||
|
4
|
||
|
5
|
||
|
6
|
||
|
7
|
||
|
8
|
||
|
9
|
||
|
10
|
||
|
11</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyApp</span><span class="p">(</span><span class="n">seiscomp</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">Application</span><span class="p">):</span>
|
||
|
<span class="c1"># MyApp constructor</span>
|
||
|
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">):</span>
|
||
|
<span class="c1"># IMPORTANT: call the base class constructor</span>
|
||
|
<span class="n">seiscomp</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">Application</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">)</span>
|
||
|
<span class="c1"># Default is TRUE</span>
|
||
|
<span class="hll"> <span class="bp">self</span><span class="o">.</span><span class="n">setMessagingEnabled</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
|
||
|
</span> <span class="c1"># Default is TRUE, TRUE</span>
|
||
|
<span class="hll"> <span class="bp">self</span><span class="o">.</span><span class="n">setDatabaseEnabled</span><span class="p">(</span><span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">)</span>
|
||
|
</span> <span class="c1"># Default is TRUE</span>
|
||
|
<span class="hll"> <span class="bp">self</span><span class="o">.</span><span class="n">setDaemonEnabled</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
|
||
|
</span></pre></div>
|
||
|
</td></tr></table></div>
|
||
|
<p>As marked in line 4, the call of the constructor of the base class is very
|
||
|
important. It takes the command line parameters and sets up internal
|
||
|
application variables. Without this call the application will either not run
|
||
|
at all or show undefined/unexpected behaviour.</p>
|
||
|
<p>The constructor takes also the initial parameters of the application such as
|
||
|
enabling a messaging connection and enabling database access.</p>
|
||
|
<p>Messaging, database and daemon mode is enabled by default. The daemon mode is
|
||
|
important if the application should be started as service and therefore should
|
||
|
support the option <code class="docutils literal notranslate"><span class="pre">-D,</span> <span class="pre">--daemon</span></code>. Utilities and non daemon applications
|
||
|
should disable that mode.</p>
|
||
|
<p>Example calls to this options are shown in the highlighted lines of the above
|
||
|
code block.</p>
|
||
|
<p>If messaging is enabled, the messaging username is derived from the binary
|
||
|
called (<em>not the class name</em>). If the script is called test.py then the username
|
||
|
selected is <strong>test</strong>. The username can be overridden either in the configuration
|
||
|
file (<a class="reference internal" href="../apps/global.html#global"><span class="std std-ref">Global parameters</span></a>) or using the API.</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="bp">self</span><span class="o">.</span><span class="n">setMessagingUsername</span><span class="p">(</span><span class="s2">"test"</span><span class="p">)</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>Setting the username to an empty string results in a random username selected
|
||
|
by the messaging server.</p>
|
||
|
<p>All application methods are defined in the C++ header file
|
||
|
<code class="file docutils literal notranslate"><span class="pre">src/trunk/libs/seiscomp/client/application.h</span></code>.</p>
|
||
|
</div>
|
||
|
<div class="section" id="init">
|
||
|
<h3>Init<a class="headerlink" href="#init" title="Permalink to this headline">¶</a></h3>
|
||
|
<p>The workflow of the init function looks like this:</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">init</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">initConfiguration</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">initCommandLine</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">createCommandLineDescription</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">parseCommandLine</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">printUsage</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">validateParameters</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">loadPlugins</span>
|
||
|
<span class="n">forkDaemon</span>
|
||
|
<span class="n">initMessaging</span>
|
||
|
<span class="n">initDatabase</span>
|
||
|
<span class="n">loadInventory</span> <span class="ow">or</span> <span class="n">loadStations</span>
|
||
|
<span class="n">loadDBConfigModule</span>
|
||
|
<span class="n">loadCities</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>Methods marked with virtual can be overridden. <code class="xref py py-func docutils literal notranslate"><span class="pre">init()</span></code> itself calls
|
||
|
a lot of handlers that can be customized. Typical handlers are
|
||
|
<code class="xref py py-func docutils literal notranslate"><span class="pre">initConfiguration()</span></code>, <code class="xref py py-func docutils literal notranslate"><span class="pre">createCommandLineDescription()</span></code>
|
||
|
and <code class="xref py py-func docutils literal notranslate"><span class="pre">validateParameters()</span></code>.</p>
|
||
|
<p><code class="xref py py-func docutils literal notranslate"><span class="pre">initConfiguration()</span></code> is used to read parameters of the configuration files
|
||
|
and to populate the internal state. If something fails or if configured values
|
||
|
are out of bounds, False can be returned which causes <code class="xref py py-func docutils literal notranslate"><span class="pre">init()</span></code> to return
|
||
|
False and to exit the application with a non-zero result code.</p>
|
||
|
<p>An example is show below:</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">initConfiguration</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">seiscomp</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">Application</span><span class="o">.</span><span class="n">initConfiguration</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
|
<span class="k">return</span> <span class="bp">False</span>
|
||
|
|
||
|
<span class="k">try</span><span class="p">:</span>
|
||
|
<span class="bp">self</span><span class="o">.</span><span class="n">_directory</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">configGetString</span><span class="p">(</span><span class="s2">"directory"</span><span class="p">)</span>
|
||
|
<span class="k">except</span><span class="p">:</span>
|
||
|
<span class="k">pass</span>
|
||
|
|
||
|
<span class="k">return</span> <span class="bp">True</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>This method reads the directory parameter from the configuration file(s) and
|
||
|
sets it internally. If the directory is not given in any of the modules
|
||
|
configuration files, it logs an error and aborts the application by returning
|
||
|
False.</p>
|
||
|
<p><code class="xref py py-func docutils literal notranslate"><span class="pre">createCommandLineDescription()</span></code> is used to add custom command line options.
|
||
|
This is a void function and does not return any value. It is also not necessary
|
||
|
to call the base class method although it does not hurt.</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">createCommandLineDescription</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
|
<span class="bp">self</span><span class="o">.</span><span class="n">commandline</span><span class="p">()</span><span class="o">.</span><span class="n">addGroup</span><span class="p">(</span><span class="s2">"Storage"</span><span class="p">)</span>
|
||
|
<span class="bp">self</span><span class="o">.</span><span class="n">commandline</span><span class="p">()</span><span class="o">.</span><span class="n">addStringOption</span><span class="p">(</span><span class="s2">"Storage"</span><span class="p">,</span> <span class="s2">"directory,o"</span><span class="p">,</span> <span class="s2">"Specify the storage directory"</span><span class="p">)</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>A new command line option group is added with <code class="xref py py-func docutils literal notranslate"><span class="pre">addGroup()</span></code> and then a new
|
||
|
option is added to this group which is a string option.
|
||
|
Four types can be added
|
||
|
as options: string, int, double and bool: <code class="xref py py-func docutils literal notranslate"><span class="pre">addStringOption()</span></code>, <code class="xref py py-func docutils literal notranslate"><span class="pre">addIntOption()</span></code>,
|
||
|
<code class="xref py py-func docutils literal notranslate"><span class="pre">addDoubleOption()</span></code> and <code class="xref py py-func docutils literal notranslate"><span class="pre">addBoolOption()</span></code>.</p>
|
||
|
<p><code class="xref py py-func docutils literal notranslate"><span class="pre">validateParameters()</span></code> can be used to fetch the values of previously added
|
||
|
command line options and to validate each parameter. If False is returned, the
|
||
|
application is aborted with a non-zero result code.</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">validateParameters</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
|
<span class="k">try</span><span class="p">:</span>
|
||
|
<span class="bp">self</span><span class="o">.</span><span class="n">_directory</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">commandline</span><span class="p">()</span><span class="o">.</span><span class="n">optionString</span><span class="p">(</span><span class="s2">"directory"</span><span class="p">)</span>
|
||
|
<span class="k">except</span><span class="p">:</span>
|
||
|
<span class="k">pass</span>
|
||
|
|
||
|
<span class="c1"># The directory validity is checked to avoid duplicate checks in</span>
|
||
|
<span class="c1"># initConfiguration.</span>
|
||
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_directory</span><span class="p">:</span>
|
||
|
<span class="n">seiscomp</span><span class="o">.</span><span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">"directory not set"</span><span class="p">)</span>
|
||
|
<span class="k">return</span> <span class="bp">False</span>
|
||
|
|
||
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">exists</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_directory</span><span class="p">):</span>
|
||
|
<span class="n">seiscomp</span><span class="o">.</span><span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
|
||
|
<span class="s2">"directory {} does not exist"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_directory</span><span class="p">))</span>
|
||
|
<span class="k">return</span> <span class="bp">False</span>
|
||
|
|
||
|
<span class="k">return</span> <span class="bp">True</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>Custom initialization code after checking all parameters can be placed in the
|
||
|
overridden method <code class="xref py py-func docutils literal notranslate"><span class="pre">init()</span></code>.</p>
|
||
|
<p>But be aware that the process forked already if started as daemon. To run before
|
||
|
the fork, it needs to be put into <code class="xref py py-func docutils literal notranslate"><span class="pre">validateParameters()</span></code>.</p>
|
||
|
</div>
|
||
|
<div class="section" id="run">
|
||
|
<h3>Run<a class="headerlink" href="#run" title="Permalink to this headline">¶</a></h3>
|
||
|
<p>The workflow of the run method looks like this:</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">run</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">startMessageThread</span>
|
||
|
<span class="n">messageLoop</span>
|
||
|
<span class="n">readMessage</span>
|
||
|
<span class="n">dispatchMessage</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">handleMessage</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">addObject</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">updateObject</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">removeObject</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">handleReconnect</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">handleDisconnect</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">handleTimeout</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">handleAutoShutdown</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>The run method starts the event loop and waits for new events in the queue.
|
||
|
In case of messaging a thread is started that sits and waits for messages
|
||
|
and feeds them to the queue and to the event loop in <code class="xref py py-func docutils literal notranslate"><span class="pre">run()</span></code>. Without
|
||
|
messaging the run loop would do nothing but waiting for SIGTERM or
|
||
|
a timer event enabled with <code class="xref py py-func docutils literal notranslate"><span class="pre">enableTimer()</span></code>. If the event loop is not needed
|
||
|
because no timer and messages are needed, it should be overridden and the
|
||
|
code should be placed there. This will disable the event loop.</p>
|
||
|
<p><code class="xref py py-func docutils literal notranslate"><span class="pre">run()</span></code> is expected to return True on success and False otherwise. If False
|
||
|
is returned the application exists with a non-zero return code. Custom return
|
||
|
codes can always be set with <code class="xref py py-func docutils literal notranslate"><span class="pre">Application.exit()</span></code>.</p>
|
||
|
<p>If the scmaster sends a message to the client it is received in the applications
|
||
|
message thread and pushed to the queue. The event loop pops the message from
|
||
|
the queue and calls <code class="xref py py-func docutils literal notranslate"><span class="pre">handleMessage()</span></code>. The default implementation uses two
|
||
|
settings when handling a messages that can be controlled with
|
||
|
<code class="xref py py-func docutils literal notranslate"><span class="pre">enableInterpretNotifier()</span></code> and <code class="xref py py-func docutils literal notranslate"><span class="pre">enableAutoApplyNotifier()</span></code>.</p>
|
||
|
<p><code class="xref py py-func docutils literal notranslate"><span class="pre">enableInterpretNotifier()</span></code> controls whether the Application queries the
|
||
|
message type and extracts notifier objects. For each notifier it parses the
|
||
|
operation and dispatches the parentID and the object either to
|
||
|
<code class="xref py py-func docutils literal notranslate"><span class="pre">addObject()</span></code>, <code class="xref py py-func docutils literal notranslate"><span class="pre">updateObject()</span></code> or <code class="xref py py-func docutils literal notranslate"><span class="pre">removeObject()</span></code> handler. This
|
||
|
behaviour is enabled by default. If disabled, a clients needs to parse the
|
||
|
messages by itself and implement this method.</p>
|
||
|
<p><code class="xref py py-func docutils literal notranslate"><span class="pre">enableAutoApplyNotifier()</span></code> controls whether incoming notifier objects are
|
||
|
applied automatically to objects in local memory. If the client has already
|
||
|
an object in memory and an update notifier for this object is received, the object
|
||
|
in the notifier is copied to the local object. This behaviour is enabled by default.</p>
|
||
|
</div>
|
||
|
<div class="section" id="done">
|
||
|
<h3>Done<a class="headerlink" href="#done" title="Permalink to this headline">¶</a></h3>
|
||
|
<p>The workflow of the done method looks like this:</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">done</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">closeTimer</span>
|
||
|
<span class="n">closeMessaging</span>
|
||
|
<span class="n">closeDatabase</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p><code class="xref py py-func docutils literal notranslate"><span class="pre">done()</span></code> is usually not overridden. If custom code and clean up procedures
|
||
|
need to be placed in <code class="xref py py-func docutils literal notranslate"><span class="pre">done()</span></code>, the base class <strong>must</strong> be called. <code class="xref py py-func docutils literal notranslate"><span class="pre">done()</span></code> is a
|
||
|
void function.</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">done</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
|
<span class="n">seiscomp</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">Application</span><span class="o">.</span><span class="n">done</span><span class="p">()</span>
|
||
|
|
||
|
<span class="c1"># Custom clean ups</span>
|
||
|
<span class="n">closeMyDataFiles</span><span class="p">()</span>
|
||
|
<span class="n">closeCustomConnections</span><span class="p">()</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="section" id="streamapplication-class">
|
||
|
<h2>StreamApplication class<a class="headerlink" href="#streamapplication-class" title="Permalink to this headline">¶</a></h2>
|
||
|
<p>The application class has another occurrence: <code class="xref py py-class docutils literal notranslate"><span class="pre">seiscomp.client.StreamApplication</span></code>.</p>
|
||
|
<p>The class <code class="xref py py-class docutils literal notranslate"><span class="pre">StreamApplication</span></code> extends the <code class="xref py py-class docutils literal notranslate"><span class="pre">Application</span></code>
|
||
|
in terms of record acquisition. It spawns another thread that reads the records
|
||
|
from a configurable source and adds a new handler method
|
||
|
<code class="xref py py-func docutils literal notranslate"><span class="pre">StreamApplication.handleRecord()</span></code> to handle these records.</p>
|
||
|
<p>Its workflow looks like this:</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">init</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="o">+</span><span class="n">initRecordStream</span>
|
||
|
<span class="n">run</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="o">+</span><span class="n">startAcquisitionThread</span>
|
||
|
<span class="o">+</span><span class="n">storeRecord</span>
|
||
|
<span class="n">Application</span><span class="o">.</span><span class="n">messageLoop</span>
|
||
|
<span class="n">dispatchMessage</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="o">+</span><span class="n">handleRecord</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="n">done</span> <span class="p">(</span><span class="n">virtual</span><span class="p">)</span>
|
||
|
<span class="o">+</span><span class="n">closeRecordStream</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>Received records can be handled with <code class="xref py py-func docutils literal notranslate"><span class="pre">handleRecord()</span></code>.</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">handleRecord</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rec</span><span class="p">):</span>
|
||
|
<span class="k">print</span> <span class="n">rec</span><span class="o">.</span><span class="n">streamID</span><span class="p">()</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>The stream subscription should be done in <code class="xref py py-func docutils literal notranslate"><span class="pre">init()</span></code>. <code class="xref py py-func docutils literal notranslate"><span class="pre">recordStream()</span></code>
|
||
|
returns the RecordStream instance which can be used to add stream requests.</p>
|
||
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">init</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">seiscomp</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">StreamApplication</span><span class="o">.</span><span class="n">init</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
|
<span class="k">return</span> <span class="bp">False</span>
|
||
|
|
||
|
<span class="c1"># Subscribe to some streams</span>
|
||
|
<span class="bp">self</span><span class="o">.</span><span class="n">recordStream</span><span class="p">()</span><span class="o">.</span><span class="n">addStream</span><span class="p">(</span><span class="s2">"GE"</span><span class="p">,</span> <span class="s2">"MORC"</span><span class="p">,</span> <span class="s2">""</span><span class="p">,</span> <span class="s2">"BHZ"</span><span class="p">)</span>
|
||
|
<span class="k">return</span> <span class="bp">True</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>The record stream service is configured either with configuration files
|
||
|
(<a class="reference internal" href="../apps/global.html#confval-recordstream"><code class="xref std std-confval docutils literal notranslate"><span class="pre">recordstream</span></code></a>) or
|
||
|
via command-line options <code class="docutils literal notranslate"><span class="pre">-I`,</span> <span class="pre">``--record-url</span></code>.</p>
|
||
|
<p>The application finishes if the record stream read EOF. Running a <code class="xref py py-class docutils literal notranslate"><span class="pre">StreamApplication</span></code>
|
||
|
with <a class="reference internal" href="../apps/seedlink.html#seedlink"><span class="std std-ref">Seedlink</span></a> would probably never terminate since it is a
|
||
|
real time connection and handles reconnects automatically.</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
<div id="anchors-bottom"></div>
|
||
|
</div>
|
||
|
|
||
|
<div class="sidebar" role="navigation" aria-label="main navigation">
|
||
|
<div id="anchors-top"></div>
|
||
|
<div id="anchors" class="content">
|
||
|
<div id="searchbox" style="display: none" role="search">
|
||
|
<h3 id="searchlabel">Quick search</h3>
|
||
|
<div class="searchformwrapper">
|
||
|
<form class="search" action="../search.html" method="get">
|
||
|
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||
|
<input type="submit" value="Go" />
|
||
|
</form>
|
||
|
</div>
|
||
|
</div>
|
||
|
<script>$('#searchbox').show(0);</script>
|
||
|
<h3><a href="../index.html">Table of Contents</a></h3>
|
||
|
<ul>
|
||
|
<li><a class="reference internal" href="#">seiscomp.client</a><ul>
|
||
|
<li><a class="reference internal" href="#application-class">Application class</a><ul>
|
||
|
<li><a class="reference internal" href="#constructor">Constructor</a></li>
|
||
|
<li><a class="reference internal" href="#init">Init</a></li>
|
||
|
<li><a class="reference internal" href="#run">Run</a></li>
|
||
|
<li><a class="reference internal" href="#done">Done</a></li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
<li><a class="reference internal" href="#streamapplication-class">StreamApplication class</a></li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
</ul>
|
||
|
|
||
|
<h4>Previous topic</h4>
|
||
|
<p class="topless"><a href="api-python.html"
|
||
|
title="previous chapter">seiscomp.datamodel</a></p>
|
||
|
<h4>Next topic</h4>
|
||
|
<p class="topless"><a href="sdk-python-examples.html"
|
||
|
title="next chapter">Examples</a></p>
|
||
|
<div role="note" aria-label="source link">
|
||
|
<h3>This Page</h3>
|
||
|
<ul class="this-page-menu">
|
||
|
<li><a href="../_sources/base/api-python-client.rst.txt"
|
||
|
rel="nofollow">Show Source</a></li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="footer">
|
||
|
<div class="container">
|
||
|
<div class="horizontal layout content">
|
||
|
<a class="fade-in" href="https://www.gempa.de" target="_blank">
|
||
|
<img class="brand" src="../_static/brands/gempa.svg"/>
|
||
|
</a>
|
||
|
<div class="stretched align-center fitted content">
|
||
|
<div>
|
||
|
Version <b>5.3.0</b> Release
|
||
|
</div>
|
||
|
<div class="copyright">
|
||
|
Copyright © gempa GmbH, GFZ Potsdam.
|
||
|
</div>
|
||
|
</div>
|
||
|
<a class="fade-in" href="https://www.gfz-potsdam.de" target="_blank">
|
||
|
<img class="brand" src="../_static/brands/gfz.svg"/>
|
||
|
</a>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</body>
|
||
|
</html>
|