[seiscomp, scanloc] Install, add .gitignore

This commit is contained in:
2025-10-09 15:07:02 +02:00
commit 20f5301bb1
2848 changed files with 1315858 additions and 0 deletions

View 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 &timestamp,
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 &timestamp);
/**
* 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 &timestamp, 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

View 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

View 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

View 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

View 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

View 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

View 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 &timestamp);
private:
bool _startAcquisition;
bool _closeOnAcquisitionFinished;
Record::Hint _recordInputHint;
Array::DataType _recordDatatype;
IO::RecordStreamPtr _recordStream;
std::thread *_recordThread;
size_t _receivedRecords;
ObjectLog *_logRecords;
};
}
}
#endif