iCub-main
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 
46 #include<abstractEthResource.h>
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;
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;
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 
260  Impl()
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 
318 std::mutex eth::theNVmanager::Impl::mtx {};
319 
320 
321 //bool eth::theNVmanager::Impl::initialise(const Config &_config)
322 //{
323 // config = _config;
324 // data.pp1 = 1;
325 // return true;
326 //}
327 
329 {
330  return t->getResource()->getProperties();
331 }
332 
333 string eth::theNVmanager::Impl::getid32string(eOprotID32_t id32)
334 {
335  char nvinfo[128];
336  eoprot_ID2information(id32, nvinfo, sizeof(nvinfo));
337  return nvinfo;
338 }
339 
340 bool eth::theNVmanager::Impl::supported(const eOprotIP_t ipv4)
341 {
342  eth::HostTransceiver *t = transceiver(ipv4);
343 
344  return (nullptr == t) ? false : true;
345 }
346 
347 bool 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 
359 size_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 
447 bool 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 
471 bool 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 
498 bool 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 
524 bool 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 
589 bool 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 
620 bool 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 
670 bool 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 
690 bool 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 
729 bool 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 
755 bool 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 
910 bool 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 
995 bool 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 
1014 bool 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 
1024 bool 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 
1104 eth::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 
1141 bool eth::theNVmanager::supported(const eOprotIP_t ipv4)
1142 {
1143  return pImpl->supported(ipv4);
1144 }
1145 
1146 bool eth::theNVmanager::supported(const eOprotIP_t ipv4, const eOprotID32_t id32)
1147 {
1148  return pImpl->supported(ipv4, id32);
1149 }
1150 
1151 size_t eth::theNVmanager::sizeOfNV(const eOprotID32_t id32)
1152 {
1153  return pImpl->sizeofnv(id32);
1154 }
1155 
1156 bool 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 
1162 bool 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 
1168 bool 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 
1175 bool 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 
1181 bool 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 
1186 bool eth::theNVmanager::set(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value)
1187 {
1188  return pImpl->set(t, id32, value);
1189 }
1190 
1191 bool 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 
1198 bool 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 
1203 bool 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 
1210 bool 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 
1216 bool 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 
1221 bool 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 
1236 bool 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 const Properties & getProperties()=0
virtual HostTransceiver * getTransceiver()=0
eth::AbstractEthResource * getEthResource(eOipv4addr_t ipv4)
Definition: ethManager.cpp:708
static TheEthManager * instance()
Definition: ethManager.cpp:159
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
FirmwareUpdaterCore * self
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
bool read(yarp::os::Searchable &cfgtotal, pc104Data &pc104data)
Definition: ethParser.cpp:92
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)
std::condition_variable cv_semaphore
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)
bool check(eth::HostTransceiver *t, const eOprotID32_t id32, const void *value, const double timeout, const unsigned int retries)
eth::AbstractEthResource * ethresource(const eOprotIP_t ipv4)
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 * ethresourceID32s(const eOprotIP_t ipv4, const std::vector< eOprotID32_t > &id32s)
bool onarrival(const ropCode ropcode, const eOprotIP_t ipv4, const eOprotID32_t id32, const std::uint32_t signature)
eth::AbstractEthResource * ethresourceID32(const eOprotIP_t ipv4, const eOprotID32_t id32)
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)
eth::HostTransceiver * transceiver(eth::AbstractEthResource *res)
bool validparameters(eth::HostTransceiver *t, const eOprotID32_t id32, void *value)