FACT++  1.0
feeserver.c
Go to the documentation of this file.
1  Return to feeserver.c CVS log Up to [MAIN] / dcscvs / FeeServer / feeserver / src
2 
3 --------------------------------------------------------------------------------
4 File: [MAIN] / dcscvs / FeeServer / feeserver / src / feeserver.c (download)
5 Revision: 1.26, Wed May 7 14:08:13 2008 UTC (22 months ago) by dominik
6 Branch: MAIN
7 CVS Tags: d, HEAD, FeeServer_v0-9-4_RCU-v0-9-9-dev, FeeServer_v0-9-4_RCU-v0-9-8-dev, FeeServer_v0-9-4_RCU-v0-9-7-dev, FeeServer_v0-9-4_RCU-v0-9-6-dev, FeeServer_v0-9-4_RCU-v0-9-5-dev, FeeServer_v0-9-4_RCU-v0-9-4, FeeServer_v0-9-4_RCU-v0-9-14-dev, FeeServer_v0-9-4_RCU-v0-9-13-dev, FeeServer_v0-9-4_RCU-v0-9-12-dev, FeeServer_v0-9-4_RCU-v0-9-11-dev, FeeServer_v0-9-4_RCU-v0-9-10-dev
8 Changes since 1.25: +32 -16 lines
9 updated to core version 0.9.4
10 
11 
12 
13 --------------------------------------------------------------------------------
14 
15 /************************************************************************
16  **
17  **
18  ** This file is property of and copyright by the Department of Physics
19  ** Institute for Physic and Technology, University of Bergen,
20  ** Bergen, Norway.
21  ** In cooperation with Center for Technology Transfer and
22  ** Telecommunication (ZTT), University of Applied Sciences Worms
23  ** Worms, Germany.
24  **
25  ** This file has been written by Sebastian Bablok,
26  ** Sebastian.Bablok@uib.no
27  **
28  ** Important: This file is provided without any warranty, including
29  ** fitness for any particular purpose. Further distribution of this file,
30  ** even with changes in the code, is only allowed, when this copyright
31  ** and warranty paragraph is kept unchanged and included to the sources.
32  **
33  **
34  *************************************************************************/
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <unistd.h> // for pause() necessary
39 #include <string.h>
40 #include <dim/dis.h> // dimserver library
41 #include <math.h> // for fabsf
42 
43 #include <time.h> // time for threads
44 #include <sys/time.h> // for gettimeofday()
45 #include <pthread.h>
46 //#include <stdbool.h> // included by fee_types.h
47 #include <errno.h> // for the error numbers
48 #include <signal.h>
49 
50 #include "fee_types.h" // declaration of own datatypes
51 #include "fee_functions.h" // declaration of feeServer functions
52 #include "fee_defines.h" // declaration of all globaly used constants
53 #include "feepacket_flags.h" // declaration of flag bits in a feepacket
54 #include "fee_errors.h" // defines of error codes
55 #include "ce_command.h" //control engine header file
56 
57 #ifdef __UTEST
58 #include "fee_utest.h"
59 #endif
60 
65 //-- global variables --
66 
71 static int state = COLLECTING;
72 
77 static bool ceReadySignaled = false;
78 
83 static int ceInitState = CE_NOT_INIT; // CE_OK; this has changed in version 0.9.4
84 
89 static ItemNode* firstNode = 0;
90 
95 static ItemNode* lastNode = 0;
96 
101 static MessageStruct message;
102 
108 static MessageStruct lastMessage;
109 
114 static unsigned short replicatedMsgCount = 0;
115 
122 static bool logWatchDogRunning = false;
123 
133 static unsigned int logWatchDogTimeout = DEFAULT_LOG_WATCHDOG_TIMEOUT;
134 
139 static unsigned int nodesAmount = 0;
140 
147 static bool monitorThreadStarted = false;
148 
153 static unsigned int serviceACKID;
154 
159 static unsigned int messageServiceID;
160 
165 static unsigned int commandID;
166 
171 static char* cmndACK = 0;
172 
177 static int cmndACKSize = 0;
178 
183 static char* serverName = 0;
184 
189 static int serverNameLength = 0;
190 
196 static unsigned short updateRate = DEFAULT_UPDATE_RATE;
197 
203 static unsigned long issueTimeout = DEFAULT_ISSUE_TIMEOUT;
204 
211 static unsigned int logLevel = DEFAULT_LOGLEVEL;
212 
217 static pthread_t thread_init;
218 
223 static pthread_t thread_mon;
224 
236 static pthread_t thread_logWatchdog;
237 
242 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
243 
248 static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER;
249 
254 static pthread_mutex_t wait_mut = PTHREAD_MUTEX_INITIALIZER;
255 
260 static pthread_mutex_t wait_init_mut = PTHREAD_MUTEX_INITIALIZER;
261 
266 static pthread_mutex_t command_mut = PTHREAD_MUTEX_INITIALIZER;
267 
272 static pthread_mutex_t log_mut = PTHREAD_MUTEX_INITIALIZER;
273 
274 
276 
281 static IntItemNode* firstIntNode = 0;
282 
287 static IntItemNode* lastIntNode = 0;
288 
293 static unsigned int intNodesAmount = 0;
294 
299 static pthread_t thread_mon_int;
300 
307 static bool intMonitorThreadStarted = false;
308 
309 
311 
316 static MemoryNode* firstMemoryNode = 0;
317 
322 static MemoryNode* lastMemoryNode = 0;
323 
324 
326 
331 static unsigned int charNodesAmount = 0;
332 
337 static CharItemNode* firstCharNode = 0;
338 
343 static CharItemNode* lastCharNode = 0;
344 
345 
346 
347 //-- Main --
348 
363 int main(int argc, char** arg) {
364  //-- only for unit tests
365 # ifdef __UTEST
366  // insert here the testfunction-calls
367  testFrameWork();
368  return 0;
369 # endif
370 
371  // now here starts the real stuff
372  initialize();
373  // test server (functional test)
374  while (1) {
375  // maybe do some checks here, like:
376  // - monitoring thread is still in good state
377  // - CE is still in good state
378  // - everything within the FeeServer is OK (assertions?)
379  pause();
380  }
381  return 0;
382 }
383 
384 
385 void initialize() {
386  //-- Declaring variables --
387  struct timeval now;
388  struct timespec timeout;
389  pthread_attr_t attr;
390  int nRet;
391  int status;
392  int initState = FEE_CE_NOTINIT;
393  char* name = 0;
394  char* dns = 0;
395  bool initOk = true;
396  unsigned int envVal = 0;
397  char msg[250];
398  int restartCount = 0;
399 
400  //-- register interrupt handler (CTRL-C)
401  // not used yet, causes problems
402 // if (signal(SIGINT, interrupt_handler) == SIG_ERR) {
403 //# ifdef __DEBUG
404 // printf("Unable to register interrupt handler.\n");
405 // printf("This is not fatal -> continuing.\n");
406 //# endif
407 // }
408 
409  //-- get name of the server --
410  name = getenv("FEE_SERVER_NAME");
411  if (name == 0) {
412 # ifdef __DEBUG
413  printf("No FEE_SERVER_NAME \n");
414 # endif
415  exit(202);
416  }
417 
418  serverName = (char*) malloc(strlen(name) + 1);
419  if (serverName == 0) {
420  //no memory available!
421 # ifdef __DEBUG
422  printf("no memory available while trying to create server name!\n");
423 # endif
424  exit(201);
425  }
426  strcpy(serverName, name);
427  serverNameLength = strlen(serverName);
428 
429  //-- test, if DIM_DNS_NODE is specified
430  dns = getenv("DIM_DNS_NODE");
431  if (dns == 0) {
432 # ifdef __DEBUG
433  printf("No DIM_DNS_NODE specified. \n");
434 # endif
435  exit(203);
436  }
437 
438  // set the desired log level, if provided
439  if (getenv("FEE_LOG_LEVEL")) {
440  sscanf(getenv("FEE_LOG_LEVEL"), "%d", &envVal);
441  if ((envVal < 0) || (envVal > MSG_MAX_VAL)) {
442 # ifdef __DEBUG
443  printf("Environmental variable has invalid Log Level, using default instead.\n");
444  fflush(stdout);
445 # endif
446  } else {
447  logLevel = envVal | MSG_ALARM;
448  }
449  }
450 
451  // set logWatchDogTimeout, if env variable "FEE_LOGWATCHDOG_TIMEOUT" is set
452  if (getenv("FEE_LOGWATCHDOG_TIMEOUT")) {
453  sscanf(getenv("FEE_LOGWATCHDOG_TIMEOUT"), "%d", &envVal);
454  if ((envVal <= 0) || (envVal > MAX_TIMEOUT)) {
455 # ifdef __DEBUG
456  printf("Environmental variable has invalid LogWatchDog Timeout, using default instead.\n");
457  fflush(stdout);
458 # endif
459  } else {
460  logWatchDogTimeout = envVal;
461  }
462  }
463 
464  // get restart counter
465  if (getenv("FEESERVER_RESTART_COUNT")) {
466  restartCount = atoi(getenv("FEESERVER_RESTART_COUNT"));
467  }
468 
469  // Initial printout
470 # ifdef __DEBUG
471  printf("\n ** FeeServer version %s ** \n\n", FEESERVER_VERSION);
472  printf("FeeServer name: %s\n", serverName);
473  printf("Using DIM_DNS_NODE: %s\n", dns);
474 # ifdef __BENCHMARK
475  printf(" -> Benchmark version of FeeServer <- \n");
476 # endif
477  printf("Current log level is: %d (MSG_ALARM (%d) is always on)\n", logLevel, MSG_ALARM);
478  printf("Restart Count is: %d; Restart-Env is: %s\n", restartCount,
479  getenv("FEESERVER_RESTART_COUNT"));
480 # endif
481 
482  //set dummy exit_handler to disable framework exit command, returns void
484 
485  //set error handler to catch DIM framework messages
487 
488  // to ensure that signal is in correct state before init procedure
489  ceReadySignaled = false;
490 
491  // lock mutex
492  status = pthread_mutex_lock(&wait_init_mut);
493  if (status != 0) {
494 # ifdef __DEBUG
495  printf("Lock init mutex error: %d\n", status);
496  fflush(stdout);
497 # endif
498  initOk = false;
499  } else {
500  // initiailisation of thread attribute only if mutex has been locked
501  status = pthread_attr_init(&attr);
502  if (status != 0) {
503 # ifdef __DEBUG
504  printf("Init attribute error: %d\n", status);
505  fflush(stdout);
506 # endif
507  initOk = false;
508  } else {
509  status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
510  if (status != 0) {
511 # ifdef __DEBUG
512  printf("Set attribute error: %d\n", status);
513  fflush(stdout);
514 # endif
515  initOk = false;
516  }
517  }
518  }
519 
520  if (initOk == true) {
521  // call only if initOk == true,
522  status = pthread_create(&thread_init, &attr, (void*) &threadInitializeCE, 0);
523  if (status != 0) {
524 # ifdef __DEBUG
525  printf("Create thread error: %d\n", status);
526  fflush(stdout);
527 # endif
528  initState = FEE_CE_NOTINIT;
529  } else {
530 # ifdef __DEBUG // for debugging the time amount the watchdog really waits (START)
531  time_t initStartTime = time(NULL);
532 # endif //__DEBUG
533 
534  // timeout set in ms, should be enough for initialisation; see fee_defines.h for current value
535  status = gettimeofday(&now, 0);
536  if ((status != 0) || (restartCount <= 0)) {
537  // backup solution for detetcting end of init process
538 # ifdef __DEBUG
539  printf("Get time of day error: %d or restartCount <= 0 (%d), using backup solution\n",
540  status, restartCount);
541  fflush(stdout);
542 # endif
543  // unlock mutex to enable functionality of signalCEReady
544  status = pthread_mutex_unlock(&wait_init_mut);
545 # ifdef __DEBUG
546  if (status != 0) {
547  printf("Unlock mutex error: %d\n", status);
548  fflush(stdout);
549  }
550 # endif
551  // sleep init-timeout length
552  usleep((TIMEOUT_INIT_CE_MSEC * 1000)); // sleep the microsec fraction
553 
554  const int sleepFraction = 1; // to check ready signal each second
555  int sleepLoops = TIMEOUT_INIT_CE_SEC / sleepFraction;
556  int cycles = 0;
557  do {
558  dtq_sleep(sleepFraction);
559  if (ceReadySignaled) {
560  break;
561  }
562  } while ( cycles++ < sleepLoops);
563 // dtq_sleep(TIMEOUT_INIT_CE_SEC); // old style without check each second
564 
565  if (ceReadySignaled == false) {
566  status = pthread_cancel(thread_init);
567 # ifdef __DEBUG
568  if (status != 0) {
569  printf("No thread to cancel: %d\n", status);
570  fflush(stdout);
571  }
572 # endif
573  // start with "the CE is not initialized!"
574  initState = FEE_CE_NOTINIT;
575 # ifdef __DEBUG
576  printf("Timeout in init [sleep]: %d\n", initState);
577  fflush(stdout);
578 # endif
579  } else {
580  if (ceInitState != CE_OK) {
581  // init failed, but no timeout occured
582  // (insufficient memory, etc. ... or something else)
583 # ifdef __DEBUG
584  printf("Init of CE failed, error: %d\n", ceInitState);
585  fflush(stdout);
586 # endif
587  initState = FEE_CE_NOTINIT;
588  } else {
589  // start with "everything is fine"
590  initState = FEE_OK;
591 # ifdef __DEBUG
592  printf("Init OK\n");
593  fflush(stdout);
594 # endif
595  }
596  }
597  } else {
598  timeout.tv_sec = now.tv_sec + TIMEOUT_INIT_CE_SEC;
599  timeout.tv_nsec = (now.tv_usec * 1000) +
600  (TIMEOUT_INIT_CE_MSEC * 1000000);
601 
602  // wait for finishing "issue" or timeout after the mutex is unlocked
603  // a retcode of 0 means, that pthread_cond_timedwait has returned
604  // with the cond_init signaled
605  status = pthread_cond_timedwait(&init_cond, &wait_init_mut, &timeout);
606  // -- start FeeServer depending on the state of the CE --
607  if (status != 0) {
608  status = pthread_cancel(thread_init);
609 # ifdef __DEBUG
610  if (status != 0) {
611  printf("No thread to cancel: %d\n", status);
612  fflush(stdout);
613  }
614 # endif
615  // start with "the CE is not initialized!"
616  initState = FEE_CE_NOTINIT;
617 # ifdef __DEBUG
618  printf("Timeout in init [timed_wait]: %d\n", initState);
619  fflush(stdout);
620 # endif
621  } else {
622  if (ceInitState != CE_OK) {
623  // init failed, but no timeout occured
624  // (insufficient memory, etc. ... or something else)
625 # ifdef __DEBUG
626  printf("Init of CE failed, error: %d\n", ceInitState);
627  fflush(stdout);
628 # endif
629  initState = FEE_CE_NOTINIT;
630  } else {
631  // start with "everything is fine"
632  initState = FEE_OK;
633 # ifdef __DEBUG
634  printf("Init OK\n");
635  fflush(stdout);
636 # endif
637  }
638  }
639  }
640 # ifdef __DEBUG // for debugging the time amout the watchdog waits (STOP)
641  time_t initStopTime = time(NULL);
642  if (initState != FEE_OK) {
643  printf("Watchdog: CE init tread\n started %s",
644  ctime(&initStartTime));
645  printf(" killed %s\n", ctime(&initStopTime));
646  // don't put this into one printf line -
647  // ctime or printf doe not work correct then, why?
648  fflush(stdout);
649  } else {
650  printf("Watchdog: CE init tread\n started %s",
651  ctime(&initStartTime));
652  printf(" finished %s\n", ctime(&initStopTime));
653  // don't put this into one printf line -
654  // ctime or printf doe not work correct then, why?
655  fflush(stdout);
656  }
657 # endif //__DEBUG
658  }
659  // destroy thread attribute
660  status = pthread_attr_destroy(&attr);
661 # ifdef __DEBUG
662  if (status != 0) {
663  printf("Destroy attribute error: %d\n", status);
664  fflush(stdout);
665  }
666 # endif
667  }
668 
669  // init message struct -> FeeServer name, version and DNS are also provided
671 
672  if (initState != FEE_OK) {
673  // remove all services of Items of ItemList
674 # ifdef __DEBUG
675  printf("Init failed, unpublishing item list\n");
676  fflush(stdout);
677 # endif
679  // new since version 0.8.1 -> int channels
681  // new since version 0.8.2b -> char channels
683  }
684 
685  // add div. services and the command channel and then start DIM server
686  nRet = start(initState);
687 
688  // unlock mutex
689  status = pthread_mutex_unlock(&wait_init_mut);
690  if (status != 0) {
691 # ifdef __DEBUG
692  printf("Unlock mutex error: %d\n", status);
693  fflush(stdout);
694 # endif
695  if (nRet == FEE_OK) {
696  createLogMessage(MSG_WARNING, "Unable to unlock init mutex.", 0);
697  }
698  }
699 
700  if (nRet != FEE_OK) {
701 # ifdef __DEBUG
702  printf("unable to start DIM server, exiting.\n");
703  fflush(stdout);
704 # endif
705  fee_exit_handler(205);
706  } else {
707 # ifdef __DEBUG
708  printf("DIM Server successfully started, ready to accept commands.\n");
709  fflush(stdout);
710 # endif
711  }
712 
713 # ifdef __DEBUG
714  printf("DEBUG - Init-State: %d, CE-State: %d, Restart-Env: %s, RestartCount: %d.\n",
715  initState, ceInitState, getenv("FEESERVER_RESTART_COUNT"), restartCount);
716  fflush(stdout);
717 # endif
718 
719  // test for failed init of CE and init restart counter,
720  // counter counts backwards: only if counter > 0 restart is triggerd
721  if ((initState != FEE_OK) && (getenv("FEESERVER_RESTART_COUNT")) &&
722  (restartCount > 0)) {
723  msg[sprintf(msg,
724  "Triggering a FeeServer restart to give CE init another try. Restart count (backward counter): %d ",
725  restartCount)] = 0;
726  createLogMessage(MSG_WARNING, msg, 0);
727 # ifdef __DEBUG
728  printf("Triggering a FeeServer restart for another CE init try (backward count: %d).\n",
729  restartCount);
730  fflush(stdout);
731 # endif
732  // small sleep, that DIM is able to send log messages before restart
733  dtq_sleep(1);
734  // trigger restart to give it another try for the CE to init
735  triggerRestart(FEE_EXITVAL_TRY_INIT_RESTART);
736  // NOTE this function won't return ...
737  }
738  // look through watchdog and backup solution about ceInitState and check it again !!!
739  // afterwards the following line won't be necessary !!!
740  // needed later in information about properties !!!
741 // ceInitState = initState;
742 
743  return;
744 }
745 
746 
748  int status = -1;
749  status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
750  // if cancelation is not able, it won't hurt ?!
751 # ifdef __DEBUG
752  if (status != 0) {
753  printf("Set cancel state (init) error: %d\n", status);
754  fflush(stdout);
755  }
756 # endif
757 
758  status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
759  // if cancelation is not able, it won't hurt ?!
760 # ifdef __DEBUG
761  if (status != 0) {
762  printf("Set cancel type (init) error: %d\n", status);
763  fflush(stdout);
764  }
765 # endif
766 
767  // Here starts the actual CE
768  initializeCE();
769 
770  // not necessary, return 0 is better
771 // pthread_exit(0);
772  return;
773 
774 }
775 
776 
777 void signalCEready(int ceState) {
778  int status = -1;
779 
780  // set cancel type to deferred
781  status = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
782 # ifdef __DEBUG
783  if (status != 0) {
784  printf("Set cancel type error: %d\n", status);
785  fflush(stdout);
786  }
787 # endif
788 
789  //lock the mutex before broadcast
790  status = pthread_mutex_lock(&wait_init_mut);
791 # ifdef __DEBUG
792  if (status != 0) {
793  printf("Lock mutex error: %d\n", status);
794  fflush(stdout);
795  }
796 # endif
797 
798  // provide init state of CE
799  ceInitState = ceState;
800 
801  //signal that CE has completed initialisation
802  // maybe try the call pthread_cond_signal instead for performance
803  pthread_cond_broadcast(&init_cond);
804 
805  // set variable for backup solution
806  ceReadySignaled = true;
807 
808  // unlock mutex
809  status = pthread_mutex_unlock(&wait_init_mut);
810 # ifdef __DEBUG
811  if (status != 0) {
812  printf("Unlock mutex error: %d\n", status);
813  fflush(stdout);
814  }
815 # endif
816 
817  // set cancel type to asyncroneous
818  status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
819 # ifdef __DEBUG
820  if (status != 0) {
821  printf("Set cancel type error: %d\n", status);
822  fflush(stdout);
823  }
824 # endif
825 }
826 
827 
828 // -- Command handler routine --
829 void command_handler(int* tag, char* address, int* size) {
830  struct timeval now;
831  struct timespec timeout;
832  int retcode = -1;
833  int status = -1;
834  pthread_t thread_handle;
835  pthread_attr_t attr;
836  IssueStruct issueParam;
837  CommandHeader header;
838  char* pHeaderStream = 0;
839  MemoryNode* memNode = 0;
840  bool useMM = false;
841 
842 #ifdef __BENCHMARK
843  char benchmsg[200];
844  // make benchmark entry
845  if ((size != 0 ) && (*size >= 4)) {
846  benchmsg[sprintf(benchmsg,
847  "FeeServer CommandHandler (Received command) - Packet-ID: %d",
848  *address)] = 0;
849  createBenchmark(benchmsg);
850  } else {
851  createBenchmark("FeeServer CommandHandler (Received command)");
852  }
853 #endif
854 
855  // init struct
856  initIssueStruct(&issueParam);
857 
858  issueParam.nRet = FEE_UNKNOWN_RETVAL;
859 
860  // check state (ERROR state is allowed for FeeServer commands, not CE)
861  if ((state != RUNNING) && (state != ERROR_STATE)) {
862  return;
863  }
864 
865  // lock command mutex to save command &ACK data until it is send
866  // and only one CE-Thread exists at one time
867  status = pthread_mutex_lock(&command_mut);
868  if (status != 0) {
869 # ifdef __DEBUG
870  printf("Lock command mutex error: %d\n", status);
871  fflush(stdout);
872 # endif
873  createLogMessage(MSG_WARNING, "Unable to lock command mutex.", 0);
874  }
875 
876  if ((tag == 0) || (address == 0) || (size == 0)) {
877  leaveCommandHandler(0, FEE_NULLPOINTER, MSG_WARNING,
878  "Received null pointer of DIM framework in command handler.");
879  return;
880  }
881 
882  if (*size < HEADER_SIZE) {
883  leaveCommandHandler(0, FEE_INVALID_PARAM, MSG_WARNING,
884  "FeeServer received corrupted command.");
885  return;
886  }
887 
888 # ifdef __DEBUG
889  printf(" Cmnd - Size: %d\n", *size);
890  fflush(stdout);
891 # endif
892 
893  //-- storing the header information in struct --
894  memcpy(&header.id, address, HEADER_SIZE_ID);
895  memcpy(&header.errorCode, address + HEADER_OFFSET_ID, HEADER_SIZE_ERROR_CODE);
896  memcpy(&header.flags, address + HEADER_OFFSET_ERROR_CODE, HEADER_SIZE_FLAGS);
897  memcpy(&header.checksum, address + HEADER_OFFSET_FLAGS, HEADER_SIZE_CHECKSUM);
898 
899  // --------------------- Check Flags --------------------------
900  if ((header.flags & HUFFMAN_FLAG) != 0) {
901  //-- do Huffmann decoding if flag is set --
902  // not implemented yet !!!
903  }
904 
905  issueParam.size = *size - HEADER_SIZE;
906  issueParam.command = (address + HEADER_SIZE);
907  // !!! if Huffman decoding necessary, think about memory management ???
908 
909  if ((header.flags & CHECKSUM_FLAG) != 0) {
910  //-- do checksum test if flag is set --
911  if (!checkCommand(issueParam.command, issueParam.size, header.checksum)) {
912  // -- checksum failed - notification
913  leaveCommandHandler(header.id, FEE_CHECKSUM_FAILED, MSG_WARNING,
914  "FeeServer received corrupted command data (checksum failed).");
915  return;
916  }
917  }
918 
919  // -- here start the Commands for the FeeServer itself --
920  if ((header.flags & FEESERVER_UPDATE_FLAG) != 0) {
921 #ifdef ENABLE_MASTERMODE
922  updateFeeServer(&issueParam);
923 #else
924  createLogMessage(MSG_WARNING, "FeeServer is not authorized to execute shell programs, skip ...", 0);
925 #endif //ENABLE_MASTERMODE
926  // this is only reached, if update has not been sucessful
927  issueParam.nRet = FEE_FAILED;
928  issueParam.size = 0;
929  } else if ((header.flags & FEESERVER_RESTART_FLAG) != 0) {
931  } else if ((header.flags & FEESERVER_REBOOT_FLAG) != 0) {
932  createLogMessage(MSG_INFO, "Rebooting DCS board.", 0);
933  system("reboot");
934  exit(0);
935  } else if ((header.flags & FEESERVER_SHUTDOWN_FLAG) != 0) {
936  createLogMessage(MSG_INFO, "Shuting down DCS board.", 0);
937  system("poweroff");
938  exit(0);
939  } else if ((header.flags & FEESERVER_EXIT_FLAG) != 0) {
940  fee_exit_handler(0);
941  } else if ((header.flags & FEESERVER_SET_DEADBAND_FLAG) != 0) {
942  issueParam.nRet = setDeadband(&issueParam);
943  } else if ((header.flags & FEESERVER_GET_DEADBAND_FLAG) != 0) {
944  issueParam.nRet = getDeadband(&issueParam);
945  } else if ((header.flags & FEESERVER_SET_ISSUE_TIMEOUT_FLAG) != 0) {
946  issueParam.nRet = setIssueTimeout(&issueParam);
947  } else if ((header.flags & FEESERVER_GET_ISSUE_TIMEOUT_FLAG) != 0) {
948  issueParam.nRet = getIssueTimeout(&issueParam);
949  } else if ((header.flags & FEESERVER_SET_UPDATERATE_FLAG) != 0) {
950  issueParam.nRet = setUpdateRate(&issueParam);
951  } else if ((header.flags & FEESERVER_GET_UPDATERATE_FLAG) != 0) {
952  issueParam.nRet = getUpdateRate(&issueParam);
953  } else if ((header.flags & FEESERVER_SET_LOGLEVEL_FLAG) != 0) {
954  issueParam.nRet = setLogLevel(&issueParam);
955  } else if ((header.flags & FEESERVER_GET_LOGLEVEL_FLAG) != 0) {
956  issueParam.nRet = getLogLevel(&issueParam);
957  } else {
958  // commands for CE are not allowed in ERROR state
959  if (state == ERROR_STATE) {
960  leaveCommandHandler(header.id, FEE_WRONG_STATE, MSG_ERROR,
961  "FeeServer is in ERROR_STATE, ignoring command for CE!");
962  return;
963  }
964 
965  // packet with no flags in header and no payload makes no sense
966  if (issueParam.size == 0) {
967  leaveCommandHandler(header.id, FEE_INVALID_PARAM, MSG_WARNING,
968  "FeeServer received empty command.");
969  return;
970  }
971 
972  // lock mutex
973  status = pthread_mutex_lock(&wait_mut);
974  if (status != 0) {
975  leaveCommandHandler(header.id, FEE_THREAD_ERROR, MSG_ERROR,
976  "Unable to lock condition mutex for watchdog.");
977  return;
978  }
979 
980  status = pthread_attr_init(&attr);
981  if (status != 0) {
983  leaveCommandHandler(header.id, FEE_THREAD_ERROR, MSG_ERROR,
984  "Unable to initialize issue thread.");
985  return;
986  }
987 
988  status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
989  if (status != 0) {
991  leaveCommandHandler(header.id, FEE_THREAD_ERROR, MSG_ERROR,
992  "Unable to initialize issue thread.");
993  return;
994  }
995 
996  status = pthread_create(&thread_handle, &attr, &threadIssue, (void*) &issueParam);
997  if (status != 0) {
999  leaveCommandHandler(header.id, FEE_THREAD_ERROR, MSG_ERROR,
1000  "Unable to create issue thread.");
1001  return;
1002  }
1003 
1004  status = pthread_attr_destroy(&attr);
1005  if (status != 0) {
1006 # ifdef __DEBUG
1007  printf("Destroy attribute error: %d\n", status);
1008  fflush(stdout);
1009 # endif
1010  createLogMessage(MSG_WARNING,
1011  "Unable to destroy thread attribute.", 0);
1012  }
1013 
1014  // timeout set in ms, see fee_defines.h for current value
1015  status = gettimeofday(&now, 0);
1016  if (status == 0) {
1017  // issueTimeout is in milliseconds:
1018  // get second-part with dividing by 1000
1019  timeout.tv_sec = now.tv_sec + (int) (issueTimeout / 1000);
1020  // get rest of division by 1000 (which is milliseconds)
1021  // and make it nanoseconds
1022  timeout.tv_nsec = (now.tv_usec * 1000) +
1023  ((issueTimeout % 1000) * 1000000);
1024 
1025  // wait for finishing "issue" or timeout, if signal has been sent
1026  // retcode is 0 !
1027  // this is the main logic of the watchdog for the CE of the FeeServer
1028  retcode = pthread_cond_timedwait(&cond, &wait_mut, &timeout);
1029 # ifdef __DEBUG
1030  printf("Retcode of CMND timedwait: %d\n", retcode);
1031  fflush(stdout);
1032 # endif
1033 
1034  // check retcode to detect and handle Timeout
1035  if (retcode == ETIMEDOUT) {
1036 # ifdef __DEBUG
1037  printf("ControlEngine watchdog detected TimeOut.\n");
1038  fflush(stdout);
1039 # endif
1040  createLogMessage(MSG_WARNING,
1041  "ControlEngine watch dog noticed a time out for last command.", 0);
1042 
1043  // kill not finished thread. no problem if this returns an error
1044  pthread_cancel(thread_handle);
1045  // setting errorCode to "a timout occured"
1046  issueParam.nRet = FEE_TIMEOUT;
1047  issueParam.size = 0;
1048  } else if (retcode != 0) {
1049  // "handling" of other error than timeout
1050 # ifdef __DEBUG
1051  printf("ControlEngine watchdog detected unknown error.\n");
1052  fflush(stdout);
1053 # endif
1054  createLogMessage(MSG_WARNING,
1055  "ControlEngine watch dog received an unknown for last command.", 0);
1056 
1057  // kill not finished thread. no problem if this returns an error
1058  pthread_cancel(thread_handle);
1059  // setting errorCode to "a thread error occured"
1060  issueParam.nRet = FEE_THREAD_ERROR;
1061  issueParam.size = 0;
1062  }
1063 
1064  } else {
1065 # ifdef __DEBUG
1066  printf("Get time of day error: %d\n", status);
1067  fflush(stdout);
1068 # endif
1069  createLogMessage(MSG_WARNING,
1070  "Watchdog timer could not be initialized. Using non-reliable sleep instead.",
1071  0);
1072  // release mutex to avoid hang up in issueThread before signaling condition
1073  unlockIssueMutex();
1074  // watchdog with condition signal could not be used, because gettimeofday failed.
1075  // sleeping instead for usual amount of time and trying to cancel thread aftterwards.
1076  usleep(issueTimeout * 1000);
1077  status = pthread_cancel(thread_handle);
1078  // if thread did still exist something went wrong -> "timeout" (== 0)
1079  if (status == 0) {
1080 # ifdef __DEBUG
1081  printf("TimeOut occured.\n");
1082 # endif
1083  createLogMessage(MSG_WARNING,
1084  "ControlEngine issue did not return in time.", 0);
1085  issueParam.nRet = FEE_TIMEOUT;
1086  issueParam.size = 0;
1087  }
1088  }
1089 
1090  unlockIssueMutex();
1091  }
1092  //--- end of CE call area --------------------
1093 
1094  // ---------- start to compose result -----------------
1095 # ifdef __DEBUG
1096  printf("Issue-nRet: %d\n", issueParam.nRet);
1097  fflush(stdout);
1098 # endif
1099  // check return value of issue
1100  if ((issueParam.nRet < FEE_UNKNOWN_RETVAL) ||
1101  (issueParam.nRet > FEE_MAX_RETVAL)) {
1102  issueParam.nRet = FEE_UNKNOWN_RETVAL;
1103  createLogMessage(MSG_DEBUG,
1104  "ControlEngine [command] returned unkown RetVal.", 0);
1105  }
1106 
1107 // start here with new memory management check for ACK
1108  // check if old ACK data is in MemoryNode list and free it
1109  if ((cmndACKSize > HEADER_SIZE) && (findMemoryNode(cmndACK + HEADER_SIZE) != 0)) {
1110  memNode = findMemoryNode(cmndACK + HEADER_SIZE);
1111  freeMemoryNode(memNode);
1112  } else { // free cmndACK in original way
1113  if (cmndACK != 0) {
1114  free(cmndACK);
1115  cmndACK = 0;
1116  }
1117  }
1118 
1119  // check if new result data is in MemoryNode list
1120  memNode = findMemoryNode(issueParam.result);
1121  if (memNode != 0) {
1122  cmndACK = memNode->ptr;
1123  useMM = true;
1124  } else {
1125  // create Acknowledge as return value of command
1126  // HEADER_SIZE bytes are added before result to insert the command
1127  // header before the result -> see CommandHeader in Client for details
1128  cmndACK = (char*) malloc(issueParam.size + HEADER_SIZE);
1129  }
1130 
1131  if (cmndACK == 0) {
1132  //no memory available!
1133 # ifdef __DEBUG
1134  printf("no memory available!\n");
1135  fflush(stdout);
1136 # endif
1137  createLogMessage(MSG_ERROR, "Insufficient memory for ACK.", 0);
1138 
1139  // no ACK because no memory!
1140  cmndACKSize = 0;
1141  status = pthread_mutex_unlock(&command_mut);
1142  if (status != 0) {
1143 # ifdef __DEBUG
1144  printf("Lock command mutex error: %d\n", status);
1145  fflush(stdout);
1146 # endif
1147  createLogMessage(MSG_WARNING,
1148  "Error while trying to unlock command mutex.", 0);
1149  }
1150  return;
1151  }
1152 
1153 # ifdef __DEBUG
1154  if (issueParam.size > 0) {
1155 // printf("in cmnd-Handler -> issue result: ");
1156 // printData(issueParam.result, 0, issueParam.size);
1157 // fflush(stdout);
1158  }
1159 # endif
1160 
1161  // checks checksumflag and calculates it if necessary
1162  if ((header.flags & CHECKSUM_FLAG) != 0) {
1163  header.checksum = calculateChecksum((unsigned char*) issueParam.result,
1164  issueParam.size);
1165  // !!! Do (Huffman- ) encoding, if wished afterwards.
1166  } else {
1167  header.checksum = CHECKSUM_ZERO;
1168  }
1169 
1170  // keep the whole flags also for the result packet
1171  header.errorCode = (short) issueParam.nRet;
1172 # ifdef __DEBUG
1173  printf("ErrorCode in Header: %d\n", header.errorCode);
1174  fflush(stdout);
1175 # endif
1176 
1177  pHeaderStream = marshallHeader(&header);
1178  memcpy((void*) cmndACK, (void*) pHeaderStream, HEADER_SIZE);
1179  if (pHeaderStream != 0) {
1180  free(pHeaderStream);
1181  }
1182 
1183  if (useMM) {
1184  /*
1185 # ifdef __DEBUG
1186  printf("ACK channel used with MemoryManagement in FeeServer.\n");
1187  fflush(stdout);
1188  createLogMessage(MSG_DEBUG,
1189  "ACK channel used with MemoryManagement in FeeServer.", 0);
1190 # endif
1191  */
1192  } else {
1193  memcpy(((void*) cmndACK + HEADER_SIZE), (void*) issueParam.result,
1194  issueParam.size);
1195  }
1196 
1197  //store the size of the result globally
1198  cmndACKSize = issueParam.size + HEADER_SIZE;
1199  // propagate change of ACK(nowledge channel) to upper Layers
1200  dis_update_service(serviceACKID);
1201 
1202 # ifdef __DEBUG
1203  // -- see the cmndACK as a char - string
1204  printf("ACK \n");
1205 // printData(cmndACK, HEADER_SIZE, cmndACKSize);
1206  // -- see the cmndACK in a HEX view for the ALTRO
1207  //print_package(cmndACK + HEADER_SIZE);
1208 # endif
1209 
1210  if ((!useMM) && (issueParam.result != 0)) {
1211  free(issueParam.result);
1212  }
1213 // end of new stuff for memory managment.
1214 
1215 /*
1216  if (cmndACK != 0) {
1217  free(cmndACK);
1218  cmndACK = 0;
1219  }
1220  // create Acknowledge as return value of command
1221  // HEADER_SIZE bytes are added before result to insert the command
1222  // header before the result -> see CommandHeader in Client for details
1223  cmndACK = (char*) malloc(issueParam.size + HEADER_SIZE);
1224  if (cmndACK == 0) {
1225  //no memory available!
1226 # ifdef __DEBUG
1227  printf("no memory available!\n");
1228  fflush(stdout);
1229 # endif
1230  createLogMessage(MSG_ERROR, "Insufficient memory for ACK.", 0);
1231 
1232  // no ACK because no memory!
1233  cmndACKSize = 0;
1234  status = pthread_mutex_unlock(&command_mut);
1235  if (status != 0) {
1236 # ifdef __DEBUG
1237  printf("Lock command mutex error: %d\n", status);
1238  fflush(stdout);
1239 # endif
1240  createLogMessage(MSG_WARNING,
1241  "Error while trying to unlock command mutex.", 0);
1242  }
1243  return;
1244  }
1245 
1246 # ifdef __DEBUG
1247  if (issueParam.size > 0) {
1248 // printf("in cmnd-Handler -> issue result: ");
1249 // printData(issueParam.result, 0, issueParam.size);
1250 // fflush(stdout);
1251  }
1252 # endif
1253 
1254  // checks checksumflag and calculates it if necessary
1255  if ((header.flags & CHECKSUM_FLAG) != 0) {
1256  header.checksum = calculateChecksum((unsigned char*) issueParam.result,
1257  issueParam.size);
1258  // !!! Do (Huffman- ) encoding, if wished afterwards.
1259  } else {
1260  header.checksum = CHECKSUM_ZERO;
1261  }
1262 
1263  // keep the whole flags also for the result packet
1264  header.errorCode = (short) issueParam.nRet;
1265 # ifdef __DEBUG
1266  printf("ErrorCode in Header: %d\n", header.errorCode);
1267  fflush(stdout);
1268 # endif
1269 
1270  pHeaderStream = marshallHeader(&header);
1271  memcpy((void*) cmndACK, (void*) pHeaderStream, HEADER_SIZE);
1272  if (pHeaderStream != 0) {
1273  free(pHeaderStream);
1274  }
1275  memcpy(((void*) cmndACK + HEADER_SIZE), (void*) issueParam.result,
1276  issueParam.size);
1277 
1278  //store the size of the result globally
1279  cmndACKSize = issueParam.size + HEADER_SIZE;
1280  // propagate change of ACK(nowledge channel) to upper Layers
1281  dis_update_service(serviceACKID);
1282 
1283 # ifdef __DEBUG
1284  // -- see the cmndACK as a char - string
1285  printf("ACK \n");
1286 // printData(cmndACK, HEADER_SIZE, cmndACKSize);
1287  // -- see the cmndACK in a HEX view for the ALTRO
1288  //print_package(cmndACK + HEADER_SIZE);
1289 # endif
1290 
1291  if (issueParam.result != 0) {
1292  free(issueParam.result);
1293  }
1294 
1295 */
1296 
1297 
1298  // unlock command mutex, data has been sent
1299  status = pthread_mutex_unlock(&command_mut);
1300  if (status != 0) {
1301 # ifdef __DEBUG
1302  printf("Lock command mutex error: %d\n", status);
1303  fflush(stdout);
1304 # endif
1305  createLogMessage(MSG_WARNING,
1306  "Error while trying to unlock command mutex.", 0);
1307  }
1308 }
1309 
1310 
1311 //-- user_routine to provide the ACK-data
1312 void ack_service(int* tag, char** address, int* size) {
1313 #ifdef __BENCHMARK
1314  char benchmsg[200];
1315 #endif
1316 
1317  if ((tag == 0) || (*tag != ACK_SERVICE_TAG)) {
1318 # ifdef __DEBUG
1319  printf("invalid ACK Service\n");
1320  fflush(stdout);
1321 # endif
1322  createLogMessage(MSG_WARNING, "DIM Framework called wrong ACK channel.",
1323  0);
1324  return;
1325  }
1326 // use the line below for checking flags of an outgoing feePacket!
1327 // printf("\nack_service was called flags are:%x%x\n", *(cmndACK+6), *(cmndACK+7));
1328  if ((cmndACKSize > 0) && (cmndACK != 0)) {
1329  *address = cmndACK;
1330  *size = cmndACKSize;
1331  } else {
1332  *size = 0;
1333  }
1334 #ifdef __BENCHMARK
1335  // make benchmark entry
1336  benchmsg[sprintf(benchmsg,
1337  "FeeServer AckHandler (sending ACK) - Packet-ID: %d", *cmndACK)] = 0;
1338  createBenchmark(benchmsg);
1339 #endif
1340 
1341 }
1342 
1343 
1344 void leaveCommandHandler(unsigned int id, short errorCode,
1345  unsigned int msgType, char* message) {
1346  int status = -1;
1347 
1348 # ifdef __DEBUG
1349  printf("%s\n", message);
1350  fflush(stdout);
1351 # endif
1352 
1353  createLogMessage(msgType, message, 0);
1354 
1355  // tell client that command is ignored
1356  if (cmndACK != 0) {
1357  free(cmndACK);
1358  cmndACK = 0;
1359  }
1360  // send error code
1361  cmndACK = createHeader(id, errorCode, false, false, 0);
1362  cmndACKSize = HEADER_SIZE;
1363  dis_update_service(serviceACKID);
1364 
1365  // unlock command mutex to "free" commandHandler
1366  status = pthread_mutex_unlock(&command_mut);
1367  if (status != 0) {
1368 # ifdef __DEBUG
1369  printf("Lock command mutex error: %d\n", status);
1370  fflush(stdout);
1371 # endif
1372  createLogMessage(MSG_WARNING,
1373  "Error while trying to unlock command mutex.", 0);
1374  }
1375 }
1376 
1377 
1379  int status = -1;
1380 
1381  status = pthread_mutex_unlock(&wait_mut);
1382  if (status != 0) {
1383 # ifdef __DEBUG
1384  printf("Unlock condition mutex error: %d. Going in ERROR state!\n", status);
1385  fflush(stdout);
1386 # endif
1387  createLogMessage(MSG_ALARM,
1388  "Unable to unlock watchdog mutex. No more commands will be possible for CE. Going in ERROR state!",
1389  0);
1390  state = ERROR_STATE;
1391  }
1392 }
1393 
1394 
1395 //-- publish-function called by CE (Control Engine) to declare Float - Items
1396 int publish(Item* item) {
1397  unsigned int id;
1398  char* serviceName = 0;
1399 
1400  // check for right state
1401  if (state != COLLECTING) {
1402  return FEE_WRONG_STATE;
1403  }
1404 
1405  // Testing for NULL - Pointer
1406  // !! Attention: if pointer is not initialized and also NOT set to NULL, this won't help !!
1407  if (item == 0) {
1408 # ifdef __DEBUG
1409  printf("Bad item, not published\n");
1410  fflush(stdout);
1411 # endif
1412  return FEE_NULLPOINTER;
1413  }
1414  if (item->name == 0 || item->location == 0) {
1415 # ifdef __DEBUG
1416  printf("Bad item, not published\n");
1417  fflush(stdout);
1418 # endif
1419  return FEE_NULLPOINTER;
1420  }
1421 
1422  // Check name for duplicate here (float)
1423  if (findItem(item->name) != 0) {
1424 # ifdef __DEBUG
1425  printf("Item name already published (float), new float item discarded.\n");
1426  fflush(stdout);
1427 # endif
1428  return FEE_ITEM_NAME_EXISTS;
1429  }
1430  // Check in INT list
1431  if (findIntItem(item->name) != 0) {
1432 # ifdef __DEBUG
1433  printf("Item name already published (int), float item discarded.\n");
1434  fflush(stdout);
1435 # endif
1436  return FEE_ITEM_NAME_EXISTS;
1437  }
1438  // Check in Char service list
1439  if (findCharItem(item->name) != 0) {
1440 # ifdef __DEBUG
1441  printf("Item name already published in char list, float item discarded.\n");
1442  fflush(stdout);
1443 # endif
1444  return FEE_ITEM_NAME_EXISTS;
1445  }
1446 
1447  // -- add item as service --
1448  serviceName = (char*) malloc(serverNameLength + strlen(item->name) + 2);
1449  if (serviceName == 0) {
1450  return FEE_INSUFFICIENT_MEMORY;
1451  }
1452  // terminate string with '\0'
1453  serviceName[sprintf(serviceName, "%s_%s", serverName, item->name)] = 0;
1454  id = dis_add_service(serviceName, "F", (int*) item->location,
1455  sizeof(float), 0, 0);
1456  free(serviceName);
1457  add_item_node(id, item);
1458 
1459  return FEE_OK;
1460 }
1461 
1462 
1463 //-- function to add service to our servicelist
1464 void add_item_node(unsigned int _id, Item* _item) {
1465  //create new node with enough memory
1466  ItemNode* newNode = 0;
1467 
1468  newNode = (ItemNode*) malloc(sizeof(ItemNode));
1469  if (newNode == 0) {
1470  //no memory available!
1471 # ifdef __DEBUG
1472  printf("no memory available while adding itemNode!\n");
1473 # endif
1474  // !!! unable to run FeeServer, write msg in kernel logger !!! (->Tobias)
1475  cleanUp();
1476  exit(201);
1477  }
1478  //initialize "members" of node
1479  newNode->prev = 0;
1480  newNode->next = 0;
1481  newNode->id = _id;
1482  newNode->item = _item;
1483  newNode->lastTransmittedValue = *(_item->location);
1484  //if default deadband is negative -> set threshold 0, otherwise set half of defaultDeadband
1485  newNode->threshold = (_item->defaultDeadband < 0) ? 0.0 : (_item->defaultDeadband / 2);
1486  /*
1487  if(_item->defaultDeadband < 0) {
1488  newNode->threshold = 0.0;
1489  } else {
1490  newNode->threshold = _item->defaultDeadband / 2;
1491  }
1492 */
1493  newNode->locBackup = _item->location;
1494  newNode->checksum = calculateChecksum((unsigned char*) &(_item->location),
1495  sizeof(volatile float*));
1496  newNode->checksumBackup = newNode->checksum;
1497 
1498 #ifdef __DEBUG
1499  // complete debug display of added Item
1500 /*
1501  printf("Item: %d\n", _id);
1502  printf("location: %f, locBackup %f\n", *(_item->location), *(newNode->locBackup));
1503  printf("location addr: %p, locBackup addr %p\n", _item->location, newNode->locBackup);
1504  printf("checksum1: %d, checksum2: %d\n\n", newNode->checksum,
1505  newNode->checksumBackup);
1506 */
1507 #endif
1508 
1509 # ifdef __DEBUG
1510  // short debug display of added Item
1511  printf("init of %s with ID %d: %f\n", newNode->item->name, newNode->id,
1512  newNode->lastTransmittedValue);
1513  fflush(stdout);
1514 # endif
1515 
1516  ++nodesAmount;
1517  //redirect pointers of doubly linked list
1518  if (firstNode != 0) {
1519  lastNode->next = newNode;
1520  newNode->prev = lastNode;
1521  lastNode = newNode;
1522  } else {
1523  firstNode = newNode;
1524  lastNode = newNode;
1525  }
1526 }
1527 
1528 
1529 //-- Logging function -----
1530 void createLogMessage(unsigned int type, char* description, char* origin) {
1531  int status = -1; // for mutex
1532  int descLength = 0;
1533  int originLength = 0;
1534  time_t timeVal;
1535  struct tm* now = 0;
1536 
1537  // check if not in COLLECTING state
1538  if (state == COLLECTING) {
1539  return; // no log channel available at that time
1540  }
1541 
1542  //lock access with mutex due to the fact that FeeServer & CE can use it
1543  status = pthread_mutex_lock(&log_mut);
1544  // discard eventual error, this would cause more problems
1545  // in each case, do NOT call createLogMessage ;) !
1546 # ifdef __DEBUG
1547  if (status != 0) {
1548  printf("Lock log mutex error: %d\n", status);
1549  fflush(stdout);
1550  }
1551 # endif
1552 
1553  if (!checkLogLevel(type)) { //if not -> unlock mutex -> return
1554  //unlock mutex
1555  status = pthread_mutex_unlock(&log_mut);
1556  // discard eventual error, this would cause more problems
1557  // in each case, do NOT call createLogMessage ;)
1558 # ifdef __DEBUG
1559  if (status != 0) {
1560  printf("Unlock log mutex error: %d\n", status);
1561  fflush(stdout);
1562  }
1563 # endif
1564  return;
1565  }
1566 
1567  // check if message is a replicate of the last log message
1568  if ((logWatchDogRunning) && (strncmp(description, lastMessage.description,
1569  (MSG_DESCRIPTION_SIZE - 1)) == 0)) {
1570  replicatedMsgCount++;
1571 
1572  //unlock mutex
1573  status = pthread_mutex_unlock(&log_mut);
1574  // discard eventual error, this would cause more problems
1575  // in each case, do NOT call createLogMessage ;)
1576 # ifdef __DEBUG
1577  if (status != 0) {
1578  printf("Unlock log mutex error: %d\n", status);
1579  fflush(stdout);
1580  }
1581 # endif
1582  // message is a replicate of last message, leave Messenger
1583  return;
1584  } else {
1585  // message is not a replicate of last one send,
1586  // check if replicated log messages are pending
1587  if (checkReplicatedLogMessage()) {
1588  // sleep a small amount to let Dim update channel
1589 // usleep(1000);
1590  }
1591  }
1592 
1593  // prepare data (cut off overlength)
1594  if (description != 0) {
1595  // limit description to maximum of field in message struct if longer
1596  descLength = ((strlen(description) >= MSG_DESCRIPTION_SIZE)
1597  ? (MSG_DESCRIPTION_SIZE - 1) : strlen(description));
1598  }
1599  if (origin != 0) {
1600  // limit origin to maximum of field in message struct if longer
1601  // be aware that "source" also contains server name and a slash
1602  originLength = ((strlen(origin) >= MSG_SOURCE_SIZE - serverNameLength - 1)
1603  ? (MSG_SOURCE_SIZE - serverNameLength - 2) : strlen(origin));
1604  }
1605 
1606  //set type
1607  message.eventType = type;
1608  //set detector
1609  memcpy(message.detector, LOCAL_DETECTOR, MSG_DETECTOR_SIZE);
1610  //set origin
1611  strcpy(message.source, serverName);
1612  if (origin != 0) {
1613  // append slash
1614  strcpy(message.source + serverNameLength, "/");
1615  // append origin maximum til end of source field in message struct
1616  strncpy(message.source + serverNameLength + 1, origin, originLength);
1617  // terminate with '\0'
1618  message.source[serverNameLength + 1 + originLength] = 0;
1619  }
1620  //set description
1621  if (description != 0) {
1622  // fill description field of message struct maximum til end
1623  strncpy(message.description, description, descLength);
1624  // terminate with '\0'
1625  message.description[descLength] = 0;
1626  } else {
1627  strcpy(message.description, "No description specified.");
1628  }
1629  //set current date and time
1630  time(&timeVal);
1631  now = localtime(&timeVal);
1632  message.date[strftime(message.date, MSG_DATE_SIZE, "%Y-%m-%d %H:%M:%S",
1633  now)] = 0;
1634 
1635  //updateService
1636  dis_update_service(messageServiceID);
1637 
1638  // copy send message to storage of last message
1639  lastMessage = message;
1640 
1641  //unlock mutex
1642  status = pthread_mutex_unlock(&log_mut);
1643  // discard eventual error, this would cause more problems
1644  // in each case, do NOT call createLogMessage ;)
1645 # ifdef __DEBUG
1646  if (status != 0) {
1647  printf("Unlock log mutex error: %d\n", status);
1648  fflush(stdout);
1649  }
1650 # endif
1651 }
1652 
1653 bool checkLogLevel(int event) {
1654  // Comparision with binary AND, if result has 1 as any digit, event is
1655  // included in current logLevel
1656  if ((logLevel & event) != 0) {
1657  return true;
1658  }
1659  return false;
1660 }
1661 
1662 void dim_error_msg_handler(int severity, int error_code, char* msg) {
1663  char type[8];
1664  int eventType = 0;
1665  char message[MSG_DESCRIPTION_SIZE];
1666  int length = 0;
1667 
1668  // map severity to own log levels
1669  switch (severity) {
1670  case 0:
1671  type[sprintf(type, "INFO")] = 0;
1672  eventType = MSG_INFO;
1673  break;
1674  case 1:
1675  type[sprintf(type, "WARNING")] = 0;
1676  eventType = MSG_WARNING;
1677  break;
1678  case 2:
1679  type[sprintf(type, "ERROR")] = 0;
1680  eventType = MSG_ERROR;
1681  break;
1682  case 3:
1683  type[sprintf(type, "FATAL")] = 0;
1684  eventType = MSG_ERROR;
1685  break;
1686  default :
1687  type[sprintf(type, "UNKNOWN")] = 0;
1688  eventType = MSG_WARNING;
1689  break;
1690  }
1691 
1692 # ifdef __DEBUG
1693  // print to command line if wanted
1694  printf("DIM: [%s - %d] - %d: %s.\n", type, severity, error_code, msg);
1695  fflush(stdout);
1696 # endif
1697 
1698  // send message only if FeeServer is in serving or error state
1699  if ((state == RUNNING) || (state == ERROR_STATE)) {
1700  // put DIM error code in front of message
1701  message[sprintf(message, "%s: ", mapDimErrorCodes(error_code))] = 0;
1702  length = strlen(message);
1703  strncpy((message + length), msg, (MSG_DESCRIPTION_SIZE - length - 1));
1704  message[MSG_DESCRIPTION_SIZE - 1] = 0;
1705  // deliver message to FeeServer message system
1706  createLogMessage(eventType, message, "DIM\0");
1707  }
1708 }
1709 
1710 char* mapDimErrorCodes(int errorCode) {
1711  switch (errorCode) {
1712  case (0x1): return "DIMDNSUNDEF";
1713  case (0x2): return "DIMDNSREFUS";
1714  case (0x3): return "DIMDNSDUPLC";
1715  case (0x4): return "DIMDNSEXIT ";
1716  case (0x5): return "DIMDNSTMOUT";
1717 
1718  case (0x10): return "DIMSVCDUPLC";
1719  case (0x11): return "DIMSVCFORMT";
1720  case (0x12): return "DIMSVCINVAL";
1721  case (0x13): return "DIMSVCTOOLG";
1722 
1723  case (0x20): return "DIMTCPRDERR";
1724  case (0x21): return "DIMTCPWRRTY";
1725  case (0x22): return "DIMTCPWRTMO";
1726  case (0x23): return "DIMTCPLNERR";
1727  case (0x24): return "DIMTCPOPERR";
1728  case (0x25): return "DIMTCPCNERR";
1729  case (0x26): return "DIMTCPCNEST";
1730 
1731  case (0x30): return "DIMDNSCNERR";
1732  case (0x31): return "DIMDNSCNEST";
1733 
1734  default: return "DIMUNKWNERR";
1735  }
1736 }
1737 
1738 //-- tells the server, that he can start serving;
1739 //-- no services can be added when server is in state RUNNING
1740 int start(int initState) {
1741  int nRet = FEE_UNKNOWN_RETVAL;
1742  char* serviceName = 0;
1743  char* messageName = 0;
1744  char* commandName = 0;
1745  char msgStructure[50];
1746 
1747  if (state == COLLECTING) {
1748  //----- add service for acknowledge -----
1749  serviceName = (char*) malloc(serverNameLength + 13);
1750  if (serviceName == 0) {
1751  //no memory available!
1752 # ifdef __DEBUG
1753  printf("no memory available while trying to create ACK channel!\n");
1754  fflush(stdout);
1755 # endif
1756  // !!! unable to run FeeServer, write msg in kernel logger !!! (-> Tobias)
1757  cleanUp();
1758  exit(201);
1759  }
1760  // compose ACK channel name and terminate with '\0'
1761  serviceName[sprintf(serviceName, "%s_Acknowledge", serverName)] = 0;
1762  if (cmndACK != 0) {
1763  free(cmndACK);
1764  cmndACK = 0;
1765  }
1766  // take created header
1767  cmndACK = createHeader(0, initState, false, false, 0);
1768  cmndACKSize = HEADER_SIZE;
1769  // add ACK channel as service to DIM
1770  serviceACKID = dis_add_service(serviceName, "C", 0, 0, &ack_service,
1771  ACK_SERVICE_TAG);
1772  free(serviceName);
1773 
1774  //----- add message service -----
1775  messageName = (char*) malloc(serverNameLength + 9);
1776  if (messageName == 0) {
1777  //no memory available!
1778 # ifdef __DEBUG
1779  printf("no memory available while trying to create message channel!\n");
1780  fflush(stdout);
1781 # endif
1782  // !!! unable to run FeeServer, write msg in kernel logger !!! (->Tobias)
1783  cleanUp();
1784  exit(201);
1785  }
1786  // compose message channel name and terminate with '\0'
1787  messageName[sprintf(messageName, "%s_Message", serverName)] = 0;
1788  // compose message structure
1789  msgStructure[sprintf(msgStructure, "I:1;C:%d;C:%d;C:%d;C:%d",
1790  MSG_DETECTOR_SIZE, MSG_SOURCE_SIZE, MSG_DESCRIPTION_SIZE,
1791  MSG_DATE_SIZE)] = 0;
1792  // add message channel as service to DIM
1793  messageServiceID = dis_add_service(messageName, msgStructure, (int*) &message,
1794  sizeof(unsigned int) + MSG_DETECTOR_SIZE + MSG_SOURCE_SIZE +
1795  MSG_DESCRIPTION_SIZE + MSG_DATE_SIZE, 0, 0);
1796  free(messageName);
1797 
1798  //----- before start serving we add the only command handled by the server -----
1799  commandName = (char*) malloc(serverNameLength + 9);
1800  if (commandName == 0) {
1801  //no memory available!
1802 # ifdef __DEBUG
1803  printf("no memory available while trying to create CMD channel!\n");
1804  fflush(stdout);
1805 # endif
1806  // !!! unable to run FeeServer, write msg in kernel logger !!! (->Tobias)
1807  cleanUp();
1808  exit(201);
1809  }
1810  // compose Command channel name and terminate with '\0'
1811  commandName[sprintf(commandName, "%s_Command", serverName)] = 0;
1812  // add CMD channel as command to DIM, no tag needed,
1813  // only one command possible
1814  commandID = dis_add_cmnd(commandName, "C", &command_handler, 0);
1815  free(commandName);
1816 
1817  //-- now start serving --
1818  if (dis_start_serving(serverName) == 1) {
1819  // if start server was successful
1820  if (initState == FEE_OK) {
1821  state = RUNNING;
1822  // start monitoring thread now
1823  nRet = startMonitorThread();
1824  if (nRet != FEE_OK) {
1825 # ifdef __DEBUG
1826  printf("Could NOT start monitor thread, error: %d\n", nRet);
1827  fflush(stdout);
1828 # endif
1829  createLogMessage(MSG_ERROR,
1830  "Unable to start monitor thread on FeeServer.", 0);
1831  return nRet;
1832  }
1833  // inform CE about update rate
1835  createLogMessage(MSG_INFO,
1836  "FeeServer started correctly, including monitor thread.", 0);
1837  nRet = FEE_OK;
1838  } else {
1839  state = ERROR_STATE;
1840  createLogMessage(MSG_ERROR,
1841  "Initialisation of ControlEngine failed. FeeServer is running in ERROR state (without CE).",
1842  0);
1843  // starting itself worked, so nRet is OK
1844  nRet = FEE_OK;
1845  }
1846  // start "relicated log messages" watchdog now
1847  nRet = startLogWatchDogThread();
1848  if (nRet != FEE_OK) {
1849 # ifdef __DEBUG
1850  printf("Could NOT start log watch dog thread, error: %d; FeeServer will run without it.\n",
1851  nRet);
1852  fflush(stdout);
1853 # endif
1854  createLogMessage(MSG_WARNING,
1855  "Can not start LogWatchDog thread (filters replicated MSGs). Uncritical error - running without it.",
1856  0);
1857  }
1858  } else {
1859  // starting server was not successful, so remove added core - services
1860  // so they can be added again by next start() - call
1861  dis_remove_service(serviceACKID);
1862  free(cmndACK);
1863  cmndACK = 0;
1864  cmndACKSize = 0;
1865  dis_remove_service(messageServiceID);
1866  dis_remove_service(commandID);
1867  nRet = FEE_FAILED;
1868  }
1869  return nRet;
1870  }
1871  //server is already running
1872  return FEE_OK;
1873 }
1874 
1875 // ****************************************
1876 // ---- starts the monitoring thread ----
1877 // ****************************************
1879  int status = -1;
1880  pthread_attr_t attr;
1881 
1882  // when item lists are empty, no monitor threads are needed
1883  if ((nodesAmount == 0) && (intNodesAmount == 0)) {
1884  createLogMessage(MSG_INFO,
1885  "No Items (float and int) for monitoring are available.", 0);
1886  return FEE_OK;
1887  }
1888 
1889  // init thread attribut and set it
1890  status = pthread_attr_init(&attr);
1891  if (status != 0) {
1892 # ifdef __DEBUG
1893  printf("Init attribute error [mon]: %d\n", status);
1894  fflush(stdout);
1895 # endif
1896  return FEE_MONITORING_FAILED;
1897  }
1898  status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1899  if (status != 0) {
1900 # ifdef __DEBUG
1901  printf("Set attribute error [mon]: %d\n", status);
1902  fflush(stdout);
1903 # endif
1904  return FEE_MONITORING_FAILED;
1905  }
1906 
1907  // start the monitor thread for float values
1908  if (nodesAmount > 0) {
1909  status = pthread_create(&thread_mon, &attr, (void*)&monitorValues, 0);
1910  if (status != 0) {
1911 # ifdef __DEBUG
1912  printf("Create thread error [mon - float]: %d\n", status);
1913  fflush(stdout);
1914 # endif
1915  return FEE_MONITORING_FAILED;
1916  }
1917  }
1918 
1919  //start the monitor thread for int values --> NEW v.0.8.1
1920  if (intNodesAmount > 0) {
1921  status = pthread_create(&thread_mon_int, &attr, (void*)&monitorIntValues, 0);
1922  if (status != 0) {
1923 # ifdef __DEBUG
1924  printf("Create thread error [mon - int]: %d\n", status);
1925  fflush(stdout);
1926 # endif
1927  return FEE_MONITORING_FAILED;
1928  }
1929  }
1930 
1931  // cleanup attribut
1932  status = pthread_attr_destroy(&attr);
1933  if (status != 0) {
1934 # ifdef __DEBUG
1935  printf("Destroy attribute error [mon]: %d\n", status);
1936  fflush(stdout);
1937 # endif
1938  // no error return value necessary !
1939  }
1940  return FEE_OK;
1941 }
1942 
1943 // --- this is the monitoring thread ---
1945  int status = -1;
1946  int nRet;
1947  unsigned long sleepTime = 0;
1948  ItemNode* current = 0;
1949  char msg[120];
1950  unsigned long innerCounter = 0; // used for update check after time interval
1951  unsigned long outerCounter = 0; // used for update check after time interval
1952 
1953  // set flag, that monitor thread has been started
1954  monitorThreadStarted = true;
1955 
1956  // set cancelation type
1957  status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
1958  if (status != 0) {
1959 # ifdef __DEBUG
1960  printf("Set cancel state error [mon - float]: %d\n", status);
1961  fflush(stdout);
1962 # endif
1963  createLogMessage(MSG_WARNING,
1964  "Unable to configure monitor thread (float) properly. Monitoring is not affected.", 0);
1965  }
1966  status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
1967  if (status != 0) {
1968 # ifdef __DEBUG
1969  printf("Set cancel type error [mon - float]: %d\n", status);
1970  fflush(stdout);
1971 # endif
1972  createLogMessage(MSG_WARNING,
1973  "Unable to configure monitor thread (float) properly. Monitoring is not affected.", 0);
1974  }
1975 
1976  createLogMessage(MSG_DEBUG, "Started monitor thread for FLOAT values successfully.", 0);
1977 
1978  while (1) {
1979  current = firstNode;
1980  sleepTime = (unsigned long) (updateRate / nodesAmount);
1981  while (current != 0) { // is lastNode->next (end of list)
1982  if (!checkLocation(current)) {
1983  msg[sprintf(msg, "Value of item %s (float) is corrupt, reconstruction failed. Ignoring!",
1984  current->item->name)] = 0;
1985  createLogMessage(MSG_ERROR, msg, 0);
1986  // message and do some stuff (like invalidate value)
1987  // (test, what happens if pointer is redirected ???)
1988  } else {
1989  if ((fabsf((*(current->item->location)) - current->lastTransmittedValue)
1990  >= current->threshold) || (outerCounter ==
1991  (innerCounter * TIME_INTERVAL_MULTIPLIER))) {
1992  nRet = dis_update_service(current->id);
1993  current->lastTransmittedValue = *(current->item->location);
1994 # ifdef __DEBUG
1995  //printf("Updated %d clients for service %s [float]: %f\n", nRet,
1996  // current->item->name, *(current->item->location));
1997  //fflush(stdout);
1998 # endif
1999  }
2000  }
2001 
2002  ++innerCounter;
2003  current = current->next;
2004  usleep(sleepTime * 1000);
2005  // sleeps xy microseconds, needed milliseconds-> "* 1000"
2006  }
2007  // with the check of both counter, each service is at least updated after
2008  // every (deadband updateRate * nodesAmount) seconds
2009  innerCounter = 0;
2010  ++outerCounter;
2011  // after every service in list is updated set counter back to 0
2012  // the TIME_INTERVAL_MULTIPLIER is used to enlarge the time interval of
2013  // the request of services without touching the deadband checker updateRate
2014  if (outerCounter >= (nodesAmount * TIME_INTERVAL_MULTIPLIER)) {
2015  outerCounter = 0;
2016  }
2017  }
2018  // should never be reached !
2019  pthread_exit(0);
2020 }
2021 
2022 // checks against bitflips in location
2023 bool checkLocation(ItemNode* node) {
2024  if (node->item->location == node->locBackup) {
2025  // locations are identical, so no bitflip
2026  return true;
2027  }
2028  // locations are not identical, check further
2029 
2030  if (node->checksum == calculateChecksum((unsigned char*)
2031  &(node->item->location), sizeof(volatile float*))) {
2032  // checksum tells, that first location should be valid, repair backup
2033  node->locBackup = node->item->location;
2034  return true;
2035  }
2036  // original location or first checksum is wrong, continue checking
2037 
2038  if (node->checksum == calculateChecksum((unsigned char*)
2039  &(node->locBackup), sizeof(volatile float*))) {
2040  // checksum tells, that location backup should be valid, repair original
2041  node->item->location = node->locBackup;
2042  return true;
2043  }
2044  // location backup or first checksum is wrong, continue checking
2045 
2046  if (node->checksum == node->checksumBackup) {
2047  // it seems that location and location backup are wrong
2048  // or checksum value runs banana, not repairable
2049  return false;
2050  }
2051  // it seems that first checksum is wrong
2052  // try to fix with second checksum
2053 
2054  if (node->checksumBackup == calculateChecksum((unsigned char*)
2055  &(node->item->location), sizeof(volatile float*))) {
2056  // checksum backup tells, that first location should be valid, repair backup
2057  node->locBackup = node->item->location;
2058  // repair first checksum
2059  node->checksum = node->checksumBackup;
2060  return true;
2061  }
2062  // original location or second checksum is wrong, continue checking
2063 
2064  if (node->checksumBackup == calculateChecksum((unsigned char*)
2065  &(node->locBackup), sizeof(volatile float*))) {
2066  // checksum backup tells, that location backup should be valid, repair original
2067  node->item->location = node->locBackup;
2068  // repair checksum
2069  node->checksum = node->checksumBackup;
2070  return true;
2071  }
2072  // value is totally banana, no chance to fix
2073  return false;
2074 }
2075 
2076 // ****************************************
2077 // ---- starts the LogWatchdog Thread ----
2078 // ****************************************
2080  int status = -1;
2081  pthread_attr_t attr;
2082 
2083  // init thread attribut and set it
2084  status = pthread_attr_init(&attr);
2085  if (status != 0) {
2086 # ifdef __DEBUG
2087  printf("Init attribute error [LogWatchDog]: %d\n", status);
2088  fflush(stdout);
2089 # endif
2090  return FEE_THREAD_ERROR;
2091  }
2092  status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2093  if (status != 0) {
2094 # ifdef __DEBUG
2095  printf("Set attribute error [LogWatchDog]: %d\n", status);
2096  fflush(stdout);
2097 # endif
2098  return FEE_THREAD_ERROR;
2099  }
2100 
2101  // start the LogWatchDog thread
2102  status = pthread_create(&thread_logWatchdog, &attr, (void*) &runLogWatchDog,
2103  0);
2104  if (status != 0) {
2105 # ifdef __DEBUG
2106  printf("Create thread error [LogWatchDog]: %d\n", status);
2107  fflush(stdout);
2108 # endif
2109  return FEE_THREAD_ERROR;
2110  }
2111 
2112  // cleanup attribut
2113  status = pthread_attr_destroy(&attr);
2114  if (status != 0) {
2115 # ifdef __DEBUG
2116  printf("Destroy attribute error [LogWatchDog]: %d\n", status);
2117  fflush(stdout);
2118 # endif
2119  // no error return value necessary !
2120  }
2121 
2122  return FEE_OK;
2123 }
2124 
2126  int status = -1;
2127  unsigned int sleepSec = 0;
2128  unsigned int sleepMilliSec = 0;
2129 
2130  // set cancelation type
2131  status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
2132  if (status != 0) {
2133 # ifdef __DEBUG
2134  printf("Set cancel state error [LogWatchDog]: %d\n", status);
2135  fflush(stdout);
2136 # endif
2137  createLogMessage(MSG_WARNING,
2138  "Can not set cancel state for LogWatchDog thread. WatchDog should not not be affected.",
2139  0);
2140  }
2141  status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
2142  if (status != 0) {
2143 # ifdef __DEBUG
2144  printf("Set cancel type error [LogWatchDog]: %d\n", status);
2145  fflush(stdout);
2146 # endif
2147  createLogMessage(MSG_WARNING,
2148  "Can not set cancel type for LogWatchDog thread. WatchDog should not not be affected.",
2149  0);
2150  }
2151 
2152  // thread started successfully, set flag accordingly
2153  logWatchDogRunning = true;
2154  createLogMessage(MSG_DEBUG,
2155  "LogWatchDog thread for filtering replicated log messages successfully started.",
2156  0);
2157 # ifdef __DEBUG
2158  printf("LogWatchDog thread for filtering replicated log messages successfully started.\n");
2159  fflush(stdout);
2160 # endif
2161 
2162  while (1) {
2163  // before test for replicated messages lock mutex,
2164  // DON'T call createLogMessage() inside mutex lock
2165  status = pthread_mutex_lock(&log_mut);
2166  // discard eventual error, this would cause more problems
2167 # ifdef __DEBUG
2168  if (status != 0) {
2169  printf("Lock log mutex error: %d\n", status);
2170  fflush(stdout);
2171  }
2172 # endif
2173 
2174  // perform check here
2176 
2177  // release mutex
2178  status = pthread_mutex_unlock(&log_mut);
2179  // discard eventual error, this would cause more problems
2180 # ifdef __DEBUG
2181  if (status != 0) {
2182  printf("Unlock log mutex error: %d\n", status);
2183  fflush(stdout);
2184  }
2185 # endif
2186 
2187  // set cancelation point
2188  pthread_testcancel();
2189  // prepare sleep time (timeout)
2190  sleepSec = logWatchDogTimeout / 1000;
2191  sleepMilliSec = logWatchDogTimeout % 1000;
2192  usleep(sleepMilliSec * 1000);
2193  dtq_sleep(sleepSec);
2194  // set cancelation point
2195  pthread_testcancel();
2196  }
2197 
2198  // should never be reached !
2199  pthread_exit(0);
2200 }
2201 
2203  int tempLength = 0;
2204  time_t timeVal;
2205  struct tm* now = 0;
2206 
2207  // check if replicated messages are pending
2208  if (replicatedMsgCount > 0) {
2209  // replicated messages occured in between, informing upper layer ...
2210  message.description[sprintf(message.description,
2211  "Log message repeated %d times: ", replicatedMsgCount)] = 0;
2212  // append original message as far as possible
2213  tempLength = strlen(message.description);
2214  if ((strlen(lastMessage.description) + tempLength) >=
2215  MSG_DESCRIPTION_SIZE) {
2216  // copy only a part of the original message that fits in the
2217  // description field
2218  strncpy((message.description + tempLength), lastMessage.description,
2219  (MSG_DESCRIPTION_SIZE - tempLength));
2220  message.description[MSG_DESCRIPTION_SIZE - 1] = 0;
2221  } else {
2222  // enough space free, copy the whole original message
2223  strcpy((message.description + tempLength),
2224  lastMessage.description);
2225  message.description[strlen(lastMessage.description) +
2226  tempLength - 1] = 0;
2227  }
2228  // set correct timestamp
2229  time(&timeVal);
2230  now = localtime(&timeVal);
2231  message.date[strftime(message.date, MSG_DATE_SIZE, "%Y-%m-%d %H:%M:%S",
2232  now)] = 0;
2233 
2234  //update MsgService with notification of repeated messages
2235  dis_update_service(messageServiceID);
2236  // clearing counter
2237  replicatedMsgCount = 0;
2238  return true;
2239  }
2240  return false;
2241 }
2242 
2243 void* threadIssue(void* threadParam) {
2244  IssueStruct* issueParam = (IssueStruct*) threadParam;
2245  int status;
2246 
2247  status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
2248  if (status != 0) {
2249 # ifdef __DEBUG
2250  printf("Set cancel state error: %d\n", status);
2251  fflush(stdout);
2252 # endif
2253  createLogMessage(MSG_WARNING,
2254  "Unable to configure issue thread properly. Execution might eventually be affected.", 0);
2255  }
2256 
2257  status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
2258  if (status != 0) {
2259 # ifdef __DEBUG
2260  printf("Set cancel type error error: %d\n", status);
2261  fflush(stdout);
2262 # endif
2263  createLogMessage(MSG_WARNING,
2264  "Unable to configure issue thread properly. Execution might eventually be affected.", 0);
2265  }
2266 
2267  // executing command inside CE
2268  issueParam->nRet = issue(issueParam->command, &(issueParam->result), &(issueParam->size));
2269 
2270  //set cancel type to deferred
2271  status = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
2272  if (status != 0) {
2273 # ifdef __DEBUG
2274  printf("Set cancel type error: %d\n", status);
2275  fflush(stdout);
2276 # endif
2277  createLogMessage(MSG_WARNING,
2278  "Unable to configure issue thread properly. Execution might eventually be affected.", 0);
2279  }
2280 
2281  //lock the mutex before broadcast
2282  status = pthread_mutex_lock(&wait_mut);
2283  if (status != 0) {
2284 # ifdef __DEBUG
2285  printf("Lock cond mutex error: %d\n", status);
2286  fflush(stdout);
2287 # endif
2288  createLogMessage(MSG_WARNING,
2289  "Unable to lock condition mutex for watchdog in issue thread. Execution might eventually be affected.",
2290  0);
2291  }
2292 
2293  //signal that issue has returned from ControlEngine
2294  // maybe try the call pthread_cond_signal instead for performance
2295  pthread_cond_broadcast(&cond);
2296 
2297  // unlock mutex
2298  status = pthread_mutex_unlock(&wait_mut);
2299  if (status != 0) {
2300 # ifdef __DEBUG
2301  printf("Unlock cond mutex error: %d\n", status);
2302  fflush(stdout);
2303 # endif
2304  createLogMessage(MSG_WARNING,
2305  "Unable to unlock condition mutex for watchdog in issue thread. Execution might eventually be affected.",
2306  0);
2307  }
2308 
2309 // not needed, return 0 is better solution
2310 // pthread_exit(0);
2311  return 0;
2312 }
2313 
2314 
2315 char* createHeader(unsigned int id, short errorCode, bool huffmanFlag,
2316  bool checksumFlag, int checksum) {
2317  char* pHeader = 0;
2318  FlagBits flags = NO_FLAGS;
2319 
2320  if (huffmanFlag) {
2321  //set huffman flag via binary OR
2322  flags |= HUFFMAN_FLAG;
2323  }
2324  if (checksumFlag) {
2325  //set checksum flag via binary OR
2326  flags |= CHECKSUM_FLAG;
2327  }
2328 
2329  pHeader = (char*) malloc(HEADER_SIZE);
2330  if (pHeader == 0) {
2331  //no memory available!
2332 # ifdef __DEBUG
2333  printf("no memory available while trying to create header!\n");
2334  fflush(stdout);
2335 # endif
2336  createLogMessage(MSG_ALARM,
2337  "No more memory available, unable to continue serving - exiting.",
2338  0);
2339  cleanUp();
2340  exit(201);
2341  }
2342 
2343  memcpy(pHeader, &id, HEADER_SIZE_ID);
2344  memcpy(pHeader + HEADER_OFFSET_ID, &errorCode, HEADER_SIZE_ERROR_CODE);
2345  memcpy(pHeader + HEADER_OFFSET_ERROR_CODE, &flags, HEADER_SIZE_FLAGS);
2346  memcpy(pHeader + HEADER_OFFSET_FLAGS, &checksum, HEADER_SIZE_CHECKSUM);
2347 
2348  return pHeader;
2349 }
2350 
2351 
2352 bool checkCommand(char* payload, int size, unsigned int checksum) {
2353  unsigned int payloadChecksum = 0;
2354 
2355  // payload has to contain data, if size is greater than 0,
2356  // and size must not be negative
2357  if (((payload == 0) && (size > 0)) || (size < 0)) {
2358  return false;
2359  }
2360 
2361  payloadChecksum = calculateChecksum((unsigned char*) payload, size);
2362 # ifdef __DEBUG
2363  printf("\nReceived Checksum: \t%x , \nCalculated Checksum: \t%x .\n\n",
2364  checksum, payloadChecksum);
2365  fflush(stdout);
2366 # endif
2367  return (payloadChecksum == checksum) ? true : false;
2368 }
2369 
2370 // ! Problems with signed and unsigned char, make differences in checksum
2371 // -> so USE "unsigned char*" !
2372 unsigned int calculateChecksum(unsigned char* buffer, int size) {
2373  int n;
2374  unsigned int checks = 0;
2375  unsigned long adler = 1L;
2376  unsigned long part1 = adler & 0xffff;
2377  unsigned long part2 = (adler >> 16) & 0xffff;
2378 
2379  // calculates the checksum with the Adler32 algorithm
2380  for (n = 0; n < size; n++) {
2381  part1 = (part1 + buffer[n]) % ADLER_BASE;
2382  part2 = (part2 + part1) % ADLER_BASE;
2383  }
2384  checks = (unsigned int) ((part2 << 16) + part1);
2385 
2386  return checks;
2387 }
2388 
2389 char* marshallHeader(CommandHeader* pHeader) {
2390  char* tempHeader = 0;
2391 
2392  tempHeader = (char*) malloc(HEADER_SIZE);
2393  if (tempHeader == 0) {
2394  //no memory available!
2395 # ifdef __DEBUG
2396  printf("no memory available!\n");
2397  fflush(stdout);
2398 # endif
2399  createLogMessage(MSG_ALARM,
2400  "No more memory available, unable to continue serving - exiting.",
2401  0);
2402  cleanUp();
2403  exit(201);
2404  }
2405 
2406  memcpy(tempHeader, &(pHeader->id), HEADER_SIZE_ID);
2407  memcpy(tempHeader + HEADER_OFFSET_ID, &(pHeader->errorCode), HEADER_SIZE_ERROR_CODE);
2408  memcpy(tempHeader + HEADER_OFFSET_ERROR_CODE, &(pHeader->flags), HEADER_SIZE_FLAGS);
2409  memcpy(tempHeader + HEADER_OFFSET_FLAGS, &(pHeader->checksum), HEADER_SIZE_CHECKSUM);
2410 
2411  return tempHeader;
2412 }
2413 
2414 // *********************************************************************************************
2415 // ---------------- here come all the FeeServer commands ----------------------------------------
2416 // *********************************************************************************************
2417 void updateFeeServer(IssueStruct* issueParam) {
2418 #ifdef ENABLE_MASTERMODE
2419  int status = 0;
2420  int i = 0;
2421  FILE* fp = 0;
2422 
2423  if ((*issueParam).size == 0) {
2424  createLogMessage(MSG_ERROR, "Received new FeeServer with size 0.", 0);
2425  return;
2426  }
2427 # ifdef __DEBUG
2428  printf("Received update command, updating FeeServer now!\n");
2429  fflush(stdout);
2430 # endif
2431  // execute instruction self and release mutex before return
2432  fp = fopen("newFeeserver", "w+b");
2433  if (fp == 0) {
2434  createLogMessage(MSG_ERROR, "Unable to save new FeeServer binary.", 0);
2435  return;
2436  }
2437 
2438  for ( i = 0; i < (*issueParam).size; ++i) {
2439  fputc((*issueParam).command[i], fp);
2440  }
2441  fclose(fp);
2442  createLogMessage(MSG_INFO, "FeeServer updated.", 0);
2443 
2444  // should we call cleanUp() before restart
2445  // better not: another possibility to hang ???
2446  // -> cleanUp is in restart implicit ! except opened drivers
2447  // could only be necessary, if some driver conns have to be closed.
2448  cleanUp();
2449  status = pthread_mutex_unlock(&command_mut);
2450 # ifdef __DEBUG
2451  if (status != 0) {
2452  printf("Unlock FeeCommand mutex error: %d\n", status);
2453  fflush(stdout);
2454  }
2455 # endif
2456 
2457  // Exit status "3" tells the starting script to finalise update and restart
2458  // FeeServer after termination.
2459  exit(3);
2460 #endif //ENABLE_MASTERMODE
2461 }
2462 
2464  triggerRestart(FEE_EXITVAL_RESTART);
2465 }
2466 
2467 void triggerRestart(int exitVal) {
2468  int status = 0;
2469  char msg[80];
2470 
2471 # ifdef __DEBUG
2472  printf("Triggering restart with exit value: %d\n", exitVal);
2473  fflush(stdout);
2474 # endif
2475  msg[sprintf(msg, "Restarting FeeServer - exit value: %d ", exitVal)] = 0;
2476  createLogMessage(MSG_INFO, msg, 0);
2477 
2478  // should we call cleanUp() before restart
2479  // better not: another possibility to hang ???
2480  // -> cleanUp is in restart implicit ! except opened drivers
2481  // could only be necessary, if some driver cons has to be closed.
2482  cleanUp();
2483  status = pthread_mutex_unlock(&command_mut);
2484 # ifdef __DEBUG
2485  if (status != 0) {
2486  printf("Unlock FeeCommand mutex error: %d\n", status);
2487  fflush(stdout);
2488  }
2489 # endif
2490  // Exit status tells the startScript which type of restart is performed
2491  exit(exitVal);
2492 }
2493 
2494 int setDeadband(IssueStruct* issueParam) {
2495  char* itemName = 0;
2496  float newDeadband = 0;
2497  int nameLength = 0;
2498  ItemNode* node = 0;
2499  IntItemNode* intNode = 0;
2500  char msg[100];
2501  unsigned int count = 0;
2502 
2503  if ((*issueParam).size <= sizeof(newDeadband)) {
2504  (*issueParam).size = 0;
2505  createLogMessage(MSG_DEBUG,
2506  "FeeServer command for setting dead band contained invalid parameter.",
2507  0);
2508  return FEE_INVALID_PARAM;
2509  }
2510 
2511  nameLength = (*issueParam).size - sizeof(newDeadband);
2512 
2513  if (nameLength <= 0) {
2514  (*issueParam).size = 0;
2515  createLogMessage(MSG_DEBUG,
2516  "FeeServer command for setting dead band contained no service name.",
2517  0);
2518  return FEE_INVALID_PARAM;
2519  }
2520 
2521  itemName = (char*) malloc(nameLength + 1);
2522  if (itemName == 0) {
2523  (*issueParam).size = 0;
2524  return FEE_INSUFFICIENT_MEMORY;
2525  }
2526 
2527  memcpy(&newDeadband, (*issueParam).command, sizeof(newDeadband));
2528  memcpy(itemName, (*issueParam).command + sizeof(newDeadband), nameLength);
2529  itemName[nameLength] = 0;
2530 
2531  if (itemName[0] != '*') {
2532  // search wanted itemNode
2533  node = findItem(itemName);
2534  if (node == 0) {
2535  //check in IntItemList
2536  intNode = findIntItem(itemName);
2537  }
2538  if ((node == 0) && (intNode == 0)) {
2539  // message is NOT sent in findItem() or findIntItem()
2540  msg[sprintf(msg, "Item %s not found in list.", itemName)] = 0;
2541  createLogMessage(MSG_WARNING, msg, 0);
2542 # ifdef __DEBUG
2543  printf("Item %s not found in list.\n", itemName);
2544  fflush(stdout);
2545 # endif
2546 
2547  free(itemName);
2548  (*issueParam).size = 0;
2549  createLogMessage(MSG_DEBUG,
2550  "FeeServer command for setting dead band contained invalid parameter.",
2551  0);
2552  return FEE_INVALID_PARAM;
2553  } else {
2554  // set new threshold ( = dead band / 2)
2555  if (node != 0) {
2556  node->threshold = newDeadband / 2;
2557  } else {
2558  intNode->threshold = newDeadband / 2;
2559  }
2560 # ifdef __DEBUG
2561  printf("Set deadband on item %s to %f.\n", itemName, newDeadband);
2562  fflush(stdout);
2563 # endif
2564  msg[sprintf(msg, "New dead band (%f) is set for item %s.",
2565  newDeadband, itemName)] = 0;
2566  createLogMessage(MSG_INFO, msg, 0);
2567  }
2568  } else {
2569  // set now for all wanted value the new deadband
2570  count = setDeadbandBroadcast(itemName, newDeadband);
2571 
2572 # ifdef __DEBUG
2573  printf("Set deadband for %d items (%s) to %f.\n", count, itemName, newDeadband);
2574  fflush(stdout);
2575 # endif
2576  msg[sprintf(msg, "New dead band (%f) is set for %d items (%s).",
2577  newDeadband, count, itemName)] = 0;
2578  createLogMessage(MSG_INFO, msg, 0);
2579  }
2580 
2581  free(itemName);
2582  (*issueParam).size = 0;
2583  return FEE_OK;
2584 }
2585 
2586 int getDeadband(IssueStruct* issueParam) {
2587  char* itemName = 0;
2588  int nameLength = 0;
2589  ItemNode* node = 0;
2590  IntItemNode* intNode = 0;
2591  float currentDeadband = 0;
2592  char msg[120];
2593 
2594  if ((*issueParam).size <= 0) {
2595  (*issueParam).size = 0;
2596  createLogMessage(MSG_DEBUG,
2597  "FeeServer command for getting dead band contained invalid parameter.",
2598  0);
2599  return FEE_INVALID_PARAM;
2600  }
2601 
2602  nameLength = (*issueParam).size;
2603  itemName = (char*) malloc(nameLength + 1);
2604  if (itemName == 0) {
2605  (*issueParam).size = 0;
2606  return FEE_INSUFFICIENT_MEMORY;
2607  }
2608 
2609  memcpy(itemName, (*issueParam).command, nameLength);
2610  itemName[nameLength] = 0;
2611 
2612  // search wanted itemNode
2613  node = findItem(itemName);
2614  if (node == 0) {
2615  //check in IntItemList
2616  intNode = findIntItem(itemName);
2617  }
2618  if ((node == 0) && (intNode == 0)) {
2619  // message is NOT sent in findItem() or findIntItem()
2620  msg[sprintf(msg, "Item %s not found in list.", itemName)] = 0;
2621  createLogMessage(MSG_WARNING, msg, 0);
2622 # ifdef __DEBUG
2623  printf("Item %s not found in list.\n", itemName);
2624  fflush(stdout);
2625 # endif
2626 
2627  free(itemName);
2628  (*issueParam).size = 0;
2629  createLogMessage(MSG_DEBUG,
2630  "FeeServer command for getting dead band contained invalid parameter.",
2631  0);
2632  return FEE_INVALID_PARAM;
2633  } else {
2634  (*issueParam).result = (char*) malloc(sizeof(float) + nameLength);
2635  if ((*issueParam).result == 0) {
2636  (*issueParam).size = 0;
2637  return FEE_INSUFFICIENT_MEMORY;
2638  }
2639 
2640  // copy current deadband value to ACK result
2641  if (node != 0) {
2642  currentDeadband = node->threshold * 2.0; // compute deadband
2643  } else {
2644  currentDeadband = intNode->threshold * 2.0; // compute deadband
2645  }
2646 
2647  memcpy((*issueParam).result, &currentDeadband, sizeof(float));
2648  memcpy((*issueParam).result + sizeof(float), itemName, nameLength);
2649  (*issueParam).size = sizeof(float) + nameLength;
2650 # ifdef __DEBUG
2651  printf("Current deadband on item %s is %f.\n", itemName, currentDeadband);
2652  fflush(stdout);
2653 # endif
2654  msg[sprintf(msg, "Current deadband for item %s is %f.", itemName,
2655  currentDeadband)] = 0;
2656  createLogMessage(MSG_DEBUG, msg, 0);
2657  }
2658  free(itemName);
2659  return FEE_OK;
2660 }
2661 
2662 int setIssueTimeout(IssueStruct* issueParam) {
2663  char msg[70];
2664  unsigned long newTimeout;
2665 
2666  if ((*issueParam).size < sizeof(unsigned long)) {
2667  (*issueParam).size = 0;
2668  createLogMessage(MSG_DEBUG,
2669  "FeeServer command for setting issue timeout contained invalid parameter.",
2670  0);
2671  return FEE_INVALID_PARAM;
2672  }
2673  memcpy(&newTimeout, (*issueParam).command, sizeof(unsigned long));
2674 
2675  // check new timeout for possible buffer overflow (value will be multiplied
2676  // with 1000 later -> has to lower than 4294967 )
2677  if (newTimeout > MAX_ISSUE_TIMEOUT) {
2678  (*issueParam).size = 0;
2679  createLogMessage(MSG_WARNING,
2680  "New timeout for issue watchdog exceeded value limit (4294967).",
2681  0);
2682  return FEE_INVALID_PARAM;
2683  }
2684 
2685  issueTimeout = newTimeout;
2686 # ifdef __DEBUG
2687  printf("set new Issue timeout to %lu\n", issueTimeout);
2688  fflush(stdout);
2689 # endif
2690  msg[sprintf(msg, "Watch dog time out is set to %lu.", issueTimeout)] = 0;
2691  createLogMessage(MSG_INFO, msg, 0);
2692 
2693  (*issueParam).size = 0;
2694  return FEE_OK;
2695 }
2696 
2697 int getIssueTimeout(IssueStruct* issueParam) {
2698  char msg[50];
2699 
2700  (*issueParam).result = (char*) malloc(sizeof(unsigned long));
2701  if ((*issueParam).result == 0) {
2702  (*issueParam).size = 0;
2703  return FEE_INSUFFICIENT_MEMORY;
2704  }
2705 
2706  // copy current timeout for issue to ACK result
2707  memcpy((*issueParam).result, &issueTimeout, sizeof(unsigned long));
2708  (*issueParam).size = sizeof(unsigned long);
2709 # ifdef __DEBUG
2710  printf("issue timeout is %lu\n", issueTimeout);
2711  fflush(stdout);
2712 # endif
2713  msg[sprintf(msg, "Issue timeout is %lu.", issueTimeout)] = 0;
2714  createLogMessage(MSG_DEBUG, msg, 0);
2715 
2716  return FEE_OK;
2717 }
2718 
2719 int setUpdateRate(IssueStruct* issueParam) {
2720  char msg[70];
2721  unsigned short newRate;
2722 
2723  if ((*issueParam).size < sizeof(unsigned short)) {
2724  (*issueParam).size = 0;
2725  createLogMessage(MSG_DEBUG,
2726  "FeeServer command for setting update rate contained invalid parameter.",
2727  0);
2728  return FEE_INVALID_PARAM;
2729  }
2730  memcpy(&newRate, (*issueParam).command, sizeof(unsigned short));
2731  updateRate = newRate;
2732  // inform CE about update rate change
2734 # ifdef __DEBUG
2735  printf("set new update rate to %d\n", updateRate);
2736  fflush(stdout);
2737 # endif
2738  msg[sprintf(msg, "New update rate for monitoring items: %d.", updateRate)] = 0;
2739  createLogMessage(MSG_INFO, msg, 0);
2740 
2741  (*issueParam).size = 0;
2742  return FEE_OK;
2743 }
2744 
2745 int getUpdateRate(IssueStruct* issueParam) {
2746  char msg[50];
2747 
2748  (*issueParam).result = (char*) malloc(sizeof(unsigned short));
2749  if ((*issueParam).result == 0) {
2750  (*issueParam).size = 0;
2751  return FEE_INSUFFICIENT_MEMORY;
2752  }
2753 
2754  // copy current update rate to ACK result
2755  memcpy((*issueParam).result, &updateRate, sizeof(unsigned short));
2756  (*issueParam).size = sizeof(unsigned short);
2757 # ifdef __DEBUG
2758  printf("update rate is %d\n", updateRate);
2759  fflush(stdout);
2760 # endif
2761  msg[sprintf(msg, "Monitoring update rate is %d.", updateRate)] = 0;
2762  createLogMessage(MSG_DEBUG, msg, 0);
2763 
2764  return FEE_OK;
2765 }
2766 
2767 // be aware of different size of unsigned int in heterogen systems !!
2768 int setLogLevel(IssueStruct* issueParam) {
2769  int status = -1;
2770  char msg[70];
2771  unsigned int testLogLevel = 0;
2772 
2773  if ((*issueParam).size < sizeof(unsigned int)) {
2774  (*issueParam).size = 0;
2775  createLogMessage(MSG_DEBUG,
2776  "FeeServer command for setting log level contained invalid parameter.",
2777  0);
2778  return FEE_INVALID_PARAM;
2779  }
2780  memcpy(&testLogLevel, (*issueParam).command, sizeof(unsigned int));
2781  // check loglevel for valid data
2782  if (testLogLevel > MSG_MAX_VAL) {
2783 # ifdef __DEBUG
2784  printf("received invalid log level %d\n", testLogLevel);
2785  fflush(stdout);
2786 # endif
2787  createLogMessage(MSG_DEBUG,
2788  "FeeServer command for setting log level contained invalid parameter.",
2789  0);
2790  return FEE_INVALID_PARAM;
2791  }
2792 
2793  status = pthread_mutex_lock(&log_mut);
2794  // discard eventual error
2795  if (status != 0) {
2796 # ifdef __DEBUG
2797  printf("Lock log mutex error: %d\n", status);
2798  fflush(stdout);
2799 # endif
2800  (*issueParam).size = 0;
2801  return FEE_FAILED;
2802  } else {
2803  logLevel = testLogLevel | MSG_ALARM;
2804 
2805  status = pthread_mutex_unlock(&log_mut);
2806  if (status != 0) {
2807 # ifdef __DEBUG
2808  printf("Unlock log mutex error: %d\n", status);
2809  fflush(stdout);
2810 # endif
2811  createLogMessage(MSG_WARNING, "Unable to unlock logger mutex.", 0);
2812  }
2813 
2814 # ifdef __DEBUG
2815  printf("set new logLevel to %d\n", logLevel);
2816  fflush(stdout);
2817 # endif
2818  msg[sprintf(msg, "New log level on FeeServer: %d.", logLevel)] = 0;
2819  createLogMessage(MSG_INFO, msg, 0);
2820 
2821  (*issueParam).size = 0;
2822  return FEE_OK;
2823  }
2824 }
2825 
2826 int getLogLevel(IssueStruct* issueParam) {
2827  char msg[50];
2828 
2829  (*issueParam).result = (char*) malloc(sizeof(unsigned int));
2830  if ((*issueParam).result == 0) {
2831  (*issueParam).size = 0;
2832  return FEE_INSUFFICIENT_MEMORY;
2833  }
2834 
2835  // copy current update rate to ACK result
2836  memcpy((*issueParam).result, &logLevel, sizeof(unsigned int));
2837  (*issueParam).size = sizeof(unsigned int);
2838 # ifdef __DEBUG
2839  printf("Requested loglevel is %d\n", logLevel);
2840  fflush(stdout);
2841 # endif
2842  msg[sprintf(msg, "Requested LogLevel is %d.", logLevel)] = 0;
2843  createLogMessage(MSG_DEBUG, msg, 0);
2844 
2845  return FEE_OK;
2846 }
2847 
2849  FeeProperty feeProp;
2850  if ((ceInitState == CE_OK) && ((nodesAmount > 0) || (intNodesAmount > 0))) {
2851  feeProp.flag = PROPERTY_UPDATE_RATE;
2852  feeProp.uShortVal = updateRate;
2853  signalFeePropertyChanged(&feeProp);
2854  }
2855 }
2856 
2857 
2858 unsigned int setDeadbandBroadcast(char* name, float newDeadbandBC) {
2859  unsigned int count = 0;
2860  ItemNode* current = 0;
2861  IntItemNode* intCurrent = 0;
2862  char* namePart = 0;
2863  char* itemNamePart = 0;
2864 
2865  if (name == 0) {
2866  return count;
2867  }
2868 
2869  // pointer at first occurance of "_"
2870  namePart = strpbrk(name, "_");
2871  if (namePart == 0) {
2872  return count;
2873  }
2874 
2875  // go through list of float values
2876  current = firstNode;
2877  while (current != 0) { // is end of list
2878  // pointer at first occurance of "_"
2879  itemNamePart = strpbrk(current->item->name, "_");
2880  // check if "_" not first character in name and is existing
2881  if ((itemNamePart == 0) || (itemNamePart == current->item->name)) {
2882  current = current->next;
2883  continue;
2884  }
2885  if (strcmp(namePart, itemNamePart) == 0) {
2886  // success, set threshold (= deadband / 2)
2887  current->threshold = newDeadbandBC / 2;
2888  ++count;
2889  }
2890  current = current->next;
2891  }
2892 
2893  // go through list of integer values
2894  intCurrent = firstIntNode;
2895  while (intCurrent != 0) { // is end of list
2896  // pointer at first occurance of "_"
2897  itemNamePart = strpbrk(intCurrent->intItem->name, "_");
2898  // check if "_" not first character in name and is existing
2899  if ((itemNamePart == 0) || (itemNamePart == intCurrent->intItem->name)) {
2900  intCurrent = intCurrent->next;
2901  continue;
2902  }
2903  if (strcmp(namePart, itemNamePart) == 0) {
2904  // success, set threshold (= deadband / 2)
2905  intCurrent->threshold = newDeadbandBC / 2;
2906  ++count;
2907  }
2908  intCurrent = intCurrent->next;
2909  }
2910 
2911  return count;
2912 }
2913 
2914 int updateFeeService(char* serviceName) {
2915  char msg[80];
2916  ItemNode* node = 0;
2917  IntItemNode* intNode = 0;
2918  CharItemNode* charNode = 0;
2919  int nRet = 0;
2920 # ifdef __DEBUG
2921  char* addr = 0;
2922  char* data = 0;
2923  int size = 0;
2924 # endif
2925 
2926  if (state != RUNNING) {
2927  return FEE_WRONG_STATE;
2928  }
2929  if (serviceName == 0) {
2930  return FEE_NULLPOINTER;
2931  }
2932 
2933  // find desired service
2934  node = findItem(serviceName);
2935  if (node == 0) {
2936  //check in IntItemList
2937  intNode = findIntItem(serviceName);
2938  }
2939  if ((node == 0) || (intNode == 0)) {
2940  //check in CharItemList
2941  charNode = findCharItem(serviceName);
2942  }
2943 
2944  // check node
2945  if ((node == 0) && (intNode == 0) && (charNode == 0)) {
2946  // message is NOT sent in findItem(), findIntItem() or findCharItem()
2947  msg[sprintf(msg, "Item %s not found in list.", serviceName)] = 0;
2948  createLogMessage(MSG_WARNING, msg, 0);
2949 # ifdef __DEBUG
2950  printf("Item %s not found in list.\n", serviceName);
2951  fflush(stdout);
2952 # endif
2953  return FEE_INVALID_PARAM;
2954  } else {
2955  if (node != 0) {
2956  nRet = dis_update_service(node->id);
2957 # ifdef __DEBUG
2958 /* printf("CE triggered an updated on %d clients for service %s [float]: %f\n", */
2959 /* nRet, node->item->name, *(node->item->location)); */
2960 /* fflush(stdout); */
2961 # endif
2962  } else if (intNode != 0) {
2963  nRet = dis_update_service(intNode->id);
2964 # ifdef __DEBUG
2965 /* printf("CE triggered an updated on %d clients for service %s [int]: %d\n", */
2966 /* nRet, intNode->intItem->name, *(intNode->intItem->location)); */
2967 /* fflush(stdout); */
2968 # endif
2969  } else {
2970  nRet = dis_update_service(charNode->id);
2971 # ifdef __DEBUG
2972  (charNode->charItem->user_routine)(&(charNode->charItem->tag),
2973  (int**) &addr, &size);
2974  data = (char*) malloc(size +1);
2975  strncpy(data, addr, size);
2976  data[size] = 0;
2977 /* printf("CE triggered an updated on %d clients for service %s [char]: %s\n", */
2978 /* nRet, charNode->charItem->name, data); */
2979 /* fflush(stdout); */
2980  free(data);
2981 # endif
2982  }
2983  }
2984 
2985  // return number of updated clients
2986  return nRet;
2987 }
2988 
2989 
2990 // *********************************************************************************************
2991 // ---------- here comes all the initialisation of selfdefined datatypes -----------------------
2992 // *********************************************************************************************
2993 void initIssueStruct(IssueStruct* issueStr) {
2994  issueStr->nRet = 0;
2995  issueStr->command = 0;
2996  issueStr->result = 0;
2997  issueStr->size = 0;
2998 }
2999 
3001  time_t timeVal;
3002  struct tm* now;
3003 
3004  // fill the original message struct
3005  message.eventType = MSG_INFO;
3006  memcpy(message.detector, LOCAL_DETECTOR, MSG_DETECTOR_SIZE);
3007  memcpy(message.source, "FeeServer\0", 10);
3008  message.description[sprintf(message.description,
3009  "FeeServer %s (Version: %s) has been initialized (DNS: %s) ...",
3010  serverName, FEESERVER_VERSION, getenv("DIM_DNS_NODE"))] = 0;
3011  //set current date and time
3012  time(&timeVal);
3013  now = localtime(&timeVal);
3014  message.date[strftime(message.date, MSG_DATE_SIZE, "%Y-%m-%d %H:%M:%S",
3015  now)] = 0;
3016 
3017  // the the storage of the "last Message" struct - must be different in
3018  // the description compared to the original message struct above in init
3019  lastMessage.eventType = MSG_DEBUG;
3020  memcpy(lastMessage.detector, LOCAL_DETECTOR, MSG_DETECTOR_SIZE);
3021  memcpy(lastMessage.source, "FeeServer\0", 10);
3022  // now use a different description:
3023  lastMessage.description[sprintf(lastMessage.description,
3024  "Init of Backup Message Struct!")] = 0;
3025  //set current date and time
3026  time(&timeVal);
3027  now = localtime(&timeVal);
3028  lastMessage.date[strftime(lastMessage.date, MSG_DATE_SIZE,
3029  "%Y-%m-%d %H:%M:%S", now)] = 0;
3030 }
3031 
3032 
3033 void initItemNode(ItemNode* iNode) {
3034  iNode->prev = 0;
3035  iNode->next = 0;
3036  iNode->id = 0;
3037  iNode->item = 0;
3038  iNode->lastTransmittedValue = 0.0;
3039  iNode->threshold = 0.0;
3040  iNode->locBackup = 0;
3041  iNode->checksum = 0;
3042  iNode->checksumBackup = 0;
3043 }
3044 
3045 ItemNode* findItem(char* name) {
3046 // char msg[70];
3047  ItemNode* current = 0;
3048 
3049  if (name == 0) {
3050  return 0;
3051  }
3052  current = firstNode;
3053  while (current != 0) { // is end of list
3054  if (strcmp(name, current->item->name) == 0) {
3055  // success, give back itemNode
3056  return current;
3057  }
3058  current = current->next;
3059  }
3060 // since two lists, which are searched seperately don't make log output in
3061 // findItem()-function -> move to where called to combine with other
3062 // findXYItem calls
3063 /*
3064  if (state == RUNNING) {
3065  msg[sprintf(msg, "Item %s not found in list.", name)] = 0;
3066  createLogMessage(MSG_WARNING, msg, 0);
3067 # ifdef __DEBUG
3068  printf("Item %s not found in list.\n", name);
3069  fflush(stdout);
3070 # endif
3071  }
3072 */
3073  return 0;
3074 }
3075 
3077  ItemNode* current = 0;
3078 
3079  current = firstNode;
3080  while (current != 0) {
3081  dis_remove_service(current->id);
3082  current = current->next;
3083  }
3084  // pretending ItemList is completely empty to avoid access
3085  // to not existing elements
3086  nodesAmount = 0;
3087  firstNode = 0;
3088  lastNode = 0;
3089 }
3090 
3091 // ****************************************************************************
3092 // ------------------ here come all the closing and cleanup functions ---------
3093 // ****************************************************************************
3094 void interrupt_handler(int sig) {
3095 // *** causes props on DCS board -> not used yet ***
3096 # ifdef __DEBUG
3097  printf("Received interrupt: %d, exiting now.\n", sig);
3098  fflush(stdout);
3099 # endif
3100 
3101  if ((state == RUNNING) || (state == ERROR_STATE)) {
3102  fee_exit_handler(0);
3103  } else {
3104  cleanUp();
3105  exit(0);
3106  }
3107 }
3108 
3109 void fee_exit_handler(unsigned int state) {
3110  char msg[70];
3111 
3112 # ifdef __DEBUG
3113  printf("Exit state: %d\n\n", state);
3114  fflush(stdout);
3115 # endif
3116  msg[sprintf(msg, "Exiting FeeServer (exit state: %d).", state)] = 0;
3117  createLogMessage(MSG_INFO, msg, 0);
3118 
3119  cleanUp();
3120  exit(state);
3121 }
3122 
3123 void dim_dummy_exit_handler(int* bufp) {
3124  char msg[200];
3125  char clientName[50];
3126  int dummy = 0;
3127 
3128  // if bufp null pointer, redirect to valid value
3129  if (bufp == 0) {
3130  bufp = &dummy;
3131  }
3132 
3133  // DO almost nothing, just to disable the build-in exit command of the DIM framework
3134  // just notifying about intrusion, except for framework exit
3135  clientName[0] = 0;
3136  dis_get_client(clientName);
3137  // let's asume exit from ambitious user has clientName (pid@host).
3138  if (clientName[0] == 0) {
3139 # ifdef __DEBUG
3140  printf("Framework tries to exit FeeServer (%d)\n", *bufp);
3141  printf("Most likely FeeServer name already exists.\n");
3142  fflush(stdout);
3143 # endif
3144  // IMPORTANT don't use the bufp - state of framework, it could interfere
3145  // with own specified exit states !! (e.g. for restarting in case of "2")
3146  // the same state is signaled by kill all servers of dns !?
3147  fee_exit_handler(204);
3148  } else {
3149  msg[sprintf(msg, "Ambitious user (%s) tried to kill FeeServer, ignoring command!",
3150  clientName)] = 0;
3151  createLogMessage(MSG_WARNING, msg, 0);
3152 # ifdef __DEBUG
3153  printf("Ambitious user (%s) tried to kill FeeServer (%d)\n", clientName, *bufp);
3154  fflush(stdout);
3155 # endif
3156  }
3157 }
3158 
3159 void cleanUp() {
3160  // the order of the clean up sequence here is important to evade seg faults
3161 # ifdef __DEBUG
3162  printf("Cleaning up FeeServer before finishing:\n");
3163  fflush(stdout);
3164 # endif
3165  if (ceInitState == CE_OK) {
3166  cleanUpCE();
3167 # ifdef __DEBUG
3168  printf(" - Clean up of CE finished\n");
3169  fflush(stdout);
3170 # endif
3171  }
3172 
3173  if (monitorThreadStarted) {
3174  pthread_cancel(thread_mon);
3175  }
3176  if (intMonitorThreadStarted) {
3177  pthread_cancel(thread_mon_int);
3178  }
3179  if (state == RUNNING) {
3180  pthread_cancel(thread_init);
3181  }
3182  if (logWatchDogRunning) {
3183  pthread_cancel(thread_logWatchdog);
3184  }
3185 # ifdef __DEBUG
3186  printf(" - All threads except for main thread killed\n");
3187  fflush(stdout);
3188 # endif
3189 
3190  dis_stop_serving();
3191 # ifdef __DEBUG
3192  printf(" - DIM server stopped\n");
3193  fflush(stdout);
3194 # endif
3195 
3196  deleteItemList();
3197  // new since version 0.8.1 -> int channels
3199  // new since version 0.8.2b -> char channels
3201 
3202  if (cmndACK != 0) {
3203  free(cmndACK);
3204  }
3205  if (serverName != 0) {
3206  free(serverName);
3207  }
3208 
3209  // new since 0.8.3 -> memory list
3210  //cleanupMemoryList();
3211 # ifdef __DEBUG
3212  printf(" - Memory freed (lists and globaly allocated)\n");
3213  fflush(stdout);
3214 # endif
3215 }
3216 
3218  ItemNode* tmp = 0;
3219 
3220  while (firstNode != 0) {
3221  if (firstNode->item != 0) {
3222  if (firstNode->item->name != 0) {
3223  free(firstNode->item->name);
3224  }
3225  free(firstNode->item);
3226  }
3227 
3228  tmp = firstNode->next;
3229  free(firstNode);
3230  firstNode = tmp;
3231  }
3232  return FEE_OK;
3233 }
3234 
3235 /*
3236 MessageStruct copyMessage(const MessageStruct* const orgMsg) {
3237  MessageStruct msg;
3238  msg.eventType = orgMsg->eventType;
3239  memcpy(msg.detector, orgMsg->detector, MSG_DETECTOR_SIZE);
3240  memcpy(msg.source, orgMsg->source, MSG_SOURCE_SIZE);
3241  memcpy(msg.description, orgMsg->description, MSG_DESCRIPTION_SIZE);
3242  memcpy(msg.date, orgMsg->date, MSG_DATE_SIZE);
3243  return msg;
3244 }
3245 */
3246 
3248 
3249 int publishInt(IntItem* intItem) {
3250  unsigned int id;
3251  char* serviceName = 0;
3252 
3253  // check for right state
3254  if (state != COLLECTING) {
3255  return FEE_WRONG_STATE;
3256  }
3257 
3258  // Testing for NULL - Pointer
3259  // !! Attention: if pointer is not initialized and also NOT set to NULL, this won't help !!
3260  if (intItem == 0) {
3261 # ifdef __DEBUG
3262  printf("Bad intItem, not published\n");
3263  fflush(stdout);
3264 # endif
3265  return FEE_NULLPOINTER;
3266  }
3267  if (intItem->name == 0 || intItem->location == 0) {
3268 # ifdef __DEBUG
3269  printf("Bad intItem, not published\n");
3270  fflush(stdout);
3271 # endif
3272  return FEE_NULLPOINTER;
3273  }
3274 
3275  // Check name for duplicate here
3276  // Check in Float list
3277  if (findItem(intItem->name) != 0) {
3278 # ifdef __DEBUG
3279  printf("Item name already published in float list, int item discarded.\n");
3280  fflush(stdout);
3281 # endif
3282  return FEE_ITEM_NAME_EXISTS;
3283  }
3284  // Check in INT list
3285  if (findIntItem(intItem->name) != 0) {
3286 # ifdef __DEBUG
3287  printf("Item name already published in int list, new int item discarded.\n");
3288  fflush(stdout);
3289 # endif
3290  return FEE_ITEM_NAME_EXISTS;
3291  }
3292  // Check in Char service list
3293  if (findCharItem(intItem->name) != 0) {
3294 # ifdef __DEBUG
3295  printf("Item name already published in char list, int item discarded.\n");
3296  fflush(stdout);
3297 # endif
3298  return FEE_ITEM_NAME_EXISTS;
3299  }
3300 
3301 
3302  // -- add intItem as service --
3303  serviceName = (char*) malloc(serverNameLength + strlen(intItem->name) + 2);
3304  if (serviceName == 0) {
3305  return FEE_INSUFFICIENT_MEMORY;
3306  }
3307  // terminate string with '\0'
3308  serviceName[sprintf(serviceName, "%s_%s", serverName, intItem->name)] = 0;
3309  id = dis_add_service(serviceName, "I", (int*) intItem->location,
3310  sizeof(int), 0, 0);
3311  free(serviceName);
3312  add_int_item_node(id, intItem);
3313 
3314  return FEE_OK;
3315 }
3316 
3317 void add_int_item_node(unsigned int _id, IntItem* _int_item) {
3318  //create new node with enough memory
3319  IntItemNode* newNode = 0;
3320 
3321  newNode = (IntItemNode*) malloc(sizeof(IntItemNode));
3322  if (newNode == 0) {
3323  //no memory available!
3324 # ifdef __DEBUG
3325  printf("no memory available while adding IntItemNode!\n");
3326  fflush(stdout);
3327 # endif
3328  cleanUp();
3329  exit(201);
3330  }
3331  //initialize "members" of node
3332  newNode->prev = 0;
3333  newNode->next = 0;
3334  newNode->id = _id;
3335  newNode->intItem = _int_item;
3336  newNode->lastTransmittedIntValue = *(_int_item->location);
3337  //if default deadband is negative -> set threshold 0, otherwise set half of defaultDeadband
3338  newNode->threshold = (_int_item->defaultDeadband < 0) ? 0.0 : (_int_item->defaultDeadband / 2);
3339 
3340  newNode->locBackup = _int_item->location;
3341 
3342  // Check if these feature have to be ported as well ??? !!!
3343 // newNode->checksum = calculateChecksum((unsigned char*) &(_item->location),
3344 // sizeof(volatile float*));
3345 // newNode->checksumBackup = newNode->checksum;
3346 
3347 #ifdef __DEBUG
3348  // complete debug display of added IntItem
3349 /*
3350  printf("IntItem: %d\n", _id);
3351  printf("location: %f, locBackup %f\n", *(_int_item->location), *(newNode->locBackup));
3352  printf("location addr: %p, locBackup addr %p\n", _int_item->location, newNode->locBackup);
3353  printf("checksum1: %d, checksum2: %d\n\n", newNode->checksum,
3354  newNode->checksumBackup);
3355 */
3356 #endif
3357 
3358 # ifdef __DEBUG
3359  // short debug display of added Item
3360  printf("init of %s (int) with ID %d: %d\n", newNode->intItem->name,
3361  newNode->id, newNode->lastTransmittedIntValue);
3362  fflush(stdout);
3363 # endif
3364 
3365  ++intNodesAmount;
3366  //redirect pointers of doubly linked list (int)
3367  if (firstIntNode != 0) {
3368  lastIntNode->next = newNode;
3369  newNode->prev = lastIntNode;
3370  lastIntNode = newNode;
3371  } else {
3372  firstIntNode = newNode;
3373  lastIntNode = newNode;
3374  }
3375 }
3376 
3377 
3378 IntItemNode* findIntItem(char* name) {
3379 // char msg[70];
3380  IntItemNode* current = 0;
3381 
3382  if (name == 0) {
3383  return 0;
3384  }
3385  current = firstIntNode;
3386  while (current != 0) { // is end of list
3387  if (strcmp(name, current->intItem->name) == 0) {
3388  // success, give back IntItemNode
3389  return current;
3390  }
3391  current = current->next;
3392  }
3393 // since two lists, which are searched seperately don't make log output in
3394 // findIntItem()-function -> move to where called to combine with other
3395 // findXYItem calls
3396 /*
3397  if (state == RUNNING) {
3398  msg[sprintf(msg, "Item %s not found in IntItem list.", name)] = 0;
3399  createLogMessage(MSG_WARNING, msg, 0);
3400 # ifdef __DEBUG
3401  printf("Item %s not found in IntItem list.\n", name);
3402  fflush(stdout);
3403 # endif
3404  }
3405 */
3406  return 0;
3407 }
3408 
3410  IntItemNode* tmp = 0;
3411 
3412  while (firstIntNode != 0) {
3413  if (firstIntNode->intItem != 0) {
3414  if (firstIntNode->intItem->name != 0) {
3415  free(firstIntNode->intItem->name);
3416  }
3417  free(firstIntNode->intItem);
3418  }
3419 
3420  tmp = firstIntNode->next;
3421  free(firstIntNode);
3422  firstIntNode = tmp;
3423  }
3424  return FEE_OK;
3425 }
3426 
3427 void initIntItemNode(IntItemNode* intItemNode) {
3428  intItemNode->prev = 0;
3429  intItemNode->next = 0;
3430  intItemNode->id = 0;
3431  intItemNode->intItem = 0;
3432  intItemNode->lastTransmittedIntValue = 0;
3433  intItemNode->threshold = 0.0;
3434  intItemNode->locBackup = 0;
3435  intItemNode->checksum = 0;
3436  intItemNode->checksumBackup = 0;
3437 }
3438 
3440  IntItemNode* current = 0;
3441 
3442  current = firstIntNode;
3443  while (current != 0) {
3444  dis_remove_service(current->id);
3445  current = current->next;
3446  }
3447  // pretending ItemList is completely empty to avoid access
3448  // to not existing elements
3449  intNodesAmount = 0;
3450  firstIntNode = 0;
3451  lastIntNode = 0;
3452 }
3453 
3454 Item* createItem() {
3455  Item* item = 0;
3456 
3457  item = (Item*) malloc(sizeof(Item));
3458  if (item == 0) {
3459  //no memory available!
3460 # ifdef __DEBUG
3461  printf("no memory available!\n");
3462 # endif
3463  return 0;
3464  }
3465  item->location = 0;
3466  item->name = 0;
3467  item->defaultDeadband = 0;
3468  return item;
3469 }
3470 
3471 IntItem* createIntItem() {
3472  IntItem* intItem = 0;
3473 
3474  intItem = (IntItem*) malloc(sizeof(IntItem));
3475  if (intItem == 0) {
3476  //no memory available!
3477 # ifdef __DEBUG
3478  printf("no memory available!\n");
3479 # endif
3480  return 0;
3481  }
3482  intItem->location = 0;
3483  intItem->name = 0;
3484  intItem->defaultDeadband = 0;
3485  return intItem;
3486 }
3487 
3488 Item* fillItem(float* floatLocation, char* itemName, float defDeadband) {
3489  Item* item = 0;
3490 
3491  item = createItem();
3492  if (item == 0) {
3493  //no memory available!
3494 # ifdef __DEBUG
3495  printf("no memory available!\n");
3496 # endif
3497  return 0;
3498  }
3499  item->location = floatLocation;
3500  item->name = (char*) malloc(strlen(itemName) + 1);
3501  if (item->name == 0) {
3502  //no memory available!
3503 # ifdef __DEBUG
3504  printf("no memory available!\n");
3505 # endif
3506  free(item);
3507  return 0;
3508  }
3509  strcpy(item->name, itemName);
3510  item->defaultDeadband = defDeadband;
3511  return item;
3512 }
3513 
3514 IntItem* fillIntItem(int* intLocation, char* itemName, int defDeadband) {
3515  IntItem* intItem = 0;
3516 
3517  intItem = createIntItem();
3518  if (intItem == 0) {
3519  //no memory available!
3520 # ifdef __DEBUG
3521  printf("no memory available!\n");
3522 # endif
3523  return 0;
3524  }
3525  intItem->location = intLocation;
3526  intItem->name = (char*) malloc(strlen(itemName) + 1);
3527  if (intItem->name == 0) {
3528  //no memory available!
3529 # ifdef __DEBUG
3530  printf("no memory available!\n");
3531 # endif
3532  free(intItem);
3533  return 0;
3534  }
3535  strcpy(intItem->name, itemName);
3536  intItem->defaultDeadband = defDeadband;
3537  return intItem;
3538 }
3539 
3541  int status = -1;
3542  int nRet;
3543  unsigned long sleepTime = 0;
3544  IntItemNode* current = 0;
3545  char msg[120];
3546  unsigned long innerCounter = 0; // used for update check after time interval
3547  unsigned long outerCounter = 0; // used for update check after time interval
3548 
3549  // set flag, that monitor thread has been started
3550  intMonitorThreadStarted = true;
3551 
3552  // set cancelation type
3553  status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
3554  if (status != 0) {
3555 # ifdef __DEBUG
3556  printf("Set cancel state error [mon - int]: %d\n", status);
3557  fflush(stdout);
3558 # endif
3559  createLogMessage(MSG_WARNING,
3560  "Unable to configure monitor thread (int) properly. Monitoring is not affected.", 0);
3561  }
3562  status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
3563  if (status != 0) {
3564 # ifdef __DEBUG
3565  printf("Set cancel type error [mon - int]: %d\n", status);
3566  fflush(stdout);
3567 # endif
3568  createLogMessage(MSG_WARNING,
3569  "Unable to configure monitor thread (int) properly. Monitoring is not affected.", 0);
3570  }
3571 
3572  createLogMessage(MSG_DEBUG, "Started monitor thread for INT values successfully.", 0);
3573 
3574  while (1) {
3575  current = firstIntNode;
3576  sleepTime = (unsigned long) (updateRate / intNodesAmount);
3577  while (current != 0) { // is lastIntNode->next (end of list)
3578  if (!checkIntLocation(current)) {
3579  msg[sprintf(msg, "Value of item %s (int) is corrupt, reconstruction failed. Ignoring!",
3580  current->intItem->name)] = 0;
3581  createLogMessage(MSG_ERROR, msg, 0);
3582  // message and do some stuff (like invalidate value)
3583  // (test, what happens if pointer is redirected ???)
3584  } else {
3585  if ((abs((*(current->intItem->location)) - current->lastTransmittedIntValue)
3586  >= current->threshold) || (outerCounter ==
3587  (innerCounter * TIME_INTERVAL_MULTIPLIER))) {
3588  nRet = dis_update_service(current->id);
3589  current->lastTransmittedIntValue = *(current->intItem->location);
3590 # ifdef __DEBUG
3591  printf("CE triggered an updated on %d clients for service %s [int]: %d\n",
3592  nRet, current->intItem->name, *(current->intItem->location));
3593  fflush(stdout);
3594 # endif
3595  }
3596  }
3597 
3598  ++innerCounter;
3599  current = current->next;
3600  usleep(sleepTime * 1000);
3601  // sleeps xy microseconds, needed milliseconds-> "* 1000"
3602  }
3603  // with the check of both counter, each service is at least updated after
3604  // every (deadband updateRate * nodesAmount) seconds
3605  innerCounter = 0;
3606  ++outerCounter;
3607  // after every service in list is updated set counter back to 0
3608  // the TIME_INTERVAL_MULTIPLIER is used to enlarge the time interval of
3609  // the request of services without touching the deadband checker updateRate
3610  if (outerCounter >= (intNodesAmount * TIME_INTERVAL_MULTIPLIER)) {
3611  outerCounter = 0;
3612  }
3613  }
3614  // should never be reached !
3615  pthread_exit(0);
3616 }
3617 
3618 // checks against bitflips in location (integer Item)
3619 bool checkIntLocation(IntItemNode* node) {
3620  if (node->intItem->location == node->locBackup) {
3621  // locations are identical, so no bitflip
3622  return true;
3623  }
3624  // locations are not identical, check further
3625 
3626  if (node->checksum == calculateChecksum((unsigned char*)
3627  &(node->intItem->location), sizeof(volatile int*))) {
3628  // checksum tells, that first location should be valid, repair backup
3629  node->locBackup = node->intItem->location;
3630  return true;
3631  }
3632  // original location or first checksum is wrong, continue checking
3633 
3634  if (node->checksum == calculateChecksum((unsigned char*)
3635  &(node->locBackup), sizeof(volatile int*))) {
3636  // checksum tells, that location backup should be valid, repair original
3637  node->intItem->location = node->locBackup;
3638  return true;
3639  }
3640  // location backup or first checksum is wrong, continue checking
3641 
3642  if (node->checksum == node->checksumBackup) {
3643  // it seems that location and location backup are wrong
3644  // or checksum value runs banana, not repairable
3645  return false;
3646  }
3647  // it seems that first checksum is wrong
3648  // try to fix with second checksum
3649 
3650  if (node->checksumBackup == calculateChecksum((unsigned char*)
3651  &(node->intItem->location), sizeof(volatile int*))) {
3652  // checksum backup tells, that first location should be valid, repair backup
3653  node->locBackup = node->intItem->location;
3654  // repair first checksum
3655  node->checksum = node->checksumBackup;
3656  return true;
3657  }
3658  // original location or second checksum is wrong, continue checking
3659 
3660  if (node->checksumBackup == calculateChecksum((unsigned char*)
3661  &(node->locBackup), sizeof(volatile int*))) {
3662  // checksum backup tells, that location backup should be valid, repair original
3663  node->intItem->location = node->locBackup;
3664  // repair checksum
3665  node->checksum = node->checksumBackup;
3666  return true;
3667  }
3668  // value is totally banana, no chance to fix
3669  return false;
3670 }
3671 
3672 // --- Wrapper for the Float Items --- //
3673 
3674 int publishFloat(FloatItem* floatItem) {
3675  return publish(floatItem);
3676 }
3677 
3678 
3679 FloatItem* createFloatItem() {
3680  return createItem();
3681 }
3682 
3683 
3684 FloatItem* fillFloatItem(float* floatLocation, char* itemName, float defDeadband) {
3685  return fillItem(floatLocation, itemName, defDeadband);
3686 }
3687 
3688 
3690 
3691 MemoryNode* findMemoryNode(void* addr) {
3692  MemoryNode* current = 0;
3693 
3694  if (addr == 0) {
3695  /*
3696  createLogMessage(MSG_WARNING,
3697  "Reqesting MemoryNode with ID \"NULL\", discarding call!", 0);
3698 # ifdef __DEBUG
3699  printf("Reqesting MemoryNode with ID \"NULL\", discarding call!\n");
3700  fflush(stdout);
3701 # endif
3702  */
3703  return 0;
3704  }
3705 
3706  current = firstMemoryNode;
3707  while (current != 0) { // is end of list
3708  if (current->identityAddr == addr) {
3709  // success, give back MemoryNode
3710  return current;
3711  }
3712  current = current->next;
3713  }
3714 
3715 /* // only used for debug output; comment it in if required
3716  if (current == 0) {
3717  char msg[80];
3718  msg[sprintf(msg, "Unable to find MemoryNode with ID \"%p\".",
3719  addr)] = 0;
3720  createLogMessage(MSG_DEBUG, msg, 0);
3721 # ifdef __DEBUG
3722  printf("Unable to find MemoryNode with ID \"%p\".\n", addr);
3723  fflush(stdout);
3724 # endif
3725  }
3726 */
3727 
3728  return 0;
3729 }
3730 
3731 
3732 MemoryNode* createMemoryNode(unsigned int size, char type, char* module,
3733  unsigned int preSize) {
3734 
3735  // check, if size is greater then preSize
3736  if (size <= preSize) {
3737  createLogMessage(MSG_ERROR,
3738  "Error: asking for memory smaller or equal than its prefix size.",
3739  0);
3740 # ifdef __DEBUG
3741  printf("Error: asking for memory smaller or equal than its prefix size.\n");
3742  fflush(stdout);
3743 # endif
3744  return 0;
3745  }
3746 
3747  MemoryNode* memNode = (MemoryNode*) malloc(sizeof(MemoryNode));
3748  if (memNode == 0) {
3749  // insufficient memory
3750  createLogMessage(MSG_ERROR,
3751  "Insufficient memory! Unable to allocate memory for MemoryNode.",
3752  0);
3753 # ifdef __DEBUG
3754  printf("Insufficient memory! Unable to allocate memory for MemoryNode.\n");
3755  fflush(stdout);
3756 # endif
3757  }
3758 
3759  // fill MemoryNode
3760  void* ptr = (void*) malloc(size);
3761  if (ptr == 0) {
3762  // insufficient memory
3763  char msg[100];
3764  msg[sprintf(msg,
3765  "Insufficient memory! Unable to allocate memory block of %d .",
3766  size)] = 0;
3767  createLogMessage(MSG_ERROR, msg, 0);
3768 # ifdef __DEBUG
3769  printf("Insufficient memory! Unable to allocate memory block of %d .\n",
3770  size);
3771  fflush(stdout);
3772 # endif
3773 
3774  free(memNode);
3775  return 0;
3776  }
3777 
3778  memNode->ptr = ptr;
3779  memNode->identityAddr = ptr + preSize;
3780  memNode->mmData.memSize = size;
3781  memNode->mmData.memType = type;
3782  if (module != 0) {
3783  strncpy(memNode->mmData.memDest, module, 30);
3784  memNode->mmData.memDest[29] = 0;
3785  } else {
3786  memNode->mmData.memDest[0] = 0;
3787  }
3788  if (preSize > 0) {
3789  memNode->mmData.prefixed = true;
3790  } else {
3791  memNode->mmData.prefixed = false;
3792  }
3793  memNode->mmData.prefixSize = preSize;
3794 
3795  // add Node to list (add at end)
3796  memNode->prev = lastMemoryNode;
3797  memNode->next = 0;
3798 
3799  if (lastMemoryNode != 0) {
3800  lastMemoryNode->next = memNode;
3801  }
3802  lastMemoryNode = memNode;
3803 
3804  if (firstMemoryNode == 0) {
3805  firstMemoryNode = memNode;
3806  }
3807 
3808  return memNode;
3809 }
3810 
3811 
3812 void freeMemoryNode(MemoryNode* node) {
3813  if (node == 0) {
3814  return;
3815  }
3816 
3817  // free memory corresponding to this node
3818  if (node->ptr != 0) {
3819  free(node->ptr);
3820  }
3821 
3822  // redirect links in doubly linked list
3823  if (node->next != 0) {
3824  node->next->prev = node->prev;
3825  } else {
3826  lastMemoryNode = node->prev;
3827  }
3828 
3829  if (node->prev != 0) {
3830  node->prev->next = node->next;
3831  } else {
3832  firstMemoryNode = node->next;
3833  }
3834 
3835  //free node itself
3836  free(node);
3837 }
3838 
3839 
3841  MemoryNode* current = firstMemoryNode;
3842  while (current != 0) {
3843  MemoryNode* nextMemNode = current->next;
3844  freeMemoryNode(current);
3845  current = nextMemNode;
3846  }
3847 }
3848 
3849 
3850 // ------ NEW interface functions for memory management ------ //
3851 
3852 int allocateMemory(unsigned int size, char type, char* module,
3853  char prefixPurpose, void** ptr) {
3854  MemoryNode* memNode = 0;
3855  unsigned int realSize = 0;
3856  unsigned int addSize = 0;
3857  char msg[200];
3858  *ptr = 0;
3859 
3860  if (size == 0) {
3861  createLogMessage(MSG_WARNING,
3862  "FeeServer shall allocate memory of size 0; discarding call!", 0);
3863 # ifdef __DEBUG
3864  printf("FeeServer shall allocate memory of size 0; discarding call!\n");
3865  fflush(stdout);
3866 # endif
3867  return FEE_INVALID_PARAM;
3868  }
3869 
3870  switch (prefixPurpose) {
3871  case ('0'):
3872  realSize = size;
3873  break;
3874 
3875  case ('A'):
3876  realSize = size + HEADER_SIZE;
3877  addSize = HEADER_SIZE;
3878  break;
3879 
3880  default:
3881  msg[sprintf(msg,
3882  "Received allocateMemory call with unknown prefix purpose ('%c'), discarding call.",
3883  prefixPurpose)] = 0;
3884  createLogMessage(MSG_ERROR, msg, 0);
3885 # ifdef __DEBUG
3886  printf("%s\n", msg);
3887  fflush(stdout);
3888 # endif
3889  return FEE_INVALID_PARAM;
3890  }
3891 
3892  memNode = createMemoryNode(realSize, type, module, addSize);
3893  if (memNode == 0) {
3894  return FEE_FAILED;
3895  }
3896 
3897  *ptr = memNode->identityAddr;
3898 /* // only for debug output to test functyionality
3899  msg[sprintf(msg,
3900  "Allocated memory (type %c) for %s of size %d + prefix memory size %d. Purpose is set to: %c.",
3901  type, memNode->mmData.memDest, size, addSize, prefixPurpose)] = 0;
3902  createLogMessage(MSG_DEBUG, msg, 0);
3903 # ifdef __DEBUG
3904  printf("%s\n", msg);
3905  fflush(stdout);
3906 # endif
3907 */
3908  return FEE_OK;
3909 }
3910 
3911 
3912 int freeMemory(void* addr) {
3913  MemoryNode* memNode = 0;
3914  if (addr == 0) {
3915  // received NULL pointer
3916  createLogMessage(MSG_WARNING,
3917  "Received an NULL pointer for freeing memory, discarding call!", 0);
3918 # ifdef __DEBUG
3919  printf("Received an NULL pointer for freeing memory, discarding call! \n");
3920  fflush(stdout);
3921 # endif
3922  return FEE_NULLPOINTER;
3923  }
3924 
3925  memNode = findMemoryNode(addr);
3926  if (memNode == 0) {
3927  // memory pointer id not found in list
3928  return FEE_INVALID_PARAM;
3929  }
3930 
3931  freeMemoryNode(memNode);
3932  return FEE_OK;
3933 }
3934 
3935 
3937 
3938 int publishChar(CharItem* charItem) {
3939  unsigned int id;
3940  char* serviceName = 0;
3941 
3942  // check for right state
3943  if (state != COLLECTING) {
3944  return FEE_WRONG_STATE;
3945  }
3946 
3947  // Testing for NULL - Pointer
3948  // !! Attention: if pointer is not initialized and also NOT set to NULL, this won't help !!
3949  if (charItem == 0) {
3950 # ifdef __DEBUG
3951  printf("Bad charItem, not published\n");
3952  fflush(stdout);
3953 # endif
3954  return FEE_NULLPOINTER;
3955  }
3956  if (charItem->name == 0 || charItem->user_routine == 0) {
3957 # ifdef __DEBUG
3958  printf("Bad charItem, not published\n");
3959  fflush(stdout);
3960 # endif
3961  return FEE_NULLPOINTER;
3962  }
3963 
3964  // Check name for duplicate here
3965  // Check in Float list
3966  if (findItem(charItem->name) != 0) {
3967 # ifdef __DEBUG
3968  printf("Item name already published in float list, char item discarded.\n");
3969  fflush(stdout);
3970 # endif
3971  return FEE_ITEM_NAME_EXISTS;
3972  }
3973  // Check in INT list
3974  if (findIntItem(charItem->name) != 0) {
3975 # ifdef __DEBUG
3976  printf("Item name already published in int list, char item discarded.\n");
3977  fflush(stdout);
3978 # endif
3979  return FEE_ITEM_NAME_EXISTS;
3980  }
3981  // Check in CHAR list
3982  if (findCharItem(charItem->name) != 0) {
3983 # ifdef __DEBUG
3984  printf("Item name already published in char list, new char item discarded.\n");
3985  fflush(stdout);
3986 # endif
3987  return FEE_ITEM_NAME_EXISTS;
3988  }
3989 
3990  // -- add charItem as service --
3991  serviceName = (char*) malloc(serverNameLength + strlen(charItem->name) + 2);
3992  if (serviceName == 0) {
3993  return FEE_INSUFFICIENT_MEMORY;
3994  }
3995  // terminate string with '\0'
3996  serviceName[sprintf(serviceName, "%s_%s", serverName, charItem->name)] = 0;
3997  // add service in DIM
3998  id = dis_add_service(serviceName, "C", 0, 0, charItem->user_routine,
3999  charItem->tag);
4000  free(serviceName);
4001 
4002  // !!! implement add_char_item_node() func !!!
4003  add_char_item_node(id, charItem);
4004 
4005  return FEE_OK;
4006 }
4007 
4008 
4009 CharItem* createCharItem() {
4010  CharItem* charItem = 0;
4011 
4012  charItem = (CharItem*) malloc(sizeof(CharItem));
4013  if (charItem == 0) {
4014  //no memory available!
4015 # ifdef __DEBUG
4016  printf("no memory available for CharItem!\n");
4017 # endif
4018  return 0;
4019  }
4020  charItem->user_routine = 0;
4021  charItem->name = 0;
4022  charItem->tag = 0;
4023  return charItem;
4024 }
4025 
4026 
4027 //CharItem* fillCharItem(void* funcPointer, char* itemName, long tag) {
4028 CharItem* fillCharItem(void (*funcPointer)(long*, int**, int*), char* itemName,
4029  long tag) {
4030  CharItem* charItem = 0;
4031 
4032  charItem = createCharItem();
4033  if (charItem == 0) {
4034  //no memory available!
4035 # ifdef __DEBUG
4036  printf("no memory available for CharItem!\n");
4037 # endif
4038  return 0;
4039  }
4040  charItem->user_routine = funcPointer;
4041  charItem->name = (char*) malloc(strlen(itemName) + 1);
4042  if (charItem->name == 0) {
4043  //no memory available!
4044 # ifdef __DEBUG
4045  printf("no memory available!\n");
4046 # endif
4047  free(charItem);
4048  return 0;
4049  }
4050  strcpy(charItem->name, itemName);
4051  charItem->tag = tag;
4052  return charItem;
4053 }
4054 
4055 
4056 void add_char_item_node(unsigned int _id, CharItem* _char_item) {
4057  //create new node with enough memory
4058  CharItemNode* newNode = 0;
4059 
4060  newNode = (CharItemNode*) malloc(sizeof(CharItemNode));
4061  if (newNode == 0) {
4062  //no memory available!
4063 # ifdef __DEBUG
4064  printf("no memory available while adding CharItemNode!\n");
4065  fflush(stdout);
4066 # endif
4067  cleanUp();
4068  exit(201);
4069  }
4070  //initialize "members" of node
4071  newNode->prev = 0;
4072  newNode->next = 0;
4073  newNode->id = _id;
4074  newNode->charItem = _char_item;
4075 
4076 # ifdef __DEBUG
4077  // complete debug display of added charItem
4078 /*
4079  printf("CharItem ID: %d\n", _id);
4080  printf("CharItem name: %s\n", _char_item->name);
4081  printf("CharItem user_routine: %p\n", _char_item->user_routine);
4082  printf("CharItem tag: %d\n", _char_item->tag);
4083 */
4084 # endif
4085 
4086 # ifdef __DEBUG
4087  // short debug display of added Item
4088  printf("init of %s (char) with ID %d; user_routine at: %p\n",
4089  newNode->charItem->name, newNode->id,
4090  newNode->charItem->user_routine);
4091  fflush(stdout);
4092 # endif
4093 
4094  ++charNodesAmount;
4095  //redirect pointers of doubly linked list (char)
4096  if (firstCharNode != 0) {
4097  lastCharNode->next = newNode;
4098  newNode->prev = lastCharNode;
4099  lastCharNode = newNode;
4100  } else {
4101  firstCharNode = newNode;
4102  lastCharNode = newNode;
4103  }
4104 }
4105 
4106 
4107 CharItemNode* findCharItem(char* name) {
4108 // char msg[70];
4109  CharItemNode* current = 0;
4110 
4111  if (name == 0) {
4112  return 0;
4113  }
4114  current = firstCharNode;
4115  while (current != 0) { // is end of list
4116  if (strcmp(name, current->charItem->name) == 0) {
4117  // success, give back CharItemNode
4118  return current;
4119  }
4120  current = current->next;
4121  }
4122 // since three lists, which are searched seperately don't make log output in
4123 // findCharItem()-function -> move to where called to combine with other
4124 // findXYItem calls
4125 /*
4126  if (state == RUNNING) {
4127  msg[sprintf(msg, "Item %s not found in CharItem list.", name)] = 0;
4128  createLogMessage(MSG_WARNING, msg, 0);
4129 # ifdef __DEBUG
4130  printf("Item %s not found in CharItem list.\n", name);
4131  fflush(stdout);
4132 # endif
4133  }
4134 */
4135  return 0;
4136 }
4137 
4138 
4140  CharItemNode* tmp = 0;
4141 
4142  while (firstCharNode != 0) {
4143  if (firstCharNode->charItem != 0) {
4144  if (firstCharNode->charItem->name != 0) {
4145  free(firstCharNode->charItem->name);
4146  }
4147  free(firstCharNode->charItem);
4148  }
4149 
4150  tmp = firstCharNode->next;
4151  free(firstCharNode);
4152  firstCharNode = tmp;
4153  }
4154  return FEE_OK;
4155 }
4156 
4157 
4158 void initCharItemNode(CharItemNode* charItemNode) {
4159  charItemNode->prev = 0;
4160  charItemNode->next = 0;
4161  charItemNode->id = 0;
4162  charItemNode->charItem = 0;
4163 }
4164 
4165 
4167  CharItemNode* current = 0;
4168 
4169  current = firstCharNode;
4170  while (current != 0) {
4171  dis_remove_service(current->id);
4172  current = current->next;
4173  }
4174  // pretending CharItemList is completely empty to avoid access
4175  // to not existing DIM services. Don't delete charItems, CE might still
4176  // try to access their content (same for float and int lists)
4177  charNodesAmount = 0;
4178  firstCharNode = 0;
4179  lastCharNode = 0;
4180 }
4181 
4182 
4184 
4185 bool setFeeProperty(FeeProperty* prop) {
4186  bool retVal = false;
4187  if (state != INITIALIZING) {
4188  createLogMessage(MSG_WARNING,
4189  "Trying to change a FeeProperty during wrong FeeServer state, ignoring ...",
4190  0);
4191 # ifdef __DEBUG
4192  printf("Trying to change a FeeProperty during wrong FeeServer state, ignoring ...\n");
4193  fflush(stdout);
4194 # endif
4195  return retVal;
4196  }
4197 
4198  if (prop == 0) {
4199 # ifdef __DEBUG
4200  printf("Received NULL pointer in setting FeeProperty, ignoring...\n");
4201  fflush(stdout);
4202 # endif
4203  // No log message: in "INITIALIZING" state are no DIM channels available
4204  return retVal;
4205  }
4206 
4207  switch (prop->flag) {
4208  case (PROPERTY_UPDATE_RATE):
4209  if (prop->uShortVal > 0) {
4210  updateRate = prop->uShortVal;
4211  retVal = true;
4212 # ifdef __DEBUG
4213  printf("FeeProperty changed: new update rate (%d).\n",
4214  updateRate);
4215  fflush(stdout);
4216 # endif
4217  } else {
4218 # ifdef __DEBUG
4219  printf("Received invalid value for setting update rate (%d), ignoring...\n",
4220  prop->uShortVal);
4221  fflush(stdout);
4222 # endif
4223  }
4224  break;
4225 
4226  case (PROPERTY_LOGWATCHDOG_TIMEOUT):
4227  if (prop->uIntVal > 0) {
4228  logWatchDogTimeout = prop->uIntVal;
4229  retVal = true;
4230 # ifdef __DEBUG
4231  printf("FeeProperty changed: new log watchdog timeout (%d).\n",
4232  logWatchDogTimeout);
4233  fflush(stdout);
4234 # endif
4235  } else {
4236 # ifdef __DEBUG
4237  printf("Received invalid value for setting log watchdog timeout (%d), ignoring...\n",
4238  prop->uIntVal);
4239  fflush(stdout);
4240 # endif
4241  }
4242  break;
4243 
4244  case (PROPERTY_ISSUE_TIMEOUT):
4245  if (prop->uLongVal > 0) {
4246  issueTimeout = prop->uLongVal;
4247  retVal = true;
4248 # ifdef __DEBUG
4249  printf("FeeProperty changed: new issue timeout (%ld).\n",
4250  issueTimeout);
4251  fflush(stdout);
4252 # endif
4253  } else {
4254 # ifdef __DEBUG
4255  printf("Received invalid value for setting issue timeout (%ld), ignoring...\n",
4256  prop->uLongVal);
4257  fflush(stdout);
4258 # endif
4259  }
4260  break;
4261 
4262  case (PROPERTY_LOGLEVEL):
4263  if ((prop->uIntVal > 0) && (prop->uIntVal <= MSG_MAX_VAL)) {
4264  logLevel = prop->uIntVal | MSG_ALARM;
4265  retVal = true;
4266 # ifdef __DEBUG
4267  printf("FeeProperty changed: new log level (%d).\n", logLevel);
4268  fflush(stdout);
4269 # endif
4270  } else {
4271 # ifdef __DEBUG
4272  printf("Received invalid value for setting loglevel (%d), ignoring...\n",
4273  prop->uIntVal);
4274  fflush(stdout);
4275 # endif
4276  }
4277  break;
4278 
4279  default:
4280  // unknown property flag, but no logging
4281 # ifdef __DEBUG
4282  printf("Received unknown flag in setting FeeProperty (%d), ignoring...\n",
4283  prop->flag);
4284  fflush(stdout);
4285 # endif
4286  }
4287 
4288  return retVal;
4289 }
4290 
4291 
4295 #ifdef __BENCHMARK
4296 void createBenchmark(char* msg) {
4297  // this part is only used for benchmarking
4298  // timestamp to benchmark reception of a command
4299  struct tm *today;
4300  struct timeval tStamp;
4301  char benchmark_msg[200];
4302  int status = 0;
4303  FILE* pFile = 0;
4304 
4305  status = gettimeofday(&tStamp, 0);
4306  if (status != 0) {
4307  benchmark_msg[sprintf(benchmark_msg,
4308  "Unable to get timestamp for benchmark!")] = 0;
4309  } else {
4310  today = localtime(&(tStamp.tv_sec));
4311  benchmark_msg[sprintf(benchmark_msg,
4312  "%s: \t%.8s - %ld us", msg, asctime(today) + 11,
4313  tStamp.tv_usec)] = 0;
4314  }
4315 
4316  if (getenv("FEE_BENCHMARK_FILENAME")) {
4317  pFile = fopen(getenv("FEE_BENCHMARK_FILENAME"), "a+");
4318  if (pFile) {
4319  fprintf(pFile, benchmark_msg);
4320  fprintf(pFile, "\n");
4321  fclose(pFile);
4322  } else {
4323 #ifdef __DEBUG
4324  printf("Unable to open benchmark file.\n");
4325  printf("%s\n", benchmark_msg);
4326 #endif
4327  createLogMessage(MSG_WARNING, "Unable to write to benchmarkfile.", 0);
4328  }
4329  } else {
4330  createLogMessage(MSG_SUCCESS_AUDIT, benchmark_msg, 0);
4331  }
4332 }
4333 #else
4334 // empty function
4335 void createBenchmark(char* msg) {
4336 }
4337 #endif
4338 
4339 
4340 
4344 #ifdef __DEBUG
4345 void printData(char* data, int start, int size) {
4346  int i;
4347  int iBackUp;
4348 
4349  if ((data == 0) || (size == 0)) {
4350  return;
4351  }
4352  iBackUp = start;
4353  for (i = start; (i < size) || (iBackUp < size); ++i) {
4354  ++iBackUp;
4355  printf("%c", data[i]);
4356  }
4357  printf("\nData - Size: %d", size);
4358  printf("\n\n");
4359  fflush(stdout);
4360 }
4361 #endif
4362 
4363 
4364 //-- only for the testcases necessary
4365 #ifdef __UTEST
4366 const int getState() {
4367  return state;
4368 }
4369 
4370 const ItemNode* getFirstNode() {
4371  return firstNode;
4372 }
4373 
4374 const ItemNode* getLastNode() {
4375  return lastNode;
4376 }
4377 
4378 int listSize() {
4379  ItemNode* tmp = firstNode;
4380  int count = 0;
4381 
4382  while (tmp != 0) {
4383  tmp = tmp->next;
4384  ++count;
4385  }
4386  return count;
4387 }
4388 
4389 const char* getCmndACK() {
4390  return cmndACK;
4391 }
4392 
4393 void setState(int newState) {
4394  state = newState;
4395 }
4396 
4397 void setCmndACK(char* newData) {
4398  cmndACK = newData;
4399 }
4400 
4401 void setCmndACKSize(int size) {
4402  cmndACKSize = size;
4403 }
4404 
4405 void setServerName(char* name) {
4406  if (serverName != 0) {
4407  free(serverName);
4408  }
4409  serverName = (char*) malloc(strlen(name) + 1);
4410  if (serverName == 0) {
4411  printf(" No memory available !\n");
4412  }
4413  strcpy(serverName, name);
4414 }
4415 
4416 void clearServerName() {
4417  if (serverName != 0) {
4418  free(serverName);
4419  }
4420 }
4421 
4422 void stopServer() {
4423  dis_remove_service(serviceACKID);
4424  dis_remove_service(commandID);
4425  dis_stop_serving();
4426 }
4427 
4428 pthread_cond_t* getInitCondPtr() {
4429  return &init_cond;
4430 }
4431 
4432 
4433 pthread_mutex_t* getWaitInitMutPtr() {
4434  return &wait_init_mut;
4435 }
4436 
4437 #endif
4438 
4439 
4440 
4441 --------------------------------------------------------------------------------
4442 for assistance refer to the CVS howto. Maintained by Matthias Richter Powered by
4443 ViewCVS 0.9.2
int start(int initState)
Definition: feeserver.c:1740
bool checkIntLocation(IntItemNode *node)
Definition: feeserver.c:3619
Return to feeserver c CVS log Up to[MAIN] dcscvs FeeServer feeserver src Wed FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0
Definition: feeserver.c:5
unsigned int calculateChecksum(unsigned char *buffer, int size)
Definition: feeserver.c:2372
Definition: dns.c:26
static MemoryNode * lastMemoryNode
Definition: feeserver.c:322
ItemNode * findItem(char *name)
Definition: feeserver.c:3045
#define dis_remove_service
Definition: dis.h:19
unsigned int setDeadbandBroadcast(char *name, float newDeadbandBC)
Definition: feeserver.c:2858
void initIntItemNode(IntItemNode *intItemNode)
Definition: feeserver.c:3427
static unsigned short updateRate
Definition: feeserver.c:196
void add_item_node(unsigned int _id, Item *_item)
Definition: feeserver.c:1464
static bool ceReadySignaled
Definition: feeserver.c:77
static unsigned int charNodesAmount
-— NEW FEATURE SINCE VERSION 0.8.2b [Char Channel] (2007-07-28) –— ///
Definition: feeserver.c:331
int setUpdateRate(IssueStruct *issueParam)
Definition: feeserver.c:2719
static MessageStruct message
Definition: feeserver.c:101
int freeMemory(void *addr)
Definition: feeserver.c:3912
static IntItemNode * firstIntNode
Definition: feeserver.c:281
static pthread_t thread_mon_int
Definition: feeserver.c:299
int publishChar(CharItem *charItem)
— NEW FEATURE SINCE VERSION 0.8.2b [Char channel] (2007-07-28) — ///
Definition: feeserver.c:3938
void add_char_item_node(unsigned int _id, CharItem *_char_item)
Definition: feeserver.c:4056
Definition: did.h:42
int i
Definition: db_dim_client.c:21
void cleanUp()
Definition: feeserver.c:3159
FloatItem * createFloatItem()
Definition: feeserver.c:3679
int publishFloat(FloatItem *floatItem)
Definition: feeserver.c:3674
void command_handler(int *tag, char *address, int *size)
Definition: feeserver.c:829
CharItemNode * findCharItem(char *name)
Definition: feeserver.c:4107
void dim_dummy_exit_handler(int *bufp)
Definition: feeserver.c:3123
void fee_exit_handler(unsigned int state)
Definition: feeserver.c:3109
bool setFeeProperty(FeeProperty *prop)
– NEW FEATURE V. 0.9.1 [Set FeeServer Properies in CE] (2007-08-17) – ///
Definition: feeserver.c:4185
void runLogWatchDog()
Definition: feeserver.c:2125
char * createHeader(unsigned int id, short errorCode, bool huffmanFlag, bool checksumFlag, int checksum)
Definition: feeserver.c:2315
void signalCEready(int ceState)
Definition: feeserver.c:777
static bool intMonitorThreadStarted
Definition: feeserver.c:307
void * malloc()
Definition: EventBuilder.cc:99
char id[4]
Definition: FITS.h:71
void initIssueStruct(IssueStruct *issueStr)
Definition: feeserver.c:2993
char * mapDimErrorCodes(int errorCode)
Definition: feeserver.c:1710
int main(int argc, char **arg)
Definition: feeserver.c:363
bool checkLogLevel(int event)
Definition: feeserver.c:1653
static unsigned int intNodesAmount
Definition: feeserver.c:293
void threadInitializeCE()
Definition: feeserver.c:747
int setLogLevel(IssueStruct *issueParam)
Definition: feeserver.c:2768
static unsigned int serviceACKID
Definition: feeserver.c:153
MemoryNode * findMemoryNode(void *addr)
Definition: feeserver.c:3691
CharItem * fillCharItem(void(*funcPointer)(long *, int **, int *), char *itemName, long tag)
Definition: feeserver.c:4028
int deleteItemList()
Definition: feeserver.c:3217
static int serverNameLength
Definition: feeserver.c:189
void updateFeeServer(IssueStruct *issueParam)
Definition: feeserver.c:2417
void dis_add_error_handler(void(*user_routine)())
Definition: dis.c:540
unsigned int dtq_sleep(int secs)
Definition: dtq.c:837
void createLogMessage(unsigned int type, char *description, char *origin)
Definition: feeserver.c:1530
int getUpdateRate(IssueStruct *issueParam)
Definition: feeserver.c:2745
static pthread_t thread_logWatchdog
Definition: feeserver.c:236
void unpublishCharItemList()
Definition: feeserver.c:4166
Return to feeserver c CVS log Up to[MAIN] dcscvs FeeServer feeserver src Wed FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0 dev Changes since
Definition: feeserver.c:5
void initCharItemNode(CharItemNode *charItemNode)
Definition: feeserver.c:4158
void initItemNode(ItemNode *iNode)
Definition: feeserver.c:3033
void dim_error_msg_handler(int severity, int error_code, char *msg)
Definition: feeserver.c:1662
static pthread_mutex_t wait_mut
Definition: feeserver.c:254
bool checkLocation(ItemNode *node)
Definition: feeserver.c:2023
void cleanupMemoryList()
Definition: feeserver.c:3840
#define dis_add_cmnd
Definition: dis.h:13
void add_int_item_node(unsigned int _id, IntItem *_int_item)
Definition: feeserver.c:3317
static pthread_mutex_t command_mut
Definition: feeserver.c:266
void ack_service(int *tag, char **address, int *size)
Definition: feeserver.c:1312
bool checkReplicatedLogMessage()
Definition: feeserver.c:2202
static ItemNode * firstNode
Definition: feeserver.c:89
int startLogWatchDogThread()
Definition: feeserver.c:2079
static CharItemNode * lastCharNode
Definition: feeserver.c:343
static unsigned int logWatchDogTimeout
Definition: feeserver.c:133
int type
int updateFeeService(char *serviceName)
Definition: feeserver.c:2914
static pthread_t thread_mon
Definition: feeserver.c:223
CharItem * createCharItem()
Definition: feeserver.c:4009
void unlockIssueMutex()
Definition: feeserver.c:1378
Return to feeserver c CVS log Up to[MAIN] dcscvs FeeServer feeserver src Wed May
Definition: feeserver.c:5
static pthread_mutex_t log_mut
Definition: feeserver.c:272
static IntItemNode * lastIntNode
Definition: feeserver.c:287
#define dis_start_serving
Definition: dis.h:8
#define dis_update_service
Definition: dis.h:18
static unsigned int logLevel
Definition: feeserver.c:211
int setIssueTimeout(IssueStruct *issueParam)
Definition: feeserver.c:2662
void initialize()
Definition: feeserver.c:385
void unpublishItemList()
Definition: feeserver.c:3076
Warning because the service this data corrsponds to might have been last updated longer ago than Local time
Definition: smartfact.txt:92
#define dis_stop_serving
Definition: dis.h:9
static char * cmndACK
Definition: feeserver.c:171
static MemoryNode * firstMemoryNode
Definition: feeserver.c:316
void monitorValues()
Definition: feeserver.c:1944
static int ceInitState
Definition: feeserver.c:83
int buffer[BUFFSIZE]
Definition: db_dim_client.c:14
int count
Definition: db_dim_server.c:18
static pthread_cond_t cond
Definition: feeserver.c:242
static char * serverName
Definition: feeserver.c:183
#define dis_get_client
Definition: dis.h:11
int getDeadband(IssueStruct *issueParam)
Definition: feeserver.c:2586
int size
Definition: db_dim_server.c:17
float data[4 *1440]
void freeMemoryNode(MemoryNode *node)
Definition: feeserver.c:3812
void provideUpdateRate()
Definition: feeserver.c:2848
int setDeadband(IssueStruct *issueParam)
Definition: feeserver.c:2494
void free(void *mem)
static pthread_cond_t init_cond
Definition: feeserver.c:248
int publish(Item *item)
Definition: feeserver.c:1396
static pthread_mutex_t wait_init_mut
Definition: feeserver.c:260
int startMonitorThread()
Definition: feeserver.c:1878
static int cmndACKSize
Definition: feeserver.c:177
void createBenchmark(char *msg)
Definition: feeserver.c:4335
#define dis_add_service
Definition: dis.h:12
void initMessageStruct()
Definition: feeserver.c:3000
void unpublishIntItemList()
Definition: feeserver.c:3439
Item * fillItem(float *floatLocation, char *itemName, float defDeadband)
Definition: feeserver.c:3488
static pthread_t thread_init
Definition: feeserver.c:217
static bool monitorThreadStarted
Definition: feeserver.c:147
Return to feeserver c CVS log Up to[MAIN] dcscvs FeeServer feeserver src Wed FeeServer_v0 v0 dev
Definition: feeserver.c:5
void triggerRestart(int exitVal)
Definition: feeserver.c:2467
void leaveCommandHandler(unsigned int id, short errorCode, unsigned int msgType, char *message)
Definition: feeserver.c:1344
#define dis_add_exit_handler
Definition: dis.h:15
void restartFeeServer()
Definition: feeserver.c:2463
int publishInt(IntItem *intItem)
Definition: feeserver.c:3249
Return to feeserver c CVS log Up to[MAIN] dcscvs FeeServer feeserver src File
Definition: feeserver.c:5
static unsigned int nodesAmount
Definition: feeserver.c:139
MemoryNode * createMemoryNode(unsigned int size, char type, char *module, unsigned int preSize)
Definition: feeserver.c:3732
FloatItem * fillFloatItem(float *floatLocation, char *itemName, float defDeadband)
Definition: feeserver.c:3684
IntItem * createIntItem()
Definition: feeserver.c:3471
static unsigned int commandID
Definition: feeserver.c:165
static unsigned long issueTimeout
Definition: feeserver.c:203
IntItemNode * findIntItem(char *name)
Definition: feeserver.c:3378
void * threadIssue(void *threadParam)
Definition: feeserver.c:2243
static unsigned short replicatedMsgCount
Definition: feeserver.c:114
bool checkCommand(char *payload, int size, unsigned int checksum)
Definition: feeserver.c:2352
static bool logWatchDogRunning
Definition: feeserver.c:122
Return to feeserver c CVS log Up to[MAIN] dcscvs FeeServer feeserver src Wed HEAD
Definition: feeserver.c:5
int allocateMemory(unsigned int size, char type, char *module, char prefixPurpose, void **ptr)
Definition: feeserver.c:3852
void monitorIntValues()
Definition: feeserver.c:3540
static MessageStruct lastMessage
Definition: feeserver.c:108
int deleteCharItemList()
Definition: feeserver.c:4139
sprintf(name1,"NewService%d", i)
Item * createItem()
Definition: feeserver.c:3454
static CharItemNode * firstCharNode
Definition: feeserver.c:337
static unsigned int messageServiceID
Definition: feeserver.c:159
char * marshallHeader(CommandHeader *pHeader)
Definition: feeserver.c:2389
int getIssueTimeout(IssueStruct *issueParam)
Definition: feeserver.c:2697
int deleteIntItemList()
Definition: feeserver.c:3409
void interrupt_handler(int sig)
Definition: feeserver.c:3094
static ItemNode * lastNode
Definition: feeserver.c:95
IntItem * fillIntItem(int *intLocation, char *itemName, int defDeadband)
Definition: feeserver.c:3514
int getLogLevel(IssueStruct *issueParam)
Definition: feeserver.c:2826
Changes for version
Definition: README_v11.txt:85