• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

HttpPages.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /****************************************************************************
00025 
00026    HttpPages.cc
00027 
00028    Description:
00029        Data structurs and stat page generators for http info
00030 
00031 
00032  ****************************************************************************/
00033 #include "HttpPages.h"
00034 #include "HttpSM.h"
00035 #include "HttpDebugNames.h"
00036 
00037 HttpSMListBucket HttpSMList[HTTP_LIST_BUCKETS];
00038 
00039 HttpPagesHandler::HttpPagesHandler(Continuation * cont, HTTPHdr * header)
00040   : BaseStatPagesHandler(new_ProxyMutex()),
00041     request(NULL),
00042     list_bucket(0),
00043     state(HP_INIT),
00044     sm_id(0)
00045 {
00046   action = cont;
00047 
00048   URL *url;
00049   int length;
00050 
00051   url = header->url_get();
00052   request = (char *) url->path_get(&length);
00053   request = arena.str_store(request, length);
00054 
00055   if (strncmp(request, "sm_details", sizeof("sm_details")) == 0) {
00056     arena.str_free(request);
00057     request = (char *) url->query_get(&length);
00058     request = arena.str_store(request, length);
00059     SET_HANDLER(&HttpPagesHandler::handle_smdetails);
00060 
00061   } else {
00062     SET_HANDLER(&HttpPagesHandler::handle_smlist);
00063   }
00064 }
00065 
00066 HttpPagesHandler::~HttpPagesHandler()
00067 {
00068 }
00069 
00070 int64_t
00071 HttpPagesHandler::extract_id(const char *query)
00072 {
00073   char *p;
00074   int64_t id;
00075 
00076   p = (char *) strstr(query, "id=");
00077   if (!p) {
00078     return -1;
00079   }
00080   p += sizeof("id=") - 1;
00081 
00082   id = ink_atoi64(p);
00083 
00084   // Check to see if we found the id
00085   if (id == 0) {
00086     if (*p == '0' && *(p + 1) == '\0') {
00087       return 0;
00088     } else {
00089       return -1;
00090     }
00091   } else {
00092     return id;
00093   }
00094 }
00095 
00096 void
00097 HttpPagesHandler::dump_hdr(HTTPHdr *hdr, const char *desc)
00098 {
00099 
00100   if (hdr->valid()) {
00101     resp_add("<h4> %s </h4>\n<pre>\n", desc);
00102     char b[4096];
00103     int used, tmp, offset;
00104     int done;
00105     offset = 0;
00106     do {
00107       used = 0;
00108       tmp = offset;
00109       done = hdr->print(b, 4095, &used, &tmp);
00110       offset += used;
00111       b[used] = '\0';
00112       resp_add(b);
00113     } while (!done);
00114     resp_add("</pre>\n");
00115   }
00116 }
00117 
00118 void
00119 HttpPagesHandler::dump_tunnel_info(HttpSM * sm)
00120 {
00121   HttpTunnel *t = sm->get_tunnel();
00122 
00123   resp_add("<h4> Tunneling Info </h4>");
00124 
00125   resp_add("<p> Producers </p>");
00126   resp_begin_table(1, 4, 60);
00127   for (int i = 0; i < MAX_PRODUCERS; i++) {
00128     if (t->producers[i].vc != NULL) {
00129       resp_begin_row();
00130 
00131       // Col 1 - name
00132       resp_begin_column();
00133       resp_add(t->producers[i].name);
00134       resp_end_column();
00135 
00136       // Col 2 - alive
00137       resp_begin_column();
00138       resp_add("%d", t->producers[i].alive);
00139       resp_end_column();
00140 
00141       // Col 3 - ndone
00142       resp_begin_column();
00143       if (t->producers[i].alive && t->producers[i].read_vio) {
00144         resp_add("%d", t->producers[i].read_vio->ndone);
00145       } else {
00146         resp_add("%d", t->producers[i].bytes_read);
00147       }
00148       resp_end_column();
00149 
00150       // Col 4 - nbytes
00151       resp_begin_column();
00152       if (t->producers[i].alive && t->producers[i].read_vio) {
00153         resp_add("%d", t->producers[i].read_vio->nbytes);
00154       } else {
00155         resp_add("-");
00156       }
00157       resp_end_column();
00158 
00159       resp_end_row();
00160     }
00161   }
00162   resp_end_table();
00163 
00164 
00165   resp_add("<p> Consumers </p>");
00166   resp_begin_table(1, 5, 60);
00167   for (int j = 0; j < MAX_CONSUMERS; j++) {
00168     if (t->consumers[j].vc != NULL) {
00169       resp_begin_row();
00170 
00171       // Col 1 - name
00172       resp_begin_column();
00173       resp_add(t->consumers[j].name);
00174       resp_end_column();
00175 
00176       // Col 2 - alive
00177       resp_begin_column();
00178       resp_add("%d", t->consumers[j].alive);
00179       resp_end_column();
00180 
00181       // Col 3 - ndone
00182       resp_begin_column();
00183       if (t->consumers[j].alive && t->consumers[j].write_vio) {
00184         resp_add("%d", t->consumers[j].write_vio->ndone);
00185       } else {
00186         resp_add("%d", t->consumers[j].bytes_written);
00187       }
00188       resp_end_column();
00189 
00190       // Col 4 - nbytes
00191       resp_begin_column();
00192       if (t->consumers[j].alive && t->consumers[j].write_vio) {
00193         resp_add("%d", t->consumers[j].write_vio->nbytes);
00194       } else {
00195         resp_add("-");
00196       }
00197       resp_end_column();
00198 
00199       // Col 5 - read avail
00200       resp_begin_column();
00201       if (t->consumers[j].alive && t->consumers[j].buffer_reader) {
00202         resp_add("%d", t->consumers[j].buffer_reader->read_avail());
00203       } else {
00204         resp_add("-");
00205       }
00206       resp_end_column();
00207 
00208 
00209       resp_end_row();
00210     }
00211   }
00212   resp_end_table();
00213 
00214 }
00215 
00216 void
00217 HttpPagesHandler::dump_history(HttpSM * sm)
00218 {
00219   resp_add("<h4> History</h4>");
00220   resp_begin_table(1, 3, 60);
00221 
00222   int size;
00223 
00224   // Figure out how big the history is and look
00225   //  for wrap around
00226   if (sm->history_pos > HISTORY_SIZE) {
00227     size = HISTORY_SIZE;
00228   } else {
00229     size = sm->history_pos;
00230   }
00231 
00232   for (int i = 0; i < size; i++) {
00233     resp_begin_row();
00234 
00235     resp_begin_column();
00236     resp_add("%s", sm->history[i].fileline);
00237     resp_end_column();
00238 
00239     resp_begin_column();
00240     resp_add("%u", (unsigned int) sm->history[i].event);
00241     resp_end_column();
00242 
00243     resp_begin_column();
00244     resp_add("%d", (int) sm->history[i].reentrancy);
00245     resp_end_column();
00246 
00247     resp_end_row();
00248   }
00249 
00250   resp_end_table();
00251 }
00252 
00253 int
00254 HttpPagesHandler::dump_sm(HttpSM * sm)
00255 {
00256   // Dump the current state
00257   const char *sm_state = HttpDebugNames::get_action_name(sm->t_state.next_action);
00258 
00259   resp_begin_item();
00260   resp_add("Current State: %s", sm_state);
00261   resp_end_item();
00262 
00263   dump_hdr(&sm->t_state.hdr_info.client_request, "Client Request");
00264   dump_hdr(&sm->t_state.hdr_info.server_request, "Server Request");
00265   dump_hdr(&sm->t_state.hdr_info.server_response, "Server Response");
00266   dump_hdr(&sm->t_state.hdr_info.client_response, "Client Response");
00267 
00268   dump_tunnel_info(sm);
00269   dump_history(sm);
00270 
00271   return EVENT_DONE;
00272 }
00273 
00274 int
00275 HttpPagesHandler::handle_smdetails(int event, void * /* data ATS_UNUSED */)
00276 {
00277   EThread *ethread = this_ethread();
00278   HttpSM *sm = NULL;
00279 
00280   switch (event) {
00281   case EVENT_NONE:
00282   case EVENT_INTERVAL:
00283   case EVENT_IMMEDIATE:
00284     break;
00285   default:
00286     ink_assert(0);
00287     break;
00288   }
00289 
00290   // Do initial setup if necessary
00291   if (state == HP_INIT) {
00292     state = HP_RUN;
00293 
00294     // Get our SM id
00295     sm_id = extract_id(request);
00296 
00297     if (sm_id < 0) {
00298       resp_begin("Http Pages Error");
00299       resp_add("<b>Unable to extract id</b>\n");
00300       resp_end();
00301       return handle_callback(EVENT_NONE, NULL);
00302 
00303     }
00304 
00305     resp_begin("Http:SM Details");
00306     resp_begin_item();
00307     resp_add("Details for SM id  %" PRId64 "", sm_id);
00308     resp_end_item();
00309   }
00310 
00311   for (; list_bucket < HTTP_LIST_BUCKETS; list_bucket++) {
00312     MUTEX_TRY_LOCK(lock, HttpSMList[list_bucket].mutex, ethread);
00313 
00314     if (!lock) {
00315       eventProcessor.schedule_in(this, HTTP_LIST_RETRY, ET_CALL);
00316       return EVENT_DONE;
00317     }
00318 
00319     sm = HttpSMList[list_bucket].sm_list.head;
00320 
00321     while (sm != NULL) {
00322       if (sm->sm_id == sm_id) {
00323         // In this block we try to get the lock of the
00324         //   state machine
00325         {
00326           MUTEX_TRY_LOCK(sm_lock, sm->mutex, ethread);
00327           if (sm_lock) {
00328             dump_sm(sm);
00329             resp_end();
00330             return handle_callback(EVENT_NONE, NULL);
00331           } else {
00332             // We missed the lock so retry
00333             eventProcessor.schedule_in(this, HTTP_LIST_RETRY, ET_CALL);
00334             return EVENT_DONE;
00335           }
00336         }
00337       }
00338 
00339       sm = sm->debug_link.next;
00340     }
00341   }
00342 
00343 
00344   // If we got here, we did not find our state machine
00345   resp_add("<h2>Id %" PRId64 " not found</h2>", sm_id);
00346   resp_end();
00347   return handle_callback(EVENT_NONE, NULL);
00348 }
00349 
00350 int
00351 HttpPagesHandler::handle_smlist(int event, void */* data ATS_UNUSED */)
00352 {
00353   EThread *ethread = this_ethread();
00354   HttpSM *sm;
00355 
00356   switch (event) {
00357   case EVENT_NONE:
00358   case EVENT_INTERVAL:
00359   case EVENT_IMMEDIATE:
00360     break;
00361   default:
00362     ink_assert(0);
00363     break;
00364   }
00365 
00366   if (state == HP_INIT) {
00367     resp_begin("Http:SM List");
00368     state = HP_RUN;
00369   }
00370 
00371   for (; list_bucket < HTTP_LIST_BUCKETS; list_bucket++) {
00372     MUTEX_TRY_LOCK(lock, HttpSMList[list_bucket].mutex, ethread);
00373 
00374     if (!lock) {
00375       eventProcessor.schedule_in(this, HTTP_LIST_RETRY, ET_CALL);
00376       return EVENT_DONE;
00377     }
00378 
00379     sm = HttpSMList[list_bucket].sm_list.head;
00380 
00381     while (sm != NULL) {
00382 
00383       char *url = NULL;
00384       const char *method = NULL;
00385       int method_len;
00386       const char *sm_state = NULL;
00387 
00388       // In this block we try to get the lock of the
00389       //   state machine
00390       {
00391         MUTEX_TRY_LOCK(sm_lock, sm->mutex, ethread);
00392         if (sm_lock) {
00393           if (sm->t_state.hdr_info.client_request.valid()) {
00394             sm_state = HttpDebugNames::get_action_name(sm->t_state.next_action);
00395 
00396             method = sm->t_state.hdr_info.client_request.method_get(&method_len);
00397             method = arena.str_store(method, method_len);
00398             URL *u = sm->t_state.hdr_info.client_request.url_get();
00399             if (u->valid()) {
00400               url = u->string_get(&arena);
00401             }
00402           }
00403 
00404           if (url == NULL) {
00405             url = arena.str_store("-", 1);
00406             sm_state = "READ_REQUEST";
00407           }
00408         } else {
00409           url = arena.str_store("-", 1);
00410           sm_state = "LOCKED";
00411         }
00412       }
00413 
00414       resp_begin_item();
00415       resp_add("id: <a href=\"./sm_details?id=%" PRId64 "\"> %" PRId64 " </a> | %s %s | %s\n",
00416                sm->sm_id, sm->sm_id, method ? method : "", url, sm_state ? sm_state : "");
00417       resp_end_item();
00418       arena.str_free(url);
00419 
00420       sm = sm->debug_link.next;
00421     }
00422   }
00423 
00424   resp_end();
00425   handle_callback(EVENT_NONE, NULL);
00426 
00427   return EVENT_DONE;
00428 }
00429 
00430 int
00431 HttpPagesHandler::handle_callback(int /* event ATS_UNUSED */, void * /* edata ATS_UNUSED */)
00432 {
00433   MUTEX_TRY_LOCK(trylock, action.mutex, this_ethread());
00434   if (!trylock) {
00435     SET_HANDLER(&HttpPagesHandler::handle_callback);
00436     eventProcessor.schedule_in(this, HTTP_LIST_RETRY, ET_CALL);
00437     return EVENT_DONE;
00438   }
00439 
00440   if (!action.cancelled) {
00441     if (response) {
00442       StatPageData data;
00443 
00444       data.data = response;
00445       data.type = ats_strdup("text/html");
00446       data.length = response_length;
00447       response = NULL;
00448 
00449       action.continuation->handleEvent(STAT_PAGE_SUCCESS, &data);
00450     } else {
00451       action.continuation->handleEvent(STAT_PAGE_FAILURE, NULL);
00452     }
00453   }
00454 
00455   delete this;
00456   return EVENT_DONE;
00457 }
00458 
00459 static Action *
00460 http_pages_callback(Continuation * cont, HTTPHdr * header)
00461 {
00462   HttpPagesHandler *handler;
00463 
00464   handler = new HttpPagesHandler(cont, header);
00465   eventProcessor.schedule_imm(handler, ET_CALL);
00466 
00467   return &handler->action;
00468 }
00469 
00470 void
00471 http_pages_init()
00472 {
00473   statPagesManager.register_http("http", http_pages_callback);
00474 
00475   // Create the mutexes for http list protection
00476   for (int i = 0; i < HTTP_LIST_BUCKETS; i++) {
00477     HttpSMList[i].mutex = new_ProxyMutex();
00478   }
00479 
00480 }

Generated by  doxygen 1.7.1