ICP  1
icputils.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 #include "DAEstatus.h"
3 #include "icputils.h"
4 
5 Poco::SingletonHolder<ICPClock> g_icp_clock;
6 
8 std::string convertLatin1ToUTF8(const std::string& latin_string)
9 {
10  Poco::Latin1Encoding latin1;
11  Poco::UTF8Encoding utf8;
12  Poco::TextConverter text_converter(latin1, utf8);
13  std::string utf8_string;
14  text_converter.convert(latin_string, utf8_string);
15  return utf8_string;
16 }
17 
18 std::string convertWindows1252ToUTF8(const std::string& win_string)
19 {
20  Poco::Windows1252Encoding win1252;
21  Poco::UTF8Encoding utf8;
22  Poco::TextConverter text_converter(win1252, utf8);
23  std::string utf8_string;
24  text_converter.convert(win_string, utf8_string);
25  return utf8_string;
26 }
27 
28 
29 ICPTimer::ICPTimer() : m_status(NULL)
30 {
31  start();
32 }
33 
34 ICPTimer::ICPTimer(const char* title, DAEstatus& status) : m_status(&status)
35 {
36  start(title);
37 }
38 
40 {
41  if (m_status != NULL)
42  {
43  info(m_title.c_str(), *m_status);
44  }
45 }
46 
47 void ICPTimer::start(const char* title)
48 {
49  if (title != NULL)
50  {
51  m_title = title;
52  }
53  m_ts.fromEpochTime(time(NULL));
54  GetSystemTime(&m_st);
55  ftime(&m_tb);
56  if (GetThreadTimes(GetCurrentThread(), &m_thread_times.create, &m_thread_times.exit, &m_thread_times.kernel, &m_thread_times.user) == 0)
57  {
58  memset(&m_thread_times, 0, sizeof(m_thread_times));
59  }
60  if (GetProcessTimes(GetCurrentProcess(), &m_process_times.create, &m_process_times.exit, &m_process_times.kernel, &m_process_times.user) == 0)
61  {
62  memset(&m_process_times, 0, sizeof(m_process_times));
63  }
64 }
65 
66 // labview by default only unescapes &lt; &gt; and &amp; so we need to do any others ourselves
67 
68 static const char* escape_sequence[] = { "&quot;", "&apos;" };
69 static const int escape_length[] = { 6, 6 }; // lengths of above
70 static const char* escape_replace[] = { "\"", "\'" };
71 
72 std::string unescapeXML(const char* xml_str)
73 {
74  std::string s;
75  size_t n = strlen(xml_str);
76  s.reserve(n);
77  int j;
78  size_t i = 0;
79  bool done_escape;
80  while(i<n)
81  {
82  if (xml_str[i] == '&')
83  {
84  done_escape = false;
85  for(j=0; !done_escape && (j < sizeof(escape_sequence) / sizeof(const char*)); j++)
86  {
87  if (strncmp(xml_str+i, escape_sequence[j], escape_length[j]) == 0)
88  {
89  s.push_back(*(escape_replace[j]));
90  i += escape_length[j];
91  done_escape = true;
92  }
93  }
94  // maybe &#nnn; sequence
95  if ( !done_escape && (xml_str[i+1] == '#') )
96  {
97  sscanf(xml_str+i, "&#%d;", &j);
98  s.push_back((char)j);
99  i = i + 4 + (j > 9 ? 1 : 0) + (j > 99 ? 1 : 0);
100  done_escape = true;
101  }
102  // unrecognised escape sequence - could be &amp; (OK) or one we don't yet know to handle (not OK)
103  if ( !done_escape )
104  {
105  s.push_back(xml_str[i]);
106  ++i;
107  }
108  }
109  else
110  {
111  s.push_back(xml_str[i]);
112  ++i;
113  }
114  }
115  return s;
116 }
117 
118 std::string escapeXML(const char* xml_str)
119 {
120  char buffer[10];
121  std::string s;
122  size_t n = strlen(xml_str);
123  s.reserve(n+10);
124  while (*xml_str)
125  {
126  if (*xml_str == '&')
127  s.append("&amp;");
128  else if (*xml_str == '<')
129  s.append("&lt;");
130  else if (*xml_str == '>')
131  s.append("&gt;");
132  else if (*xml_str == '\"')
133  s.append("&quot;");
134  else if (*xml_str == '\'')
135  s.append("&apos;");
136  else if (*xml_str & 128)
137  {
138  /*
139  * Convert UTF-8 to Unicode constant...
140  */
141  int ch; /* Unicode character */
142  ch = *xml_str & 255;
143  if ((ch & 0xe0) == 0xc0)
144  {
145  ch = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
146  xml_str++;
147  }
148  else if ((ch & 0xf0) == 0xe0)
149  {
150  ch = ((((ch * 0x0f) << 6) | (s[1] & 0x3f)) << 6) | (s[2] & 0x3f);
151  xml_str += 2;
152  }
153 
154  if (ch == 0xa0)
155  {
156  /*
157  * Handle non-breaking space as-is...
158  */
159  s.append("&nbsp;");
160  }
161  else
162  {
163  sprintf(buffer, "&#x%x;", ch);
164  s.append(buffer);
165  }
166  }
167  else
168  {
169  s.push_back(*xml_str);
170  }
171  xml_str++;
172  }
173  return s;
174 }
175 
176 
177 double ICPTimer::info(const char* title, std::ostream& os, bool add_nl)
178 {
179  ICPTimer tim_end;
180  double tdiff1ms = ( (tim_end.m_tb.millitm - m_tb.millitm) +
181  1000.0 * difftime(tim_end.m_tb.time, m_tb.time) );
182  double tdiff1 = tdiff1ms / 1000.0;
183 // tdiff2 does not allow for a day change
184  double tdiff2 = 3600.0 * (double)(tim_end.m_st.wHour - m_st.wHour) +
185  60.0 * (double)(tim_end.m_st.wMinute - m_st.wMinute) +
186  (double)(tim_end.m_st.wSecond - m_st.wSecond) +
187  (double)(tim_end.m_st.wMilliseconds - m_st.wMilliseconds) / 1000.0;
188  double tdiff3 = m_ts.elapsed() / 1.0e6;
189  os << "*** Timing information for " << title << ": real(" << tdiff3 <<
190  ") thread(kernel=" << diffFileTimesInMilliSec(m_thread_times.kernel, tim_end.m_thread_times.kernel) / 1.0e3 <<
191  ", user=" << diffFileTimesInMilliSec(m_thread_times.user, tim_end.m_thread_times.user) / 1.0e3 <<
192  ") process(kernel=" << diffFileTimesInMilliSec(m_process_times.kernel, tim_end.m_process_times.kernel) / 1.0e3 <<
193  ", user=" << diffFileTimesInMilliSec(m_process_times.user, tim_end.m_process_times.user) / 1.0e3 << (add_nl ? ")\n" : ")");
194  return tdiff3;
195 }
196 
197 
198 double ICPTimer::info(const char* title, DAEstatus& status)
199 {
200  std::ostringstream oss;
201  double d = info(title, oss, false);
202  status.addInfo(FAC_DAE, oss.str());
203  return d;
204 }
205 
206  void AddEventSource( PCTSTR pszName, PCTSTR pszMessageFile, DWORD dwCategoryCount)
207  {
208  HKEY hRegKey = NULL;
209  DWORD dwError = 0;
210  TCHAR szPath[ MAX_PATH ];
211 
212  _stprintf( szPath,
213  _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s"),
214  pszName );
215 
216  // Create the event source registry key
217  dwError = RegCreateKey( HKEY_LOCAL_MACHINE, szPath, &hRegKey );
218 
219  // Name of the PE module that contains the message resource
220  GetModuleFileName( NULL, szPath, MAX_PATH );
221 
222  // Register EventMessageFile
223  dwError = RegSetValueEx( hRegKey,
224  _T("EventMessageFile"), 0, REG_EXPAND_SZ,
225  (PBYTE) pszMessageFile, (_tcslen( pszMessageFile) + 1) * sizeof TCHAR );
226 
227  // Register supported event types
228  DWORD dwTypes = EVENTLOG_ERROR_TYPE |
229  EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE | EVENTLOG_SUCCESS;
230  dwError = RegSetValueEx( hRegKey, _T("TypesSupported"), 0, REG_DWORD,
231  (LPBYTE) &dwTypes, sizeof dwTypes );
232 
233  // If we want to support event categories,
234  // we have also to register the CategoryMessageFile.
235  // and set CategoryCount. Note that categories
236  // need to have the message ids 1 to CategoryCount!
237 
238  if( dwCategoryCount > 0 ) {
239 
240  dwError = RegSetValueEx( hRegKey, _T("CategoryMessageFile"),
241  0, REG_EXPAND_SZ, (PBYTE) szPath,
242  (_tcslen( szPath) + 1) * sizeof TCHAR );
243 
244  dwError = RegSetValueEx( hRegKey, _T("CategoryCount"), 0, REG_DWORD,
245  (PBYTE) &dwCategoryCount, sizeof dwCategoryCount );
246  }
247 
248  RegCloseKey( hRegKey );
249  }
250 
251 
252 // md5sum must be long enough to take 16 characters (see md5checksum_t )
253 int md5sumFile(const char* filename, unsigned char* md5sum, DAEstatus& status)
254 {
255  struct stat stat_buffer;
256  int len;
257  memset(md5sum, 0, sizeof(md5checksum_t));
258  if (stat(filename, &stat_buffer) != 0)
259  {
260  return DAEstatus::Failure;
261  }
262  FILE* f = _fsopen(filename, "rbN", _SH_DENYNO);
263  if (f == NULL)
264  {
265  return DAEstatus::Failure;
266  }
267  len = stat_buffer.st_size;
268  unsigned char* buffer = new unsigned char[len];
269  fread(buffer, 1, len, f);
270  fclose(f);
271  md5sumString(buffer, len, md5sum, status);
272  delete []buffer;
273  return status.result();
274 }
275 
276 // md5sum must be long enough to take 16 characters (see md5checksum_t )
277 int md5sumString(const void* buffer, int len, unsigned char* md5sum, DAEstatus& status)
278 {
279  static MD5Init_t MD5Init = 0;
280  static MD5Update_t MD5Update = 0;
281  static MD5Final_t MD5Final = 0;
282  static HINSTANCE hcrypt = 0;
283  memset(md5sum, 0, sizeof(md5checksum_t));
284  if (MD5Init == 0)
285  {
286  hcrypt = LoadLibrary("cryptdll.dll");
287  if (hcrypt == 0)
288  {
290  "cannot load cryptdll.dll");
291  return DAEstatus::Failure;
292  }
293  MD5Init = (MD5Init_t)GetProcAddress(hcrypt, "MD5Init");
294  MD5Update = (MD5Update_t)GetProcAddress(hcrypt, "MD5Update");
295  MD5Final = (MD5Final_t)GetProcAddress(hcrypt, "MD5Final");
296  }
297  if (MD5Init == 0)
298  {
300  "cannot find MD5Init in cryptdll.dll");
301  return DAEstatus::Failure;
302  }
303  MD5_CTX context;
304  (*MD5Init)(&context);
305  (*MD5Update)(&context, (const unsigned char*)buffer, len);
306  (*MD5Final)(&context);
307  memcpy((char*)md5sum, (const char*)context.digest, sizeof(context.digest));
308  return DAEstatus::Success;
309 }
310 
311 // return true if checksums the same
312 // all zeros means uninitialised checksum so return false if compare two
313 bool compareChecksums(const unsigned char* md5sum1, const unsigned char* md5sum2)
314 {
315  int i, sum = 0;
316  for(i=0; i<sizeof(md5checksum_t); i++)
317  {
318  sum = sum + md5sum1[i] + md5sum2[i];
319  if (md5sum1[i] != md5sum2[i])
320  {
321  return false;
322  }
323  }
324  if (sum == 0)
325  {
326  return false;
327  }
328  return true;
329 }
330 
331 int updateChecksum(unsigned char* md5sum1, const unsigned char* md5sum2)
332 {
333  memcpy(md5sum1, md5sum2, sizeof(md5checksum_t));
334  return DAEstatus::Success;
335 }
336 
337 // parge a [23:234] expression
338 int parseSpectraRange(const std::string& spec_range, int& spec_from, int& spec_to)
339 {
340  size_t i, j, k;
341  spec_from = spec_to = 0;
342  i = spec_range.find('[');
343  j = spec_range.find(':');
344  k = spec_range.find(']');
345  if (i == std::string::npos || j == std::string::npos || k == std::string::npos)
346  {
347  return DAEstatus::Failure;
348  }
349  spec_from = atoi(spec_range.substr(i+1,j-i-1).c_str());
350  spec_to = atoi(spec_range.substr(j+1,k-j-1).c_str());
351  return DAEstatus::Success;
352 }
353 
354 std::string checksumAsString(md5checksum_t checksum)
355 {
356  std::stringstream s;
357  s << std::hex;
358  for(int i=0; i<sizeof(md5checksum_t); i++)
359  {
360  s << (unsigned)checksum[i];
361  }
362  s << std::dec;
363  return s.str();
364 }
365 
366 
367 
368 struct MyOverlapped : public OVERLAPPED
369 {
370 private:
372 public:
374  void* arg;
375  MyOverlapped(overlap_complete_func_t func_, void* arg_) : func(func_), arg(arg_)
376  {
377  memset(this, 0, sizeof(OVERLAPPED));
378  }
379 };
380 
382 {
383 private:
385 public:
386  HANDLE h;
387  char* data;
388  my_overlap_t(HANDLE h_, const char* data_) : h(h_), data(0)
389  {
390  data = strdup(data_);
391  }
393  {
394  free(data);
395  if (h != INVALID_HANDLE_VALUE)
396  {
397  CloseHandle(h);
398  }
399  }
400 };
401 
402 static void my_overlap(void* arg)
403 {
404  my_overlap_t* ov = (my_overlap_t*)arg;
405  delete ov;
406 }
407 
408 static HANDLE file_complete = NULL;
409 
410 void my_io_complete(void* arg)
411 {
412  DWORD ntrans = 0;
413  ULONG_PTR key = 0;
414  MyOverlapped* overlapped = 0;
415  while(true)
416  {
417  GetQueuedCompletionStatus(file_complete, &ntrans, &key, (OVERLAPPED**)&overlapped, INFINITE);
418  (*(overlapped->func))(overlapped->arg);
419  delete overlapped;
420  }
421 }
422 
423 
424 HANDLE createAppendFile(const char* filename)
425 {
426  if (file_complete == NULL)
427  {
428  file_complete = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1);
429  _beginthread(my_io_complete, 0, NULL);
430  }
431  // need to specify FILE_SHARE_WRITE so other threads in this process can access it etc.
432  HANDLE h = CreateFile(filename, FILE_APPEND_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE,
433  defaultNoInheritHandles(), OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
434  if (h != INVALID_HANDLE_VALUE)
435  {
436  CreateIoCompletionPort(h, file_complete, 0 ,1);
437  }
438  return h;
439 }
440 
441 void appendToFileAsync(HANDLE h, const char* message, bool close_after_write)
442 {
443  if (message == NULL)
444  {
445  return;
446  }
447  if (h != INVALID_HANDLE_VALUE)
448  {
449  my_overlap_t* arg;
450  if (close_after_write)
451  {
452  arg = new my_overlap_t(h, message);
453  }
454  else
455  {
456  arg = new my_overlap_t(INVALID_HANDLE_VALUE, message);
457  }
458  MyOverlapped* overlapped = new MyOverlapped(my_overlap, arg);
459  WriteFile(h, arg->data, static_cast<DWORD>(strlen(message)), NULL, overlapped);
460  }
461 }
462 
463 void appendToFileAsync(const char* filename, const char* message)
464 {
465  if (message == NULL)
466  {
467  return;
468  }
469  HANDLE h = createAppendFile(filename);
470  if (h != INVALID_HANDLE_VALUE)
471  {
472  appendToFileAsync(h, message, true);
473  }
474 }
475 
476 
477 int findFiles(const char* directory, const char* pattern, std::vector<std::string>& list, bool full_path)
478 {
479  WIN32_FIND_DATA FindFileData;
480  HANDLE hFind;
481  list.clear();
482  std::string match = std::string(directory) + "\\" + std::string(pattern);
483  std::string file;
484  hFind = FindFirstFile(match.c_str(), &FindFileData);
485  if (hFind == INVALID_HANDLE_VALUE)
486  {
487  return 0;
488  }
489  if (full_path)
490  {
491  file = std::string(directory) + "\\" + std::string(FindFileData.cFileName);
492  }
493  else
494  {
495  file = std::string(FindFileData.cFileName);
496  }
497  list.push_back(file);
498  while(FindNextFile(hFind, &FindFileData) != 0)
499  {
500  if (full_path)
501  {
502  file = std::string(directory) + "\\" + std::string(FindFileData.cFileName);
503  }
504  else
505  {
506  file = std::string(FindFileData.cFileName);
507  }
508  list.push_back(file);
509  }
510  FindClose(hFind);
511  return 0;
512 }
513 
514 #include "Poco/StreamCopier.h"
515 #include "Poco/Path.h"
516 #include "Poco/URI.h"
517 #include "Poco/Exception.h"
518 
519 #include "Poco/Net/HTTPClientSession.h"
520 #include "Poco/Net/HTTPRequest.h"
521 #include "Poco/Net/HTTPResponse.h"
522 #include "Poco/Net/HTMLForm.h"
523 
524 #include "Poco/Net/SMTPClientSession.h"
525 #include "Poco/Net/MailMessage.h"
526 #include "Poco/Net/MailRecipient.h"
527 #include "Poco/Net/StringPartSource.h"
528 
529 #include "Poco/StringTokenizer.h"
530 
531 static int sendSMSMain(const std::string& phone, const std::string& message, DAEstatus& status)
532 {
533  using Poco::Net::HTTPClientSession;
534  using Poco::Net::HTTPRequest;
535  using Poco::Net::HTTPResponse;
536  using Poco::Net::HTTPMessage;
537  using Poco::Net::HTMLForm;
538  using Poco::StreamCopier;
539  using Poco::Path;
540  using Poco::URI;
541  using Poco::Exception;
542  try
543  {
544  HTTPClientSession session("www.kapow.co.uk");
545  HTMLForm form;
546  form.set("username","isissms");
547  form.set("password","camacdead");
548  form.set("mobile",phone);
549  form.set("sms",message);
550  session.setProxy("wwwcache.rl.ac.uk", 8080);
551  HTTPRequest request(HTTPRequest::HTTP_POST, "/scripts/sendsms.php", HTTPMessage::HTTP_1_1);
552  std::ostringstream oss;
553  form.prepareSubmit(request);
554  HTTPResponse res;
555  std::ostream& os = session.sendRequest(request);
556  form.write(os);
557  std::istream& rs = session.receiveResponse(res);
558  oss << "SMS status: " << res.getStatus() << " " << res.getReason() << " ";
559  StreamCopier::copyStream(rs, oss);
560  status.addInfo(FAC_DAE, oss.str());
561  }
562  catch(Exception& exc)
563  {
564  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, exc.displayText());
565  }
566  return 0;
567 }
568 
569 int sendSMS(const std::string& phone, const std::string& message, DAEstatus& status)
570 {
571  using Poco::StringTokenizer;
572  status.addInfoVa(FAC_DAE, "Sending SMS text to %s: %s", phone.c_str(), message.c_str());
573  StringTokenizer tokenizer(phone, ";,", StringTokenizer::TOK_IGNORE_EMPTY|StringTokenizer::TOK_TRIM);
574  for (StringTokenizer::Iterator it = tokenizer.begin(); it != tokenizer.end(); ++it)
575  {
576  sendSMSMain(*it, message, status);
577  }
578 // sendSMSMain("07766422175", message, status);
579  return 0;
580 }
581 
582 int sendEmail(const std::string& sender, const std::string& recipient, const std::string& subject, const std::string& content, DAEstatus& status)
583 {
584  using Poco::Net::MailMessage;
585  using Poco::Net::MailRecipient;
586  using Poco::Net::SMTPClientSession;
587  using Poco::Net::StringPartSource;
588  using Poco::Path;
589  using Poco::Exception;
590  using Poco::StringTokenizer;
591  status.addInfoVa(FAC_DAE, "Sending email to %s: %s", recipient.c_str(), subject.c_str());
592  try
593  {
594  MailMessage message;
595  message.setSender(sender);
596  StringTokenizer tokenizer(recipient, ";,", StringTokenizer::TOK_IGNORE_EMPTY|StringTokenizer::TOK_TRIM);
597  for (StringTokenizer::Iterator it = tokenizer.begin(); it != tokenizer.end(); ++it)
598  {
599  message.addRecipient(MailRecipient(MailRecipient::PRIMARY_RECIPIENT, *it));
600  }
601  if (tokenizer.count() == 0)
602  {
603  message.addRecipient(MailRecipient(MailRecipient::PRIMARY_RECIPIENT, "freddie.akeroyd@stfc.ac.uk"));
604  }
605  else
606  {
607  message.addRecipient(MailRecipient(MailRecipient::BCC_RECIPIENT, "freddie.akeroyd@stfc.ac.uk"));
608  }
609  message.setSubject(subject);
610  message.addContent(new StringPartSource(content));
611  SMTPClientSession session("outbox.nd.rl.ac.uk");
612  session.login();
613  session.sendMessage(message);
614  session.close();
615  }
616  catch(Exception& exc)
617  {
618  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, exc.displayText());
619  }
620  return 0;
621 }
622 
624 double diffFileTimesInMilliSec(const FILETIME& start, const FILETIME& finish)
625 {
626  return diffFileTimes(start, finish) / 1.0e4;
627 }
628 
630 LONGLONG diffFileTimes(const FILETIME& start, const FILETIME& finish)
631 {
632  ULARGE_INTEGER ularge1, ularge2;
633  ularge1.LowPart = start.dwLowDateTime;
634  ularge1.HighPart = start.dwHighDateTime;
635  ularge2.LowPart = finish.dwLowDateTime;
636  ularge2.HighPart= finish.dwHighDateTime;
637  if (ularge2.QuadPart > ularge1.QuadPart)
638  {
639  return ularge2.QuadPart - ularge1.QuadPart;
640  }
641  else
642  {
643  return -static_cast<LONGLONG>(ularge1.QuadPart - ularge2.QuadPart);
644  }
645 }
646 
648 off_t file_size_bytes(const std::string& filename)
649 {
650  struct stat stat_buffer;
651  if (stat(filename.c_str(), &stat_buffer) == 0)
652  {
653  return stat_buffer.st_size;
654  }
655  else
656  {
657  return 0;
658  }
659 }
660 
661 
663 template <typename T>
664 void findConsecutive(const std::vector<T>& vec, T invalid_val, std::vector<int>& indexes, std::vector<int>& sizes)
665 {
666  indexes.clear();
667  sizes.clear();
668  int start = -1;
669  for(int i=0; i<vec.size(); ++i)
670  {
671  if (vec[i] != invalid_val)
672  {
673  start = i;
674  break;
675  }
676  }
677  if (start == -1)
678  {
679  return;
680  }
681  indexes.push_back(start);
682  int len = 1;
683  int j = start + 1;
684  while(j < vec.size())
685  {
686  if (vec[j] != invalid_val)
687  {
688  if ( (vec[j] - vec[j-1]) == 1 )
689  {
690  ++len;
691  }
692  else
693  {
694  sizes.push_back(len);
695  indexes.push_back(j);
696  len = 1;
697  }
698  ++j;
699  }
700  else
701  {
702  start = -1;
703  for(int k=j+1; (k < vec.size()) && (start == -1); ++k)
704  {
705  if (vec[k] != invalid_val)
706  {
707  start = k;
708  }
709  }
710  if (start != -1)
711  {
712  j = start + 1;
713  sizes.push_back(len);
714  indexes.push_back(start);
715  len = 1;
716  }
717  else
718  {
719  j = vec.size(); // terminate loop
720  }
721  }
722  }
723  sizes.push_back(len);
724  // check result
725  for(int i=0; i<indexes.size(); ++i)
726  {
727  for(j=0; j<sizes[i]; ++j)
728  {
729  if (vec[indexes[i]+j] == invalid_val)
730  {
731  throw std::exception("invalid val");
732  }
733  if ( (j != 0) && ((vec[indexes[i]+j] - vec[indexes[i]+j-1]) != 1) )
734  {
735  throw std::exception("not consec");
736  }
737  }
738  }
739  for(int i=1; i<indexes.size(); ++i)
740  {
741  if ( (indexes[i-1] + sizes[i-1]) > indexes[i] )
742  {
743  throw std::exception("range overlap");
744  }
745  }
746 }
747 
748 int compareBuffers(const std::string& title, const isisU32_t* buffer1, const isisU32_t* buffer2, int nbuffer, DAEstatus& status)
749 {
750  int i;
751  std::vector<int> error_locs;
752  for(i=0; i<nbuffer; ++i)
753  {
754  if (buffer1[i] != buffer2[i])
755  {
756  error_locs.push_back(i);
757  }
758  }
759  if (error_locs.size() > 0)
760  {
761  std::ostringstream oss;
762  std::vector<int> indexes, sizes;
763  oss << title;
764  findConsecutive(error_locs, -1, indexes, sizes);
765  for(i=0; i<indexes.size(); ++i)
766  {
767  oss << " " << error_locs[indexes[i]] << "-" << error_locs[indexes[i]+sizes[i]-1];
768  }
769  status.addInfoVa(FAC_DAE, "%s", oss.str().c_str());
770  }
771  return 0;
772 }
773 
774 
775 template void findConsecutive(const std::vector<int>& vec, int invalid_val, std::vector<int>& indexes, std::vector<int>& sizes);
776 
777 static Poco::Mutex atomic_mutex_impl;
779 
780 class DebuggerChannel : public Poco::Channel
781 {
782  public:
783  void log(const Poco::Message& msg)
784  {
785  OutputDebugString((msg.getText() + "\n").c_str());
786  }
787 };
788 
789 class ICPFileChannel : public Poco::Channel
790 {
791  private:
794  static void* m_report_arg;
795 
796  public:
797  ICPFileChannel() : Poco::Channel()
798  {
799  m_status.reportImmediately(true);
800  }
801 
802  static void setReporter(DAEreport_func_t* report_func, void* report_arg)
803  {
804  m_report_func = report_func;
805  m_report_arg = report_arg;
806  }
807 
808  void log(const Poco::Message& msg)
809  {
810  m_status.setReportFunction(m_report_func, m_report_arg);
811  m_status.addInfo(FAC_DAE, msg.getText());
812  }
813 };
814 
816 void* ICPFileChannel::m_report_arg = NULL;
817 
818 class TestChannel : public Poco::Channel
819 {
820 private:
821  std::list<Poco::Message> m_messages;
822 
823 public:
824  void log(const Poco::Message& msg)
825  {
826  m_messages.push_back(msg);
827  }
828 };
829 
831 {
832  // the instantiators are deleted in the destructor for logging factory, so need to use "new"
833  Poco::Instantiator<DebuggerChannel, Poco::Channel> *debugger_channel_instantiator = new Poco::Instantiator<DebuggerChannel, Poco::Channel>;
834  Poco::Instantiator<ICPFileChannel, Poco::Channel> *icp_file_channel_instantiator = new Poco::Instantiator<ICPFileChannel, Poco::Channel>;
835  Poco::LoggingFactory::defaultFactory().registerChannelClass("DebuggerChannel", debugger_channel_instantiator);
836  Poco::LoggingFactory::defaultFactory().registerChannelClass("ICPFileChannel", icp_file_channel_instantiator);
837 }
838 
839 void setICPChannelReporter(DAEreport_func_t* report_func, void* report_arg)
840 {
841  ICPFileChannel::setReporter(report_func, report_arg);
842 }
843 
845 void getConfigStringList(std::vector<std::string>& string_list, const std::string& config_item)
846 {
847  string_list.clear();
848  std::string config_value = Poco::Util::Application::instance().config().getString(config_item, "");
849  Poco::StringTokenizer toks(config_value, ";", Poco::StringTokenizer::TOK_IGNORE_EMPTY|Poco::StringTokenizer::TOK_TRIM);
850  std::copy(toks.begin(), toks.end(), back_inserter(string_list));
851 }
852 
854 void getConfigIntList(std::vector<int>& int_list, const std::string& config_item)
855 {
856  int_list.clear();
857  std::vector<std::string> string_list;
858  getConfigStringList(string_list, config_item);
859  BOOST_FOREACH(const std::string& s, string_list)
860  {
861  int_list.push_back(atoi(s.c_str()));
862  }
863 }
864 
866 int loadAppConfig(const std::string& app_name)
867 {
868  Poco::Util::Application& the_app = Poco::Util::Application::instance();
869  std::string app_dir;
870  try
871  {
872  app_dir = the_app.config().getString("application.dir");
873  }
874  catch(const std::exception& ex)
875  {
876  the_app.logger().fatal(std::string("Cannot determine application.dir ") + ex.what());
877  std::cerr << "Cannot determine application.dir " << ex.what() << std::endl;
878  return -1;
879  }
880  Poco::Path app_props(app_dir+"/../../..", app_name+".properties");
881  Poco::Path app_props_default(app_dir+"/../../..", app_name+".default.properties");
882  app_props.makeAbsolute();
883  app_props_default.makeAbsolute();
884  // poco configurations have priorities that govern search order
885  // lower number -> searched first, with PRIO_APPLICATION searched before PRIO_DEFAULT before PRIO_SYSTEM
886  try
887  {
888  the_app.loadConfiguration(app_props_default.toString(), Poco::Util::Application::PRIO_DEFAULT);
889  }
890  catch(const std::exception& ex)
891  {
892  the_app.logger().fatal(std::string("Cannot load ") + app_props_default.toString() + ex.what());
893  std::cerr << "Cannot load " << app_props_default.toString() << ex.what() << std::endl;
894  return -1;
895  }
896  try
897  {
898  the_app.loadConfiguration(app_props.toString(), Poco::Util::Application::PRIO_APPLICATION);
899  }
900  catch(const std::exception& ex)
901  {
902  the_app.logger().information(std::string("Cannot load ") + app_props.toString() + ex.what());
903  std::cerr << "Cannot load " << app_props.toString() << ex.what() << std::endl;
904  }
905  return 0;
906 }
907 
908 
909 // 0 on success, -1 on error
910 static int flushed_write(const std::vector<std::string>& files, const std::vector<const void*>& data, const std::vector<int>& nbytes)
911 {
912  std::vector<FILE*> fp;
913  BOOST_FOREACH(const std::string& filename, files)
914  {
915  fp.push_back(fopen(filename.c_str(), "wbcN")); // "c" forces commit to disk on fflush()
916  }
917  for(int i=0; i<files.size(); ++i)
918  {
919  FILE* f = fp[i];
920  if (f != NULL)
921  {
922  if (std::fwrite(data[i], 1, nbytes[i], f) != nbytes[i])
923  {
924  std::fclose(f);
925  throw std::runtime_error("cannot write data");
926  }
927  }
928  else
929  {
930  throw std::runtime_error("cannot open file");
931  }
932  }
933  for(int i=0; i<files.size(); ++i)
934  {
935  FILE* f = fp[i];
936  if (std::fflush(f) != 0)
937  {
938  std::fclose(f);
939  throw std::runtime_error("cannot flush data");
940  }
941  if (std::fclose(f) != 0)
942  {
943  throw std::runtime_error("cannot close data");
944  }
945  }
946  return 0;
947 }
948 
949 // 0 on success, -1 on error
950 int flushed_write(const std::string& file, const void* data, int nbytes)
951 {
952  std::vector<std::string> file_v;
953  std::vector<const void*>data_v;
954  std::vector<int> nbytes_v;
955  file_v.push_back(file);
956  data_v.push_back(data);
957  nbytes_v.push_back(nbytes);
958  return flushed_write(file_v, data_v, nbytes_v);
959 }
960 
963 HANDLE createEmptyFile(const std::string& file_name, size_t file_size)
964 {
965  HANDLE h = CreateFile(file_name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, defaultNoInheritHandles(), CREATE_ALWAYS, 0, 0);
966  if (h == INVALID_HANDLE_VALUE)
967  {
968  return INVALID_HANDLE_VALUE;
969  }
970  LARGE_INTEGER li;
971  li.QuadPart = file_size;
972  if (SetFilePointerEx(h, li, 0, FILE_BEGIN) == 0)
973  {
974  CloseHandle(h);
975  return INVALID_HANDLE_VALUE;
976  }
977  if (SetEndOfFile(h) == 0)
978  {
979  CloseHandle(h);
980  return INVALID_HANDLE_VALUE;
981  }
982  return h;
983 }
984 
985 
986 static void deviceNameToDriveLetter(TCHAR* pszFilename)
987 {
988  // Translate path with device name to drive letters.
989  const int buffer_size = 512;
990  TCHAR szTemp[buffer_size];
991  szTemp[0] = '\0';
992 
993  if (GetLogicalDriveStrings(buffer_size-1, szTemp))
994  {
995  TCHAR szName[MAX_PATH];
996  TCHAR szDrive[3] = TEXT(" :");
997  BOOL bFound = FALSE;
998  TCHAR* p = szTemp;
999 
1000  do
1001  {
1002  // Copy the drive letter to the template string
1003  *szDrive = *p;
1004 
1005  // Look up each device name
1006  if (QueryDosDevice(szDrive, szName, MAX_PATH))
1007  {
1008  size_t uNameLen = _tcslen(szName);
1009 
1010  if (uNameLen < MAX_PATH)
1011  {
1012  bFound = _tcsnicmp(pszFilename, szName, uNameLen) == 0;
1013 
1014  if (bFound && *(pszFilename + uNameLen) == _T('\\'))
1015  {
1016  // Reconstruct pszFilename using szTempFile
1017  // Replace device path with DOS path
1018  TCHAR szTempFile[MAX_PATH];
1019  _snprintf(szTempFile, MAX_PATH, "%s%s", szDrive, pszFilename+uNameLen);
1020  strncpy(pszFilename, szTempFile, MAX_PATH);
1021  // StringCchPrintf(szTempFile, MAX_PATH, TEXT("%s%s"), szDrive, pszFilename+uNameLen);
1022  // StringCchCopyN(pszFilename, MAX_PATH+1, szTempFile, _tcslen(szTempFile));
1023  }
1024  }
1025  }
1026 
1027  // Go to the next NULL character.
1028  while (*p++);
1029  } while (!bFound && *p); // end of string
1030  }
1031 }
1032 
1033 std::string fileNameFromMappedView(void* pMem)
1034 {
1035  TCHAR pszFilename[MAX_PATH+1];
1036  int n = GetMappedFileName(GetCurrentProcess(), pMem, pszFilename, MAX_PATH);
1037  pszFilename[n] = '\0';
1038  if (n > 0)
1039  {
1040  deviceNameToDriveLetter(pszFilename);
1041  return pszFilename;
1042  }
1043  else
1044  {
1045  return "";
1046  }
1047 }
1048 
1049 int64_t fileSizeBytes(const std::string& filename)
1050 {
1051  int64_t the_size = 0;
1052  WIN32_FILE_ATTRIBUTE_DATA file_attr;
1053  if ( GetFileAttributesEx(filename.c_str(), GetFileExInfoStandard, &file_attr) != 0 )
1054  {
1055  the_size = (static_cast<int64_t>(file_attr.nFileSizeHigh) << 32) | file_attr.nFileSizeLow;
1056  }
1057  return the_size;
1058 }
1059 
1060 
1061 int createEmptyFileAndClose(const std::string& file_name, size_t file_size)
1062 {
1063  HANDLE h = createEmptyFile(file_name, file_size);
1064  if (h == INVALID_HANDLE_VALUE)
1065  {
1066  return DAEstatus::Failure;
1067  }
1068  CloseHandle(h);
1069  return DAEstatus::Success;
1070 }
1071 
1073 {
1074  MEMORYSTATUSEX statex;
1075  statex.dwLength = sizeof(statex);
1076  if (GlobalMemoryStatusEx(&statex) != 0)
1077  {
1078  status.addInfoVa(FAC_DAE, "There is %8ld percent of memory in use.", statex.dwMemoryLoad);
1079  status.addInfoVa(FAC_DAE, "There are %8I64d total Kbytes of physical memory.", statex.ullTotalPhys/1024);
1080  status.addInfoVa(FAC_DAE, "There are %8I64d free Kbytes of physical memory.", statex.ullAvailPhys/1024);
1081  status.addInfoVa(FAC_DAE, "There are %8I64d total Kbytes of paging file.", statex.ullTotalPageFile/1024);
1082  status.addInfoVa(FAC_DAE, "There are %8I64d free Kbytes of paging file.", statex.ullAvailPageFile/1024);
1083  status.addInfoVa(FAC_DAE, "There are %8I64d total Kbytes of virtual memory.", statex.ullTotalVirtual/1024);
1084  status.addInfoVa(FAC_DAE, "There are %8I64d free Kbytes of virtual memory.", statex.ullAvailVirtual/1024);
1085  status.addInfoVa(FAC_DAE, "There are %8I64d free Kbytes of extended memory", statex.ullAvailExtendedVirtual/1024);
1086  }
1087 }
1088 
1090 int removeWithRetry(const char* filename)
1091 {
1092  int ret = -1, nretry = 30;
1093  while( (--nretry > 0) && ((ret = std::remove(filename)) != 0) )
1094  {
1095  Poco::Thread::sleep(1000);
1096  }
1097  return ret;
1098 }
1099 
1100 void pollUntilTasksComplete(const Poco::TaskManager& tm, int poll_time_in_ms)
1101 {
1102  while(tm.count() > 0)
1103  {
1104  Poco::Thread::sleep(poll_time_in_ms);
1105  }
1106 }
1107 
1108 struct my_SECURITY_ATTRIBUTES : public SECURITY_ATTRIBUTES
1109 {
1110  my_SECURITY_ATTRIBUTES() : SECURITY_ATTRIBUTES()
1111  {
1112  ZeroMemory(this, sizeof(SECURITY_ATTRIBUTES));
1113  nLength = sizeof(SECURITY_ATTRIBUTES);
1114  lpSecurityDescriptor = NULL;
1115  bInheritHandle = FALSE;
1116  }
1117 };
1118 
1120 
1121 SECURITY_ATTRIBUTES* defaultNoInheritHandles()
1122 {
1123  return &my_security_attributes;
1124 }
int md5sumFile(const char *filename, unsigned char *md5sum, DAEstatus &status)
Definition: icputils.cpp:253
Poco::Timestamp m_ts
Definition: icptimer.h:10
#define FAC_DAE
LONGLONG diffFileTimes(const FILETIME &start, const FILETIME &finish)
finish - start, returned in 100ns units
Definition: icputils.cpp:630
#define ERRTYPE_OUTOFMEM
void pollUntilTasksComplete(const Poco::TaskManager &tm, int poll_time_in_ms)
Definition: icputils.cpp:1100
static ISISICPApp * the_app
Definition: isisicp.cpp:72
std::string checksumAsString(md5checksum_t checksum)
Definition: icputils.cpp:354
void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
Definition: md5.cpp:79
int compareBuffers(const std::string &title, const isisU32_t *buffer1, const isisU32_t *buffer2, int nbuffer, DAEstatus &status)
Definition: icputils.cpp:748
SYSTEMTIME m_st
Definition: icptimer.h:9
bool compareChecksums(const unsigned char *md5sum1, const unsigned char *md5sum2)
Definition: icputils.cpp:313
void setICPChannelReporter(DAEreport_func_t *report_func, void *report_arg)
Definition: icputils.cpp:839
int DAEreport_func_t(const DAEstatus_message &mess, void *arg)
Definition: DAEstatus.h:119
std::string fileNameFromMappedView(void *pMem)
Definition: icputils.cpp:1033
DAEstatus * m_status
Definition: icputils.h:241
unsigned long isisU32_t
Definition: isisvme_types.h:8
void(* overlap_complete_func_t)(void *arg)
Definition: icputils.h:311
static const int Failure
Definition: DAEstatus.h:141
int add(DAEstatus &dstatus, bool clear)
Definition: DAEstatus.cpp:131
static void * m_report_arg
Definition: icputils.cpp:794
void log(const Poco::Message &msg)
Definition: icputils.cpp:808
off_t file_size_bytes(const std::string &filename)
return size of a file in bytes
Definition: icputils.cpp:648
int updateChecksum(unsigned char *md5sum1, const unsigned char *md5sum2)
Definition: icputils.cpp:331
static const char * escape_sequence[]
Definition: icputils.cpp:68
void my_io_complete(void *arg)
Definition: icputils.cpp:410
SECURITY_ATTRIBUTES * defaultNoInheritHandles()
Definition: icputils.cpp:1121
static const int Success
Definition: DAEstatus.h:140
int setReportFunction(DAEreport_func_t *report_func, void *arg)
Definition: DAEstatus.h:178
static const int escape_length[]
Definition: icputils.cpp:69
Poco::Mutex * atomic_mutex
Definition: icputils.cpp:778
double diffFileTimesInMilliSec(const FILETIME &start, const FILETIME &finish)
finish - start in milliseconds
Definition: icputils.cpp:624
void(__stdcall * MD5Final_t)(MD5_CTX *)
Definition: icputils.h:328
HANDLE createEmptyFile(const std::string &file_name, size_t file_size)
Definition: icputils.cpp:963
std::string convertWindows1252ToUTF8(const std::string &win_string)
Definition: icputils.cpp:18
void * arg
Definition: icputils.cpp:374
std::list< Poco::Message > m_messages
Definition: icputils.cpp:821
void appendToFileAsync(HANDLE h, const char *message, bool close_after_write)
Definition: icputils.cpp:441
static void my_overlap(void *arg)
Definition: icputils.cpp:402
std::string escapeXML(const char *xml_str)
Definition: icputils.cpp:118
timings_t m_thread_times
Definition: icptimer.h:18
void(__stdcall * MD5Init_t)(MD5_CTX *)
Definition: icputils.h:324
#define SEV_ERROR
double diffFileTimesInMilliSec(const FILETIME &start, const FILETIME &finish)
finish - start in milliseconds
Definition: icptimer.h:32
int findFiles(const char *directory, const char *pattern, std::vector< std::string > &list, bool full_path)
Definition: icputils.cpp:477
static int sendSMSMain(const std::string &phone, const std::string &message, DAEstatus &status)
Definition: icputils.cpp:531
static my_SECURITY_ATTRIBUTES my_security_attributes
Definition: icputils.cpp:1119
DAEstatus m_status
Definition: icputils.cpp:792
static void setReporter(DAEreport_func_t *report_func, void *report_arg)
Definition: icputils.cpp:802
HANDLE createAppendFile(const char *filename)
Definition: icputils.cpp:424
std::string m_title
Definition: icptimer.h:7
int loadAppConfig(const std::string &app_name)
load a config file from ../../.. i.e. from c:/labview modules/dae if we are in c:/labview modules/dae...
Definition: icputils.cpp:866
unsigned char md5checksum_t[16]
Definition: icputils.h:303
ICPTimer()
Definition: icputils.cpp:29
int sendEmail(const std::string &sender, const std::string &recipient, const std::string &subject, const std::string &content, DAEstatus &status)
Definition: icputils.cpp:582
double info(const char *title, std::ostream &os, bool add_nl=true)
Definition: icptimer.h:83
void start(const char *title=NULL)
Definition: icptimer.h:64
Poco::SingletonHolder< ICPClock > g_icp_clock
Definition: icputils.cpp:5
FILETIME kernel
Definition: icptimer.h:15
static const char * escape_replace[]
Definition: icputils.cpp:70
void AddEventSource(PCTSTR pszName, PCTSTR pszMessageFile, DWORD dwCategoryCount)
Definition: icputils.cpp:206
static void deviceNameToDriveLetter(TCHAR *pszFilename)
Definition: icputils.cpp:986
int removeWithRetry(const char *filename)
return 0 on success, else error
Definition: icputils.cpp:1090
void getConfigIntList(std::vector< int > &int_list, const std::string &config_item)
read a ; separated list of items from a properties file and return the items as a vector&lt;int&gt; ...
Definition: icputils.cpp:854
void(__stdcall * MD5Update_t)(MD5_CTX *, const unsigned char *, unsigned int)
Definition: icputils.h:326
void MD5Init(struct MD5Context *ctx, int brokenEndian)
Definition: md5.cpp:53
int md5sumString(const void *buffer, int len, unsigned char *md5sum, DAEstatus &status)
Definition: icputils.cpp:277
FILETIME create
Definition: icptimer.h:13
int createEmptyFileAndClose(const std::string &file_name, size_t file_size)
Definition: icputils.cpp:1061
timings_t m_process_times
Definition: icptimer.h:19
void log(const Poco::Message &msg)
Definition: icputils.cpp:783
void reportImmediately(bool value)
Definition: DAEstatus.h:162
void getConfigStringList(std::vector< std::string > &string_list, const std::string &config_item)
read a ; separated list of items from a properties file and return the items as a vector&lt;string&gt; ...
Definition: icputils.cpp:845
char * data
Definition: icputils.cpp:387
static DAEreport_func_t * m_report_func
Definition: icputils.cpp:793
std::string unescapeXML(const char *xml_str)
Definition: icputils.cpp:72
void registerExtraLoggerChannels()
Definition: icputils.cpp:830
int addInfo(int facility, const std::string &text)
Definition: DAEstatus.cpp:86
static Poco::Mutex atomic_mutex_impl
Definition: icputils.cpp:777
int parseSpectraRange(const std::string &spec_range, int &spec_from, int &spec_to)
Definition: icputils.cpp:338
void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
Definition: md5.cpp:129
overlap_complete_func_t func
Definition: icputils.cpp:373
int result()
Definition: DAEstatus.h:144
int sendSMS(const std::string &phone, const std::string &message, DAEstatus &status)
Definition: icputils.cpp:569
int addInfoVa(int facility, const char *format,...)
Definition: DAEstatus.cpp:91
MyOverlapped(overlap_complete_func_t func_, void *arg_)
Definition: icputils.cpp:375
void findConsecutive(const std::vector< T > &vec, T invalid_val, std::vector< int > &indexes, std::vector< int > &sizes)
return an array of indices containing the start points of consecutive sequences of numbers ...
Definition: icputils.cpp:664
void log(const Poco::Message &msg)
Definition: icputils.cpp:824
static int flushed_write(const std::vector< std::string > &files, const std::vector< const void * > &data, const std::vector< int > &nbytes)
Definition: icputils.cpp:910
void printComputerMemoryStats(DAEstatus &status)
Definition: icputils.cpp:1072
~ICPTimer()
Definition: icptimer.h:60
std::string convertLatin1ToUTF8(const std::string &latin_string)
convert ISO Latin-1 (8859-1) to UTF-8
Definition: icputils.cpp:8
my_overlap_t(HANDLE h_, const char *data_)
Definition: icputils.cpp:388
static HANDLE file_complete
Definition: icputils.cpp:408
struct timeb m_tb
Definition: icptimer.h:8
int64_t fileSizeBytes(const std::string &filename)
Definition: icputils.cpp:1049