Line data Source code
1 : #ifndef ARTDAQ_DAQDATA_GLOBALS_HH
2 : #define ARTDAQ_DAQDATA_GLOBALS_HH
3 :
4 : #ifndef TRACE_DEFINE // as set in Globals.cc
5 : #define TRACE_DECLARE
6 : #endif
7 : #include "artdaq-utilities/Plugins/MetricManager.hh"
8 : #include "artdaq/DAQdata/PortManager.hh"
9 :
10 : #define my_rank artdaq::Globals::my_rank_
11 : #define app_name artdaq::Globals::app_name_
12 : #define metricMan artdaq::Globals::metricMan_
13 : #define portMan artdaq::Globals::portMan_
14 :
15 : // https://stackoverflow.com/questions/21594140/c-how-to-ensure-different-random-number-generation-in-c-when-program-is-execut
16 : #include <fcntl.h>
17 : #include <unistd.h>
18 : #include <cstdlib>
19 : #include <memory>
20 : #include <mutex>
21 : #include <sstream>
22 : #include <string>
23 :
24 : /**
25 : * \brief The artdaq namespace
26 : */
27 : namespace artdaq {
28 : /**
29 : * \brief The artdaq::Globals class contains several variables which are useful across the entire artdaq system
30 : */
31 : class Globals
32 : {
33 : public:
34 : static int my_rank_; ///< The rank of the current application
35 : static std::unique_ptr<MetricManager> metricMan_; ///< A handle to MetricManager
36 : static std::unique_ptr<PortManager> portMan_; ///< A handle to PortManager
37 : static std::string app_name_; ///< The name of the current application, to be used in logging and metrics
38 : static int partition_number_; ///< The partition number of the current application
39 : static int my_art_id_; ///< The ID number of the current art application. Used by art processes connected to the same rank
40 :
41 : static std::mutex mftrace_mutex_; ///< Mutex to protect mftrace_module_ and mftrace_iteration_
42 : static std::string mftrace_module_; ///< MessageFacility's module and iteration are thread-local, but we want to use them to represent global state in artdaq.
43 : static std::string mftrace_iteration_; ///< MessageFacility's module and iteration are thread-local, but we want to use them to represent global state in artdaq.
44 :
45 : /**
46 : * \brief Seed the C random number generator with the current time (if that has not been done already) and generate a random value
47 : * \return A random number.
48 : */
49 2 : static uint32_t SeedAndRandom()
50 : {
51 : static bool initialized_ = false;
52 2 : if (!initialized_)
53 : {
54 2 : int fp = open("/dev/random", O_RDONLY);
55 2 : if (fp == -1) abort();
56 : unsigned seed;
57 2 : unsigned pos = 0;
58 4 : while (pos < sizeof(seed))
59 : {
60 2 : int amt = read(fp, reinterpret_cast<char *>(&seed) + pos, sizeof(seed) - pos); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic)
61 2 : if (amt <= 0) abort();
62 2 : pos += amt;
63 : }
64 2 : srand(seed);
65 2 : close(fp);
66 2 : initialized_ = true;
67 : }
68 2 : return rand(); // NOLINT(cert-msc50-cpp)
69 : }
70 :
71 : /**
72 : * \brief Get the current partition number, as defined by the ARTDAQ_PARTITION_NUMBER environment variable
73 : * \return The current partition number (defaults to 0 if unset, will be between 0 and 127)
74 : */
75 51 : static int GetPartitionNumber()
76 : {
77 51 : uint32_t part_u = 0;
78 :
79 : // 23-May-2018, KAB: added the option to return the partition number data member
80 : // and gave it precedence over the env var since it is typcally based on information
81 : // that the user specified on the command line.
82 51 : if (partition_number_ >= 0)
83 : {
84 44 : part_u = static_cast<uint32_t>(partition_number_);
85 : }
86 : else
87 : {
88 7 : auto part = getenv("ARTDAQ_PARTITION_NUMBER"); // Valid values 0-127
89 7 : if (part != nullptr)
90 : {
91 : try
92 : {
93 0 : auto part_s = std::string(part);
94 0 : part_u = static_cast<uint32_t>(std::stoll(part_s, nullptr, 0));
95 0 : }
96 0 : catch (const std::invalid_argument &)
97 0 : {}
98 0 : catch (const std::out_of_range &)
99 0 : {}
100 : }
101 7 : partition_number_ = part_u & 0x7F;
102 : }
103 :
104 51 : return (part_u & 0x7F);
105 : }
106 :
107 : /**
108 : * \brief Get the Shared Memory Key for a given partition number
109 : */
110 30 : static uint32_t SharedMemoryKey(uint32_t seed, bool useParentPID = false)
111 : {
112 30 : return seed + ((GetPartitionNumber() + 1) << 16) + ((useParentPID ? getppid() : getpid()) & 0xFFFF);
113 : }
114 :
115 : /**
116 : * \brief Get the current iteration for MessageFacility messages
117 : * \return The current iteration
118 : */
119 : static std::string GetMFIteration()
120 : {
121 : std::unique_lock<std::mutex> lk(mftrace_mutex_);
122 : return mftrace_iteration_;
123 : }
124 :
125 : /**
126 : * \brief Get the current module name for MessageFacility messages
127 : * \return The current module name
128 : */
129 : static std::string GetMFModuleName()
130 : {
131 : std::unique_lock<std::mutex> lk(mftrace_mutex_);
132 : return mftrace_module_;
133 : }
134 :
135 : /**
136 : * \brief Set the current iteration for MessageFacility messages
137 : * \param name The current iteration
138 : */
139 443 : static void SetMFIteration(std::string const &name)
140 : {
141 443 : std::unique_lock<std::mutex> lk(mftrace_mutex_);
142 443 : mftrace_iteration_ = name;
143 443 : }
144 :
145 : /**
146 : * \brief Set the current module name for MessageFacility messages
147 : * \param name The current module name
148 : */
149 15 : static void SetMFModuleName(std::string const &name)
150 : {
151 15 : std::unique_lock<std::mutex> lk(mftrace_mutex_);
152 15 : mftrace_module_ = name;
153 15 : }
154 :
155 : /**
156 : * \brief Clean up statically-allocated Manager class instances
157 : */
158 2 : static void CleanUpGlobals()
159 : {
160 2 : metricMan_.reset(nullptr);
161 2 : portMan_.reset(nullptr);
162 2 : }
163 : };
164 : } // namespace artdaq
165 :
166 : #include "tracemf.h"
167 :
168 : #endif // ARTDAQ_DAQDATA_GLOBALS_HH
|