GCC Code Coverage Report


Directory: ./
File: pdserv-1.1.0/src/lib/Main.cpp
Date: 2024-12-01 04:08:21
Exec Total Coverage
Lines: 115 244 47.1%
Branches: 73 287 25.4%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * $Id$
4 *
5 * Copyright 2010 Richard Hacker (lerichi at gmx dot net)
6 *
7 * This file is part of the pdserv library.
8 *
9 * The pdserv library is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation, either version 3 of the License, or (at
12 * your option) any later version.
13 *
14 * The pdserv library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 * License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with the pdserv library. If not, see <http://www.gnu.org/licenses/>.
21 *
22 *****************************************************************************/
23
24 #include "config.h"
25
26 #include "../Debug.h"
27
28 #include <iostream>
29 #include <cerrno>
30 #include <cstring>
31 #include <cstdlib>
32 #include <cstdio>
33 #include <ctime>
34 #include <sstream>
35 #include <algorithm>
36 #include <sys/mman.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <unistd.h> // fork(), getpid(), chdir, sysconf
40 #include <signal.h> // signal()
41 #include <fcntl.h> // open()
42 #include <limits.h> // _POSIX_OPEN_MAX
43
44 #include <log4cplus/logger.h>
45 #include <log4cplus/syslogappender.h>
46 #include <log4cplus/consoleappender.h>
47 #include <log4cplus/streams.h>
48 #include <log4cplus/configurator.h>
49 #include <log4cplus/loggingmacros.h>
50
51 #include "pdserv.h"
52 #include "Main.h"
53 #include "Task.h"
54 #include "Parameter.h"
55 #include "Signal.h"
56 #include "Event.h"
57 #include "Pointer.h"
58 #include "ShmemDataStructures.h"
59 #include "../Session.h"
60 #include "../DataType.h"
61 #include "../Config.h"
62
63 /////////////////////////////////////////////////////////////////////////////
64 struct SDOStruct {
65 const Parameter *parameter;
66 unsigned int offset;
67 unsigned int count;
68 int rv;
69 struct timespec time;
70 };
71
72 struct SessionData {
73 struct EventData* eventReadPointer;
74 };
75
76 /////////////////////////////////////////////////////////////////////////////
77 const double Main::bufferTime = 2.0;
78
79 /////////////////////////////////////////////////////////////////////////////
80 10 Main::Main( const char *name, const char *version,
81 10 int (*gettime)(struct timespec*)):
82 PdServ::Main(name, version),
83 mutex(1), eventMutex(1), sdoMutex(1),
84
8/16
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 12 taken 10 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 10 times.
✗ Branch 17 not taken.
✓ Branch 29 taken 10 times.
✗ Branch 30 not taken.
✓ Branch 35 taken 10 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 10 times.
✗ Branch 40 not taken.
✓ Branch 43 taken 10 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 10 times.
✗ Branch 46 not taken.
10 rttime(gettime ? gettime : &PdServ::Main::localtime)
85 {
86 10 shmem_len = 0;
87 10 shmem = 0;
88 10 }
89
90 /////////////////////////////////////////////////////////////////////////////
91 30 Main::~Main()
92 {
93 10 ::kill(pid, SIGHUP);
94
95 10 ::munmap(shmem, shmem_len);
96 20 }
97
98 /////////////////////////////////////////////////////////////////////////////
99 10 void Main::setConfigFile(const char *file)
100 {
101 10 configFile = file;
102 10 }
103
104 /////////////////////////////////////////////////////////////////////////////
105 20 Task* Main::addTask(double sampleTime, const char *name)
106 {
107
1/2
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
20 Task *t = new Task(this, sampleTime, name);
108
1/2
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
20 task.push_back(t);
109 20 return t;
110 }
111
112 /////////////////////////////////////////////////////////////////////////////
113 Task *Main::getTask(size_t index) const
114 {
115 return static_cast<Task*>(task[index]);
116 }
117
118 /////////////////////////////////////////////////////////////////////////////
119 int Main::gettime(struct timespec* t) const
120 {
121 return rttime(t);
122 }
123
124 /////////////////////////////////////////////////////////////////////////////
125 20 Event* Main::addEvent (
126 const char *path, int prio, size_t nelem, const char **messages)
127 {
128
3/6
✓ Branch 8 taken 20 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 20 times.
✗ Branch 13 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 20 times.
20 if (variableSet.find(path) != variableSet.end())
129 return 0;
130
131 20 PdServ::Event::Priority eventPrio;
132
2/7
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
20 switch (prio) {
133 case 1: eventPrio = PdServ::Event::Alert; break;
134 case 2: eventPrio = PdServ::Event::Critical; break;
135 10 case 3: eventPrio = PdServ::Event::Error; break;
136 10 case 4: eventPrio = PdServ::Event::Warning; break;
137 case 5: eventPrio = PdServ::Event::Notice; break;
138 case 6: eventPrio = PdServ::Event::Info; break;
139 default:
140 eventPrio = prio <= 0
141 ? PdServ::Event::Emergency
142 : PdServ::Event::Debug;
143 }
144
2/4
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
20 Event *e = new Event(this, path, eventPrio, nelem, messages);
145
146
2/4
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 20 times.
✗ Branch 10 not taken.
20 variableSet.insert(path);
147
1/2
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 events.push_back(e);
148
149 20 return e;
150 }
151
152 /////////////////////////////////////////////////////////////////////////////
153 60 Parameter* Main::addParameter( const char *path,
154 unsigned int mode, const PdServ::DataType& datatype,
155 void *addr, size_t n, const size_t *dim)
156 {
157
3/6
✓ Branch 8 taken 60 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 60 times.
✗ Branch 13 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 60 times.
60 if (variableSet.find(path) != variableSet.end())
158 return 0;
159
160
1/2
✓ Branch 3 taken 60 times.
✗ Branch 4 not taken.
60 Parameter *p = new Parameter(this, path, mode, datatype, addr, n, dim);
161
162
2/4
✓ Branch 5 taken 60 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 60 times.
✗ Branch 10 not taken.
60 variableSet.insert(path);
163
1/2
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
60 parameters.push_back(p);
164
165 60 return p;
166 }
167
168 /////////////////////////////////////////////////////////////////////////////
169 60 Signal* Main::addSignal( Task *task, unsigned int decimation,
170 const char *path, const PdServ::DataType& datatype,
171 const void *addr, size_t n, const size_t *dim)
172 {
173
3/6
✓ Branch 8 taken 60 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 60 times.
✗ Branch 13 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 60 times.
60 if (variableSet.find(path) != variableSet.end())
174 return 0;
175
176 60 Signal *s = task->addSignal(decimation, path, datatype, addr, n, dim);
177
178
2/4
✓ Branch 5 taken 60 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 60 times.
✗ Branch 10 not taken.
60 variableSet.insert(path);
179
180 60 return s;
181 }
182
183 /////////////////////////////////////////////////////////////////////////////
184 2 bool Main::setEvent(const Event* event,
185 size_t element, bool state, const timespec *t) const
186 {
187
1/2
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 ost::SemaphoreLock lock(eventMutex);
188 2 struct EventData *eventData = event->data + element;
189
190
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 if (eventData->state == state)
191 return false;
192
193 2 eventData->state = state;
194 2 eventData->time = *t;
195
196 2 **eventDataWp = *eventData;
197
198 2 eventData = *eventDataWp;
199
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 if (++eventData == eventDataEnd)
200 eventData = eventDataStart;
201 2 *eventDataWp = eventData;
202
203 2 return true;
204 }
205
206 /////////////////////////////////////////////////////////////////////////////
207 int Main::setParameter(const Parameter *p, size_t offset,
208 size_t count, const char *data, struct timespec *mtime) const
209 {
210 ost::SemaphoreLock lock(sdoMutex);
211
212 size_t delay = 100; // ms FIXME
213
214 // Write the parameters into the shared memory sorted from widest
215 // to narrowest data type size. This ensures that the data is
216 // always aligned correctly.
217 sdo->parameter = p;
218 sdo->offset = offset;
219 std::copy(data, data + count, p->valueBuf + sdo->offset);
220
221 // Now write the length to trigger the action
222 sdo->count = count;
223
224 do {
225 ost::Thread::sleep(delay);
226 } while (sdo->count);
227
228 if (!sdo->rv)
229 *mtime = sdo->time;
230
231 return sdo->rv;
232 }
233
234 /////////////////////////////////////////////////////////////////////////////
235 void Main::processPoll(unsigned int delay_ms,
236 const PdServ::Signal * const *s, size_t nelem,
237 void * const *pollDest, struct timespec *t) const
238 {
239 bool fin[task.size()];
240 bool finished;
241 std::fill_n(fin, 4, false);
242 do {
243 finished = true;
244 int i = 0;
245 for (TaskList::const_iterator it = task.begin();
246 it != task.end(); ++it, ++i) {
247 const Task *task = static_cast<const Task*>(*it);
248 fin[i] = fin[i] or task->pollFinished( s, nelem, pollDest, t);
249 finished = finished and fin[i];
250 }
251 ost::Thread::sleep(delay_ms);
252 } while (!finished);
253 }
254
255 /////////////////////////////////////////////////////////////////////////////
256 10 int Main::run()
257 {
258 10 size_t numTasks = task.size();
259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 size_t taskMemSize[numTasks];
260 size_t i, eventCount;
261
262 // The following two variables are used to organize parameters according
263 // to the size of their elements so that their data type alignment is
264 // correct.
265 //
266 // dataTypeIndex[] maps the data type to the index in parameterDataOffset,
267 // e.g. a parameter with data type double (sizeof() = 8) will then go into
268 // container parameterDataOffset[dataTypeIndex[8]]
269 //
270 // parameterDataOffset[] holds the start index of a data types with
271 // 8, 4, 2 and 1 bytes alignment
272 10 const size_t dataTypeIndex[PdServ::DataType::maxWidth+1] = {
273 3 /*0*/, 3 /*1*/, 2 /*2*/, 3 /*3*/,
274 1 /*4*/, 3 /*5*/, 3 /*6*/, 3 /*7*/, 0 /*8*/
275 };
276 10 size_t parameterDataOffset[5] = {0, 0, 0, 0, 0};
277
278 // don't need variableSet any more
279 10 variableSet.clear();
280
281 70 for (PdServ::Main::ProcessParameters::iterator it = parameters.begin();
282
2/2
✓ Branch 6 taken 60 times.
✓ Branch 7 taken 10 times.
70 it != parameters.end(); it++) {
283
1/2
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
60 const Parameter *p = static_cast<const Parameter*>(*it);
284
285 // Push the next smaller data type forward by the parameter's
286 // memory requirement
287
1/2
✓ Branch 15 taken 60 times.
✗ Branch 16 not taken.
60 parameterDataOffset[dataTypeIndex[p->dtype.align()] + 1] += p->memSize;
288 }
289
290 // Accumulate the offsets so that they follow each other in the shared
291 // data space. This also has the effect, that the value of
292 // parameterDataOffset[4] is the total memory requirement of all
293 // parameters
294
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 10 times.
50 for (i = 1; i < 5; ++i)
295 40 parameterDataOffset[i] += parameterDataOffset[i-1];
296
297 // Extend shared memory size with the parameter memory requirement
298 // and as many sdo's for every parameter.
299 20 shmem_len += sizeof(*sdo) * (parameters.size() + 1)
300 10 + parameterDataOffset[4];
301
302 // Now check how much memory is required for events
303 10 eventCount = 0;
304
2/2
✓ Branch 8 taken 20 times.
✓ Branch 9 taken 10 times.
30 for (EventList::iterator it = events.begin(); it != events.end(); ++it) {
305 20 eventCount += (*it)->nelem;
306 }
307 20 shmem_len +=
308 sizeof(*eventData) * eventCount
309 10 + sizeof(*eventDataStart) * 2 * eventCount;
310
311 10 shmem_len += sizeof(*eventDataWp); // Memory location for write pointer
312
313 // Find out the memory requirement for the tasks to pipe their variables
314 // out of the real time environment
315 10 i = 0;
316 30 for (TaskList::const_iterator it = task.begin();
317
2/2
✓ Branch 6 taken 20 times.
✓ Branch 7 taken 10 times.
30 it != task.end(); ++it) {
318
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 taskMemSize[i] = ptr_align(
319
1/2
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 static_cast<const Task*>(*it)->getShmemSpace(bufferTime));
320 //log_debug("Task %i %f shmlen=%zu", i, bufferTime, taskMemSize[i]);
321 20 shmem_len += taskMemSize[i++];
322 }
323
324 10 shmem = ::mmap(0, shmem_len, PROT_READ | PROT_WRITE,
325 MAP_SHARED | MAP_ANON, -1, 0);
326
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
10 if (MAP_FAILED == shmem) {
327 // log(LOGCRIT, "could not mmap
328 // err << "mmap(): " << strerror(errno);
329 ::perror("mmap()");
330 return -errno;
331 }
332
1/2
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
10 ::memset(shmem, 0, shmem_len);
333
334 10 sdo = ptr_align<struct SDOStruct>(shmem);
335 10 sdoData = ptr_align<char>(ptr_align<double>(sdo + parameters.size() + 1));
336
337 // cerr_debug() << "shmemlen=" << shmem_len
338 // << " shmem=" << shmem
339 // << " sdo=" << sdo
340 // // << " sdoTaskTime=" << sdoTaskTime
341 // << " sdoData=" << (void*)sdoData;
342
343 70 for (PdServ::Main::ProcessParameters::iterator it = parameters.begin();
344
2/2
✓ Branch 6 taken 60 times.
✓ Branch 7 taken 10 times.
70 it != parameters.end(); it++) {
345
1/2
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
60 const Parameter *p = static_cast<const Parameter*>(*it);
346 120 p->valueBuf =
347
1/2
✓ Branch 18 taken 60 times.
✗ Branch 19 not taken.
120 sdoData + parameterDataOffset[dataTypeIndex[p->dtype.align()]];
348
1/2
✓ Branch 15 taken 60 times.
✗ Branch 16 not taken.
60 parameterDataOffset[dataTypeIndex[p->dtype.align()]] += p->memSize;
349
350
1/2
✓ Branch 13 taken 60 times.
✗ Branch 14 not taken.
60 std::copy(p->addr, p->addr + p->memSize, p->valueBuf);
351 }
352
353 10 char* buf = ptr_align<char>(sdoData + parameterDataOffset[4]);
354 10 i = 0;
355
2/2
✓ Branch 8 taken 20 times.
✓ Branch 9 taken 10 times.
30 for (TaskList::iterator it = task.begin(); it != task.end(); ++it) {
356
2/4
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 12 taken 20 times.
✗ Branch 13 not taken.
20 static_cast<Task*>(*it)->prepare(buf, buf + taskMemSize[i]);
357 20 buf += taskMemSize[i++];
358 }
359
360 10 eventData = ptr_align<struct EventData>(buf);
361 10 eventDataStart = ptr_align<struct EventData>(eventData + eventCount);
362 10 eventDataEnd = eventDataStart + 2*eventCount;
363 10 eventDataWp = ptr_align<struct EventData*>(eventDataEnd);
364 10 *eventDataWp = eventDataStart;
365
366 10 i = 0;
367
2/2
✓ Branch 8 taken 20 times.
✓ Branch 9 taken 10 times.
30 for (EventList::iterator it = events.begin(); it != events.end(); ++it) {
368 20 (*it)->data = eventData + i;
369
2/2
✓ Branch 3 taken 40 times.
✓ Branch 4 taken 20 times.
60 for(size_t j = 0; j < (*it)->nelem; ++j, ++i) {
370 40 eventData[i].event = *it;
371 40 eventData[i].index = j;
372 }
373 }
374 // log_debug("%zu %p %p %zu", eventCount, eventDataWp+1, (char*)shmem + shmem_len, shmem_len);
375
376
1/2
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
20 return daemonize();
377 }
378
379 /////////////////////////////////////////////////////////////////////////////
380 void Main::consoleLogging()
381 {
382 log4cplus::BasicConfigurator::doConfigure();
383 // log4cplus::SharedAppenderPtr cerr(new log4cplus::ConsoleAppender(true));
384 // cerr->setLayout(
385 // std::auto_ptr<log4cplus::Layout>(new log4cplus::PatternLayout(
386 // LOG4CPLUS_TEXT("%D %p %c %x: %m"))));
387 //
388 // log4cplus::Logger::getRoot().addAppender(cerr);
389 }
390
391 /////////////////////////////////////////////////////////////////////////////
392 void Main::syslogLogging()
393 {
394 log4cplus::helpers::Properties p;
395 p.setProperty(LOG4CPLUS_TEXT("ident"),
396 LOG4CPLUS_STRING_TO_TSTRING(name));
397 p.setProperty(LOG4CPLUS_TEXT("facility"),LOG4CPLUS_TEXT("local0"));
398
399 log4cplus::SharedAppenderPtr appender( new log4cplus::SysLogAppender(p));
400 appender->setLayout(
401 std::auto_ptr<log4cplus::Layout>(new log4cplus::PatternLayout(
402 LOG4CPLUS_TEXT("%-5p %c <%x>: %m"))));
403
404 log4cplus::Logger root = log4cplus::Logger::getRoot();
405 root.addAppender(appender);
406 root.setLogLevel(log4cplus::INFO_LOG_LEVEL);
407 }
408
409 /////////////////////////////////////////////////////////////////////////////
410 void Main::configureLogging(const PdServ::Config& config)
411 {
412 if (!config) {
413 syslogLogging();
414 return;
415 }
416
417 typedef std::basic_istringstream<log4cplus::tchar> tistringstream;
418 tistringstream is(LOG4CPLUS_STRING_TO_TSTRING(config.toString()));
419 log4cplus::PropertyConfigurator(is).configure();
420 }
421
422 /////////////////////////////////////////////////////////////////////////////
423 10 int Main::daemonize()
424 {
425 10 pid = ::fork();
426
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
10 if (pid < 0) {
427 // Some error occurred
428 ::perror("fork()");
429 return pid;
430 }
431
1/2
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
10 else if (pid) {
432 // Parent here; go back to the caller
433 30 for (TaskList::iterator it = task.begin();
434
2/2
✓ Branch 6 taken 20 times.
✓ Branch 7 taken 10 times.
30 it != task.end(); ++it)
435
2/4
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 10 taken 20 times.
✗ Branch 11 not taken.
20 static_cast<Task*>(*it)->rt_init();
436 10 return 0;
437 }
438
439 const char *env = ::getenv("PDSERV_CONFIG");
440
441 // Load custom configuration file
442 if (!configFile.empty()) {
443 const char *err = config.load(configFile.c_str());
444 if (err)
445 std::cout << "Load config: " << err << std::endl;
446 else {
447 log_debug("Loaded specified configuration file %s",
448 configFile.c_str());
449 }
450 }
451 else if (env and ::strlen(env)) {
452 // Try to load environment configuration file
453 const char *err = config.load(env);
454
455 if (err)
456 std::cout << "Error loading config file " << env
457 << ": " << err << std::endl;
458 else {
459 log_debug("Loaded ENV config %s", env);
460 }
461 }
462 else {
463 // Try to load default configuration file
464 const char *f = QUOTE(SYSCONFDIR) "/pdserv.conf";
465 const char *err = config.load(f);
466 if (err) {
467 if (::access(f, R_OK))
468 log_debug("Could not access configuration file %s: %s",
469 f, ::strerror(errno));
470 else
471 std::cout << "Load config error: " << err << std::endl;
472 }
473 else {
474 log_debug("Loaded default configuration file %s", f);
475 }
476 }
477
478 if (!config) {
479 log_debug("No configuration loaded");
480 }
481
482 // Only child runs after this point
483 pid = getpid();
484
485 // Go to root
486 #ifndef PDS_DEBUG
487 ::chdir("/");
488 ::umask(0777);
489 #endif
490
491 // Reset signal handlers
492 ::signal(SIGHUP, SIG_DFL);
493 ::signal(SIGINT, SIG_DFL);
494 ::signal(SIGTERM, SIG_DFL);
495
496 // close all file handles
497 // sysconf() usually returns one more than max file handle
498 long int fd_max = ::sysconf(_SC_OPEN_MAX);
499 if (fd_max < _POSIX_OPEN_MAX)
500 fd_max = _POSIX_OPEN_MAX;
501 else if (fd_max > 100000)
502 fd_max = 512; // no rediculous values please
503 while (fd_max--) {
504 #ifdef PDS_DEBUG
505 if (fd_max == 2)
506 break;
507 #endif
508 ::close(fd_max);
509 }
510
511 #ifndef PDS_DEBUG
512 // Reopen STDIN, STDOUT and STDERR
513 if (STDIN_FILENO == ::open("/dev/null", O_RDWR)) {
514 dup2(STDIN_FILENO, STDOUT_FILENO);
515 dup2(STDIN_FILENO, STDERR_FILENO);
516
517 fcntl( STDIN_FILENO, F_SETFL, O_RDONLY);
518 fcntl(STDOUT_FILENO, F_SETFL, O_WRONLY);
519 fcntl(STDERR_FILENO, F_SETFL, O_WRONLY);
520 }
521 #endif
522
523 // Initialize non-real time tasks
524 for (TaskList::iterator it = task.begin(); it != task.end(); ++it)
525 static_cast<Task*>(*it)->nrt_init();
526
527 #ifdef PDS_DEBUG
528 consoleLogging();
529 #endif
530
531 // Do the logging configuration. Note that logging may open file handles
532 configureLogging(config["logging"]);
533
534 LOG4CPLUS_INFO(log4cplus::Logger::getRoot(),
535 LOG4CPLUS_TEXT("Started application ")
536 << LOG4CPLUS_STRING_TO_TSTRING(name)
537 << LOG4CPLUS_TEXT(", Version ")
538 << LOG4CPLUS_STRING_TO_TSTRING(version));
539
540 PdServ::Main::startServers(config);
541
542 // Hang here forever
543 while (true) {
544 pause();
545 }
546 return 0;
547 }
548
549 /////////////////////////////////////////////////////////////////////////////
550 PdServ::Main::Events Main::getEvents() const
551 {
552 return Events(events.begin(), events.end());
553 }
554
555 /////////////////////////////////////////////////////////////////////////////
556 void Main::prepare(PdServ::Session *session) const
557 {
558 session->data = new SessionData;
559 session->data->eventReadPointer = *eventDataWp;
560 }
561
562 /////////////////////////////////////////////////////////////////////////////
563 void Main::cleanup(const PdServ::Session *session) const
564 {
565 delete session->data;
566 }
567
568 /////////////////////////////////////////////////////////////////////////////
569 const PdServ::Event *Main::getNextEvent( const PdServ::Session* session,
570 size_t *index, bool *state, struct timespec *t) const
571 {
572 const EventData* eventData = session->data->eventReadPointer;
573 if (eventData == *eventDataWp)
574 return 0;
575
576 *index = eventData->index;
577 *state = eventData->state;
578 *t = eventData->time;
579
580 if (++session->data->eventReadPointer == eventDataEnd)
581 session->data->eventReadPointer = eventDataStart;
582
583 return eventData->event;
584 }
585
586 /////////////////////////////////////////////////////////////////////////////
587 1242 void Main::getParameters(Task *task, const struct timespec *t) const
588 {
589
1/2
✗ Branch 4 not taken.
✓ Branch 5 taken 1242 times.
1242 for (struct SDOStruct *s = sdo; s->count; s++) {
590 const Parameter *p = s->parameter;
591 const PdServ::Variable *v = p;
592 s->time = *t;
593 s->rv = p->trigger(reinterpret_cast<struct pdtask *>(task),
594 reinterpret_cast<const struct pdvariable *>(v),
595 p->addr + s->offset,
596 p->valueBuf + s->offset, s->count, p->priv_data);
597 s->count = 0;
598 }
599 1245 }
600