Commit 5fb4279e authored by Dirk Manske's avatar Dirk Manske Committed by Daniel Stenberg
Browse files

multi & hiper examples: updates and cleanups

all multi and hiper examples:

* don't loop curl_multi_perform calls, that was <7.20.0 style, currently
  the exported multi functions will not return CURLM_CALL_MULTI_PERFORM

all hiper examples:
* renamed check_run_count to check_multi_info
* don't  compare current running handle count with previous value, this
  was the wrong way to check for finished requests, simply call
  curl_multi_info_read
* it's also safe to call curl_multi_remove_handle inside the
  curl_multi_info_read loop.

ghiper.c:
* replaced curl_multi_socket (that function is marked as obsolete) calls
  with curl_multi_socket_action calls (as in hiperfifo.c and
  evhiperfifo.c)

ghiper.c and evhiperfifo.c:
* be smart as hiperfifo.c, don't do uncessary curl_multi_* calls in
  new_conn and main
parent 67c83eb9
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ int main(void)
  }

  while (U) {
    while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(cm, &U));
    curl_multi_perform(cm, &U);

    if (U) {
      FD_ZERO(&R);
+34 −64
Original line number Diff line number Diff line
@@ -68,7 +68,6 @@ typedef struct _GlobalInfo
  struct ev_io fifo_event;
  struct ev_timer timer_event;
  CURLM *multi;
  int prev_running;
  int still_running;
  FILE* input;
} GlobalInfo;
@@ -122,7 +121,6 @@ static void mcode_or_die(const char *where, CURLMcode code)
    switch ( code )
    {
    case CURLM_CALL_MULTI_PERFORM: s="CURLM_CALL_MULTI_PERFORM"; break;
    case CURLM_OK:                 s="CURLM_OK";                 break;
    case CURLM_BAD_HANDLE:         s="CURLM_BAD_HANDLE";         break;
    case CURLM_BAD_EASY_HANDLE:    s="CURLM_BAD_EASY_HANDLE";    break;
    case CURLM_OUT_OF_MEMORY:      s="CURLM_OUT_OF_MEMORY";      break;
@@ -144,39 +142,20 @@ static void mcode_or_die(const char *where, CURLMcode code)


/* Check for completed transfers, and remove their easy handles */
static void check_run_count(GlobalInfo *g)
static void check_multi_info(GlobalInfo *g)
{
  DPRINT("%s prev %i still %i\n", __PRETTY_FUNCTION__,
         g->prev_running, g->still_running);
  if ( g->prev_running > g->still_running )
  {
    char *eff_url=NULL;
  char *eff_url;
  CURLMsg *msg;
  int msgs_left;
    ConnInfo *conn=NULL;
  ConnInfo *conn;
  CURL *easy;
  CURLcode res;

  fprintf(MSG_OUT, "REMAINING: %d\n", g->still_running);
    /*
      I am still uncertain whether it is safe to remove an easy
      handle from inside the curl_multi_info_read loop, so here I
      will search for completed transfers in the inner "while"
      loop, and then remove them in the outer "do-while" loop...
    */
    do
    {
      easy=NULL;
      while ( (msg = curl_multi_info_read(g->multi, &msgs_left)) )
      {
        if ( msg->msg == CURLMSG_DONE )
        {
  while ((msg = curl_multi_info_read(g->multi, &msgs_left))) {
    if (msg->msg == CURLMSG_DONE) {
      easy = msg->easy_handle;
      res = msg->data.result;
        }

        if ( easy )
        {
      curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn);
      curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url);
      fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, res, conn->error);
@@ -186,12 +165,10 @@ static void check_run_count(GlobalInfo *g)
      free(conn);
    }
  }
    } while ( easy );
  }
  g->prev_running = g->still_running;
}



/* Called by libevent when we get action on a multi socket */
static void event_cb(EV_P_ struct ev_io *w, int revents)
{
@@ -201,12 +178,9 @@ static void event_cb(EV_P_ struct ev_io *w, int revents)

  int action = (revents&EV_READ?CURL_POLL_IN:0)|
    (revents&EV_WRITE?CURL_POLL_OUT:0);
  do
  {
  rc = curl_multi_socket_action(g->multi, w->fd, action, &g->still_running);
  } while ( rc == CURLM_CALL_MULTI_PERFORM );
  mcode_or_die("event_cb: curl_multi_socket", rc);
  check_run_count(g);
  mcode_or_die("event_cb: curl_multi_socket_action", rc);
  check_multi_info(g);
  if ( g->still_running <= 0 )
  {
    fprintf(MSG_OUT, "last transfer done, kill timeout\n");
@@ -222,12 +196,9 @@ static void timer_cb(EV_P_ struct ev_timer *w, int revents)
  GlobalInfo *g = (GlobalInfo *)w->data;
  CURLMcode rc;

  do
  {
  rc = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0, &g->still_running);
  } while ( rc == CURLM_CALL_MULTI_PERFORM );
  mcode_or_die("timer_cb: curl_multi_socket", rc);
  check_run_count(g);
  mcode_or_die("timer_cb: curl_multi_socket_action", rc);
  check_multi_info(g);
}

/* Clean up the SockInfo structure */
@@ -367,8 +338,8 @@ static void new_conn(char *url, GlobalInfo *g )
  rc = curl_multi_add_handle(g->multi, conn->easy);
  mcode_or_die("new_conn: curl_multi_add_handle", rc);

  mcode_or_die("new_conn: curl_multi_socket_all", rc);
  check_run_count(g);
  /* note that the add_handle() will set a time-out to trigger very soon so
     that the necessary socket_action() call will be called by this app */
}

/* This gets called whenever data is received from the fifo */
@@ -448,10 +419,9 @@ int main(int argc, char **argv)
  curl_multi_setopt(g.multi, CURLMOPT_SOCKETDATA, &g);
  curl_multi_setopt(g.multi, CURLMOPT_TIMERFUNCTION, multi_timer_cb);
  curl_multi_setopt(g.multi, CURLMOPT_TIMERDATA, &g);
  do
  {
    rc = curl_multi_socket_all(g.multi, &g.still_running);
  } while ( CURLM_CALL_MULTI_PERFORM == rc );

  /* we don't call any curl_multi_socket*() function yet as we have no handles
     added! */

  ev_loop(g.loop, 0);
  curl_multi_cleanup(g.multi);
+2 −8
Original line number Diff line number Diff line
@@ -184,12 +184,7 @@ fill_buffer(URL_FILE *file,int want,int waittime)

        default:
            /* timeout or readable/writable sockets */
            /* note we *could* be more efficient and not wait for
             * CURLM_CALL_MULTI_PERFORM to clear here and check it on re-entry
             * but that gets messy */
            while(curl_multi_perform(multi_handle, &file->still_running) ==
                  CURLM_CALL_MULTI_PERFORM);

            curl_multi_perform(multi_handle, &file->still_running);
            break;
        }
    } while(file->still_running && (file->buffer_pos < want));
@@ -260,8 +255,7 @@ url_fopen(const char *url,const char *operation)
        curl_multi_add_handle(multi_handle, file->handle.curl);

        /* lets start the fetch */
        while(curl_multi_perform(multi_handle, &file->still_running) ==
              CURLM_CALL_MULTI_PERFORM );
        curl_multi_perform(multi_handle, &file->still_running);

        if((file->buffer_pos == 0) && (!file->still_running))
        {
+41 −62
Original line number Diff line number Diff line
@@ -58,10 +58,7 @@ callback.
typedef struct _GlobalInfo {
  CURLM *multi;
  guint timer_event;
  int prev_running;
  int still_running;
  int requested; /* count: curl_easy_init() */
  int completed; /* count: curl_easy_cleanup() */
} GlobalInfo;


@@ -95,7 +92,6 @@ static void mcode_or_die(const char *where, CURLMcode code) {
    const char *s;
    switch (code) {
      case     CURLM_CALL_MULTI_PERFORM: s="CURLM_CALL_MULTI_PERFORM"; break;
      case     CURLM_OK:                 s="CURLM_OK";                 break;
      case     CURLM_BAD_HANDLE:         s="CURLM_BAD_HANDLE";         break;
      case     CURLM_BAD_EASY_HANDLE:    s="CURLM_BAD_EASY_HANDLE";    break;
      case     CURLM_OUT_OF_MEMORY:      s="CURLM_OUT_OF_MEMORY";      break;
@@ -113,62 +109,43 @@ static void mcode_or_die(const char *where, CURLMcode code) {


/* Check for completed transfers, and remove their easy handles */
static void check_run_count(GlobalInfo *g)
static void check_multi_info(GlobalInfo *g)
{
  if (g->prev_running > g->still_running) {
    char *eff_url=NULL;
  char *eff_url;
  CURLMsg *msg;
  int msgs_left;
    ConnInfo *conn=NULL;
  ConnInfo *conn;
  CURL *easy;
  CURLcode res;

  MSG_OUT("REMAINING: %d\n", g->still_running);
    /*
      I am still uncertain whether it is safe to remove an easy handle
      from inside the curl_multi_info_read loop, so here I will search
      for completed transfers in the inner "while" loop, and then remove
      them in the outer "do-while" loop...
   */
    do {
      easy=NULL;
  while ((msg = curl_multi_info_read(g->multi, &msgs_left))) {
    if (msg->msg == CURLMSG_DONE) {
      easy = msg->easy_handle;
      res = msg->data.result;
          break;
        }
      }
      if (easy) {
      curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn);
      curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url);
      MSG_OUT("DONE: %s => (%d) %s\n", eff_url, res, conn->error);
      curl_multi_remove_handle(g->multi, easy);
          g_free(conn->url);
      free(conn->url);
      curl_easy_cleanup(easy);
          g_free(conn);
          g->completed++;
      free(conn);
    }
    } while ( easy );
    MSG_OUT("Requested: %d Completed:%d\n", g->requested, g->completed);
  }
  g->prev_running = g->still_running;
}




/* Called by glib when our timeout expires */
static gboolean timer_cb(gpointer data)
{
  GlobalInfo *g = (GlobalInfo *)data;
  CURLMcode rc;

  do {
    rc = curl_multi_socket(g->multi, CURL_SOCKET_TIMEOUT, &g->still_running);
  } while (rc == CURLM_CALL_MULTI_PERFORM);
  mcode_or_die("timer_cb: curl_multi_socket", rc);
  check_run_count(g);
  rc = curl_multi_socket_action(g->multi,
                                  CURL_SOCKET_TIMEOUT, 0, &g->still_running);
  mcode_or_die("timer_cb: curl_multi_socket_action", rc);
  check_multi_info(g);
  return FALSE;
}

@@ -198,11 +175,15 @@ static gboolean event_cb(GIOChannel *ch, GIOCondition condition, gpointer data)
  GlobalInfo *g = (GlobalInfo*) data;
  CURLMcode rc;
  int fd=g_io_channel_unix_get_fd(ch);
  do {
    rc = curl_multi_socket(g->multi, fd, &g->still_running);
  } while (rc == CURLM_CALL_MULTI_PERFORM);
  mcode_or_die("event_cb: curl_multi_socket", rc);
  check_run_count(g);

  int action =
    (condition & G_IO_IN ? CURL_CSELECT_IN : 0) |
    (condition & G_IO_OUT ? CURL_CSELECT_OUT : 0);

  rc = curl_multi_socket_action(g->multi, fd, action, &g->still_running);
  mcode_or_die("event_cb: curl_multi_socket_action", rc);

  check_multi_info(g);
  if(g->still_running) {
    return TRUE;
  } else {
@@ -338,12 +319,9 @@ static void new_conn(char *url, GlobalInfo *g )
  MSG_OUT("Adding easy %p to multi %p (%s)\n", conn->easy, g->multi, url);
  rc =curl_multi_add_handle(g->multi, conn->easy);
  mcode_or_die("new_conn: curl_multi_add_handle", rc);
  g->requested++;
  do {
    rc = curl_multi_socket_all(g->multi, &g->still_running);
  } while (CURLM_CALL_MULTI_PERFORM == rc);
  mcode_or_die("new_conn: curl_multi_socket_all", rc);
  check_run_count(g);

  /* note that the add_handle() will set a time-out to trigger very soon so
     that the necessary socket_action() call will be called by this app */
}


@@ -451,9 +429,10 @@ int main(int argc, char **argv)
  curl_multi_setopt(g->multi, CURLMOPT_SOCKETDATA, g);
  curl_multi_setopt(g->multi, CURLMOPT_TIMERFUNCTION, update_timeout_cb);
  curl_multi_setopt(g->multi, CURLMOPT_TIMERDATA, g);
  do {
    rc = curl_multi_socket_all(g->multi, &g->still_running);
  } while (CURLM_CALL_MULTI_PERFORM == rc);

  /* we don't call any curl_multi_socket*() function yet as we have no handles
     added! */

  g_main_loop_run(gmain);
  curl_multi_cleanup(g->multi);
  return 0;
+28 −50
Original line number Diff line number Diff line
@@ -62,7 +62,6 @@ typedef struct _GlobalInfo {
  struct event fifo_event;
  struct event timer_event;
  CURLM *multi;
  int prev_running;
  int still_running;
  FILE* input;
} GlobalInfo;
@@ -110,7 +109,6 @@ static void mcode_or_die(const char *where, CURLMcode code)
    const char *s;
    switch (code) {
      case     CURLM_CALL_MULTI_PERFORM: s="CURLM_CALL_MULTI_PERFORM"; break;
      case     CURLM_OK:                 s="CURLM_OK";                 break;
      case     CURLM_BAD_HANDLE:         s="CURLM_BAD_HANDLE";         break;
      case     CURLM_BAD_EASY_HANDLE:    s="CURLM_BAD_EASY_HANDLE";    break;
      case     CURLM_OUT_OF_MEMORY:      s="CURLM_OUT_OF_MEMORY";      break;
@@ -132,33 +130,20 @@ static void mcode_or_die(const char *where, CURLMcode code)


/* Check for completed transfers, and remove their easy handles */
static void check_run_count(GlobalInfo *g)
static void check_multi_info(GlobalInfo *g)
{
  if (g->prev_running > g->still_running) {
    char *eff_url=NULL;
  char *eff_url;
  CURLMsg *msg;
  int msgs_left;
    ConnInfo *conn=NULL;
  ConnInfo *conn;
  CURL *easy;
  CURLcode res;

  fprintf(MSG_OUT, "REMAINING: %d\n", g->still_running);
    /*
      I am still uncertain whether it is safe to remove an easy handle
      from inside the curl_multi_info_read loop, so here I will search
      for completed transfers in the inner "while" loop, and then remove
      them in the outer "do-while" loop...
   */
    do {
      easy=NULL;
  while ((msg = curl_multi_info_read(g->multi, &msgs_left))) {
    if (msg->msg == CURLMSG_DONE) {
      easy = msg->easy_handle;
      res = msg->data.result;
          break;
        }
      }
      if (easy) {
      curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn);
      curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url);
      fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, res, conn->error);
@@ -167,9 +152,7 @@ static void check_run_count(GlobalInfo *g)
      curl_easy_cleanup(easy);
      free(conn);
    }
    } while ( easy );
  }
  g->prev_running = g->still_running;
}


@@ -184,13 +167,10 @@ static void event_cb(int fd, short kind, void *userp)
    (kind & EV_READ ? CURL_CSELECT_IN : 0) |
    (kind & EV_WRITE ? CURL_CSELECT_OUT : 0);

  do {
  rc = curl_multi_socket_action(g->multi, fd, action, &g->still_running);
  } while (rc == CURLM_CALL_MULTI_PERFORM);

  mcode_or_die("event_cb: curl_multi_socket_action", rc);

  check_run_count(g);
  check_multi_info(g);
  if ( g->still_running <= 0 ) {
    fprintf(MSG_OUT, "last transfer done, kill timeout\n");
    if (evtimer_pending(&g->timer_event, NULL)) {
@@ -209,12 +189,10 @@ static void timer_cb(int fd, short kind, void *userp)
  (void)fd;
  (void)kind;

  do {
  rc = curl_multi_socket_action(g->multi,
                                  CURL_SOCKET_TIMEOUT, 0, &g->still_running);
  } while (rc == CURLM_CALL_MULTI_PERFORM);
  mcode_or_die("timer_cb: curl_multi_socket_action", rc);
  check_run_count(g);
  check_multi_info(g);
}


Loading