[seiscomp, scanloc] Install, add .gitignore
This commit is contained in:
780
include/seiscomp/client/application.h
Normal file
780
include/seiscomp/client/application.h
Normal file
@ -0,0 +1,780 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SEISCOMP_CLIENT_APPLICATION_H
|
||||
#define SEISCOMP_CLIENT_APPLICATION_H
|
||||
|
||||
|
||||
#include <seiscomp/system/application.h>
|
||||
|
||||
#include <seiscomp/core/message.h>
|
||||
|
||||
#include <seiscomp/client/queue.h>
|
||||
#include <seiscomp/client/monitor.h>
|
||||
#include <seiscomp/client/inventory.h>
|
||||
#include <seiscomp/client.h>
|
||||
|
||||
#include <seiscomp/datamodel/databasequery.h>
|
||||
#include <seiscomp/datamodel/notifier.h>
|
||||
#include <seiscomp/datamodel/configmodule.h>
|
||||
|
||||
#include <seiscomp/math/coord.h>
|
||||
|
||||
#include <seiscomp/messaging/connection.h>
|
||||
|
||||
#include <seiscomp/utils/timer.h>
|
||||
#include <seiscomp/utils/stringfirewall.h>
|
||||
|
||||
#include <set>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
|
||||
#define SCCoreApp (Seiscomp::Client::Application::Instance())
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
|
||||
namespace Logging {
|
||||
class Output;
|
||||
}
|
||||
|
||||
namespace Client {
|
||||
|
||||
|
||||
MAKEENUM(
|
||||
ApplicationStatus,
|
||||
EVALUES(
|
||||
STARTED,
|
||||
FINISHED
|
||||
),
|
||||
ENAMES(
|
||||
"started",
|
||||
"finished"
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
class SC_SYSTEM_CLIENT_API ApplicationStatusMessage : public Core::Message {
|
||||
DECLARE_SC_CLASS(ApplicationStatusMessage);
|
||||
DECLARE_SERIALIZATION;
|
||||
|
||||
public:
|
||||
ApplicationStatusMessage();
|
||||
ApplicationStatusMessage(const std::string &module,
|
||||
ApplicationStatus status);
|
||||
|
||||
ApplicationStatusMessage(const std::string &module,
|
||||
const std::string &username,
|
||||
ApplicationStatus status);
|
||||
|
||||
|
||||
public:
|
||||
virtual bool empty() const;
|
||||
|
||||
const std::string &module() const;
|
||||
const std::string &username() const;
|
||||
ApplicationStatus status() const;
|
||||
|
||||
|
||||
private:
|
||||
std::string _module;
|
||||
std::string _username;
|
||||
ApplicationStatus _status;
|
||||
};
|
||||
|
||||
|
||||
struct SC_SYSTEM_CLIENT_API Notification {
|
||||
//! Declares the application internal notification types.
|
||||
//! Custom types can be used with negative values.
|
||||
enum Type {
|
||||
Object,
|
||||
Disconnect,
|
||||
Reconnect,
|
||||
Close,
|
||||
Timeout,
|
||||
AcquisitionFinished,
|
||||
StateOfHealth
|
||||
};
|
||||
|
||||
Notification() : object(nullptr), type(Object) {}
|
||||
Notification(Core::BaseObject * o) : object(o), type(Object) {}
|
||||
Notification(int t) : object(nullptr), type(t) {}
|
||||
Notification(int t, Core::BaseObject * o) : object(o), type(t) {}
|
||||
|
||||
Core::BaseObject *object;
|
||||
int type;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Application class to write commandline clients easily which are
|
||||
* connected to the messaging and need database access.
|
||||
*
|
||||
* In addition to @ref System::Application it adds the method
|
||||
* @ref handleMessage which must be implemented to handle receives
|
||||
* messages. An additional abstraction layer is implemented which already
|
||||
* checks the message for notifier objects, extracts them and calls respective
|
||||
* callbacks:
|
||||
* * @ref addObject()
|
||||
* * @ref removeObject()
|
||||
* * @ref updateObject()
|
||||
*/
|
||||
class SC_SYSTEM_CLIENT_API Application : public System::Application {
|
||||
// ----------------------------------------------------------------------
|
||||
// Public types
|
||||
// ----------------------------------------------------------------------
|
||||
public:
|
||||
typedef ObjectMonitor::Log ObjectLog;
|
||||
|
||||
//! Initialization stages used when reporting errors
|
||||
enum ClientStage {
|
||||
MESSAGING = System::Application::ST_QUANTITY,
|
||||
DATABASE = System::Application::ST_QUANTITY + 1,
|
||||
CONFIGMODULE = System::Application::ST_QUANTITY + 2,
|
||||
INVENTORY = System::Application::ST_QUANTITY + 3,
|
||||
CST_QUANTITY
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// X'truction
|
||||
// ----------------------------------------------------------------------
|
||||
public:
|
||||
Application(int argc, char **argv);
|
||||
~Application();
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Public functions
|
||||
// ----------------------------------------------------------------------
|
||||
public:
|
||||
//! Returns the configured agencyID
|
||||
const std::string &agencyID() const;
|
||||
|
||||
//! Returns the configured author
|
||||
const std::string &author() const;
|
||||
|
||||
/**
|
||||
* Returns according to the configured white- and blacklist of
|
||||
* agencyID's whether the passed agencyID is allowed or not
|
||||
* @param agencyID The agencyID to check
|
||||
* @return The boolean result
|
||||
*/
|
||||
bool isAgencyIDAllowed(const std::string &agencyID) const;
|
||||
|
||||
/**
|
||||
* Returns !isAgencyIDAllowed(agencyID)
|
||||
* @param agencyID The agencyID to check
|
||||
* @return !isAgencyIDAllowed(agencyID)
|
||||
*/
|
||||
bool isAgencyIDBlocked(const std::string &agencyID) const;
|
||||
|
||||
/**
|
||||
* Exit the application and set the returnCode.
|
||||
* @param returnCode The value returned from exec()
|
||||
*/
|
||||
virtual void exit(int returnCode);
|
||||
|
||||
//! Returns the application's messaging connection interface
|
||||
Client::Connection *connection() const;
|
||||
|
||||
//! Returns the configured database type
|
||||
const std::string &databaseType() const;
|
||||
|
||||
//! Returns the configured database connection parameters
|
||||
const std::string &databaseParameters() const;
|
||||
|
||||
//! Returns the application's database interface
|
||||
IO::DatabaseInterface *database() const;
|
||||
|
||||
void setDatabaseURI(const std::string &uri);
|
||||
//! Returns the application's database URI
|
||||
const std::string &databaseURI() const;
|
||||
|
||||
//! Returns the application's database query interface
|
||||
DataModel::DatabaseQuery *query() const;
|
||||
|
||||
void setRecordStreamURL(const std::string &url);
|
||||
//! Returns the configures recordstream URL to be used by
|
||||
//! RecordStream::Open()
|
||||
const std::string &recordStreamURL() const;
|
||||
|
||||
//! Returns the list of configured points of interest
|
||||
const std::vector<Math::Geo::CityD> &cities() const;
|
||||
|
||||
//! Returns the nearest city with respect to lat/lon and
|
||||
//! a given maximum distance and minimum population
|
||||
const Math::Geo::CityD *nearestCity(double lat, double lon,
|
||||
double maxDist, double minPopulation,
|
||||
double *dist, double *azi) const;
|
||||
|
||||
//! Returns the config module object if available
|
||||
DataModel::ConfigModule *configModule() const;
|
||||
|
||||
//! Returns the state of a station
|
||||
bool isStationEnabled(const std::string& networkCode,
|
||||
const std::string& stationCode);
|
||||
|
||||
//! Returns the messaging-server
|
||||
const std::string &messagingURL() const;
|
||||
|
||||
|
||||
//! Returns the filename of the OpenSSL certificate or
|
||||
//! the certificate data Base64 encoded. The Base64 encoded
|
||||
//! data starts with the special DataTag.
|
||||
//! If no certificate is used the method returns an empty
|
||||
//! string.
|
||||
const std::string &messagingCertificate() const;
|
||||
|
||||
//! Enables a timer that calls every n seconds the
|
||||
//! handleTimeout() methods
|
||||
//! A value of 0 seconds disables the timer
|
||||
void enableTimer(unsigned int seconds);
|
||||
|
||||
//! Disables the timer
|
||||
void disableTimer();
|
||||
|
||||
//! Sends a notification to the application. If used in derived
|
||||
//! classes to send custom notifications use negative notification
|
||||
//! types and reimplement dispatchNotification(...).
|
||||
void sendNotification(const Notification &);
|
||||
|
||||
bool waitEvent();
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Initialization configuration methods
|
||||
// These methods have to be called before the init() method.
|
||||
// ----------------------------------------------------------------------
|
||||
public:
|
||||
//! Sets the primary messaging group
|
||||
void setPrimaryMessagingGroup(const std::string&);
|
||||
|
||||
//! Returns the set primary messaging group
|
||||
const std::string &primaryMessagingGroup() const;
|
||||
|
||||
//! Sets the username used for the messaging connection
|
||||
void setMessagingUsername(const std::string&);
|
||||
|
||||
/**
|
||||
* Adds a group to subscribe to. This is only a default group.
|
||||
* If another group or groups are given via commandline or config
|
||||
* file this subscription will be overriden completely.
|
||||
*/
|
||||
void addMessagingSubscription(const std::string&);
|
||||
|
||||
//! Initialize the database, default = true, true
|
||||
void setDatabaseEnabled(bool enable, bool tryToFetch);
|
||||
bool isDatabaseEnabled() const;
|
||||
|
||||
//! Returns whether the inventory should be loaded from a
|
||||
//! file (false) or from the database (true)
|
||||
bool isInventoryDatabaseEnabled() const;
|
||||
|
||||
//! Returns whether the config module should be loaded from a
|
||||
//! file (false) or from the database (true)
|
||||
bool isConfigDatabaseEnabled() const;
|
||||
|
||||
//! Initialize the messaging, default = true
|
||||
void setMessagingEnabled(bool enable);
|
||||
bool isMessagingEnabled() const;
|
||||
|
||||
/**
|
||||
* @brief Toggles receiption of messaging membership messages. The
|
||||
* default is false.
|
||||
* @param enable Flag
|
||||
*/
|
||||
void setMembershipMessagesEnabled(bool enable);
|
||||
bool areMembershipMessagesEnabled() const;
|
||||
|
||||
//! Enables/disables sending of start/stop messages.
|
||||
//! If enabled, a start message (at startup) and a
|
||||
//! stop message (at shutdown) will be sent to the
|
||||
//! STATUS group. Default = false
|
||||
void setStartStopMessagesEnabled(bool enable);
|
||||
bool areStartStopMessagesEnabled() const;
|
||||
|
||||
//! Enables/disables auto shutdown caused by
|
||||
//! the shutdown of a definable master module or
|
||||
//! master username. If both values are set the
|
||||
//! one coming first is used.
|
||||
void setAutoShutdownEnabled(bool enable);
|
||||
bool isAutoShutdownEnabled() const;
|
||||
|
||||
//! Enables recordstream URL option, default = true
|
||||
void setRecordStreamEnabled(bool enable);
|
||||
bool isRecordStreamEnabled() const;
|
||||
|
||||
//! Load the stations from the inventory at startup, default = false
|
||||
void setLoadStationsEnabled(bool enable);
|
||||
bool isLoadStationsEnabled() const;
|
||||
|
||||
//! Load the complete inventory at startup, default = false
|
||||
void setLoadInventoryEnabled(bool enable);
|
||||
bool isLoadInventoryEnabled() const;
|
||||
|
||||
//! Load the configmodule from the database at startup, default = false
|
||||
void setLoadConfigModuleEnabled(bool enable);
|
||||
bool isLoadConfigModuleEnabled() const;
|
||||
|
||||
//! Load the cities.xml file, default = false
|
||||
void setLoadCitiesEnabled(bool enable);
|
||||
bool isLoadCitiesEnabled() const;
|
||||
|
||||
//! Load the custom defined fep regions in ~/.seiscomp/fep or
|
||||
//! ~/seiscomp/trunk/share/fep, default = false
|
||||
void setLoadRegionsEnabled(bool enable);
|
||||
bool isLoadRegionsEnabled() const;
|
||||
|
||||
//! Sets whether the received notifier are applied automatically
|
||||
//! or not, default: true
|
||||
|
||||
/**
|
||||
* Sets whether the received notifier are applied automatically
|
||||
* or not, default: true
|
||||
* When AutoApplyNotifier is enabled a received message will
|
||||
* be handled in two passes:
|
||||
* 1. pass: Apply all attached notifier
|
||||
* 2. pass: Interpret all notifier
|
||||
*
|
||||
* So when using an object in an interprete callback it is
|
||||
* garantueed that all child objects that also has been sent
|
||||
* inside the message are attached to it.
|
||||
*/
|
||||
void setAutoApplyNotifierEnabled(bool enable);
|
||||
bool isAutoApplyNotifierEnabled() const;
|
||||
|
||||
/**
|
||||
* Sets whether the received notifier will be interpreted or not.
|
||||
* Default: true
|
||||
* When this option is enabled, the callback methods
|
||||
* addObject(), updateObject() and removeObject() will be
|
||||
* called after a notifier has been received.
|
||||
*/
|
||||
void setInterpretNotifierEnabled(bool enable);
|
||||
bool isInterpretNotifierEnabled() const;
|
||||
|
||||
/** Returns whether a custom publicID pattern has been configured
|
||||
or not */
|
||||
bool hasCustomPublicIDPattern() const;
|
||||
|
||||
/**
|
||||
* Sets the number of retries if a connection fails.
|
||||
* The default value is 0xFFFFFFFF and should be understood
|
||||
* as "keep on trying".
|
||||
*/
|
||||
void setConnectionRetries(unsigned int);
|
||||
|
||||
//! Sets the config module name to use when reading
|
||||
//! the database configuration. An empty module name
|
||||
//! means: read all available modules.
|
||||
//! The default module is "trunk".
|
||||
void setConfigModuleName(const std::string &module);
|
||||
const std::string &configModuleName() const;
|
||||
|
||||
//! Sets the master module used when auto shutdown
|
||||
//! is activated.
|
||||
void setShutdownMasterModule(const std::string &module);
|
||||
|
||||
//! Sets the master username used when auto shutdown
|
||||
//! is activated.
|
||||
void setShutdownMasterUsername(const std::string &username);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Public methods
|
||||
// These methods have to be called after the init() method.
|
||||
// ----------------------------------------------------------------------
|
||||
public:
|
||||
/**
|
||||
* Adds a logger for an input object flow.
|
||||
* This method must be called after Application::init().
|
||||
* The returned pointer is managed by the Application and must not
|
||||
* be deleted.
|
||||
*/
|
||||
ObjectLog *
|
||||
addInputObjectLog(const std::string &name,
|
||||
const std::string &channel = "");
|
||||
|
||||
/**
|
||||
* Adds a logger for an output object flow.
|
||||
* This method must be called after Application::init().
|
||||
* The returned pointer is managed by the Application and must not
|
||||
* be deleted.
|
||||
*/
|
||||
ObjectLog *
|
||||
addOutputObjectLog(const std::string &name,
|
||||
const std::string &channel = "");
|
||||
|
||||
/**
|
||||
* Logs input/output object throughput.
|
||||
* @param log Pointer returned by addInputObjectLog or addOutputObjectLog
|
||||
* @param timestamp The timestamp to be logged
|
||||
*/
|
||||
void logObject(ObjectLog *log, const Core::Time ×tamp,
|
||||
size_t count = 1);
|
||||
|
||||
/**
|
||||
* Reloads the application inventory from either an XML file or
|
||||
* the database.
|
||||
*/
|
||||
bool reloadInventory();
|
||||
|
||||
/**
|
||||
* Reloads the application configuration (bindings) from either an
|
||||
* XML file or the database.
|
||||
*/
|
||||
bool reloadBindings();
|
||||
|
||||
/**
|
||||
* @brief Injects a message from outside. The message will actually
|
||||
* take the same path as when it would have been received via
|
||||
* the messaging.
|
||||
* @param msg The message. The ownership if left to the caller.
|
||||
* @param pkt The optional network packet. The ownership is left to
|
||||
* the caller.
|
||||
*/
|
||||
void injectMessage(Core::Message *msg, Packet *pkt = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Routes a notifier to either add/update or removeObject.
|
||||
* @param notifier The notifier pointer which must not be nullptr
|
||||
*/
|
||||
void handleNotifier(DataModel::Notifier *notifier);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Static public members
|
||||
// ----------------------------------------------------------------------
|
||||
public:
|
||||
//! Returns the pointer to the application's instance.
|
||||
static Application *Instance();
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Protected functions
|
||||
// ----------------------------------------------------------------------
|
||||
protected:
|
||||
virtual bool validateParameters() override;
|
||||
virtual bool handlePreFork() override;
|
||||
|
||||
virtual bool init() override;
|
||||
|
||||
/**
|
||||
* Starts the mainloop until exit() or quit() is called.
|
||||
* The default implementation waits for messages in blocking mode
|
||||
* and calls handleMessage() whenever a new message arrives.
|
||||
*/
|
||||
virtual bool run() override;
|
||||
|
||||
//! This method gets called when all messages has been read or
|
||||
//! the connection is invalid
|
||||
virtual void idle();
|
||||
|
||||
//! Cleanup method called before exec() returns.
|
||||
virtual void done() override;
|
||||
|
||||
//! Opens the configuration file and reads the state variables
|
||||
virtual bool initConfiguration() override;
|
||||
|
||||
//! Initialized the database
|
||||
virtual bool initDatabase();
|
||||
|
||||
//! Sets the database interface and creates a database query object
|
||||
void setDatabase(IO::DatabaseInterface* db);
|
||||
|
||||
/**
|
||||
* Reads the requested subscriptions from the configuration file
|
||||
* and apply them to the messaging connection.
|
||||
*/
|
||||
virtual bool initSubscriptions();
|
||||
|
||||
const std::set<std::string> &subscribedGroups() const;
|
||||
|
||||
/**
|
||||
* Called when the application received the AcquisitionFinished event.
|
||||
* This is most likely send from the readRecords thread of the
|
||||
* StreamApplication. The default implementation does nothing.
|
||||
*/
|
||||
virtual void handleEndAcquisition();
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Messaging handlers
|
||||
// ----------------------------------------------------------------------
|
||||
protected:
|
||||
virtual bool dispatch(Core::BaseObject*);
|
||||
|
||||
//! Custom dispatch method for notifications with negative (< 0)
|
||||
//! types. The default implementation return false.
|
||||
virtual bool dispatchNotification(int type, Core::BaseObject*);
|
||||
|
||||
/**
|
||||
* Reads messages from the connection.
|
||||
* @return true, if successfull, false if not. When returning false,
|
||||
* the mainloop will stop and the program is going to
|
||||
* terminate.
|
||||
*/
|
||||
bool readMessages();
|
||||
|
||||
void stateOfHealth();
|
||||
|
||||
/**
|
||||
* This method gets called when a previously started timer timeout's.
|
||||
* The timer has to be started by enableTimer(timeout).
|
||||
*/
|
||||
virtual void handleTimeout();
|
||||
|
||||
/**
|
||||
* This method is called when close event is sent to the application.
|
||||
* The default handler returns true and causes the event queue to
|
||||
* shutdown and to exit the application.
|
||||
* It false is returned the close event is ignored.
|
||||
*/
|
||||
virtual bool handleClose();
|
||||
|
||||
/**
|
||||
* This methods gets called when an auto shutdown has been
|
||||
* initiated. The default implementation just quits.
|
||||
*/
|
||||
virtual void handleAutoShutdown();
|
||||
|
||||
/**
|
||||
* This methods gets called when an the log interval is reached
|
||||
* and the application should prepare its logging information. This
|
||||
* method can be used to sync logs.
|
||||
* The default implementation does nothing.
|
||||
*/
|
||||
virtual void handleMonitorLog(const Core::Time ×tamp);
|
||||
|
||||
/**
|
||||
* This method gets called after the connection got lost.
|
||||
*/
|
||||
virtual void handleDisconnect();
|
||||
|
||||
/**
|
||||
* This method gets called after the connection got reestablished.
|
||||
*/
|
||||
virtual void handleReconnect();
|
||||
|
||||
/**
|
||||
* Handles receiption of a network packet which is a candidate
|
||||
* for message decoding. Special service messages such as ENTER or
|
||||
* LEAVE will not cause a message to be created. This method is always
|
||||
* called *before* a message should be handled.
|
||||
*/
|
||||
virtual void handleNetworkMessage(const Client::Packet *msg);
|
||||
|
||||
/**
|
||||
* This method gets called whenever a new message arrives. Derived
|
||||
* classes have to implement this method to receive messages.
|
||||
* To enable autoapplying and notifier interpreting call this method
|
||||
* inside the reimplemented version.
|
||||
* @param msg The message. A smartpointer may be stored for
|
||||
* future use. The pointer must not be deleted!
|
||||
*/
|
||||
virtual void handleMessage(Core::Message *msg);
|
||||
|
||||
//! Callback for interpret notifier
|
||||
virtual void addObject(const std::string &parentID, DataModel::Object*) {}
|
||||
|
||||
//! Callback for interpret notifier
|
||||
virtual void removeObject(const std::string &parentID, DataModel::Object*) {}
|
||||
|
||||
//! Callback for interpret notifier
|
||||
virtual void updateObject(const std::string &parentID, DataModel::Object*) {}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Private functions
|
||||
// ----------------------------------------------------------------------
|
||||
private:
|
||||
bool initMessaging();
|
||||
|
||||
bool loadConfig(const std::string &configDB);
|
||||
bool loadInventory(const std::string &inventoryDB);
|
||||
|
||||
void startMessageThread();
|
||||
void runMessageThread();
|
||||
|
||||
bool processEvent();
|
||||
|
||||
void timeout();
|
||||
void stateOfHealthTimeout();
|
||||
|
||||
void monitorLog(const Core::Time ×tamp, std::ostream &os);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementation
|
||||
// ----------------------------------------------------------------------
|
||||
protected:
|
||||
DataModel::DatabaseQueryPtr _query;
|
||||
DataModel::ConfigModulePtr _configModule;
|
||||
|
||||
std::vector<Math::Geo::CityD> _cities;
|
||||
std::set<std::string> _messagingSubscriptions;
|
||||
|
||||
|
||||
private:
|
||||
static Application *_instance;
|
||||
|
||||
|
||||
protected:
|
||||
using StringVector = std::vector<std::string>;
|
||||
|
||||
struct AppSettings : AbstractSettings {
|
||||
int objectLogTimeWindow{60};
|
||||
|
||||
std::string agencyID{"UNSET"};
|
||||
std::string author{"@appname@@@@hostname@"};
|
||||
|
||||
bool enableLoadRegions{false};
|
||||
std::string customPublicIDPattern;
|
||||
std::string configModuleName{"trunk"};
|
||||
|
||||
bool enableFetchDatabase{true};
|
||||
bool enableLoadStations{false};
|
||||
bool enableLoadInventory{false};
|
||||
bool enableLoadConfigModule{false};
|
||||
bool enableAutoApplyNotifier{true};
|
||||
bool enableInterpretNotifier{true};
|
||||
|
||||
unsigned int retryCount{0xFFFFFFFF};
|
||||
|
||||
Util::StringFirewall networkTypeFirewall;
|
||||
Util::StringFirewall stationTypeFirewall;
|
||||
|
||||
struct SOH {
|
||||
void accept(SettingsLinker &linker);
|
||||
|
||||
int interval{60};
|
||||
} soh;
|
||||
|
||||
struct Database {
|
||||
void accept(SettingsLinker &linker);
|
||||
|
||||
bool enable{true};
|
||||
bool showDrivers{false};
|
||||
|
||||
std::string type;
|
||||
std::string parameters;
|
||||
std::string URI;
|
||||
|
||||
std::string inventoryDB;
|
||||
std::string configDB;
|
||||
} database;
|
||||
|
||||
struct Inventory {
|
||||
void accept(SettingsLinker &linker);
|
||||
|
||||
StringVector netTypeAllowlist;
|
||||
StringVector netTypeBlocklist;
|
||||
StringVector staTypeAllowlist;
|
||||
StringVector staTypeBlocklist;
|
||||
} inventory;
|
||||
|
||||
// Messaging
|
||||
struct Messaging {
|
||||
void accept(SettingsLinker &linker);
|
||||
|
||||
bool enable{true};
|
||||
bool membershipMessages{false};
|
||||
|
||||
std::string user;
|
||||
std::string URL{"localhost/production"};
|
||||
std::string primaryGroup{Protocol::LISTENER_GROUP};
|
||||
std::string contentType;
|
||||
unsigned int timeout{3};
|
||||
std::string certificate;
|
||||
|
||||
StringVector subscriptions;
|
||||
|
||||
} messaging;
|
||||
|
||||
struct Client {
|
||||
void accept(SettingsLinker &linker);
|
||||
|
||||
bool startStopMessages{false};
|
||||
bool autoShutdown{false};
|
||||
std::string shutdownMasterModule;
|
||||
std::string shutdownMasterUsername;
|
||||
} client;
|
||||
|
||||
struct RecordStream {
|
||||
void accept(SettingsLinker &linker);
|
||||
|
||||
bool enable{false};
|
||||
bool showDrivers{false};
|
||||
|
||||
std::string URI;
|
||||
std::string file;
|
||||
std::string fileType;
|
||||
} recordstream;
|
||||
|
||||
struct Processing {
|
||||
void accept(SettingsLinker &linker);
|
||||
|
||||
StringVector agencyAllowlist;
|
||||
StringVector agencyBlocklist;
|
||||
Util::StringFirewall firewall;
|
||||
StringVector magnitudeAliases;
|
||||
|
||||
} processing;
|
||||
|
||||
struct Cities {
|
||||
void accept(SettingsLinker &linker);
|
||||
|
||||
bool enable{false};
|
||||
std::string db;
|
||||
} cities;
|
||||
|
||||
void accept(SettingsLinker &linker) override;
|
||||
};
|
||||
|
||||
AppSettings _settings;
|
||||
|
||||
ObjectMonitor *_inputMonitor;
|
||||
ObjectMonitor *_outputMonitor;
|
||||
|
||||
ThreadedQueue<Notification> _queue;
|
||||
std::thread *_messageThread;
|
||||
|
||||
ConnectionPtr _connection;
|
||||
IO::DatabaseInterfacePtr _database;
|
||||
Util::Timer _userTimer;
|
||||
Util::Timer _sohTimer;
|
||||
Core::Time _sohLastUpdate;
|
||||
|
||||
std::mutex _objectLogMutex;
|
||||
};
|
||||
|
||||
|
||||
inline bool Application::waitEvent() {
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
81
include/seiscomp/client/configdb.h
Normal file
81
include/seiscomp/client/configdb.h
Normal file
@ -0,0 +1,81 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SEISCOMP_CLIENT_CONFIG_H
|
||||
#define SEISCOMP_CLIENT_CONFIG_H
|
||||
|
||||
|
||||
#include <seiscomp/datamodel/config.h>
|
||||
#include <seiscomp/datamodel/configmodule.h>
|
||||
#include <seiscomp/datamodel/configstation.h>
|
||||
#include <seiscomp/datamodel/parameterset.h>
|
||||
#include <seiscomp/datamodel/databasereader.h>
|
||||
#include <seiscomp/client.h>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Client {
|
||||
|
||||
|
||||
class SC_SYSTEM_CLIENT_API ConfigDB {
|
||||
private:
|
||||
ConfigDB();
|
||||
|
||||
public:
|
||||
static ConfigDB* Instance();
|
||||
static void Reset();
|
||||
|
||||
void load(DataModel::DatabaseReader* reader,
|
||||
const OPT(std::string)& moduleName = Seiscomp::Core::None,
|
||||
const OPT(std::string)& networkCode = Seiscomp::Core::None,
|
||||
const OPT(std::string)& stationCode = Seiscomp::Core::None,
|
||||
const OPT(std::string)& setupName = Seiscomp::Core::None,
|
||||
const std::set<std::string>& parameterNames = std::set<std::string>());
|
||||
|
||||
void load(const char *xml);
|
||||
|
||||
DataModel::Config *config();
|
||||
|
||||
private:
|
||||
std::map<int, DataModel::ConfigModulePtr> _configModules;
|
||||
std::map<int, DataModel::ConfigStationPtr> _configStations;
|
||||
std::map<int, DataModel::ParameterSetPtr> _parameterSets;
|
||||
DataModel::ConfigPtr _config;
|
||||
static ConfigDB *_instance;
|
||||
|
||||
DataModel::DatabaseIterator getConfigObjects(DataModel::DatabaseReader* reader,
|
||||
const Core::RTTI& classType,
|
||||
const OPT(std::string)& moduleName,
|
||||
const OPT(std::string)& networkCode,
|
||||
const OPT(std::string)& stationCode,
|
||||
const OPT(std::string)& setupName,
|
||||
const std::set<std::string>& parameterNames);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
156
include/seiscomp/client/inventory.h
Normal file
156
include/seiscomp/client/inventory.h
Normal file
@ -0,0 +1,156 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SEISCOMP_CLIENT_INVENTORY_H
|
||||
#define SEISCOMP_CLIENT_INVENTORY_H
|
||||
|
||||
|
||||
#include <seiscomp/datamodel/inventory.h>
|
||||
#include <seiscomp/datamodel/pick.h>
|
||||
#include <seiscomp/datamodel/databasereader.h>
|
||||
#include <seiscomp/datamodel/utils.h>
|
||||
#include <seiscomp/utils/stringfirewall.h>
|
||||
#include <seiscomp/client.h>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Client {
|
||||
|
||||
|
||||
struct SC_SYSTEM_CLIENT_API StationLocation {
|
||||
StationLocation();
|
||||
StationLocation(double lat, double lon, double elevation);
|
||||
|
||||
double latitude;
|
||||
double longitude;
|
||||
double elevation;
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<Seiscomp::DataModel::Station*> StationList;
|
||||
|
||||
class SC_SYSTEM_CLIENT_API Inventory {
|
||||
// ----------------------------------------------------------------------
|
||||
// X'truction
|
||||
// ----------------------------------------------------------------------
|
||||
private:
|
||||
//! Private c'tor. This class implements the singleton pattern and
|
||||
//! can be accessed through the static Instance() method.
|
||||
Inventory();
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Public interface
|
||||
// ----------------------------------------------------------------------
|
||||
public:
|
||||
static Inventory* Instance();
|
||||
static void Reset();
|
||||
|
||||
void load(const char *filename);
|
||||
void load(DataModel::DatabaseReader*);
|
||||
void setInventory(DataModel::Inventory*);
|
||||
|
||||
int filter(const Util::StringFirewall *networkTypeFW,
|
||||
const Util::StringFirewall *stationTypeFW);
|
||||
|
||||
void loadStations(DataModel::DatabaseReader*);
|
||||
|
||||
//! Returns the station location for a network- and stationcode and
|
||||
//! a time. If the station has not been found a ValueException will
|
||||
//! be thrown.
|
||||
StationLocation stationLocation(const std::string& networkCode,
|
||||
const std::string& stationCode,
|
||||
const Core::Time&) const;
|
||||
|
||||
//! Returns the station for a network- and stationcode and
|
||||
//! a time. If the station has not been found nullptr will be returned.
|
||||
DataModel::Station* getStation(const std::string &networkCode,
|
||||
const std::string &stationCode,
|
||||
const Core::Time &,
|
||||
DataModel::InventoryError *error = nullptr) const;
|
||||
|
||||
//! Returns the sensorlocation for a network-, station- and locationcode and
|
||||
//! a time. If the sensorlocation has not been found nullptr will be returned.
|
||||
DataModel::SensorLocation* getSensorLocation(const std::string &networkCode,
|
||||
const std::string &stationCode,
|
||||
const std::string &locationCode,
|
||||
const Core::Time &,
|
||||
DataModel::InventoryError *error = nullptr) const;
|
||||
|
||||
//! Returns the stream for a network-, station-, location- and channelcode and
|
||||
//! a time. If the stream has not been found nullptr will be returned.
|
||||
DataModel::Stream* getStream(const std::string &networkCode,
|
||||
const std::string &stationCode,
|
||||
const std::string &locationCode,
|
||||
const std::string &channelCode,
|
||||
const Core::Time &,
|
||||
DataModel::InventoryError *error = nullptr) const;
|
||||
|
||||
//! Returns the three streams (vertical, horizontal1, horizontal2) corresponding
|
||||
//! to the given network-, station-, location- and channel code
|
||||
DataModel::ThreeComponents getThreeComponents(const std::string& networkCode,
|
||||
const std::string& stationCode,
|
||||
const std::string& locationCode,
|
||||
const std::string& channelCode,
|
||||
const Core::Time&) const;
|
||||
|
||||
//! Returns the station used for a pick. If the station has not been found
|
||||
//! nullptr will be returned.
|
||||
DataModel::Station* getStation(const DataModel::Pick*) const;
|
||||
|
||||
//! Returns the sensor location used for a pick. If the sensor location has
|
||||
//! not been found nullptr will be returned.
|
||||
DataModel::SensorLocation* getSensorLocation(const DataModel::Pick*) const;
|
||||
|
||||
DataModel::Stream* getStream(const DataModel::Pick*) const;
|
||||
|
||||
//! Returns the three streams (vertical, horizontal1, horizontal2) corresponding
|
||||
//! to the picked stream.
|
||||
DataModel::ThreeComponents getThreeComponents(const DataModel::Pick*) const;
|
||||
|
||||
double getGain(const std::string& networkCode,
|
||||
const std::string& stationCode,
|
||||
const std::string& locationCode,
|
||||
const std::string& channelCode,
|
||||
const Core::Time&);
|
||||
|
||||
//! Returns all defined stations for the given time
|
||||
int getAllStations(StationList&, const Core::Time&);
|
||||
|
||||
DataModel::Inventory* inventory();
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Private members
|
||||
// ----------------------------------------------------------------------
|
||||
private:
|
||||
DataModel::InventoryPtr _inventory;
|
||||
static Inventory _instance;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
114
include/seiscomp/client/monitor.h
Normal file
114
include/seiscomp/client/monitor.h
Normal file
@ -0,0 +1,114 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SEISCOMP_UTILS_MONITOR_H
|
||||
#define SEISCOMP_UTILS_MONITOR_H
|
||||
|
||||
#include <seiscomp/client.h>
|
||||
#include <seiscomp/core/datetime.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Client {
|
||||
|
||||
|
||||
//! A running average calculator that logs the number of
|
||||
//! objects/thingies in a certain interval. The accuracy is
|
||||
//! a second.
|
||||
class SC_SYSTEM_CLIENT_API RunningAverage {
|
||||
public:
|
||||
RunningAverage(int timeSpanInSeconds);
|
||||
|
||||
|
||||
public:
|
||||
int timeSpan() const { return _timeSpan; }
|
||||
|
||||
void push(const Core::Time &time, size_t count = 1);
|
||||
|
||||
//! Returns the current count per time span.
|
||||
int count(const Core::Time &time) const;
|
||||
|
||||
//! Returns the value (average) per time span.
|
||||
double value(const Core::Time &time) const;
|
||||
|
||||
//! Returns the timestamp of the last values pushed
|
||||
Core::Time last() const;
|
||||
|
||||
void dumpBins() const;
|
||||
|
||||
|
||||
private:
|
||||
Core::Time _first;
|
||||
Core::Time _last;
|
||||
size_t _timeSpan;
|
||||
double _scale;
|
||||
mutable
|
||||
double _shift;
|
||||
mutable
|
||||
std::vector<size_t> _bins;
|
||||
size_t _front;
|
||||
};
|
||||
|
||||
|
||||
class SC_SYSTEM_CLIENT_API ObjectMonitor {
|
||||
public:
|
||||
typedef RunningAverage Log;
|
||||
|
||||
ObjectMonitor(int timeSpanInSeconds);
|
||||
~ObjectMonitor();
|
||||
|
||||
|
||||
public:
|
||||
Log *add(const std::string &name, const std::string &channel = "");
|
||||
void update(const Core::Time &time);
|
||||
|
||||
|
||||
public:
|
||||
struct Test {
|
||||
std::string name;
|
||||
std::string channel;
|
||||
Core::Time updateTime;
|
||||
size_t count;
|
||||
Log *test;
|
||||
};
|
||||
|
||||
typedef std::list<Test> Tests;
|
||||
typedef Tests::const_iterator const_iterator;
|
||||
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
size_t size() const;
|
||||
|
||||
|
||||
private:
|
||||
Tests _tests;
|
||||
int _timeSpan;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
157
include/seiscomp/client/queue.h
Normal file
157
include/seiscomp/client/queue.h
Normal file
@ -0,0 +1,157 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SEISCOMP_CLIENT_QUEUE_H
|
||||
#define SEISCOMP_CLIENT_QUEUE_H
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
|
||||
#include <seiscomp/core/baseobject.h>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Client {
|
||||
|
||||
class QueueClosedException : public Core::GeneralException {
|
||||
public:
|
||||
QueueClosedException() : Core::GeneralException("Queue has been closed") {}
|
||||
QueueClosedException(const std::string& str ) : Core::GeneralException(str) {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ThreadedQueue {
|
||||
// ----------------------------------------------------------------------
|
||||
// Public types
|
||||
// ----------------------------------------------------------------------
|
||||
public:
|
||||
typedef std::unique_lock<std::mutex> lock;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Non copyable
|
||||
// ----------------------------------------------------------------------
|
||||
private:
|
||||
ThreadedQueue(const ThreadedQueue&) = delete;
|
||||
ThreadedQueue &operator=(const ThreadedQueue&) = delete;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// X'truction
|
||||
// ----------------------------------------------------------------------
|
||||
public:
|
||||
ThreadedQueue();
|
||||
ThreadedQueue(int n);
|
||||
~ThreadedQueue();
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Interface
|
||||
// ----------------------------------------------------------------------
|
||||
public:
|
||||
/**
|
||||
* @brief Resizes the queue to hold a maximum of n items before
|
||||
* blocking.
|
||||
* @param n The number of items to queue before blocking occurs.
|
||||
*/
|
||||
void resize(int n);
|
||||
|
||||
/**
|
||||
* @brief Checks whether the queue can take new items without blocking.
|
||||
* @return true if non-blocking push is possible, false otherwise.
|
||||
*/
|
||||
bool canPush() const;
|
||||
|
||||
/**
|
||||
* @brief Appends a new item to the end of the queue. If the queue is
|
||||
* full then it will block until a consumer has popped an item.
|
||||
* @param v The new item.
|
||||
* @return true if successful, false if queue is closed.
|
||||
*/
|
||||
bool push(T v);
|
||||
|
||||
/**
|
||||
* @brief Checks with equality operator if the item is already queued
|
||||
* and if not, pushes it to the end of the queue.
|
||||
* @param v The new item.
|
||||
* @return true if successful which also covers the case that the item
|
||||
* is already queued. False if the queue is closed.
|
||||
*/
|
||||
bool pushUnique(T v);
|
||||
|
||||
/**
|
||||
* @brief Checks whether an item can be popped or not.
|
||||
* Actually it returns whether the queue is empty or not.
|
||||
* @return true if not empty, false if empty.
|
||||
*/
|
||||
bool canPop() const;
|
||||
|
||||
/**
|
||||
* @brief Pops an items from the queue. If the queue is empty then
|
||||
* it blocks until a producer pushed an item.
|
||||
* @return The popped item.
|
||||
*/
|
||||
T pop();
|
||||
|
||||
/**
|
||||
* @brief Close the queue and cause all subsequent calls to push and
|
||||
* pop to fail.
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* @brief Returns whether the queue is closed or not.
|
||||
* @return The closed flag.
|
||||
*/
|
||||
bool isClosed() const;
|
||||
|
||||
/**
|
||||
* @brief Query the number of queued items.
|
||||
* @return The number of currently queued items.
|
||||
*/
|
||||
size_t size() const;
|
||||
|
||||
/**
|
||||
* @brief Resets the queue which incorporates resetting the buffer
|
||||
* insertations and the closed state.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Private members
|
||||
// ----------------------------------------------------------------------
|
||||
private:
|
||||
volatile int _begin, _end;
|
||||
volatile size_t _buffered;
|
||||
volatile bool _closed;
|
||||
std::vector<T> _buffer;
|
||||
std::condition_variable _notFull, _notEmpty;
|
||||
mutable std::mutex _monitor;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
266
include/seiscomp/client/queue.ipp
Normal file
266
include/seiscomp/client/queue.ipp
Normal file
@ -0,0 +1,266 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef SEISCOMP_CLIENT_QUEUE_IPP
|
||||
#define SEISCOMP_CLIENT_QUEUE_IPP
|
||||
|
||||
|
||||
#include <seiscomp/core/exceptions.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Client {
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T, int IsPtr>
|
||||
struct QueueHelper {};
|
||||
|
||||
template <typename T>
|
||||
struct QueueHelper<T,0> {
|
||||
static void clean(const std::vector<T> &) {}
|
||||
static T defaultValue() { return T(); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct QueueHelper<T,1> {
|
||||
static void clean(const std::vector<T> &b) {
|
||||
for ( size_t i = 0; i < b.size(); ++i ) {
|
||||
if ( b[i] ) delete b[i];
|
||||
}
|
||||
}
|
||||
|
||||
static T defaultValue() { return nullptr; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
template <typename T>
|
||||
ThreadedQueue<T>::ThreadedQueue() :
|
||||
_begin(0), _end(0),
|
||||
_buffered(0), _closed(false), _buffer(0)
|
||||
{}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
template <typename T>
|
||||
ThreadedQueue<T>::ThreadedQueue(int n) :
|
||||
_begin(0), _end(0),
|
||||
_buffered(0), _closed(false), _buffer(n)
|
||||
{}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
template <typename T>
|
||||
ThreadedQueue<T>::~ThreadedQueue() {
|
||||
close();
|
||||
QueueHelper<T, std::is_pointer<T>::value>::clean(_buffer);
|
||||
}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
template <typename T>
|
||||
void ThreadedQueue<T>::resize(int n) {
|
||||
lock lk(_monitor);
|
||||
_buffer.resize(n);
|
||||
}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
template <typename T>
|
||||
bool ThreadedQueue<T>::canPush() const {
|
||||
lock lk(_monitor);
|
||||
|
||||
if ( _closed )
|
||||
throw QueueClosedException();
|
||||
|
||||
return _buffered < _buffer.size();
|
||||
}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
template <typename T>
|
||||
bool ThreadedQueue<T>::push(T v) {
|
||||
lock lk(_monitor);
|
||||
while (_buffered == _buffer.size() && !_closed)
|
||||
_notFull.wait(lk);
|
||||
if ( _closed ) {
|
||||
_notEmpty.notify_all();
|
||||
return false;
|
||||
}
|
||||
_buffer[_end] = v;
|
||||
_end = (_end+1) % _buffer.size();
|
||||
++_buffered;
|
||||
_notEmpty.notify_all();
|
||||
return true;
|
||||
}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
template <typename T>
|
||||
bool ThreadedQueue<T>::pushUnique(T v) {
|
||||
lock lk(_monitor);
|
||||
// Find existing item
|
||||
auto it = _begin;
|
||||
while ( it != _end ) {
|
||||
if ( _buffer[it] == v ) {
|
||||
return true;
|
||||
}
|
||||
it = (it + 1) % _buffer.size();
|
||||
}
|
||||
|
||||
while (_buffered == _buffer.size() && !_closed)
|
||||
_notFull.wait(lk);
|
||||
if ( _closed ) {
|
||||
_notEmpty.notify_all();
|
||||
return false;
|
||||
}
|
||||
_buffer[_end] = v;
|
||||
_end = (_end+1) % _buffer.size();
|
||||
++_buffered;
|
||||
_notEmpty.notify_all();
|
||||
return true;
|
||||
}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
template <typename T>
|
||||
bool ThreadedQueue<T>::canPop() const {
|
||||
lock lk(_monitor);
|
||||
|
||||
if ( _closed )
|
||||
throw QueueClosedException();
|
||||
|
||||
return _buffered > 0;
|
||||
}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
template <typename T>
|
||||
T ThreadedQueue<T>::pop() {
|
||||
lock lk(_monitor);
|
||||
while (_buffered == 0 && !_closed) {
|
||||
_notEmpty.wait(lk);
|
||||
}
|
||||
if ( _closed )
|
||||
throw QueueClosedException();
|
||||
T v = _buffer[_begin];
|
||||
_buffer[_begin] = QueueHelper<T, std::is_pointer<T>::value>::defaultValue();
|
||||
_begin = (_begin+1) % _buffer.size();
|
||||
--_buffered;
|
||||
_notFull.notify_all();
|
||||
return v;
|
||||
}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
template <typename T>
|
||||
void ThreadedQueue<T>::close() {
|
||||
lock lk(_monitor);
|
||||
if ( _closed ) return;
|
||||
_closed = true;
|
||||
_notFull.notify_all();
|
||||
_notEmpty.notify_all();
|
||||
}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
template <typename T>
|
||||
bool ThreadedQueue<T>::isClosed() const {
|
||||
lock lk(_monitor);
|
||||
return _closed;
|
||||
}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
template <typename T>
|
||||
size_t ThreadedQueue<T>::size() const {
|
||||
lock lk(_monitor);
|
||||
return _buffered;
|
||||
}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
template <typename T>
|
||||
void ThreadedQueue<T>::reset() {
|
||||
lock lk(_monitor);
|
||||
_closed = false;
|
||||
_begin = _end = 0;
|
||||
_buffered = 0;
|
||||
QueueHelper<T, std::is_pointer<T>::value>::clean(_buffer);
|
||||
std::fill(_buffer.begin(), _buffer.end(), QueueHelper<T, std::is_pointer<T>::value>::defaultValue());
|
||||
}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
142
include/seiscomp/client/streamapplication.h
Normal file
142
include/seiscomp/client/streamapplication.h
Normal file
@ -0,0 +1,142 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SEISCOMP_CLIENT_STREAM_APPLICATION_H
|
||||
#define SEISCOMP_CLIENT_STREAM_APPLICATION_H
|
||||
|
||||
|
||||
#include <seiscomp/client/application.h>
|
||||
#include <seiscomp/core/record.h>
|
||||
#include <seiscomp/io/recordstream.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Client {
|
||||
|
||||
|
||||
class SC_SYSTEM_CLIENT_API StreamApplication : public Application {
|
||||
// ----------------------------------------------------------------------
|
||||
// X'truction
|
||||
// ----------------------------------------------------------------------
|
||||
public:
|
||||
StreamApplication(int argc, char **argv);
|
||||
~StreamApplication();
|
||||
|
||||
|
||||
public:
|
||||
bool openStream();
|
||||
void closeStream();
|
||||
|
||||
IO::RecordStream* recordStream() const;
|
||||
|
||||
bool addStation(const std::string& networkCode,
|
||||
const std::string& stationCode);
|
||||
bool addStream(const std::string& networkCode,
|
||||
const std::string& stationCode,
|
||||
const std::string& locationCode,
|
||||
const std::string& channelCode);
|
||||
|
||||
void setStartTime(const Seiscomp::Core::Time&);
|
||||
void setEndTime(const Seiscomp::Core::Time&);
|
||||
bool setTimeWindow(const Seiscomp::Core::TimeWindow&);
|
||||
|
||||
//! Sets whether to start the acquisition automatically
|
||||
//! before the run loop or not. This method has to be called before run().
|
||||
//! The default is true. If set to false then the acquisition needs
|
||||
//! to be started with readRecords or startRecordThread and
|
||||
//! autoCloseOnAcquisitionFinished is also set to false.
|
||||
void setAutoAcquisitionStart(bool);
|
||||
|
||||
//! Sets the application close flag when acquisition is finished.
|
||||
//! The default is true as auto start is true. If setAutoAcquisitionStart
|
||||
//! is changed this flag is set as well.
|
||||
void setAutoCloseOnAcquisitionFinished(bool);
|
||||
|
||||
//! Sets the storage hint of incoming records.
|
||||
//! The default is: DATA_ONLY
|
||||
void setRecordInputHint(Record::Hint hint);
|
||||
|
||||
//! Sets the data type of read records.
|
||||
//! The default is: FLOAT
|
||||
void setRecordDatatype(Array::DataType datatype);
|
||||
|
||||
//! Returns the data type of the internal record sample buffer
|
||||
Array::DataType recordDataType() const { return _recordDatatype; }
|
||||
|
||||
void startRecordThread();
|
||||
void waitForRecordThread();
|
||||
bool isRecordThreadActive() const;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Protected interface
|
||||
// ----------------------------------------------------------------------
|
||||
protected:
|
||||
bool init();
|
||||
bool run();
|
||||
void done();
|
||||
void exit(int returnCode);
|
||||
|
||||
bool dispatch(Core::BaseObject* obj);
|
||||
|
||||
void readRecords(bool sendEndNotification);
|
||||
|
||||
//! This method gets called when the acquisition is finished
|
||||
//! The default implementation closes the objects queue and
|
||||
//! finishes the application
|
||||
virtual void acquisitionFinished();
|
||||
|
||||
//! This method gets called when a new record has been received
|
||||
//! by recordstream thread.
|
||||
//! The default implementation stores it in the threaded object
|
||||
//! queue which gets read by the main thread.
|
||||
//! The input record is not managed and ownership is transferred
|
||||
//! to this method.
|
||||
virtual bool storeRecord(Record *rec);
|
||||
|
||||
//! This method gets called when a record has been popped from
|
||||
//! the event queue in the main thread. The ownership of the
|
||||
//! pointer is transferred to this method. An empty function
|
||||
//! body override would cause a memory leak.
|
||||
virtual void handleRecord(Record *rec) = 0;
|
||||
|
||||
//! Logs the received records for the last period
|
||||
virtual void handleMonitorLog(const Core::Time ×tamp);
|
||||
|
||||
|
||||
private:
|
||||
bool _startAcquisition;
|
||||
bool _closeOnAcquisitionFinished;
|
||||
Record::Hint _recordInputHint;
|
||||
Array::DataType _recordDatatype;
|
||||
IO::RecordStreamPtr _recordStream;
|
||||
std::thread *_recordThread;
|
||||
size_t _receivedRecords;
|
||||
ObjectLog *_logRecords;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user