artdaq_core  v3_06_10
SharedMemoryManager_t.cc
1 #include "artdaq-core/Core/SharedMemoryManager.hh"
2 #include "artdaq-core/Utilities/TimeUtils.hh"
3 #include "artdaq-core/Utilities/configureMessageFacility.hh"
4 
5 #define BOOST_TEST_MODULE SharedMemoryManager_t
6 #include "cetlib/quiet_unit_test.hpp"
7 #include "cetlib_except/exception.h"
8 
9 #define TRACE_NAME "SharedMemoryManager_t"
10 #include "SharedMemoryTestShims.hh"
11 #include "tracemf.h"
12 
13 BOOST_AUTO_TEST_SUITE(SharedMemoryManager_test)
14 
15 BOOST_AUTO_TEST_CASE(Construct)
16 {
17  artdaq::configureMessageFacility("SharedMemoryManager_t", true, true);
18  TLOG(TLVL_DEBUG) << "BEGIN TEST Construct";
19  uint32_t key = GetRandomKey(0x7357);
20  artdaq::SharedMemoryManager man(key, 10, 0x1000, 0x10000);
21  BOOST_REQUIRE_EQUAL(man.IsValid(), true);
22  BOOST_REQUIRE_EQUAL(man.GetMyId(), 0);
23  BOOST_REQUIRE_EQUAL(man.size(), 10);
24  BOOST_REQUIRE_EQUAL(man.GetAttachedCount(), 1);
25  BOOST_REQUIRE_EQUAL(man.GetKey(), key);
26  TLOG(TLVL_DEBUG) << "END TEST Construct";
27 }
28 
29 BOOST_AUTO_TEST_CASE(Attach)
30 {
31  TLOG(TLVL_DEBUG) << "BEGIN TEST Attach";
32  uint32_t key = GetRandomKey(0x7357);
33  artdaq::SharedMemoryManager man(key, 10, 0x1000, 0x10000);
35 
36  BOOST_REQUIRE_EQUAL(man.IsValid(), true);
37  BOOST_REQUIRE_EQUAL(man.GetMyId(), 0);
38  BOOST_REQUIRE_EQUAL(man.size(), 10);
39  BOOST_REQUIRE_EQUAL(man.GetAttachedCount(), 2);
40  BOOST_REQUIRE_EQUAL(man.GetKey(), key);
41 
42  BOOST_REQUIRE_EQUAL(man2.IsValid(), true);
43  BOOST_REQUIRE_EQUAL(man2.GetMyId(), 1);
44  BOOST_REQUIRE_EQUAL(man2.size(), 10);
45  BOOST_REQUIRE_EQUAL(man2.GetAttachedCount(), 2);
46  BOOST_REQUIRE_EQUAL(man2.GetKey(), key);
47 
48  TLOG(TLVL_DEBUG) << "END TEST Attach";
49 }
50 
51 BOOST_AUTO_TEST_CASE(DataFlow)
52 {
53  TLOG(TLVL_DEBUG) << "BEGIN TEST DataFlow";
54  uint32_t key = GetRandomKey(0x7357);
55  artdaq::SharedMemoryManager man(key, 10, 0x1000);
57 
58  BOOST_REQUIRE_EQUAL(man.ReadyForWrite(false), true);
59  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(false), 10);
60  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
61  BOOST_REQUIRE_EQUAL(man.ReadReadyCount(), 0);
62 
63  int buf = man.GetBufferForWriting(false);
64  BOOST_REQUIRE_EQUAL(man.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Writing), true);
65  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 1);
66  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager()[0], buf);
67  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(), 0);
68  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0);
69 
70  uint8_t n = 0;
71  uint8_t data[0x1000];
72  std::generate_n(data, 0x1000, [&]() { return ++n; });
73  man.Write(buf, data, 0x1000);
74  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0x1000);
75  BOOST_REQUIRE_EQUAL(man2.BufferDataSize(buf), 0x1000);
76  man.MarkBufferFull(buf, 1);
77  BOOST_REQUIRE_EQUAL(man2.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Full), true);
78  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 0);
79  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(), 1);
80 
81  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
82  BOOST_REQUIRE_EQUAL(man2.ReadyForRead(), true);
83  BOOST_REQUIRE_EQUAL(man2.ReadReadyCount(), 1);
84 
85  auto readbuf = man2.GetBufferForReading();
86  BOOST_REQUIRE_EQUAL(man2.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Reading), true);
87  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
88  uint8_t byte;
89  auto sts = man2.Read(readbuf, &byte, 1);
90  BOOST_REQUIRE_EQUAL(sts, true);
91  BOOST_REQUIRE_EQUAL(byte, 1); // ++n means that the first entry will be 1
92  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
93  sts = man2.Read(readbuf, &byte, 1);
94  BOOST_REQUIRE_EQUAL(sts, true);
95  BOOST_REQUIRE_EQUAL(byte, 2); // Second entry is 2
96  man2.IncrementReadPos(readbuf, 0x10);
97  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
98  sts = man2.Read(readbuf, &byte, 1);
99  BOOST_REQUIRE_EQUAL(sts, true);
100  BOOST_REQUIRE_EQUAL(byte, 0x13); // Read increments, so it would have read 3, but we added 0x10, so we expect 0x13.
101  man2.ResetReadPos(readbuf);
102  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
103  sts = man2.Read(readbuf, &byte, 1);
104  BOOST_REQUIRE_EQUAL(sts, true);
105  BOOST_REQUIRE_EQUAL(byte, 1);
106  man2.IncrementReadPos(readbuf, 0xFFF);
107  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), false);
108  man2.MarkBufferEmpty(readbuf);
109 
110  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(), 0);
111  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 0);
112  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(false), 10);
113  TLOG(TLVL_DEBUG) << "END TEST DataFlow";
114 }
115 
116 BOOST_AUTO_TEST_CASE(Exceptions)
117 {
118  artdaq::configureMessageFacility("SharedMemoryManager_t", true, true);
119  TLOG(TLVL_DEBUG) << "BEGIN TEST Exceptions";
120  uint32_t key = GetRandomKey(0x7357);
121  artdaq::SharedMemoryManager man(key, 10, 0x1000);
122  artdaq::SharedMemoryManager man2(key);
123  BOOST_REQUIRE_EQUAL(man.ReadyForWrite(false), true);
124  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(false), 10);
125  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
126  BOOST_REQUIRE_EQUAL(man.ReadReadyCount(), 0);
127 
128  // Trying to get an invalid buffer is an exception
129  BOOST_REQUIRE_EXCEPTION(man.ResetReadPos(11), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
130  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
131  man.Attach();
132  BOOST_REQUIRE_EXCEPTION(man.BufferDataSize(11), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
133  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
134  man.Attach();
135  BOOST_REQUIRE_EXCEPTION(man.ResetWritePos(11), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
136  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
137  man.Attach();
138  BOOST_REQUIRE_EXCEPTION(man.IncrementReadPos(11, 1), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
139  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
140  man.Attach();
141  BOOST_REQUIRE_EXCEPTION(man.IncrementWritePos(11, 1), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
142  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
143  man.Attach();
144  BOOST_REQUIRE_EXCEPTION(man.MoreDataInBuffer(11), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
145  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
146  man.Attach();
147  BOOST_REQUIRE_EXCEPTION(man.CheckBuffer(11, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Full), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
148  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
149  man.Attach();
150  BOOST_REQUIRE_EXCEPTION(man.MarkBufferFull(11), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
151  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
152  man.Attach();
153  BOOST_REQUIRE_EXCEPTION(man.MarkBufferEmpty(11), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
154  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
155  man.Attach();
156  BOOST_REQUIRE_EXCEPTION(man.ResetBuffer(11), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
157  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
158  man.Attach();
159  int dummy[2]{0, 1};
160  BOOST_REQUIRE_EXCEPTION(man.Write(11, &dummy, sizeof(dummy)), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
161  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
162  man.Attach();
163  BOOST_REQUIRE_EXCEPTION(man.Read(11, &dummy, sizeof(dummy)), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
164  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
165  man.Attach();
166 
167  // Trying to access a buffer that is in the wrong state is an exception
168  BOOST_REQUIRE_EXCEPTION(man.MarkBufferEmpty(0), cet::exception, [&](cet::exception e) { return e.category() == "StateAccessViolation"; });
169  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
170 
171  man.Attach();
172 
173  // Writing too much data is an exception
174  int buf = man.GetBufferForWriting(false);
175  BOOST_REQUIRE_EQUAL(man.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Writing), true);
176  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 1);
177  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager()[0], buf);
178  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0);
179 
180  uint8_t n = 0;
181  uint8_t data[0x2000];
182  std::generate_n(data, 0x2000, [&]() { return ++n; });
183  BOOST_REQUIRE_EXCEPTION(man.Write(buf, data, 0x2000), cet::exception, [&](cet::exception e) { return e.category() == "SharedMemoryWrite"; });
184  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
185 
186  man.Attach();
187  man2.Attach();
188  buf = man.GetBufferForWriting(false);
189  BOOST_REQUIRE_EQUAL(man.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Writing), true);
190  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 1);
191  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager()[0], buf);
192  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0);
193  man.Write(buf, data, 0x1000);
194  man.MarkBufferFull(buf);
195 
196  // Reading too much data is an exception
197  BOOST_REQUIRE_EQUAL(man2.IsValid(), true);
198  BOOST_REQUIRE_EQUAL(man2.ReadyForRead(), true);
199  BOOST_REQUIRE_EQUAL(man2.ReadReadyCount(), 1);
200 
201  int readbuf = man2.GetBufferForReading();
202  BOOST_REQUIRE_EQUAL(readbuf, buf);
203  BOOST_REQUIRE_EXCEPTION(man2.Read(readbuf, data, 0x1001), cet::exception, [&](cet::exception e) { return e.category() == "SharedMemoryRead"; });
204  BOOST_REQUIRE_EQUAL(man2.IsValid(), false);
205 
206  man.Attach();
207  man2.Attach();
208 
209  man.MarkBufferEmpty(readbuf, true);
210  buf = man.GetBufferForWriting(false);
211  BOOST_REQUIRE_EQUAL(man.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Writing), true);
212  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 1);
213  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager()[0], buf);
214  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0);
215  man.Write(buf, data, 0x1000);
216  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 1);
217  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager()[0], buf);
218  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0x1000);
219  man.MarkBufferFull(buf);
220  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 0);
221  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0x1000);
222 
223  BOOST_REQUIRE_EQUAL(man2.ReadyForRead(), true);
224  BOOST_REQUIRE_EQUAL(man2.ReadReadyCount(), 1);
225  readbuf = man2.GetBufferForReading();
226  BOOST_REQUIRE_EQUAL(readbuf, buf);
227  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(), 1);
228  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager()[0], readbuf);
229  BOOST_REQUIRE_EQUAL(man2.BufferDataSize(readbuf), 0x1000);
230  // Accessing a buffer that is not owned by the manager is an exception
231  BOOST_REQUIRE_EXCEPTION(man.MarkBufferEmpty(readbuf), cet::exception, [&](cet::exception e) { return e.category() == "OwnerAccessViolation"; });
232  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
233 
234  TLOG(TLVL_DEBUG) << "END TEST Exceptions";
235 }
236 
237 BOOST_AUTO_TEST_CASE(Broadcast)
238 {
239  TLOG(TLVL_DEBUG) << "BEGIN TEST Broadcast";
240  uint32_t key = GetRandomKey(0x7357);
241  artdaq::SharedMemoryManager man(key, 10, 0x1000, 0x10000, false);
242  artdaq::SharedMemoryManager man2(key);
243  artdaq::SharedMemoryManager man3(key);
244 
245  BOOST_REQUIRE_EQUAL(man.ReadyForWrite(false), true);
246  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(false), 10);
247  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
248  BOOST_REQUIRE_EQUAL(man.ReadReadyCount(), 0);
249 
250  int buf = man.GetBufferForWriting(false);
251  BOOST_REQUIRE_EQUAL(man.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Writing), true);
252  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 1);
253  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager()[0], buf);
254  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(), 0);
255  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0);
256 
257  uint8_t n = 0;
258  uint8_t data[0x1000];
259  std::generate_n(data, 0x1000, [&]() { return ++n; });
260  man.Write(buf, data, 0x1000);
261  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0x1000);
262  BOOST_REQUIRE_EQUAL(man2.BufferDataSize(buf), 0x1000);
263  man.MarkBufferFull(buf, -1);
264  BOOST_REQUIRE_EQUAL(man2.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Full), true);
265  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 0);
266 
267  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
268  BOOST_REQUIRE_EQUAL(man2.ReadyForRead(), true);
269  BOOST_REQUIRE_EQUAL(man2.ReadReadyCount(), 1);
270 
271  auto readbuf = man2.GetBufferForReading();
272  BOOST_REQUIRE_EQUAL(readbuf, buf);
273  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(), 1);
274  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
275  BOOST_REQUIRE_EQUAL(man3.ReadyForRead(), false);
276  BOOST_REQUIRE_EQUAL(man2.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Reading), true);
277  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
278  uint8_t byte;
279  auto sts = man2.Read(readbuf, &byte, 1);
280  BOOST_REQUIRE_EQUAL(sts, true);
281  BOOST_REQUIRE_EQUAL(byte, 1); // ++n means that the first entry will be 1
282  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
283  sts = man2.Read(readbuf, &byte, 1);
284  BOOST_REQUIRE_EQUAL(sts, true);
285  BOOST_REQUIRE_EQUAL(byte, 2); // Second entry is 2
286  man2.IncrementReadPos(readbuf, 0x10);
287  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
288  sts = man2.Read(readbuf, &byte, 1);
289  BOOST_REQUIRE_EQUAL(sts, true);
290  BOOST_REQUIRE_EQUAL(byte, 0x13); // Read increments, so it would have read 3, but we added 0x10, so we expect 0x13.
291  man2.ResetReadPos(readbuf);
292  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
293  sts = man2.Read(readbuf, &byte, 1);
294  BOOST_REQUIRE_EQUAL(sts, true);
295  BOOST_REQUIRE_EQUAL(byte, 1);
296  man2.IncrementReadPos(readbuf, 0xFFF);
297  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), false);
298  man2.MarkBufferEmpty(readbuf);
299  BOOST_REQUIRE_EQUAL(man3.ReadyForRead(), true);
300  BOOST_REQUIRE_EQUAL(man3.ReadReadyCount(), 1);
301  BOOST_REQUIRE_EQUAL(man2.ReadyForRead(), false);
302  BOOST_REQUIRE_EQUAL(man2.ReadReadyCount(), 0);
303  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
304 
305  readbuf = man3.GetBufferForReading();
306  BOOST_REQUIRE_EQUAL(readbuf, buf);
307  BOOST_REQUIRE_EQUAL(man3.GetBuffersOwnedByManager().size(), 1);
308  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
309  BOOST_REQUIRE_EQUAL(man3.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Reading), true);
310  BOOST_REQUIRE_EQUAL(man3.MoreDataInBuffer(readbuf), true);
311  sts = man3.Read(readbuf, &byte, 1);
312  BOOST_REQUIRE_EQUAL(sts, true);
313  BOOST_REQUIRE_EQUAL(byte, 1); // ++n means that the first entry will be 1
314  BOOST_REQUIRE_EQUAL(man3.MoreDataInBuffer(readbuf), true);
315  sts = man3.Read(readbuf, &byte, 1);
316  BOOST_REQUIRE_EQUAL(sts, true);
317  BOOST_REQUIRE_EQUAL(byte, 2); // Second entry is 2
318  man3.IncrementReadPos(readbuf, 0x10);
319  BOOST_REQUIRE_EQUAL(man3.MoreDataInBuffer(readbuf), true);
320  sts = man3.Read(readbuf, &byte, 1);
321  BOOST_REQUIRE_EQUAL(sts, true);
322  BOOST_REQUIRE_EQUAL(byte, 0x13); // Read increments, so it would have read 3, but we added 0x10, so we expect 0x13.
323  man3.ResetReadPos(readbuf);
324  BOOST_REQUIRE_EQUAL(man3.MoreDataInBuffer(readbuf), true);
325  sts = man3.Read(readbuf, &byte, 1);
326  BOOST_REQUIRE_EQUAL(sts, true);
327  BOOST_REQUIRE_EQUAL(byte, 1);
328  man3.IncrementReadPos(readbuf, 0xFFF);
329  BOOST_REQUIRE_EQUAL(man3.MoreDataInBuffer(readbuf), false);
330  man3.MarkBufferEmpty(readbuf);
331  BOOST_REQUIRE_EQUAL(man3.ReadyForRead(), false);
332  BOOST_REQUIRE_EQUAL(man2.ReadyForRead(), false);
333  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
334 
335  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(), 0);
336  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 0);
337  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(false), 9);
338  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(true), 10);
339  sleep(1);
340  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(false), 10);
341  TLOG(TLVL_DEBUG) << "END TEST Broadcast";
342 }
343 
344 BOOST_AUTO_TEST_SUITE_END()
The buffer is full, and waiting for a reader.
The buffer is currently being read from.
The buffer is currently being written to.
The SharedMemoryManager creates a Shared Memory area which is divided into a number of fixed-size buf...
void configureMessageFacility(char const *progname, bool useConsole=true, bool printDebug=false)
Configure and start the message facility. Provide the program name so that messages will be appropria...