Esempio n. 1
0
void init_data(void) {
  int verbose = 0;
  if (verbose>0) fprintf(stderr, "init_data: creating data buffer\n");
  if (header) {
    unsigned int wordsize = wordsize_from_type(header->def->data_type);

    if (wordsize==0) {
      fprintf(stderr, "init_data: unsupported data type (%u)\n", header->def->data_type);
      return;
    }
    /* heuristic of choosing size of buffer:
       set current_max_num_sample to MAXNUMSAMPLE if nchans <= 256
       otherwise, allocate about MAXNUMBYTE and calculate current_max_num_sample from nchans + wordsize
       */
    if (header->def->nchans <= 256) {
      current_max_num_sample = MAXNUMSAMPLE;
    } else {
      current_max_num_sample = MAXNUMBYTE / (wordsize * header->def->nchans);
    }
    data = (data_t*)malloc(sizeof(data_t));

    DIE_BAD_MALLOC(data);

    data->def = (datadef_t*)malloc(sizeof(datadef_t));

    DIE_BAD_MALLOC(data->def);

    data->def->nchans    = header->def->nchans;
    data->def->nsamples  = current_max_num_sample;
    data->def->data_type = header->def->data_type;
    data->buf = malloc(header->def->nchans*current_max_num_sample*wordsize);

    DIE_BAD_MALLOC(data->buf);
  }
}
Esempio n. 2
0
void init_event(void) {
  int verbose = 0;
  int i;
  if (verbose>0) fprintf(stderr, "init_event: creating event buffer\n");
  if (header) {
    event = (event_t*)malloc(MAXNUMEVENT*sizeof(event_t));
    DIE_BAD_MALLOC(event);
    for (i=0; i<MAXNUMEVENT; i++) {
      event[i].def = NULL;
      event[i].buf = NULL;
    }
  }
}
Esempio n. 3
0
/* this function deals with the incoming client request */
void *tcpsocket(void *arg) {
	int n;
	int status = 0, verbose = 0;
	int oldcancelstate, oldcanceltype;

#ifdef ENABLE_POLLING
	struct pollfd fds;
#endif

	/* these are used for communication over the TCP socket */
	int client = 0;
	message_t *request = NULL, *response = NULL;

    threadlocal_t threadlocal;
    threadlocal.message = NULL;
    threadlocal.fd = -1;

	/* the connection to the client has been made by the server */
	client = (int)arg;

    /* this will be closed at cleanup */
    threadlocal.fd = client;

    pthread_cleanup_push(cleanup_tcpsocket, &threadlocal);

    /* this is for debugging */
    pthread_mutex_lock(&mutexsocketcount);
    socketcount++;
    pthread_mutex_unlock(&mutexsocketcount);

    if (verbose>1) fprintf(stderr, "tcpsocket: client = %d, socketcount = %d, threadcount = %d\n", client, socketcount, threadcount);

	/* keep processing messages untill the connection is closed */
	while (1) {
		int swap = 0;
		UINT16_T reqCommand;
		UINT32_T respBufSize;

		request       = (message_t*)malloc(sizeof(message_t));
		DIE_BAD_MALLOC(request);
		
		request->def  = (messagedef_t*)malloc(sizeof(messagedef_t));
		DIE_BAD_MALLOC(request->def);
		request->buf  = NULL;

#ifdef ENABLE_POLLING
		/* wait for data to become available or until the connection is closed */
		/* thohar: i think this is not neccessary as we dont need a timeout. */
		/* roboos: we need it to detect when the socket is closed by the client */
		while (1) {
			fds.fd      = client;
			fds.events  = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | POLLOUT | POLLWRNORM | POLLWRBAND | POLLERR | POLLNVAL;
			fds.revents = 0;

			if (poll(&fds, 1, 1)==-1) {
				perror("poll");
				goto cleanup;
			}

			if (fds.revents & POLLHUP)
				goto cleanup;				/* the connection has been closed */
			else if (fds.revents & POLLERR)
				goto cleanup;				/* the connection has been closed */
			else if (fds.revents & POLLIN)
				break;						/* data is available, process the message */
			else
				usleep(POLLSLEEP);			/* wait for data or closed connection */
		}
#endif

		if ((n = bufread(client, request->def, sizeof(messagedef_t))) != sizeof(messagedef_t)) {
			if (verbose>0) fprintf(stderr, "tcpsocket: packet size = %d, should be %d\n", n, sizeof(messagedef_t));
			goto cleanup;
		}
		
		if (request->def->version==VERSION_OE) {
			swap = 1;
			ft_swap16(2, &request->def->version); /* version + command */
			ft_swap32(1, &request->def->bufsize);
			reqCommand = request->def->command;		
		}

		if (request->def->version!=VERSION) {
			if (verbose>0) fprintf(stderr, "tcpsocket: incorrect request version\n");
			goto cleanup;
		}
		
		if (request->def->bufsize>0) {
			request->buf = malloc(request->def->bufsize);
			DIE_BAD_MALLOC(request->buf);
			if ((n = bufread(client, request->buf, request->def->bufsize)) != request->def->bufsize) {
				if (verbose>0) fprintf(stderr, "tcpsocket: read size = %d, should be %d\n", n, request->def->bufsize);
				goto cleanup;
			}
		}
		
		if (swap && request->def->bufsize > 0) ft_swap_buf_to_native(reqCommand, request->def->bufsize, request->buf);

		if (verbose>1) print_request(request->def);
		if (verbose>1) print_buf(request->buf, request->def->bufsize);

		if ((status = dmarequest(request, &response)) != 0) {
			if (verbose>0) fprintf(stderr, "tcpsocket: an unexpected error occurred\n");
			goto cleanup;
		}
		
		DIE_BAD_MALLOC(response);
		DIE_BAD_MALLOC(response->def);
		
		if (verbose>1) print_response(response->def);
		if (verbose>1) print_buf(request->buf, request->def->bufsize);
		
		respBufSize = response->def->bufsize;
		if (swap) ft_swap_from_native(reqCommand, response);

		/* we don't need the request anymore */
		cleanup_message((void**)&request);
		request = NULL;
		
		/* merge response->def and response->buf if they are small, so we can send it in one go over TCP */
		if (respBufSize + sizeof(messagedef_t) <= MERGE_THRESHOLD) {
			int msize = respBufSize + sizeof(messagedef_t);
			void *merged = NULL;
			
			append(&merged, 0, response->def, sizeof(messagedef_t));
			DIE_BAD_MALLOC(merged);
			append(&merged, sizeof(messagedef_t), response->buf, respBufSize);
			DIE_BAD_MALLOC(merged);
						
			if ((n=bufwrite(client, merged, msize) != msize)) {
				if (verbose>0) fprintf(stderr, "tcpsocket: write size = %d, should be %d\n", n, msize);
				FREE(merged);
				goto cleanup;
			}
			FREE(merged);
		} else {
			if ((n = bufwrite(client, response->def, sizeof(messagedef_t)))!=sizeof(messagedef_t)) {
				if (verbose>0) fprintf(stderr, "tcpsocket: write size = %d, should be %d\n", n, sizeof(messagedef_t));
				goto cleanup;
			}
			if ((n = bufwrite(client, response->buf, respBufSize))!=respBufSize) {
				if (verbose>0) fprintf(stderr, "tcpsocket: write size = %d, should be %d\n", n, respBufSize);
				goto cleanup;
			}
		}

		cleanup_message((void**)&response);
        response = NULL;

	} /* while (1) */

cleanup:
    printf(""); /* otherwise the pthread_cleanup_pop won't compile */

	if (response!=NULL) 
		cleanup_message((void**)&response);
	response = NULL;	/* SK: prevent double free in following pthread_cleanup_pop */

	pthread_cleanup_pop(1);

    /* this is for debugging */
    pthread_mutex_lock(&mutexsocketcount);
    socketcount--;
    pthread_mutex_unlock(&mutexsocketcount);

    /* this is for debugging */
    pthread_mutex_lock(&mutexthreadcount);
    threadcount--;
    pthread_mutex_unlock(&mutexthreadcount);

	pthread_exit(NULL);
	return NULL;
}
Esempio n. 4
0
/***************************************************************************** 
 * this function handles the direct memory access to the buffer
 * and copies objects to and from memory
 *****************************************************************************/
int dmarequest(const message_t *request, message_t **response_ptr) {
  unsigned int offset;
  /*
     int blockrequest = 0;
     */
  int verbose = 0;

  /* these are used for blocking the read requests */
  struct timeval tp;
  struct timespec ts;

  /* use a local variable for datasel (in GET_DAT) */
  datasel_t datasel;

  /* these are for typecasting */
  headerdef_t    *headerdef;
  datadef_t      *datadef;
  eventdef_t     *eventdef;
  eventsel_t     *eventsel;

  /* this will hold the response */
  message_t *response;
  response      = (message_t*)malloc(sizeof(message_t));

  /* check for "out of memory" problems */
  if (response == NULL) {
    *response_ptr = NULL;
    return -1;
  }
  response->def = (messagedef_t*)malloc(sizeof(messagedef_t));

  /* check for "out of memory" problems */
  if (response->def == NULL) {
    *response_ptr = NULL;
    free(response);
    return -1;
  }
  response->buf = NULL;
  /* the response should be passed to the calling function, where it should be freed */
  *response_ptr = response;

  if (verbose>1) print_request(request->def);

  switch (request->def->command) {

    case PUT_HDR:
      if (verbose>1) fprintf(stderr, "dmarequest: PUT_HDR\n");
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexdata);
      pthread_mutex_lock(&mutexevent);

      headerdef = (headerdef_t*)request->buf;
      if (verbose>1) print_headerdef(headerdef);

      /* delete the old header, data and events */
      free_header();
      free_data();
      free_event();

      /* store the header and re-initialize */
      header      = (header_t*)malloc(sizeof(header_t));
      DIE_BAD_MALLOC(header);
      header->def = (headerdef_t*)malloc(sizeof(headerdef_t));
      DIE_BAD_MALLOC(header->def);
      header->buf = malloc(headerdef->bufsize);
      DIE_BAD_MALLOC(header->buf);
      memcpy(header->def, request->buf, sizeof(headerdef_t));
      memcpy(header->buf, (char*)request->buf+sizeof(headerdef_t), headerdef->bufsize);
      header->def->nsamples = 0;
      header->def->nevents  = 0;

      init_data();
      init_event();

      response->def->version = VERSION;
      response->def->bufsize = 0;
      /* check whether memory could indeed be allocated */
      if (data!= NULL && data->buf != NULL && data->def != NULL) {
        response->def->command = PUT_OK;
      } else {
        /* let's at least tell the client that something's wrong */
        response->def->command = PUT_ERR;	
      }

      pthread_mutex_unlock(&mutexevent);
      pthread_mutex_unlock(&mutexdata);
      pthread_mutex_unlock(&mutexheader);
      break;

    case PUT_DAT:
      if (verbose>1) fprintf(stderr, "dmarequest: PUT_DAT\n");
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexdata);

      datadef = (datadef_t*)request->buf;
      if (verbose>1) print_datadef(datadef);
      if (verbose>2) print_buf(request->buf, request->def->bufsize);

      response->def->version = VERSION;
      response->def->bufsize = 0;
      if (request->def->bufsize < sizeof(datadef_t))
        response->def->command = PUT_ERR;
      else if (header==NULL || data==NULL)
        response->def->command = PUT_ERR;
      else if (header->def->nchans != datadef->nchans)
        response->def->command = PUT_ERR;
      else if (header->def->data_type != datadef->data_type)
        response->def->command = PUT_ERR;
      else if (datadef->nsamples > current_max_num_sample)
        response->def->command = PUT_ERR;
      else {
        unsigned int i;
        unsigned int wordsize = wordsize_from_type(header->def->data_type);
        unsigned int datasize = wordsize * datadef->nsamples * datadef->nchans;

        response->def->command = PUT_OK;

        if (wordsize == 0) {
          fprintf(stderr, "dmarequest: unsupported data type (%d)\n", datadef->data_type);
          response->def->command = PUT_ERR;
        } else if (datasize > datadef->bufsize || (datadef->bufsize + sizeof(datadef_t)) > request->def->bufsize) {
          fprintf(stderr, "dmarequest: invalid size definitions in PUT_DAT request\n");
          response->def->command = PUT_ERR;
        } else {

          /* record the time at which the data was received */
          if (clock_gettime(CLOCK_REALTIME, &putdat_clock) != 0) {
            perror("clock_gettime");
            return -1;
          }

          /* number of bytes per sample (all channels) is given by wordsize x number of channels */
          unsigned int chansize = wordsize * data->def->nchans;
          /* request_data points to actual data samples within the request, use char* for convenience */
          const char *request_data = (const char *) request->buf + sizeof(datadef_t);
          char *buffer_data = (char *)data->buf;

          for (i=0; i<datadef->nsamples; i++) {
            memcpy(buffer_data+(thissample*chansize), request_data+(i*chansize), chansize);
            header->def->nsamples++;
            thissample++;
            thissample = WRAP(thissample, current_max_num_sample);
          }
          /* Signal possibly waiting threads that we have received data */
          pthread_cond_broadcast(&getData_cond);
        }
      }

      pthread_mutex_unlock(&mutexdata);
      pthread_mutex_unlock(&mutexheader);
      break;

    case PUT_EVT:
      if (verbose>1) fprintf(stderr, "dmarequest: PUT_EVT\n");
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexevent);

      /* record the time at which the event was received */
      if (clock_gettime(CLOCK_REALTIME, &putevt_clock) != 0) {
        perror("clock_gettime");
        return -1;
      }

      /* Give an error message if there is no header, or if the given event array is defined badly */
      if (header==NULL || event==NULL || check_event_array(request->def->bufsize, request->buf) < 0) {
        response->def->version = VERSION;
        response->def->command = PUT_ERR;
        response->def->bufsize = 0;
      }
      else {	/* go over all events and store them one by one */
        response->def->version = VERSION;
        response->def->command = PUT_OK;
        response->def->bufsize = 0;

        offset = 0; /* this represents the offset of the event in the buffer */
        while (offset<request->def->bufsize) {
          FREE(event[thisevent].def);
          FREE(event[thisevent].buf);

          eventdef = (eventdef_t*)((char*)request->buf+offset);
          if (verbose>1) print_eventdef(eventdef);

          event[thisevent].def = (eventdef_t*)malloc(sizeof(eventdef_t));
          DIE_BAD_MALLOC(event[thisevent].def);
          memcpy(event[thisevent].def, (char*)request->buf+offset, sizeof(eventdef_t));

          if (event[thisevent].def->sample == EVENT_AUTO_SAMPLE) {
            /* automatically convert event->def->sample to current sample number */
            /* make some fine adjustment of the assigned sample number */
            double adjust = (putevt_clock.tv_sec - putdat_clock.tv_sec) + (double)(putevt_clock.tv_nsec - putdat_clock.tv_nsec) / 1000000000L;
            event[thisevent].def->sample = header->def->nsamples + (int)(header->def->fsample*adjust);
          }

          offset += sizeof(eventdef_t);
          event[thisevent].buf = malloc(eventdef->bufsize);
          DIE_BAD_MALLOC(event[thisevent].buf);
          memcpy(event[thisevent].buf, (char*)request->buf+offset, eventdef->bufsize);
          offset += eventdef->bufsize;
          if (verbose>1) print_eventdef(event[thisevent].def);
          thisevent++;
          thisevent = WRAP(thisevent, MAXNUMEVENT);
          header->def->nevents++;
        }
      }

      pthread_mutex_unlock(&mutexevent);
      pthread_mutex_unlock(&mutexheader);
      break;

    case GET_HDR:
      if (verbose>1) fprintf(stderr, "dmarequest: GET_HDR\n");
      if (header==NULL) {
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
        break;
      }

      pthread_mutex_lock(&mutexheader);

      response->def->version = VERSION;
      response->def->command = GET_OK;
      response->def->bufsize = 0;
      response->def->bufsize = append(&response->buf, response->def->bufsize, header->def, sizeof(headerdef_t));
      response->def->bufsize = append(&response->buf, response->def->bufsize, header->buf, header->def->bufsize);

      pthread_mutex_unlock(&mutexheader);
      break;

    case GET_DAT:
      if (verbose>1) fprintf(stderr, "dmarequest: GET_DAT\n");
      if (header==NULL || data==NULL) {
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
        break;
      }

      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexdata);

      if (request->def->bufsize) {
        /* the selection has been specified */
        memcpy(&datasel, request->buf, sizeof(datasel_t));
        /* If endsample is -1 read the buffer to the end */
        if(datasel.endsample == -1)
        {
          datasel.endsample = header->def->nsamples - 1;
        }
      }
      else {
        /* determine a valid selection */
        if (header->def->nsamples>current_max_num_sample) {
          /* the ringbuffer is completely full */
          datasel.begsample = header->def->nsamples - current_max_num_sample;
          datasel.endsample = header->def->nsamples - 1;
        }
        else {
          /* the ringbuffer is not yet completely full */
          datasel.begsample = 0;
          datasel.endsample = header->def->nsamples - 1;
        }
      }

      /*

      // if the read should block...
      if(blockrequest == 1)
      {
      // check whether data is available
      while((datasel.begsample >= (datasel.endsample+1)) || (datasel.endsample > header->def->nsamples - 1))
      {
      // if not unlock all mutexes
      pthread_mutex_unlock(&mutexdata);
      pthread_mutex_unlock(&mutexheader);

      // wait for the condition to be signaled
      pthread_mutex_lock(&getData_mutex);
      gettimeofday(&tp, NULL);
      ts.tv_sec = tp.tv_sec;
      ts.tv_nsec = tp.tv_usec * 1000;
      ts.tv_sec += 1;
      pthread_cond_timedwait(&getData_cond, &getData_mutex, &ts);
      pthread_mutex_unlock(&getData_mutex);

      // Lock the mutexes again
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexdata);
      if(datasel.begsample == (datasel.endsample+1))
      datasel.endsample = header->def->nsamples - 1;
      }
      }
      */

      if (verbose>1) print_headerdef(header->def);
      if (verbose>1) print_datasel(&datasel);

      if (datasel.begsample < 0 || datasel.endsample < 0) {
        fprintf(stderr, "dmarequest: err1\n");
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else if (datasel.begsample >= header->def->nsamples || datasel.endsample >= header->def->nsamples) {
        fprintf(stderr, "dmarequest: err2\n");
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else if ((header->def->nsamples - datasel.begsample) > current_max_num_sample) {
        fprintf(stderr, "dmarequest: err3\n");
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else {
        unsigned int wordsize = wordsize_from_type(data->def->data_type);
        if (wordsize==0) {
          fprintf(stderr, "dmarequest: unsupported data type (%d)\n", data->def->data_type);
          response->def->version = VERSION;
          response->def->command = GET_ERR;
          response->def->bufsize = 0;
        }  else {
          unsigned int n;
          response->def->version = VERSION;
          response->def->command = GET_OK;
          response->def->bufsize = 0;

          /* determine the number of samples to return */
          n = datasel.endsample - datasel.begsample + 1;

          response->buf = malloc(sizeof(datadef_t) + n*data->def->nchans*wordsize);
          if (response->buf == NULL) {
            /* not enough space for copying data into response */
            fprintf(stderr, "dmarequest: out of memory\n");
            response->def->command = GET_ERR;
          } 
          else {
            /* number of bytes per sample (all channels) */
            unsigned int chansize = data->def->nchans * wordsize;

            /* convenience pointer to start of actual data in response */
            char *resp_data = ((char *) response->buf) + sizeof(datadef_t);

            /* this is the location of begsample within the ringbuffer */
            unsigned int start_index = 	WRAP(datasel.begsample, current_max_num_sample);

            /* have datadef point into the freshly allocated response buffer and directly
               fill in the information */
            datadef = (datadef_t *) response->buf;
            datadef->nchans    = data->def->nchans;
            datadef->data_type = data->def->data_type;
            datadef->nsamples  = n;
            datadef->bufsize   = n*chansize;

            response->def->bufsize = sizeof(datadef_t) + datadef->bufsize;

            if (start_index + n <= current_max_num_sample) {
              /* we can copy everything in one go */
              memcpy(resp_data, (char*)(data->buf) + start_index*chansize, n*chansize);
            } else {
              /* need to wrap around at current_max_num_sample */
              unsigned int na = current_max_num_sample - start_index;
              unsigned int nb = n - na;

              memcpy(resp_data, (char*)(data->buf) + start_index*chansize, na*chansize);
              memcpy(resp_data + na*chansize, (char*)(data->buf), nb*chansize);

              /* printf("Wrapped around!\n"); */
            }
          }
        }
      }

      pthread_mutex_unlock(&mutexdata);
      pthread_mutex_unlock(&mutexheader);
      break;

    case GET_EVT:
      if (verbose>1) fprintf(stderr, "dmarequest: GET_EVT\n");
      if (header==NULL || event==NULL || header->def->nevents==0) {
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
        break;
      }

      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexevent);

      eventsel = (eventsel_t*)malloc(sizeof(eventsel_t));
      DIE_BAD_MALLOC(eventsel);

      /* determine the selection */
      if (request->def->bufsize) {
        /* the selection has been specified */
        memcpy(eventsel, request->buf, sizeof(eventsel_t));
      }
      else {
        /* determine a valid selection */
        if (header->def->nevents>MAXNUMEVENT) {
          /* the ringbuffer is completely full */
          eventsel->begevent = header->def->nevents - MAXNUMEVENT;
          eventsel->endevent = header->def->nevents - 1;
        }
        else {
          /* the ringbuffer is not yet completely full */
          eventsel->begevent = 0;
          eventsel->endevent = header->def->nevents - 1;
        }
      }

      if (verbose>1) print_headerdef(header->def);
      if (verbose>1) print_eventsel(eventsel);

      if (eventsel==NULL) {
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else if (eventsel->begevent < 0 || eventsel->endevent < 0) {
        fprintf(stderr, "dmarequest: err1\n");
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else if (eventsel->begevent >= header->def->nevents || eventsel->endevent >= header->def->nevents) {
        fprintf(stderr, "dmarequest: err2\n");
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else if ((header->def->nevents-eventsel->begevent) > MAXNUMEVENT) {
        fprintf(stderr, "dmarequest: err3\n");
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else {
        unsigned int j,n;

        response->def->version = VERSION;
        response->def->command = GET_OK;
        response->def->bufsize = 0;

        /* determine the number of events to return */
        n = eventsel->endevent - eventsel->begevent + 1;

        for (j=0; j<n; j++) {
          if (verbose>1) print_eventdef(event[WRAP(eventsel->begevent+j, MAXNUMEVENT)].def);
          response->def->bufsize = append(&response->buf, response->def->bufsize, event[WRAP(eventsel->begevent+j, MAXNUMEVENT)].def, sizeof(eventdef_t));
          response->def->bufsize = append(&response->buf, response->def->bufsize, event[WRAP(eventsel->begevent+j, MAXNUMEVENT)].buf, event[WRAP(eventsel->begevent+j, MAXNUMEVENT)].def->bufsize);
        }
      }

      FREE(eventsel);
      pthread_mutex_unlock(&mutexevent);
      pthread_mutex_unlock(&mutexheader);
      break;

    case FLUSH_HDR:
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexdata);
      pthread_mutex_lock(&mutexevent);
      if (header) {
        free_header();
        free_data();
        free_event();
        response->def->version = VERSION;
        response->def->command = FLUSH_OK;
        response->def->bufsize = 0;
      }
      else {
        response->def->version = VERSION;
        response->def->command = FLUSH_ERR;
        response->def->bufsize = 0;
      }
      pthread_mutex_unlock(&mutexevent);
      pthread_mutex_unlock(&mutexdata);
      pthread_mutex_unlock(&mutexheader);
      break;

    case FLUSH_DAT:
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexdata);
      if (header && data) {
        header->def->nsamples = thissample = 0;
        response->def->version = VERSION;
        response->def->command = FLUSH_OK;
        response->def->bufsize = 0;
      }
      else {
        response->def->version = VERSION;
        response->def->command = FLUSH_ERR;
        response->def->bufsize = 0;
      }
      pthread_mutex_unlock(&mutexdata);
      pthread_mutex_unlock(&mutexheader);
      break;

    case FLUSH_EVT:
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexevent);
      if (header && event) {
        unsigned int i;

        header->def->nevents = thisevent = 0;
        for (i=0; i<MAXNUMEVENT; i++) {
          FREE(event[i].def);
          FREE(event[i].buf);
        }
        response->def->version = VERSION;
        response->def->command = FLUSH_OK;
        response->def->bufsize = 0;
      }
      else {
        response->def->version = VERSION;
        response->def->command = FLUSH_ERR;
        response->def->bufsize = 0;
      }
      pthread_mutex_unlock(&mutexevent);
      pthread_mutex_unlock(&mutexheader);
      break;

    case WAIT_DAT:
      /* SK: This request means that the client wants to wait until
         MORE than waitdef_t.threshold.nsamples samples OR 
         MORE THAN waitdef_t.threshold.nevents events 
         are in the buffer, BUT 
         only for the time given in waitdef_t.milliseconds. 
         The response is just the number of samples and events 
         in the buffer as described by samples_events_t.
         */
      response->def->version = VERSION;
      if (header==NULL || request->def->bufsize!=sizeof(waitdef_t)) {
        response->def->command = WAIT_ERR;
        response->def->bufsize = 0;
      } else {
        int waiterr;
        waitdef_t *wd = (waitdef_t *) request->buf;
        samples_events_t *nret = malloc(sizeof(samples_events_t));
        UINT32_T nsmp, nevt;

        if (nret == NULL) {
          /* highly unlikely, but we cannot allocate a sample_event_t - return an error */
          response->def->command = WAIT_ERR;
          response->def->bufsize = 0;
          break;
        }
        /* Let response->buf point to the new sample_event_t structure */
        response->def->command = WAIT_OK;
        response->def->bufsize = sizeof(samples_events_t);
        response->buf = nret;

        /* get current number of samples */
        pthread_mutex_lock(&mutexheader);
        nsmp = header->def->nsamples;
        nevt = header->def->nevents;
        pthread_mutex_unlock(&mutexheader);

        if (wd->milliseconds == 0 || nsmp > wd->threshold.nsamples || nevt > wd->threshold.nevents) {
          /* the client doesn't want to wait, or
             we're already above the threshold: 
             return immediately */
          nret->nsamples = nsmp;
          nret->nevents = nevt;
          break;
        }
        gettimeofday(&tp, NULL);
        ts.tv_sec = tp.tv_sec + (wd->milliseconds/1000);
        ts.tv_nsec = 1000 * (tp.tv_usec + (wd->milliseconds % 1000)*1000);
        while (ts.tv_nsec >= 1000000000) {
          ts.tv_sec++;
          ts.tv_nsec-=1000000000;
        }

        /* FIXME: The getData condition variable is only triggered by incoming data, not events */
        do {
          pthread_mutex_lock(&getData_mutex);
          waiterr = pthread_cond_timedwait(&getData_cond, &getData_mutex, &ts);
          pthread_mutex_unlock(&getData_mutex);

          /* get current number of samples */
          pthread_mutex_lock(&mutexheader);
          nsmp = header->def->nsamples;
          nevt = header->def->nevents;
          pthread_mutex_unlock(&mutexheader);
        } while (nsmp <= wd->threshold.nsamples && nevt <= wd->threshold.nevents && waiterr==0);
        nret->nsamples = nsmp;
        nret->nevents = nevt;				
      }
      break;
    default:
      fprintf(stderr, "dmarequest: unknown command\n");
  }

  if (verbose>0) fprintf(stderr, "dmarequest: thissample = %u, thisevent = %u\n", thissample, thisevent);

  /* everything went fine */
  return 0;
}