iCub-main
Loading...
Searching...
No Matches
theNVmanager.cpp
Go to the documentation of this file.
1// -*- Mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-
2
3
4/*
5 * Copyright (C) 2017 iCub Facility - Istituto Italiano di Tecnologia
6 * Author: Marco Accame
7 * email: marco.accame@iit.it
8 * website: www.robotcub.org
9 * Permission is granted to copy, distribute, and/or modify this program
10 * under the terms of the GNU General Public License, version 2 or any
11 * later version published by the Free Software Foundation.
12 *
13 * A copy of the license can be found at
14 * http://www.robotcub.org/icub/license/gpl.txt
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
19 * Public License for more details
20*/
21
22
23// --------------------------------------------------------------------------------------------------------------------
24// - public interface
25// --------------------------------------------------------------------------------------------------------------------
26
27#include "theNVmanager.h"
28
29
30
31// --------------------------------------------------------------------------------------------------------------------
32// - external dependencies
33// --------------------------------------------------------------------------------------------------------------------
34
35#include "ethManager.h"
36
37#include <mutex>
38#include <condition_variable>
39#include <chrono>
40#include <map>
41#include <cstring>
42
43#include "EoProtocol.h"
44#include "EoProtocolMN.h"
45
47
48
49
50// --------------------------------------------------------------------------------------------------------------------
51// - pimpl: private implementation (see scott meyers: item 22 of effective modern c++, item 31 of effective c++
52// --------------------------------------------------------------------------------------------------------------------
53
54
55
57{
58 static std::mutex mtx;
59
61 {
62 std::uint16_t expectedrops {0};
63 std::uint16_t receivedrops {0};
64 eOprotIP_t _ipv4 {0};
65 eOprotID32_t _id32 {0};
66 std::uint32_t signature {eo_rop_SIGNATUREdummy};
67 std::mutex mtx_semaphore {};
68 std::condition_variable cv_semaphore {};
69 ACE_thread_t owner {0};
70 double timeofwait {0};
71 double timeofpost {0};
72
74 expectedrops(0), receivedrops(0), _ipv4(0), _id32(0), signature(eo_rop_SIGNATUREdummy), owner(0), timeofwait(0), timeofpost(0)
75 {
76 }
77
79 {
80 owner = 0;
81 }
82
83 void load(eOprotIP_t _ip, eOprotID32_t _id, std::uint32_t _s)
84 {
85 expectedrops = 1;
86 receivedrops = 0;
87
88 _ipv4 = _ip;
89 _id32 = _id;
90 signature = _s;
91 owner = ACE_Thread::self();
92 }
93
94 void load(eOprotIP_t _ip, const std::vector<eOprotID32_t> &_ids, std::uint32_t _s)
95 {
96 expectedrops = static_cast<uint16_t>(_ids.size()); // ok to downcast
97 receivedrops = 0;
98
99 _ipv4 = _ip;
100 _id32 = 0xffffff;
101 signature = _s;
102 owner = ACE_Thread::self();
103 }
104
105
106
107 bool wait(std::uint16_t &numofrxrops, double timeout = 0.5)
108 {
109 timeofwait = SystemClock::nowSystem();
110 const int timeout_millis = static_cast<int>(1000.0 * timeout);
111 std::unique_lock<std::mutex> lck(mtx_semaphore);
112 bool r = (cv_semaphore.wait_for(lck, std::chrono::milliseconds(timeout_millis)) == cv_status::no_timeout);
113 numofrxrops = receivedrops;
114 return r;
115 }
116
117 bool post()
118 {
119 receivedrops++;
121 {
122 timeofpost = SystemClock::nowSystem();
123 cv_semaphore.notify_one();
124 }
125 return true;
126 }
127 };
128
129
130 struct Data
131 {
132 std::mutex locker {};
133 // the key is u64: either [0, signature] or [ipv4, id32]
134 std::multimap<std::uint64_t, askTransaction*> themap {};
135 std::uint32_t sequence {0};
136 std::uint32_t filler {0};
137
138 Data() { reset(); }
139 void reset()
140 {
141 themap.clear();
142 sequence = 0;
143 }
144
145 std::uint32_t uniquesignature()
146 {
147 std::uint32_t r = sequence++;
148 if(sequence >= 0xA0000000)
149 {
150 sequence = 0;
151 }
152 return r;
153 }
154
155 void insert(askTransaction *transaction, const eOprotIP_t ip, const eOprotID32_t id, std::uint32_t &assignedsignature)
156 {
157 assignedsignature = uniquesignature();
158 transaction->load(ip, id, assignedsignature);
159 std::uint64_t key = static_cast<std::uint64_t>(assignedsignature);
160 themap.insert(std::make_pair(key, transaction));
161 }
162
163 void insert(askTransaction *transaction, const eOprotIP_t ip, const eOprotID32_t id)
164 {
165 transaction->load(ip, id, eo_rop_SIGNATUREdummy);
166 std::uint64_t key = (static_cast<std::uint64_t>(ip) << 32) | static_cast<std::uint64_t>(id);
167 themap.insert(std::make_pair(key, transaction));
168 }
169
170 void insert(askTransaction *transaction, const eOprotIP_t ip, const std::vector<eOprotID32_t> &ids, std::uint32_t &assignedsignature)
171 {
172 assignedsignature = uniquesignature();
173 transaction->load(ip, ids, assignedsignature);
174 std::uint64_t key = static_cast<std::uint64_t>(assignedsignature);
175 themap.insert(std::make_pair(key, transaction));
176 }
177
178 void remove(const std::uint32_t signature)
179 {
180 std::uint64_t key = static_cast<std::uint64_t>(signature);
181 themap.erase(themap.find(key));
182 }
183
184 bool alert(const std::uint32_t signature)
185 {
186 //yDebug() << "theNVmanager::Impl::Data::alert(): themap.size() =" << themap.size();
187 if(true == themap.empty())
188 {
189 yDebug() << "theNVmanager::Impl::Data::alert(): themap is empty()";
190
191 return false;
192 }
193 std::uint64_t key = static_cast<std::uint64_t>(signature);
194 std::multimap<std::uint64_t, askTransaction*>::iterator it = themap.find(key);
195
196 if(themap.end() == it)
197 {
198 yDebug() << "theNVmanager::Impl::Data::alert(): signature not found" << signature;
199 return false;
200 }
201
202 (*it).second->post();
203
204 return true;
205 }
206
207 void remove(const eOprotIP_t ip, const eOprotID32_t id)
208 {
209 std::uint64_t key = (static_cast<std::uint64_t>(ip) << 32) | static_cast<std::uint64_t>(id);
210 themap.erase(themap.find(key));
211 }
212
213 bool alert(const eOprotIP_t ip, const eOprotID32_t id)
214 {
215 //yDebug() << "theNVmanager::Impl::Data::alert(): themap.size() =" << themap.size();
216 if(true == themap.empty())
217 {
218 yDebug() << "theNVmanager::Impl::Data::alert(): themap is empty()";
219
220 return false;
221 }
222 std::uint64_t key = (static_cast<std::uint64_t>(ip) << 32) | static_cast<std::uint64_t>(id);
223 std::multimap<std::uint64_t, askTransaction*>::iterator it = themap.find(key);
224
225 if(themap.end() == it)
226 {
227 yDebug() << "theNVmanager::Impl::Data::alert(): key not found" << key;
228 return false;
229 }
230
231 (*it).second->post();
232
233 return true;
234 }
235
236 void lock()
237 {
238 locker.lock();
239 }
240
241 void unlock()
242 {
243 locker.unlock();
244 }
245 };
246
247
248
249 // see http://en.cppreference.com/w/cpp/container/map/find
250
251
252// Config config;
253
255
256 // we can use: std::map, std::multimap, std::set, std::multiset because therya re ordered and thus quicker. they have teh find method.
257 // strategy: find by signature. in such a way every transaction is unique. it must have ....
258 // see https://www.fluentcpp.com/2017/01/26/searching-an-stl-container/
259
261 {
262 data.reset();
263 }
264
265
266
267
268// bool initialise(const Config &_config);
269
270 bool supported(const eOprotIP_t ipv4);
271 bool supported(const eOprotIP_t ipv4, const eOprotID32_t id32);
272
273 size_t sizeofnv(const eOprotID32_t id32);
274
275 eth::AbstractEthResource * ethresource(const eOprotIP_t ipv4);
276 eth::AbstractEthResource * ethresourceID32(const eOprotIP_t ipv4, const eOprotID32_t id32);
277 eth::AbstractEthResource * ethresourceID32s(const eOprotIP_t ipv4, const std::vector<eOprotID32_t> &id32s);
278
279
281 eth::HostTransceiver * transceiver(const eOprotIP_t ipv4);
282
283 bool validparameters(eth::HostTransceiver *t, const eOprotID32_t id32, void *value);
284
285 bool validparameters(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value);
286
287
288 bool validparameters(eth::HostTransceiver *t, const std::vector<eOprotID32_t> &id32s, const std::vector<void*> &values);
289
290 bool set(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value);
291 bool setcheck(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value, const unsigned int retries, double waitbeforecheck, double timeout);
292
293
294 //size_t maxSizeOfNV(const eOprotIP_t ipv4);
295
296 bool ping(eth::HostTransceiver *t, eoprot_version_t &mnprotversion, const double timeout = 0.5, const unsigned int retries = 20);
297
298 bool ask(eth::HostTransceiver *t, const eOprotID32_t id32, void *value, const double timeout);
299
300 bool ask(eth::HostTransceiver *t, const std::vector<eOprotID32_t> &id32s, const std::vector<void*> &values, const double timeout);
301
302 bool check(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value, const double timeout, const unsigned int retries);
303
304 bool signatureisvalid(const std::uint32_t signature);
305 bool onarrival(const ropCode ropcode, const eOprotIP_t ipv4, const eOprotID32_t id32, const std::uint32_t signature);
306
307 bool wait(const ropCode ropcode, eth::HostTransceiver *t, const eOprotID32_t id32, const double timeout);
308
309 bool read(eth::HostTransceiver *t, const eOprotID32_t id32, void *value);
310
311 bool command(eth::HostTransceiver *t, const eOprotID32_t id32cmd, const void *cmd, const eOprotID32_t id32rep, void *rep, double timeout = 0.5);
312
314 string getid32string(eOprotID32_t id32);
315};
316
317
319
320
321//bool eth::theNVmanager::Impl::initialise(const Config &_config)
322//{
323// config = _config;
324// data.pp1 = 1;
325// return true;
326//}
327
332
334{
335 char nvinfo[128];
336 eoprot_ID2information(id32, nvinfo, sizeof(nvinfo));
337 return nvinfo;
338}
339
340bool eth::theNVmanager::Impl::supported(const eOprotIP_t ipv4)
341{
342 eth::HostTransceiver *t = transceiver(ipv4);
343
344 return (nullptr == t) ? false : true;
345}
346
347bool eth::theNVmanager::Impl::supported(const eOprotIP_t ipv4, const eOprotID32_t id32)
348{
349 eth::HostTransceiver *t = transceiver(ipv4);
350
351 if(nullptr == t)
352 {
353 return false;
354 }
355
356 return t->isID32supported(id32);
357}
358
359size_t eth::theNVmanager::Impl::sizeofnv(const eOprotID32_t id32)
360{
361 return eoprot_variable_sizeof_get(eoprot_board_localboard, id32);
362}
363
364
365
366
368{
370 if(nullptr == res)
371 {
372 char ipinfo[20];
373 eo_common_ipv4addr_to_string(ipv4, ipinfo, sizeof(ipinfo));
374 yError("theNVmanager::Impl::transceiverZ() cannot obtain from TheEthManager a EthResource * for IP = %s", ipinfo);
375 }
376
377 if(nullptr == res)
378 {
379 return nullptr;
380 }
381
382 return res->getTransceiver();
383}
384
385
386//eth::AbstractEthResource * eth::theNVmanager::Impl::ethresourceID32(const eOprotIP_t ipv4, const eOprotID32_t id32)
387//{
388// eth::AbstractEthResource * res = eth::TheEthManager::instance()->getEthResource(ipv4);
389// if(nullptr == res)
390// {
391// char ipinfo[20];
392// eo_common_ipv4addr_to_string(ipv4, ipinfo, sizeof(ipinfo));
393// yError("theNVmanager::Impl::ethresourceID32() cannot obtain from TheEthManager a EthResource * for IP = %s", ipinfo);
394// return nullptr;
395// }
396
397// eth::HostTransceiver *t = transceiver(res);
398// if(nullptr == tra)
399// {
400// return nullptr;
401// }
402
403// if(false == t->isID32supported(id32))
404// {
405// char nvinfo[128];
406// eoprot_ID2information(id32, nvinfo, sizeof(nvinfo));
407// yError() << "theNVmanager::Impl::ethresourceID32() called with an invalid ID in BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "for nv" << nvinfo;
408// return nullptr;
409// }
410
411// return res;
412//}
413
414
415//eth::AbstractEthResource * eth::theNVmanager::Impl::ethresourceID32s(const eOprotIP_t ipv4, const std::vector<eOprotID32_t> &id32s)
416//{
417// eth::AbstractEthResource * res = eth::TheEthManager::instance()->getEthResource(ipv4);
418// if(nullptr == res)
419// {
420// char ipinfo[20];
421// eo_common_ipv4addr_to_string(ipv4, ipinfo, sizeof(ipinfo));
422// yError("theNVmanager::Impl::ethresourceID32() cannot obtain from TheEthManager a EthResource * for IP = %s", ipinfo);
423// return nullptr;
424// }
425
426// eth::HostTransceiver *t = transceiver(res);
427// if(nullptr == tra)
428// {
429// return nullptr;
430// }
431
432// for(int i=0; i<id32s.size(); i++)
433// {
434// if(false == t->isID32supported(id32s[i]))
435// {
436// char nvinfo[128];
437// eoprot_ID2information(id32s[i], nvinfo, sizeof(nvinfo));
438// yError() << "theNVmanager::Impl::ethresourceID32s(ip, vector<eOprotID32_t>) called with an invalid ID in BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "for nv" << nvinfo;
439// return nullptr;
440// }
441// }
442
443
444// return res;
445//}
446
447bool eth::theNVmanager::Impl::validparameters(eth::HostTransceiver *t, const eOprotID32_t id32, void *value)
448{
449 if(nullptr == t)
450 {
451 return false;
452 }
453
454 if(false == t->isID32supported(id32))
455 {
456 const AbstractEthResource::Properties & props = getboardproperties(t);;
457 yError() << "theNVmanager::Impl::validparameters() called with an invalid ID in BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "for nv" << getid32string(id32);
458 return false;
459 }
460
461 if(nullptr == value)
462 {
463 const AbstractEthResource::Properties & props = getboardproperties(t);
464 yError() << "theNVmanager::Impl::validparameters(res, ipv4, id32, value) found invalid params in BOARD" << props.boardnameString << "IP" << props.ipv4addrString;
465 return false;
466 }
467
468 return true;
469}
470
471bool eth::theNVmanager::Impl::validparameters(eth::HostTransceiver *t, const std::vector<eOprotID32_t> &id32s, const std::vector<void*> &values)
472{
473 if(nullptr == t)
474 {
475 return false;
476 }
477
478 for(int i=0; i<id32s.size(); i++)
479 {
480 if(false == t->isID32supported(id32s[i]))
481 {
482 const AbstractEthResource::Properties & props = getboardproperties(t);
483 yError() << "theNVmanager::Impl::validparameters(vector<>) called with an invalid ID in BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "for nv" << getid32string(id32s[i]);
484 return false;
485 }
486 }
487
488 if((0 == id32s.size()) || (id32s.size() != values.size()))
489 {
490 const AbstractEthResource::Properties & props = getboardproperties(t);
491 yError() << "theNVmanager::Impl::validparameters(vector<>) found invalid params in BOARD" << props.boardnameString << "IP" << props.ipv4addrString;
492 return false;
493 }
494
495 return true;
496}
497
498bool eth::theNVmanager::Impl::validparameters(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value)
499{
500 if(nullptr == t)
501 {
502 return false;
503 }
504
505 if(false == t->isID32supported(id32))
506 {
507 const AbstractEthResource::Properties & props = getboardproperties(t);
508 yError() << "theNVmanager::Impl::validparameters() called with an invalid ID in BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "for nv" << getid32string(id32);
509 return false;
510 }
511
512 if(nullptr == value)
513 {
514 const AbstractEthResource::Properties & props = getboardproperties(t);
515 yError() << "theNVmanager::Impl::validparameters(res, ipv4, id32, value) found invalid params in BOARD" << props.boardnameString << "IP" << props.ipv4addrString;
516 return false;
517 }
518
519 return true;
520}
521
522
523
524bool eth::theNVmanager::Impl::setcheck(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value, const unsigned int retries, double waitbeforecheck, double timeout)
525{
526 int attempt = 0;
527 bool done = false;
528
529
530 if(false == validparameters(t, id32, value))
531 {
532 return false;
533 }
534
535
536 int maxattempts = retries + 1;
537
538 for(attempt=0; (attempt<maxattempts) && (false == done); attempt++)
539 {
540 if(false == set(t, id32, value))
541 {
542 const AbstractEthResource::Properties & props = getboardproperties(t);
543 yWarning() << "theNVmanager::Impl::setcheck() had an error while calling set() in BOARD" << props.boardnameString << "with IP" << props.ipv4addrString << "at attempt #" << attempt+1;
544 continue;
545 }
546
547 // ok, now i wait some time before asking the value back for verification
548 SystemClock::delaySystem(waitbeforecheck);
549
550 if(false == check(t, id32, value, timeout, 0))
551 {
552 const AbstractEthResource::Properties & props = getboardproperties(t);
553 yWarning() << "theNVmanager::Impl::setcheck() had an error while calling check() in BOARD" << props.boardnameString << "with IP" << props.ipv4addrString << "at attempt #" << attempt+1;
554 }
555 else
556 {
557 done = true;
558 }
559
560 }
561
562
563 if(done)
564 {
565 if(attempt > 1)
566 {
567 const AbstractEthResource::Properties & props = getboardproperties(t);
568 yWarning() << "theNVmanager::Impl::setcheck() has set and verified ID" << getid32string(id32) << "in BOARD" << props.boardnameString << "with IP" << props.ipv4addrString << "at attempt #" << attempt;
569 }
570 else
571 {
572// if(verbosewhenok)
573// {
574// yDebug() << "EthResource::setRemoteValueUntilVerified has set and verified ID" << nvinfo << "in BOARD" << getProperties().boardnameString << "with IP" << getProperties().ipv4addrString << "at attempt #" << attempt;
575// }
576 }
577 }
578 else
579 {
580 const AbstractEthResource::Properties & props = getboardproperties(t);
581 yError() << "FATAL: theNVmanager::Impl::setcheck() could not set and verify ID" << getid32string(id32) << "in BOARD" << props.boardnameString << "with IP" << props.ipv4addrString << " even after " << attempt << "attempts";
582 }
583
584
585 return(done);
586}
587
588
589bool eth::theNVmanager::Impl::check(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value, const double timeout, const unsigned int retries)
590{
591 if(false == validparameters(t, id32, value))
592 {
593 return false;
594 }
595
596 bool equal = false;
597
598 std::uint16_t size = sizeofnv(id32);
599 std::uint8_t * vv = new std::uint8_t[size];
600
601 for(int i=0; i<(retries+1); i++)
602 {
603 if(true == ask(t, id32, reinterpret_cast<void*>(vv), timeout))
604 {
605 if(0 == std::memcmp(value, vv, size))
606 {
607 equal = true;
608 }
609 }
610 }
611
612
613 delete[] vv;
614
615 return equal;
616}
617
618
619
620bool eth::theNVmanager::Impl::wait(const ropCode ropcode, eth::HostTransceiver *t, const eOprotID32_t id32, const double timeout)
621{
622 const eOprotIP_t ipv4 = t->getIPv4();
623
624 if(false == supported(ipv4, id32))
625 {
626 const AbstractEthResource::Properties & props = getboardproperties(t);
627 yError() << "theNVmanager::Impl::wait() fails because the following ipv4-id32 is not supported: ipv4 =" << props.ipv4addrString << "id32 =" << getid32string(id32);
628 return false;
629 }
630 // 2. must prepare wait data etc.
631
632 askTransaction* transaction = new askTransaction;
633
634
635 data.lock();
636
637 data.insert(transaction, ipv4, id32);
638
639 data.unlock();
640
641 std::uint16_t numberOfReceivedROPs = 0;
642
643 if(false == transaction->wait(numberOfReceivedROPs, timeout))
644 {
645 // a timeout occurred .... manage it.
646
647 // remove the transaction
648 data.lock();
649 data.remove(ipv4, id32);
650 data.unlock();
651 // and delete it
652 delete transaction;
653
654 const AbstractEthResource::Properties & props = getboardproperties(t);
655 yError() << "theNVmanager::Impl::wait() had a timeout for BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "and nv" << getid32string(id32);
656 return false;
657 }
658
659 // remove the transaction
660 data.lock();
661 data.remove(ipv4, id32);
662 data.unlock();
663 // and delete it
664 delete transaction;
665
666 return true;
667}
668
669
670bool eth::theNVmanager::Impl::read(eth::HostTransceiver *t, const eOprotID32_t id32, void *value)
671{
672 if(false == validparameters(t, id32, value))
673 {
674 return false;
675 }
676
677
678 // 2. must prepare wait data etc.
679 if(false == t->read(id32, value))
680 {
681 const AbstractEthResource::Properties & props = getboardproperties(t);
682 yError() << "theNVmanager::Impl::ask() fails t->read() for BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "and nv" << getid32string(id32);
683 return false;
684 }
685
686 return true;
687}
688
689
690bool eth::theNVmanager::Impl::command(eth::HostTransceiver *t, const eOprotID32_t id32cmd, const void *cmd, const eOprotID32_t id32rep, void *rep, double timeout)
691{
692 if(false == set(t, id32cmd, cmd))
693 {
694 const AbstractEthResource::Properties & props = getboardproperties(t);
695 yError() << "theNVmanager::Impl::command() fails a set() to IP" << props.ipv4addrString << "for nv" << getid32string(id32cmd);
696 return false;
697 }
698
699 if(false == wait(theNVmanager::ropCode::sig, t, id32rep, timeout))
700 {
701 const AbstractEthResource::Properties & props = getboardproperties(t);
702 yError() << "theNVmanager::Impl::command() fails a wait() from IP" << props.ipv4addrString << "for nv" << getid32string(id32rep);
703 return false;
704 }
705
706 if(false == read(t, id32rep, rep))
707 {
708 const AbstractEthResource::Properties & props = getboardproperties(t);
709 yError() << "theNVmanager::Impl::command() fails a read() for IP" << props.ipv4addrString << "and nv" << getid32string(id32rep);
710 return false;
711 }
712
713 return true;
714}
715
716
717
718//size_t eth::theNVmanager::Impl::maxSizeOfNV(const eOprotIP_t ipv4)
719//{
720// eth::AbstractEthResource * res = ethresource(ipv4);
721
722// if(nullptr == res)
723// {
724// return 0;
725// }
726// return res->getMaxSizeofROP();
727//}
728
729bool eth::theNVmanager::Impl::ping(eth::HostTransceiver *t, eoprot_version_t &mnprotversion, const double timeout, const unsigned int retries)
730{
731 eOprotID32_t id32 = eoprot_ID_get(eoprot_endpoint_management, eoprot_entity_mn_comm, 0, eoprot_tag_mn_comm_status_managementprotocolversion);
732 bool replied = false;
733
734 if(false == supported(t->getIPv4(), id32))
735 {
736 const AbstractEthResource::Properties & props = getboardproperties(t);
737 yError() << "theNVmanager::Impl::ping() fails because the following ipv4-id32 is not supported: ipv4 =" << props.ipv4addrString << "id32 =" << getid32string(id32);
738 return replied;
739 }
740
741 for(int i=0; i<(1+retries); i++)
742 {
743 if(true == ask(t, id32, &mnprotversion, timeout))
744 {
745 replied = true;
746 break;
747 }
748 }
749
750 return replied;
751}
752
753
754
755bool eth::theNVmanager::Impl::ask(eth::HostTransceiver *t, const eOprotID32_t id32, void *value, const double timeout)
756{
757 if(false == validparameters(t, id32, value))
758 {
759 yError() << "theNVmanager::Impl::ask() called with invalid parameters";
760 return false;
761 }
762
763 // 1. must prepare wait data etc.
764
765 askTransaction* transaction = new askTransaction;
766 std::uint32_t assignedsignature = 0;
767
768 data.lock();
769
770 data.insert(transaction, t->getIPv4(), id32, assignedsignature);
771
772 data.unlock();
773
774 // 2. must send a request
775
776 if(false == t->addROPask(id32, assignedsignature))
777 {
778 const AbstractEthResource::Properties & props = getboardproperties(t);
779 yError() << "theNVmanager::Impl::ask() fails res->addROPask() to BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "for nv" << getid32string(id32);
780
781 // remove the transaction
782 data.lock();
783 data.remove(assignedsignature);
784 data.unlock();
785 // and delete it
786 delete transaction;
787
788 return false;
789 }
790
791 // 3. must wait now and manage a possible timeout
792 std::uint16_t numberOfReceivedROPs = 0;
793
794 if(false == transaction->wait(numberOfReceivedROPs, timeout))
795 {
796 // a timeout occurred .... manage it.
797
798 // remove the transaction
799 data.lock();
800 data.remove(assignedsignature);
801 data.unlock();
802 // and delete it
803 delete transaction;
804
805 const AbstractEthResource::Properties & props = getboardproperties(t);
806 yError() << "theNVmanager::Impl::ask() had a timeout for BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "and nv" << getid32string(id32);
807 return false;
808 }
809
810 // remove the transaction
811 data.lock();
812 data.remove(assignedsignature);
813 data.unlock();
814 // and delete it
815 delete transaction;
816
817 // 4. can retrieve value now
818 if(false == t->read(id32, value))
819 {
820 const AbstractEthResource::Properties & props = getboardproperties(t);
821 yError() << "theNVmanager::Impl::ask() fails res->getLocalValue() for BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "and nv" << getid32string(id32);
822 return false;
823 }
824
825 return true;
826}
827
828
829//bool eth::theNVmanager::Impl::ask(const eOprotIP_t ipv4, const eOprotID32_t id32, void *value, const double timeout)
830//{
831// eth::AbstractEthResource * res = ethresource(ipv4);
832
833// if(false == validparameters(res, ipv4, id32, value))
834// {
835// return false;
836// }
837
838
839// // 2. must prepare wait data etc.
840
841
842// askTransaction* transaction = new askTransaction;
843// std::uint32_t assignedsignature = 0;
844
845// data.lock();
846
847// data.insert(transaction, ipv4, id32, assignedsignature);
848
849// data.unlock();
850
851// // 3. must send a request
852
853// if(false == res->addROPask(id32, assignedsignature))
854// {
855// char nvinfo[128];
856// eoprot_ID2information(id32, nvinfo, sizeof(nvinfo));
857// yError() << "theNVmanager::Impl::ask() fails res->addGetROP() to BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "for nv" << nvinfo;
858
859// // remove the transaction
860// data.lock();
861// data.remove(assignedsignature);
862// data.unlock();
863// // and delete it
864// delete transaction;
865
866// return false;
867// }
868
869// // 4. must wait now and manage a possible timeout
870// std::uint16_t numberOfReceivedROPs = 0;
871
872// if(false == transaction->wait(numberOfReceivedROPs, timeout))
873// {
874// // a timeout occurred .... manage it.
875
876// // remove the transaction
877// data.lock();
878// data.remove(assignedsignature);
879// data.unlock();
880// // and delete it
881// delete transaction;
882
883// char nvinfo[128];
884// eoprot_ID2information(id32, nvinfo, sizeof(nvinfo));
885// yError() << "theNVmanager::Impl::ask() had a timeout for BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "and nv" << nvinfo;
886// return false;
887// }
888
889// // remove the transaction
890// data.lock();
891// data.remove(assignedsignature);
892// data.unlock();
893// // and delete it
894// delete transaction;
895
896// // 5. can retrieve value now
897// uint16_t size = 0;
898// if(false == res->readBufferedValue(id32, reinterpret_cast<uint8_t*>(value), &size))
899// {
900// char nvinfo[128];
901// eoprot_ID2information(id32, nvinfo, sizeof(nvinfo));
902// yError() << "theNVmanager::Impl::ask() fails res->readBufferedValue() for BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "and nv" << nvinfo;
903// return false;
904// }
905
906// return true;
907//}
908
909
910bool eth::theNVmanager::Impl::ask(eth::HostTransceiver *t, const std::vector<eOprotID32_t> &id32s, const std::vector<void*> &values, const double timeout)
911{
912 const eOprotIP_t ipv4 = t->getIPv4();
913
914 if(false == validparameters(t, id32s, values))
915 {
916 return false;
917 }
918
919
920 // 2. must prepare wait data etc.
921
922
923 askTransaction* transaction = new askTransaction;
924 std::uint32_t assignedsignature = 0;
925
926 data.lock();
927
928 data.insert(transaction, ipv4, id32s, assignedsignature);
929
930 data.unlock();
931
932 // 3. must send a request to all the id32s
933
934 for(int i=0; i<id32s.size(); i++)
935 {
936 if(false == t->addROPask(id32s[i], assignedsignature))
937 {
938 const AbstractEthResource::Properties & props = getboardproperties(t);
939 yError() << "theNVmanager::Impl::ask() fails t->addROPask() to BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "for nv" << getid32string(id32s[i]);
940
941 // remove the transaction
942 data.lock();
943 data.remove(assignedsignature);
944 data.unlock();
945 // and delete it
946 delete transaction;
947
948 return false;
949 }
950 }
951
952 // 4. must wait now and manage a possible timeout
953 std::uint16_t numberOfReceivedROPs = 0;
954
955 if(false == transaction->wait(numberOfReceivedROPs))
956 {
957 // a timeout occurred .... manage it.
958
959 // remove the transaction
960 data.lock();
961 data.remove(assignedsignature);
962 data.unlock();
963 // and delete it
964 delete transaction;
965
966 const AbstractEthResource::Properties & props = getboardproperties(t);
967 yError() << "theNVmanager::Impl::ask() had a timeout for BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "w/ multiple NVs. Received only" << numberOfReceivedROPs << "out of" << id32s.size();
968 return false;
969 }
970
971 //yDebug() << "received" << numberOfReceivedROPs << "numberOfReceivedROPs";
972
973 // remove the transaction
974 data.lock();
975 data.remove(assignedsignature);
976 data.unlock();
977 // and delete it
978 delete transaction;
979
980 // 5. can retrieve values now
981 for(int i=0; i<id32s.size(); i++)
982 {
983 if(false == t->read(id32s[i], values[i]))
984 {
985 const AbstractEthResource::Properties & props = getboardproperties(t);
986 yError() << "theNVmanager::Impl::ask() fails res->getLocalValue() for BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "and nv" << getid32string(id32s[i]);
987 return false;
988 }
989 }
990
991 return true;
992}
993
994
995bool eth::theNVmanager::Impl::set(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value)
996{
997
998// if(false == validparameters(t, id32, value))
999// {
1000// return false;
1001// }
1002
1003 if(false == t->addROPset(id32, value))
1004 {
1005 const AbstractEthResource::Properties & props = getboardproperties(t);
1006 yError() << "theNVmanager::Impl::set() fails t->addSetROP() to BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "for nv" << getid32string(id32);
1007 return false;
1008 }
1009
1010 return true;
1011}
1012
1013
1014bool eth::theNVmanager::Impl::signatureisvalid(const std::uint32_t signature)
1015{
1016 if((eo_rop_SIGNATUREdummy == signature) || (signature >= 0xaa000000))
1017 {
1018 return false;
1019 }
1020 return true;
1021}
1022
1023
1024bool eth::theNVmanager::Impl::onarrival(const ropCode ropcode, const eOprotIP_t ipv4, const eOprotID32_t id32, const std::uint32_t signature)
1025{
1026 static double tprev = SystemClock::nowSystem();
1027 double tcurr = SystemClock::nowSystem();
1028
1029 double delta = tcurr - tprev;
1030
1031 tprev = tcurr;
1032
1033 eth::HostTransceiver *t = transceiver(ipv4);
1034
1035 if(nullptr == t)
1036 {
1037 char ipinfo[32];
1038 eo_common_ipv4addr_to_string(ipv4, ipinfo, sizeof(ipinfo));
1039 yDebug() << "theNVmanager::Impl::onarrival() called for unsupported IP" << ipinfo << "for nv" << getid32string(id32) << "w/ signature" << signature;
1040 //#warning meglio CONTROLLARE CHE NON CI SIA NULLA QUI ...
1041 return false;
1042 }
1043
1044 if(ropCode::say == ropcode)
1045 {
1046 //const AbstractEthResource::Properties & props = getboardproperties(t);
1047 //yDebug() << "theNVmanager::Impl::onarrival(ropCode::say) called for BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "for nv" << getid32string(id32) << "w/ signature" << signature << "after sec" << delta;
1048
1049 // we manage a reply. we decide that we search only by signature.
1050
1051 if(false == signatureisvalid(signature))
1052 {
1053 yDebug() << "theNVmanager::Impl::onarrival() has found a false signature";
1054 return false;
1055 }
1056
1057 // 1. alert the thread which is waiting
1058 data.lock();
1059
1060 data.alert(signature);
1061
1062 data.unlock();
1063
1064 }
1065 else if(ropCode::sig == ropcode)
1066 {
1067 //const AbstractEthResource::Properties & props = getboardproperties(t);
1068 //yDebug() << "theNVmanager::Impl::onarrival(ropCode::sig) called for BOARD" << props.boardnameString << "IP" << props.ipv4addrString << "for nv" << getid32string(id32) << "w/ signature" << signature << "after sec" << delta;
1069
1070 // we manage an expected sig<>. we search by [ipv4-id32].
1071
1072
1073 // 1. alert the thread which is waiting
1074 data.lock();
1075
1076 data.alert(ipv4, id32);
1077
1078 data.unlock();
1079
1080 }
1081
1082 return true;
1083}
1084
1085
1086// --------------------------------------------------------------------------------------------------------------------
1087// - the class
1088// --------------------------------------------------------------------------------------------------------------------
1089
1091{
1092 static theNVmanager* p = nullptr;
1093
1094 std::lock_guard<std::mutex> lck(eth::theNVmanager::Impl::mtx);
1095 if(nullptr == p)
1096 {
1097 p = new theNVmanager();
1098 }
1099
1100 return *p;
1101}
1102
1103
1104eth::theNVmanager::theNVmanager()
1105: pImpl(new Impl)
1106{
1107 //Config cfg;
1108 //initialise(cfg);
1109
1110}
1111
1112
1113//bool eth::theNVmanager::initialise(const Config &config)
1114//{
1115
1116// pImpl->initialise(config);
1117
1118// return true;
1119//}
1120
1121//
1122//size_t eth::theNVmanager::sizeOfNV(const eOprotIP_t ipv4, const eOprotID32_t id32)
1123//{
1124// eth::AbstractEthResource * res = pImpl->ethresourceID32(ipv4, id32);
1125//
1126// if(nullptr == res)
1127// {
1128// return 0;
1129// }
1130//
1131// return eoprot_variable_sizeof_get(eoprot_board_localboard, id32);
1132//}
1133//
1134//size_t eth::theNVmanager::maxSizeOfNV(const eOprotIP_t ipv4)
1135//{
1136// return pImpl->maxSizeOfNV(ipv4);
1137//}
1138//
1139
1140
1141bool eth::theNVmanager::supported(const eOprotIP_t ipv4)
1142{
1143 return pImpl->supported(ipv4);
1144}
1145
1146bool eth::theNVmanager::supported(const eOprotIP_t ipv4, const eOprotID32_t id32)
1147{
1148 return pImpl->supported(ipv4, id32);
1149}
1150
1151size_t eth::theNVmanager::sizeOfNV(const eOprotID32_t id32)
1152{
1153 return pImpl->sizeofnv(id32);
1154}
1155
1156bool eth::theNVmanager::ping(const eOprotIP_t ipv4, eoprot_version_t &mnprotversion, const double timeout, const unsigned int retries)
1157{
1158 eth::HostTransceiver *t = pImpl->transceiver(ipv4);
1159 return pImpl->ping(t, mnprotversion, timeout, retries);
1160}
1161
1162bool eth::theNVmanager::ask(const eOprotIP_t ipv4, const eOprotID32_t id32, void *value, const double timeout)
1163{
1164 eth::HostTransceiver *t = pImpl->transceiver(ipv4);
1165 return pImpl->ask(t, id32, value, timeout);
1166}
1167
1168bool eth::theNVmanager::ask(eth::HostTransceiver *t, const eOprotID32_t id32, void *value, const double timeout)
1169{
1170 return pImpl->ask(t, id32, value, timeout);
1171}
1172
1173
1174
1175bool eth::theNVmanager::ask(const eOprotIP_t ipv4, const std::vector<eOprotID32_t> &id32s, const std::vector<void*> &values, const double timeout)
1176{
1177 eth::HostTransceiver *t = pImpl->transceiver(ipv4);
1178 return pImpl->ask(t, id32s, values, timeout);
1179}
1180
1181bool eth::theNVmanager::ask(eth::HostTransceiver *t, const std::vector<eOprotID32_t> &id32s, const std::vector<void*> &values, const double timeout)
1182{
1183 return pImpl->ask(t, id32s, values, timeout);
1184}
1185
1186bool eth::theNVmanager::set(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value)
1187{
1188 return pImpl->set(t, id32, value);
1189}
1190
1191bool eth::theNVmanager::set(const eOprotIP_t ipv4, const eOprotID32_t id32, const void *value)
1192{
1193 eth::HostTransceiver *t = pImpl->transceiver(ipv4);
1194 return pImpl->set(t, id32, value);
1195}
1196
1197
1198bool eth::theNVmanager::check(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value, const double timeout, const unsigned int retries)
1199{
1200 return pImpl->check(t, id32, value, timeout, retries);
1201}
1202
1203bool eth::theNVmanager::check(const eOprotIP_t ipv4, const eOprotID32_t id32, const void *value, const double timeout, const unsigned int retries)
1204{
1205 eth::HostTransceiver *t = pImpl->transceiver(ipv4);
1206 return pImpl->check(t, id32, value, timeout, retries);
1207}
1208
1209
1210bool eth::theNVmanager::setcheck(const eOprotIP_t ipv4, const eOprotID32_t id32, const void *value, const unsigned int retries, double waitbeforecheck, double timeout)
1211{
1212 eth::HostTransceiver *t = pImpl->transceiver(ipv4);
1213 return pImpl->setcheck(t, id32, value, retries, waitbeforecheck, timeout);
1214}
1215
1216bool eth::theNVmanager::setcheck(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value, const unsigned int retries, double waitbeforecheck, double timeout)
1217{
1218 return pImpl->setcheck(t, id32, value, retries, waitbeforecheck, timeout);
1219}
1220
1221bool eth::theNVmanager::onarrival(const ropCode ropcode, const eOprotIP_t ipv4, const eOprotID32_t id32, const std::uint32_t signature)
1222{
1223 return pImpl->onarrival(ropcode, ipv4, id32, signature);
1224}
1225
1226//bool eth::theNVmanager::wait(const ropCode ropcode, const eOprotIP_t ipv4, const eOprotID32_t id32, const double timeout)
1227//{
1228// return pImpl->wait(ropcode, ipv4, id32, timeout);
1229//}
1230
1231//bool eth::theNVmanager::read(const eOprotIP_t ipv4, const eOprotID32_t id32, void *value)
1232//{
1233// return pImpl->read(ipv4, id32, value);
1234//}
1235
1236bool eth::theNVmanager::command(const eOprotIP_t ipv4, const eOprotID32_t id32cmd, const void *cmd, const eOprotID32_t id32rep, void *rep, double timeout)
1237{
1238 eth::HostTransceiver *t = pImpl->transceiver(ipv4);
1239 return pImpl->command(t, id32cmd, cmd, id32rep, rep, timeout);
1240}
1241
1242
1243
1244
1245
1246// - end-of-file (leave a blank line after)----------------------------------------------------------------------------
1247
1248
1249
1250
1251
@ data
virtual HostTransceiver * getTransceiver()=0
virtual const Properties & getProperties()=0
eth::AbstractEthResource * getEthResource(eOipv4addr_t ipv4)
static TheEthManager * instance()
bool supported(const eOprotIP_t ipv4)
bool check(const eOprotIP_t ipv4, const eOprotID32_t id32, const void *value, const double timeout=0.5, const unsigned int retries=0)
bool onarrival(const ropCode ropcode, const eOprotIP_t ipv4, const eOprotID32_t id32, const std::uint32_t signature)
static theNVmanager & getInstance()
size_t sizeOfNV(const eOprotID32_t id32)
bool setcheck(const eOprotIP_t ipv4, const eOprotID32_t id32, const void *value, const unsigned int retries=10, double waitbeforecheck=0.001, double timeout=0.5)
bool ask(const eOprotIP_t ipv4, const eOprotID32_t id32, void *value, const double timeout=0.5)
bool command(const eOprotIP_t ipv4, const eOprotID32_t id32cmd, const void *cmd, const eOprotID32_t id32rep, void *rep, double timeout=0.5)
bool ping(const eOprotIP_t ipv4, eoprot_version_t &mnprotversion, const double timeout=0.5, const unsigned int retries=20)
bool set(const eOprotIP_t ipv4, const eOprotID32_t id32, const void *value)
cmd
Definition dataTypes.h:30
bool addROPask(const eOprotID32_t id32, const uint32_t signature=eo_rop_SIGNATUREdummy)
bool addROPset(const eOprotID32_t id32, const void *data, const uint32_t signature=eo_rop_SIGNATUREdummy)
bool isID32supported(const eOprotID32_t id32)
AbstractEthResource * getResource()
bool read(const eOprotID32_t id32, void *data)
bool done
Definition main.cpp:42
axis equal
void insert(askTransaction *transaction, const eOprotIP_t ip, const eOprotID32_t id, std::uint32_t &assignedsignature)
bool alert(const eOprotIP_t ip, const eOprotID32_t id)
void remove(const std::uint32_t signature)
void insert(askTransaction *transaction, const eOprotIP_t ip, const eOprotID32_t id)
std::multimap< std::uint64_t, askTransaction * > themap
void insert(askTransaction *transaction, const eOprotIP_t ip, const std::vector< eOprotID32_t > &ids, std::uint32_t &assignedsignature)
void remove(const eOprotIP_t ip, const eOprotID32_t id)
bool alert(const std::uint32_t signature)
void load(eOprotIP_t _ip, const std::vector< eOprotID32_t > &_ids, std::uint32_t _s)
void load(eOprotIP_t _ip, eOprotID32_t _id, std::uint32_t _s)
bool wait(std::uint16_t &numofrxrops, double timeout=0.5)
const eth::AbstractEthResource::Properties & getboardproperties(eth::HostTransceiver *t)
bool ask(eth::HostTransceiver *t, const eOprotID32_t id32, void *value, const double timeout)
bool setcheck(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value, const unsigned int retries, double waitbeforecheck, double timeout)
eth::HostTransceiver * transceiver(eth::AbstractEthResource *res)
bool check(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value, const double timeout, const unsigned int retries)
bool supported(const eOprotIP_t ipv4)
string getid32string(eOprotID32_t id32)
bool wait(const ropCode ropcode, eth::HostTransceiver *t, const eOprotID32_t id32, const double timeout)
bool read(eth::HostTransceiver *t, const eOprotID32_t id32, void *value)
bool command(eth::HostTransceiver *t, const eOprotID32_t id32cmd, const void *cmd, const eOprotID32_t id32rep, void *rep, double timeout=0.5)
eth::AbstractEthResource * ethresourceID32(const eOprotIP_t ipv4, const eOprotID32_t id32)
eth::AbstractEthResource * ethresource(const eOprotIP_t ipv4)
bool onarrival(const ropCode ropcode, const eOprotIP_t ipv4, const eOprotID32_t id32, const std::uint32_t signature)
eth::AbstractEthResource * ethresourceID32s(const eOprotIP_t ipv4, const std::vector< eOprotID32_t > &id32s)
static std::mutex mtx
bool set(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value)
size_t sizeofnv(const eOprotID32_t id32)
bool signatureisvalid(const std::uint32_t signature)
bool ping(eth::HostTransceiver *t, eoprot_version_t &mnprotversion, const double timeout=0.5, const unsigned int retries=20)
bool validparameters(eth::HostTransceiver *t, const eOprotID32_t id32, void *value)