MADARA  3.1.8
Utility.cpp
Go to the documentation of this file.
1 #include <ctype.h>
2 #include <cmath>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <iostream>
6 #include <sstream>
7 #include <fstream>
8 
10 #include "madara/utility/Utility.h"
11 #include "ace/INET_Addr.h"
12 
13 #include "ace/Default_Constants.h"
14 #include "ace/Mem_Map.h"
15 #include "ace/OS_NS_fcntl.h"
16 #include "ace/OS_NS_unistd.h"
17 #include "ace/OS_NS_sys_socket.h"
18 #include "ace/OS_NS_Thread.h"
19 #include "ace/OS_NS_sys_time.h"
20 #include "ace/High_Res_Timer.h"
21 
23 
26 {
27 #include "madara/Version.h"
28 
29  return version + std::string (" compiled on ") +
30  __DATE__ + " at " + __TIME__;
31 }
32 
33 
34 uint32_t
36 {
37  std::string str_version = get_version ();
38  unsigned char version_buffer[4] = {0,0,0,0};
39  uint32_t * return_value = (uint32_t *) version_buffer;
40  unsigned int major, minor, revision;
41  char version_delimiter;
42 
43  std::stringstream buffer;
44 
45  // copy the stringified version
46  buffer << str_version;
47 
48  // major version
49  buffer >> major;
50 
51  buffer >> version_delimiter;
52 
53  // minor version
54  buffer >> minor;
55 
56  buffer >> version_delimiter;
57 
58  // revision number
59  buffer >> revision;
60 
61  // copy these into the version_buffer
62 
63  version_buffer[1] = (unsigned char)major;
64  version_buffer[2] = (unsigned char)minor;
65  version_buffer[3] = (unsigned char)revision;
66 
67  return *return_value;
68 }
69 
72 {
73  std::stringstream new_version;
74  unsigned char * version_ptr = (unsigned char *)&version;
75  unsigned int major, minor, revision;
76 
77  major = (unsigned int)version_ptr[1];
78  minor = (unsigned int)version_ptr[2];
79  revision = (unsigned int)version_ptr[3];
80 
81  new_version << major;
82  new_version << '.';
83  new_version << minor;
84  new_version << '.';
85  new_version << revision;
86 
87  return new_version.str ();
88 }
89 
93 const std::string & input, const std::string & prefix)
94 {
95  return input.substr (prefix.size ());
96 }
97 
98 
100 std::string &
102 {
103  for (std::string::iterator cur = input.begin ();
104  cur != input.end (); ++cur)
105  *cur = toupper (*cur);
106 
107  return input;
108 }
109 
111 std::string &
113 {
114  for (std::string::iterator cur = input.begin ();
115  cur != input.end (); ++cur)
116  {
117  // change periods to _
118  if (*cur == '.')
119  *cur = '_';
120  }
121 
122  return input;
123 }
124 
126 std::string &
128 {
129  for (std::string::iterator cur = input.begin ();
130  cur != input.end (); ++cur)
131  *cur = tolower (*cur);
132 
133  return input;
134 }
135 
138 std::string &
140 {
141  std::string::iterator cur = input.begin ();
142  char prev = 0;
143 
144  for (std::string::iterator eval = cur;
145  eval != input.end (); ++eval)
146  {
147  // if it isn't whitespace, then copy it over immediately
148  if (*eval != ' ' && *eval != '\t' && *eval != '\n' && *eval != '\r')
149  {
150  prev = *cur = *eval;
151  ++cur;
152  }
153  // if it is whitespace, only insert whitespace if the previous char
154  // was non-whitespace
155  else if (prev)
156  {
157  *cur = ' ';
158  prev = 0;
159  ++cur;
160  }
161  }
162 
163  // if the last char is actually whitespace, then move cur back one spot
164  if (cur != input.end ())
165  {
166  --cur;
167  if (*cur != ' ' && *cur != '\t' && *cur != '\n' && *cur != '\r')
168  ++cur;
169  }
170 
171  // erase everything from cur to end of input string
172  if (cur != input.end ())
173  input.erase (cur, input.end ());
174 
175  return input;
176 }
177 
178 
180 std::string &
182 {
183  std::string::iterator cur = input.begin ();
184 
185  for (std::string::iterator eval = cur;
186  eval != input.end (); ++eval)
187  {
188  // if it isn't whitespace, then copy it over immediately
189  if (*eval != ' ' && *eval != '\t' && *eval != '\n' && *eval != '\r')
190  {
191  *cur = *eval;
192  ++cur;
193  }
194  }
195 
196  // erase everything from cur to end of input string
197  if (cur != input.end ())
198  input.erase (cur, input.end ());
199 
200  return input;
201 }
202 
203 
208 std::string &
210 {
211  std::string::iterator cur = input.begin ();
212 
213  for (std::string::iterator eval = cur;
214  eval != input.end (); ++eval)
215  {
216  // if it isn't whitespace, then copy it over immediately
217  if (*eval != unwanted)
218  {
219  *cur = *eval;
220  ++cur;
221  }
222  }
223 
224  // erase everything from cur to end of input string
225  if (cur != input.end ())
226  input.erase (cur, input.end ());
227 
228  return input;
229 }
230 
231 size_t
233  const std::string & old_phrase,
234  const std::string & new_phrase,
235  bool replace_all)
236 {
237  // return value
238  size_t replacements = 0;
239 
240  if (old_phrase != "")
241  {
242  for (std::string::size_type i = source.find (old_phrase, 0);
243  i != source.npos; i = source.find (old_phrase, i))
244  {
245  source.replace (i, old_phrase.size (), new_phrase);
246  i += new_phrase.size ();
247 
248  ++replacements;
249 
250  if (!replace_all)
251  break;
252  }
253  }
254 
255  return replacements;
256 }
257 
258 std::string &
260 {
261  std::stringstream source, dest;
262  std::string cur;
263  std::vector <std::string> splitters;
264  splitters.resize (2);
265 
266  splitters[0] = "//";
267 
268  // place the input in the string stream
269  source << input;
270 
271  while (std::getline (source, cur))
272  {
273  std::vector <std::string> tokens;
274  std::vector <std::string> pivots;
275  tokenizer (cur, splitters, tokens, pivots);
276 
277  if (tokens.size ())
278  {
279  dest << tokens[0];
280  dest << "\n";
281  }
282  }
283 
284  input = dest.str ();
285  return input;
286 }
287 
288 
290 void
292  const ::std::vector< std::string> & splitters,
293  ::std::vector< std::string> & tokens,
294  ::std::vector< std::string> & pivots)
295 {
296  std::string::size_type last = 0;
297  std::string::size_type cur = 0;
298  tokens.clear ();
299  pivots.clear ();
300 
301  for (; cur < input.size (); ++cur)
302  {
303  for (std::string::size_type i = 0; i < splitters.size (); ++i)
304  {
305  // if the splitter string length is greater than zero
306  if (splitters[i].size () > 0)
307  {
308  // if the first char of the splitter string is equal to the char
309  if (input[cur] == splitters[i][0])
310  {
311  std::string::size_type checker = cur;
312  std::string::size_type j = 1;
313  for (++checker;
314  checker < input.size () && j < splitters[i].size () &&
315  input[checker] == splitters[i][j];
316  ++j, ++checker);
317 
318  // we have found a splitter. Tokenize from last to splitter.
319  if (j == splitters[i].size ())
320  {
321  // need to update this to only have as many pivots as tokens - 1
322  pivots.push_back (input.substr (cur, j));
323 
324  if (cur - last >= splitters[i].size () - 1)
325  tokens.push_back (input.substr (last, cur - last));
326  else
327  tokens.push_back ("");
328 
329  // we want last to point to the last valid token begin
330  cur = checker - 1;
331  last = checker;
332  } // if found a splitter
333  } // if first char == splitter first char
334  } // if splitter length >= 1
335  } // for splitters
336 
337  } // for chars
338 
339  if (last != cur)
340  {
341  tokens.push_back (input.substr (last, cur - last));
342  }
343 }
344 
345 // split a key into a corresponding host and port
346 int
348  std::string & host, std::string & port)
349 {
350  // delimiter is either a : or an @
351  std::string::size_type delim = key.rfind (':');
352  delim = delim == key.npos ? key.rfind ('@') : delim;
353 
354  // no delimiter found
355  if (delim == key.npos)
356  {
357  host = key;
358  port = "";
359 
360  return 1;
361  }
362 
363  // otherwise, set the host and port appropriately
364  host = key.substr (0, delim);
365  port = key.substr (delim + 1, key.size () - delim);
366 
367  return 0;
368 }
369 
370 // merge a host and port into a key
371 int
373  const std::string & host, const std::string & port)
374 {
375  if ((const std::string *)&key != &host)
376  key = host;
377 
378  key += ':';
379  key += port;
380 
381  return 0;
382 }
383 
384 // merge a host and ushort port into a key
385 int
387  const std::string & host, unsigned short u_port)
388 {
389  std::stringstream port_stream;
390  port_stream << u_port;
391 
392  return merge_hostport_identifier (key, host, port_stream.str ());
393 }
394 
396 int
398  std::string & host, unsigned short & port, bool increase_until_bound)
399 {
400  // start with the initial port provided
401  // increase port each time we don't properly bind
402 
404  "utility::bind_to_ephemeral_port:" \
405  " creating ACE_INET_Addr\n");
406 
407  ACE_INET_Addr addr (port);
408  char hostname[HOST_NAME_MAX + 1] = "";
409 
411  "utility::bind_to_ephemeral_port:" \
412  " getting hostname from ACE_INET_Addr\n");
413 
414  addr.get_host_name (hostname, HOST_NAME_MAX);
415  host = hostname;
416 
418  "utility::bind_to_ephemeral_port:" \
419  " hostname equals %s\n", hostname);
420 
422  "utility::bind_to_ephemeral_port:" \
423  " calling ACE_OS::socket_init\n");
424 
425  ACE_OS::socket_init (2, 2);
426 
427  for ( ; port < 65535; ++port, addr.set (port))
428  {
429 
431  "utility::bind_to_ephemeral_port:" \
432  " attempting open on socket %d\n", port);
433 
434  if (socket.open (addr, 2, 0, 0) != -1)
435  return 0;
436 
437  // failed to get port
438  if (!increase_until_bound)
439  break;
440  }
441 
443  "utility::bind_to_ephemeral_port:" \
444  " unable to bind to any ephemeral port. Check firewall\n");
445 
446  return -1;
447 }
448 
451 {
452  std::string line;
453  std::stringstream buffer;
454 
455  std::ifstream file (filename.c_str ());
456 
457  // if the file was able to open
458  if (file.is_open ())
459  {
460  std::getline (file, line);
461 
462  if (line != "")
463  buffer << line;
464 
465  // while there is still a line left in the file, read that line
466  // into our stringstream buffer
467  while (std::getline (file, line))
468  buffer << "\n" << line;
469  file.close ();
470  }
471  else
472  {
474  "utility::file_to_string:" \
475  " failed to open file: %s\n", filename.c_str());
476  }
477 
478  return buffer.str ();
479 }
480 
481 
484 {
485  std::string::size_type start = 0;
486  for (std::string::size_type i = 0; i < name.size (); ++i)
487  {
488  // check for directory delimiters and update start
489  if (name[i] == '/' || name[i] == '\\')
490  {
491  // if they have supplied a directory with an
492  // ending slash, then use the previous start
493  if (i != name.size () - 1)
494  start = i + 1;
495  }
496  }
497 
498  // return the substring from 0 with start number of elements
499  return name.substr (0, start);
500 }
501 
504 {
505  std::string::size_type start = 0;
506  for (std::string::size_type i = 0; i < name.size (); ++i)
507  {
508  // check for directory delimiters and update start
509  if (name[i] == '/' || name[i] == '\\')
510  {
511  // if they have supplied a directory with an
512  // ending slash, then use the previous start
513  if (i != name.size () - 1)
514  start = i + 1;
515  }
516  }
517 
518  // return the substring from start to the end of the filename
519  return name.substr (start, name.size () - start);
520 }
521 
525 {
526  std::stringstream buffer;
527 
528  for (size_t i = 0; i < source.size (); ++i)
529  {
530  // environment variable must be larger than $()
531  if (source[i] == '$' && i + 3 < source.size ())
532  {
533  char * value = get_var (source, i+2, i);
534  if (value)
535  buffer << value;
536  }
537  else
538  buffer << source[i];
539  }
540  return buffer.str ();
541 }
542 
544 char *
546  size_t cur, size_t & end)
547 {
548  for (end = cur; end < source.size (); ++end)
549  {
550  if (source[end] == ')' || source[end] == '}')
551  {
552  return getenv (source.substr (cur, end - cur).c_str ());
553  }
554  }
555 
556  return getenv (source.substr (cur,source.size () - cur).c_str ());
557 }
558 
561 {
562  // define the characters we'll want to replace
563 #ifdef ACE_WIN32
564  #define REPLACE_THIS '/'
565  #define REPLACE_WITH '\\'
566 #else
567  #define REPLACE_THIS '\\'
568  #define REPLACE_WITH '/'
569 #endif
570 
571  std::string target (source);
572 
573  for (std::string::iterator i = target.begin (); i != target.end(); ++i)
574  {
575  if (*i == REPLACE_THIS)
576  *i = REPLACE_WITH;
577  }
578 
579  return target;
580 }
581 
582 
587 {
588 public:
593  {
594  x.us = 1;
595 
596  if (x.c[sizeof (unsigned short) - 1] == 1)
597  is_little = false;
598  else
599  is_little = true;
600  }
601 
605  bool is_little;
606 
607 private:
609  union {
611  unsigned short us;
612 
614  unsigned char c[sizeof (unsigned short)];
615  } x;
616 };
617 
620 
624 uint64_t
626 {
627  // if host is little endian, then we have work to do
628  if (::endianness.is_little)
629  {
630  value = ((value << 8) & 0xFF00FF00FF00FF00ULL )
631  | ((value >> 8) & 0x00FF00FF00FF00FFULL );
632  value = ((value << 16) & 0xFFFF0000FFFF0000ULL )
633  | ((value >> 16) & 0x0000FFFF0000FFFFULL );
634  return (value << 32) | (value >> 32);
635  }
636 
637  return value;
638 }
639 
643 int64_t
645 {
646  // if host is little endian, then we have work to do
647  if (::endianness.is_little)
648  {
649  value = ((value << 8) & 0xFF00FF00FF00FF00ULL )
650  | ((value >> 8) & 0x00FF00FF00FF00FFULL );
651  value = ((value << 16) & 0xFFFF0000FFFF0000ULL )
652  | ((value >> 16) & 0x0000FFFF0000FFFFULL );
653  return (value << 32) | ((value >> 32) & 0xFFFFFFFFULL);
654  }
655 
656  return value;
657 }
658 
659 
663 uint32_t
665 {
666  // if host is little endian, then we have work to do
667  if (::endianness.is_little)
668  {
669  value = ((value << 8) & 0xFF00FF00 ) |
670  ((value >> 8) & 0xFF00FF );
671  return (value << 16) | (value >> 16);
672  }
673 
674  return value;
675 }
676 
680 int32_t
682 {
683  // if host is little endian, then we have work to do
684  if (::endianness.is_little)
685  {
686  value = ((value << 8) & 0xFF00FF00) |
687  ((value >> 8) & 0xFF00FF );
688  return (value << 16) | ((value >> 16) & 0xFFFF);
689  }
690 
691  return value;
692 }
693 
697 uint16_t
699 {
700  // if host is little endian, then we have work to do
701  if (::endianness.is_little)
702  {
703  return ((value << 8) & 0xFFFF) | (value >> 8);
704  }
705 
706  return value;
707 }
708 
712 int16_t
714 {
715  // if host is little endian, then we have work to do
716  if (::endianness.is_little)
717  {
718  return ((value << 8) & 0xFFFF) | (value >> 8);
719  }
720 
721  return value;
722 }
723 
727 double
729 {
730  // if host is little endian, then we have work to do
731  if (::endianness.is_little)
732  {
733  uint64_t value;
734  memcpy(&value, &orig, sizeof(value));
735 
736  value = endian_swap(value);
737 
738  double result;
739  memcpy (&result, &value, sizeof(result));
740  return result;
741  }
742 
743  return orig;
744 }
745 
746 int
748  void *& buffer, size_t & size, bool add_zero_char)
749 {
750  int ret_value = 0;
751  if (filename != "")
752  {
753  // load the source file into a mapped file of the OS's
754  // virtual memory system
755  ACE_Mem_Map mapped_file;
756  void * temp_buffer;
757  ret_value = mapped_file.map (filename.c_str ());
758  temp_buffer = mapped_file.addr ();
759  size = mapped_file.size ();
760 
761  if (add_zero_char)
762  ++size;
763 
764  buffer = new unsigned char [size];
765  memcpy (buffer, temp_buffer, size);
766 
767  if (add_zero_char)
768  {
769  unsigned char * zeroed = (unsigned char *)buffer;
770  zeroed[size - 1] = 0;
771  }
772  }
773  else ret_value = -1;
774 
775  return ret_value;
776 }
777 
778 ssize_t
780  void * buffer, size_t size)
781 {
782  // error is -1
783  ssize_t actual = -1;
784 
785  // using ACE for writing to the destination file
786  ACE_HANDLE file_handle = ACE_OS::open (filename.c_str (),
787  O_RDWR | O_CREAT | O_TRUNC,
788  ACE_DEFAULT_FILE_PERMS);
789 
791  "Files::write_file : beginning write of %" PRIu64 " bytes\n", size);
792 
793  if (file_handle != ACE_INVALID_HANDLE)
794  {
795  // write to the file, save actual bytes read, and close the file handle
796  actual = ACE_OS::write (file_handle, buffer, size);
797  ACE_OS::close (file_handle);
798  }
799 
800  // return the actual bytes written. -1 if error
801  return actual;
802 }
803 
804 int64_t
806 {
807  ACE_Time_Value tv = ACE_High_Res_Timer::gettimeofday ();
808  int64_t timeofday (tv.sec () * 1000000000);
809  timeofday += tv.usec () * 1000;
810 
811  return timeofday;
812 }
813 
814 double
815 madara::utility::rand_double (double floor, double ceiling,
816  bool set_seed_to_time)
817 {
818  // check if the user has specified setting through srand
819  if (set_seed_to_time)
820  {
821  unsigned int new_seed (get_time ());
822  srand (new_seed);
823  }
824 
825  // Get a double number between 0 and 1.
826  double position_in_range = ((double)rand()) / ((double)RAND_MAX);
827 
828  if (floor < ceiling)
829  return (position_in_range * (ceiling - floor)) + floor;
830  else
831  return (position_in_range * (floor - ceiling)) + ceiling;
832 }
833 
834 int64_t
835 madara::utility::rand_int (int64_t floor, int64_t ceiling,
836  bool set_seed_to_time)
837 {
838  double random = rand_double (floor, ceiling, set_seed_to_time);
839  return nearest_int (random);
840 }
841 
842 int64_t
844 {
845  int change = input >= 0 ? 1 : -1;
846  int64_t left = input;
847  int64_t right = input + change;
848 
849  if (input - left < -input + right)
850  return left;
851  else
852  return right;
853 }
854 
855 
856 double madara::utility::sleep (double sleep_time)
857 {
858  ACE_Time_Value current = ACE_High_Res_Timer::gettimeofday ();
859  ACE_Time_Value actual_time;
860  actual_time.set (sleep_time);
861 
862  sleep (actual_time);
863 
864  ACE_Time_Value end = ACE_High_Res_Timer::gettimeofday ();
865  end = end - current;
866  double time_taken = (double) end.sec ();
867  time_taken += (double) end.usec () / 1000000;
868 
869  return time_taken;
870 }
871 
872 
873 ACE_Time_Value madara::utility::sleep (const ACE_Time_Value & sleep_time)
874 {
875  ACE_Time_Value current = ACE_High_Res_Timer::gettimeofday ();
876  ACE_Time_Value earliest = current + sleep_time;
877 
878  while (current < earliest)
879  {
880  ACE_OS::sleep (earliest - current);
881  current = ACE_High_Res_Timer::gettimeofday ();
882  }
883 
884  return ACE_High_Res_Timer::gettimeofday () - current;
885 }
886 
888  double value1, double value2, double epsilon)
889 {
890  return std::abs (value1 - value2) < epsilon;
891 }
892 
893 bool
895 {
896  if (FILE * file = fopen (filename.c_str(), "r"))
897  {
898  fclose(file);
899  return true;
900  }
901  else
902  {
903  return false;
904  }
905 }
906 
907 unsigned int
909 {
910  unsigned int size = 0;
911  if (FILE * file = fopen (filename.c_str(), "r"))
912  {
913  fseek (file, 0L, SEEK_END);
914  size = ftell (file);
915  fclose (file);
916  }
917 
918  return size;
919 }
920 
921 bool
924  const std::string & variable,
925  const knowledge::WaitSettings & settings)
926 {
927  // get current time of day
928  ACE_Time_Value current = ACE_High_Res_Timer::gettimeofday ();
929  ACE_Time_Value max_wait, sleep_time, next_epoch;
930  ACE_Time_Value poll_frequency, last = current;
931 
932  knowledge::VariableReference ref = knowledge.get_ref (variable);
933 
934  if (settings.poll_frequency >= 0)
935  {
936  max_wait.set (settings.max_wait_time);
937  max_wait = current + max_wait;
938 
939  poll_frequency.set (settings.poll_frequency);
940  next_epoch = current + poll_frequency;
941  }
942 
943  // print the post statement at highest log level (cannot be masked)
944  if (settings.pre_print_statement != "")
945  knowledge.print (settings.pre_print_statement, logger::LOG_ALWAYS);
946 
947  madara::knowledge::KnowledgeRecord last_value = knowledge.get (ref, settings);
948 
950  "utility::wait_true:" \
951  " variable returned %s\n",
952  last_value.to_string ().c_str ());
953 
954  current = ACE_High_Res_Timer::gettimeofday ();
955 
956  // wait for expression to be true
957  while (!last_value.to_integer () &&
958  (settings.max_wait_time < 0 || current < max_wait))
959  {
961  "utility::wait_true:" \
962  " current is %" PRIu64 ".%" PRIu64 " and max is %" PRIu64 ".%" PRIu64 " (poll freq is %f)\n",
963  current.sec (), current.usec (), max_wait.sec (), max_wait.usec (),
964  settings.poll_frequency);
965 
967  "utility::wait_true:" \
968  " last value didn't result in success\n");
969 
970  // Unlike the other wait statements, we allow for a time based wait.
971  // To do this, we allow a user to specify a
972  if (settings.poll_frequency > 0)
973  {
974  if (current < next_epoch)
975  {
976  sleep_time = next_epoch - current;
977  madara::utility::sleep (sleep_time);
978  }
979 
980  next_epoch = next_epoch + poll_frequency;
981  }
982  else
983  knowledge.wait_for_change ();
984 
986  "utility::wait_true:" \
987  " waiting on %s\n", variable.c_str ());
988 
989  last_value = knowledge.get (ref, settings);
990 
992  "utility::wait_true:" \
993  " completed eval to get %s\n",
994  last_value.to_string ().c_str ());
995 
996  // get current time
997  current = ACE_High_Res_Timer::gettimeofday ();
998 
999  } // end while (!last)
1000 
1001  if (current >= max_wait)
1002  {
1004  "utility::wait_true:" \
1005  " Evaluate did not succeed. Timeout occurred\n",
1006  last_value.to_string ().c_str ());
1007  }
1008 
1009  // print the post statement at highest log level (cannot be masked)
1010  if (settings.post_print_statement != "")
1011  knowledge.print (settings.post_print_statement, logger::LOG_ALWAYS);
1012 
1013  return last_value.is_true ();
1014 }
1015 
1018  const std::string & variable,
1019  const knowledge::WaitSettings & settings)
1020 {
1021  // get current time of day
1022  ACE_Time_Value current = ACE_High_Res_Timer::gettimeofday ();
1023  ACE_Time_Value max_wait, sleep_time, next_epoch;
1024  ACE_Time_Value poll_frequency, last = current;
1025 
1026  knowledge::VariableReference ref = knowledge.get_ref (variable);
1027 
1028  if (settings.poll_frequency >= 0)
1029  {
1030  max_wait.set (settings.max_wait_time);
1031  max_wait = current + max_wait;
1032 
1033  poll_frequency.set (settings.poll_frequency);
1034  next_epoch = current + poll_frequency;
1035  }
1036 
1037  // print the post statement at highest log level (cannot be masked)
1038  if (settings.pre_print_statement != "")
1039  knowledge.print (settings.pre_print_statement, logger::LOG_ALWAYS);
1040 
1041  knowledge::KnowledgeRecord last_value (!knowledge.get (ref, settings));
1042 
1044  "utility::wait_false:" \
1045  " variable returned %s\n",
1046  last_value.to_string ().c_str ());
1047 
1048  current = ACE_High_Res_Timer::gettimeofday ();
1049 
1050  // wait for expression to be true
1051  while (!last_value.to_integer () &&
1052  (settings.max_wait_time < 0 || current < max_wait))
1053  {
1055  "utility::wait_false:" \
1056  " current is %d.%d and max is %d.%d (poll freq is %f)\n",
1057  current.sec (), current.usec (), max_wait.sec (), max_wait.usec (),
1058  settings.poll_frequency);
1059 
1061  "utility::wait_false:"
1062  " last value didn't result in success\n");
1063 
1064  // Unlike the other wait statements, we allow for a time based wait.
1065  // To do this, we allow a user to specify a
1066  if (settings.poll_frequency > 0)
1067  {
1068  if (current < next_epoch)
1069  {
1070  sleep_time = next_epoch - current;
1071  madara::utility::sleep (sleep_time);
1072  }
1073 
1074  next_epoch = next_epoch + poll_frequency;
1075  }
1076  else
1077  knowledge.wait_for_change ();
1078 
1080  "utility::wait_false:"
1081  " waiting on %s\n", variable.c_str ());
1082 
1083  last_value = knowledge::KnowledgeRecord (!knowledge.get (ref, settings));
1084 
1086  "utility::wait_false:"
1087  " completed eval to get %s\n",
1088  last_value.to_string ().c_str ());
1089 
1090  // get current time
1091  current = ACE_High_Res_Timer::gettimeofday ();
1092 
1093  } // end while (!last)
1094 
1095  if (current >= max_wait)
1096  {
1098  "utility::wait_false:"
1099  " Evaluate did not succeed. Timeout occurred\n",
1100  last_value.to_string ().c_str ());
1101  }
1102 
1103  // print the post statement at highest log level (cannot be masked)
1104  if (settings.post_print_statement != "")
1105  knowledge.print (settings.post_print_statement, logger::LOG_EMERGENCY);
1106 
1107  return last_value.is_true ();
1108 }
This class encapsulates an entry in a KnowledgeBase.
bool is_true(void) const
Checks to see if the record is true.
double max_wait_time
Maximum time to wait for an expression to become true (in seconds)
Definition: WaitSettings.h:113
MADARA_Export int64_t rand_int(int64_t floor=0, int64_t ceiling=RAND_MAX, bool set_seed_to_time=true)
Returns a random integer between a floor and ceiling.
Definition: Utility.cpp:835
MADARA_Export bool wait_false(knowledge::KnowledgeBase &knowledge, const std::string &variable, const knowledge::WaitSettings &settings=knowledge::WaitSettings())
Waits on a knowledge record to be false without needing KaRL language.
Definition: Utility.cpp:1016
MADARA_Export int bind_to_ephemeral_port(ACE_SOCK_Dgram &socket, std::string &host, unsigned short &port, bool increase_until_bound=true)
Binds to an ephemeral port.
Definition: Utility.cpp:397
madara::knowledge::KnowledgeRecord KnowledgeRecord
MADARA_Export std::string get_version(void)
Gets the MADARA version number.
Definition: Utility.cpp:25
MADARA_Export int read_file(const std::string &filename, void *&buffer, size_t &size, bool add_zero_char=false)
Reads a file into a provided void pointer.
Definition: Utility.cpp:747
MADARA_Export int64_t get_time(void)
Returns a time of day in nanoseconds.
Definition: Utility.cpp:805
std::string pre_print_statement
Statement to print before evaluations.
Definition: EvalSettings.h:119
unsigned short us
unsigned short value
Definition: Utility.cpp:611
MADARA_Export std::string strip_prefix(const std::string &input, const std::string &prefix)
Strips a prefix from an input string and returns the result.
Definition: Utility.cpp:92
MADARA_Export unsigned int file_size(const std::string &filename)
Returns the size of a file.
Definition: Utility.cpp:908
MADARA_Export bool wait_true(knowledge::KnowledgeBase &knowledge, const std::string &variable, const knowledge::WaitSettings &settings=knowledge::WaitSettings())
Waits on a knowledge record to be true without needing KaRL language.
Definition: Utility.cpp:922
unsigned char c[sizeof(unsigned short)]
unsigned char array value
Definition: Utility.cpp:614
MADARA_Export std::string & lower(std::string &input)
Converts the string to lower.
Definition: Utility.cpp:127
MADARA_Export utility::Refcounter< logger::Logger > global_logger
MADARA_Export uint32_t get_uint_version(void)
Gets the MADARA version number.
Definition: Utility.cpp:35
MADARA_Export int split_hostport_identifier(const std::string &key, std::string &host, std::string &port)
Splits a key of host:port into a corresponding host and port.
Definition: Utility.cpp:347
MADARA_Export double sleep(double sleep_time)
Sleeps for a certain amount of time.
Definition: Utility.cpp:856
Optimized reference to a variable within the knowledge base.
MADARA_Export int64_t nearest_int(double input)
Rounds a double to the nearest integer.
Definition: Utility.cpp:843
madara::knowledge::KnowledgeRecord get(const std::string &key, const KnowledgeReferenceSettings &settings=KnowledgeReferenceSettings(false))
Retrieves a knowledge value.
std::string post_print_statement
Statement to print after evaluations.
Definition: EvalSettings.h:124
MADARA_Export std::string & upper(std::string &input)
Converts the string to upper.
Definition: Utility.cpp:101
MADARA_Export std::string extract_path(const std::string &name)
Extracts the path of a filename.
Definition: Utility.cpp:483
bool is_little
indicates whether this is little endian (modified by constructor)
Definition: Utility.cpp:605
MADARA_Export double rand_double(double floor=0.0, double ceiling=1.0, bool set_seed_to_time=true)
Returns a random double between floor and ceiling.
Definition: Utility.cpp:815
MADARA_Export uint64_t endian_swap(uint64_t value)
Converts a host format uint64_t into big endian.
Definition: Utility.cpp:625
INTERNAL USE: Checks for and converting to network long (htonl)
Definition: Utility.cpp:586
MADARA_Export ssize_t write_file(const std::string &filename, void *buffer, size_t size)
Writes a file with provided contents.
Definition: Utility.cpp:779
EndiannessChecker()
Constructor.
Definition: Utility.cpp:592
#define madara_logger_ptr_log(logger, level,...)
Fast version of the madara::logger::log method for Logger pointers.
Definition: Logger.h:32
This class provides a distributed knowledge base to users.
Definition: KnowledgeBase.h:44
MADARA_Export std::string & dds_topicify(std::string &input)
Changes periods to underscores in compliance with OpenSplice needs.
Definition: Utility.cpp:112
double poll_frequency
Frequency to poll an expression for truth (in seconds)
Definition: WaitSettings.h:108
MADARA_Export std::string & strip_white_space(std::string &input)
Strips all whitespace characters from a string.
Definition: Utility.cpp:181
Integer to_integer(void) const
converts the value to an integer
static constexpr struct madara::knowledge::tags::string_t string
MADARA_Export int merge_hostport_identifier(std::string &key, const std::string &host, const std::string &port)
Merges a host and port into a host:port key.
Definition: Utility.cpp:372
MADARA_Export std::string & strip_extra_white_space(std::string &input)
Strips whitespace from front and end of string and also condenses multiple whitespace into a single s...
Definition: Utility.cpp:139
#define REPLACE_WITH
MADARA_Export std::string to_string_version(uint32_t version)
Converts a MADARA uint32_t version number to human-readable.
Definition: Utility.cpp:71
MADARA_Export std::string & string_remove(std::string &input, char unwanted)
Strips an unwanted character.
Definition: Utility.cpp:209
EndiannessChecker endianness
checks for endianness of architecture on library load
Definition: Utility.cpp:619
MADARA_Export std::string expand_envs(const std::string &source)
Expands environment variables referenced in the string.
Definition: Utility.cpp:524
Provides functions and classes for the distributed knowledge base.
MADARA_Export std::string file_to_string(const std::string &filename)
Reads a file into a string.
Definition: Utility.cpp:450
MADARA_Export bool file_exists(const std::string &filename)
Checks if a file exists.
Definition: Utility.cpp:894
#define REPLACE_THIS
MADARA_Export size_t string_replace(std::string &source, const std::string &old_phrase, const std::string &new_phrase, bool replace_all=true)
Replaces an old phrase with a new phrase within a string.
Definition: Utility.cpp:232
MADARA_Export std::string extract_filename(const std::string &name)
Extracts the file name of an absolute or relative path.
Definition: Utility.cpp:503
Encapsulates settings for a wait statement.
Definition: WaitSettings.h:23
MADARA_Export void tokenizer(const std::string &input, const ::std::vector< std::string > &splitters,::std::vector< std::string > &tokens,::std::vector< std::string > &pivot_list)
Splits an input string into tokens.
Definition: Utility.cpp:291
union EndiannessChecker::@18 x
by using a union, we can reference the bytes of the short
std::string to_string(const std::string &delimiter=", ") const
converts the value to a string.
MADARA_Export bool approx_equal(double value1, double value2, double epsilon=0.0001)
Checks two doubles for approximate equality.
Definition: Utility.cpp:887
char * get_var(const std::string &source, size_t cur, size_t &end)
Helper function for madara::utility::expand_envs which retrieves an environment variable.
Definition: Utility.cpp:545
VariableReference get_ref(const std::string &key, const KnowledgeReferenceSettings &settings=KnowledgeReferenceSettings(false))
Atomically returns a reference to the variable.
void print(unsigned int level=0) const
Prints all knowledge variables and values in the context.
MADARA_Export std::string & strip_comments(std::string &input)
Strips all comments (single-line and multi-line).
Definition: Utility.cpp:259
void wait_for_change(void)
Wait for a change to happen to the context (e.g., from transports)
MADARA_Export std::string clean_dir_name(const std::string &target)
Substitutes the appropriate directory delimiter, which may help with portability between operating sy...
Definition: Utility.cpp:560