Belle II Software  release-06-01-15
DesSerCOPPER.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <daq/rawdata/modules/copper.h>
10 #include <daq/rawdata/DesSerCOPPER.h>
11 
12 #include <fcntl.h>
13 #include <sys/ioctl.h>
14 
15 using namespace std;
16 using namespace Belle2;
17 
18 
19 
20 //----------------------------------------------------------------
21 // Implementation
22 //----------------------------------------------------------------
23 
24 DesSerCOPPER::DesSerCOPPER(string host_recv, int port_recv, string host_send, int port_send, int shmflag,
25  const std::string& nodename, int nodeid, int finesse_bitflag)
26 {
27  m_finesse_bit_flag = finesse_bitflag;
28 
29  for (int i = 0 ; i < m_num_connections; i++) {
30  // m_hostname_from.push_back( "localhost");
31  m_hostname_from.push_back(host_recv);
32  // m_port_from.push_back(30000);
33  m_port_from.push_back(port_recv) ;
34  m_socket_recv.push_back(-1);
35  }
36 
37  // m_port_to = 31001;
38  m_port_to = port_send;
39  // m_hostname_local = "localhost";
40  m_hostname_local = host_send;
41  m_nodename = nodename;
42 
43  m_shmflag = shmflag;
44 
45  m_nodeid = nodeid;
46 
47  // B2INFO("DeSerializerPrePC: Constructor done.");
48  printf("[DEBUG] DeSerializerPrePC: Constructor done.\n"); fflush(stdout);
49 }
50 
51 
52 
53 DesSerCOPPER::~DesSerCOPPER()
54 {
55 }
56 
57 void DesSerCOPPER::DataAcquisition()
58 {
59  // For data check
60  unsigned int eve_copper_0 = 0;
61  // B2INFO("initializing...");
62  printf("[DEBUG] initializing...\n"); fflush(stdout);
63  initialize(false);
64 
65 
66  // B2INFO("Done.");
67  printf("[DEBUG] Done.\n"); fflush(stdout);
68 
69  unsigned int m_prev_ftsweve32 = 0xffffffff;
70 
71  if (m_start_flag == 0) {
72  //
73  // Connect to eb0: This should be here because we want Serializer first to accept connection from eb1tx
74  //
75  initializeCOPPER();
76  // Connect();
77 
78  if (m_status.isAvailable()) {
79  // B2INFO("DeSerializerPrePC: Waiting for Start...\n");
80  printf("[DEBUG] DeSerializerPrePC: Waiting for Start...\n"); fflush(stdout);
81  m_status.reportRunning();
82  }
83  m_start_time = getTimeSec();
84  n_basf2evt = 0;
85  }
86 
87  //
88  // Main loop
89  //
90  while (1) {
91  //
92  // Stand-by loop
93  //
94 #ifdef NONSTOP
95  if (m_run_pause > 0 || m_run_error > 0) {
96  waitResume();
97  }
98 #endif
99 
100  clearNumUsedBuf();
101  // RawDataBlock raw_datablk[ NUM_EVT_PER_BASF2LOOP_PC ];
102  RawDataBlockFormat raw_datablk[ NUM_EVT_PER_BASF2LOOP_PC ];
103 
104 
105  //
106  // Recv loop
107  //
108  for (int j = 0; j < NUM_EVT_PER_BASF2LOOP_PC; j++) {
109  //
110  // Receive data from COPPER
111  //
112  eve_copper_0 = 0;
113  int delete_flag_from =
114  0; // Delete flag for temp_rawdatablk.It can be set to 1 by setRecvdBuffer if the buffer size is larger than that of pre-allocated buffer.
115  int delete_flag_to =
116  0; // Delete flag for raw_datablk[i]. It can be set to 1 by getNewBuffer if the buffer size is larger than that of pre-allocated buffer.
117  RawDataBlockFormat temp_rawdatablk;
118  try {
119 
120  int delete_flag = 0, m_size_word = 0;
121 
122  if (m_start_flag == 0) {
123  printf("[DEBUG] DeSerializerCOPPER: Reading the 1st event from COPPER FIFO... run %.8x eve %.8x\n", m_prev_exprunsubrun_no,
124  m_prev_ftsweve32); fflush(stdout);
125  }
126  int* temp_buf;
127 
128  temp_buf = readOneEventFromCOPPERFIFO(j, &delete_flag, &m_size_word);
129  m_status.copyEventHeader(temp_buf);
130  if (m_start_flag == 0) {
131  printf("[DEBUG] DeSerializerCOPPER: Done. the size of the 1st event is %d words\n", m_size_word); fflush(stdout);
132  }
133  const int num_nodes = 1;
134  const int num_events = 1;
135  PreRawCOPPERFormat_v2 temp_rawcopper;
136  temp_rawcopper.SetBuffer(temp_buf, m_size_word, 0, num_events, num_nodes);
137  // Fill header and trailer
138  try {
139  m_prev_ftsweve32 = temp_rawcopper.FillTopBlockRawHeader(m_nodeid, m_prev_ftsweve32, m_prev_exprunsubrun_no, &m_exprunsubrun_no);
140  m_prev_exprunsubrun_no = m_exprunsubrun_no;
141  // fillNewRawCOPPERHeader( &temp_rawcopper );
142  } catch (string err_str) {
143  print_err.PrintError(m_shmflag, &m_status, err_str);
144  exit(1);
145  }
146 
147 // if (m_dump_fname.size() > 0) {
148 // dumpData((char*)temp_buf, m_size_word * sizeof(int));
149 // }
150  m_recvd_totbytes += m_size_word * sizeof(int);
151 
152  // temp_rawdblk = raw_dblkarray.appendNew();
153  // temp_rawdatablk->SetBuffer(temp_buf, m_size_word, delete_flag, num_events, num_nodes);
154  raw_datablk[ j ].SetBuffer(temp_buf, m_size_word, delete_flag, num_events, num_nodes);
155 
156  } catch (string err_str) {
157  printf("Error was detected\n"); fflush(stdout);
158  break;
159  }
160  }
161 
162 #ifdef NONSTOP
163  // Goto Stand-by loop when run is paused or stopped by error
164  if (m_run_pause != 0 || m_run_error != 0) continue;
165 #endif
166 
167 
169  // From Serializer.cc
171  if (m_start_flag == 0) {
172  m_start_time = getTimeSec();
173  n_basf2evt = 0;
174  }
175 
176  //
177  // Send data
178  //
179  for (int j = 0; j < NUM_EVT_PER_BASF2LOOP_PC; j++) {
180  if (m_start_flag == 0) {
181  // B2INFO("SerializerPC: Sending the 1st packet...");
182  printf("[DEBUG] SerializerPC: Sending the 1st packet...\n"); fflush(stdout);
183  }
184  try {
185  m_sent_totbytes += sendByWriteV(&(raw_datablk[ j ]));
186  } catch (string err_str) {
187 #ifdef NONSTOP
188  break;
189 #endif
190  print_err.PrintError((char*)err_str.c_str(), __FILE__, __PRETTY_FUNCTION__, __LINE__);
191  exit(1);
192  }
193  if (m_start_flag == 0) {
194  // B2INFO("Done. ");
195  printf("[DEBUG] Done.\n"); fflush(stdout);
196  m_start_flag = 1;
197  }
198  }
199 
200 #ifdef NONSTOP
201  // Goto Stand-by loop when run is paused or stopped by error
202  if (m_run_pause != 0 || m_run_error != 0) continue;
203 #endif
204 
205  //
206  // Monitor
207  //
208  if (max_nevt >= 0 || max_seconds >= 0.) {
209 #ifdef AIUEO
210  if (n_basf2evt % 10000 == 0) {
211 // if ((n_basf2evt * NUM_EVT_PER_BASF2LOOP_PC >= max_nevt && max_nevt > 0)
212 // || (getTimeSec() - m_start_time > max_seconds && max_seconds > 0.)) {
213  printf("[DEBUG] RunStop was detected. ( Setting: Max event # %d MaxTime %lf ) Processed Event %d Elapsed Time %lf[s]\n",
214  max_nevt , max_seconds, n_basf2evt * NUM_EVT_PER_BASF2LOOP_PC, getTimeSec() - m_start_time);
215  }
216 #endif
217  }
218 
219  if ((n_basf2evt * NUM_EVT_PER_BASF2LOOP_PC) % 100000 == 0) {
220  double interval = cur_time - m_prev_time;
221  double total_time = cur_time - m_start_time;
222  printf("[DEBUG] Event %12d Rate %6.2lf[kHz] Recvd %6.2lf[MB/s] sent %6.2lf[MB/s] RunTime %8.2lf[s] interval %8.4lf[s]\n",
223  n_basf2evt * NUM_EVT_PER_BASF2LOOP_PC,
224  (n_basf2evt - m_prev_nevt)*NUM_EVT_PER_BASF2LOOP_PC / interval / 1.e3,
225  (m_recvd_totbytes - m_recvd_prev_totbytes) / interval / 1.e6,
226  (m_sent_totbytes - m_sent_prev_totbytes) / interval / 1.e6,
227  total_time,
228  interval);
229  fflush(stdout);
230 
231  m_prev_time = cur_time;
232  m_recvd_prev_totbytes = m_recvd_totbytes;
233  m_sent_prev_totbytes = m_sent_totbytes;
234  m_prev_nevt = n_basf2evt;
235  cur_time = getTimeSec();
236  }
237 
238  n_basf2evt++;
239 
240  if (m_status.isAvailable()) {
241  m_status.setOutputNBytes(m_sent_totbytes);
242  m_status.setOutputCount(n_basf2evt * NUM_EVT_PER_BASF2LOOP_PC);
243  }
244 
245  }
246 
247  return;
248 }
249 
251 // From Serializer.cc
253 
254 #ifdef NONSTOP
255 void DesSerCOPPER::waitResume()
256 {
257  if (m_run_pause == 0) {
258  while (true) {
259  if (checkRunPause()) break;
260 #ifdef NONSTOP_DEBUG
261  printf("\033[31m");
262  printf("###########(DesSerCOPPER) Waiting for Runstop() ###############\n");
263  fflush(stdout);
264  printf("\033[0m");
265 #endif
266  sleep(1);
267  }
268  }
269 
270  // close COPPER FIFO
271  if (m_cpr_fd != -1) close(m_cpr_fd);
272  m_cpr_fd = -1;
273 
274  while (true) {
275 #ifdef NONSTOP_DEBUG
276  printf("\033[31m");
277  printf("###########(Ser) Waiting for Resume ###############\n");
278  fflush(stdout);
279  printf("\033[0m");
280 #endif
281  if (checkRunRecovery()) {
282  m_run_pause = 0;
283  m_run_error = 0;
284 
285  break;
286  }
287  sleep(1);
288  }
289 
290  printf("Done!\n"); fflush(stdout);
291 
292  if (CheckConnection(m_socket_send) < 0) {
293  printf("Trying Accept1\n"); fflush(stdout);
294  Accept(false);
295  printf("Trying Accept2\n"); fflush(stdout);
296  }
297 
298  resumeRun();
299  return;
300 }
301 
302 
303 
304 void DesSerCOPPER::resumeRun()
305 {
306  initializeCOPPER();
307 #ifdef NONSTOP_DEBUG
308  printf("\033[34m");
309  printf("###########(Ser) the 1st event sicne the resume ###############\n");
310  fflush(stdout);
311  printf("\033[0m");
312 #endif
313  m_run_error = 0;
314  m_run_pause = 0;
315  return;
316 }
317 
318 
319 
320 #endif
321 
322 
323 
324 int* DesSerCOPPER::readOneEventFromCOPPERFIFO(const int entry, int* delete_flag, int* m_size_word)
325 {
326 
327  // prepare buffer
328  *m_size_word = 0;
329  int* temp_buf = m_bufary[ entry ];
330  temp_buf[0] = BUF_SIZE_WORD ;
331  *delete_flag = 0;
332 
333  //
334  // Read data from HSLB
335  //
336 #ifndef DUMMY
337  int recvd_byte = (m_pre_rawcpr.tmp_header.RAWHEADER_NWORDS) * sizeof(int);
338  // Firstly, read data with an allocated buffer.
339  while (1) {
340  int read_size = 0;
341  if ((read_size = read(m_cpr_fd, (char*)m_bufary[entry] + recvd_byte, sizeof(int) * BUF_SIZE_WORD - recvd_byte)) < 0) {
342  if (errno == EINTR) {
343  continue;
344  } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
345 
346  if (recvd_byte > (int)((m_pre_rawcpr.tmp_header.RAWHEADER_NWORDS) * sizeof(int))) {
347  char err_buf[500];
348  sprintf(err_buf, "[FATAL] EAGAIN return in the middle of an event( COPPER driver should't do this.). Exting...");
349  print_err.PrintError(m_shmflag, &m_status, err_buf, __FILE__, __PRETTY_FUNCTION__, __LINE__);
350  exit(-1);
351  }
352 
353 #ifdef NONSTOP
354  // Check run-pause request from SLC
355  string err_str;
356  callCheckRunPause(err_str);
357 #endif
358  continue;
359 
360  } else {
361  char err_buf[500];
362  sprintf(err_buf, "[FATAL] Failed to read data from COPPER. Exiting...");
363  print_err.PrintError(m_shmflag, &m_status, err_buf, __FILE__, __PRETTY_FUNCTION__, __LINE__);
364  exit(-1);
365  }
366  } else {
367  recvd_byte += read_size;
368  if (recvd_byte - (m_pre_rawcpr.tmp_header.RAWHEADER_NWORDS) * sizeof(int) > (int)(sizeof(int) *
369  (m_pre_rawcpr.POS_DATA_LENGTH + 1)))break;
370  }
371  }
372 
373  //
374  // Calcurate data size
375  //
376  *m_size_word = m_bufary[ entry ][ m_pre_rawcpr.POS_DATA_LENGTH + (m_pre_rawcpr.tmp_header.RAWHEADER_NWORDS) ]
377  + m_pre_rawcpr.SIZE_COPPER_DRIVER_HEADER + m_pre_rawcpr.SIZE_COPPER_DRIVER_TRAILER
378  + m_pre_rawcpr.tmp_header.RAWHEADER_NWORDS +
379  m_pre_rawcpr.tmp_trailer.RAWTRAILER_NWORDS; // 9 words are COPPER haeder and trailer size.
380 
381  //
382  // If there are data remaining to be read, continue reading
383  //
384  if ((int)((*m_size_word - m_pre_rawcpr.tmp_trailer.RAWTRAILER_NWORDS) * sizeof(int)) > recvd_byte) {
385 
386  // If event size is larger than BUF_SIZE_WORD, allocate a new buffer
387  if (*m_size_word > BUF_SIZE_WORD) {
388  *delete_flag = 1;
389  temp_buf = new int[ *m_size_word ];
390  memcpy(temp_buf, m_bufary[ entry ], recvd_byte);
391  recvd_byte += readFD(m_cpr_fd, (char*)temp_buf + recvd_byte,
392  (*m_size_word - m_pre_rawcpr.tmp_trailer.RAWTRAILER_NWORDS) * sizeof(int) - recvd_byte, *delete_flag);
393  } else {
394 
395  recvd_byte += readFD(m_cpr_fd, (char*)(m_bufary[ entry ]) + recvd_byte,
396  (*m_size_word - m_pre_rawcpr.tmp_trailer.RAWTRAILER_NWORDS) * sizeof(int) - recvd_byte, *delete_flag);
397  }
398 
399  if ((int)((*m_size_word - m_pre_rawcpr.tmp_trailer.RAWTRAILER_NWORDS) * sizeof(int)) != recvd_byte) {
400  char err_buf[500];
401 
402  sprintf(err_buf, "[FATAL] CORRUPTED DATA: Read less bytes(%d) than expected(%d:%d). Exiting...\n",
403  recvd_byte,
404  *m_size_word * sizeof(int) - m_pre_rawcpr.tmp_trailer.RAWTRAILER_NWORDS * sizeof(int),
405  m_bufary[ entry ][ m_pre_rawcpr.POS_DATA_LENGTH ]);
406  print_err.PrintError(m_shmflag, &m_status, err_buf, __FILE__, __PRETTY_FUNCTION__, __LINE__);
407  exit(-1);
408  }
409  } else if ((int)((*m_size_word - m_pre_rawcpr.tmp_trailer.RAWTRAILER_NWORDS) * sizeof(int)) < recvd_byte) {
410  char err_buf[500];
411  sprintf(err_buf, "[FATAL] CORRUPTED DATA: Read more than data size. Exiting...: %d %d %d %d %d\n",
412  recvd_byte, *m_size_word * sizeof(int) , m_pre_rawcpr.tmp_trailer.RAWTRAILER_NWORDS * sizeof(int),
413  m_bufary[ entry ][ m_pre_rawcpr.POS_DATA_LENGTH ], m_pre_rawcpr.POS_DATA_LENGTH);
414  print_err.PrintError(m_shmflag, &m_status, err_buf, __FILE__, __PRETTY_FUNCTION__, __LINE__);
415  exit(-1);
416  }
417 #else
418  //
419  // Make dummy data
420  //
421  *m_size_word = 256 + entry;
422  m_bufary[entry][0] = *m_size_word;
423 #endif
424 
425  //
426  // Fill Data length
427  //
428  temp_buf[ 0 ] = *m_size_word;
429 
430 
431 #ifdef TIME_MONITOR
432  if (n_basf2evt >= 50000 && n_basf2evt < 50500) {
433  cur_time = getTimeSec();
434  time_array2[ n_basf2evt - 50000 ] = cur_time - m_start_time;
435  }
436 #endif
437 
438 #ifdef CHECK_SUM
439  unsigned int checksum = 0;
440  for (int i = 0; i < m_bufary[entry][0]; i++) {
441  if (i != 2) checksum += m_bufary[entry][i];
442  }
443  m_bufary[entry][2] = checksum;
444 #endif
445  return temp_buf;
446 }
447 
448 
449 
450 void DesSerCOPPER::initializeCOPPER()
451 {
452 
453 #ifndef DUMMY
454  m_use_slot = 0; /* bit mask */
455  int slot_shift;
456 
457  if ((m_finesse_bit_flag & 0x1) == 1) {
458  slot_shift = 0; // a:0, b:1, c:2, d:3
459  m_use_slot |= 1 << slot_shift; //
460  }
461 
462  if (((m_finesse_bit_flag >> 1) & 0x1) == 1) {
463  slot_shift = 1; // a:0, b:1, c:2, d:3
464  m_use_slot |= 1 << slot_shift; //
465  }
466 
467  if (((m_finesse_bit_flag >> 2) & 0x1) == 1) {
468  slot_shift = 2; // a:0, b:1, c:2, d:3
469  m_use_slot |= 1 << slot_shift; //
470  }
471 
472  if (((m_finesse_bit_flag >> 3) & 0x1) == 1) {
473  slot_shift = 3; // a:0, b:1, c:2, d:3
474  m_use_slot |= 1 << slot_shift; //
475  }
476  //
477  // Present slots to use
478  //
479  if (! m_use_slot) {
480  char err_buf[100] = "[FATAL] Slot is not specified. Exiting...";
481  print_err.PrintError(m_shmflag, &m_status, err_buf, __FILE__, __PRETTY_FUNCTION__, __LINE__);
482  exit(1);
483  } else {
484  int slot;
485  printf("[DEBUG] ");
486  for (slot = 0; slot < 4; slot++) {
487  if (m_use_slot & (1 << slot)) printf(" %c", 'A' + slot);
488  }
489  printf("\n");
490  }
491 
492 
493 #endif
494 
495 #ifndef YAMADA_DUMMY
496  // B2INFO("Opening COPPER..."); fflush(stderr);
497  printf("[DEBUG] Opening COPPER...\n"); fflush(stdout);
498  openCOPPER();
499  // B2INFO("Done.\n"); fflush(stderr);
500  printf("[DEBUG] Done.\n"); fflush(stdout);
501 #endif
502 }
503 
504 
505 void DesSerCOPPER::openCOPPER()
506 {
507 
508  if (m_cpr_fd != -1) {
509  close(m_cpr_fd);
510  m_cpr_fd = -1;
511  }
512  //
513  // Open a finesse device
514  //
515  if ((m_cpr_fd = open("/dev/copper/copper", O_RDONLY)) == -1) {
516  char err_buf[500];
517  sprintf(err_buf, "[FATAL] Failed to open /dev/copper/copper. Exiting... ");
518  print_err.PrintError(m_shmflag, &m_status, err_buf, __FILE__, __PRETTY_FUNCTION__, __LINE__);
519  exit(1);
520  }
521 
522  int set_regval = 15; // How many events to be stored in COPPER FIFO before request for DMA
523  // int set_regval=1;
524  ioctl(m_cpr_fd, CPRIOSET_LEF_WA_FF, &set_regval);
525  ioctl(m_cpr_fd, CPRIOSET_LEF_WB_FF, &set_regval);
526  ioctl(m_cpr_fd, CPRIOSET_LEF_WC_FF, &set_regval);
527  ioctl(m_cpr_fd, CPRIOSET_LEF_WD_FF, &set_regval);
528  ioctl(m_cpr_fd, CPRIOSET_FINESSE_STA, &m_use_slot, sizeof(m_use_slot));
529 
530  int v = 511 - 32;
531 
532  ioctl(m_cpr_fd, CPRIOSET_LEF_WA_AF, &v, sizeof(v));
533  ioctl(m_cpr_fd, CPRIOSET_LEF_WB_AF, &v, sizeof(v));
534  ioctl(m_cpr_fd, CPRIOSET_LEF_WC_AF, &v, sizeof(v));
535  ioctl(m_cpr_fd, CPRIOSET_LEF_WD_AF, &v, sizeof(v));
536 
537 
538  // B2INFO("DeSerializerCOPPER: openCOPPER() done.");
539  printf("[DEBUG] DeSerializerCOPPER: openCOPPER() done.\n"); fflush(stdout);
540 
541 }
542 
543 
544 
545 int DesSerCOPPER::readFD(int fd, char* buf, int data_size_byte, int delete_flag)
546 {
547 
548  int n = 0;
549  int read_size = 0;
550  while (1) {
551  if ((read_size = read(fd, (char*)buf + n, data_size_byte - n)) < 0) {
552  if (errno == EINTR) {
553  continue;
554  } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
555  if (n > 0) {
556  char err_buf[500];
557  sprintf(err_buf, "[FATAL] Return due to EAGAIN in the middle of an event( COPPER driver would't do this.). Exting...");
558  print_err.PrintError(m_shmflag, &m_status, err_buf, __FILE__, __PRETTY_FUNCTION__, __LINE__);
559  exit(-1);
560  }
561 #ifdef NONSTOP
562  // Check run-pause request from SLC
563  string err_str;
564  try {
565  callCheckRunPause(err_str);
566  } catch (string err_str) {
567  if (delete_flag) {
568  // Delete allocated buffer
569  // B2WARNING("Delete buffer before going to Run-pause state");
570  printf("[WARNING] Delete buffer before going to Run-pause state\n"); fflush(stdout);
571  delete buf;
572  }
573  throw (err_str);
574  }
575 #endif
576  continue;
577  } else {
578 #ifdef NONSTOP
579  m_run_error = 1;
580  // B2ERROR(err_buf);
581  printf("[ERROR] Failed to read data from COPPER. %s %s %d",
582  __FILE__, __PRETTY_FUNCTION__, __LINE__);
583  string err_str = "RUN_ERROR";
584  throw (err_str);
585 #endif
586  char err_buf[500];
587  sprintf(err_buf, "[FATAL] Failed to read data from COPPER. %s %s %d",
588  __FILE__, __PRETTY_FUNCTION__, __LINE__);
589  print_err.PrintError(m_shmflag, &m_status, err_buf, __FILE__, __PRETTY_FUNCTION__, __LINE__);
590  exit(-1);
591  }
592  } else {
593  n += read_size;
594  if (n == data_size_byte)break;
595  }
596  }
597  return n;
598 }
The Raw COPPER class ver.1 ( the latest version since May, 2014 ) This class stores data received by ...
unsigned int FillTopBlockRawHeader(unsigned int m_node_id, unsigned int prev_eve32, unsigned int prev_exprunsubrun_no, unsigned int *cur_exprunsubrun_no) OVERRIDE_CPP17
should be called by DeSerializerCOPPER.cc and fill contents in RawHeader
The RawDataBlockFormat class Format information for rawdata handling.
virtual void SetBuffer(int *bufin, int nwords, int delete_flag, int num_events, int num_nodes)
set buffer ( delete_flag : m_buffer is freeed( = 0 )/ not freeed( = 1 ) in Destructer )
Abstract base class for different kinds of events.