Compare commits

..

270 Commits

Author SHA1 Message Date
Alexey Rybalchenko
1b30f3ac14 Update return types in ofi::Socket 2020-09-23 09:29:57 +02:00
Alexey Rybalchenko
35c7959c53 Workaround Cpp17MoveInsertable issue on xcode 12 2020-09-22 05:33:29 +02:00
Alexey Rybalchenko
5ea8ffeb34 Update command format in PMIx plugin 2020-09-17 14:22:03 +02:00
Alexey Rybalchenko
04ee1db8e5 Avoid default session id in shmem tests 2020-09-17 14:22:03 +02:00
Dennis Klein
4a15a38dd4 Tests.Device: Set correct log level for FairLogger 1.[7-8] 2020-09-16 15:43:58 +02:00
Dennis Klein
0f5e1b6815 Tests.SDK: Reduce timeout by factor 1000 because new machines can be fast enough to complete within 1ms 2020-09-16 15:43:58 +02:00
Dennis Klein
5e6ad47223 CI: Run macOS checks on newer environment 2020-09-16 15:43:58 +02:00
Alexey Rybalchenko
6932f88c84 Adjust transfer methods behaviour when interrupted
A transer is attempted even if the transport has been interrupted
(with a timeout). When the timeout is reached, transfer methods will
return TransferResult::interrupted (-3).
2020-09-16 15:43:58 +02:00
Alexey Rybalchenko
5e97d85956 Cleanup includes 2020-09-08 16:56:35 +02:00
Alexey Rybalchenko
fdbf289364 Update monitor & debug tools for multiple segments 2020-09-08 16:56:35 +02:00
Alexey Rybalchenko
266843cda5 Shm: initial multiple segments support 2020-09-08 16:56:35 +02:00
Alexey Rybalchenko
b126ede45a Shm: Verbosity switch for Cleanup methods 2020-09-08 16:56:35 +02:00
Alexey Rybalchenko
12e6a874db Remove built-in devices from the main lib 2020-09-08 16:56:35 +02:00
Alexey Rybalchenko
73109fe6d3 Shm: configurable allocation strategy 2020-09-08 16:56:35 +02:00
Alexey Rybalchenko
3b2d2a0ac8 Shm: Refactor to localize segment access 2020-09-08 16:56:35 +02:00
Alexey Rybalchenko
72a45f78b3 Shm: Add Monitor::GetDebugInfo() 2020-09-08 16:56:35 +02:00
Alexey Rybalchenko
b63f31d0e0 Shm: Provide debug infos only in debug mode 2020-09-08 16:56:35 +02:00
Alexey Rybalchenko
70a583d08d Shm: Provide segment/msg debug infos 2020-09-08 16:56:35 +02:00
Alexey Rybalchenko
fe9b87e4e2 Improve error reporting in SDK/fairmq-dds-command-ui 2020-09-07 12:52:43 +02:00
Alexey Rybalchenko
2ac27905e7 Move fairmq-dds-command-ui to SDK 2020-09-03 17:34:05 +02:00
Alexey Rybalchenko
690e8a0370 Retry on EINTR in blocking zmq calls 2020-08-28 18:22:03 +02:00
Alexey Rybalchenko
1f0c94f898 Fix tag mismatch in topology files 2020-08-17 12:39:10 +02:00
Alexey Rybalchenko
62ed4e5f80 Avoid unconditional call to now() when allocating message 2020-08-13 14:16:12 +02:00
neskovic@gmail.com
f1d6b18668 Message counter: use relaxed/acquire memory ordering 2020-08-13 11:49:55 +02:00
Alexey Rybalchenko
c0153a6b55 shmMonitor: Adjust output slightly 2020-08-07 14:27:14 +02:00
Alexey Rybalchenko
86a1dd38a2 ShmMonitor: Use FairLogger for timestamp calculation 2020-08-07 14:27:14 +02:00
Alexey Rybalchenko
be8ab06cc1 Bump FairLogger requirement to 1.6 2020-08-07 14:27:14 +02:00
Alexey Rybalchenko
b0f73017e2 shmmonitor: add output with -v (non-interactive) 2020-08-06 12:24:01 +02:00
Alexey Rybalchenko
b83655d5da MessageBadAlloc: report amount of available memory 2020-08-06 12:24:01 +02:00
Alexey Rybalchenko
9c27051cdc BenchmarkSampler: add alignment parameter 2020-08-06 12:24:01 +02:00
Alexey Rybalchenko
65f9519917 Add error handling for mlock 2020-08-06 12:24:01 +02:00
Alexey Rybalchenko
b5545c1575 Add helpers for AggregatedTopologyState 2020-07-17 12:41:53 +02:00
Alexey Rybalchenko
3eca8e9def Add test for shm transport options 2020-07-15 13:59:53 +02:00
Alexey Rybalchenko
beb7766fca Shm: add options to zero and/or mlock the segment 2020-07-15 13:59:53 +02:00
Giulio Eulisse
bf909f94dc ofi: adapt to the new API for FairMQSocket::Events 2020-07-15 13:58:47 +02:00
Dennis Klein
1140c4c6ab SDK: Provide comparison operator for device and topo states 2020-07-15 13:01:23 +02:00
Alexey Rybalchenko
a6da208e79 Add Undefined and Mixed state for use in SDK 2020-07-15 13:01:23 +02:00
Giulio Eulisse
ba3a82b1df Update FairMQSocket.h 2020-07-15 12:09:54 +02:00
Giulio Eulisse
e8cc104344 Add API to extract ZMQ_EVENTS from socket backend 2020-07-15 12:09:54 +02:00
Alexey Rybalchenko
d5d5c27958 QC examples: fix incorrect topology path 2020-07-09 23:34:28 +02:00
Alexey Rybalchenko
5a7dcd9fc1 SDK: warn if given path translates to no selected tasks 2020-07-09 23:34:28 +02:00
Alexey Rybalchenko
78b1c188bf Shm: report correct size when opening segment 2020-06-30 20:58:53 +02:00
Alexey Rybalchenko
66bc7ba762 Remove useless variable 2020-06-30 20:58:53 +02:00
Alexey Rybalchenko
88bc1f7a06 Shm: throw if requested message size exceeds total segment size 2020-06-30 20:58:53 +02:00
Alexey Rybalchenko
f70201610b Do not attemp to find random port for non-TCP protocols 2020-06-30 20:58:53 +02:00
Alexey Rybalchenko
fc7f6f1116 Enable Boost_NO_BOOST_CMAKE for tests 2020-06-29 14:44:49 +02:00
Alexey Rybalchenko
8125489776 Handle out_of_range when locating RegionInfo 2020-06-29 14:44:49 +02:00
Alexey Rybalchenko
6dd0a44308 Make shmid an 8-digit hex number 2020-06-29 14:44:49 +02:00
Alexey Rybalchenko
afe2dcaa02 BenchmarkSampler: add memset option 2020-06-29 14:44:49 +02:00
Alexey Rybalchenko
aeab9e5407 Socket.h: refactor to reduce duplicate code 2020-06-29 14:44:49 +02:00
Alexey Rybalchenko
539e5602a6 Expose fair::mq::shmem::Monitor::Cleanup() API 2020-06-29 14:44:49 +02:00
Alexey Rybalchenko
beb510ded8 Adjust example 1 docs 2020-06-29 14:44:49 +02:00
Alexey Rybalchenko
d1c51e0f1f Use region linger setting in region example 2020-06-29 14:44:49 +02:00
Alexey Rybalchenko
f885b4618e Optimize unmanaged region ReceiveAcks 2020-06-29 14:44:49 +02:00
Alexey Rybalchenko
3364da9541 Add linger setting for unmanaged region 2020-06-29 14:44:49 +02:00
Alexey Rybalchenko
7aec6f91de Fix typo 2020-06-29 14:44:49 +02:00
Alexey Rybalchenko
9e2a002942 Add -Og flag to Debug build 2020-06-29 14:44:49 +02:00
Alexey Rybalchenko
52c6264faf Fix message counter in region example 2020-06-29 14:44:49 +02:00
Alexey Rybalchenko
79489bb501 Add missing includes 2020-06-10 13:55:15 +02:00
Alexey Rybalchenko
c60dd9965c Add copyright entry for PicoSHA2 2020-06-05 18:16:13 +02:00
Alexey Rybalchenko
79ca436b74 Zmq: let GetData of an empty message return nullptr 2020-06-05 18:16:13 +02:00
Alexey Rybalchenko
36d4f3c937 Use SHA2 instead of boost::hash to generate shmem id 2020-06-05 18:16:13 +02:00
Alexey Rybalchenko
bdf895ae9e Add PicoSHA2 dependency 2020-06-05 18:16:13 +02:00
Alexey Rybalchenko
42986e664c Add PicoSHA2 submodule 2020-06-05 18:16:13 +02:00
Giulio Eulisse
dd47b34e06 Add ability to retrieve ZMQ_FD 2020-06-03 19:44:00 +02:00
Alexey Rybalchenko
a59c902c74 MemoryResource: propagate alignment 2020-06-03 19:41:40 +02:00
Alexey Rybalchenko
dabc48c21a Shm: fix incorrect ptr range check 2020-05-29 23:34:27 +02:00
Alexey Rybalchenko
236d5a8608 Let default shm segm size be multiple of page size
To allow potential optimizations (e.g. huge pages)
2020-05-28 17:23:18 +02:00
Alexey Rybalchenko
5a782e8726 Add a test for unregisted options 2020-05-28 17:23:18 +02:00
Alexey Rybalchenko
5008fa4732 Fix regression in handling unregistered options 2020-05-28 17:23:18 +02:00
Alexey Rybalchenko
b5bb476b0d Adjust program options style to disallow guessing 2020-05-25 14:03:12 +02:00
Giulio Eulisse
ea7ae04025 Adapt to requests by @rbx 2020-05-25 08:36:57 +02:00
Giulio Eulisse
02692e7002 Initiate termination process on SIGTERM as well 2020-05-25 08:36:57 +02:00
Alexey Rybalchenko
53a4d17f8b Alignment part I - Interface and shmem send 2020-05-20 19:34:27 +02:00
Giulio Eulisse
20544e1f18 Do not handle double SIGTERM as abort
A double SIGTERM, or even worse a SIGINT + SIGTERM combination should
not result in an abort, given such a signal really means "die whenever
you want" and can only be generated programmatically. If one wants the
child to die programmatically, they should use SIGKILL.

On the other hand that bashing ctrl-c (i.e. SIGINT) multiple times
on the keyboard really means abort.
2020-05-20 12:14:18 +02:00
Dennis Klein
b32e04db60 Do not search external GTest by default
Can be overridden by -DUSE_EXTERNAL_GTEST=ON.
2020-05-19 10:53:02 +02:00
Alexey Rybalchenko
0d03c76a75 Shm: throw on bad_alloc, option to disable 2020-05-18 14:32:19 +02:00
Alexey Rybalchenko
2916a491b9 Format 2020-05-18 14:32:19 +02:00
Alexey Rybalchenko
b56e32eb11 Replace exit()s with exceptions 2020-05-18 14:32:19 +02:00
Alexey Rybalchenko
4b516de81a Minor formatting 2020-05-18 14:32:19 +02:00
Alexey Rybalchenko
361fb0cba5 Zmq: refactor to use namespaces 2020-05-18 14:32:19 +02:00
Alexey Rybalchenko
df574c6466 Zmq: header only 2020-05-18 14:32:19 +02:00
Alexey Rybalchenko
dbdabd23a4 Zmq: remove global (static) state, refactor 2020-05-18 14:32:19 +02:00
Alexey Rybalchenko
ccbf0be572 Shmem: refactor, clean includes, make header only 2020-05-18 14:32:19 +02:00
Alexey Rybalchenko
7a67719a3c Remove useless members 2020-05-18 14:32:19 +02:00
Alexey Rybalchenko
f4a54ff550 Minor refactoring 2020-05-18 14:32:19 +02:00
Alexey Rybalchenko
d22023bcb5 Implement bulk callbacks for unmanaged regions 2020-05-18 14:32:19 +02:00
Alexey Rybalchenko
a15d59c725 Remove nanomsg transport 2020-05-11 17:38:16 +02:00
Alexey Rybalchenko
8cfc04721e Add unit tests for regions 2020-05-11 12:02:19 +02:00
Alexey Rybalchenko
e9318dd234 Add FairMQTransportFactory::GetId() 2020-05-11 12:02:19 +02:00
Alexey Rybalchenko
c8fc5ad33f Add bool FairMQTransportFactory::SubscribedToRegionEvents() 2020-05-11 12:02:19 +02:00
Alexey Rybalchenko
59e32437a2 shmem region subscriptions: fix race condition 2020-05-11 12:02:19 +02:00
Alexey Rybalchenko
a3afadb824 Call region event callback with local_only event for zmq 2020-05-11 12:02:19 +02:00
Alexey Rybalchenko
9992811822 Implement region events for zmq 2020-05-11 12:02:19 +02:00
Alexey Rybalchenko
4218c185a4 Shmem: Send acks also for local regions 2020-05-04 10:01:29 +02:00
Alexey Rybalchenko
5a49c5b9b1 Truncate the file used for the region mapping 2020-05-04 10:01:29 +02:00
Alexey Rybalchenko
960b612d80 Update docs 2020-04-28 14:47:26 +02:00
Alexey Rybalchenko
e1a113aabe Add region events subscriptions 2020-04-28 14:09:04 +02:00
Alexey Rybalchenko
5721ea9510 SDK: send heartbeats when subscribed to state changes 2020-04-10 18:40:14 +02:00
Alexey Rybalchenko
330687772f Add SubscriptionHeartbeat command 2020-04-10 18:40:14 +02:00
Alexey Rybalchenko
7cbd154344 PMIx plugin: Fix Commands API usage 2020-04-07 14:44:51 +02:00
Alexey Rybalchenko
036561ab38 SDK: track state change (un-)subscriptions 2020-04-07 14:44:51 +02:00
Alexey Rybalchenko
274ba5ec00 Commands: Add task id to subscription status cmds 2020-04-07 14:44:51 +02:00
Alexey Rybalchenko
c5efd3e4a6 SDK: minor refactoring of the command handling 2020-04-07 14:44:51 +02:00
Alexey Rybalchenko
0a5820c07f Fix Typo 2020-04-06 18:42:34 +02:00
Dennis Klein
5788daa410 Plugin manager: extent lifetime of DLLs 2020-04-06 18:42:34 +02:00
Alexey Rybalchenko
46014118f0 QC ex: rename qc devices, granular state control 2020-03-30 13:14:12 +02:00
Alexey Rybalchenko
adc4688f9b DDSCommandUI: include path argument in ChangeState 2020-03-30 13:14:12 +02:00
Alexey Rybalchenko
c3127f22e5 SDK: refactor subscription to allow reuse 2020-03-30 13:14:12 +02:00
Alexey Rybalchenko
926ee743ed DDS plugin: refactor for better readability 2020-03-25 09:53:22 +01:00
Alexey Rybalchenko
c7b1304a2c DDS plugin: Update property instead of set to avoid errors 2020-03-25 09:53:22 +01:00
Alexey Rybalchenko
32764e1b12 DDS plugin: refactor for better readability 2020-03-25 09:53:22 +01:00
Alexey Rybalchenko
96348b8462 DDS plugin: improve error message on unexpected update 2020-03-25 09:53:22 +01:00
Alexey Rybalchenko
cd83efadea DDS plugin: refactor to load DDS task id only once 2020-03-25 09:53:22 +01:00
Alexey Rybalchenko
38eb9d22e4 Shmem: more detailed errors on meta data mismatch 2020-03-24 04:07:58 +01:00
Alexey Rybalchenko
a20ac7af08 SDK: Refactor StateChangeOp and add path parameter 2020-03-24 04:07:58 +01:00
Alexey Rybalchenko
24aabdb854 Add example and test of a n-to-m topology, incuding sub-channel use 2020-03-11 14:51:19 +01:00
Alexey Rybalchenko
539b088ade DDS Plugin: Simplify subchannel bookkeeping 2020-03-11 14:51:19 +01:00
Alexey Rybalchenko
b05782af16 CMake: Reformat 2020-03-11 14:51:19 +01:00
Alexey Rybalchenko
3a8f34efaa Example.QC: Add README 2020-03-11 14:51:19 +01:00
Dennis Klein
8160edfd04 Silence -Wunused-parameter 2020-03-10 14:30:23 +01:00
Dennis Klein
3d4cd02812 Allow undefining LOG macro with FairLogger v1.6.2+
Resolves #244
2020-03-10 14:30:23 +01:00
Alexey Rybalchenko
0ae53fd7d9 Throw an error if shmem receives invalid meta data 2020-03-09 14:09:29 +01:00
Alexey Rybalchenko
a545bee3b1 Do not report interruption by system call as error 2020-03-02 13:42:37 +01:00
Alexey Rybalchenko
f00519b99b PMIx plugin: adapt to updated commands format 2020-02-24 14:41:47 +01:00
Alexey Rybalchenko
41fc27d504 SDK: Update docs 2020-02-21 18:37:33 +01:00
Alexey Rybalchenko
811d1b8973 Update examples readme 2020-02-21 18:37:33 +01:00
Alexey Rybalchenko
ced67d8952 DDS Command UI: remove direct DDS dependency 2020-02-21 18:37:33 +01:00
Alexey Rybalchenko
8123a6ecab QC example: add setting of the property, test if its successful 2020-02-21 18:37:33 +01:00
Alexey Rybalchenko
beff0af51b DDS plugin: fix exiting timeout 2020-02-21 18:37:33 +01:00
Alexey Rybalchenko
21835cc104 Revert the session renaming 2020-02-21 18:37:33 +01:00
Alexey Rybalchenko
334d81a1ab SDK: Unsubscribe in the Topology destructor 2020-02-21 18:37:33 +01:00
Alexey Rybalchenko
c1719eb285 SDK Commands: remove heartbeat commands 2020-02-21 18:37:33 +01:00
Alexey Rybalchenko
fcd1022997 Add session id to DDS commands in dds/qc examples 2020-02-21 18:37:33 +01:00
Alexey Rybalchenko
e221242f9a Use SDK in dds-command-ui 2020-02-21 18:37:33 +01:00
Alexey Rybalchenko
e853d121bf SDK: Add garbage collection for completed ops 2020-02-21 18:37:33 +01:00
Alexey Rybalchenko
14d6d717a3 Add qc example 2020-02-21 18:37:33 +01:00
Alexey Rybalchenko
119cbe37f1 SDK: Add WaitForState() 2020-02-21 18:37:33 +01:00
Alexey Rybalchenko
0e72a9bf54 SDK::DDSSession: remove channel id to task id association 2020-02-21 18:37:33 +01:00
Dennis Klein
3785fd9ff9 SDK: Support DYLD_LIBRARY_PATH from parent env in sdk::DDSEnv
Fixes #235
2020-02-17 19:18:00 +01:00
Dennis Klein
278cd62049 Fix ODR violations for unity builds 2020-02-08 18:58:23 +01:00
Dennis Klein
6c63b01cfe Commands: Add [so]version to and rename installed lib 2020-02-06 15:51:22 +01:00
Andrey Lebedev
66acde2a69 Example.DDS: Fix env script for macOS
- For macOS append Boost_LIBRARY_DIRS to DYLD_LIBRARY_PATH and export DYLD_LIBRARY_PATH in the fairmq-ex-dds-env.sh
- Update CONTRIBUTORS list
2020-01-31 20:45:02 +01:00
Dennis Klein
19ab8bba3b SDK: One more test 2020-01-27 20:50:11 +01:00
Dennis Klein
be524d838a SDK: Add inline docs 2020-01-27 20:50:11 +01:00
Alexey Rybalchenko
92af823135 SDK: Allow passing path to Set/GetProperties 2020-01-27 20:50:11 +01:00
Alexey Rybalchenko
50dacbcdde SDK: update DDSTopology::GetTasks() 2020-01-27 20:50:11 +01:00
Alexey Rybalchenko
264a178424 SDK: Add Topology::AsyncGetProperties
Co-Author: Dennis Klein <d.klein@gsi.de>
2020-01-27 20:50:11 +01:00
Dennis Klein
1c8ad03f3c SDK: Add Topology::AsyncSetProperties
Co-Author: Alexey Rybalchenko <alexryba@gmail.com>
2020-01-27 20:50:11 +01:00
Alexey Rybalchenko
25658370fa SDK: Add DDSTopology::GetTasksMatchingPath 2020-01-27 20:50:11 +01:00
Alexey Rybalchenko
f42945b3a3 SDK: Allow passing path to DDSSession::SendCommand 2020-01-27 20:50:11 +01:00
Dennis Klein
9544de0647 SDK: Do not require r-value refs
I mistakenly thought they were forwarding refs.
2020-01-27 20:50:11 +01:00
Dennis Klein
d608abf31c Fix -Wpedantic 2020-01-27 20:50:11 +01:00
Alexey Rybalchenko
15de80cfd3 Detect network interface of the default route without use of ip 2020-01-17 16:48:31 +01:00
Dennis Klein
f2da29a650 Update copyright 2020-01-16 20:26:53 +01:00
Dennis Klein
c180300303 Increase severity
From user feedback we learned that it is preferred to have this
condition rather fail fast than just warn.
2020-01-16 19:11:36 +01:00
Alexey Rybalchenko
9f8a3553ba Avoid deadlock in FairMQChannel operator=, handle self-assignment 2020-01-16 17:17:52 +01:00
Alexey Rybalchenko
692ec4e997 Fix CIDs 350447, 321250 (uncaught exception) 2020-01-16 17:17:52 +01:00
Alexey Rybalchenko
b6d9c949ae Fix CID 350448 (uncaught exception) 2020-01-16 17:17:52 +01:00
Alexey Rybalchenko
b6791856f9 Fix CID 350451 (uncaught exception) 2020-01-16 17:17:52 +01:00
Alexey Rybalchenko
a1e0814a92 Fix CIDs 350452, 323467 (missing_lock) 2020-01-16 17:17:52 +01:00
Alexey Rybalchenko
38bb14e556 Fix CID 350453 (uninit_member) 2020-01-16 17:17:52 +01:00
Alexey Rybalchenko
7187953604 Fix CID 350455 (uncaught exception) 2020-01-16 17:17:52 +01:00
Alexey Rybalchenko
c290c16896 PMIx: Add commands to plugin and command ui 2020-01-06 20:20:18 +01:00
Dennis Klein
fd2bac3e22 Modernize ctor
https://clang.llvm.org/extra/clang-tidy/checks/modernize-pass-by-value.html#pass-by-value-in-constructors
2020-01-06 20:20:18 +01:00
Alexey Rybalchenko
8e3f25851c Pass by const ref 2020-01-06 20:20:18 +01:00
Alexey Rybalchenko
ce937ca03e Bump linger time for multipart test 2019-12-20 14:04:58 +01:00
Alexey Rybalchenko
684e711b8b Shmem: track number of message objects, throw if non-zero at reset 2019-12-20 14:04:58 +01:00
Alexey Rybalchenko
5b5fecc994 Extend multipart tests to include single part, transfer across >1 channel 2019-12-20 14:04:58 +01:00
Alexey Rybalchenko
462a93b58b Add multipart arguments to the benchmark script 2019-12-20 14:04:58 +01:00
Alexey Rybalchenko
a2cff5b7bb Shmem: simplify message/socket and refactor to use namespaces 2019-12-20 14:04:58 +01:00
Alexey Rybalchenko
b2e027478e shmem: properly initialize received multipart messages 2019-12-16 21:17:06 +01:00
Dennis Klein
e6dede492e Disable codecov.io checks 2019-12-13 14:52:36 +01:00
Dennis Klein
f195eeac66 Silence warning: unused variable 'a' [-Wunused-variable] 2019-12-13 14:52:36 +01:00
Dennis Klein
4d1e7b9cdb Fix AppleClang 10.0.1 support with Boost.Asio <= 1.68 2019-12-13 14:52:36 +01:00
Dennis Klein
50be386191 Support and require DDS 3.0 2019-12-13 14:52:36 +01:00
Alexey Rybalchenko
f31be6d7a1 Update to new DDS API, bump required version 2019-12-04 15:30:45 +01:00
Alexey Rybalchenko
5607d47664 DDSCommandUI: add support for more commands 2019-12-03 15:44:25 +01:00
Alexey Rybalchenko
0f4595b8c1 Remove TransitionTo from plugin APIs 2019-12-03 15:44:25 +01:00
Alexey Rybalchenko
b0b271d1f4 DDS plugin: remove static mode 2019-12-03 15:44:25 +01:00
Alexey Rybalchenko
073f5e5c0e Fix regression in the DDS plugin shutdown handling 2019-11-20 14:07:44 +01:00
Dennis Klein
f6e3183f45 SDK commands: Link shared flatbuffers if no static avail 2019-11-17 11:16:31 +01:00
Dennis Klein
71325828f6 CMake: Add option ENABLE_CCACHE 2019-11-15 14:44:56 +01:00
Alexey Rybalchenko
9d30ff25c2 Remove deprecated methods 2019-11-15 14:36:27 +01:00
Alexey Rybalchenko
2ac8f98178 Shm monitor: fix startup race and enable view-only mode 2019-11-13 16:16:16 +01:00
Alexey Rybalchenko
2c6f436858 Fix shmmonitor daemonization 2019-10-29 20:06:31 +01:00
Alexey Rybalchenko
dd191551ca Include empty parts in multipart example/test 2019-10-29 20:06:31 +01:00
Alexey Rybalchenko
88dbcbe4fd Formatting, some refactoring 2019-10-29 20:06:31 +01:00
Alexey Rybalchenko
85a3a254d4 Shmem: Fix handling of empty message parts 2019-10-29 20:06:31 +01:00
Alexey Rybalchenko
c34d1f0946 Cleanup includes 2019-10-29 20:06:31 +01:00
Alexey Rybalchenko
160ee9d064 Add safety check in shmem region location 2019-10-29 20:06:31 +01:00
Dennis Klein
040931fba7 CMake: Pass multi-value argument atomically 2019-10-28 18:01:56 +01:00
Dennis Klein
0d46ffe010 Docs: Add section on the Controller SDK 2019-10-21 15:52:47 +02:00
Alexey Rybalchenko
72a8e9b33c Commands: support JSON in addition to binary 2019-10-10 10:55:20 +02:00
Dennis Klein
caeee626a3 PMIx plugin: Add barriers and fix lookup of multiple keys 2019-10-07 14:07:27 +02:00
Dennis Klein
e1134321dd PMIx: Support integer values 2019-10-07 14:07:27 +02:00
Dennis Klein
5fc1c47e2a Relax required ZeroMQ version to support the CentOS 7 system package 2019-10-07 14:07:27 +02:00
Alexey Rybalchenko
2f69526c04 Enable commands in tests 2019-09-30 12:18:49 +02:00
Alexey Rybalchenko
7502f4b424 Add unit tests for commands 2019-09-30 12:18:49 +02:00
Alexey Rybalchenko
1c1509af3e Use new commands format in dds command UI 2019-09-30 12:18:49 +02:00
Alexey Rybalchenko
a53e95b5f6 Add flatbuffers-based command format to SDK/plugin 2019-09-30 12:18:49 +02:00
Alexey Rybalchenko
ea9ad64664 CMake: Support multiple values for REQUIRES in fairmq_build_option 2019-09-30 12:18:49 +02:00
Alexey Rybalchenko
b9720e5269 Update Topology.h 2019-09-19 15:45:28 +02:00
Dennis Klein
343605899f CI: Record DDS logs in error cases for analysis 2019-09-18 18:06:46 +02:00
Alexey Rybalchenko
d64169a163 SDK: optimize container access 2019-09-18 18:06:46 +02:00
Alexey Rybalchenko
37c8041997 Add missing include 2019-09-18 18:06:46 +02:00
Alexey Rybalchenko
d8d293302d Remove unused includes 2019-09-18 18:06:46 +02:00
Alexey Rybalchenko
9544d9665b DDS plugin: Prefix channel properties 2019-09-18 18:06:46 +02:00
Dennis Klein
47d9e282d4 SDK: Replace for loop with count_if 2019-09-17 11:34:46 +02:00
Alexey Rybalchenko
23423a86d9 Reduce codecov verbosity 2019-09-16 16:02:47 +02:00
Alexey Rybalchenko
dc72262af1 DDS Plugin: reset channel containers before filling 2019-09-16 16:02:47 +02:00
Alexey Rybalchenko
44bfbe02ed SDK: optimize TryChangeStateCompletion 2019-09-16 16:02:47 +02:00
Dennis Klein
924320a0ac DDS plugin: Move Boost dependency to intended target 2019-09-13 15:00:14 +02:00
Dennis Klein
e3890a4033 DDS plugin: Do not block the DDS KeyValue callback 2019-09-13 14:53:42 +02:00
Dennis Klein
fa394194e8 CMake: Fix working directory for submodule update command 2019-09-11 15:41:43 +02:00
Dennis Klein
79bcb40c04 CI: Preserve full paths in coverage reports 2019-09-05 21:59:37 +02:00
Dennis Klein
54719da645 CI: Enable SDK build and tests 2019-09-05 21:59:37 +02:00
Alexey Rybalchenko
4b78c472b1 Add sdk:GroupByTaskId(TopologyState) 2019-09-05 21:59:37 +02:00
Alexey Rybalchenko
92112c812f Handle InitializingDevice in the ShutdownSequence 2019-09-05 21:59:37 +02:00
Alexey Rybalchenko
870d0deae1 Add test for sdk::GroupByCollectionId(TopologyState) 2019-09-05 21:59:37 +02:00
Alexey Rybalchenko
acbf57d6f3 Add sdk::GroupByCollectionId(TopologyState) 2019-09-05 21:59:37 +02:00
Alexey Rybalchenko
2973ce0352 Add collections to test topology 2019-09-05 21:59:37 +02:00
Alexey Rybalchenko
e1b6b804bd sdk: Add DDSTopology::GetCollections() and extend DDSTask 2019-09-05 21:59:37 +02:00
Alexey Rybalchenko
456b65871a sdk: Add DDSCollection class 2019-09-05 21:59:37 +02:00
Dennis Klein
3f5374820a CMake: Add config for --graphviz 2019-09-04 21:17:35 +02:00
Dennis Klein
8a2c7fb601 DDS plugin: Wait for IDLE->EXITING state-change to be acknowledged
Sometimes devices shut down too fast when entering the EXITING state so
that the publication of that state-change will never be sent. The plugin
now waits for an acknowledgement by the external controller with a
configurable timeout.
2019-09-04 21:17:35 +02:00
Dennis Klein
c1a17c97b8 SDK: Add getter for agent path 2019-09-04 21:17:35 +02:00
Dennis Klein
ac8825c8de SDK: Update convenience header 2019-09-04 21:17:35 +02:00
Dennis Klein
1c49dde668 SDK: Fix data races on the local semaphores 2019-09-04 21:17:35 +02:00
Dennis Klein
5d6184cd1a Tools: Add a copyable SharedSemaphore 2019-09-04 21:17:35 +02:00
Dennis Klein
0e5f648d2b SDK: Require DDS 2.5.46
This DDS version fixed a critical deadlock
2019-09-04 21:17:35 +02:00
Dennis Klein
8057b8ae33 Tests.SDK: Fix formatting 2019-09-04 21:17:35 +02:00
Dennis Klein
da28b85497 Tests.SDK: Add optional DDS Tools API stability tests 2019-09-04 21:17:35 +02:00
Dennis Klein
33b5a2a342 SDK: Require DDS 2.5.42 and adapt to most recent API change 2019-09-04 21:17:35 +02:00
Dennis Klein
5b47df3014 SDK: Fix race condition which lead to frequent segfaults on destruction 2019-09-04 21:17:35 +02:00
Dennis Klein
fd77f2b729 SDK: Add usage examples (and tests) 2019-09-04 21:17:35 +02:00
Dennis Klein
6275f4d267 fairmq: Remove obsolete functions 2019-09-04 21:17:35 +02:00
Dennis Klein
d09be4ab79 Docs: Fix link 2019-09-04 21:17:35 +02:00
Dennis Klein
246e99a577 SDK: Fix exception specification 2019-09-04 21:17:35 +02:00
Dennis Klein
0d182dc18f fairmq: Fix -Wdefaulted-function-deleted 2019-09-04 21:17:35 +02:00
Dennis Klein
46e0796e77 CMake: Make the SDK depend on DDS_PLUGIN 2019-09-04 21:17:35 +02:00
Dennis Klein
1055f035ff CMake: Issue a warning if build option requirements are not met 2019-09-04 21:17:35 +02:00
Dennis Klein
7a0d348bd4 SDK: Implement Topology with asio-compliant async interface 2019-09-04 21:17:35 +02:00
Dennis Klein
3cd6d8cfca SDK: Refactor out DDSTask 2019-09-04 21:17:35 +02:00
Dennis Klein
0f50abf3d9 SDK: Fix completion signature and catch completion exceptions 2019-09-04 21:17:35 +02:00
Dennis Klein
75a3a80ac1 CMake: Fix submodule update command 2019-09-04 21:17:35 +02:00
Dennis Klein
25539e99f2 SDK: Introduce fairmq error category 2019-09-04 21:17:35 +02:00
Dennis Klein
f73a6d71ed CMake: Do not use git version in install tree 2019-09-04 21:17:35 +02:00
Dennis Klein
73af0ed78b SDK: Implement asio-compliant asynchronous operation helpers 2019-09-04 21:17:35 +02:00
Dennis Klein
1dec059104 SDK: Require C++14, CMake 3.11 and bundle asio 1.13.0
Decouple from Boost distro to be able to use
newest releases and rely on std::error_code only.
2019-09-04 21:17:35 +02:00
Dennis Klein
88ff5d8fc0 CMake: Bundle GTest 2019-09-04 21:17:35 +02:00
Dennis Klein
d6d9312e53 CMake: Add find module for asio 2019-09-04 21:17:35 +02:00
Dennis Klein
2208fe91e8 README: Update instructions 2019-09-04 21:17:35 +02:00
Dennis Klein
8d12b908b6 SDK: Implement helper to find most recent running DDS session 2019-09-04 21:17:35 +02:00
Alexey Rybalchenko
02b20c320c Add support for fairlogger dependencies 2019-08-22 15:52:45 +02:00
Alexey Rybalchenko
be06a5629e Print install prefix in cmake summary 2019-08-14 15:03:12 +02:00
Alexey Rybalchenko
eaa8f5cbdd SDK: Require DDS 2.5.36 and support new Tools API 2019-08-13 20:04:05 +02:00
Alexey Rybalchenko
7f0237d97d Example.DDS: Support DDS 2.5.25+ CLI 2019-08-13 20:04:05 +02:00
Alexey Rybalchenko
2fc93994d1 Execute test for DDS example only if DDS was found 2019-08-12 16:22:39 +02:00
Alexey Rybalchenko
8feffe70ba Topology: Use DDSTask type, remove unused member 2019-08-12 16:22:39 +02:00
Dennis Klein
31edf948de FairMQ: Require Boost 1.66 2019-08-07 18:37:36 +02:00
Dennis Klein
7cacf471b9 CI: Disable sdk until DDS 2.6 2019-07-29 09:22:02 +02:00
Dennis Klein
7316b0e7f2 Example.DDS: Run example as unit test
Part of #185
2019-07-29 09:22:02 +02:00
Dennis Klein
1fa82f5f22 Example.DDS: Make example topologies pass xml validation 2019-07-29 09:22:02 +02:00
Dennis Klein
1bb77bf47b DDS plugin: Automatically set session and device id if not provided
Resolves #187
2019-07-29 09:22:02 +02:00
Dennis Klein
07fe02a0a0 Tests.SDK: Add another test 2019-07-29 09:22:02 +02:00
Dennis Klein
9cbccface7 DDS plugin: Synchronize FillChannelContainers and DDSKeyValue updates
This was a regression after introducing external control mode in f7cdf5e.
2019-07-29 09:22:02 +02:00
Dennis Klein
7b773cde51 SDK: Improve error handling in case state-change fails on a device
Replace the log message with

1. Nothing, if the device is already in the target state
2. Abort and call the completion callback with error otherwise
2019-07-29 09:22:02 +02:00
Dennis Klein
fd282fa950 SDK: Track channel to task id association 2019-07-29 09:22:02 +02:00
Dennis Klein
008be36125 PluginServices: Do not throw if device control cannot be released 2019-07-29 09:22:02 +02:00
252 changed files with 13398 additions and 8475 deletions

View File

@@ -1,3 +1,3 @@
--- ---
Checks: '*,-google-*,-fuchsia-*,-cert-*,-llvm-header-guard,-readability-named-parameter,-misc-non-private-member-variables-in-classes,-*-magic-numbers,-llvm-include-order,-hicpp-no-array-decay,-performance-unnecessary-value-param,-cppcoreguidelines-pro-bounds-array-to-pointer-decay' Checks: '*,-google-*,-fuchsia-*,-cert-*,-llvm-header-guard,-readability-named-parameter,-misc-non-private-member-variables-in-classes,-*-magic-numbers,-llvm-include-order,-hicpp-no-array-decay,-performance-unnecessary-value-param,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-modernize-use-trailing-return-type,-readability-redundant-member-init'
HeaderFilterRegex: '/(fairmq/|FairMQ)' HeaderFilterRegex: '/(fairmq/)'

View File

@@ -1,2 +1,3 @@
comment: comment:
layout: "diff, files" layout: "diff, files"
behavior: once

9
.gitmodules vendored Normal file
View File

@@ -0,0 +1,9 @@
[submodule "extern/googletest"]
path = extern/googletest
url = https://github.com/google/googletest
[submodule "extern/asio"]
path = extern/asio
url = https://github.com/chriskohlhoff/asio
[submodule "extern/PicoSHA2"]
path = extern/PicoSHA2
url = https://github.com/okdshin/PicoSHA2

View File

@@ -0,0 +1,14 @@
set(GRAPHVIZ_GRAPH_TYPE digraph)
set(GRAPHVIZ_GRAPH_NAME FairMQ)
set(GRAPHVIZ_EXECUTABLES ON)
set(GRAPHVIZ_STATIC_LIBS OFF)
set(GRAPHVIZ_SHARED_LIBS ON)
set(GRAPHVIZ_MODULE_LIBS OFF)
set(GRAPHVIZ_GENERATE_PER_TARGET OFF)
set(GRAPHVIZ_GENERATE_DEPENDERS OFF)
set(GRAPHVIZ_IGNORE_TARGETS
"fairmq-ex.*"
"testsuite_.*"
"testhelper_.*"
"FairMQPlugin_test_dummy"
)

View File

@@ -6,8 +6,8 @@
# copied verbatim in the file "LICENSE" # # copied verbatim in the file "LICENSE" #
################################################################################ ################################################################################
cmake_minimum_required(VERSION 3.10 FATAL_ERROR) cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
cmake_policy(VERSION 3.10...3.14) cmake_policy(VERSION 3.12...3.15)
# Project ###################################################################### # Project ######################################################################
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
@@ -18,7 +18,7 @@ get_git_version()
project(FairMQ VERSION ${PROJECT_VERSION} LANGUAGES CXX) project(FairMQ VERSION ${PROJECT_VERSION} LANGUAGES CXX)
message(STATUS "${BWhite}${PROJECT_NAME}${CR} ${PROJECT_GIT_VERSION} from ${PROJECT_DATE}") message(STATUS "${BWhite}${PROJECT_NAME}${CR} ${PROJECT_GIT_VERSION} from ${PROJECT_DATE}")
if(BUILD_OFI_TRANSPORT) if(BUILD_OFI_TRANSPORT OR BUILD_SDK OR BUILD_PMIX_PLUGIN)
set(PROJECT_MIN_CXX_STANDARD 14) set(PROJECT_MIN_CXX_STANDARD 14)
else() else()
set(PROJECT_MIN_CXX_STANDARD 11) set(PROJECT_MIN_CXX_STANDARD 11)
@@ -31,17 +31,30 @@ include(CTest)
# Build options ################################################################ # Build options ################################################################
include(CMakeDependentOption) fairmq_build_option(BUILD_FAIRMQ "Build FairMQ library and devices."
option(BUILD_FAIRMQ "Build FairMQ library and devices." ON) DEFAULT ON)
cmake_dependent_option(BUILD_TESTING "Build tests." OFF "BUILD_FAIRMQ" OFF) fairmq_build_option(BUILD_TESTING "Build tests."
cmake_dependent_option(BUILD_NANOMSG_TRANSPORT "Build nanomsg transport." OFF "BUILD_FAIRMQ" OFF) DEFAULT OFF REQUIRES "BUILD_FAIRMQ")
cmake_dependent_option(BUILD_OFI_TRANSPORT "Build experimental OFI transport." OFF "BUILD_FAIRMQ" OFF) fairmq_build_option(BUILD_OFI_TRANSPORT "Build experimental OFI transport."
cmake_dependent_option(BUILD_DDS_PLUGIN "Build DDS plugin." OFF "BUILD_FAIRMQ" OFF) DEFAULT OFF REQUIRES "BUILD_FAIRMQ")
cmake_dependent_option(BUILD_PMIX_PLUGIN "Build PMIx plugin." OFF "BUILD_FAIRMQ" OFF) fairmq_build_option(BUILD_SDK_COMMANDS "Build the FairMQ SDK commands."
cmake_dependent_option(BUILD_EXAMPLES "Build FairMQ examples." ON "BUILD_FAIRMQ" OFF) DEFAULT OFF)
option(BUILD_SDK "Build the FairMQ controller SDK." OFF) fairmq_build_option(BUILD_DDS_PLUGIN "Build DDS plugin."
option(BUILD_DOCS "Build FairMQ documentation." OFF) DEFAULT OFF REQUIRES "BUILD_FAIRMQ;BUILD_SDK_COMMANDS")
option(FAST_BUILD "Fast production build. Not recommended for development." OFF) fairmq_build_option(BUILD_PMIX_PLUGIN "Build PMIx plugin."
DEFAULT OFF REQUIRES "BUILD_FAIRMQ;BUILD_SDK_COMMANDS")
fairmq_build_option(BUILD_EXAMPLES "Build FairMQ examples."
DEFAULT ON REQUIRES "BUILD_FAIRMQ")
fairmq_build_option(BUILD_SDK "Build the FairMQ controller SDK."
DEFAULT OFF REQUIRES "BUILD_DDS_PLUGIN;BUILD_SDK_COMMANDS")
fairmq_build_option(BUILD_DOCS "Build FairMQ documentation."
DEFAULT OFF)
fairmq_build_option(FAST_BUILD "Fast production build. Not recommended for development."
DEFAULT OFF)
fairmq_build_option(USE_EXTERNAL_GTEST "Do not use bundled GTest. Not recommended."
DEFAULT OFF)
fairmq_build_option(FAIRMQ_DEBUG_MODE "Compile in debug mode (may decrease performance)."
DEFAULT OFF)
################################################################################ ################################################################################
@@ -54,11 +67,6 @@ set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
if(BUILD_NANOMSG_TRANSPORT)
find_package2(PRIVATE nanomsg REQUIRED)
set(PROJECT_nanomsg_VERSION 1.1.3) # Once upstream releases 1.1.5, we should bump again and use version check
endif()
if(BUILD_OFI_TRANSPORT) if(BUILD_OFI_TRANSPORT)
find_package2(PRIVATE asiofi REQUIRED find_package2(PRIVATE asiofi REQUIRED
VERSION 0.3.1 VERSION 0.3.1
@@ -68,22 +76,15 @@ if(BUILD_OFI_TRANSPORT)
) )
endif() endif()
if(BUILD_NANOMSG_TRANSPORT) if(BUILD_SDK_COMMANDS)
find_package2(PRIVATE msgpack REQUIRED find_package2(PRIVATE Flatbuffers REQUIRED)
VERSION 3.1.0
)
endif() endif()
if(BUILD_SDK)
set(required_dds_version 2.5.22)
else()
set(required_dds_version 2.4)
endif()
if(BUILD_DDS_PLUGIN OR BUILD_SDK) if(BUILD_DDS_PLUGIN OR BUILD_SDK)
find_package2(PRIVATE DDS REQUIRED find_package2(PRIVATE DDS REQUIRED
VERSION ${required_dds_version} VERSION 3.0
) )
set(DDS_Boost_COMPONENTS system log log_setup) set(DDS_Boost_COMPONENTS system log log_setup regex filesystem thread)
set(DDS_Boost_VERSION 1.67) set(DDS_Boost_VERSION 1.67)
endif() endif()
@@ -95,9 +96,16 @@ endif()
if(BUILD_FAIRMQ OR BUILD_SDK) if(BUILD_FAIRMQ OR BUILD_SDK)
find_package2(PUBLIC FairLogger REQUIRED find_package2(PUBLIC FairLogger REQUIRED
VERSION 1.2.0 VERSION 1.6.0
) )
foreach(dep IN LISTS FairLogger_PACKAGE_DEPENDENCIES)
if(NOT dep STREQUAL "Boost")
find_package2(PUBLIC ${dep} REQUIRED VERSION ${FairLogger_${dep}_VERSION})
set(PROJECT_${dep}_VERSION ${FairLogger_${dep}_VERSION})
endif()
endforeach()
if(NOT DEFINED Boost_NO_BOOST_CMAKE AND CMAKE_VERSION VERSION_LESS 3.15) if(NOT DEFINED Boost_NO_BOOST_CMAKE AND CMAKE_VERSION VERSION_LESS 3.15)
# Since Boost 1.70 a CMake package is shipped by default. Unfortunately, it has a number # Since Boost 1.70 a CMake package is shipped by default. Unfortunately, it has a number
# of problems that are only fixed in Boost 1.71 or CMake 3.15. By default we skip the # of problems that are only fixed in Boost 1.71 or CMake 3.15. By default we skip the
@@ -105,7 +113,7 @@ if(BUILD_FAIRMQ OR BUILD_SDK)
set(Boost_NO_BOOST_CMAKE ON) set(Boost_NO_BOOST_CMAKE ON)
endif() endif()
find_package2(PUBLIC Boost REQUIRED find_package2(PUBLIC Boost REQUIRED
VERSION 1.64 VERSION 1.66
COMPONENTS COMPONENTS
container container
@@ -119,18 +127,39 @@ if(BUILD_FAIRMQ OR BUILD_SDK)
DDS DDS
FairLogger FairLogger
) )
# Normalize Boost version
if(CMAKE_VERSION VERSION_LESS 3.15)
set(Boost_VERSION "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}")
endif()
endif()
if(BUILD_SDK)
find_package2(BUNDLED asio
VERSION 1.13.0
)
if(NOT asio_FOUND)
build_bundled(asio extern/asio)
find_package2(PRIVATE asio REQUIRED)
endif()
endif() endif()
if(BUILD_FAIRMQ) if(BUILD_FAIRMQ)
find_package2(PRIVATE ZeroMQ REQUIRED find_package2(PRIVATE ZeroMQ REQUIRED
VERSION 4.1.5 VERSION 4.1.4
) )
build_bundled(PicoSHA2 extern/PicoSHA2)
find_package2(PRIVATE PicoSHA2 REQUIRED)
endif() endif()
if(BUILD_TESTING) if(BUILD_TESTING)
find_package2(PRIVATE GTest REQUIRED if(USE_EXTERNAL_GTEST)
VERSION 1.7.0 find_package2(PRIVATE GTest VERSION 1.7.0)
) endif()
if(NOT GTest_FOUND)
build_bundled(GTest extern/googletest)
find_package2(PRIVATE GTest REQUIRED)
endif()
endif() endif()
if(BUILD_DOCS) if(BUILD_DOCS)
@@ -181,9 +210,6 @@ endif()
if(BUILD_PMIX_PLUGIN) if(BUILD_PMIX_PLUGIN)
list(APPEND PROJECT_PACKAGE_COMPONENTS pmix_plugin) list(APPEND PROJECT_PACKAGE_COMPONENTS pmix_plugin)
endif() endif()
if(BUILD_NANOMSG_TRANSPORT)
list(APPEND PROJECT_PACKAGE_COMPONENTS nanomsg_transport)
endif()
if(BUILD_OFI_TRANSPORT) if(BUILD_OFI_TRANSPORT)
list(APPEND PROJECT_PACKAGE_COMPONENTS ofi_transport) list(APPEND PROJECT_PACKAGE_COMPONENTS ofi_transport)
endif() endif()
@@ -196,6 +222,9 @@ endif()
if(BUILD_SDK) if(BUILD_SDK)
list(APPEND PROJECT_PACKAGE_COMPONENTS sdk) list(APPEND PROJECT_PACKAGE_COMPONENTS sdk)
endif() endif()
if(BUILD_SDK_COMMANDS)
list(APPEND PROJECT_PACKAGE_COMPONENTS sdk_commands)
endif()
################################################################################ ################################################################################
@@ -210,6 +239,22 @@ if(BUILD_DOCS)
DESTINATION ${PROJECT_INSTALL_DATADIR}/docs DESTINATION ${PROJECT_INSTALL_DATADIR}/docs
) )
endif() endif()
if(BUILD_SDK)
install(FILES cmake/Findasio.cmake
DESTINATION ${PROJECT_INSTALL_CMAKEMODDIR}
)
if(asio_BUNDLED)
install(TARGETS bundled_asio_headers EXPORT ${PROJECT_EXPORT_SET})
install(DIRECTORY "${asio_BUILD_INCLUDE_DIR}/asio"
DESTINATION ${asio_INSTALL_INCLUDE_DIR}
PATTERN "Makefile.am" EXCLUDE
PATTERN ".gitignore" EXCLUDE
)
install(FILES "${asio_BUILD_INCLUDE_DIR}/asio.hpp"
DESTINATION ${asio_INSTALL_INCLUDE_DIR}
)
endif()
endif()
install_cmake_package() install_cmake_package()
################################################################################ ################################################################################
@@ -245,16 +290,8 @@ if(PROJECT_PACKAGE_DEPENDENCIES)
message(STATUS " ") message(STATUS " ")
message(STATUS " ${Cyan}DEPENDENCY FOUND VERSION PREFIX${CR}") message(STATUS " ${Cyan}DEPENDENCY FOUND VERSION PREFIX${CR}")
foreach(dep IN LISTS PROJECT_PACKAGE_DEPENDENCIES) foreach(dep IN LISTS PROJECT_PACKAGE_DEPENDENCIES)
if(${dep}_VERSION) if(${dep}_VERSION AND NOT ${dep}_VERSION STREQUAL "..")
if(${dep} STREQUAL Boost) set(version_str "${BGreen}${${dep}_VERSION}${CR}")
if(Boost_VERSION_MAJOR)
set(version_str "${BGreen}${${dep}_VERSION_MAJOR}.${${dep}_VERSION_MINOR}${CR}")
else()
set(version_str "${BGreen}${${dep}_MAJOR_VERSION}.${${dep}_MINOR_VERSION}${CR}")
endif()
else()
set(version_str "${BGreen}${${dep}_VERSION}${CR}")
endif()
else() else()
set(version_str "${BYellow}unknown${CR}") set(version_str "${BYellow}unknown${CR}")
endif() endif()
@@ -275,16 +312,10 @@ if(PROJECT_PACKAGE_DEPENDENCIES)
endif() endif()
elseif(${dep} STREQUAL GTest) elseif(${dep} STREQUAL GTest)
get_filename_component(prefix ${GTEST_INCLUDE_DIRS}/.. ABSOLUTE) get_filename_component(prefix ${GTEST_INCLUDE_DIRS}/.. ABSOLUTE)
elseif(${dep} STREQUAL msgpack)
get_target_property(msgpack_include msgpackc-cxx INTERFACE_INCLUDE_DIRECTORIES)
get_filename_component(prefix ${msgpack_include}/.. ABSOLUTE)
elseif(${dep} STREQUAL asiofi) elseif(${dep} STREQUAL asiofi)
set(prefix ${asiofi_ROOT}) set(prefix ${asiofi_ROOT})
elseif(${dep} STREQUAL OFI) elseif(${dep} STREQUAL OFI)
get_filename_component(prefix ${${dep}_INCLUDE_DIRS}/.. ABSOLUTE) get_filename_component(prefix ${${dep}_INCLUDE_DIRS}/.. ABSOLUTE)
elseif(${dep} STREQUAL nanomsg)
get_target_property(nn_include nanomsg INTERFACE_INCLUDE_DIRECTORIES)
get_filename_component(prefix ${nn_include}/.. ABSOLUTE)
elseif(${dep} STREQUAL DDS) elseif(${dep} STREQUAL DDS)
set(prefix "${DDS_INSTALL_PREFIX}") set(prefix "${DDS_INSTALL_PREFIX}")
elseif(${dep} STREQUAL Boost) elseif(${dep} STREQUAL Boost)
@@ -298,10 +329,22 @@ if(PROJECT_PACKAGE_DEPENDENCIES)
get_target_property(doxygen_bin Doxygen::doxygen INTERFACE_LOCATION) get_target_property(doxygen_bin Doxygen::doxygen INTERFACE_LOCATION)
get_filename_component(prefix ${doxygen_bin} DIRECTORY) get_filename_component(prefix ${doxygen_bin} DIRECTORY)
get_filename_component(prefix ${prefix}/.. ABSOLUTE) get_filename_component(prefix ${prefix}/.. ABSOLUTE)
elseif(${dep} STREQUAL fmt)
get_target_property(fmt_include fmt::fmt INTERFACE_INCLUDE_DIRECTORIES)
get_filename_component(prefix ${fmt_include}/.. ABSOLUTE)
elseif(${dep} STREQUAL Flatbuffers)
if(TARGET flatbuffers::flatbuffers)
get_target_property(flatbuffers_include flatbuffers::flatbuffers INTERFACE_INCLUDE_DIRECTORIES)
else()
get_target_property(flatbuffers_include flatbuffers::flatbuffers_shared INTERFACE_INCLUDE_DIRECTORIES)
endif()
get_filename_component(prefix ${flatbuffers_include}/.. ABSOLUTE)
else() else()
get_filename_component(prefix ${${dep}_INCLUDE_DIR}/.. ABSOLUTE) get_filename_component(prefix ${${dep}_INCLUDE_DIR}/.. ABSOLUTE)
endif() endif()
message(STATUS " ${BWhite}${dep_padded}${CR}${version_padded}${prefix}") if(NOT ${dep}_BUNDLED)
message(STATUS " ${BWhite}${dep_padded}${CR}${version_padded}${prefix}")
endif()
unset(version_str) unset(version_str)
unset(version_padded) unset(version_padded)
unset(version_req_str) unset(version_req_str)
@@ -321,12 +364,6 @@ else()
set(tests_summary "${BRed} NO${CR} (enable with ${BMagenta}-DBUILD_TESTING=ON${CR})") set(tests_summary "${BRed} NO${CR} (enable with ${BMagenta}-DBUILD_TESTING=ON${CR})")
endif() endif()
message(STATUS " ${BWhite}tests${CR} ${tests_summary}") message(STATUS " ${BWhite}tests${CR} ${tests_summary}")
if(BUILD_NANOMSG_TRANSPORT)
set(nn_summary "${BGreen}YES${CR} (disable with ${BMagenta}-DBUILD_NANOMSG_TRANSPORT=OFF${CR})")
else()
set(nn_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_NANOMSG_TRANSPORT=ON${CR})")
endif()
message(STATUS " ${BWhite}nanomsg_transport${CR} ${nn_summary}")
if(BUILD_OFI_TRANSPORT) if(BUILD_OFI_TRANSPORT)
set(ofi_summary "${BGreen}YES${CR} EXPERIMENTAL (requires C++14) (disable with ${BMagenta}-DBUILD_OFI_TRANSPORT=OFF${CR})") set(ofi_summary "${BGreen}YES${CR} EXPERIMENTAL (requires C++14) (disable with ${BMagenta}-DBUILD_OFI_TRANSPORT=OFF${CR})")
else() else()
@@ -340,9 +377,9 @@ else()
endif() endif()
message(STATUS " ${BWhite}dds_plugin${CR} ${dds_summary}") message(STATUS " ${BWhite}dds_plugin${CR} ${dds_summary}")
if(BUILD_PMIX_PLUGIN) if(BUILD_PMIX_PLUGIN)
set(pmix_summary "${BGreen}YES${CR} (disable with ${BMagenta}-DBUILD_PMIX_PLUGIN=OFF${CR})") set(pmix_summary "${BGreen}YES${CR} EXPERIMENTAL (requires C++14) (disable with ${BMagenta}-DBUILD_PMIX_PLUGIN=OFF${CR})")
else() else()
set(pmix_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_PMIX_PLUGIN=ON${CR})") set(pmix_summary "${BRed} NO${CR} EXPERIMENTAL (requires C++14) (default, enable with ${BMagenta}-DBUILD_PMIX_PLUGIN=ON${CR})")
endif() endif()
message(STATUS " ${BWhite}pmix_plugin${CR} ${pmix_summary}") message(STATUS " ${BWhite}pmix_plugin${CR} ${pmix_summary}")
if(BUILD_EXAMPLES) if(BUILD_EXAMPLES)
@@ -358,11 +395,17 @@ else()
endif() endif()
message(STATUS " ${BWhite}docs${CR} ${docs_summary}") message(STATUS " ${BWhite}docs${CR} ${docs_summary}")
if(BUILD_SDK) if(BUILD_SDK)
set(sdk_summary "${BGreen}YES${CR} EXPERIMENTAL (disable with ${BMagenta}-DBUILD_SDK=OFF${CR})") set(sdk_summary "${BGreen}YES${CR} EXPERIMENTAL (required C++14) (disable with ${BMagenta}-DBUILD_SDK=OFF${CR})")
else() else()
set(sdk_summary "${BRed} NO${CR} EXPERIMENTAL (default, enable with ${BMagenta}-DBUILD_SDK=ON${CR})") set(sdk_summary "${BRed} NO${CR} EXPERIMENTAL (required C++14) (default, enable with ${BMagenta}-DBUILD_SDK=ON${CR})")
endif() endif()
message(STATUS " ${BWhite}sdk${CR} ${sdk_summary}") message(STATUS " ${BWhite}sdk${CR} ${sdk_summary}")
if(BUILD_SDK_COMMANDS)
set(sdk_commands_summary "${BGreen}YES${CR} (disable with ${BMagenta}-DBUILD_SDK_COMMANDS=OFF${CR})")
else()
set(sdk_commands_summary "${BRed} NO${CR} (default, enable with ${BMagenta}-DBUILD_SDK_COMMANDS=ON${CR})")
endif()
message(STATUS " ${BWhite}sdk_commands${CR} ${sdk_commands_summary}")
message(STATUS " ") message(STATUS " ")
if(RUN_STATIC_ANALYSIS) if(RUN_STATIC_ANALYSIS)
list(LENGTH PROJECT_STATIC_ANALYSERS size) list(LENGTH PROJECT_STATIC_ANALYSERS size)
@@ -384,6 +427,14 @@ if(RUN_STATIC_ANALYSIS)
else() else()
set(static_ana_summary "${BRed}OFF${CR} (default, enable with ${BMagenta}-DRUN_STATIC_ANALYSIS=ON${CR})") set(static_ana_summary "${BRed}OFF${CR} (default, enable with ${BMagenta}-DRUN_STATIC_ANALYSIS=ON${CR})")
endif() endif()
message(STATUS " ${Cyan}INSTALL PREFIX${CR} ${BGreen}${CMAKE_INSTALL_PREFIX}${CR} (change with ${BMagenta}-DCMAKE_INSTALL_PREFIX=...${CR})")
message(STATUS " ")
message(STATUS " ${Cyan}RUN STATIC ANALYSIS ${static_ana_summary}") message(STATUS " ${Cyan}RUN STATIC ANALYSIS ${static_ana_summary}")
message(STATUS " ") message(STATUS " ")
if(FAIRMQ_DEBUG_MODE)
message(STATUS " ${Cyan}DEBUG_MODE${CR} ${BGreen}${FAIRMQ_DEBUG_MODE}${CR} (disable with ${BMagenta}-DFAIRMQ_DEBUG_MODE=OFF${CR})")
else()
message(STATUS " ${Cyan}DEBUG_MODE${CR} ${BRed}${FAIRMQ_DEBUG_MODE}${CR} (enable with ${BMagenta}-DFAIRMQ_DEBUG_MODE=ON${CR})")
endif()
message(STATUS " ")
################################################################################ ################################################################################

View File

@@ -4,6 +4,7 @@ Eulisse, Giulio
Karabowicz, Radoslaw Karabowicz, Radoslaw
Kretz, Matthias <kretz@kde.org> Kretz, Matthias <kretz@kde.org>
Krzewicki, Mikolaj Krzewicki, Mikolaj
Lebedev, Andrey
Mrnjavac, Teo <teo.m@cern.ch> Mrnjavac, Teo <teo.m@cern.ch>
Neskovic, Gvozden Neskovic, Gvozden
Richter, Matthias Richter, Matthias

View File

@@ -15,6 +15,18 @@ Files: cmake/cotire.cmake
Copyright: 2012-2018 Sascha Kratky Copyright: 2012-2018 Sascha Kratky
License: COTIRE License: COTIRE
Files: extern/googletest
Copyright: 2008, Google Inc.
License: GOOGLE
Files: extern/asio
Copyright: 2003-2019, Christopher M. Kohlhoff (chris at kohlhoff dot com)
License: BSL-1.0
Files: extern/PicoSHA2
Copyright: 2017 okdshin
License: MIT
License: LGPL-3.0-only License: LGPL-3.0-only
[see LICENSE file] [see LICENSE file]
@@ -39,3 +51,77 @@ License: COTIRE
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. OTHER DEALINGS IN THE SOFTWARE.
License: GOOGLE
Copyright 2008, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License: BSL-1.0
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -65,7 +65,7 @@ if [ "$1" == "alfa_ci" ]; then
export ctest_model=Experimental export ctest_model=Experimental
elif [ "$1" == "codecov" ]; then elif [ "$1" == "codecov" ]; then
export ctest_model=Profile export ctest_model=Profile
export do_codecov_upload=1 export do_codecov_upload=0
else else
export ctest_model=$1 export ctest_model=$1
fi fi

View File

@@ -26,16 +26,17 @@ Set(configure_options "${configure_options};-DCTEST_USE_LAUNCHERS=${CTEST_USE_LA
Set(configure_options "${configure_options};-DDISABLE_COLOR=ON") Set(configure_options "${configure_options};-DDISABLE_COLOR=ON")
Set(configure_options "${configure_options};-DCMAKE_PREFIX_PATH=$ENV{SIMPATH}") Set(configure_options "${configure_options};-DCMAKE_PREFIX_PATH=$ENV{SIMPATH}")
Set(configure_options "${configure_options};-DBUILD_NANOMSG_TRANSPORT=ON")
# Set(configure_options "${configure_options};-DBUILD_OFI_TRANSPORT=ON") # Set(configure_options "${configure_options};-DBUILD_OFI_TRANSPORT=ON")
Set(configure_options "${configure_options};-DBUILD_DDS_PLUGIN=ON") Set(configure_options "${configure_options};-DBUILD_DDS_PLUGIN=ON")
Set(configure_options "${configure_options};-DBUILD_SDK=ON") Set(configure_options "${configure_options};-DBUILD_SDK=ON")
Set(configure_options "${configure_options};-DBUILD_SDK_COMMANDS=ON")
Set(configure_options "${configure_options};-DFAST_BUILD=ON") Set(configure_options "${configure_options};-DFAST_BUILD=ON")
Set(configure_options "${configure_options};-DCOTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES=-j$ENV{number_of_processors}") Set(configure_options "${configure_options};-DCOTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES=-j$ENV{number_of_processors}")
Set(configure_options "${configure_options};-DBoost_NO_BOOST_CMAKE=ON")
Set(EXTRA_FLAGS $ENV{EXTRA_FLAGS}) Set(EXTRA_FLAGS $ENV{EXTRA_FLAGS})
If(EXTRA_FLAGS) If(EXTRA_FLAGS)
Set(configure_options "${configure_options};${EXTRA_FLAGS}") Set(configure_options "${configure_options};${EXTRA_FLAGS}")
EndIf() EndIf()
If($ENV{ctest_model} MATCHES Profile) If($ENV{ctest_model} MATCHES Profile)
@@ -43,6 +44,7 @@ If($ENV{ctest_model} MATCHES Profile)
If(GCOV_COMMAND) If(GCOV_COMMAND)
Message("Found GCOV: ${GCOV_COMMAND}") Message("Found GCOV: ${GCOV_COMMAND}")
Set(CTEST_COVERAGE_COMMAND ${GCOV_COMMAND}) Set(CTEST_COVERAGE_COMMAND ${GCOV_COMMAND})
set(CTEST_COVERAGE_EXTRA_FLAGS "-p")
EndIf(GCOV_COMMAND) EndIf(GCOV_COMMAND)
EndIf() EndIf()
@@ -58,7 +60,7 @@ Ctest_Configure(BUILD "${CTEST_BINARY_DIRECTORY}"
Ctest_Build(BUILD "${CTEST_BINARY_DIRECTORY}") Ctest_Build(BUILD "${CTEST_BINARY_DIRECTORY}")
Ctest_Test(BUILD "${CTEST_BINARY_DIRECTORY}" Ctest_Test(BUILD "${CTEST_BINARY_DIRECTORY}"
# PARALLEL_LEVEL $ENV{number_of_processors} # PARALLEL_LEVEL $ENV{number_of_processors}
PARALLEL_LEVEL $ENV{number_of_processors} PARALLEL_LEVEL $ENV{number_of_processors}
RETURN_VALUE _ctest_test_ret_val RETURN_VALUE _ctest_test_ret_val
@@ -78,7 +80,7 @@ If("$ENV{do_codecov_upload}")
EndIf() EndIf()
Ctest_Submit() Ctest_Submit()
if (_ctest_test_ret_val) if (_ctest_test_ret_val)
Message(FATAL_ERROR "Some tests failed.") Message(FATAL_ERROR "Some tests failed.")
endif() endif()

27
Jenkinsfile vendored
View File

@@ -8,11 +8,15 @@ def jobMatrix(String prefix, List specs, Closure callback) {
def nodes = [:] def nodes = [:]
for (spec in specs) { for (spec in specs) {
def label = specToLabel(spec) def label = specToLabel(spec)
def node_tag = label
if (spec.os =~ /macOS/) {
node_tag = spec.os
}
def fairsoft = spec.fairsoft def fairsoft = spec.fairsoft
def os = spec.os def os = spec.os
def compiler = spec.compiler def compiler = spec.compiler
nodes["${prefix}/${label}"] = { nodes["${prefix}/${label}"] = {
node(label) { node(node_tag) {
githubNotify(context: "${prefix}/${label}", description: 'Building ...', status: 'PENDING') githubNotify(context: "${prefix}/${label}", description: 'Building ...', status: 'PENDING')
try { try {
deleteDir() deleteDir()
@@ -22,14 +26,14 @@ def jobMatrix(String prefix, List specs, Closure callback) {
echo "export SIMPATH=\${SIMPATH_PREFIX}${fairsoft}" >> Dart.cfg echo "export SIMPATH=\${SIMPATH_PREFIX}${fairsoft}" >> Dart.cfg
echo "export FAIRSOFT_VERSION=${fairsoft}" >> Dart.cfg echo "export FAIRSOFT_VERSION=${fairsoft}" >> Dart.cfg
""" """
if (os =~ /Debian/ && compiler =~ /gcc8/) { if (os =~ /Debian/ && compiler =~ /gcc9/) {
sh '''\ sh '''\
echo "source /etc/profile.d/modules.sh" >> Dart.cfg echo "source /etc/profile.d/modules.sh" >> Dart.cfg
echo "module use /cvmfs/it.gsi.de/modulefiles" >> Dart.cfg echo "module use /cvmfs/it.gsi.de/modulefiles" >> Dart.cfg
echo "module load compiler/gcc/8" >> Dart.cfg echo "module load compiler/gcc/9.1.0" >> Dart.cfg
''' '''
} }
if (os =~ /MacOS/) { if (os =~ /[Mm]acOS/) {
sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=clang++'\" >> Dart.cfg" sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=clang++'\" >> Dart.cfg"
} else { } else {
sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=g++'\" >> Dart.cfg" sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=g++'\" >> Dart.cfg"
@@ -49,6 +53,10 @@ def jobMatrix(String prefix, List specs, Closure callback) {
deleteDir() deleteDir()
githubNotify(context: "${prefix}/${label}", description: 'Success', status: 'SUCCESS') githubNotify(context: "${prefix}/${label}", description: 'Success', status: 'SUCCESS')
} catch (e) { } catch (e) {
def tarball = "${prefix}_${label}_dds_logs.tar.gz"
sh "tar czvf ${tarball} -C \${WORKSPACE}/build/test/ .DDS/"
archiveArtifacts tarball
deleteDir() deleteDir()
githubNotify(context: "${prefix}/${label}", description: 'Error', status: 'ERROR') githubNotify(context: "${prefix}/${label}", description: 'Error', status: 'ERROR')
throw e throw e
@@ -65,16 +73,15 @@ pipeline{
stage("Run CI Matrix") { stage("Run CI Matrix") {
steps{ steps{
script { script {
def build_jobs = jobMatrix('alfa-ci/build', [ def build_jobs = jobMatrix('build', [
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc8.1.0', fairsoft: 'fairmq_dev'], [os: 'Debian8', arch: 'x86_64', compiler: 'gcc9.1.0', fairsoft: 'fairmq_dev'],
[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'], [os: 'macOS10.15', arch: 'x86_64', compiler: 'AppleLLVM11.0.3', fairsoft: 'fairmq_dev'],
[os: 'MacOS10.14', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'],
]) { spec, label -> ]) { spec, label ->
sh './Dart.sh alfa_ci Dart.cfg' sh './Dart.sh alfa_ci Dart.cfg'
} }
def profile_jobs = jobMatrix('alfa-ci/codecov', [ def profile_jobs = jobMatrix('codecov', [
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc8.1.0', fairsoft: 'fairmq_dev'], [os: 'Debian8', arch: 'x86_64', compiler: 'gcc9.1.0', fairsoft: 'fairmq_dev'],
]) { spec, label -> ]) { spec, label ->
withCredentials([string(credentialsId: 'fairmq_codecov_token', variable: 'CODECOV_TOKEN')]) { withCredentials([string(credentialsId: 'fairmq_codecov_token', variable: 'CODECOV_TOKEN')]) {
sh './Dart.sh codecov Dart.cfg' sh './Dart.sh codecov Dart.cfg'

View File

@@ -21,11 +21,11 @@ def buildMatrix(List specs, Closure callback) {
echo "export SIMPATH=\${SIMPATH_PREFIX}${fairsoft}" >> Dart.cfg echo "export SIMPATH=\${SIMPATH_PREFIX}${fairsoft}" >> Dart.cfg
echo "export FAIRSOFT_VERSION=${fairsoft}" >> Dart.cfg echo "export FAIRSOFT_VERSION=${fairsoft}" >> Dart.cfg
""" """
if (os =~ /Debian/ && compiler =~ /gcc8/) { if (os =~ /Debian/ && compiler =~ /gcc9/) {
sh '''\ sh '''\
echo "source /etc/profile.d/modules.sh" >> Dart.cfg echo "source /etc/profile.d/modules.sh" >> Dart.cfg
echo "module use /cvmfs/it.gsi.de/modulefiles" >> Dart.cfg echo "module use /cvmfs/it.gsi.de/modulefiles" >> Dart.cfg
echo "module load compiler/gcc/8" >> Dart.cfg echo "module load compiler/gcc/9.1.0" >> Dart.cfg
''' '''
} }
if (os =~ /MacOS/) { if (os =~ /MacOS/) {
@@ -46,6 +46,10 @@ def buildMatrix(List specs, Closure callback) {
deleteDir() deleteDir()
} catch (e) { } catch (e) {
def tarball = "${label}_dds_logs.tar.gz"
sh "tar czvf ${tarball} -C \${WORKSPACE}/build/test/ .DDS/"
archiveArtifacts tarball
deleteDir() deleteDir()
throw e throw e
} }
@@ -63,7 +67,7 @@ pipeline{
steps{ steps{
script { script {
parallel(buildMatrix([ parallel(buildMatrix([
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc8.1.0', fairsoft: 'fairmq_dev'], [os: 'Debian8', arch: 'x86_64', compiler: 'gcc9.1.0', fairsoft: 'fairmq_dev'],
[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'], [os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'],
[os: 'MacOS10.14', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'], [os: 'MacOS10.14', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'],
]) { spec, label -> ]) { spec, label ->

View File

@@ -21,7 +21,7 @@ FairMQ is designed to help implementing large-scale data processing workflows ne
The core of FairMQ provides an abstract asynchronous message passing API with scalability protocols The core of FairMQ provides an abstract asynchronous message passing API with scalability protocols
inspired by [ZeroMQ](https://github.com/zeromq/libzmq) (e.g. PUSH/PULL, PUB/SUB). inspired by [ZeroMQ](https://github.com/zeromq/libzmq) (e.g. PUSH/PULL, PUB/SUB).
FairMQ provides multiple implementations for its API (so-called "transports", FairMQ provides multiple implementations for its API (so-called "transports",
e.g. `zeromq`, `shmem`, `nanomsg`, and `ofi` (in development)) to cover a variety of use cases e.g. `zeromq`, `shmem` and `ofi` (in development)) to cover a variety of use cases
(e.g. inter-thread, inter-process, inter-node communication) and machines (e.g. Ethernet, Infiniband). (e.g. inter-thread, inter-process, inter-node communication) and machines (e.g. Ethernet, Infiniband).
In addition to this core functionality FairMQ provides a framework for creating "devices" - actors which In addition to this core functionality FairMQ provides a framework for creating "devices" - actors which
are communicating through message passing. FairMQ does not only allow the user to use different transport but also to mix them; i.e: A Device can communicate using different transport on different channels at the same time. Device execution is modelled as a simple state machine that are communicating through message passing. FairMQ does not only allow the user to use different transport but also to mix them; i.e: A Device can communicate using different transport on different channels at the same time. Device execution is modelled as a simple state machine that
@@ -33,25 +33,21 @@ configuration and control services.
FairMQ has been developed in the context of its mother project [FairRoot](https://github.com/FairRootGroup/FairRoot) - FairMQ has been developed in the context of its mother project [FairRoot](https://github.com/FairRootGroup/FairRoot) -
a simulation, reconstruction and analysis framework. a simulation, reconstruction and analysis framework.
## Dependencies
* PUBLIC: [**Boost**](https://www.boost.org/), [**FairLogger**](https://github.com/FairRootGroup/FairLogger)
* BUILD: [CMake](https://cmake.org/), [GTest](https://github.com/google/googletest), [Doxygen](http://www.doxygen.org/)
* PRIVATE: [ZeroMQ](http://zeromq.org/), [Msgpack](https://msgpack.org/index.html), [nanomsg](http://nanomsg.org/),
[asiofi](https://github.com/FairRootGroup/asiofi), [DDS](http://dds.gsi.de), [PMIx](https://pmix.org/)
Supported platforms: Linux and MacOS.
## Installation from Source ## Installation from Source
Recommended:
```bash ```bash
git clone https://github.com/FairRootGroup/FairMQ fairmq git clone https://github.com/FairRootGroup/FairMQ fairmq_source
mkdir fairmq_build && cd fairmq_build cmake -S fairmq_source -B fairmq_build -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=fairmq_install
cmake -DCMAKE_INSTALL_PREFIX=./fairmq_install ../fairmq cmake --build fairmq_build
cmake --build . --target install cd fairmq_build; ctest -j4; cd ..
cmake --build fairmq_build --target install
``` ```
If dependencies are not installed in standard system directories, you can hint the installation location via `-DCMAKE_PREFIX_PATH=...` or per dependency via `-D{DEPENDENCY}_ROOT=...`. `{DEPENDENCY}` can be `GTEST`, `BOOST`, `FAIRLOGGER`, `ZEROMQ`, `MSGPACK`, `NANOMSG`, `OFI`, `PMIX`, `ASIOFI` or `DDS` (`*_ROOT` variables can also be environment variables). Please consult the [manpages of your CMake version](https://cmake.org/cmake/help/latest/manual/cmake.1.html) for more options.
If dependencies are not installed in standard system directories, you can hint the installation location via `-DCMAKE_PREFIX_PATH=...` or per dependency via `-D{DEPENDENCY}_ROOT=...`. `{DEPENDENCY}` can be `GTEST`, `BOOST`, `FAIRLOGGER`, `ZEROMQ`, `OFI`, `PMIX`, `ASIO`, `ASIOFI` or `DDS` (`*_ROOT` variables can also be environment variables).
## Usage ## Usage
@@ -70,30 +66,48 @@ find_package(FairMQ)
`find_package(FairMQ)` will define an imported target `FairMQ::FairMQ`. `find_package(FairMQ)` will define an imported target `FairMQ::FairMQ`.
In order to succesfully compile and link against the `FairMQ::FairMQ` target, you need to discover its public package dependencies, too. In order to succesfully compile and link against the `FairMQ::FairMQ` target, you need to discover its public package dependencies:
```cmake ```cmake
find_package(FairMQ) find_package(FairMQ)
if(FairMQ_FOUND) if(FairMQ_FOUND)
find_package(FairLogger ${FairMQ_FairLogger_VERSION}) foreach(dep IN LISTS FairMQ_PACKAGE_DEPENDENCIES)
find_package(Boost ${FairMQ_Boost_VERSION} COMPONENTS ${FairMQ_Boost_COMPONENTS}) if(FairMQ_${dep}_COMPONENTS)
find_package(${dep} ${FairMQ_${dep}_VERSION} COMPONENTS ${FairMQ_${dep}_COMPONENTS})
else()
find_package(${dep} ${FairMQ_${dep}_VERSION})
endif()
endforeach()
endif() endif()
``` ```
Of course, feel free to customize the above commands to your needs. If your project shares a dependency with FairMQ or if you want to omit a certain dependency, you may want to customize the above example code to your needs.
Optionally, you can require certain FairMQ package components and a minimum version: Optionally, you can require certain FairMQ package components and a minimum version:
```cmake ```cmake
find_package(FairMQ 1.1.0 COMPONENTS nanomsg_transport dds_plugin) find_package(FairMQ 1.1.0 COMPONENTS dds_plugin)
if(FairMQ_FOUND)
find_package(FairLogger ${FairMQ_FairLogger_VERSION})
find_package(Boost ${FairMQ_Boost_VERSION} COMPONENTS ${FairMQ_Boost_COMPONENTS})
endif()
``` ```
When building FairMQ, CMake will print a summary table of all available package components. When building FairMQ, CMake will print a summary table of all available package components.
## Dependencies
* [asio](https://github.com/chriskohlhoff/asio) (optionally bundled)
* [asiofi](https://github.com/FairRootGroup/asiofi)
* [Boost](https://www.boost.org/)
* [CMake](https://cmake.org/)
* [DDS](http://dds.gsi.de)
* [Doxygen](http://www.doxygen.org/)
* [FairLogger](https://github.com/FairRootGroup/FairLogger)
* [GTest](https://github.com/google/googletest) (optionally bundled)
* [PMIx](https://pmix.org/)
* [ZeroMQ](http://zeromq.org/)
Which dependencies are required depends on which components are built.
Supported platforms: Linux and MacOS.
## CMake options ## CMake options
On command line: On command line:
@@ -101,12 +115,11 @@ On command line:
* `-DDISABLE_COLOR=ON` disables coloured console output. * `-DDISABLE_COLOR=ON` disables coloured console output.
* `-DBUILD_TESTING=OFF` disables building of tests. * `-DBUILD_TESTING=OFF` disables building of tests.
* `-DBUILD_EXAMPLES=OFF` disables building of examples. * `-DBUILD_EXAMPLES=OFF` disables building of examples.
* `-DBUILD_NANOMSG_TRANSPORT=ON` enables building of nanomsg transport.
* `-DBUILD_OFI_TRANSPORT=ON` enables building of the experimental OFI transport. * `-DBUILD_OFI_TRANSPORT=ON` enables building of the experimental OFI transport.
* `-DBUILD_DDS_PLUGIN=ON` enables building of the DDS plugin. * `-DBUILD_DDS_PLUGIN=ON` enables building of the DDS plugin.
* `-DBUILD_PMIX_PLUGIN=ON` enables building of the PMIx plugin. * `-DBUILD_PMIX_PLUGIN=ON` enables building of the PMIx plugin.
* `-DBUILD_DOCS=ON` enables building of API docs. * `-DBUILD_DOCS=ON` enables building of API docs.
* You can hint non-system installations for dependent packages, see the #Installation section above * You can hint non-system installations for dependent packages, see the #installation-from-source section above
After the `find_package(FairMQ)` call the following CMake variables are defined: After the `find_package(FairMQ)` call the following CMake variables are defined:
@@ -165,4 +178,4 @@ After the `find_package(FairMQ)` call the following CMake variables are defined:
3. [Provided Plugins](docs/Plugins.md#73-provided-plugins) 3. [Provided Plugins](docs/Plugins.md#73-provided-plugins)
1. [DDS](docs/Plugins.md#731-dds) 1. [DDS](docs/Plugins.md#731-dds)
2. [PMIx](docs/Plugins.md#732-pmix) 2. [PMIx](docs/Plugins.md#732-pmix)
8. [Controller SDK](docs/SDK.md)

View File

@@ -36,4 +36,6 @@ set(CMAKE_MODULE_PATH ${@PROJECT_NAME@_CMAKEMODDIR} ${CMAKE_MODULE_PATH})
### Import targets ### Import targets
include(@PACKAGE_CMAKE_INSTALL_PREFIX@/@PACKAGE_INSTALL_DESTINATION@/@PROJECT_EXPORT_SET@.cmake) include(@PACKAGE_CMAKE_INSTALL_PREFIX@/@PACKAGE_INSTALL_DESTINATION@/@PROJECT_EXPORT_SET@.cmake)
@BUNDLED_PACKAGES@
@PACKAGE_COMPONENTS@ @PACKAGE_COMPONENTS@

View File

@@ -143,15 +143,17 @@ macro(set_fairmq_defaults)
set(PROJECT_EXPORT_SET ${PROJECT_NAME}Targets) set(PROJECT_EXPORT_SET ${PROJECT_NAME}Targets)
# Configure build types # Configure build types
set(CMAKE_CONFIGURATION_TYPES "Debug" "Release" "RelWithDebInfo" "Nightly" "Profile" "Experimental" "AdressSan" "ThreadSan") set(CMAKE_CONFIGURATION_TYPES "Debug" "Release" "RelWithDebInfo" "Nightly" "Profile" "Experimental" "AddressSan" "ThreadSan")
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wshadow -Wall -Wextra") set(_warnings "-Wshadow -Wall -Wextra -Wpedantic")
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g ${_warnings}")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -Wshadow -Wall -Wextra -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g ${_warnings} -DNDEBUG")
set(CMAKE_CXX_FLAGS_NIGHTLY "-O2 -g -Wshadow -Wall -Wextra") set(CMAKE_CXX_FLAGS_NIGHTLY "-O2 -g ${_warnings}")
set(CMAKE_CXX_FLAGS_PROFILE "-g3 -Wshadow -Wall -Wextra -fno-inline -ftest-coverage -fprofile-arcs") set(CMAKE_CXX_FLAGS_PROFILE "-g3 ${_warnings} -fno-inline -ftest-coverage -fprofile-arcs")
set(CMAKE_CXX_FLAGS_EXPERIMENTAL "-O2 -g -Wshadow -Wall -Wextra -DNDEBUG") set(CMAKE_CXX_FLAGS_EXPERIMENTAL "-O2 -g ${_warnings} -DNDEBUG")
set(CMAKE_CXX_FLAGS_ADRESSSAN "-O2 -g -Wshadow -Wall -Wextra -fsanitize=address -fno-omit-frame-pointer") set(CMAKE_CXX_FLAGS_ADDRESSSAN "-O2 -g ${_warnings} -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS_THREADSAN "-O2 -g -Wshadow -Wall -Wextra -fsanitize=thread") set(CMAKE_CXX_FLAGS_THREADSAN "-O2 -g ${_warnings} -fsanitize=thread")
unset(_warnings)
if(CMAKE_GENERATOR STREQUAL "Ninja" AND if(CMAKE_GENERATOR STREQUAL "Ninja" AND
((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR
@@ -194,6 +196,13 @@ macro(set_fairmq_defaults)
endif() endif()
list(APPEND PROJECT_STATIC_ANALYSERS "${analyser}") list(APPEND PROJECT_STATIC_ANALYSERS "${analyser}")
endif() endif()
if(CMAKE_GENERATOR STREQUAL Ninja AND ENABLE_CCACHE)
find_program(CCACHE ccache)
if(CCACHE)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
endif()
endif()
endmacro() endmacro()
function(join VALUES GLUE OUTPUT) function(join VALUES GLUE OUTPUT)
@@ -266,13 +275,30 @@ check_required_components(${PROJECT_NAME})
set(PACKAGE_COMPONENTS ${PACKAGE_COMPONENTS} PARENT_SCOPE) set(PACKAGE_COMPONENTS ${PACKAGE_COMPONENTS} PARENT_SCOPE)
endfunction() endfunction()
function(generate_bundled_packages)
if(asio_BUNDLED)
set(BUNDLED_PACKAGES "\
####### Expanded from @BUNDLED_PACKAGES@ by configure_package_config_file() #########
if(\"\${CMAKE_MAJOR_VERSION}.\${CMAKE_MINOR_VERSION}\" VERSION_LESS 3.11)
message(FATAL_ERROR \"CMake >= 3.11 required\")
endif()
set_target_properties(${PROJECT_NAME}::bundled_asio_headers PROPERTIES IMPORTED_GLOBAL TRUE)
add_library(asio::headers ALIAS ${PROJECT_NAME}::bundled_asio_headers)
set(asio_VERSION ${asio_VERSION})
")
endif()
set(BUNDLED_PACKAGES ${BUNDLED_PACKAGES} PARENT_SCOPE)
endfunction()
# Configure/Install CMake package # Configure/Install CMake package
macro(install_cmake_package) macro(install_cmake_package)
list(SORT PROJECT_PACKAGE_DEPENDENCIES) list(SORT PROJECT_PACKAGE_DEPENDENCIES)
list(SORT PROJECT_INTERFACE_PACKAGE_DEPENDENCIES) list(SORT PROJECT_INTERFACE_PACKAGE_DEPENDENCIES)
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
set(PACKAGE_INSTALL_DESTINATION set(PACKAGE_INSTALL_DESTINATION
${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_GIT_VERSION} ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION}
) )
if(BUILD_FAIRMQ) if(BUILD_FAIRMQ)
install(EXPORT ${PROJECT_EXPORT_SET} install(EXPORT ${PROJECT_EXPORT_SET}
@@ -288,6 +314,7 @@ macro(install_cmake_package)
) )
generate_package_dependencies() # fills ${PACKAGE_DEPENDENCIES} generate_package_dependencies() # fills ${PACKAGE_DEPENDENCIES}
generate_package_components() # fills ${PACKAGE_COMPONENTS} generate_package_components() # fills ${PACKAGE_COMPONENTS}
generate_bundled_packages() # fills ${BUNDLED_PACKAGES}
string(TOUPPER ${CMAKE_BUILD_TYPE} PROJECT_BUILD_TYPE_UPPER) string(TOUPPER ${CMAKE_BUILD_TYPE} PROJECT_BUILD_TYPE_UPPER)
set(PROJECT_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${PROJECT_BUILD_TYPE_UPPER}}) set(PROJECT_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${PROJECT_BUILD_TYPE_UPPER}})
configure_package_config_file( configure_package_config_file(
@@ -312,10 +339,11 @@ endmacro()
# #
# Wrapper around CMake's native find_package command to add some features and bookkeeping. # Wrapper around CMake's native find_package command to add some features and bookkeeping.
# #
# The qualifier (PRIVATE|PUBLIC|INTERFACE) to the package to populate # The qualifier (PRIVATE|PUBLIC|INTERFACE|BUNDLED) to the package to populate
# the variables PROJECT_[INTERFACE]_<pkgname>_([VERSION]|[COMPONENTS]|PACKAGE_DEPENDENCIES) # the variables PROJECT_[INTERFACE]_<pkgname>_([VERSION]|[COMPONENTS]|PACKAGE_DEPENDENCIES)
# accordingly. This bookkeeping information is used to print our dependency found summary # accordingly. This bookkeeping information is used to print our dependency found summary
# table and to generate a part of our CMake package. # table and to generate a part of our CMake package. BUNDLED decays to PUBLIC if the variable
# <pkgname>_BUNDLED is false and to PRIVATE otherwise.
# #
# When a dependending package is listed with ADD_REQUIREMENTS_OF the variables # When a dependending package is listed with ADD_REQUIREMENTS_OF the variables
# <dep_pkgname>_<pkgname>_VERSION|COMPONENTS are looked up to and added to the native # <dep_pkgname>_<pkgname>_VERSION|COMPONENTS are looked up to and added to the native
@@ -372,28 +400,151 @@ macro(find_package2 qualifier pkgname)
find_package(${pkgname} ${__version__} QUIET ${ARGS_UNPARSED_ARGUMENTS}) find_package(${pkgname} ${__version__} QUIET ${ARGS_UNPARSED_ARGUMENTS})
endif() endif()
if(${qualifier} STREQUAL BUNDLED)
if(${pkgname}_BUNDLED)
set(__qualifier__ PRIVATE)
else()
set(__qualifier__ PUBLIC)
endif()
else()
set(__qualifier__ ${qualifier})
endif()
if(${pkgname}_FOUND) if(${pkgname}_FOUND)
if(${qualifier} STREQUAL PRIVATE) if(${__qualifier__} STREQUAL PRIVATE)
set(PROJECT_${pkgname}_VERSION ${__version__}) set(PROJECT_${pkgname}_VERSION ${__version__})
set(PROJECT_${pkgname}_COMPONENTS ${__components__}) set(PROJECT_${pkgname}_COMPONENTS ${__components__})
set(PROJECT_PACKAGE_DEPENDENCIES ${PROJECT_PACKAGE_DEPENDENCIES} ${pkgname}) set(PROJECT_PACKAGE_DEPENDENCIES ${PROJECT_PACKAGE_DEPENDENCIES} ${pkgname})
elseif(${qualifier} STREQUAL PUBLIC) elseif(${__qualifier__} STREQUAL PUBLIC)
set(PROJECT_${pkgname}_VERSION ${__version__}) set(PROJECT_${pkgname}_VERSION ${__version__})
set(PROJECT_${pkgname}_COMPONENTS ${__components__}) set(PROJECT_${pkgname}_COMPONENTS ${__components__})
set(PROJECT_PACKAGE_DEPENDENCIES ${PROJECT_PACKAGE_DEPENDENCIES} ${pkgname}) set(PROJECT_PACKAGE_DEPENDENCIES ${PROJECT_PACKAGE_DEPENDENCIES} ${pkgname})
set(PROJECT_INTERFACE_${pkgname}_VERSION ${__version__}) set(PROJECT_INTERFACE_${pkgname}_VERSION ${__version__})
set(PROJECT_INTERFACE_${pkgname}_COMPONENTS ${__components__}) set(PROJECT_INTERFACE_${pkgname}_COMPONENTS ${__components__})
set(PROJECT_INTERFACE_PACKAGE_DEPENDENCIES ${PROJECT_INTERFACE_PACKAGE_DEPENDENCIES} ${pkgname}) set(PROJECT_INTERFACE_PACKAGE_DEPENDENCIES ${PROJECT_INTERFACE_PACKAGE_DEPENDENCIES} ${pkgname})
elseif(${qualifier} STREQUAL INTERFACE) elseif(${__qualifier__} STREQUAL INTERFACE)
set(PROJECT_INTERFACE_${pkgname}_VERSION ${__version__}) set(PROJECT_INTERFACE_${pkgname}_VERSION ${__version__})
set(PROJECT_INTERFACE_${pkgname}_COMPONENTS ${__components__}) set(PROJECT_INTERFACE_${pkgname}_COMPONENTS ${__components__})
set(PROJECT_INTERFACE_PACKAGE_DEPENDENCIES ${PROJECT_INTERFACE_PACKAGE_DEPENDENCIES} ${pkgname}) set(PROJECT_INTERFACE_PACKAGE_DEPENDENCIES ${PROJECT_INTERFACE_PACKAGE_DEPENDENCIES} ${pkgname})
endif() endif()
endif() endif()
unset(__qualifier__)
unset(__version__) unset(__version__)
unset(__components__) unset(__components__)
unset(__required_versions__) unset(__required_versions__)
set(CMAKE_PREFIX_PATH ${__old_cpp__}) set(CMAKE_PREFIX_PATH ${__old_cpp__})
unset(__old_cpp__) unset(__old_cpp__)
endmacro() endmacro()
macro(exec cmd)
join("${ARGN}" " " args)
file(APPEND ${${package}_BUILD_LOGFILE} ">>> ${cmd} ${args}\n")
execute_process(COMMAND ${cmd} ${ARGN}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
OUTPUT_VARIABLE log
ERROR_VARIABLE log
RESULT_VARIABLE res
)
file(APPEND ${${package}_BUILD_LOGFILE} ${log})
if(res)
message(FATAL_ERROR "${res} \nSee also \"${${package}_BUILD_LOGFILE}\"")
endif()
endmacro()
macro(exec_source cmd)
join("${ARGN}" " " args)
file(APPEND ${${package}_BUILD_LOGFILE} ">>> ${cmd} ${args}\n")
execute_process(COMMAND ${cmd} ${ARGN}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE log
ERROR_VARIABLE log
RESULT_VARIABLE res
)
file(APPEND ${${package}_BUILD_LOGFILE} ${log})
if(res)
message(FATAL_ERROR "${res} \nSee also \"${${package}_BUILD_LOGFILE}\"")
endif()
endmacro()
function(build_bundled package bundle)
message(STATUS "Building bundled ${package}")
set(${package}_SOURCE_DIR ${CMAKE_SOURCE_DIR}/${bundle})
set(${package}_BINARY_DIR ${CMAKE_BINARY_DIR}/${bundle})
file(MAKE_DIRECTORY ${${package}_BINARY_DIR})
set(${package}_BUILD_LOGFILE ${${package}_BINARY_DIR}/build.log)
file(REMOVE ${${package}_BUILD_LOGFILE})
if(Git_FOUND)
exec_source(${GIT_EXECUTABLE} submodule update --init -- ${${package}_SOURCE_DIR})
endif()
if(${package} STREQUAL GTest)
set(${package}_INSTALL_DIR ${CMAKE_BINARY_DIR}/${bundle}_install)
file(MAKE_DIRECTORY ${${package}_INSTALL_DIR})
set(${package}_ROOT ${${package}_INSTALL_DIR})
exec(${CMAKE_COMMAND} -S ${${package}_SOURCE_DIR} -B ${${package}_BINARY_DIR} -G ${CMAKE_GENERATOR}
-DCMAKE_INSTALL_PREFIX=${${package}_INSTALL_DIR} -DBUILD_GMOCK=OFF
)
exec(${CMAKE_COMMAND} --build ${${package}_BINARY_DIR})
exec(${CMAKE_COMMAND} --build ${${package}_BINARY_DIR} --target install)
elseif(${package} STREQUAL asio)
set(${package}_BUILD_INCLUDE_DIR ${${package}_SOURCE_DIR}/asio/include CACHE PATH "Bundled ${package} build-interface include dir")
set(${package}_INSTALL_INCLUDE_DIR ${PROJECT_INSTALL_INCDIR}/bundled CACHE PATH "Bundled ${package} install-interface include dir")
set(${package}_ROOT ${${package}_SOURCE_DIR}/asio)
elseif(${package} STREQUAL PicoSHA2)
set(${package}_ROOT ${${package}_SOURCE_DIR})
endif()
string(TOUPPER ${package} package_upper)
set(${package_upper}_ROOT "${${package}_ROOT}" CACHE PATH "Bundled ${package} install prefix search hint")
set(${package}_BUNDLED ON CACHE BOOL "Whether bundled ${package} was used")
message(STATUS "Building bundled ${package} - done")
endfunction()
macro(fairmq_build_option option description)
cmake_parse_arguments(ARGS "" "DEFAULT" "REQUIRES" ${ARGN})
if(ARGS_DEFAULT)
set(__default__ ON)
else()
set(__default__ OFF)
endif()
if(ARGS_REQUIRES)
include(CMakeDependentOption)
set(__requires__ ${ARGS_REQUIRES})
foreach(d ${__requires__})
string(REGEX REPLACE " +" ";" __requires_condition__ "${d}")
if(${__requires_condition__})
else()
if(${option})
message(FATAL_ERROR "Cannot enable build option ${option}, depending option is not set: ${__requires_condition__}")
endif()
endif()
endforeach()
else()
set(__requires__)
endif()
if(__requires__)
cmake_dependent_option(${option} ${description} ${__default__} "${__requires__}" OFF)
else()
option(${option} ${description} ${__default__})
endif()
set(__default__)
set(__requires__)
set(__requires_condition__)
set(ARGS_DEFAULT)
set(ARGS_REQUIRES)
set(option)
set(description)
endmacro()

21
cmake/FindPicoSHA2.cmake Normal file
View File

@@ -0,0 +1,21 @@
################################################################################
# Copyright (C) 2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
# copied verbatim in the file "LICENSE" #
################################################################################
find_path(PicoSHA2_INCLUDE_DIR NAMES picosha2.h)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(PicoSHA2
REQUIRED_VARS PicoSHA2_INCLUDE_DIR
)
if(PicoSHA2_FOUND)
add_library(PicoSHA2 INTERFACE IMPORTED)
set_target_properties(PicoSHA2 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${PicoSHA2_INCLUDE_DIR}"
)
endif()

53
cmake/Findasio.cmake Normal file
View File

@@ -0,0 +1,53 @@
################################################################################
# Copyright (C) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
# copied verbatim in the file "LICENSE" #
################################################################################
find_path(asio_INCLUDE_DIR
NAMES asio.hpp
PATH_SUFFIXES include
)
if(asio_INCLUDE_DIR)
find_file(asio_VERSION_HEADER "asio/version.hpp"
${asio_INCLUDE_DIR}
NO_DEFAULT_PATH
)
endif()
if(asio_VERSION_HEADER)
file(READ "${asio_VERSION_HEADER}" _asio_VERSION_HEADER_CONTENT)
string(REGEX MATCH "#define ASIO_VERSION ([0-9]+)" _MATCH "${_asio_VERSION_HEADER_CONTENT}")
set(asio_VERSION_MACRO ${CMAKE_MATCH_1})
math(EXPR asio_VERSION_MAJOR "${asio_VERSION_MACRO} / 100000")
math(EXPR asio_VERSION_MINOR "${asio_VERSION_MACRO} / 100 % 1000")
math(EXPR asio_VERSION_PATCH "${asio_VERSION_MACRO} % 100")
set(asio_VERSION "${asio_VERSION_MAJOR}.${asio_VERSION_MINOR}.${asio_VERSION_PATCH}")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(asio
REQUIRED_VARS asio_INCLUDE_DIR
VERSION_VAR asio_VERSION
HANDLE_COMPONENTS
)
if(asio_FOUND AND asio_BUNDLED)
add_library(bundled_asio_headers INTERFACE)
target_include_directories(bundled_asio_headers INTERFACE
$<BUILD_INTERFACE:${asio_BUILD_INCLUDE_DIR}>
$<INSTALL_INTERFACE:${asio_INSTALL_INCLUDE_DIR}>
)
add_library(asio::headers ALIAS bundled_asio_headers)
endif()
if(asio_FOUND AND NOT TARGET asio::headers)
add_library(asio::headers INTERFACE IMPORTED)
set_target_properties(asio::headers PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${asio_INCLUDE_DIR}"
)
endif()

View File

@@ -18,7 +18,7 @@ Topology configuration is currently happening via setup scripts. This is very ru
## 1.2 Communication Patterns ## 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. FairMQ devices communicate via the communication patterns offered by ZeroMQ: 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 ## 1.3 State Machine

34
docs/SDK.md Normal file
View File

@@ -0,0 +1,34 @@
← [Back](../README.md)
# 8. Controller SDK
The FairMQ Controller Software Development Kit (`-DBUILD_SDK=ON`) contains a (as of today still experimental) set of C++ APIs that provide essential functionality to the implementer of a global controller.
The FairMQ core library only provides two local controllers - `static` (a fixed sequence of state transitions) and `interactive` (a read-eval-print-loop which reads keyboard commands from standard input). A local controller only knows how steer a single [FairMQ device](Device.md) - in fact, it runs in a thread within the device process.
A global controller has knowledge about the full topology of connected FairMQ devices. Its responsibility is to facilitate the lifecycle of a distributed FairMQ-based application (*executing a topology*), such as
* allocating/releasing compute resources from a resource management system,
* launching/setting up the run-time environment and the FairMQ devices,
* driving the device state machines in lock-step across the full topology,
* pushing the device configuration,
* monitoring (some aspects of the application's) operation,
* and handling/reporting (some) error cases.
The low-level hook to integrate FairMQ devices with such a global contoller is the [plugin mechanism](Plugins.md) in the FairMQ core library. The FairMQ Controller SDK provides C++ APIs that communicate to the endpoints exposed by such a FairMQ plugin.
At the moment, the Controller SDK only supports [DDS](https://dds.gsi.de) as resource manager and run-time environment. A second implementation based on [PMIx](https://pmix.org/) (targeting its implementation in [Slurm](https://slurm.schedmd.com/documentation.html) and [OpenRTE](https://www-lb.open-mpi.org/papers/euro-pvmmpi-2005-orte/)) is in development.
The following section give a short overview on the APIs provided.
## RMS and run-time environment
The classes [`fair::mq::sdk::DDSEnvironment`](../fairmq/sdk/DDSEnvironment.h), [`fair::mq::sdk::DDSSession`](../fairmq/sdk/DDSSession.h), and [`fair::mq::sdk::DDSTopology`](../fairmq/sdk/DDSTopology.h) are thin wrappers of most of the synchronous APIs exposed by DDS ([`dds::tools_api`](http://dds.gsi.de/doc/api-docs/DDS/html/namespacedds_1_1tools__api.html) and [`dds::topology_api`](http://dds.gsi.de/doc/api-docs/DDS/html/namespacedds_1_1topology__api.html)). E.g. they allow to [start a DDS session](https://github.com/FairRootGroup/FairMQ/blob/077eb0ef691940d764cfd1852bf3981dc812ddbd/main.cpp#L26-L28), [allocate resources](https://github.com/FairRootGroup/FairMQ/blob/077eb0ef691940d764cfd1852bf3981dc812ddbd/main.cpp#L34) and [launch a topology](https://github.com/FairRootGroup/FairMQ/blob/077eb0ef691940d764cfd1852bf3981dc812ddbd/main.cpp#L39) from a C++ program.
## Driving the global state machine
The class [`fair::mq::sdk::Topology`](../fairmq/sdk/Topology.h) adds a FairMQ-specific view on an existing DDS session that is executing a topology of FairMQ devices. One can e.g. [initiate a state transition on all devices in the topology simultaneously](https://github.com/FairRootGroup/FairMQ/blob/077eb0ef691940d764cfd1852bf3981dc812ddbd/main.cpp#L48-L49). This topology transition completes once a topology-wide barrier is passed (all devices completed the transition). This effectively exposes the device state machine as a topology state machine. The implementation is based on remote procedure calls over the [DDS intercom service](http://dds.gsi.de/doc/api-docs/DDS/html/namespacedds_1_1intercom__api.html) between the controller and the DDS plugin shipped with FairMQ (`-DBUILD_DDS_PLUGIN=ON`).
For future versions of the SDK new APIs are planned to inspect and modify the device configurations and also operate only on subsets of a given topology.
← [Back](../README.md)

View File

@@ -2,7 +2,7 @@
# 2. Transport Interface # 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. The communication layer is available through the transport interface. Three interface implementations are currently available. Main implementation uses the [ZeroMQ](http://zeromq.org) library. Second transport implementation is using shared memory via boost::interprocess & ZeroMQ combination.
Here is an overview to give an idea how the interface is implemented: Here is an overview to give an idea how the interface is implemented:
@@ -10,20 +10,20 @@ Here is an overview to give an idea how the interface is implemented:
Currently, the transports have been tested to work with these communication patterns: Currently, the transports have been tested to work with these communication patterns:
| | zeromq | nanomsg | shmem | | | zeromq | shmem |
| ------------- |--------| ------- | ----- | | ------------- |--------| ----- |
| PAIR | yes | yes | yes | | PAIR | yes | yes |
| PUSH/PULL | yes | yes | yes | | PUSH/PULL | yes | yes |
| PUB/SUB | yes | yes | no | | PUB/SUB | yes | no |
| REQ/REP | yes | yes | yes | | REQ/REP | yes | yes |
The next table shows the supported address types for each transport implementation: The next table shows the supported address types for each transport implementation:
| | zeromq | nanomsg | shmem | comment | | | zeromq | shmem | comment |
| ----------- | ------ | ------- | ----- | --------------------------------------------- | | ----------- | ------ | ----- | --------------------------------------------- |
| `inproc://` | yes | yes | yes | in process: useful for unit testing | | `inproc://` | yes | yes | in process: useful for unit testing |
| `ipc://` | yes | yes | yes | inter process comm: useful on single machine | | `ipc://` | yes | yes | inter process comm: useful on single machine |
| `tcp://` | yes | yes | yes | useful for any communication, local or remote | | `tcp://` | yes | yes | useful for any communication, local or remote |
## 2.1 Message ## 2.1 Message

View File

@@ -34,11 +34,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-1-1.sh.in ${CMAKE_CURRENT_BIN
add_test(NAME Example.1-1.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh zeromq) add_test(NAME Example.1-1.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh zeromq)
set_tests_properties(Example.1-1.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ") set_tests_properties(Example.1-1.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
if(BUILD_NANOMSG_TRANSPORT)
add_test(NAME Example.1-1.nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh nanomsg)
set_tests_properties(Example.1-1.nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
endif()
add_test(NAME Example.1-1.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh shmem) add_test(NAME Example.1-1.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-1.sh shmem)
set_tests_properties(Example.1-1.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ") set_tests_properties(Example.1-1.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")

View File

@@ -6,9 +6,6 @@
* copied verbatim in the file "LICENSE" * * copied verbatim in the file "LICENSE" *
********************************************************************************/ ********************************************************************************/
#include <thread> // this_thread::sleep_for
#include <chrono>
#include "Sampler.h" #include "Sampler.h"
using namespace std; using namespace std;
@@ -20,8 +17,7 @@ Sampler::Sampler()
: fText() : fText()
, fMaxIterations(0) , fMaxIterations(0)
, fNumIterations(0) , fNumIterations(0)
{ {}
}
void Sampler::InitTask() void Sampler::InitTask()
{ {
@@ -35,25 +31,22 @@ bool Sampler::ConditionalRun()
// create a copy of the data with new(), that will be deleted after the transfer is complete // create a copy of the data with new(), that will be deleted after the transfer is complete
string* text = new string(fText); string* text = new string(fText);
// create message object with a pointer to the data buffer, // create message object with a pointer to the data buffer, its size,
// its size,
// custom deletion function (called when transfer is done), // custom deletion function (called when transfer is done),
// and pointer to the object managing the data buffer // and pointer to the object managing the data buffer
FairMQMessagePtr msg(NewMessage(const_cast<char*>(text->c_str()), FairMQMessagePtr msg(NewMessage(
text->length(), const_cast<char*>(text->c_str()),
[](void* /*data*/, void* object) { delete static_cast<string*>(object); }, text->length(),
text)); [](void* /*data*/, void* object) { delete static_cast<string*>(object); },
text));
LOG(info) << "Sending \"" << fText << "\""; LOG(info) << "Sending \"" << fText << "\"";
// in case of error or transfer interruption, return false to go to IDLE state // in case of error or transfer interruption, return false to go to the Ready state
// successfull transfer will return number of bytes transfered (can be 0 if sending an empty message). // successfull transfer will return number of bytes transfered (can be 0 if sending an empty message).
if (Send(msg, "data") < 0) if (Send(msg, "data") < 0) {
{
return false; return false;
} } else if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) {
else if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations)
{
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state."; LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
return false; return false;
} }
@@ -61,8 +54,6 @@ bool Sampler::ConditionalRun()
return true; return true;
} }
Sampler::~Sampler() Sampler::~Sampler() {}
{
}
} // namespace example_1_1 } // namespace example_1_1

View File

@@ -33,23 +33,22 @@ void Sink::InitTask()
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations"); fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
} }
// handler is called whenever a message arrives on "data", with a reference to the message and a sub-channel index (here 0) // handler is called whenever a message arrives on "data", with a reference to the message and a
// sub-channel index (here 0)
bool Sink::HandleData(FairMQMessagePtr& msg, int /*index*/) bool Sink::HandleData(FairMQMessagePtr& msg, int /*index*/)
{ {
LOG(info) << "Received: \"" << string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\""; LOG(info) << "Received: \"" << string(static_cast<char*>(msg->GetData()), msg->GetSize()) << "\"";
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) {
{
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state."; LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
return false; return false;
} }
// return true if want to be called again (otherwise return false go to IDLE state) // return true if you want the handler to be called again (otherwise return false go to the
// Ready state)
return true; return true;
} }
Sink::~Sink() Sink::~Sink() {}
{
}
} // namespace example_1_1 } // namespace example_1_1

View File

@@ -42,11 +42,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-1-n-1.sh.in ${CMAKE_CURRENT_B
add_test(NAME Example.1-n-1.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh zeromq) add_test(NAME Example.1-n-1.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh zeromq)
set_tests_properties(Example.1-n-1.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ") set_tests_properties(Example.1-n-1.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
if(BUILD_NANOMSG_TRANSPORT)
add_test(NAME Example.1-n-1.nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh nanomsg)
set_tests_properties(Example.1-n-1.nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")
endif()
add_test(NAME Example.1-n-1.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh shmem) add_test(NAME Example.1-n-1.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-1-n-1.sh shmem)
set_tests_properties(Example.1-n-1.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ") set_tests_properties(Example.1-n-1.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received: ")

View File

@@ -13,9 +13,9 @@ add_subdirectory(copypush)
add_subdirectory(dds) add_subdirectory(dds)
add_subdirectory(multipart) add_subdirectory(multipart)
add_subdirectory(multiple-channels) add_subdirectory(multiple-channels)
if(BUILD_NANOMSG_TRANSPORT) add_subdirectory(multiple-transports)
add_subdirectory(multiple-transports) add_subdirectory(n-m)
endif() add_subdirectory(qc)
add_subdirectory(readout) add_subdirectory(readout)
add_subdirectory(region) add_subdirectory(region)
add_subdirectory(req-rep) add_subdirectory(req-rep)

View File

@@ -6,41 +6,50 @@ Set of FairMQ examples. More examples that combine FairMQ with FairRoot can be f
A simple topology of two devices - **Sampler** and **Sink**. **Sampler** sends data to **Sink** with the **PUSH-PULL** pattern. A simple topology of two devices - **Sampler** and **Sink**. **Sampler** sends data to **Sink** with the **PUSH-PULL** pattern.
## 1-n-1 ## 1-n-1
A simple topology of three device types - **Sampler**, **Processor** and **Sink**. **Sampler** sends data to one or more **Processor**s, who modify the data and send it to one **Sink**. Transport with the **PUSH-PULL** pattern. The example also shows the configuration via JSON files, as oposed to `--channel-config` that is used by other examples. A simple topology of three device types - **Sampler**, **Processor** and **Sink**. **Sampler** sends data to one or more **Processor**s, who modify the data and send it to one **Sink**. Transport with the **PUSH-PULL** pattern. The example also shows the configuration via JSON files, as oposed to `--channel-config` that is used by other examples.
## Built-in devices
## DDS Usage of generic devies provided with FairMQ.
This example demonstrates usage of the Dynamic Deployment System ([DDS](http://dds.gsi.de/)) to dynamically deploy and configure a topology of devices. The topology is similar to those of Example 2, but now it can be easily distributed on different computing nodes without the need for manual reconfiguration of the devices.
## Copy & Push ## Copy & Push
A topology consisting of one **Sampler** and two **Sink**s. The **Sampler** uses the `Copy` method to send the same data to both sinks with the **PUSH-PULL** pattern. In countrary to the **PUB-SUB** pattern, this ensures that all receivers are connected and no data is lost, but requires additional channels to be configured. A topology consisting of one **Sampler** and two **Sink**s. The **Sampler** uses the `Copy` method to send the same data to both sinks with the **PUSH-PULL** pattern. In countrary to the **PUB-SUB** pattern, this ensures that all receivers are connected and no data is lost, but requires additional channels to be configured.
## DDS
## Request & Reply This example demonstrates usage of the Dynamic Deployment System ([DDS](http://dds.gsi.de/)) to dynamically deploy and configure a topology of devices. The topology is similar to those of Example 2, but now it can be easily distributed on different computing nodes without the need for manual reconfiguration of the devices.
This topology contains two devices that communicate with each other via the **REQ-REP** pettern. Bidirectional communication via a single socket. ## Multipart
This example shows how to send a multipart message from one device to the other. (two parts message parts - header and body).
## Multiple Channels ## Multiple Channels
This example demonstrates how to work with multiple channels and multiplex between them. This example demonstrates how to work with multiple channels and multiplex between them.
## Multiple Transports
## Sending Multipart messages This examples shows how to combine different channel transports (zeromq/shmem) inside of one device and/or topology.
This example shows how to send a multipart message from one device to the other. (two parts message parts - header and body). ## n-m
A topology consisting of three layers of devices: synchronizer -> n * senders -> m * receivers.
## Multiple Transports example ## QC
This examples shows how to combine different channel transports (zeromq/nanomsg/shmem) inside of one device and/or topology. A topology consisting of 4 devices - Sampler, QCDispatcher, QCTask and Sink. The data flows from Sampler through QCDispatcher to Sink. On demand - by setting the corresponding configuration property - the QCDispatcher device will duplicate the data to the QCTask device. The property is set by the topology controller, in this example this is the `fairmq-dds-command-ui` utility.
## Region example ## Readout
Two example topologies of setups to be distributed to two kinds of nodes - detector readout node and processing node. Detector readout node contains readout process, data builder and data sender (and optionally an additional processor), while processing node contains data receiver devices. communication within readout nodes is done via unmanaged region through shared memory transport.
## Region
This example demonstrates the use of a more advanced feature - UnmanagedRegion, that can be used to create a buffer through one of FairMQ transports. The contents of this buffer are managed by the user, who can also create messages out of sub-buffers of the created buffer. Such feature can be interesting in environments that have special requirements by the hardware that writes the data, to keep the transfer efficient (e.g. shared memory). This example demonstrates the use of a more advanced feature - UnmanagedRegion, that can be used to create a buffer through one of FairMQ transports. The contents of this buffer are managed by the user, who can also create messages out of sub-buffers of the created buffer. Such feature can be interesting in environments that have special requirements by the hardware that writes the data, to keep the transfer efficient (e.g. shared memory).
## Request & Reply
This topology contains two devices that communicate with each other via the **REQ-REP** pettern. Bidirectional communication via a single socket.

View File

@@ -17,22 +17,12 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-builtin-devices.sh.in ${CMAKE
add_test(NAME Example.BuiltinDevices.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh zeromq) add_test(NAME Example.BuiltinDevices.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh zeromq)
set_tests_properties(Example.BuiltinDevices.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached") set_tests_properties(Example.BuiltinDevices.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
if(BUILD_NANOMSG_TRANSPORT)
add_test(NAME Example.BuiltinDevices.nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh nanomsg)
set_tests_properties(Example.BuiltinDevices.nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
endif()
add_test(NAME Example.BuiltinDevices.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh shmem) add_test(NAME Example.BuiltinDevices.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh shmem)
set_tests_properties(Example.BuiltinDevices.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached") set_tests_properties(Example.BuiltinDevices.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
add_test(NAME Example.BuiltinDevices.multipart.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh zeromq true 2) add_test(NAME Example.BuiltinDevices.multipart.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh zeromq true 2)
set_tests_properties(Example.BuiltinDevices.multipart.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached") set_tests_properties(Example.BuiltinDevices.multipart.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
if(BUILD_NANOMSG_TRANSPORT)
add_test(NAME Example.BuiltinDevices.multipart.nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh nanomsg true 2)
set_tests_properties(Example.BuiltinDevices.multipart.nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")
endif()
add_test(NAME Example.BuiltinDevices.multipart.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh shmem true 2) add_test(NAME Example.BuiltinDevices.multipart.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-builtin-devices.sh shmem true 2)
set_tests_properties(Example.BuiltinDevices.multipart.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached") set_tests_properties(Example.BuiltinDevices.multipart.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Configured maximum number of iterations reached")

View File

@@ -35,11 +35,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-copypush.sh.in ${CMAKE_CURREN
add_test(NAME Example.CopyPush.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh zeromq) add_test(NAME Example.CopyPush.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh zeromq)
set_tests_properties(Example.CopyPush.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message: ") set_tests_properties(Example.CopyPush.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message: ")
if(BUILD_NANOMSG_TRANSPORT)
add_test(NAME Example.CopyPush.nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh nanomsg)
set_tests_properties(Example.CopyPush.nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message: ")
endif()
add_test(NAME Example.CopyPush.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh shmem) add_test(NAME Example.CopyPush.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-copypush.sh shmem)
set_tests_properties(Example.CopyPush.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message: ") set_tests_properties(Example.CopyPush.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message: ")

View File

@@ -7,12 +7,12 @@
################################################################################ ################################################################################
add_library(ExampleDDSLib STATIC add_library(ExampleDDSLib STATIC
"Sampler.cxx" "Sampler.cxx"
"Sampler.h" "Sampler.h"
"Processor.cxx" "Processor.cxx"
"Processor.h" "Processor.h"
"Sink.cxx" "Sink.cxx"
"Sink.h" "Sink.h"
) )
target_link_libraries(ExampleDDSLib PUBLIC FairMQ) target_link_libraries(ExampleDDSLib PUBLIC FairMQ)
@@ -28,7 +28,8 @@ target_link_libraries(fairmq-ex-dds-sink PRIVATE ExampleDDSLib)
add_custom_target(ExampleDDS DEPENDS fairmq-ex-dds-sampler fairmq-ex-dds-processor fairmq-ex-dds-sink) add_custom_target(ExampleDDS DEPENDS fairmq-ex-dds-sampler fairmq-ex-dds-processor fairmq-ex-dds-sink)
set(BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}:${CMAKE_BINARY_DIR}/fairmq/plugins/DDS) list(JOIN Boost_LIBRARY_DIRS ":" LIB_DIR)
set(BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}:${CMAKE_BINARY_DIR}/fairmq/sdk)
set(DATA_DIR ${CMAKE_CURRENT_BINARY_DIR}) set(DATA_DIR ${CMAKE_CURRENT_BINARY_DIR})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-dds-topology.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology.xml @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-dds-topology.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology.xml @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-dds-topology-infinite.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology-infinite.xml @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-dds-topology-infinite.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology-infinite.xml @ONLY)
@@ -37,17 +38,25 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-ex-dds-env.sh ${CMAKE_CURRENT_
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-dds.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-dds.sh @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-dds.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-dds.sh @ONLY)
# test # test
if(DDS_FOUND)
add_test(NAME Example.DDS.localhost COMMAND ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-dds.sh localhost)
set_tests_properties(Example.DDS.localhost PROPERTIES
TIMEOUT 15
RUN_SERIAL true
PASS_REGULAR_EXPRESSION "Example successful"
)
endif()
# install # install
install( install(
TARGETS TARGETS
fairmq-ex-dds-sampler fairmq-ex-dds-sampler
fairmq-ex-dds-processor fairmq-ex-dds-processor
fairmq-ex-dds-sink fairmq-ex-dds-sink
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR} LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR} RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
) )
# configure run script with different executable paths for build and for install directories # configure run script with different executable paths for build and for install directories
@@ -59,30 +68,30 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-ex-dds-env.sh ${CMAKE_CURRENT_
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-dds.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-dds.sh_install @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-dds.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-dds.sh_install @ONLY)
install( install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology.xml_install FILES ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology.xml_install
DESTINATION ${PROJECT_INSTALL_DATADIR} DESTINATION ${PROJECT_INSTALL_DATADIR}
RENAME ex-dds-topology.xml RENAME ex-dds-topology.xml
) )
install( install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology-infinite.xml_install FILES ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-topology-infinite.xml_install
DESTINATION ${PROJECT_INSTALL_DATADIR} DESTINATION ${PROJECT_INSTALL_DATADIR}
RENAME ex-dds-topology-infinite.xml RENAME ex-dds-topology-infinite.xml
) )
install( install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-hosts.cfg FILES ${CMAKE_CURRENT_BINARY_DIR}/ex-dds-hosts.cfg
DESTINATION ${PROJECT_INSTALL_DATADIR} DESTINATION ${PROJECT_INSTALL_DATADIR}
) )
install( install(
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-ex-dds-env.sh_install PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-ex-dds-env.sh_install
DESTINATION ${PROJECT_INSTALL_BINDIR} DESTINATION ${PROJECT_INSTALL_BINDIR}
RENAME fairmq-ex-dds-env.sh RENAME fairmq-ex-dds-env.sh
) )
install( install(
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-dds.sh_install PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-dds.sh_install
DESTINATION ${PROJECT_INSTALL_BINDIR} DESTINATION ${PROJECT_INSTALL_BINDIR}
RENAME fairmq-start-ex-dds.sh RENAME fairmq-start-ex-dds.sh
) )

View File

@@ -1,43 +1,43 @@
<topology name="ExampleDDS"> <topology name="ExampleDDS">
<property name="data1" /> <property name="fmqchan_data1" />
<property name="data2" /> <property name="fmqchan_data2" />
<declrequirement name="SamplerWorker" type="wnname" value="sampler"/> <declrequirement name="SamplerWorker" type="wnname" value="sampler"/>
<declrequirement name="ProcessorWorker" type="wnname" value="processor"/> <declrequirement name="ProcessorWorker" type="wnname" value="processor"/>
<declrequirement name="SinkWorker" type="wnname" value="sink"/> <declrequirement name="SinkWorker" type="wnname" value="sink"/>
<decltask name="Sampler"> <decltask name="Sampler">
<exe>fairmq-ex-dds-sampler --color false --channel-config name=data1,type=push,method=bind --rate 100 -P dds</exe>
<env reachable="false">fairmq-ex-dds-env.sh</env> <env reachable="false">fairmq-ex-dds-env.sh</env>
<exe>fairmq-ex-dds-sampler --id sampler --color false --channel-config name=data1,type=push,method=bind --rate 100 -P dds</exe>
<requirements> <requirements>
<name>SamplerWorker</name> <name>SamplerWorker</name>
</requirements> </requirements>
<properties> <properties>
<name access="write">data1</name> <name access="write">fmqchan_data1</name>
</properties> </properties>
</decltask> </decltask>
<decltask name="Processor"> <decltask name="Processor">
<exe>fairmq-ex-dds-processor --color false --channel-config name=data1,type=pull,method=connect name=data2,type=push,method=connect -P dds</exe>
<env reachable="false">fairmq-ex-dds-env.sh</env> <env reachable="false">fairmq-ex-dds-env.sh</env>
<exe>fairmq-ex-dds-processor --id processor_%taskIndex% --color false --channel-config name=data1,type=pull,method=connect name=data2,type=push,method=connect -P dds</exe>
<requirements> <requirements>
<id>ProcessorWorker</id> <name>ProcessorWorker</name>
</requirements> </requirements>
<properties> <properties>
<name access="read">data1</name> <name access="read">fmqchan_data1</name>
<name access="read">data2</name> <name access="read">fmqchan_data2</name>
</properties> </properties>
</decltask> </decltask>
<decltask name="Sink"> <decltask name="Sink">
<exe>fairmq-ex-dds-sink --color false --channel-config name=data2,type=pull,method=bind -P dds</exe>
<env reachable="false">fairmq-ex-dds-env.sh</env> <env reachable="false">fairmq-ex-dds-env.sh</env>
<exe>fairmq-ex-dds-sink --id sink --color false --channel-config name=data2,type=pull,method=bind -P dds</exe>
<requirements> <requirements>
<name>SinkWorker</name> <name>SinkWorker</name>
</requirements> </requirements>
<properties> <properties>
<name access="write">data2</name> <name access="write">fmqchan_data2</name>
</properties> </properties>
</decltask> </decltask>

View File

@@ -1,43 +1,43 @@
<topology name="ExampleDDS"> <topology name="ExampleDDS">
<property name="data1" /> <property name="fmqchan_data1" />
<property name="data2" /> <property name="fmqchan_data2" />
<declrequirement name="SamplerWorker" type="wnname" value="sampler"/> <declrequirement name="SamplerWorker" type="wnname" value="sampler"/>
<declrequirement name="ProcessorWorker" type="wnname" value="processor"/> <declrequirement name="ProcessorWorker" type="wnname" value="processor"/>
<declrequirement name="SinkWorker" type="wnname" value="sink"/> <declrequirement name="SinkWorker" type="wnname" value="sink"/>
<decltask name="Sampler"> <decltask name="Sampler">
<exe>fairmq-ex-dds-sampler --color false --channel-config name=data1,type=push,method=bind -P dds --iterations 10</exe>
<env reachable="false">fairmq-ex-dds-env.sh</env> <env reachable="false">fairmq-ex-dds-env.sh</env>
<exe>fairmq-ex-dds-sampler --id sampler --color false --channel-config name=data1,type=push,method=bind -P dds --iterations 10</exe>
<requirements> <requirements>
<name>SamplerWorker</name> <name>SamplerWorker</name>
</requirements> </requirements>
<properties> <properties>
<name access="write">data1</name> <name access="write">fmqchan_data1</name>
</properties> </properties>
</decltask> </decltask>
<decltask name="Processor"> <decltask name="Processor">
<exe>fairmq-ex-dds-processor --color false --channel-config name=data1,type=pull,method=connect name=data2,type=push,method=connect -P dds</exe>
<env reachable="false">fairmq-ex-dds-env.sh</env> <env reachable="false">fairmq-ex-dds-env.sh</env>
<exe>fairmq-ex-dds-processor --id processor_%taskIndex% --color false --channel-config name=data1,type=pull,method=connect name=data2,type=push,method=connect -P dds</exe>
<requirements> <requirements>
<id>ProcessorWorker</id> <name>ProcessorWorker</name>
</requirements> </requirements>
<properties> <properties>
<name access="read">data1</name> <name access="read">fmqchan_data1</name>
<name access="read">data2</name> <name access="read">fmqchan_data2</name>
</properties> </properties>
</decltask> </decltask>
<decltask name="Sink"> <decltask name="Sink">
<exe>fairmq-ex-dds-sink --color false --channel-config name=data2,type=pull,method=bind -P dds --iterations 10</exe>
<env reachable="false">fairmq-ex-dds-env.sh</env> <env reachable="false">fairmq-ex-dds-env.sh</env>
<exe>fairmq-ex-dds-sink --id sink --color false --channel-config name=data2,type=pull,method=bind -P dds --iterations 10</exe>
<requirements> <requirements>
<name>SinkWorker</name> <name>SinkWorker</name>
</requirements> </requirements>
<properties> <properties>
<name access="write">data2</name> <name access="write">fmqchan_data2</name>
</properties> </properties>
</decltask> </decltask>

View File

@@ -9,3 +9,8 @@
################################################################################ ################################################################################
export PATH=@BIN_DIR@:$PATH export PATH=@BIN_DIR@:$PATH
OS=$(uname -s 2>&1)
if [ "$OS" == "Darwin" ]; then
export DYLD_LIBRARY_PATH=@LIB_DIR@:$DYLD_LIBRARY_PATH
fi

View File

@@ -30,56 +30,56 @@ echo "SESSION ID: ${DDS_SESSION_ID}"
trap "cleanup ${DDS_SESSION_ID}" EXIT trap "cleanup ${DDS_SESSION_ID}" EXIT
requiredNofAgents=12 requiredNofSlots=12
if [[ "$plugin" == "ssh" ]]; then if [[ "$plugin" == "ssh" ]]; then
dds-submit -r ${plugin} -c @DATA_DIR@/ex-dds-hosts.cfg dds-submit -r ${plugin} -c @DATA_DIR@/ex-dds-hosts.cfg
else else
dds-submit -r ${plugin} -n ${requiredNofAgents} dds-submit -r ${plugin} --slots ${requiredNofSlots}
fi fi
echo "...waiting for ${requiredNofAgents} idle agents..." echo "...waiting for ${requiredNofSlots} idle slots..."
dds-info --wait-for-idle-agents ${requiredNofAgents} dds-info --idle-count --wait ${requiredNofSlots}
topologyFile=@DATA_DIR@/ex-dds-topology.xml export FAIRMQ_DDS_TOPO_FILE=@DATA_DIR@/ex-dds-topology.xml
echo "TOPOLOGY FILE: ${topologyFile}" echo "TOPOLOGY FILE: ${FAIRMQ_DDS_TOPO_FILE}"
# TODO Uncomment once DDS 2.6 is released echo "TOPOLOGY NAME: $(dds-topology --disable-validation --topology-name ${FAIRMQ_DDS_TOPO_FILE})"
# echo "TOPOLOGY NAME: $(dds-topology --disable-validation --topology-name ${topologyFile})"
# TODO Uncomment once DDS 2.6 is released dds-info --active-topology
# dds-info --active-topology dds-topology --activate ${FAIRMQ_DDS_TOPO_FILE}
dds-topology --disable-validation --activate ${topologyFile} dds-info --active-topology
# dds-info --active-topology echo "...waiting for ${requiredNofSlots} executing slots..."
# dds-info --wait-for-executing-agents ${requiredNofAgents} dds-info --executing-count --wait ${requiredNofSlots}
sleep 1
echo "------------------------" echo "------------------------"
echo "...waiting for Topology to finish..." echo "...waiting for Topology to finish..."
# TODO Retrieve number of devices from DDS topology API instead of having the user pass it explicitely # TODO Retrieve number of devices from DDS topology API instead of having the user pass it explicitely
fairmq-dds-command-ui -w "IDLE" -n ${requiredNofAgents} fairmq-dds-command-ui -w "IDLE"
fairmq-dds-command-ui -c i -w "INITIALIZING DEVICE" -n ${requiredNofAgents} fairmq-dds-command-ui -c i
fairmq-dds-command-ui -c k -w "INITIALIZED" -n ${requiredNofAgents} fairmq-dds-command-ui -c k
fairmq-dds-command-ui -c b -w "BOUND" -n ${requiredNofAgents} fairmq-dds-command-ui -c b
fairmq-dds-command-ui -c x -w "DEVICE READY" -n ${requiredNofAgents} fairmq-dds-command-ui -c x
fairmq-dds-command-ui -c j -w "READY" -n ${requiredNofAgents} fairmq-dds-command-ui -c j
fairmq-dds-command-ui -c r fairmq-dds-command-ui -c r
sampler_and_sink="main/(Sampler|Sink)" sampler_and_sink="main/(Sampler|Sink).*"
fairmq-dds-command-ui -p $sampler_and_sink -w "RUNNING->READY" -n 2 fairmq-dds-command-ui -w "RUNNING->READY" -p $sampler_and_sink
echo "...$sampler_and_sink are READY, sending shutdown..." echo "...$sampler_and_sink are READY, sending shutdown..."
fairmq-dds-command-ui -c s -w "RUNNING->READY" -n ${requiredNofAgents} fairmq-dds-command-ui -c s
fairmq-dds-command-ui -c t -w "DEVICE READY" -n ${requiredNofAgents} fairmq-dds-command-ui -c t
fairmq-dds-command-ui -c d -w "IDLE" -n ${requiredNofAgents} fairmq-dds-command-ui -c d
fairmq-dds-command-ui -c q fairmq-dds-command-ui -c q
echo "...waiting for ${requiredNofAgents} idle agents..." echo "...waiting for ${requiredNofSlots} idle slots..."
dds-info --wait-for-idle-agents ${requiredNofAgents} dds-info --idle-count --wait ${requiredNofSlots}
echo "------------------------" echo "------------------------"
# TODO Uncomment once DDS 2.6 is released dds-info --active-topology
# dds-info --active-topology
dds-topology --stop dds-topology --stop
# dds-info --active-topology dds-info --active-topology
dds-agent-cmd getlog -a dds-agent-cmd getlog -a
logDir="${wrkDir}/logs" logDir="${wrkDir}/logs"
for file in $(find "${logDir}" -name "*.tar.gz"); do tar -xf ${file} -C "${logDir}" ; done for file in $(find "${logDir}" -name "*.tar.gz"); do tar -xf ${file} -C "${logDir}" ; done
echo "AGENT LOG FILES IN: ${logDir}" echo "AGENT LOG FILES IN: ${logDir}"
# This string is used by ctest to detect success
echo "Example successful :)"
# Cleanup function is called by EXIT trap # Cleanup function is called by EXIT trap

View File

@@ -32,19 +32,14 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multipart.sh.in ${CMA
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-multipart.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-multipart.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh)
add_test(NAME Example.Multipart.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh zeromq) add_test(NAME Example.Multipart.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh zeromq)
set_tests_properties(Example.Multipart.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 5 parts") set_tests_properties(Example.Multipart.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 7 parts")
if(BUILD_NANOMSG_TRANSPORT)
add_test(NAME Example.Multipart.nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh nanomsg)
set_tests_properties(Example.Multipart.nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 5 parts")
endif()
add_test(NAME Example.Multipart.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh shmem) add_test(NAME Example.Multipart.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh shmem)
set_tests_properties(Example.Multipart.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 5 parts") set_tests_properties(Example.Multipart.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 7 parts")
if(BUILD_OFI_TRANSPORT) if(BUILD_OFI_TRANSPORT)
add_test(NAME Example.Multipart.ofi COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh ofi) add_test(NAME Example.Multipart.ofi COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multipart.sh ofi)
set_tests_properties(Example.Multipart.ofi PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 5 parts") set_tests_properties(Example.Multipart.ofi PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received message with 7 parts")
endif() endif()
# install # install

View File

@@ -40,8 +40,7 @@ bool Sampler::ConditionalRun()
header.stopFlag = 0; header.stopFlag = 0;
// Set stopFlag to 1 for last message. // Set stopFlag to 1 for last message.
if (fMaxIterations > 0 && fNumIterations == fMaxIterations - 1) if (fMaxIterations > 0 && fNumIterations == fMaxIterations - 1) {
{
header.stopFlag = 1; header.stopFlag = 1;
} }
LOG(info) << "Sending header with stopFlag: " << header.stopFlag; LOG(info) << "Sending header with stopFlag: " << header.stopFlag;
@@ -60,13 +59,20 @@ bool Sampler::ConditionalRun()
assert(auxData.Size() == 0); assert(auxData.Size() == 0);
assert(parts.Size() == 5); assert(parts.Size() == 5);
parts.AddPart(NewMessage());
assert(parts.Size() == 6);
parts.AddPart(NewMessage(100));
assert(parts.Size() == 7);
LOG(info) << "Sending body of size: " << parts.At(1)->GetSize(); LOG(info) << "Sending body of size: " << parts.At(1)->GetSize();
Send(parts, "data"); Send(parts, "data");
// Go out of the sending loop if the stopFlag was sent. // Go out of the sending loop if the stopFlag was sent.
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) {
{
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state."; LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
return false; return false;
} }
@@ -77,8 +83,4 @@ bool Sampler::ConditionalRun()
return true; return true;
} }
Sampler::~Sampler()
{
}
} // namespace example_multipart } // namespace example_multipart

View File

@@ -24,7 +24,7 @@ class Sampler : public FairMQDevice
{ {
public: public:
Sampler(); Sampler();
virtual ~Sampler(); virtual ~Sampler() {}
protected: protected:
virtual void InitTask(); virtual void InitTask();

View File

@@ -20,23 +20,28 @@ using namespace std;
namespace example_multipart namespace example_multipart
{ {
Sink::Sink()
{
OnData("data", &Sink::HandleData);
}
bool Sink::HandleData(FairMQParts& parts, int /*index*/) bool Sink::HandleData(FairMQParts& parts, int /*index*/)
{ {
LOG(info) << "Received message with " << parts.Size() << " parts";
Header header; Header header;
header.stopFlag = (static_cast<Header*>(parts.At(0)->GetData()))->stopFlag; header.stopFlag = (static_cast<Header*>(parts.At(0)->GetData()))->stopFlag;
LOG(info) << "Received message with " << parts.Size() << " parts"; LOG(info) << "Received part 1 (header) with stopFlag: " << header.stopFlag;
LOG(info) << "Received part 2 of size: " << parts.At(1)->GetSize();
assert(parts.At(1)->GetSize() == 1000);
LOG(info) << "Received part 3 of size: " << parts.At(2)->GetSize();
assert(parts.At(2)->GetSize() == 500);
LOG(info) << "Received part 4 of size: " << parts.At(3)->GetSize();
assert(parts.At(3)->GetSize() == 600);
LOG(info) << "Received part 5 of size: " << parts.At(4)->GetSize();
assert(parts.At(4)->GetSize() == 700);
LOG(info) << "Received part 6 of size: " << parts.At(5)->GetSize();
assert(parts.At(5)->GetSize() == 0);
LOG(info) << "Received part 7 of size: " << parts.At(6)->GetSize();
assert(parts.At(6)->GetSize() == 100);
LOG(info) << "Received header with stopFlag: " << header.stopFlag; if (header.stopFlag == 1) {
LOG(info) << "Received body of size: " << parts.At(1)->GetSize();
if (header.stopFlag == 1)
{
LOG(info) << "stopFlag is 1, going IDLE"; LOG(info) << "stopFlag is 1, going IDLE";
return false; return false;
} }
@@ -44,8 +49,4 @@ bool Sink::HandleData(FairMQParts& parts, int /*index*/)
return true; return true;
} }
Sink::~Sink()
{
}
} }

View File

@@ -23,8 +23,8 @@ namespace example_multipart
class Sink : public FairMQDevice class Sink : public FairMQDevice
{ {
public: public:
Sink(); Sink() { OnData("data", &Sink::HandleData); }
virtual ~Sink(); virtual ~Sink() {}
protected: protected:
bool HandleData(FairMQParts&, int); bool HandleData(FairMQParts&, int);

View File

@@ -2,12 +2,24 @@
export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@ export FAIRMQ_PATH=@FAIRMQ_BIN_DIR@
transport="zeromq"
if [[ $1 =~ ^[a-z]+$ ]]; then
transport=$1
fi
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/fairmq-uuid-gen -h)"
SAMPLER="fairmq-ex-multipart-sampler" SAMPLER="fairmq-ex-multipart-sampler"
SAMPLER+=" --id sampler1" SAMPLER+=" --id sampler1"
SAMPLER+=" --transport $transport"
SAMPLER+=" --session $SESSION"
SAMPLER+=" --channel-config name=data,type=push,method=connect,rateLogging=0,address=tcp://127.0.0.1:5555" SAMPLER+=" --channel-config name=data,type=push,method=connect,rateLogging=0,address=tcp://127.0.0.1:5555"
xterm -geometry 80x23+0+0 -hold -e @EX_BIN_DIR@/$SAMPLER & xterm -geometry 80x23+0+0 -hold -e @EX_BIN_DIR@/$SAMPLER &
SINK="fairmq-ex-multipart-sink" SINK="fairmq-ex-multipart-sink"
SINK+=" --id sink1" SINK+=" --id sink1"
SINK+=" --transport $transport"
SINK+=" --session $SESSION"
SINK+=" --channel-config name=data,type=pull,method=bind,rateLogging=0,address=tcp://127.0.0.1:5555" SINK+=" --channel-config name=data,type=pull,method=bind,rateLogging=0,address=tcp://127.0.0.1:5555"
xterm -geometry 80x23+500+0 -hold -e @EX_BIN_DIR@/$SINK & xterm -geometry 80x23+500+0 -hold -e @EX_BIN_DIR@/$SINK &

View File

@@ -20,7 +20,7 @@ SAMPLER+=" --verbosity veryhigh"
SAMPLER+=" --session $SESSION" SAMPLER+=" --session $SESSION"
SAMPLER+=" --max-iterations 1" SAMPLER+=" --max-iterations 1"
SAMPLER+=" --control static --color false" SAMPLER+=" --control static --color false"
SAMPLER+=" --channel-config name=data,type=pair,method=connect,rateLogging=0,address=tcp://127.0.0.1:5555" SAMPLER+=" --channel-config name=data,type=pair,method=connect,rateLogging=0,address=tcp://127.0.0.1:5555,linger=1000"
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER & @CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
SAMPLER_PID=$! SAMPLER_PID=$!

View File

@@ -39,11 +39,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-multiple-channels.sh.in ${CMA
add_test(NAME Example.MultipleChannels.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-channels.sh zeromq) add_test(NAME Example.MultipleChannels.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-channels.sh zeromq)
set_tests_properties(Example.MultipleChannels.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received messages from both sources.") set_tests_properties(Example.MultipleChannels.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received messages from both sources.")
if(BUILD_NANOMSG_TRANSPORT)
add_test(NAME Example.MultipleChannels.nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-channels.sh nanomsg)
set_tests_properties(Example.MultipleChannels.nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received messages from both sources.")
endif()
# install # install
install( install(

View File

@@ -1,12 +1,12 @@
Multiple Transports example Multiple Transports example
=========================== ===========================
This example demonstrates use of multiple transports (zeromq/nanomsg/shmem) within the same topology and/or device. It is a simple topology consisting of two samplers and a sink. The devices are connected via 3 channels: This example demonstrates use of multiple transports (zeromq/shmem) within the same topology and/or device. It is a simple topology consisting of two samplers and a sink. The devices are connected via 3 channels:
![Multiple Transports example](../../docs/images/example_multiple_transports.png?raw=true "Multiple Transports example") ![Multiple Transports example](../../docs/images/example_multiple_transports.png?raw=true "Multiple Transports example")
Each device has main transport that it uses. By default it is ZeroMQ, and can be overriden via the `--transport` cmd option. The device will initialize additional transports if any of the channels have them configured (e.g. as an option to `--channel-config`). Each device has main transport that it uses. By default it is ZeroMQ, and can be overriden via the `--transport` cmd option. The device will initialize additional transports if any of the channels have them configured (e.g. as an option to `--channel-config`).
In this example sampler1 and sink are started with `--transport shmem`, making shared memory their main transport, sampler2 with `--transport nanomsg`. Additionally, the ack channel is configured to use zeromq as its transport. In this example sampler1 and sink are started with `--transport shmem`, making shared memory their main transport, sampler2 with `--transport zeromq`. Additionally, the ack channel is configured to use zeromq as its transport.
The main two things that a transport does is transfer of data and allocation of memory for the messages. By default, new messages are created via the main device transport. If a message has been created with one transport and is to be transferred with another, it has to be copied into a new message of the target transport. This happens automatically behind the scenes. To avoid this copy the device can create messages via `NewMessageFor(const string& channelName, int subChannelIndex, ...)` method, that creates the messages via the transport of the given channel (check sampler1 and sink for an example) or as the channel directly to create a message. The main two things that a transport does is transfer of data and allocation of memory for the messages. By default, new messages are created via the main device transport. If a message has been created with one transport and is to be transferred with another, it has to be copied into a new message of the target transport. This happens automatically behind the scenes. To avoid this copy the device can create messages via `NewMessageFor(const string& channelName, int subChannelIndex, ...)` method, that creates the messages via the transport of the given channel (check sampler1 and sink for an example) or as the channel directly to create a message.

View File

@@ -13,7 +13,7 @@ xterm -geometry 80x30+0+0 -hold -e @EX_BIN_DIR@/$SAMPLER1 &
SAMPLER2="fairmq-ex-multiple-transports-sampler2" SAMPLER2="fairmq-ex-multiple-transports-sampler2"
SAMPLER2+=" --id sampler2" SAMPLER2+=" --id sampler2"
SAMPLER2+=" --severity debug" SAMPLER2+=" --severity debug"
SAMPLER2+=" --transport nanomsg" SAMPLER2+=" --transport shmem"
SAMPLER2+=" --channel-config name=data2,type=push,method=bind,address=tcp://127.0.0.1:5556" SAMPLER2+=" --channel-config name=data2,type=push,method=bind,address=tcp://127.0.0.1:5556"
xterm -geometry 80x30+0+450 -hold -e @EX_BIN_DIR@/$SAMPLER2 & xterm -geometry 80x30+0+450 -hold -e @EX_BIN_DIR@/$SAMPLER2 &
@@ -22,6 +22,6 @@ SINK+=" --id sink1"
SINK+=" --severity debug" SINK+=" --severity debug"
SINK+=" --transport shmem" SINK+=" --transport shmem"
SINK+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:5555" SINK+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:5555"
SINK+=" name=data2,type=pull,method=connect,address=tcp://127.0.0.1:5556,transport=nanomsg" SINK+=" name=data2,type=pull,method=connect,address=tcp://127.0.0.1:5556,transport=shmem"
SINK+=" name=ack,type=pub,method=connect,address=tcp://127.0.0.1:5557,transport=zeromq" SINK+=" name=ack,type=pub,method=connect,address=tcp://127.0.0.1:5557,transport=zeromq"
xterm -geometry 80x30+500+225 -hold -e @EX_BIN_DIR@/$SINK & xterm -geometry 80x30+500+225 -hold -e @EX_BIN_DIR@/$SINK &

View File

@@ -14,7 +14,7 @@ SINK+=" --max-iterations 1"
SINK+=" --control static --color false" SINK+=" --control static --color false"
SINK+=" --transport shmem" SINK+=" --transport shmem"
SINK+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:5555" SINK+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:5555"
SINK+=" name=data2,type=pull,method=connect,address=tcp://127.0.0.1:5556,transport=nanomsg" SINK+=" name=data2,type=pull,method=connect,address=tcp://127.0.0.1:5556,transport=zeromq"
SINK+=" name=ack,type=pub,method=connect,address=tcp://127.0.0.1:5557,transport=zeromq" SINK+=" name=ack,type=pub,method=connect,address=tcp://127.0.0.1:5557,transport=zeromq"
@CMAKE_CURRENT_BINARY_DIR@/$SINK & @CMAKE_CURRENT_BINARY_DIR@/$SINK &
SINK_PID=$! SINK_PID=$!
@@ -37,7 +37,7 @@ SAMPLER2+=" --session $SESSION"
SAMPLER2+=" --verbosity veryhigh" SAMPLER2+=" --verbosity veryhigh"
SAMPLER2+=" --max-iterations 1" SAMPLER2+=" --max-iterations 1"
SAMPLER2+=" --control static --color false" SAMPLER2+=" --control static --color false"
SAMPLER2+=" --transport nanomsg" SAMPLER2+=" --transport zeromq"
SAMPLER2+=" --channel-config name=data2,type=push,method=bind,address=tcp://127.0.0.1:5556" SAMPLER2+=" --channel-config name=data2,type=push,method=bind,address=tcp://127.0.0.1:5556"
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER2 & @CMAKE_CURRENT_BINARY_DIR@/$SAMPLER2 &
SAMPLER2_PID=$! SAMPLER2_PID=$!

View File

@@ -0,0 +1,99 @@
################################################################################
# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
# copied verbatim in the file "LICENSE" #
################################################################################
add_executable(fairmq-ex-n-m-synchronizer runSynchronizer.cxx)
target_link_libraries(fairmq-ex-n-m-synchronizer PRIVATE FairMQ)
add_executable(fairmq-ex-n-m-sender runSender.cxx)
target_link_libraries(fairmq-ex-n-m-sender PRIVATE FairMQ)
add_executable(fairmq-ex-n-m-receiver runReceiver.cxx)
target_link_libraries(fairmq-ex-n-m-receiver PRIVATE FairMQ)
add_custom_target(ExampleNM DEPENDS fairmq-ex-n-m-synchronizer fairmq-ex-n-m-sender fairmq-ex-n-m-receiver)
list(JOIN Boost_LIBRARY_DIRS ":" LIB_DIR)
set(BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}:${CMAKE_BINARY_DIR}/fairmq/sdk)
set(DATA_DIR ${CMAKE_CURRENT_BINARY_DIR})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-n-m-topology.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-n-m-topology.xml @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-n-m-pair-topology.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-n-m-pair-topology.xml @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-ex-n-m-env.sh ${CMAKE_CURRENT_BINARY_DIR}/fairmq-ex-n-m-env.sh @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-n-m.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m.sh @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-n-m-pair.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m-pair.sh @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-n-m-dds.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m-dds.sh @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-n-m-pair-dds.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m-pair-dds.sh @ONLY)
# test
if(DDS_FOUND)
add_test(NAME Example.N-M.localhost COMMAND ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m-dds.sh localhost)
set_tests_properties(Example.N-M.localhost PROPERTIES TIMEOUT 15 RUN_SERIAL true PASS_REGULAR_EXPRESSION "Example successful")
add_test(NAME Example.N-M-pair.localhost COMMAND ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m-pair-dds.sh localhost)
set_tests_properties(Example.N-M-pair.localhost PROPERTIES TIMEOUT 15 RUN_SERIAL true PASS_REGULAR_EXPRESSION "Example successful")
endif()
# install
install(
TARGETS
fairmq-ex-n-m-synchronizer
fairmq-ex-n-m-sender
fairmq-ex-n-m-receiver
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
)
# configure run script with different executable paths for build and for install directories
set(BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
set(DATA_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_DATADIR})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-n-m-topology.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-n-m-topology.xml_install @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-n-m-pair-topology.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-n-m-pair-topology.xml_install @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-ex-n-m-env.sh ${CMAKE_CURRENT_BINARY_DIR}/fairmq-ex-n-m-env.sh_install @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-n-m.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m.sh_install @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-n-m-pair.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m-pair.sh_install @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-n-m-dds.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m-dds.sh_install @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-n-m-pair-dds.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m-pair-dds.sh_install @ONLY)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/ex-n-m-topology.xml_install
DESTINATION ${PROJECT_INSTALL_DATADIR}
RENAME ex-n-m-topology.xml
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/ex-n-m-pair-topology.xml_install
DESTINATION ${PROJECT_INSTALL_DATADIR}
RENAME ex-n-m-pair-topology.xml
)
install(
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-ex-n-m-env.sh_install
DESTINATION ${PROJECT_INSTALL_BINDIR}
RENAME fairmq-ex-n-m-env.sh
)
install(
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m.sh_install
DESTINATION ${PROJECT_INSTALL_BINDIR}
RENAME fairmq-start-ex-n-m.sh
)
install(
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m-pair.sh_install
DESTINATION ${PROJECT_INSTALL_BINDIR}
RENAME fairmq-start-ex-n-m-pair.sh
)
install(
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m-dds.sh_install
DESTINATION ${PROJECT_INSTALL_BINDIR}
RENAME fairmq-start-ex-n-m-dds.sh
)
install(
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-n-m-pair-dds.sh_install
DESTINATION ${PROJECT_INSTALL_BINDIR}
RENAME fairmq-start-ex-n-m-pair-dds.sh
)

View File

@@ -5,31 +5,20 @@
* GNU Lesser General Public Licence (LGPL) version 3, * * GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" * * copied verbatim in the file "LICENSE" *
********************************************************************************/ ********************************************************************************/
#ifndef FAIR_MQ_EXAMPLE_N_M_HEADER_H
#define FAIR_MQ_EXAMPLE_N_M_HEADER_H
#include "FairMQUnmanagedRegionNN.h" #include <cstdint>
#include "FairMQLogger.h"
using namespace std; namespace example_n_m
FairMQUnmanagedRegionNN::FairMQUnmanagedRegionNN(const size_t size, FairMQRegionCallback callback, const std::string& /*path = "" */, int /*flags = 0 */)
: fBuffer(malloc(size))
, fSize(size)
, fCallback(callback)
{ {
}
void* FairMQUnmanagedRegionNN::GetData() const struct Header
{ {
return fBuffer; std::uint16_t id;
} int senderIndex;
};
size_t FairMQUnmanagedRegionNN::GetSize() const } // namespace example_n_m
{
return fSize;
}
FairMQUnmanagedRegionNN::~FairMQUnmanagedRegionNN() #endif /* FAIR_MQ_EXAMPLE_N_M_HEADER_H */
{
LOG(debug) << "destroying region";
free(fBuffer);
}

4
examples/n-m/README.md Normal file
View File

@@ -0,0 +1,4 @@
N-M
==========================
A topology consisting of three layers of devices: synchronizer -> sender(s) -> receiver(s). Senders distribute data to receivers based on the data id contained in the message from the synchronizer (same id goes to the same receiver from every sender). The senders send the data in a non-blocking fashion - if queue is full or receiver is down, data is discarded. Two configurations are provided - one using push/pull channels between senders/receivers, another using pair channels. In push/pull case there is only one receiving channel on the receiver device. In pair case there are as many receiver (sub-)channels as there are senders.

View File

@@ -0,0 +1,44 @@
<topology name="myTopology">
<var name="numSenders" value="3" />
<var name="numReceivers" value="4" />
<property name="fmqchan_sync" />
<property name="fmqchan_data" />
<decltask name="Synchronizer">
<exe reachable="true">fairmq-ex-n-m-synchronizer --id sync --rate 100 --color false -P dds --channel-config name=sync,type=pub,method=bind</exe>
<env reachable="false">fairmq-ex-n-m-env.sh</env>
<properties>
<name access="write">fmqchan_sync</name>
</properties>
</decltask>
<decltask name="Sender">
<exe reachable="true">fairmq-ex-n-m-sender --id sender%taskIndex% --timeframe-size 100000 --num-receivers ${numReceivers} --color false -P dds --channel-config name=sync,type=sub,method=connect name=data,type=pair,method=connect,numSockets=${numReceivers} --dds-i data:%taskIndex%</exe>
<env reachable="false">fairmq-ex-n-m-env.sh</env>
<properties>
<name access="read">fmqchan_sync</name>
<name access="read">fmqchan_data</name>
</properties>
</decltask>
<decltask name="Receiver">
<exe reachable="true">fairmq-ex-n-m-receiver --id receiver%taskIndex% --num-senders ${numSenders} --color false -P dds --max-timeframes 10 --channel-config name=data,type=pair,method=bind,numSockets=${numSenders}</exe>
<env reachable="false">fairmq-ex-n-m-env.sh</env>
<properties>
<name access="write">fmqchan_data</name>
</properties>
</decltask>
<main name="main">
<task>Synchronizer</task>
<group name="Senders" n="${numSenders}">
<task>Sender</task>
</group>
<group name="Receivers" n="${numReceivers}">
<task>Receiver</task>
</group>
</main>
</topology>

View File

@@ -0,0 +1,44 @@
<topology name="myTopology">
<var name="numSenders" value="3" />
<var name="numReceivers" value="4" />
<property name="fmqchan_sync" />
<property name="fmqchan_data" />
<decltask name="Synchronizer">
<exe reachable="true">fairmq-ex-n-m-synchronizer --id sync --rate 100 --color false -P dds --channel-config name=sync,type=pub,method=bind</exe>
<env reachable="false">fairmq-ex-n-m-env.sh</env>
<properties>
<name access="write">fmqchan_sync</name>
</properties>
</decltask>
<decltask name="Sender">
<exe reachable="true">fairmq-ex-n-m-sender --id sender%taskIndex% --timeframe-size 100000 --num-receivers ${numReceivers} --color false -P dds --channel-config name=sync,type=sub,method=connect name=data,type=push,method=connect,numSockets=${numReceivers}</exe>
<env reachable="false">fairmq-ex-n-m-env.sh</env>
<properties>
<name access="read">fmqchan_sync</name>
<name access="read">fmqchan_data</name>
</properties>
</decltask>
<decltask name="Receiver">
<exe reachable="true">fairmq-ex-n-m-receiver --id receiver%taskIndex% --num-senders ${numSenders} --color false -P dds --max-timeframes 10 --channel-config name=data,type=pull,method=bind</exe>
<env reachable="false">fairmq-ex-n-m-env.sh</env>
<properties>
<name access="write">fmqchan_data</name>
</properties>
</decltask>
<main name="main">
<task>Synchronizer</task>
<group name="Senders" n="${numSenders}">
<task>Sender</task>
</group>
<group name="Receivers" n="${numReceivers}">
<task>Receiver</task>
</group>
</main>
</topology>

View File

@@ -0,0 +1,16 @@
#!/bin/bash
################################################################################
# Copyright (C) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
# copied verbatim in the file "LICENSE" #
################################################################################
export PATH=@BIN_DIR@:$PATH
OS=$(uname -s 2>&1)
if [ "$OS" == "Darwin" ]; then
export DYLD_LIBRARY_PATH=@LIB_DIR@:$DYLD_LIBRARY_PATH
fi

View File

@@ -0,0 +1,76 @@
#!/bin/bash
################################################################################
# Copyright (C) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
# copied verbatim in the file "LICENSE" #
################################################################################
set -e
cleanup() {
dds-session stop $1
echo "CLEANUP PERFORMED"
}
source @DDS_INSTALL_PREFIX@/DDS_env.sh
export PATH=@BIN_DIR@:$PATH
exec 5>&1
output=$(dds-session start | tee >(cat - >&5))
export DDS_SESSION_ID=$(echo ${output} | grep "DDS session ID: " | cut -d' ' -f4)
echo "SESSION ID: ${DDS_SESSION_ID}"
trap "cleanup ${DDS_SESSION_ID}" EXIT
requiredNofSlots=8
dds-submit -r localhost --slots ${requiredNofSlots}
echo "...waiting for ${requiredNofSlots} idle slots..."
dds-info --idle-count --wait ${requiredNofSlots}
export FAIRMQ_DDS_TOPO_FILE=@DATA_DIR@/ex-n-m-topology.xml
echo "TOPOLOGY FILE: ${FAIRMQ_DDS_TOPO_FILE}"
echo "TOPOLOGY NAME: $(dds-topology --disable-validation --topology-name ${FAIRMQ_DDS_TOPO_FILE})"
dds-info --active-topology
dds-topology --activate ${FAIRMQ_DDS_TOPO_FILE}
dds-info --active-topology
echo "...waiting for ${requiredNofSlots} executing slots..."
dds-info --executing-count --wait ${requiredNofSlots}
echo "------------------------"
echo "...waiting for Topology to finish..."
# TODO Retrieve number of devices from DDS topology API instead of having the user pass it explicitely
fairmq-dds-command-ui -w "IDLE"
fairmq-dds-command-ui -c i
fairmq-dds-command-ui -c k
fairmq-dds-command-ui -c b
fairmq-dds-command-ui -c x
fairmq-dds-command-ui -c j
fairmq-dds-command-ui -c r
receivers="main/Receivers.*"
fairmq-dds-command-ui -w "RUNNING->READY" -p $receivers
echo "All receivers transitioned from RUNNING to READY"
fairmq-dds-command-ui -c s
fairmq-dds-command-ui -c t
fairmq-dds-command-ui -c d
fairmq-dds-command-ui -c q
echo "...waiting for ${requiredNofSlots} idle slots..."
dds-info --idle-count --wait ${requiredNofSlots}
echo "------------------------"
dds-info --active-topology
dds-topology --stop
dds-info --active-topology
dds-agent-cmd getlog -a
logDir="${wrkDir}/logs"
for file in $(find "${logDir}" -name "*.tar.gz"); do tar -xf ${file} -C "${logDir}" ; done
echo "AGENT LOG FILES IN: ${logDir}"
# This string is used by ctest to detect success
echo "Example successful :)"
# Cleanup function is called by EXIT trap

View File

@@ -0,0 +1,76 @@
#!/bin/bash
################################################################################
# Copyright (C) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
# copied verbatim in the file "LICENSE" #
################################################################################
set -e
cleanup() {
dds-session stop $1
echo "CLEANUP PERFORMED"
}
source @DDS_INSTALL_PREFIX@/DDS_env.sh
export PATH=@BIN_DIR@:$PATH
exec 5>&1
output=$(dds-session start | tee >(cat - >&5))
export DDS_SESSION_ID=$(echo ${output} | grep "DDS session ID: " | cut -d' ' -f4)
echo "SESSION ID: ${DDS_SESSION_ID}"
trap "cleanup ${DDS_SESSION_ID}" EXIT
requiredNofSlots=8
dds-submit -r localhost --slots ${requiredNofSlots}
echo "...waiting for ${requiredNofSlots} idle slots..."
dds-info --idle-count --wait ${requiredNofSlots}
export FAIRMQ_DDS_TOPO_FILE=@DATA_DIR@/ex-n-m-pair-topology.xml
echo "TOPOLOGY FILE: ${FAIRMQ_DDS_TOPO_FILE}"
echo "TOPOLOGY NAME: $(dds-topology --disable-validation --topology-name ${FAIRMQ_DDS_TOPO_FILE})"
dds-info --active-topology
dds-topology --activate ${FAIRMQ_DDS_TOPO_FILE}
dds-info --active-topology
echo "...waiting for ${requiredNofSlots} executing slots..."
dds-info --executing-count --wait ${requiredNofSlots}
echo "------------------------"
echo "...waiting for Topology to finish..."
# TODO Retrieve number of devices from DDS topology API instead of having the user pass it explicitely
fairmq-dds-command-ui -w "IDLE"
fairmq-dds-command-ui -c i
fairmq-dds-command-ui -c k
fairmq-dds-command-ui -c b
fairmq-dds-command-ui -c x
fairmq-dds-command-ui -c j
fairmq-dds-command-ui -c r
receivers="main/Receivers.*"
fairmq-dds-command-ui -w "RUNNING->READY" -p $receivers
echo "All receivers transitioned from RUNNING to READY"
fairmq-dds-command-ui -c s
fairmq-dds-command-ui -c t
fairmq-dds-command-ui -c d
fairmq-dds-command-ui -c q
echo "...waiting for ${requiredNofSlots} idle slots..."
dds-info --idle-count --wait ${requiredNofSlots}
echo "------------------------"
dds-info --active-topology
dds-topology --stop
dds-info --active-topology
dds-agent-cmd getlog -a
logDir="${wrkDir}/logs"
for file in $(find "${logDir}" -name "*.tar.gz"); do tar -xf ${file} -C "${logDir}" ; done
echo "AGENT LOG FILES IN: ${logDir}"
# This string is used by ctest to detect success
echo "Example successful :)"
# Cleanup function is called by EXIT trap

View File

@@ -0,0 +1,60 @@
#!/bin/bash
export PATH=@BIN_DIR@:$PATH
SYNC="fairmq-ex-n-m-synchronizer"
SYNC+=" --id Sync"
SYNC+=" --channel-config name=sync,type=pub,method=bind,address=tcp://localhost:8010"
SYNC+=" --rate 100"
xterm -geometry 80x25+0+0 -hold -e $SYNC &
SENDER0="fairmq-ex-n-m-sender"
SENDER0+=" --id Sender1"
SENDER0+=" --channel-config name=sync,type=sub,method=connect,address=tcp://localhost:8010"
SENDER0+=" name=data,type=pair,method=connect,address=tcp://localhost:8021,address=tcp://localhost:8022,address=tcp://localhost:8023,address=tcp://localhost:8024"
SENDER0+=" --sender-index 0"
SENDER0+=" --subtimeframe-size 1000000"
SENDER0+=" --num-receivers 4"
xterm -geometry 80x25+500+0 -hold -e $SENDER0 &
SENDER1="fairmq-ex-n-m-sender"
SENDER1+=" --id Sender2"
SENDER1+=" --channel-config name=sync,type=sub,method=connect,address=tcp://localhost:8010"
SENDER1+=" name=data,type=pair,method=connect,address=tcp://localhost:8031,address=tcp://localhost:8032,address=tcp://localhost:8033,address=tcp://localhost:8034"
SENDER1+=" --sender-index 1"
SENDER1+=" --subtimeframe-size 1000000"
SENDER1+=" --num-receivers 4"
xterm -geometry 80x25+500+350 -hold -e $SENDER1 &
SENDER2="fairmq-ex-n-m-sender"
SENDER2+=" --id Sender3"
SENDER2+=" --channel-config name=sync,type=sub,method=connect,address=tcp://localhost:8010"
SENDER2+=" name=data,type=pair,method=connect,address=tcp://localhost:8041,address=tcp://localhost:8042,address=tcp://localhost:8043,address=tcp://localhost:8044"
SENDER2+=" --sender-index 2"
SENDER2+=" --subtimeframe-size 1000000"
SENDER2+=" --num-receivers 4"
xterm -geometry 80x25+500+700 -hold -e $SENDER2 &
RECEIVER0="fairmq-ex-n-m-receiver"
RECEIVER0+=" --id Receiver1"
RECEIVER0+=" --channel-config name=data,type=pair,method=bind,address=tcp://localhost:8021,address=tcp://localhost:8031,address=tcp://localhost:8041"
RECEIVER0+=" --num-senders 3"
xterm -geometry 80x25+1000+0 -hold -e $RECEIVER0 &
RECEIVER1="fairmq-ex-n-m-receiver"
RECEIVER1+=" --id Receiver2"
RECEIVER1+=" --channel-config name=data,type=pair,method=bind,address=tcp://localhost:8022,address=tcp://localhost:8032,address=tcp://localhost:8042"
RECEIVER1+=" --num-senders 3"
xterm -geometry 80x25+1000+350 -hold -e $RECEIVER1 &
RECEIVER2="fairmq-ex-n-m-receiver"
RECEIVER2+=" --id Receiver3"
RECEIVER2+=" --channel-config name=data,type=pair,method=bind,address=tcp://localhost:8023,address=tcp://localhost:8033,address=tcp://localhost:8043"
RECEIVER2+=" --num-senders 3"
xterm -geometry 80x25+1000+700 -hold -e $RECEIVER2 &
RECEIVER3="fairmq-ex-n-m-receiver"
RECEIVER3+=" --id Receiver4"
RECEIVER3+=" --channel-config name=data,type=pair,method=bind,address=tcp://localhost:8024,address=tcp://localhost:8034,address=tcp://localhost:8044"
RECEIVER3+=" --num-senders 3"
xterm -geometry 80x25+1000+1050 -hold -e $RECEIVER3 &

View File

@@ -0,0 +1,60 @@
#!/bin/bash
export PATH=@BIN_DIR@:$PATH
SYNC="fairmq-ex-n-m-synchronizer"
SYNC+=" --id Sync"
SYNC+=" --channel-config name=sync,type=pub,method=bind,address=tcp://localhost:8010"
SYNC+=" --rate 100"
xterm -geometry 80x25+0+0 -hold -e $SYNC &
SENDER0="fairmq-ex-n-m-sender"
SENDER0+=" --id Sender1"
SENDER0+=" --channel-config name=sync,type=sub,method=connect,address=tcp://localhost:8010"
SENDER0+=" name=data,type=push,method=connect,address=tcp://localhost:8021,address=tcp://localhost:8022,address=tcp://localhost:8023,address=tcp://localhost:8024"
SENDER0+=" --sender-index 0"
SENDER0+=" --subtimeframe-size 1000000"
SENDER0+=" --num-receivers 4"
xterm -geometry 80x25+500+0 -hold -e $SENDER0 &
SENDER1="fairmq-ex-n-m-sender"
SENDER1+=" --id Sender2"
SENDER1+=" --channel-config name=sync,type=sub,method=connect,address=tcp://localhost:8010"
SENDER1+=" name=data,type=push,method=connect,address=tcp://localhost:8021,address=tcp://localhost:8022,address=tcp://localhost:8023,address=tcp://localhost:8024"
SENDER1+=" --sender-index 1"
SENDER1+=" --subtimeframe-size 1000000"
SENDER1+=" --num-receivers 4"
xterm -geometry 80x25+500+350 -hold -e $SENDER1 &
SENDER2="fairmq-ex-n-m-sender"
SENDER2+=" --id Sender3"
SENDER2+=" --channel-config name=sync,type=sub,method=connect,address=tcp://localhost:8010"
SENDER2+=" name=data,type=push,method=connect,address=tcp://localhost:8021,address=tcp://localhost:8022,address=tcp://localhost:8023,address=tcp://localhost:8024"
SENDER2+=" --sender-index 2"
SENDER2+=" --subtimeframe-size 1000000"
SENDER2+=" --num-receivers 4"
xterm -geometry 80x25+500+700 -hold -e $SENDER2 &
RECEIVER0="fairmq-ex-n-m-receiver"
RECEIVER0+=" --id Receiver1"
RECEIVER0+=" --channel-config name=data,type=pull,method=bind,address=tcp://localhost:8021"
RECEIVER0+=" --num-senders 3"
xterm -geometry 80x25+1000+0 -hold -e $RECEIVER0 &
RECEIVER1="fairmq-ex-n-m-receiver"
RECEIVER1+=" --id Receiver2"
RECEIVER1+=" --channel-config name=data,type=pull,method=bind,address=tcp://localhost:8022"
RECEIVER1+=" --num-senders 3"
xterm -geometry 80x25+1000+350 -hold -e $RECEIVER1 &
RECEIVER2="fairmq-ex-n-m-receiver"
RECEIVER2+=" --id Receiver3"
RECEIVER2+=" --channel-config name=data,type=pull,method=bind,address=tcp://localhost:8023"
RECEIVER2+=" --num-senders 3"
xterm -geometry 80x25+1000+700 -hold -e $RECEIVER2 &
RECEIVER3="fairmq-ex-n-m-receiver"
RECEIVER3+=" --id Receiver4"
RECEIVER3+=" --channel-config name=data,type=pull,method=bind,address=tcp://localhost:8024"
RECEIVER3+=" --num-senders 3"
xterm -geometry 80x25+1000+1050 -hold -e $RECEIVER3 &

View File

@@ -0,0 +1,119 @@
/********************************************************************************
* Copyright (C) 2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "Header.h"
#include <FairMQDevice.h>
#include <runFairMQDevice.h>
#include <string>
#include <iomanip>
#include <chrono>
#include <string>
#include <unordered_map>
#include <unordered_set>
using namespace std;
using namespace example_n_m;
namespace bpo = boost::program_options;
struct TFBuffer
{
FairMQParts parts;
chrono::steady_clock::time_point start;
chrono::steady_clock::time_point end;
};
class Receiver : public FairMQDevice
{
public:
Receiver()
: fBuffer()
, fDiscardedSet()
, fNumSenders(0)
, fBufferTimeoutInMs(5000)
, fMaxTimeframes(0)
, fTimeframeCounter(0)
{
OnData("data", &Receiver::HandleData);
}
~Receiver() = default;
void InitTask() override
{
fNumSenders = GetConfig()->GetValue<int>("num-senders");
fBufferTimeoutInMs = GetConfig()->GetValue<int>("buffer-timeout");
fMaxTimeframes = GetConfig()->GetValue<int>("max-timeframes");
}
protected:
bool HandleData(FairMQParts& parts, int /* index */)
{
Header& h = *(static_cast<Header*>(parts.At(0)->GetData()));
// LOG(info) << "Received sub-time frame #" << h.id << " from Sender" << h.senderIndex;
if (fDiscardedSet.find(h.id) == fDiscardedSet.end()) {
if (fBuffer.find(h.id) == fBuffer.end()) {
// if this is the first part with this ID, save the receive time.
fBuffer[h.id].start = chrono::steady_clock::now();
}
// if the received ID has not previously been discarded, store the data part in the buffer
fBuffer[h.id].parts.AddPart(move(parts.At(1)));
} else {
// if received ID has been previously discarded.
LOG(debug) << "Received part from an already discarded timeframe with id " << h.id;
}
if (fBuffer[h.id].parts.Size() == fNumSenders) {
LOG(info) << "Successfully completed timeframe #" << h.id;
fBuffer.erase(h.id);
if (fMaxTimeframes > 0 && ++fTimeframeCounter >= fMaxTimeframes) {
LOG(info) << "Reached configured maximum number of timeframes (" << fMaxTimeframes << "). Exiting RUNNING state.";
return false;
}
}
return true;
}
void DiscardIncompleteTimeframes()
{
auto it = fBuffer.begin();
while (it != fBuffer.end()) {
if (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - (it->second).start).count() > fBufferTimeoutInMs) {
LOG(debug) << "Timeframe #" << it->first << " incomplete after " << fBufferTimeoutInMs << " milliseconds, discarding";
fDiscardedSet.insert(it->first);
fBuffer.erase(it++);
LOG(debug) << "Number of discarded timeframes: " << fDiscardedSet.size();
} else {
// LOG(info) << "Timeframe #" << it->first << " within timeout, buffering...";
++it;
}
}
}
unordered_map<uint16_t, TFBuffer> fBuffer;
unordered_set<uint16_t> fDiscardedSet;
int fNumSenders;
int fBufferTimeoutInMs;
int fMaxTimeframes;
int fTimeframeCounter;
};
void addCustomOptions(bpo::options_description& options)
{
options.add_options()
("buffer-timeout", bpo::value<int>()->default_value(1000), "Buffer timeout in milliseconds")
("num-senders", bpo::value<int>()->required(), "Number of senders")
("max-timeframes", bpo::value<int>()->default_value(0), "Maximum number of timeframes to receive (0 - unlimited)");
}
FairMQDevice* getDevice(const FairMQProgOptions& /* config */) { return new Receiver(); }

View File

@@ -0,0 +1,79 @@
/********************************************************************************
* Copyright (C) 2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "Header.h"
#include <FairMQDevice.h>
#include <runFairMQDevice.h>
#include <string>
using namespace std;
using namespace example_n_m;
namespace bpo = boost::program_options;
class Sender : public FairMQDevice
{
public:
Sender()
: fNumReceivers(0)
, fIndex(0)
, fSubtimeframeSize(10000)
{}
~Sender() = default;
protected:
void InitTask() override
{
fIndex = GetConfig()->GetProperty<int>("sender-index");
fSubtimeframeSize = GetConfig()->GetProperty<int>("subtimeframe-size");
fNumReceivers = GetConfig()->GetProperty<int>("num-receivers");
}
void Run() override
{
FairMQChannel& dataInChannel = fChannels.at("sync").at(0);
while (!NewStatePending()) {
Header h;
FairMQMessagePtr id(NewMessage());
if (dataInChannel.Receive(id) > 0) {
h.id = *(static_cast<uint16_t*>(id->GetData()));
h.senderIndex = fIndex;
} else {
continue;
}
FairMQParts parts;
parts.AddPart(NewSimpleMessage(h));
parts.AddPart(NewMessage(fSubtimeframeSize));
uint64_t currentDataId = h.id;
int direction = currentDataId % fNumReceivers;
if (Send(parts, "data", direction, 0) < 0) {
LOG(debug) << "Failed to queue Subtimeframe #" << currentDataId << " to Receiver[" << direction << "]";
}
}
}
private:
int fNumReceivers;
unsigned int fIndex;
int fSubtimeframeSize;
};
void addCustomOptions(bpo::options_description& options)
{
options.add_options()
("sender-index", bpo::value<int>()->default_value(0), "Sender Index")
("subtimeframe-size", bpo::value<int>()->default_value(1000), "Subtimeframe size in bytes")
("num-receivers", bpo::value<int>()->required(), "Number of EPNs");
}
FairMQDevice* getDevice(const FairMQProgOptions& /* config */) { return new Sender(); }

View File

@@ -0,0 +1,46 @@
/********************************************************************************
* Copyright (C) 2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include <FairMQDevice.h>
#include <runFairMQDevice.h>
#include <string>
#include <cstdint>
using namespace std;
namespace bpo = boost::program_options;
class Synchronizer : public FairMQDevice
{
public:
Synchronizer()
: fTimeframeId(0)
{}
~Synchronizer() = default;
protected:
bool ConditionalRun() override
{
FairMQMessagePtr msg(NewSimpleMessage(fTimeframeId));
if (Send(msg, "sync") > 0) {
if (++fTimeframeId == UINT16_MAX - 1) {
fTimeframeId = 0;
}
} else {
return false;
}
return true;
}
uint16_t fTimeframeId;
};
void addCustomOptions(bpo::options_description& /* options */) {}
FairMQDevice* getDevice(const FairMQProgOptions& /* config */) { return new Synchronizer(); }

View File

@@ -0,0 +1,71 @@
################################################################################
# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
# copied verbatim in the file "LICENSE" #
################################################################################
add_executable(fairmq-ex-qc-sampler runSampler.cxx)
target_link_libraries(fairmq-ex-qc-sampler PRIVATE FairMQ)
add_executable(fairmq-ex-qc-dispatcher runQCDispatcher.cxx)
target_link_libraries(fairmq-ex-qc-dispatcher PRIVATE FairMQ)
add_executable(fairmq-ex-qc-task runQCTask.cxx)
target_link_libraries(fairmq-ex-qc-task PRIVATE FairMQ)
add_executable(fairmq-ex-qc-sink runSink.cxx)
target_link_libraries(fairmq-ex-qc-sink PRIVATE FairMQ)
add_custom_target(ExampleQC DEPENDS fairmq-ex-qc-sampler fairmq-ex-qc-dispatcher fairmq-ex-qc-task fairmq-ex-qc-sink)
list(JOIN Boost_LIBRARY_DIRS ":" LIB_DIR)
set(BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}:${CMAKE_BINARY_DIR}/fairmq/sdk)
set(DATA_DIR ${CMAKE_CURRENT_BINARY_DIR})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-qc-topology.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-qc-topology.xml @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-ex-qc-env.sh ${CMAKE_CURRENT_BINARY_DIR}/fairmq-ex-qc-env.sh @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-qc.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-qc.sh @ONLY)
# test
if(DDS_FOUND)
add_test(NAME Example.QC.localhost COMMAND ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-qc.sh localhost)
set_tests_properties(Example.QC.localhost PROPERTIES TIMEOUT 15 RUN_SERIAL true PASS_REGULAR_EXPRESSION "Example successful")
endif()
# install
install(
TARGETS
fairmq-ex-qc-sampler
fairmq-ex-qc-dispatcher
fairmq-ex-qc-task
fairmq-ex-qc-sink
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
)
# configure run script with different executable paths for build and for install directories
set(BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
set(DATA_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_DATADIR})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ex-qc-topology.xml ${CMAKE_CURRENT_BINARY_DIR}/ex-qc-topology.xml_install @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-ex-qc-env.sh ${CMAKE_CURRENT_BINARY_DIR}/fairmq-ex-qc-env.sh_install @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-qc.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-qc.sh_install @ONLY)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/ex-qc-topology.xml_install
DESTINATION ${PROJECT_INSTALL_DATADIR}
RENAME ex-qc-topology.xml
)
install(
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-ex-qc-env.sh_install
DESTINATION ${PROJECT_INSTALL_BINDIR}
RENAME fairmq-ex-qc-env.sh
)
install(
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-qc.sh_install
DESTINATION ${PROJECT_INSTALL_BINDIR}
RENAME fairmq-start-ex-qc.sh
)

4
examples/qc/README.md Normal file
View File

@@ -0,0 +1,4 @@
QC
==
A topology consisting of 4 devices - Sampler, QCDispatcher, QCTask and Sink. The data flows from Sampler through QCDispatcher to Sink. On demand - by setting the corresponding configuration property - the QCDispatcher device will duplicate the data to the QCTask device. The property is set by the topology controller, in this example this is the `fairmq-dds-command-ui` utility.

View File

@@ -0,0 +1,48 @@
<topology name="ExampleQC">
<property name="fmqchan_data1" />
<property name="fmqchan_data2" />
<property name="fmqchan_qc" />
<decltask name="Sampler">
<exe>fairmq-ex-qc-sampler --color false --channel-config name=data1,type=push,method=bind -P dds --max-iterations 1000</exe>
<env reachable="false">fairmq-ex-qc-env.sh</env>
<properties>
<name access="write">fmqchan_data1</name>
</properties>
</decltask>
<decltask name="QCDispatcher">
<exe>fairmq-ex-qc-dispatcher --color false --channel-config name=data1,type=pull,method=connect name=data2,type=push,method=connect name=qc,type=push,method=connect -P dds</exe>
<env reachable="false">fairmq-ex-qc-env.sh</env>
<properties>
<name access="read">fmqchan_data1</name>
<name access="read">fmqchan_data2</name>
<name access="read">fmqchan_qc</name>
</properties>
</decltask>
<decltask name="QCTask">
<exe>fairmq-ex-qc-task --color false --channel-config name=qc,type=pull,method=bind -P dds</exe>
<env reachable="false">fairmq-ex-qc-env.sh</env>
<properties>
<name access="write">fmqchan_qc</name>
</properties>
</decltask>
<decltask name="Sink">
<exe>fairmq-ex-qc-sink --color false --channel-config name=data2,type=pull,method=bind -P dds --max-iterations 1000</exe>
<env reachable="false">fairmq-ex-qc-env.sh</env>
<properties>
<name access="write">fmqchan_data2</name>
</properties>
</decltask>
<main name="main">
<task>Sampler</task>
<task>QCDispatcher</task>
<task>QCTask</task>
<task>Sink</task>
</main>
</topology>

16
examples/qc/fairmq-ex-qc-env.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
################################################################################
# Copyright (C) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
# copied verbatim in the file "LICENSE" #
################################################################################
export PATH=@BIN_DIR@:$PATH
OS=$(uname -s 2>&1)
if [ "$OS" == "Darwin" ]; then
export DYLD_LIBRARY_PATH=@LIB_DIR@:$DYLD_LIBRARY_PATH
fi

View File

@@ -0,0 +1,82 @@
#!/bin/bash
################################################################################
# Copyright (C) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
# copied verbatim in the file "LICENSE" #
################################################################################
# fairmq-start-ex-qc.sh -> submit agents with localhost plugin
set -e
cleanup() {
dds-session stop $1
echo "CLEANUP PERFORMED"
}
source @DDS_INSTALL_PREFIX@/DDS_env.sh
export PATH=@BIN_DIR@:$PATH
exec 5>&1
output=$(dds-session start | tee >(cat - >&5))
export DDS_SESSION_ID=$(echo ${output} | grep "DDS session ID: " | cut -d' ' -f4)
echo "SESSION ID: ${DDS_SESSION_ID}"
trap "cleanup ${DDS_SESSION_ID}" EXIT
requiredNofSlots=4
dds-submit -r localhost --slots ${requiredNofSlots}
echo "...waiting for ${requiredNofSlots} idle slots..."
dds-info --idle-count --wait ${requiredNofSlots}
export FAIRMQ_DDS_TOPO_FILE=@DATA_DIR@/ex-qc-topology.xml
echo "TOPOLOGY FILE: ${FAIRMQ_DDS_TOPO_FILE}"
echo "TOPOLOGY NAME: $(dds-topology --disable-validation --topology-name ${FAIRMQ_DDS_TOPO_FILE})"
dds-info --active-topology
dds-topology --activate ${FAIRMQ_DDS_TOPO_FILE}
dds-info --active-topology
echo "...waiting for ${requiredNofSlots} executing slots..."
dds-info --executing-count --wait ${requiredNofSlots}
echo "------------------------"
echo "...waiting for Topology to finish..."
# TODO Retrieve number of devices from DDS topology API instead of having the user pass it explicitely
fairmq-dds-command-ui -w "IDLE"
fairmq-dds-command-ui -c i
fairmq-dds-command-ui -c k
fairmq-dds-command-ui -c b
fairmq-dds-command-ui -c x
fairmq-dds-command-ui -c j
allexceptqctasks="main/(Sampler|QCDispatcher|Sink).*"
fairmq-dds-command-ui -c r -p $allexceptqctasks
qctask="main/QCTask.*"
qcdispatcher="main/QCDispatcher.*"
fairmq-dds-command-ui -c p --property-key qc --property-value active -p $qcdispatcher
fairmq-dds-command-ui -c r -p $qctask
fairmq-dds-command-ui -w "RUNNING->READY" -p $qctask
echo "...$qctask received data and transitioned to READY, sending shutdown..."
fairmq-dds-command-ui -c s
fairmq-dds-command-ui -c t
fairmq-dds-command-ui -c d
fairmq-dds-command-ui -c q
echo "...waiting for ${requiredNofSlots} idle slots..."
dds-info --idle-count --wait ${requiredNofSlots}
echo "------------------------"
dds-info --active-topology
dds-topology --stop
dds-info --active-topology
dds-agent-cmd getlog -a
logDir="${wrkDir}/logs"
for file in $(find "${logDir}" -name "*.tar.gz"); do tar -xf ${file} -C "${logDir}" ; done
echo "AGENT LOG FILES IN: ${logDir}"
# This string is used by ctest to detect success
echo "Example successful :)"
# Cleanup function is called by EXIT trap

View File

@@ -0,0 +1,59 @@
/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "runFairMQDevice.h"
#include "FairMQDevice.h"
class QCDispatcher : public FairMQDevice
{
public:
QCDispatcher()
: fDoQC(false)
{
OnData("data1", &QCDispatcher::HandleData);
}
void InitTask() override
{
GetConfig()->Subscribe<std::string>("qcdevice", [&](const std::string& key, std::string value) {
if (key == "qc") {
if (value == "active") {
fDoQC.store(true);
} else if (value == "inactive") {
fDoQC.store(false);
}
}
});
}
protected:
bool HandleData(FairMQMessagePtr& msg, int)
{
if (fDoQC.load() == true) {
FairMQMessagePtr msgCopy(NewMessage());
msgCopy->Copy(*msg);
if (Send(msg, "qc") < 0) {
return false;
}
}
if (Send(msg, "data2") < 0) {
return false;
}
return true;
}
void ResetTask() override { GetConfig()->Unsubscribe<std::string>("qcdevice"); }
private:
std::atomic<bool> fDoQC;
};
void addCustomOptions(boost::program_options::options_description& /*options*/) {}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/) { return new QCDispatcher(); }

26
examples/qc/runQCTask.cxx Normal file
View File

@@ -0,0 +1,26 @@
/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "runFairMQDevice.h"
#include "FairMQDevice.h"
class QCTask : public FairMQDevice
{
public:
QCTask()
{
OnData("qc", [](FairMQMessagePtr& /*msg*/, int) {
LOG(info) << "received data";
return false;
});
}
};
namespace bpo = boost::program_options;
void addCustomOptions(bpo::options_description& /*options*/) {}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/) { return new QCTask(); }

View File

@@ -0,0 +1,36 @@
/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "runFairMQDevice.h"
#include "FairMQDevice.h"
#include <thread> // this_thread::sleep_for
#include <chrono>
class Sampler : public FairMQDevice
{
public:
Sampler() {}
protected:
virtual bool ConditionalRun()
{
FairMQMessagePtr msg(NewMessage(1000));
if (Send(msg, "data1") < 0) {
return false;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
return true;
}
};
namespace bpo = boost::program_options;
void addCustomOptions(bpo::options_description&) {}
FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/) { return new Sampler(); }

View File

@@ -6,30 +6,20 @@
* copied verbatim in the file "LICENSE" * * copied verbatim in the file "LICENSE" *
********************************************************************************/ ********************************************************************************/
#include "FairMQUnmanagedRegionZMQ.h" #include "runFairMQDevice.h"
#include "FairMQLogger.h" #include "FairMQDevice.h"
using namespace std; #include <string>
FairMQUnmanagedRegionZMQ::FairMQUnmanagedRegionZMQ(const size_t size, FairMQRegionCallback callback, const std::string& /* path = "" */, int /* flags = 0 */) class Sink : public FairMQDevice
: fBuffer(malloc(size))
, fSize(size)
, fCallback(callback)
{ {
} public:
Sink() { OnData("data2", &Sink::HandleData); }
void* FairMQUnmanagedRegionZMQ::GetData() const protected:
{ bool HandleData(FairMQMessagePtr& /*msg*/, int /*index*/) { return true; }
return fBuffer; };
}
size_t FairMQUnmanagedRegionZMQ::GetSize() const namespace bpo = boost::program_options;
{ void addCustomOptions(bpo::options_description&) {}
return fSize; FairMQDevicePtr getDevice(const fair::mq::ProgOptions& /*config*/) { return new Sink(); }
}
FairMQUnmanagedRegionZMQ::~FairMQUnmanagedRegionZMQ()
{
LOG(debug) << "destroying region";
free(fBuffer);
}

View File

@@ -37,10 +37,10 @@ class Readout : public FairMQDevice
fRegion = FairMQUnmanagedRegionPtr(NewUnmanagedRegionFor("rb", fRegion = FairMQUnmanagedRegionPtr(NewUnmanagedRegionFor("rb",
0, 0,
10000000, 10000000,
[this](void* /*data*/, size_t /*size*/, void* /*hint*/) { // callback to be called when message buffers no longer needed by transport [this](const std::vector<fair::mq::RegionBlock>& blocks) { // callback to be called when message buffers no longer needed by transport
--fNumUnackedMsgs; fNumUnackedMsgs -= blocks.size();
if (fMaxIterations > 0) { if (fMaxIterations > 0) {
LOG(debug) << "Received ack"; LOG(debug) << "Received " << blocks.size() << " acks";
} }
} }
)); ));

View File

@@ -31,10 +31,12 @@ SENDER="fairmq-ex-readout-sender"
SENDER+=" --id sender1" SENDER+=" --id sender1"
SENDER+=" --input-name ps" SENDER+=" --input-name ps"
SENDER+=" --channel-config name=ps,type=pair,method=bind,address=tcp://localhost:7779,transport=shmem" SENDER+=" --channel-config name=ps,type=pair,method=bind,address=tcp://localhost:7779,transport=shmem"
SENDER+=" name=sr,type=pair,method=connect,address=tcp://localhost:7780,transport=ofi" #SENDER+=" name=sr,type=pair,method=connect,address=tcp://localhost:7780,transport=ofi"
SENDER+=" name=sr,type=pair,method=connect,address=tcp://localhost:7780,transport=zeromq"
xterm -geometry 80x23+1000+0 -hold -e @EX_BIN_DIR@/$SENDER & xterm -geometry 80x23+1000+0 -hold -e @EX_BIN_DIR@/$SENDER &
RECEIVER="fairmq-ex-readout-receiver" RECEIVER="fairmq-ex-readout-receiver"
RECEIVER+=" --id receiver1" RECEIVER+=" --id receiver1"
RECEIVER+=" --channel-config name=sr,type=pair,method=bind,address=tcp://localhost:7780,transport=ofi" #RECEIVER+=" --channel-config name=sr,type=pair,method=bind,address=tcp://localhost:7780,transport=ofi"
RECEIVER+=" --channel-config name=sr,type=pair,method=bind,address=tcp://localhost:7780,transport=zeromq"
xterm -geometry 80x23+1500+0 -hold -e @EX_BIN_DIR@/$RECEIVER & xterm -geometry 80x23+1500+0 -hold -e @EX_BIN_DIR@/$RECEIVER &

View File

@@ -25,10 +25,12 @@ SENDER="fairmq-ex-readout-sender"
SENDER+=" --id sender1" SENDER+=" --id sender1"
SENDER+=" --input-name bs" SENDER+=" --input-name bs"
SENDER+=" --channel-config name=bs,type=pair,method=bind,address=tcp://localhost:7778,transport=shmem" SENDER+=" --channel-config name=bs,type=pair,method=bind,address=tcp://localhost:7778,transport=shmem"
SENDER+=" name=sr,type=pair,method=connect,address=tcp://localhost:7779,transport=ofi" # SENDER+=" name=sr,type=pair,method=connect,address=tcp://localhost:7779,transport=ofi"
SENDER+=" name=sr,type=pair,method=connect,address=tcp://localhost:7779,transport=zeromq"
xterm -geometry 80x23+1000+0 -hold -e @EX_BIN_DIR@/$SENDER & xterm -geometry 80x23+1000+0 -hold -e @EX_BIN_DIR@/$SENDER &
RECEIVER="fairmq-ex-readout-receiver" RECEIVER="fairmq-ex-readout-receiver"
RECEIVER+=" --id receiver1" RECEIVER+=" --id receiver1"
RECEIVER+=" --channel-config name=sr,type=pair,method=bind,address=tcp://localhost:7779,transport=ofi" # RECEIVER+=" --channel-config name=sr,type=pair,method=bind,address=tcp://localhost:7779,transport=ofi"
RECEIVER+=" --channel-config name=sr,type=pair,method=bind,address=tcp://localhost:7779,transport=zeromq"
xterm -geometry 80x23+1500+0 -hold -e @EX_BIN_DIR@/$RECEIVER & xterm -geometry 80x23+1500+0 -hold -e @EX_BIN_DIR@/$RECEIVER &

View File

@@ -32,15 +32,10 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-region.sh.in ${CMAKE_
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-region.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-region.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh)
add_test(NAME Example.Region.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh zeromq) add_test(NAME Example.Region.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh zeromq)
set_tests_properties(Example.Region.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received ack") set_tests_properties(Example.Region.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received [0-9*] acks")
if(BUILD_NANOMSG_TRANSPORT)
add_test(NAME Example.Region.nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh nanomsg)
set_tests_properties(Example.Region.nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received ack")
endif()
add_test(NAME Example.Region.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh shmem) add_test(NAME Example.Region.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-region.sh shmem)
set_tests_properties(Example.Region.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received ack") set_tests_properties(Example.Region.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received [0-9*] acks")
# install # install

View File

@@ -23,28 +23,41 @@ namespace example_region
Sampler::Sampler() Sampler::Sampler()
: fMsgSize(10000) : fMsgSize(10000)
, fLinger(100)
, fMaxIterations(0) , fMaxIterations(0)
, fNumIterations(0) , fNumIterations(0)
, fRegion(nullptr) , fRegion(nullptr)
, fNumUnackedMsgs(0) , fNumUnackedMsgs(0)
{ {}
}
void Sampler::InitTask() void Sampler::InitTask()
{ {
fMsgSize = fConfig->GetProperty<int>("msg-size"); fMsgSize = fConfig->GetProperty<int>("msg-size");
fLinger = fConfig->GetProperty<uint32_t>("region-linger");
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations"); fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fChannels.at("data").at(0).Transport()->SubscribeToRegionEvents([](FairMQRegionInfo info) {
LOG(info) << "Region event: " << info.event
<< ", managed: " << info.managed
<< ", id: " << info.id
<< ", ptr: " << info.ptr
<< ", size: " << info.size
<< ", flags: " << info.flags;
});
fRegion = FairMQUnmanagedRegionPtr(NewUnmanagedRegionFor("data", fRegion = FairMQUnmanagedRegionPtr(NewUnmanagedRegionFor("data",
0, 0,
10000000, 10000000,
[this](void* /*data*/, size_t /*size*/, void* /*hint*/) { // callback to be called when message buffers no longer needed by transport [this](const std::vector<fair::mq::RegionBlock>& blocks) { // callback to be called when message buffers no longer needed by transport
--fNumUnackedMsgs; lock_guard<mutex> lock(fMtx);
fNumUnackedMsgs -= blocks.size();
if (fMaxIterations > 0) { if (fMaxIterations > 0) {
LOG(debug) << "Received ack"; LOG(info) << "Received " << blocks.size() << " acks";
} }
} }
)); ));
fRegion->SetLinger(fLinger);
} }
bool Sampler::ConditionalRun() bool Sampler::ConditionalRun()
@@ -61,27 +74,31 @@ bool Sampler::ConditionalRun()
// LOG(info) << "check: " << static_cast<char*>(fRegion->GetData())[3]; // LOG(info) << "check: " << static_cast<char*>(fRegion->GetData())[3];
// std::this_thread::sleep_for(std::chrono::seconds(1)); // std::this_thread::sleep_for(std::chrono::seconds(1));
lock_guard<mutex> lock(fMtx);
if (Send(msg, "data", 0) > 0) { if (Send(msg, "data", 0) > 0) {
++fNumUnackedMsgs;
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) { if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) {
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state."; LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
return false; return false;
} }
} }
++fNumUnackedMsgs;
return true; return true;
} }
void Sampler::ResetTask() void Sampler::ResetTask()
{ {
// if not all messages acknowledged, wait for a bit. But only once, since receiver could be already dead. // On destruction UnmanagedRegion will try to TODO
if (fNumUnackedMsgs != 0) {
LOG(debug) << "waiting for all acknowledgements... (" << fNumUnackedMsgs << ")";
this_thread::sleep_for(chrono::milliseconds(500));
LOG(debug) << "done, still unacked: " << fNumUnackedMsgs;
}
fRegion.reset(); fRegion.reset();
{
lock_guard<mutex> lock(fMtx);
if (fNumUnackedMsgs != 0) {
LOG(info) << "Done, still not acknowledged: " << fNumUnackedMsgs;
} else {
LOG(info) << "All acknowledgements received.";
}
}
fChannels.at("data").at(0).Transport()->UnsubscribeFromRegionEvents();
} }
Sampler::~Sampler() Sampler::~Sampler()

View File

@@ -15,7 +15,8 @@
#ifndef FAIRMQEXAMPLEREGIONSAMPLER_H #ifndef FAIRMQEXAMPLEREGIONSAMPLER_H
#define FAIRMQEXAMPLEREGIONSAMPLER_H #define FAIRMQEXAMPLEREGIONSAMPLER_H
#include <atomic> #include <mutex>
#include <cstdint>
#include "FairMQDevice.h" #include "FairMQDevice.h"
@@ -35,10 +36,12 @@ class Sampler : public FairMQDevice
private: private:
int fMsgSize; int fMsgSize;
uint32_t fLinger;
uint64_t fMaxIterations; uint64_t fMaxIterations;
uint64_t fNumIterations; uint64_t fNumIterations;
FairMQUnmanagedRegionPtr fRegion; FairMQUnmanagedRegionPtr fRegion;
std::atomic<uint64_t> fNumUnackedMsgs; std::mutex fMtx;
uint64_t fNumUnackedMsgs;
}; };
} // namespace example_region } // namespace example_region

View File

@@ -29,6 +29,14 @@ void Sink::InitTask()
{ {
// Get the fMaxIterations value from the command line options (via fConfig) // Get the fMaxIterations value from the command line options (via fConfig)
fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations"); fMaxIterations = fConfig->GetProperty<uint64_t>("max-iterations");
fChannels.at("data").at(0).Transport()->SubscribeToRegionEvents([](FairMQRegionInfo info) {
LOG(info) << "Region event: " << info.event
<< ", managed: " << info.managed
<< ", id: " << info.id
<< ", ptr: " << info.ptr
<< ", size: " << info.size
<< ", flags: " << info.flags;
});
} }
void Sink::Run() void Sink::Run()
@@ -50,6 +58,11 @@ void Sink::Run()
} }
} }
void Sink::ResetTask()
{
fChannels.at("data").at(0).Transport()->UnsubscribeFromRegionEvents();
}
Sink::~Sink() Sink::~Sink()
{ {
} }

View File

@@ -31,6 +31,7 @@ class Sink : public FairMQDevice
protected: protected:
virtual void Run(); virtual void Run();
virtual void InitTask(); virtual void InitTask();
virtual void ResetTask();
private: private:
uint64_t fMaxIterations; uint64_t fMaxIterations;

View File

@@ -15,6 +15,7 @@ void addCustomOptions(bpo::options_description& options)
{ {
options.add_options() options.add_options()
("msg-size", bpo::value<int>()->default_value(1000), "Message size in bytes") ("msg-size", bpo::value<int>()->default_value(1000), "Message size in bytes")
("region-linger", bpo::value<uint32_t>()->default_value(100), "Linger period for regions")
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)"); ("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
} }

View File

@@ -19,9 +19,11 @@ SAMPLER+=" --id sampler1"
SAMPLER+=" --transport $transport" SAMPLER+=" --transport $transport"
SAMPLER+=" --severity debug" SAMPLER+=" --severity debug"
SAMPLER+=" --session $SESSION" SAMPLER+=" --session $SESSION"
SAMPLER+=" --verbosity veryhigh"
SAMPLER+=" --control static --color false" SAMPLER+=" --control static --color false"
SAMPLER+=" --max-iterations 1" SAMPLER+=" --max-iterations 1"
SAMPLER+=" --msg-size $msgSize" SAMPLER+=" --msg-size $msgSize"
SAMPLER+=" --region-linger 500"
SAMPLER+=" --channel-config name=data,type=push,method=bind,address=tcp://127.0.0.1:7777" SAMPLER+=" --channel-config name=data,type=push,method=bind,address=tcp://127.0.0.1:7777"
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER & @CMAKE_CURRENT_BINARY_DIR@/$SAMPLER &
SAMPLER_PID=$! SAMPLER_PID=$!

View File

@@ -35,11 +35,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-req-rep.sh.in ${CMAKE_CURRENT
add_test(NAME Example.ReqRep.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh zeromq) add_test(NAME Example.ReqRep.zeromq COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh zeromq)
set_tests_properties(Example.ReqRep.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received reply from server: ") set_tests_properties(Example.ReqRep.zeromq PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received reply from server: ")
if(BUILD_NANOMSG_TRANSPORT)
add_test(NAME Example.ReqRep.nanomsg COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh nanomsg)
set_tests_properties(Example.ReqRep.nanomsg PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received reply from server: ")
endif()
add_test(NAME Example.ReqRep.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh shmem) add_test(NAME Example.ReqRep.shmem COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-req-rep.sh shmem)
set_tests_properties(Example.ReqRep.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received reply from server: ") set_tests_properties(Example.ReqRep.shmem PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received reply from server: ")

1
extern/PicoSHA2 vendored Submodule

Submodule extern/PicoSHA2 added at 599843c396

1
extern/asio vendored Submodule

Submodule extern/asio added at 90f32660cd

17
extern/bundled_asio.cmake vendored Normal file
View File

@@ -0,0 +1,17 @@
################################################################################
# Copyright (C) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
# copied verbatim in the file "LICENSE" #
################################################################################
if(NOT TARGET asio::headers)
if(Git_FOUND)
execute_process(
COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive --depth 1 -- extern/asio
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
endif()
endif()

1
extern/googletest vendored Submodule

Submodule extern/googletest added at 90a443f9c2

View File

@@ -6,16 +6,6 @@
# copied verbatim in the file "LICENSE" # # copied verbatim in the file "LICENSE" #
################################################################################ ################################################################################
####################
# external plugins #
####################
if(BUILD_DDS_PLUGIN)
add_subdirectory(plugins/DDS)
endif()
if(BUILD_PMIX_PLUGIN)
add_subdirectory(plugins/PMIx)
endif()
if(BUILD_FAIRMQ OR BUILD_SDK) if(BUILD_FAIRMQ OR BUILD_SDK)
########### ###########
# Version # # Version #
@@ -58,6 +48,12 @@ if(BUILD_FAIRMQ OR BUILD_SDK)
${TOOLS_PUBLIC_HEADER_FILES} ${TOOLS_PUBLIC_HEADER_FILES}
) )
target_compile_definitions(${target} PUBLIC BOOST_ERROR_CODE_HEADER_ONLY) target_compile_definitions(${target} PUBLIC BOOST_ERROR_CODE_HEADER_ONLY)
# workaround https://github.com/boostorg/asio/commit/43874d5497414c67655d901e48c939ef01337edb
if( Boost_VERSION VERSION_LESS 1.69
AND CMAKE_CXX_COMPILER_ID STREQUAL AppleClang
AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0.1)
target_compile_definitions(${target} PUBLIC BOOST_ASIO_HAS_STD_STRING_VIEW)
endif()
target_include_directories(${target} target_include_directories(${target}
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
@@ -70,7 +66,7 @@ if(BUILD_FAIRMQ OR BUILD_SDK)
Boost::boost Boost::boost
) )
set_target_properties(${target} PROPERTIES set_target_properties(${target} PROPERTIES
VERSION ${PROJECT_GIT_VERSION} VERSION ${PROJECT_VERSION}
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
OUTPUT_NAME FairMQ${target} OUTPUT_NAME FairMQ${target}
) )
@@ -124,7 +120,7 @@ if(BUILD_FAIRMQ OR BUILD_SDK)
Tools Tools
) )
set_target_properties(${target} PROPERTIES set_target_properties(${target} PROPERTIES
VERSION ${PROJECT_GIT_VERSION} VERSION ${PROJECT_VERSION}
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
OUTPUT_NAME FairMQ${target} OUTPUT_NAME FairMQ${target}
) )
@@ -174,43 +170,29 @@ if(BUILD_FAIRMQ)
PluginManager.h PluginManager.h
PluginServices.h PluginServices.h
runFairMQDevice.h runFairMQDevice.h
shmem/Monitor.h
) )
set(FAIRMQ_PRIVATE_HEADER_FILES set(FAIRMQ_PRIVATE_HEADER_FILES
devices/FairMQBenchmarkSampler.h
devices/FairMQMerger.h
devices/FairMQMultiplier.h
devices/FairMQProxy.h
devices/FairMQSink.h
devices/FairMQSplitter.h
plugins/Builtin.h plugins/Builtin.h
plugins/config/Config.h plugins/config/Config.h
plugins/Control.h plugins/Control.h
shmem/FairMQMessageSHM.h shmem/Message.h
shmem/FairMQPollerSHM.h shmem/Poller.h
shmem/FairMQUnmanagedRegionSHM.h shmem/UnmanagedRegion.h
shmem/FairMQSocketSHM.h shmem/Socket.h
shmem/FairMQTransportFactorySHM.h shmem/TransportFactory.h
shmem/Common.h shmem/Common.h
shmem/Manager.h shmem/Manager.h
shmem/Region.h shmem/Region.h
zeromq/FairMQMessageZMQ.h zeromq/Context.h
zeromq/FairMQPollerZMQ.h zeromq/Message.h
zeromq/FairMQUnmanagedRegionZMQ.h zeromq/Poller.h
zeromq/FairMQSocketZMQ.h zeromq/UnmanagedRegion.h
zeromq/FairMQTransportFactoryZMQ.h zeromq/Socket.h
zeromq/TransportFactory.h
) )
if(BUILD_NANOMSG_TRANSPORT)
set(FAIRMQ_PRIVATE_HEADER_FILES ${FAIRMQ_PRIVATE_HEADER_FILES}
nanomsg/FairMQMessageNN.h
nanomsg/FairMQPollerNN.h
nanomsg/FairMQUnmanagedRegionNN.h
nanomsg/FairMQSocketNN.h
nanomsg/FairMQTransportFactoryNN.h
)
endif()
if(BUILD_OFI_TRANSPORT) if(BUILD_OFI_TRANSPORT)
set(FAIRMQ_PRIVATE_HEADER_FILES ${FAIRMQ_PRIVATE_HEADER_FILES} set(FAIRMQ_PRIVATE_HEADER_FILES ${FAIRMQ_PRIVATE_HEADER_FILES}
ofi/Context.h ofi/Context.h
@@ -233,11 +215,6 @@ if(BUILD_FAIRMQ)
FairMQPoller.cxx FairMQPoller.cxx
FairMQSocket.cxx FairMQSocket.cxx
FairMQTransportFactory.cxx FairMQTransportFactory.cxx
devices/FairMQBenchmarkSampler.cxx
devices/FairMQMerger.cxx
devices/FairMQMultiplier.cxx
devices/FairMQProxy.cxx
devices/FairMQSplitter.cxx
Plugin.cxx Plugin.cxx
PluginManager.cxx PluginManager.cxx
PluginServices.cxx PluginServices.cxx
@@ -247,31 +224,10 @@ if(BUILD_FAIRMQ)
SuboptParser.cxx SuboptParser.cxx
plugins/config/Config.cxx plugins/config/Config.cxx
plugins/Control.cxx plugins/Control.cxx
shmem/FairMQMessageSHM.cxx
shmem/FairMQPollerSHM.cxx
shmem/FairMQUnmanagedRegionSHM.cxx
shmem/FairMQSocketSHM.cxx
shmem/FairMQTransportFactorySHM.cxx
shmem/Manager.cxx
shmem/Region.cxx
zeromq/FairMQMessageZMQ.cxx
zeromq/FairMQPollerZMQ.cxx
zeromq/FairMQUnmanagedRegionZMQ.cxx
zeromq/FairMQSocketZMQ.cxx
zeromq/FairMQTransportFactoryZMQ.cxx
MemoryResources.cxx MemoryResources.cxx
shmem/Monitor.cxx
) )
if(BUILD_NANOMSG_TRANSPORT)
set(FAIRMQ_SOURCE_FILES ${FAIRMQ_SOURCE_FILES}
nanomsg/FairMQMessageNN.cxx
nanomsg/FairMQPollerNN.cxx
nanomsg/FairMQUnmanagedRegionNN.cxx
nanomsg/FairMQSocketNN.cxx
nanomsg/FairMQTransportFactoryNN.cxx
)
endif()
if(BUILD_OFI_TRANSPORT) if(BUILD_OFI_TRANSPORT)
set(FAIRMQ_SOURCE_FILES ${FAIRMQ_SOURCE_FILES} set(FAIRMQ_SOURCE_FILES ${FAIRMQ_SOURCE_FILES}
ofi/Context.cxx ofi/Context.cxx
@@ -312,8 +268,8 @@ if(BUILD_FAIRMQ)
# preprocessor definitions # # preprocessor definitions #
############################ ############################
target_compile_definitions(${_target} PUBLIC BOOST_ERROR_CODE_HEADER_ONLY) target_compile_definitions(${_target} PUBLIC BOOST_ERROR_CODE_HEADER_ONLY)
if(BUILD_NANOMSG_TRANSPORT) if(FAIRMQ_DEBUG_MODE)
target_compile_definitions(${_target} PRIVATE BUILD_NANOMSG_TRANSPORT) target_compile_definitions(${_target} PUBLIC FAIRMQ_DEBUG_MODE)
endif() endif()
if(BUILD_OFI_TRANSPORT) if(BUILD_OFI_TRANSPORT)
target_compile_definitions(${_target} PRIVATE BUILD_OFI_TRANSPORT) target_compile_definitions(${_target} PRIVATE BUILD_OFI_TRANSPORT)
@@ -335,16 +291,13 @@ if(BUILD_FAIRMQ)
################## ##################
# link libraries # # link libraries #
################## ##################
if(BUILD_NANOMSG_TRANSPORT)
set(NANOMSG_DEPS nanomsg msgpackc-cxx)
endif()
if(BUILD_OFI_TRANSPORT) if(BUILD_OFI_TRANSPORT)
set(OFI_DEPS set(OFI_DEPS
asiofi::asiofi asiofi::asiofi
Boost::container Boost::container
) )
endif() endif()
set(optional_deps ${NANOMSG_DEPS} ${OFI_DEPS}) set(optional_deps ${OFI_DEPS})
if(optional_deps) if(optional_deps)
list(REMOVE_DUPLICATES optional_deps) list(REMOVE_DUPLICATES optional_deps)
endif() endif()
@@ -367,11 +320,11 @@ if(BUILD_FAIRMQ)
PRIVATE # only libFairMQ links against private dependencies PRIVATE # only libFairMQ links against private dependencies
libzmq libzmq
${NANOMSG_DEPS} PicoSHA2
${OFI_DEPS} ${OFI_DEPS}
) )
set_target_properties(${_target} PROPERTIES set_target_properties(${_target} PROPERTIES
VERSION ${PROJECT_GIT_VERSION} VERSION ${PROJECT_VERSION}
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
) )
@@ -414,12 +367,17 @@ if(BUILD_FAIRMQ)
add_executable(fairmq-shmmonitor shmem/Monitor.cxx shmem/Monitor.h shmem/runMonitor.cxx) add_executable(fairmq-shmmonitor shmem/Monitor.cxx shmem/Monitor.h shmem/runMonitor.cxx)
target_compile_definitions(fairmq-shmmonitor PUBLIC BOOST_ERROR_CODE_HEADER_ONLY) target_compile_definitions(fairmq-shmmonitor PUBLIC BOOST_ERROR_CODE_HEADER_ONLY)
if(FAIRMQ_DEBUG_MODE)
target_compile_definitions(fairmq-shmmonitor PUBLIC FAIRMQ_DEBUG_MODE)
endif()
target_link_libraries(fairmq-shmmonitor PUBLIC target_link_libraries(fairmq-shmmonitor PUBLIC
Threads::Threads Threads::Threads
$<$<PLATFORM_ID:Linux>:rt> $<$<PLATFORM_ID:Linux>:rt>
Boost::boost Boost::boost
Boost::date_time Boost::date_time
Boost::program_options Boost::program_options
FairLogger::FairLogger
PicoSHA2
) )
target_include_directories(fairmq-shmmonitor PUBLIC target_include_directories(fairmq-shmmonitor PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
@@ -460,6 +418,20 @@ if(BUILD_FAIRMQ)
endforeach() endforeach()
endif() endif()
if(BUILD_SDK_COMMANDS)
add_subdirectory(sdk/commands)
endif()
if(BUILD_SDK) if(BUILD_SDK)
add_subdirectory(sdk) add_subdirectory(sdk)
endif() endif()
####################
# external plugins #
####################
if(BUILD_DDS_PLUGIN)
add_subdirectory(plugins/DDS)
endif()
if(BUILD_PMIX_PLUGIN)
add_subdirectory(plugins/PMIx)
endif()

View File

@@ -8,10 +8,14 @@
#include "DeviceRunner.h" #include "DeviceRunner.h"
#include <exception> #include <fairmq/tools/Strings.h>
#include <fairmq/Tools.h> #include <fairmq/tools/Version.h>
#include <fairmq/Version.h> #include <fairmq/Version.h>
#include <fairlogger/Logger.h>
#include <exception>
using namespace std; using namespace std;
using namespace fair::mq; using namespace fair::mq;
@@ -63,8 +67,6 @@ bool DeviceRunner::HandleGeneralOptions(const fair::mq::ProgOptions& config, boo
<< " / __/ / /_/ / / / _ / / / / /_/ / " << FAIRMQ_REPO_URL << endl << " / __/ / /_/ / / / _ / / / / /_/ / " << FAIRMQ_REPO_URL << endl
<< " /_/ \\__,_/_/_/ /_/ /_/ \\___\\_\\ " << FAIRMQ_LICENSE << " © " << FAIRMQ_COPYRIGHT << endl; << " /_/ \\__,_/_/_/ /_/ /_/ \\___\\_\\ " << FAIRMQ_LICENSE << " © " << FAIRMQ_COPYRIGHT << endl;
} }
config.PrintOptions();
} }
return true; return true;
@@ -77,7 +79,7 @@ void DeviceRunner::SubscribeForConfigChange()
fair::Logger::SetConsoleColor(val); fair::Logger::SetConsoleColor(val);
} }
}); });
fConfig.Subscribe<string>("device-runner", [&](const std::string& key, const std::string val) { fConfig.Subscribe<string>("device-runner", [&](const std::string& key, const std::string& val) {
if (key == "severity") { if (key == "severity") {
fair::Logger::SetConsoleSeverity(val); fair::Logger::SetConsoleSeverity(val);
} else if (key == "file-severity") { } else if (key == "file-severity") {
@@ -169,6 +171,9 @@ auto DeviceRunner::Run() -> int
// Instantiate and run plugins // Instantiate and run plugins
fPluginManager.InstantiatePlugins(); fPluginManager.InstantiatePlugins();
// Log IDLE configuration
fConfig.PrintOptions();
// Run the device // Run the device
fDevice->RunStateMachine(); fDevice->RunStateMachine();

View File

@@ -13,7 +13,6 @@
#include <fairmq/PluginManager.h> #include <fairmq/PluginManager.h>
#include <fairmq/ProgOptions.h> #include <fairmq/ProgOptions.h>
#include <FairMQDevice.h> #include <FairMQDevice.h>
#include <FairMQLogger.h>
#include <functional> #include <functional>
#include <memory> #include <memory>

View File

@@ -12,12 +12,10 @@
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <tuple>
#include <typeindex> #include <typeindex>
#include <typeinfo>
#include <unordered_map> #include <unordered_map>
#include <utility> #include <utility>
#include <vector> #include <functional>
#include <boost/any.hpp> #include <boost/any.hpp>
#include <boost/functional/hash.hpp> #include <boost/functional/hash.hpp>

View File

@@ -7,10 +7,15 @@
********************************************************************************/ ********************************************************************************/
#include "FairMQChannel.h" #include "FairMQChannel.h"
#include <fairmq/Tools.h>
#include <fairmq/tools/Strings.h>
#include <fairmq/Properties.h>
#include <fairlogger/Logger.h>
#include <boost/algorithm/string.hpp> // join/split #include <boost/algorithm/string.hpp> // join/split
#include <cstddef> // size_t
#include <regex> #include <regex>
#include <set> #include <set>
#include <random> #include <random>
@@ -19,7 +24,7 @@ using namespace std;
using namespace fair::mq; using namespace fair::mq;
template<typename T> template<typename T>
T GetPropertyOrDefault(const fair::mq::Properties& m, const string& k, const T& ifNotFound) noexcept T GetPropertyOrDefault(const fair::mq::Properties& m, const string& k, const T& ifNotFound)
{ {
if (m.count(k)) { if (m.count(k)) {
return boost::any_cast<T>(m.at(k)); return boost::any_cast<T>(m.at(k));
@@ -132,26 +137,37 @@ FairMQChannel::FairMQChannel(const FairMQChannel& chan, const string& newName)
FairMQChannel& FairMQChannel::operator=(const FairMQChannel& chan) FairMQChannel& FairMQChannel::operator=(const FairMQChannel& chan)
{ {
fTransportFactory = nullptr; if (this == &chan) {
fTransportType = chan.fTransportType; return *this;
fSocket = nullptr; }
fName = chan.fName;
fType = chan.fType; {
fMethod = chan.fMethod; // TODO: replace this with std::scoped_lock (c++17)
fAddress = chan.fAddress; lock(fMtx, chan.fMtx);
fSndBufSize = chan.fSndBufSize; lock_guard<mutex> lock1(fMtx, adopt_lock);
fRcvBufSize = chan.fRcvBufSize; lock_guard<mutex> lock2(chan.fMtx, adopt_lock);
fSndKernelSize = chan.fSndKernelSize;
fRcvKernelSize = chan.fRcvKernelSize; fTransportFactory = nullptr;
fLinger = chan.fLinger; fTransportType = chan.fTransportType;
fRateLogging = chan.fRateLogging; fSocket = nullptr;
fPortRangeMin = chan.fPortRangeMin; fName = chan.fName;
fPortRangeMax = chan.fPortRangeMax; fType = chan.fType;
fAutoBind = chan.fAutoBind; fMethod = chan.fMethod;
fIsValid = false; fAddress = chan.fAddress;
fMultipart = chan.fMultipart; fSndBufSize = chan.fSndBufSize;
fModified = chan.fModified; fRcvBufSize = chan.fRcvBufSize;
fReset = false; fSndKernelSize = chan.fSndKernelSize;
fRcvKernelSize = chan.fRcvKernelSize;
fLinger = chan.fLinger;
fRateLogging = chan.fRateLogging;
fPortRangeMin = chan.fPortRangeMin;
fPortRangeMax = chan.fPortRangeMax;
fAutoBind = chan.fAutoBind;
fIsValid = false;
fMultipart = chan.fMultipart;
fModified = chan.fModified;
fReset = false;
}
return *this; return *this;
} }
@@ -659,7 +675,6 @@ void FairMQChannel::Init()
bool FairMQChannel::ConnectEndpoint(const string& endpoint) bool FairMQChannel::ConnectEndpoint(const string& endpoint)
{ {
lock_guard<mutex> lock(fMtx); lock_guard<mutex> lock(fMtx);
return fSocket->Connect(endpoint); return fSocket->Connect(endpoint);
} }
@@ -671,6 +686,13 @@ bool FairMQChannel::BindEndpoint(string& endpoint)
if (fSocket->Bind(endpoint)) { if (fSocket->Bind(endpoint)) {
return true; return true;
} else { } else {
// auto-bind only implemented for TCP
size_t protocolPos = endpoint.find(':');
string protocol = endpoint.substr(0, protocolPos);
if (protocol != "tcp") {
return false;
}
if (fAutoBind) { if (fAutoBind) {
// number of attempts when choosing a random port // number of attempts when choosing a random port
int numAttempts = 0; int numAttempts = 0;

View File

@@ -10,22 +10,20 @@
#define FAIRMQCHANNEL_H_ #define FAIRMQCHANNEL_H_
#include <FairMQTransportFactory.h> #include <FairMQTransportFactory.h>
#include <FairMQUnmanagedRegion.h>
#include <FairMQSocket.h> #include <FairMQSocket.h>
#include <fairmq/Transports.h> #include <fairmq/Transports.h>
#include <FairMQLogger.h>
#include <FairMQParts.h> #include <FairMQParts.h>
#include <fairmq/Properties.h> #include <fairmq/Properties.h>
#include <FairMQMessage.h> #include <FairMQMessage.h>
#include <boost/any.hpp>
#include <string> #include <string>
#include <memory> // unique_ptr, shared_ptr #include <memory> // unique_ptr, shared_ptr
#include <vector> #include <vector>
#include <atomic>
#include <mutex> #include <mutex>
#include <stdexcept> #include <stdexcept>
#include <utility> // std::move #include <utility> // std::move
#include <cstdint> // int64_t
class FairMQChannel class FairMQChannel
{ {
@@ -68,13 +66,13 @@ class FairMQChannel
FairMQChannel(const FairMQChannel&, const std::string& name); FairMQChannel(const FairMQChannel&, const std::string& name);
/// Move constructor /// Move constructor
FairMQChannel(FairMQChannel&&) = default; // FairMQChannel(FairMQChannel&&) = delete;
/// Assignment operator /// Assignment operator
FairMQChannel& operator=(const FairMQChannel&); FairMQChannel& operator=(const FairMQChannel&);
/// Move assignment operator /// Move assignment operator
FairMQChannel& operator=(FairMQChannel&&) = default; // FairMQChannel& operator=(FairMQChannel&&) = delete;
/// Destructor /// Destructor
virtual ~FairMQChannel() virtual ~FairMQChannel()
@@ -127,8 +125,8 @@ class FairMQChannel
/// @return Returns socket address (e.g. "tcp://127.0.0.1:5555" or "ipc://abc") /// @return Returns socket address (e.g. "tcp://127.0.0.1:5555" or "ipc://abc")
std::string GetAddress() const; std::string GetAddress() const;
/// Get channel transport name ("default", "zeromq", "nanomsg" or "shmem") /// Get channel transport name ("default", "zeromq" or "shmem")
/// @return Returns channel transport name (e.g. "default", "zeromq", "nanomsg" or "shmem") /// @return Returns channel transport name (e.g. "default", "zeromq" or "shmem")
std::string GetTransportName() const; std::string GetTransportName() const;
/// Get channel transport type /// Get channel transport type
@@ -184,7 +182,7 @@ class FairMQChannel
void UpdateAddress(const std::string& address); void UpdateAddress(const std::string& address);
/// Set channel transport /// Set channel transport
/// @param transport transport string ("default", "zeromq", "nanomsg" or "shmem") /// @param transport transport string ("default", "zeromq" or "shmem")
void UpdateTransport(const std::string& transport); void UpdateTransport(const std::string& transport);
/// Set socket send buffer size /// Set socket send buffer size
@@ -252,7 +250,7 @@ class FairMQChannel
/// Sends a message to the socket queue. /// Sends a message to the socket queue.
/// @param msg Constant reference of unique_ptr to a FairMQMessage /// @param msg Constant reference of unique_ptr to a FairMQMessage
/// @param sndTimeoutInMs send timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send) /// @param sndTimeoutInMs send timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send)
/// @return Number of bytes that have been queued. -2 If queueing was not possible or timed out. -1 if there was an error. /// @return Number of bytes that have been queued, TransferResult::timeout if timed out, TransferResult::error if there was an error, TransferResult::interrupted if interrupted (e.g. by requested state change)
int Send(FairMQMessagePtr& msg, int sndTimeoutInMs = -1) int Send(FairMQMessagePtr& msg, int sndTimeoutInMs = -1)
{ {
CheckSendCompatibility(msg); CheckSendCompatibility(msg);
@@ -262,7 +260,7 @@ class FairMQChannel
/// Receives a message from the socket queue. /// Receives a message from the socket queue.
/// @param msg Constant reference of unique_ptr to a FairMQMessage /// @param msg Constant reference of unique_ptr to a FairMQMessage
/// @param rcvTimeoutInMs receive timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot receive) /// @param rcvTimeoutInMs receive timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot receive)
/// @return Number of bytes that have been received. -2 if reading from the queue was not possible or timed out. -1 if there was an error. /// @return Number of bytes that have been received, TransferResult::timeout if timed out, TransferResult::error if there was an error, TransferResult::interrupted if interrupted (e.g. by requested state change)
int Receive(FairMQMessagePtr& msg, int rcvTimeoutInMs = -1) int Receive(FairMQMessagePtr& msg, int rcvTimeoutInMs = -1)
{ {
CheckReceiveCompatibility(msg); CheckReceiveCompatibility(msg);
@@ -272,7 +270,7 @@ class FairMQChannel
/// Send a vector of messages /// Send a vector of messages
/// @param msgVec message vector reference /// @param msgVec message vector reference
/// @param sndTimeoutInMs send timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send) /// @param sndTimeoutInMs send timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send)
/// @return Number of bytes that have been queued. -2 If queueing was not possible or timed out. -1 if there was an error. /// @return Number of bytes that have been queued, TransferResult::timeout if timed out, TransferResult::error if there was an error, TransferResult::interrupted if interrupted (e.g. by requested state change)
int64_t Send(std::vector<FairMQMessagePtr>& msgVec, int sndTimeoutInMs = -1) int64_t Send(std::vector<FairMQMessagePtr>& msgVec, int sndTimeoutInMs = -1)
{ {
CheckSendCompatibility(msgVec); CheckSendCompatibility(msgVec);
@@ -282,7 +280,7 @@ class FairMQChannel
/// Receive a vector of messages /// Receive a vector of messages
/// @param msgVec message vector reference /// @param msgVec message vector reference
/// @param rcvTimeoutInMs receive timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot receive) /// @param rcvTimeoutInMs receive timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot receive)
/// @return Number of bytes that have been received. -2 if reading from the queue was not possible or timed out. -1 if there was an error. /// @return Number of bytes that have been received, TransferResult::timeout if timed out, TransferResult::error if there was an error, TransferResult::interrupted if interrupted (e.g. by requested state change)
int64_t Receive(std::vector<FairMQMessagePtr>& msgVec, int rcvTimeoutInMs = -1) int64_t Receive(std::vector<FairMQMessagePtr>& msgVec, int rcvTimeoutInMs = -1)
{ {
CheckReceiveCompatibility(msgVec); CheckReceiveCompatibility(msgVec);
@@ -292,7 +290,7 @@ class FairMQChannel
/// Send FairMQParts /// Send FairMQParts
/// @param parts FairMQParts reference /// @param parts FairMQParts reference
/// @param sndTimeoutInMs send timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send) /// @param sndTimeoutInMs send timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send)
/// @return Number of bytes that have been queued. -2 If queueing was not possible or timed out. -1 if there was an error. /// @return Number of bytes that have been queued, TransferResult::timeout if timed out, TransferResult::error if there was an error, TransferResult::interrupted if interrupted (e.g. by requested state change)
int64_t Send(FairMQParts& parts, int sndTimeoutInMs = -1) int64_t Send(FairMQParts& parts, int sndTimeoutInMs = -1)
{ {
return Send(parts.fParts, sndTimeoutInMs); return Send(parts.fParts, sndTimeoutInMs);
@@ -301,7 +299,7 @@ class FairMQChannel
/// Receive FairMQParts /// Receive FairMQParts
/// @param parts FairMQParts reference /// @param parts FairMQParts reference
/// @param rcvTimeoutInMs receive timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot receive) /// @param rcvTimeoutInMs receive timeout in ms. -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot receive)
/// @return Number of bytes that have been received. -2 if reading from the queue was not possible or timed out. -1 if there was an error. /// @return Number of bytes that have been received, TransferResult::timeout if timed out, TransferResult::error if there was an error, TransferResult::interrupted if interrupted (e.g. by requested state change)
int64_t Receive(FairMQParts& parts, int rcvTimeoutInMs = -1) int64_t Receive(FairMQParts& parts, int rcvTimeoutInMs = -1)
{ {
return Receive(parts.fParts, rcvTimeoutInMs); return Receive(parts.fParts, rcvTimeoutInMs);
@@ -335,9 +333,10 @@ class FairMQChannel
return Transport()->NewStaticMessage(data); return Transport()->NewStaticMessage(data);
} }
FairMQUnmanagedRegionPtr NewUnmanagedRegion(const size_t size, FairMQRegionCallback callback = nullptr, const std::string& path = "", int flags = 0) template<typename... Args>
FairMQUnmanagedRegionPtr NewUnmanagedRegion(Args&&... args)
{ {
return Transport()->CreateUnmanagedRegion(size, callback, path, flags); return Transport()->CreateUnmanagedRegion(std::forward<Args>(args)...);
} }
static constexpr fair::mq::Transport DefaultTransportType = fair::mq::Transport::DEFAULT; static constexpr fair::mq::Transport DefaultTransportType = fair::mq::Transport::DEFAULT;

View File

@@ -8,19 +8,15 @@
#include <FairMQDevice.h> #include <FairMQDevice.h>
#include <fairmq/tools/RateLimit.h>
#include <fairmq/tools/Network.h>
#include <boost/algorithm/string.hpp> // join/split #include <boost/algorithm/string.hpp> // join/split
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <list> #include <list>
#include <cstdlib>
#include <chrono> #include <chrono>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
#include <functional>
#include <sstream>
#include <iomanip> #include <iomanip>
#include <future> #include <future>
#include <algorithm> // std::max #include <algorithm> // std::max
@@ -303,10 +299,15 @@ void FairMQDevice::InitWrapper()
// if binding address is not specified, try getting it from the configured network interface // if binding address is not specified, try getting it from the configured network interface
if (subChannel.fAddress == "unspecified" || subChannel.fAddress == "") { if (subChannel.fAddress == "unspecified" || subChannel.fAddress == "") {
// if the configured network interface is default, get its name from the default route // if the configured network interface is default, get its name from the default route
if (networkInterface == "default") { try {
networkInterface = tools::getDefaultRouteNetworkInterface(); if (networkInterface == "default") {
networkInterface = tools::getDefaultRouteNetworkInterface();
}
subChannel.fAddress = "tcp://" + tools::getInterfaceIP(networkInterface) + ":1";
} catch(const tools::DefaultRouteDetectionError& e) {
LOG(debug) << "binding on tcp://*:1";
subChannel.fAddress = "tcp://*:1";
} }
subChannel.fAddress = "tcp://" + tools::getInterfaceIP(networkInterface) + ":1";
} }
// fill the uninitialized list // fill the uninitialized list
fUninitializedBindingChannels.push_back(&subChannel); fUninitializedBindingChannels.push_back(&subChannel);
@@ -482,32 +483,6 @@ void FairMQDevice::InitTaskWrapper()
ChangeState(Transition::Auto); ChangeState(Transition::Auto);
} }
bool FairMQDevice::SortSocketsByAddress(const FairMQChannel &lhs, const FairMQChannel &rhs)
{
return lhs.fAddress < rhs.fAddress;
}
void FairMQDevice::SortChannel(const string& name, const bool reindex)
{
if (fChannels.find(name) != fChannels.end())
{
sort(fChannels.at(name).begin(), fChannels.at(name).end(), SortSocketsByAddress);
if (reindex)
{
for (auto vi = fChannels.at(name).begin(); vi != fChannels.at(name).end(); ++vi)
{
// set channel name: name + vector index
vi->fName = tools::ToString(name, "[", vi - fChannels.at(name).begin(), "]");
}
}
}
else
{
LOG(error) << "Sorting failed: no channel with the name \"" << name << "\".";
}
}
void FairMQDevice::RunWrapper() void FairMQDevice::RunWrapper()
{ {
LOG(info) << "DEVICE: Running..."; LOG(info) << "DEVICE: Running...";

View File

@@ -14,7 +14,6 @@
#include <fairmq/Transports.h> #include <fairmq/Transports.h>
#include <fairmq/StateQueue.h> #include <fairmq/StateQueue.h>
#include <FairMQSocket.h>
#include <FairMQChannel.h> #include <FairMQChannel.h>
#include <FairMQMessage.h> #include <FairMQMessage.h>
#include <FairMQParts.h> #include <FairMQParts.h>
@@ -24,21 +23,19 @@
#include <vector> #include <vector>
#include <memory> // unique_ptr #include <memory> // unique_ptr
#include <algorithm> // std::sort() #include <algorithm> // find
#include <string> #include <string>
#include <chrono> #include <chrono>
#include <iostream> #include <iostream>
#include <unordered_map> #include <unordered_map>
#include <functional> #include <functional>
#include <assert.h> // static_assert
#include <type_traits> // is_trivially_copyable
#include <stdexcept> #include <stdexcept>
#include <queue>
#include <mutex> #include <mutex>
#include <condition_variable> #include <atomic>
#include <cstddef>
#include <utility> // pair
#include <fairmq/Tools.h> #include <fairmq/tools/Version.h>
using FairMQChannelMap = std::unordered_map<std::string, std::vector<FairMQChannel>>; using FairMQChannelMap = std::unordered_map<std::string, std::vector<FairMQChannel>>;
@@ -115,11 +112,6 @@ class FairMQDevice
/// Outputs the socket transfer rates /// Outputs the socket transfer rates
virtual void LogSocketRates(); virtual void LogSocketRates();
/// Sorts a channel by address, with optional reindexing of the sorted values
/// @param name Channel name
/// @param reindex Should reindexing be done
void SortChannel(const std::string& name, const bool reindex = true);
template<typename Serializer, typename DataType, typename... Args> template<typename Serializer, typename DataType, typename... Args>
void Serialize(FairMQMessage& msg, DataType&& data, Args&&... args) const void Serialize(FairMQMessage& msg, DataType&& data, Args&&... args) const
{ {
@@ -137,7 +129,7 @@ class FairMQDevice
/// @param chan channel name /// @param chan channel name
/// @param i channel index /// @param i channel index
/// @param sndTimeoutInMs send timeout in ms, -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send) /// @param sndTimeoutInMs send timeout in ms, -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send)
/// @return Number of bytes that have been queued. -2 If queueing was not possible or timed out. -1 if there was an error. /// @return Number of bytes that have been queued, TransferResult::timeout if timed out, TransferResult::error if there was an error, TransferResult::interrupted if interrupted (e.g. by requested state change)
int Send(FairMQMessagePtr& msg, const std::string& channel, const int index = 0, int sndTimeoutInMs = -1) int Send(FairMQMessagePtr& msg, const std::string& channel, const int index = 0, int sndTimeoutInMs = -1)
{ {
return GetChannel(channel, index).Send(msg, sndTimeoutInMs); return GetChannel(channel, index).Send(msg, sndTimeoutInMs);
@@ -148,27 +140,18 @@ class FairMQDevice
/// @param chan channel name /// @param chan channel name
/// @param i channel index /// @param i channel index
/// @param rcvTimeoutInMs receive timeout in ms, -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot receive) /// @param rcvTimeoutInMs receive timeout in ms, -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot receive)
/// @return Number of bytes that have been received. -2 if reading from the queue was not possible or timed out. -1 if there was an error. /// @return Number of bytes that have been received, TransferResult::timeout if timed out, TransferResult::error if there was an error, TransferResult::interrupted if interrupted (e.g. by requested state change)
int Receive(FairMQMessagePtr& msg, const std::string& channel, const int index = 0, int rcvTimeoutInMs = -1) int Receive(FairMQMessagePtr& msg, const std::string& channel, const int index = 0, int rcvTimeoutInMs = -1)
{ {
return GetChannel(channel, index).Receive(msg, rcvTimeoutInMs); return GetChannel(channel, index).Receive(msg, rcvTimeoutInMs);
} }
int SendAsync(FairMQMessagePtr& msg, const std::string& channel, const int index = 0) __attribute__((deprecated("For non-blocking Send, use timeout version with timeout of 0: Send(msg, \"channelA\", subchannelIndex, timeout);")))
{
return GetChannel(channel, index).Send(msg, 0);
}
int ReceiveAsync(FairMQMessagePtr& msg, const std::string& channel, const int index = 0) __attribute__((deprecated("For non-blocking Receive, use timeout version with timeout of 0: Receive(msg, \"channelA\", subchannelIndex, timeout);")))
{
return GetChannel(channel, index).Receive(msg, 0);
}
/// Shorthand method to send FairMQParts on `chan` at index `i` /// Shorthand method to send FairMQParts on `chan` at index `i`
/// @param parts parts reference /// @param parts parts reference
/// @param chan channel name /// @param chan channel name
/// @param i channel index /// @param i channel index
/// @param sndTimeoutInMs send timeout in ms, -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send) /// @param sndTimeoutInMs send timeout in ms, -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot send)
/// @return Number of bytes that have been queued. -2 If queueing was not possible or timed out. -1 if there was an error. /// @return Number of bytes that have been queued, TransferResult::timeout if timed out, TransferResult::error if there was an error, TransferResult::interrupted if interrupted (e.g. by requested state change)
int64_t Send(FairMQParts& parts, const std::string& channel, const int index = 0, int sndTimeoutInMs = -1) int64_t Send(FairMQParts& parts, const std::string& channel, const int index = 0, int sndTimeoutInMs = -1)
{ {
return GetChannel(channel, index).Send(parts.fParts, sndTimeoutInMs); return GetChannel(channel, index).Send(parts.fParts, sndTimeoutInMs);
@@ -179,21 +162,12 @@ class FairMQDevice
/// @param chan channel name /// @param chan channel name
/// @param i channel index /// @param i channel index
/// @param rcvTimeoutInMs receive timeout in ms, -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot receive) /// @param rcvTimeoutInMs receive timeout in ms, -1 will wait forever (or until interrupt (e.g. via state change)), 0 will not wait (return immediately if cannot receive)
/// @return Number of bytes that have been received. -2 if reading from the queue was not possible or timed out. -1 if there was an error. /// @return Number of bytes that have been received, TransferResult::timeout if timed out, TransferResult::error if there was an error, TransferResult::interrupted if interrupted (e.g. by requested state change)
int64_t Receive(FairMQParts& parts, const std::string& channel, const int index = 0, int rcvTimeoutInMs = -1) int64_t Receive(FairMQParts& parts, const std::string& channel, const int index = 0, int rcvTimeoutInMs = -1)
{ {
return GetChannel(channel, index).Receive(parts.fParts, rcvTimeoutInMs); return GetChannel(channel, index).Receive(parts.fParts, rcvTimeoutInMs);
} }
int64_t SendAsync(FairMQParts& parts, const std::string& channel, const int index = 0) __attribute__((deprecated("For non-blocking Send, use timeout version with timeout of 0: Send(parts, \"channelA\", subchannelIndex, timeout);")))
{
return GetChannel(channel, index).Send(parts.fParts, 0);
}
int64_t ReceiveAsync(FairMQParts& parts, const std::string& channel, const int index = 0) __attribute__((deprecated("For non-blocking Receive, use timeout version with timeout of 0: Receive(parts, \"channelA\", subchannelIndex, timeout);")))
{
return GetChannel(channel, index).Receive(parts.fParts, 0);
}
/// @brief Getter for default transport factory /// @brief Getter for default transport factory
auto Transport() const -> FairMQTransportFactory* auto Transport() const -> FairMQTransportFactory*
{ {
@@ -243,15 +217,17 @@ class FairMQDevice
} }
// creates unamanaged region with the default device transport // creates unamanaged region with the default device transport
FairMQUnmanagedRegionPtr NewUnmanagedRegion(const size_t size, FairMQRegionCallback callback = nullptr) template<typename... Args>
FairMQUnmanagedRegionPtr NewUnmanagedRegion(Args&&... args)
{ {
return Transport()->CreateUnmanagedRegion(size, callback); return Transport()->CreateUnmanagedRegion(std::forward<Args>(args)...);
} }
// creates unmanaged region with the transport of the specified channel // creates unmanaged region with the transport of the specified channel
FairMQUnmanagedRegionPtr NewUnmanagedRegionFor(const std::string& channel, int index, const size_t size, FairMQRegionCallback callback = nullptr, const std::string& path = "", int flags = 0) template<typename... Args>
FairMQUnmanagedRegionPtr NewUnmanagedRegionFor(const std::string& channel, int index, Args&&... args)
{ {
return GetChannel(channel, index).NewUnmanagedRegion(size, callback, path, flags); return GetChannel(channel, index).NewUnmanagedRegion(std::forward<Args>(args)...);
} }
template<typename ...Ts> template<typename ...Ts>
@@ -297,11 +273,8 @@ class FairMQDevice
return channels.at(0)->Transport()->CreatePoller(channels); return channels.at(0)->Transport()->CreatePoller(channels);
} }
/// Waits for the first initialization run to finish
void WaitForInitialValidation() __attribute__((deprecated("This method will have no effect in future versions and will be removed. Instead subscribe for state changes and inspect configuration values."))) {}
/// Adds a transport to the device if it doesn't exist /// Adds a transport to the device if it doesn't exist
/// @param transport Transport string ("zeromq"/"nanomsg"/"shmem") /// @param transport Transport string ("zeromq"/"shmem")
std::shared_ptr<FairMQTransportFactory> AddTransport(const fair::mq::Transport transport); std::shared_ptr<FairMQTransportFactory> AddTransport(const fair::mq::Transport transport);
/// Assigns config to the device /// Assigns config to the device
@@ -312,11 +285,6 @@ class FairMQDevice
return fConfig; return fConfig;
} }
/// Implements the sort algorithm used in SortChannel()
/// @param lhs Right hand side value for comparison
/// @param rhs Left hand side value for comparison
static bool SortSocketsByAddress(const FairMQChannel &lhs, const FairMQChannel &rhs);
// overload to easily bind member functions // overload to easily bind member functions
template<typename T> template<typename T>
void OnData(const std::string& channelName, bool (T::* memberFunction)(FairMQMessagePtr& msg, int index)) void OnData(const std::string& channelName, bool (T::* memberFunction)(FairMQMessagePtr& msg, int index))
@@ -421,7 +389,7 @@ class FairMQDevice
int GetInitTimeoutInS() const { return fConfig->GetProperty<int>("init-timeout", DefaultInitTimeout); } int GetInitTimeoutInS() const { return fConfig->GetProperty<int>("init-timeout", DefaultInitTimeout); }
/// Sets the default transport for the device /// Sets the default transport for the device
/// @param transport Transport string ("zeromq"/"nanomsg"/"shmem") /// @param transport Transport string ("zeromq"/"shmem")
void SetTransport(const std::string& transport) { fConfig->SetProperty("transport", transport); } void SetTransport(const std::string& transport) { fConfig->SetProperty("transport", transport); }
/// Gets the default transport name /// Gets the default transport name
std::string GetTransportName() const { return fConfig->GetProperty<std::string>("transport", DefaultTransportName); } std::string GetTransportName() const { return fConfig->GetProperty<std::string>("transport", DefaultTransportName); }

View File

@@ -11,17 +11,33 @@
#include <cstddef> // for size_t #include <cstddef> // for size_t
#include <memory> // unique_ptr #include <memory> // unique_ptr
#include <stdexcept>
#include <fairmq/Transports.h> #include <fairmq/Transports.h>
using fairmq_free_fn = void(void* data, void* hint); using fairmq_free_fn = void(void* data, void* hint);
class FairMQTransportFactory; class FairMQTransportFactory;
namespace fair
{
namespace mq
{
struct Alignment
{
size_t alignment;
explicit operator size_t() const { return alignment; }
};
} /* namespace mq */
} /* namespace fair */
class FairMQMessage class FairMQMessage
{ {
public: public:
FairMQMessage() = default; FairMQMessage() = default;
FairMQMessage(FairMQTransportFactory* factory):fTransport{factory} {} FairMQMessage(FairMQTransportFactory* factory) : fTransport(factory) {}
virtual void Rebuild() = 0; virtual void Rebuild() = 0;
virtual void Rebuild(const size_t size) = 0; virtual void Rebuild(const size_t size) = 0;
virtual void Rebuild(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = nullptr) = 0; virtual void Rebuild(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = nullptr) = 0;
@@ -33,7 +49,7 @@ class FairMQMessage
virtual fair::mq::Transport GetType() const = 0; virtual fair::mq::Transport GetType() const = 0;
FairMQTransportFactory* GetTransport() { return fTransport; } FairMQTransportFactory* GetTransport() { return fTransport; }
//void SetTransport(FairMQTransportFactory* transport) { fTransport = transport; } void SetTransport(FairMQTransportFactory* transport) { fTransport = transport; }
virtual void Copy(const FairMQMessage& msg) = 0; virtual void Copy(const FairMQMessage& msg) = 0;
@@ -53,6 +69,7 @@ namespace mq
using Message = FairMQMessage; using Message = FairMQMessage;
using MessagePtr = FairMQMessagePtr; using MessagePtr = FairMQMessagePtr;
struct MessageError : std::runtime_error { using std::runtime_error::runtime_error; }; struct MessageError : std::runtime_error { using std::runtime_error::runtime_error; };
struct MessageBadAlloc : std::runtime_error { using std::runtime_error::runtime_error; };
} /* namespace mq */ } /* namespace mq */
} /* namespace fair */ } /* namespace fair */

View File

@@ -33,7 +33,7 @@ class FairMQParts
FairMQParts& operator=(const FairMQParts&) = delete; FairMQParts& operator=(const FairMQParts&) = delete;
/// Constructor from argument pack of std::unique_ptr<FairMQMessage> rvalues /// Constructor from argument pack of std::unique_ptr<FairMQMessage> rvalues
template <typename... Ts> template <typename... Ts>
FairMQParts(Ts&&... messages) : fParts() {AddPart(std::forward<Ts>(messages)...);} FairMQParts(Ts&&... messages) : fParts() { AddPart(std::forward<Ts>(messages)...); }
/// Default destructor /// Default destructor
~FairMQParts() {}; ~FairMQParts() {};
@@ -63,10 +63,10 @@ class FairMQParts
/// Add content of another object by move /// Add content of another object by move
void AddPart(FairMQParts&& other) void AddPart(FairMQParts&& other)
{ {
container parts = std::move(other.fParts); container parts = std::move(other.fParts);
for (auto& part : parts) { for (auto& part : parts) {
fParts.push_back(std::move(part)); fParts.push_back(std::move(part));
} }
} }
/// Get reference to part in the container at index (without bounds check) /// Get reference to part in the container at index (without bounds check)

View File

@@ -31,8 +31,8 @@ namespace fair
namespace mq namespace mq
{ {
using PollerPtr = std::unique_ptr<FairMQPoller>; using Poller = FairMQPoller;
using PollerPtr = FairMQPollerPtr;
struct PollerError : std::runtime_error { using std::runtime_error::runtime_error; }; struct PollerError : std::runtime_error { using std::runtime_error::runtime_error; };
} /* namespace mq */ } /* namespace mq */

View File

@@ -9,20 +9,38 @@
#ifndef FAIRMQSOCKET_H_ #ifndef FAIRMQSOCKET_H_
#define FAIRMQSOCKET_H_ #define FAIRMQSOCKET_H_
#include "FairMQMessage.h"
#include <memory>
#include <ostream>
#include <stdexcept>
#include <string> #include <string>
#include <vector> #include <vector>
#include <memory>
#include "FairMQMessage.h"
class FairMQTransportFactory; class FairMQTransportFactory;
namespace fair
{
namespace mq
{
enum class TransferResult : int
{
error = -1,
timeout = -2,
interrupted = -3
};
} // namespace mq
} // namespace fair
class FairMQSocket class FairMQSocket
{ {
public: public:
FairMQSocket() {} FairMQSocket() {}
FairMQSocket(FairMQTransportFactory* fac): fTransport(fac) {} FairMQSocket(FairMQTransportFactory* fac) : fTransport(fac) {}
virtual std::string GetId() = 0; virtual std::string GetId() const = 0;
virtual bool Bind(const std::string& address) = 0; virtual bool Bind(const std::string& address) = 0;
virtual bool Connect(const std::string& address) = 0; virtual bool Connect(const std::string& address) = 0;
@@ -37,6 +55,10 @@ class FairMQSocket
virtual void SetOption(const std::string& option, const void* value, size_t valueSize) = 0; virtual void SetOption(const std::string& option, const void* value, size_t valueSize) = 0;
virtual void GetOption(const std::string& option, void* value, size_t* valueSize) = 0; virtual void GetOption(const std::string& option, void* value, size_t* valueSize) = 0;
/// If the backend supports it, fills the unsigned integer @a events with the ZMQ_EVENTS value
/// DISCLAIMER: this API is experimental and unsupported and might be dropped / refactored in
/// the future.
virtual void Events(uint32_t* events) = 0;
virtual void SetLinger(const int value) = 0; virtual void SetLinger(const int value) = 0;
virtual int GetLinger() const = 0; virtual int GetLinger() const = 0;
virtual void SetSndBufSize(const int value) = 0; virtual void SetSndBufSize(const int value) = 0;
@@ -54,7 +76,7 @@ class FairMQSocket
virtual unsigned long GetMessagesRx() const = 0; virtual unsigned long GetMessagesRx() const = 0;
FairMQTransportFactory* GetTransport() { return fTransport; } FairMQTransportFactory* GetTransport() { return fTransport; }
void SetTransport(FairMQTransportFactory* transport) { fTransport=transport; } void SetTransport(FairMQTransportFactory* transport) { fTransport = transport; }
virtual ~FairMQSocket() {}; virtual ~FairMQSocket() {};

View File

@@ -7,70 +7,57 @@
********************************************************************************/ ********************************************************************************/
#include <FairMQTransportFactory.h> #include <FairMQTransportFactory.h>
#include <zeromq/FairMQTransportFactoryZMQ.h> #include <fairmq/shmem/TransportFactory.h>
#include <shmem/FairMQTransportFactorySHM.h> #include <fairmq/zeromq/TransportFactory.h>
#ifdef BUILD_NANOMSG_TRANSPORT
#include <nanomsg/FairMQTransportFactoryNN.h>
#endif /* BUILD_NANOMSG_TRANSPORT */
#ifdef BUILD_OFI_TRANSPORT #ifdef BUILD_OFI_TRANSPORT
#include <fairmq/ofi/TransportFactory.h> #include <fairmq/ofi/TransportFactory.h>
#endif #endif
#include <FairMQLogger.h> #include <FairMQLogger.h>
#include <fairmq/Tools.h> #include <fairmq/Tools.h>
#include <fairlogger/Logger.h>
#include <memory> #include <memory>
#include <string> #include <string>
#include <sstream>
FairMQTransportFactory::FairMQTransportFactory(const std::string& id) using namespace std;
FairMQTransportFactory::FairMQTransportFactory(const string& id)
: fkId(id) : fkId(id)
{ {}
}
auto FairMQTransportFactory::CreateTransportFactory(const std::string& type, const std::string& id, const fair::mq::ProgOptions* config) -> std::shared_ptr<FairMQTransportFactory> auto FairMQTransportFactory::CreateTransportFactory(const string& type,
const string& id,
const fair::mq::ProgOptions* config)
-> shared_ptr<FairMQTransportFactory>
{ {
using namespace std;
auto finalId = id; auto finalId = id;
// Generate uuid if empty // Generate uuid if empty
if (finalId == "") if (finalId == "") {
{
finalId = fair::mq::tools::Uuid(); finalId = fair::mq::tools::Uuid();
} }
if (type == "zeromq") if (type == "zeromq") {
{ return make_shared<fair::mq::zmq::TransportFactory>(finalId, config);
return make_shared<FairMQTransportFactoryZMQ>(finalId, config); } else if (type == "shmem") {
return make_shared<fair::mq::shmem::TransportFactory>(finalId, config);
} }
else if (type == "shmem")
{
return make_shared<FairMQTransportFactorySHM>(finalId, config);
}
#ifdef BUILD_NANOMSG_TRANSPORT
else if (type == "nanomsg")
{
return make_shared<FairMQTransportFactoryNN>(finalId, config);
}
#endif /* BUILD_NANOMSG_TRANSPORT */
#ifdef BUILD_OFI_TRANSPORT #ifdef BUILD_OFI_TRANSPORT
else if (type == "ofi") else if (type == "ofi") {
{
return make_shared<fair::mq::ofi::TransportFactory>(finalId, config); return make_shared<fair::mq::ofi::TransportFactory>(finalId, config);
} }
#endif /* BUILD_OFI_TRANSPORT */ #endif /* BUILD_OFI_TRANSPORT */
else else {
{ LOG(error) << "Unavailable transport requested: "
LOG(error) << "Unavailable transport requested: " << "\"" << type << "\"" << ". Available are: " << "\"" << type << "\""
<< "\"zeromq\"" << ". Available are: "
<< "\"zeromq\","
<< "\"shmem\"" << "\"shmem\""
#ifdef BUILD_NANOMSG_TRANSPORT
<< ", \"nanomsg\""
#endif /* BUILD_NANOMSG_TRANSPORT */
#ifdef BUILD_OFI_TRANSPORT #ifdef BUILD_OFI_TRANSPORT
<< ", and \"ofi\"" << ", and \"ofi\""
#endif /* BUILD_OFI_TRANSPORT */ #endif /* BUILD_OFI_TRANSPORT */
<< ". Exiting."; << ". Exiting.";
exit(EXIT_FAILURE); throw fair::mq::TransportFactoryError(fair::mq::tools::ToString("Unavailable transport requested: ", type));
} }
} }

View File

@@ -9,21 +9,22 @@
#ifndef FAIRMQTRANSPORTFACTORY_H_ #ifndef FAIRMQTRANSPORTFACTORY_H_
#define FAIRMQTRANSPORTFACTORY_H_ #define FAIRMQTRANSPORTFACTORY_H_
#include <FairMQLogger.h>
#include <FairMQMessage.h> #include <FairMQMessage.h>
#include <FairMQPoller.h> #include <FairMQPoller.h>
#include <fairmq/ProgOptionsFwd.h>
#include <FairMQSocket.h> #include <FairMQSocket.h>
#include <FairMQUnmanagedRegion.h> #include <FairMQUnmanagedRegion.h>
#include <fairmq/MemoryResources.h> #include <fairmq/MemoryResources.h>
#include <fairmq/Transports.h> #include <fairmq/Transports.h>
#include <string> #include <string>
#include <memory> #include <memory> // shared_ptr
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
#include <stdexcept>
#include <cstddef> // size_t
class FairMQChannel; class FairMQChannel;
namespace fair { namespace mq { class ProgOptions; } }
class FairMQTransportFactory class FairMQTransportFactory
{ {
@@ -45,13 +46,22 @@ class FairMQTransportFactory
fair::mq::ChannelResource* GetMemoryResource() { return &fMemoryResource; } fair::mq::ChannelResource* GetMemoryResource() { return &fMemoryResource; }
operator fair::mq::ChannelResource*() { return &fMemoryResource; } operator fair::mq::ChannelResource*() { return &fMemoryResource; }
/// @brief Create empty FairMQMessage /// @brief Create empty FairMQMessage (for receiving)
/// @return pointer to FairMQMessage /// @return pointer to FairMQMessage
virtual FairMQMessagePtr CreateMessage() = 0; virtual FairMQMessagePtr CreateMessage() = 0;
/// @brief Create empty FairMQMessage (for receiving), align received buffer to specified alignment
/// @param alignment alignment to align received buffer to
/// @return pointer to FairMQMessage
virtual FairMQMessagePtr CreateMessage(fair::mq::Alignment alignment) = 0;
/// @brief Create new FairMQMessage of specified size /// @brief Create new FairMQMessage of specified size
/// @param size message size /// @param size message size
/// @return pointer to FairMQMessage /// @return pointer to FairMQMessage
virtual FairMQMessagePtr CreateMessage(const size_t size) = 0; virtual FairMQMessagePtr CreateMessage(const size_t size) = 0;
/// @brief Create new FairMQMessage of specified size and alignment
/// @param size message size
/// @param alignment message alignment
/// @return pointer to FairMQMessage
virtual FairMQMessagePtr CreateMessage(const size_t size, fair::mq::Alignment alignment) = 0;
/// @brief Create new FairMQMessage with user provided buffer and size /// @brief Create new FairMQMessage with user provided buffer and size
/// @param data pointer to user provided buffer /// @param data pointer to user provided buffer
/// @param size size of the user provided buffer /// @param size size of the user provided buffer
@@ -59,20 +69,51 @@ class FairMQTransportFactory
/// @param obj optional helper pointer that can be used in the callback /// @param obj optional helper pointer that can be used in the callback
/// @return pointer to FairMQMessage /// @return pointer to FairMQMessage
virtual FairMQMessagePtr CreateMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = nullptr) = 0; virtual FairMQMessagePtr CreateMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = nullptr) = 0;
/// @brief create a message with the buffer located within the corresponding unmanaged region
/// @param unmanagedRegion the unmanaged region that this message buffer belongs to
/// @param data message buffer (must be within the region - checked at runtime by the transport)
/// @param size size of the message
/// @param hint optional parameter, returned to the user in the FairMQRegionCallback
virtual FairMQMessagePtr CreateMessage(FairMQUnmanagedRegionPtr& unmanagedRegion, void* data, const size_t size, void* hint = 0) = 0; virtual FairMQMessagePtr CreateMessage(FairMQUnmanagedRegionPtr& unmanagedRegion, void* data, const size_t size, void* hint = 0) = 0;
/// Create a socket /// @brief Create a socket
virtual FairMQSocketPtr CreateSocket(const std::string& type, const std::string& name) = 0; virtual FairMQSocketPtr CreateSocket(const std::string& type, const std::string& name) = 0;
/// Create a poller for a single channel (all subchannels) /// @brief Create a poller for a single channel (all subchannels)
virtual FairMQPollerPtr CreatePoller(const std::vector<FairMQChannel>& channels) const = 0; virtual FairMQPollerPtr CreatePoller(const std::vector<FairMQChannel>& channels) const = 0;
/// Create a poller for specific channels /// @brief Create a poller for specific channels
virtual FairMQPollerPtr CreatePoller(const std::vector<FairMQChannel*>& channels) const = 0; virtual FairMQPollerPtr CreatePoller(const std::vector<FairMQChannel*>& channels) const = 0;
/// Create a poller for specific channels (all subchannels) /// @brief Create a poller for specific channels (all subchannels)
virtual FairMQPollerPtr CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::vector<std::string>& channelList) const = 0; virtual FairMQPollerPtr CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::vector<std::string>& channelList) const = 0;
virtual FairMQUnmanagedRegionPtr CreateUnmanagedRegion(const size_t size, FairMQRegionCallback callback = nullptr, const std::string& path = "", int flags = 0) const = 0; /// @brief Create new UnmanagedRegion
/// @param size size of the region
/// @param callback callback to be called when a message belonging to this region is no longer needed by the transport
/// @param path optional parameter to pass to the underlying transport
/// @param flags optional parameter to pass to the underlying transport
/// @return pointer to UnmanagedRegion
virtual FairMQUnmanagedRegionPtr CreateUnmanagedRegion(const size_t size, FairMQRegionCallback callback = nullptr, const std::string& path = "", int flags = 0) = 0;
virtual FairMQUnmanagedRegionPtr CreateUnmanagedRegion(const size_t size, FairMQRegionBulkCallback callback = nullptr, const std::string& path = "", int flags = 0) = 0;
/// @brief Create new UnmanagedRegion
/// @param size size of the region
/// @param userFlags flags to be stored with the region, have no effect on the transport, but can be retrieved from the region by the user
/// @param callback callback to be called when a message belonging to this region is no longer needed by the transport
/// @param path optional parameter to pass to the underlying transport
/// @param flags optional parameter to pass to the underlying transport
/// @return pointer to UnmanagedRegion
virtual FairMQUnmanagedRegionPtr CreateUnmanagedRegion(const size_t size, const int64_t userFlags, FairMQRegionCallback callback = nullptr, const std::string& path = "", int flags = 0) = 0;
virtual FairMQUnmanagedRegionPtr CreateUnmanagedRegion(const size_t size, const int64_t userFlags, FairMQRegionBulkCallback callback = nullptr, const std::string& path = "", int flags = 0) = 0;
/// @brief Subscribe to region events (creation, destruction, ...)
/// @param callback the callback that is called when a region event occurs
virtual void SubscribeToRegionEvents(FairMQRegionEventCallback callback) = 0;
/// @brief Check if there is an active subscription to region events
/// @return true/false
virtual bool SubscribedToRegionEvents() = 0;
/// @brief Unsubscribe from region events
virtual void UnsubscribeFromRegionEvents() = 0;
virtual std::vector<FairMQRegionInfo> GetRegionInfo() = 0;
/// Get transport type /// Get transport type
virtual fair::mq::Transport GetType() const = 0; virtual fair::mq::Transport GetType() const = 0;
@@ -135,6 +176,7 @@ namespace fair
namespace mq namespace mq
{ {
using TransportFactory = FairMQTransportFactory;
struct TransportFactoryError : std::runtime_error { using std::runtime_error::runtime_error; }; struct TransportFactoryError : std::runtime_error { using std::runtime_error::runtime_error; };
} /* namespace mq */ } /* namespace mq */

View File

@@ -10,28 +10,113 @@
#define FAIRMQUNMANAGEDREGION_H_ #define FAIRMQUNMANAGEDREGION_H_
#include <cstddef> // size_t #include <cstddef> // size_t
#include <cstdint> // uint32_t
#include <memory> // std::unique_ptr #include <memory> // std::unique_ptr
#include <functional> // std::function #include <functional> // std::function
#include <ostream> // std::ostream
#include <vector>
class FairMQTransportFactory;
enum class FairMQRegionEvent : int
{
created,
destroyed,
local_only
};
struct FairMQRegionInfo
{
FairMQRegionInfo()
: managed(true)
, id(0)
, ptr(nullptr)
, size(0)
, flags(0)
, event(FairMQRegionEvent::created)
{}
FairMQRegionInfo(bool _managed, uint64_t _id, void* _ptr, size_t _size, int64_t _flags, FairMQRegionEvent _event)
: managed(_managed)
, id(_id)
, ptr(_ptr)
, size(_size)
, flags(_flags)
, event(_event)
{}
bool managed; // managed/unmanaged
uint64_t id; // id of the region
void* ptr; // pointer to the start of the region
size_t size; // region size
int64_t flags; // custom flags set by the creator
FairMQRegionEvent event;
};
struct FairMQRegionBlock {
void* ptr;
size_t size;
void* hint;
FairMQRegionBlock(void* p, size_t s, void* h)
: ptr(p), size(s), hint(h)
{}
};
using FairMQRegionCallback = std::function<void(void*, size_t, void*)>; using FairMQRegionCallback = std::function<void(void*, size_t, void*)>;
using FairMQRegionBulkCallback = std::function<void(const std::vector<FairMQRegionBlock>&)>;
using FairMQRegionEventCallback = std::function<void(FairMQRegionInfo)>;
class FairMQUnmanagedRegion class FairMQUnmanagedRegion
{ {
public: public:
FairMQUnmanagedRegion() {}
FairMQUnmanagedRegion(FairMQTransportFactory* factory) : fTransport(factory) {}
virtual void* GetData() const = 0; virtual void* GetData() const = 0;
virtual size_t GetSize() const = 0; virtual size_t GetSize() const = 0;
virtual uint16_t GetId() const = 0;
virtual void SetLinger(uint32_t linger) = 0;
virtual uint32_t GetLinger() const = 0;
FairMQTransportFactory* GetTransport() { return fTransport; }
void SetTransport(FairMQTransportFactory* transport) { fTransport = transport; }
virtual ~FairMQUnmanagedRegion() {}; virtual ~FairMQUnmanagedRegion() {};
private:
FairMQTransportFactory* fTransport{nullptr};
}; };
using FairMQUnmanagedRegionPtr = std::unique_ptr<FairMQUnmanagedRegion>; using FairMQUnmanagedRegionPtr = std::unique_ptr<FairMQUnmanagedRegion>;
inline std::ostream& operator<<(std::ostream& os, const FairMQRegionEvent& event)
{
switch (event) {
case FairMQRegionEvent::created:
return os << "created";
case FairMQRegionEvent::destroyed:
return os << "destroyed";
case FairMQRegionEvent::local_only:
return os << "local_only";
default:
return os << "unrecognized event";
}
}
namespace fair namespace fair
{ {
namespace mq namespace mq
{ {
using UnmanagedRegionPtr = std::unique_ptr<FairMQUnmanagedRegion>; using RegionCallback = FairMQRegionCallback;
using RegionBulkCallback = FairMQRegionBulkCallback;
using RegionEventCallback = FairMQRegionEventCallback;
using RegionEvent = FairMQRegionEvent;
using RegionInfo = FairMQRegionInfo;
using RegionBlock = FairMQRegionBlock;
using UnmanagedRegion = FairMQUnmanagedRegion;
using UnmanagedRegionPtr = FairMQUnmanagedRegionPtr;
} /* namespace mq */ } /* namespace mq */
} /* namespace fair */ } /* namespace fair */

View File

@@ -12,16 +12,19 @@
* Created on May 14, 2015, 5:01 PM * Created on May 14, 2015, 5:01 PM
*/ */
#include <fairmq/PropertyOutput.h>
#include "JSONParser.h" #include "JSONParser.h"
#include "FairMQLogger.h" #include "FairMQChannel.h"
#include <fairmq/Tools.h> #include <fairmq/PropertyOutput.h>
#include <fairmq/tools/CppSTL.h>
#include <fairmq/tools/Strings.h>
#include <fairlogger/Logger.h>
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
#include <boost/any.hpp> #include <boost/any.hpp>
#include <ios> #include <iomanip>
using namespace std; using namespace std;
using namespace fair::mq; using namespace fair::mq;

View File

@@ -15,15 +15,11 @@
#ifndef FAIR_MQ_JSONPARSER_H #ifndef FAIR_MQ_JSONPARSER_H
#define FAIR_MQ_JSONPARSER_H #define FAIR_MQ_JSONPARSER_H
#include <string> #include <fairmq/Properties.h>
#include <vector>
#include <unordered_map>
#include <exception>
#include <boost/property_tree/ptree_fwd.hpp> #include <boost/property_tree/ptree_fwd.hpp>
#include "FairMQChannel.h" #include <stdexcept>
#include <fairmq/Properties.h> #include <string>
namespace fair namespace fair
{ {

View File

@@ -60,7 +60,7 @@ FairMQMessagePtr getMessage(ContainerT &&container_, FairMQMemoryResource *targe
container.data(), container.data(),
containerSizeBytes); containerSizeBytes);
return message; return message;
}; }
} /* namespace mq */ } /* namespace mq */
} /* namespace fair */ } /* namespace fair */

View File

@@ -15,8 +15,7 @@
#include <fairmq/FairMQTransportFactory.h> #include <fairmq/FairMQTransportFactory.h>
#include <fairmq/MemoryResources.h> #include <fairmq/MemoryResources.h>
void *fair::mq::ChannelResource::do_allocate(std::size_t bytes, std::size_t /*alignment*/) void *fair::mq::ChannelResource::do_allocate(std::size_t bytes, std::size_t alignment)
{ {
return setMessage(factory->CreateMessage(bytes)); return setMessage(factory->CreateMessage(bytes, fair::mq::Alignment{alignment}));
}; }

View File

@@ -18,16 +18,13 @@
#include <fairmq/FairMQMessage.h> #include <fairmq/FairMQMessage.h>
class FairMQTransportFactory; class FairMQTransportFactory;
#include <boost/container/container_fwd.hpp>
#include <boost/container/flat_map.hpp> #include <boost/container/flat_map.hpp>
#include <boost/container/pmr/memory_resource.hpp> #include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/pmr/monotonic_buffer_resource.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
#include <cstring> #include <cstring>
#include <string> #include <stdexcept>
#include <type_traits>
#include <unordered_map>
#include <utility> #include <utility>
#include <vector>
namespace fair { namespace fair {
namespace mq { namespace mq {

Some files were not shown because too many files have changed in this diff Show More