Merge branch 'bytarget_block'
authorDennis Schafroth <dennis@indexdata.com>
Mon, 7 Nov 2011 10:15:21 +0000 (11:15 +0100)
committerDennis Schafroth <dennis@indexdata.com>
Mon, 7 Nov 2011 10:15:21 +0000 (11:15 +0100)
1  2 
src/http_command.c
src/session.h

diff --combined src/http_command.c
@@@ -126,7 -126,7 +126,7 @@@ void http_sessions_destroy(http_session
          {
              struct http_session *s_next = s->next;
              iochan_destroy(s->timeout_iochan);
 -            destroy_session(s->psession);
 +            session_destroy(s->psession);
              nmem_destroy(s->nmem);
              s = s_next;
          }
@@@ -199,7 -199,7 +199,7 @@@ void http_session_destroy(struct http_s
      {   /* destroying for real */
          yaz_log(http_sessions->log_level, "%p HTTP Session %u destroyed", s, s->session_id);
          iochan_destroy(s->timeout_iochan);
 -        destroy_session(s->psession);
 +        session_destroy(s->psession);
          http_session_use(-1);
          nmem_destroy(s->nmem);
      }
@@@ -229,6 -229,7 +229,7 @@@ static const char *get_msg(enum pazpar2
          { PAZPAR2_RECORD_FAIL, "Record command failed"},
          { PAZPAR2_NOT_IMPLEMENTED, "Not implemented"},
          { PAZPAR2_NO_SERVICE, "No service"},
+         { PAZPAR2_ALREADY_BLOCKED, "Already blocked in session on: "},
          { PAZPAR2_LAST_ERROR, "Last error"},
          { 0, 0 }
      };
@@@ -320,8 -321,8 +321,8 @@@ unsigned int make_sessionid(void
  
  static struct http_session *locate_session(struct http_channel *c)
  {
-     struct http_response *rs = c->response;
      struct http_request *rq = c->request;
+     struct http_response *rs = c->response;
      struct http_session *p;
      const char *session = http_argbyname(rq, "session");
      http_sessions_t http_sessions = c->http_sessions;
@@@ -508,7 -509,7 +509,7 @@@ static void cmd_settings(struct http_ch
      release_session(c, s);
  }
  
- static void cmd_termlist(struct http_channel *c)
+ static void termlist_response(struct http_channel *c)
  {
      struct http_request *rq = c->request;
      struct http_session *s = locate_session(c);
      int num = 15;
      int status;
  
      if (nums)
          num = atoi(nums);
  
+     status = session_active_clients(s->psession);
      response_open_no_status(c, "termlist");
      wrbuf_printf(c->wrbuf, "<activeclients>%d</activeclients>\n", status);
  
      release_session(c, s);
  }
  
+ static void termlist_result_ready(void *data)
+ {
+     struct http_channel *c = (struct http_channel *) data;
+     yaz_log(c->http_sessions->log_level, "termlist watch released");
+     termlist_response(c);
+ }
+ static void cmd_termlist(struct http_channel *c)
+ {
+     struct http_request *rq = c->request;
+     struct http_response *rs = c->response;
+     struct http_session *s = locate_session(c);
+     const char *block = http_argbyname(rq, "block");
+     int active_clients;
+     if (!s)
+         return;
+     active_clients = session_active_clients(s->psession);
+     if (block && !strcmp("1", block) && active_clients)
+     {
+         // if there is already a watch/block. we do not block this one
+         if (session_set_watch(s->psession, SESSION_WATCH_TERMLIST,
+                               termlist_result_ready, c, c) != 0)
+         {
+             yaz_log(YLOG_WARN, "Attempt to block multiple times on termlist block. Not supported!");
+             error(rs, PAZPAR2_ALREADY_BLOCKED, "termlist");
+         }
+         else
+         {
+             yaz_log(c->http_sessions->log_level, "%p Session %u: Blocking on command termlist", s, s->session_id);
+         }
+         release_session(c, s);
+         return;
+     }
+     termlist_response(c);
+     release_session(c, s);
+ }
  size_t session_get_memory_status(struct session *session);
  
  static void session_status(struct http_channel *c, struct http_session *s)
@@@ -600,20 -638,17 +638,17 @@@ static void cmd_server_status(struct ht
      xmalloc_trav(0);
  }
  
- static void cmd_bytarget(struct http_channel *c)
- {
-     struct http_request *rq = c->request;
-     struct http_session *s = locate_session(c);
+ static void bytarget_response(struct http_channel *c) {
+     int count, i;
      struct hitsbytarget *ht;
+     struct http_request *rq = c->request;
      const char *settings = http_argbyname(rq, "settings");
-     int count, i;
+     struct http_session *s = locate_session(c);
  
-     if (!s)
-         return;
      ht = get_hitsbytarget(s->psession, &count, c->nmem);
      response_open(c, "bytarget");
+     if (count == 0)
+         yaz_log(YLOG_WARN, "Empty bytarget Response. No targets found!");
      for (i = 0; i < count; i++)
      {
          wrbuf_puts(c->wrbuf, "\n<target>");
      release_session(c, s);
  }
  
+ static void bytarget_result_ready(void *data)
+ {
+     struct http_channel *c = (struct http_channel *) data;
+     yaz_log(c->http_sessions->log_level, "bytarget watch released");
+     bytarget_response(c);
+ }
+ static void cmd_bytarget(struct http_channel *c)
+ {
+     struct http_request *rq = c->request;
+     struct http_response *rs = c->response;
+     struct http_session *s = locate_session(c);
+     const char *block = http_argbyname(rq, "block");
+     int no_active;
+     if (!s)
+         return;
+     no_active = session_active_clients(s->psession);
+     if (block && !strcmp("1",block) && no_active)
+     {
+         // if there is already a watch/block. we do not block this one
+         if (session_set_watch(s->psession, SESSION_WATCH_BYTARGET,
+                               bytarget_result_ready, c, c) != 0)
+         {
+             yaz_log(YLOG_WARN, "Attempt to block multiple times on bytarget block. Not supported!");
+             error(rs, PAZPAR2_ALREADY_BLOCKED, "bytarget"); 
+         }
+         else
+         {
+             yaz_log(c->http_sessions->log_level, "%p Session %u: Blocking on command bytarget", s, s->session_id);
+         }
+         release_session(c, s);
+         return;
+     }
+     bytarget_response(c);
+     release_session(c, s);
+ }
  static void write_metadata(WRBUF w, struct conf_service *service,
          struct record_metadata **ml, int full)
  {
@@@ -865,7 -941,7 +941,7 @@@ static void cmd_record(struct http_chan
  static void cmd_record_ready(void *data)
  {
      struct http_channel *c = (struct http_channel *) data;
+     yaz_log(c->http_sessions->log_level, "record watch released");
      cmd_record(c);
  }
  
@@@ -947,13 -1023,14 +1023,14 @@@ static void show_records(struct http_ch
  static void show_records_ready(void *data)
  {
      struct http_channel *c = (struct http_channel *) data;
+     yaz_log(c->http_sessions->log_level, "show watch released");
      show_records(c, -1);
  }
  
  static void cmd_show(struct http_channel *c)
  {
-     struct http_request *rq = c->request;
+     struct http_request  *rq = c->request;
+     struct http_response *rs = c->response;
      struct http_session *s = locate_session(c);
      const char *block = http_argbyname(rq, "block");
      const char *sort = http_argbyname(rq, "sort");
          {
              // if there is already a watch/block. we do not block this one
              if (session_set_watch(s->psession, SESSION_WATCH_SHOW_PREF,
-                                   show_records_ready, c, c) != 0)
+                                   show_records_ready, c, c) == 0)
              {
                  yaz_log(c->http_sessions->log_level,
-                         "%p Session %u: Blocking on cmd_show. Waiting for preferred targets", s, s->session_id);
+                         "%p Session %u: Blocking on command show (preferred targets)", s, s->session_id);
+             }
+             else
+             {
+                 yaz_log(YLOG_WARN, "Attempt to block multiple times on show (preferred targets) block. Not supported!");
+                 error(rs, PAZPAR2_ALREADY_BLOCKED, "show (preferred targets)"); 
              }
              release_session(c, s);
              return;
              if (session_set_watch(s->psession, SESSION_WATCH_SHOW,
                                    show_records_ready, c, c) != 0)
              {
-                 yaz_log(c->http_sessions->log_level, "%p Session %u: Blocking on cmd_show", s, s->session_id);
+                 yaz_log(YLOG_WARN, "Attempt to block multiple times on show block. Not supported!");
+                 error(rs, PAZPAR2_ALREADY_BLOCKED, "show"); 
+             }
+             else
+             {
+                 yaz_log(c->http_sessions->log_level, "%p Session %u: Blocking on command show", s, s->session_id);
              }
              release_session(c, s);
              return;
diff --combined src/session.h
@@@ -48,6 -48,7 +48,7 @@@ enum pazpar2_error_code 
      PAZPAR2_RECORD_FAIL,
      PAZPAR2_NOT_IMPLEMENTED,
      PAZPAR2_NO_SERVICE,
+     PAZPAR2_ALREADY_BLOCKED,
  
      PAZPAR2_LAST_ERROR
  };
@@@ -75,7 -76,9 +76,9 @@@ struct session_databas
  #define SESSION_WATCH_SHOW      0
  #define SESSION_WATCH_RECORD    1
  #define SESSION_WATCH_SHOW_PREF 2
- #define SESSION_WATCH_MAX       2
+ #define SESSION_WATCH_TERMLIST  3
+ #define SESSION_WATCH_BYTARGET  4
+ #define SESSION_WATCH_MAX       4
  
  #define SESSION_MAX_TERMLISTS 10
  
@@@ -144,7 -147,7 +147,7 @@@ struct hitsbytarget 
  struct hitsbytarget *get_hitsbytarget(struct session *s, int *count, NMEM nmem);
  struct session *new_session(NMEM nmem, struct conf_service *service,
                              unsigned session_id);
 -void destroy_session(struct session *s);
 +void session_destroy(struct session *s);
  void session_init_databases(struct session *s);
  void statistics(struct session *s, struct statistics *stat);