On 10/28/2011 10:49 PM, Sven Geggus wrote:
Christian Grothoff schrieb am Freitag, den 28. Oktober um 15:01 Uhr:

Well, that's technically not required.  You can simply integrate your data-
polling loop into the external select loop of MHD and in the response
callbacks for data-aquisition return 0 (which will be interpreted as "no data
available yet, try again in the next round of select").  Note that MHD will
then NOT put the respective sockets into your write set, so you would not end
up busy-waiting.

Hm, looks like I do not fully understand this suggestion :(

Attached is a modified version fo your fileserver_example_external_select.c
example.

I just added a (fake) data acquisition loop which is currently using a 4
second interval.  But how can I synchronice the http output for the
http data requests via http (and only for these) now?

Sven


I've attached a completed example that writes every 4s a "Round %d" string to the client (based on the trigger). I've added comments where appropriate.

Happy hacking,

Christian
#include <stdio.h>
#include <stdlib.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <string.h>
#include <microhttpd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

#define PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"

static int acgen;

static ssize_t file_reader (void *cls, uint64_t pos, char *buf, size_t max) {
  int * gp = cls;
  ssize_t ret;

  if (*gp == acgen) 
    return 0; /* no data */
  ret = 0;
  while ( (max > ret + 20) && ((*gp) < acgen) )
  {
    ret += snprintf (&buf[ret], max - ret, "Round %d\n", acgen);
    (*gp)++; /* remember how many rounds we did transmit to this client so far */
  }
  return ret;
}

static void free_callback (void *cls) {
  fprintf (stderr, "freeing reader\n");
  free (cls);
}

static int ahc_echo (void *cls,
		     struct MHD_Connection *connection,
		     const char *url,
		     const char *method,
		     const char *version,
		     const char *upload_data,
		     size_t *upload_data_size, void **ptr) {
  static int aptr;
  struct MHD_Response *response;
  int ret;
  int *gp;
  struct stat buf;

  if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
    return MHD_NO;              /* unexpected method */
  if (&aptr != *ptr)
    {
      /* do never respond on first call */
      *ptr = &aptr;
      return MHD_YES;
    }
  *ptr = NULL;                  /* reset when done */
  gp = malloc (sizeof (int));
  *gp = acgen; /* current generation -- to only send rounds from connect on */
  if (NULL == gp)
    return MHD_NO;
  fprintf (stderr, "creating reader\n");
  response = MHD_create_response_from_callback (buf.st_size, 32 * 1024,     /* 32k page size */
						&file_reader,
						gp,
						&free_callback);
  if (response == NULL)
    {
      free (gp);
      return MHD_NO;
    }
  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
  MHD_destroy_response (response);    
  return ret;
}

int main () {
  struct MHD_Daemon *d;
  fd_set rs;
  fd_set ws;
  fd_set es;
  int max,rtcfd;
  unsigned long data;
  int tirq,acqdelay=4;

  d = MHD_start_daemon (MHD_USE_DEBUG,
                        8888,
                        NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
  if (d == NULL)
    return 1;

  rtcfd = open("/dev/rtc0", O_RDONLY);
  if (rtcfd ==  -1) {
    fprintf(stderr,"error opening /dev/rtc0");
    exit(EXIT_FAILURE);
  }
  /* Turn on update interrupts (one per second) */
  ioctl(rtcfd, RTC_UIE_ON, 0);

  tirq=acqdelay-1;
  while (1) {
    max = 0;
    FD_ZERO (&rs);
    FD_ZERO (&ws);
    FD_ZERO (&es);

    if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
      break; /* fatal internal error */

    FD_SET(rtcfd,&rs);
    if (rtcfd >max) max=rtcfd;
    
    select (max + 1, &rs, &ws, &es, NULL);
    if (FD_ISSET(rtcfd,&rs)) {
      read(rtcfd, &data, sizeof(unsigned long));
      tirq++;
      if (tirq==acqdelay) {
	acgen++; /* count up generation to trigger transmission */
	printf("do data acq here\n");
	tirq=0;
      }
    }
    /* NOTE: *always* run MHD_run() in external select loop! */
    MHD_run (d);    
  }
  MHD_stop_daemon (d);
  return 0;
}

Reply via email to