Update README

This commit is contained in:
Dennis Klein
2018-04-10 18:52:57 +02:00
parent ff16a28686
commit c0ebd58ee3
14 changed files with 867 additions and 1 deletions

113
docs/Configuration.md Normal file
View File

@@ -0,0 +1,113 @@
← [Back](../README.md)
# 3. Configuration
## 3.1 Device Configuration
Devices receive configuration primarily via provided command line options (that can be extended per device).
## 3.2 Communication Channels Configuration
The communication channels can be configured via configuration parsers. The parser system is extendable, so if provided parsers do not suit your style, you can write your own and plug them in the configuration system.
The provided parsers are:
### 3.2.1 JSON Parser
This parser reads channel configuration from a JSON file. Example:
```JSON
{
"fairMQOptions": {
"devices": [
{
"id": "sampler1",
"channels": [
{
"name": "data",
"sockets": [
{
"type": "push",
"method": "bind",
"address": "tcp://*:5555",
"sndBufSize": 1000,
"rcvBufSize": 1000,
"rateLogging": 1
}
]
}
]
},
{
"id": "sink1",
"channels": [
{
"name": "data",
"sockets": [
{
"type": "pull",
"method": "connect",
"address": "tcp://localhost:5555",
"sndBufSize": 1000,
"rcvBufSize": 1000,
"rateLogging": 1
}
]
}
]
}
]
}
}
```
The JSON file can contain configuration for multiple devices.
- The mapping between device and configuration happens via the device ID (the `--id` parameter of the launched device and the `"id"` entry in the config).
- Instead of `"id"`, JSON file may contain device configurations under `"key"`, which allows launched devices to share configuration, e.g.: `my-device-executable --id <device-id> --config-key <config-key>`.
- Socket options must contain at least *type*, *method* and *address*, the rest of the values are optional and will get default values of the channel.
- If a channel has multiple sub-channels, common properties can be defined under channel directly, and will be shared by all sub-channels, e.g.:
```JSON
"channels": [{
"name": "data",
"type": "push",
"method": "bind",
"sockets": [{
"address": "tcp://*:5555",
"address": "tcp://*:5556",
"address": "tcp://*:5557"
}]
}]
```
### 3.2.2 SuboptParser
This parser configures channels directly from the command line.
The parser handles a comma separated key=value list format by using the getsubopt function of the standard library.
The option key `--channel-config` can be used with the list of key/value pairs, e.g.:
```
--channel-config name=output,type=push,method=bind,address=tcp://127.0.0.1:5555
```
## 3.3 Introspection
A compiled device executable repots its available configuration. Run the device with one of the following options to see the corresponding help:
- `-h [ --help ]`: All available command line options with their descriptions and default values.
- `--print-options`: All available command line options in a machine-readable format: `<option>:<computed-value>:<<type>>:<description>`.
- `--print-channels`: Prints registered channels in a machine-readable format: `<channel name>:<minimum sub-channels>:<maximum sub-channels>`. There are devices where channels names are not known in advance before the configuration takes place (e.g. FairMQMultiplier has configurable channel names at runtime). This options will only print channels that have been registered in the device by implementing the following method:
```C++
void YourDevice::RegisterChannelEndpoints()
{
// provide channel name, minimum and maximum number of subchannels
RegisterChannelEndpoint("channelA", 1, 10000);
RegisterChannelEndpoint("channelB", 1, 1);
}
```
← [Back](../README.md)

13
docs/Development.md Normal file
View File

@@ -0,0 +1,13 @@
← [Back](../README.md)
# 4. Development
## 4.1 Testing
For unit testing it is often not feasible to boot up a full-blown distributed system with dozens of processes.
In some scenarios it is useful to not even instantiate a `FairMQDevice` at all. Please see [this example](../test/protocols/_push_pull_multipart.cxx) for single and multi threaded unit test without a device instance. If you store your transport factories and channels on the heap, pls make sure, you destroy the channels before you destroy the related transport factory for proper shutdown. Channels provide all the `Send/Receive` and `New*Message/New*Poller` APIs provided by the device too.
TODO Multiple devices in one process.
← [Back](../README.md)

52
docs/Device.md Normal file
View File

@@ -0,0 +1,52 @@
← [Back](../README.md)
# 1. Device
The components encapsulating the tasks are called **devices** and derive from the common base class `FairMQDevice`. FairMQ provides ready to use devices to organize the dataflow between the components (without touching the contents of a message), providing functionality like merging and splitting of the data stream (see subdirectory `devices`).
## 1.1 Topology
Devices are arranged into **topologies** where each device has a defined number of data inputs and outputs.
Example of a simple FairMQ topology:
![example of FairMQ topology](images/example_topology.png?raw=true "Example of possible FairMQ topology")
Within a topology each device needs a unique id (given to it via required command line option `--id`).
Topology configuration is currently happening via setup scripts. This is very rudimentary and a much more flexible system is now in development. For now, example setup scripts can be found in directory `FairRoot/example/Tutorial3/` along with some additional documentation.
## 1.2 Communication Patterns
FairMQ devices communicate via the communication patterns offered by ZeroMQ (or nanomsg): PUSH-PULL, PUB-SUB, REQ-REP, PAIR, [more info here](http://api.zeromq.org/4-0:zmq-socket). Each transport may provide further patterns.
## 1.3 State Machine
Each FairMQ device has an internal state machine:
![FairMQ state machine](images/device_states.png?raw=true "FairMQ state machine")
The state machine can be querried and controlled via `GetCurrentStateName()` and `ChangeState("<state name>")` methods. Only legal state transitions are allowed (see image above). Illegal transitions will fail with an error.
If the device is running in interactive mode (default), states can be changed via keyboard input:
- `'h'` - help
- `'p'` - pause
- `'r'` - run
- `'s'` - stop
- `'t'` - reset task
- `'d'` - reset device
- `'q'` - end
- `'j'` - init task
- `'i'` - init device
Without the interactive mode, for example for a run in background, two other control mechanisms are available:
- static (`--control static`) - device goes through a simple init -> run -> reset -> exit chain.
- dds (`--control dds`) - device is controled by external command, in this case using dds commands (fairmq-dds-command-ui).
## 1.4 Multiple devices in the same process
Technically one can create two or more devices within the same process without any conflicts. However the configuration (FairMQProgOptions) currently assumes the supplied configuration values are for one device/process.
← [Back](../README.md)

9
docs/Examples.md Normal file
View File

@@ -0,0 +1,9 @@
← [Back](../README.md)
# 6. Examples
A collection of simple examples in `FairRoot/examples/MQ` directory demonstrates some common usage patterns of FairMQ.
A number of devices to handle the data from the Tutorial3 FairTestDetector of FairRoot are provided as an example and can be found in `FairRoot/base/MQ` directory. The implementation of the tasks run by these devices can be found `FairRoot/examples/advanced/Tutorial3`. The implementation includes sending raw binary data as well as serializing the data with either [Boost Serialization](http://www.boost.org/doc/libs/release/libs/serialization/), [Google Protocol Buffers](https://developers.google.com/protocol-buffers/) or [Root TMessage](http://root.cern.ch/root/html/TMessage.html). Following the examples you can implement your own devices to transport arbitrary data.
← [Back](../README.md)

103
docs/Logging.md Normal file
View File

@@ -0,0 +1,103 @@
← [Back](../README.md)
# 5. Logging
The FairMQLogger header uses fair::Logger library for logging.
All log calls go through the provided LOG(severity) macro. Output through this macro is thread-safe. Logging is done to cout, file output and/or custom sinks.
## 5.1 Log severity
The log severity is controlled via:
```C++
fair::Logger::SetConsoleSeverity("<severity level>");
// and/or
fair::Logger::SetFileSeverity("<severity level>");
// and/or
fair::Logger::SetCustomSeverity("<customSinkName>", "<severity level>");
```
where severity level is one of the following:
```C++
"nolog",
"fatal",
"error",
"warn",
"state",
"info",
"debug",
"debug1",
"debug2",
"debug3",
"debug4",
"trace",
```
Logger will log the chosen severity and all above it (except "nolog", which deactivates logging for that sink completely). Fatal severity is always logged.
When running a FairMQ device, the log severity can be simply provided via `--severity <level>` cmd option.
## 5.2 Log verbosity
The log verbosity is controlled via:
```C++
fair::Logget::SetVerbosity("<verbosity level>");
```
it is same for all sinks, and is one of the following values: `low`, `medium`, `high`, `veryhigh`, which translates to following output:
```
low: [severity] message
medium: [HH:MM:SS][severity] message
high: [process name][HH:MM:SS:µS][severity] message
veryhigh: [process name][HH:MM:SS:µS][severity][file:line:function] message
```
When running a FairMQ device, the log severity can be simply provided via `--verbosity <level>` cmd option.
## 5.3 Color
Colored output on console can be activated with:
```C++
Logger::SetConsoleColor(true);
```
When running a FairMQ device, the log color (console) can be simply provided via `--color <true/false>` cmd option (default is true).
## 5.4 File output
Output to file can be enabled via:
```C++
Logger::InitFileSink("<severity level>", "test_log", true);
```
which will add output to "test_log" filename (if third parameter is `true` it will add timestamp to the file name) with `<severity level>` severity.
When running a FairMQ device, the log file can be simply provided via `--log-to-file <filename_prefix>` cmd option (this will also turn off console output).
## 5.5 Custom sinks
Custom sinks can be added via `Logger::AddCustomSink("sink name", "<severity>", callback)` method.
Here is an example adding a custom sink for all severities ("trace" and above). It has access to the log content and meta data. Custom log calls are also thread-safe.
```C++
Logger::AddCustomSink("MyCustomSink", "trace", [](const string& content, const LogMetaData& metadata)
{
cout << "content: " << content << endl;
cout << "available metadata: " << endl;
cout << "std::time_t timestamp: " << metadata.timestamp << endl;
cout << "std::chrono::microseconds us: " << metadata.us.count() << endl;
cout << "std::string process_name: " << metadata.process_name << endl;
cout << "std::string file: " << metadata.file << endl;
cout << "std::string line: " << metadata.line << endl;
cout << "std::string func: " << metadata.func << endl;
cout << "std::string severity_name: " << metadata.severity_name << endl;
cout << "fair::Severity severity: " << static_cast<int>(metadata.severity) << endl;
});
```
If only output from custom sinks is desirable, console/file sinks must be deactivated by setting their severity to `"nolog"`.
← [Back](../README.md)

94
docs/Transport.md Normal file
View File

@@ -0,0 +1,94 @@
← [Back](../README.md)
# 2. Transport Interface
The communication layer is available through the transport interface. Three interface implementations are currently available. Main implementation uses the [ZeroMQ](http://zeromq.org) library. Alternative implementation relies on the [nanomsg](http://nanomsg.org) library. Third transport implementation is using shared memory via boost::interprocess & ZeroMQ combination.
Here is an overview to give an idea how the interface is implemented:
![FairMQ transport interface](images/transport_interface.png?raw=true "FairMQ transport interface")
Currently, the transports have been tested to work with these communication patterns:
| | zeromq | nanomsg | shmem |
| ------------- |--------| ------- | ----- |
| PAIR | yes | yes | yes |
| PUSH/PULL | yes | yes | yes |
| PUB/SUB | yes | yes | no |
| REQ/REP | yes | yes | yes |
The next table shows the supported address types for each transport implementation:
| | zeromq | nanomsg | shmem | comment |
| ----------- | ------ | ------- | ----- | --------------------------------------------- |
| `inproc://` | yes | yes | yes | in process: useful for unit testing |
| `ipc://` | yes | yes | yes | inter process comm: useful on single machine |
| `tcp://` | yes | yes | yes | useful for any communication, local or remote |
## 2.1 Message
Devices transport data between each other in form of `FairMQMessage`s. These can be filled with arbitrary content. Message can be initialized in three different ways by calling `NewMessage()`:
```cpp
FairMQMessagePtr NewMessage() const;
```
**with no parameters**: Initializes an empty message (typically used for receiving).
```cpp
FairMQMessagePtr NewMessage(const size_t size) const;
```
**given message size**: Initializes message body with a given size. Fill the created contents via buffer pointer.
```cpp
using fairmq_free_fn = void(void* data, void* hint);
FairMQMessagePtr NewMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = nullptr) const;
```
**given existing buffer and a size**: Initialize the message from an existing buffer. In case of ZeroMQ this is a zero-copy operation.
Additionally, FairMQ provides two more message factories for convenience:
```cpp
template<typename T>
FairMQMessagePtr NewSimpleMessage(const T& data) const
```
**copy and own**: Copy the `data` argument into the returned message and take ownership (free memory after message is sent). This interface is useful for small, [trivially copyable](http://en.cppreference.com/w/cpp/concept/TriviallyCopyable) data.
```cpp
template<typename T>
FairMQMessagePtr NewStaticMessage(const T& data) const
```
**point to existing memory**: The returned message will point to the `data` argument, but not take ownership (someone else must destruct this variable). Make sure that `data` lives long enough to be successfully sent. This interface is most useful for third party managed, contiguous memory (Be aware of shallow types with internal pointer references! These will not be sent.)
## 2.1.1 Ownership
The component of a program, that is reponsible for the allocation or destruction of data in memory, is taking ownership over this data. Ownership may be passed along to another component. It is also possible that multiple components share ownership of data. In this case, some strategy must be in place to determine the last user of the data and assign her the responsibility of destruction.
After queuing a message for sending in FairMQ, the transport takes ownership over the message body and will free it with `free()` after it is no longer used. A callback can be passed to the message object, to be called instead of the destruction with `free()` (for initialization via buffer+size).
```cpp
static void FairMQNoCleanup(void* /*data*/, void* /*obj*/) {}
template<typename T>
static void FairMQSimpleMsgCleanup(void* /*data*/, void* obj) { delete static_cast<T*>(obj); }
```
For convenience, two common deleter callbacks are already defined in the `FairMQTransportFactory` class to aid the user in controlling ownership of the data.
## 2.2 Channel
A channel represents a communication endpoint in FairMQ. Usage is similar to a traditional Unix network socket. A device usually contains a number of channels that can either listen for incoming connections from channels of other devices or they can connect to other listening channels. Channels are organized by a channel name and a subchannel index.
```cpp
const FairMQChannel& GetChannel(const std::string& channelName, const int index = 0) const;
```
All subchannels with a common channel name need to be of the same transport type.
## 2.3 Poller
A poller allows to wait on multiple channels either to receive or send a message.
```cpp
FairMQPollerPtr NewPoller(const std::vector<const FairMQChannel*>& channels)
```
**list channels**: This poller waits on all supplied channels. Currently, it is limited to channels of the same transport type only.
← [Back](../README.md)

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB