00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
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
00132 resp_begin_column();
00133 resp_add(t->producers[i].name);
00134 resp_end_column();
00135
00136
00137 resp_begin_column();
00138 resp_add("%d", t->producers[i].alive);
00139 resp_end_column();
00140
00141
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
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
00172 resp_begin_column();
00173 resp_add(t->consumers[j].name);
00174 resp_end_column();
00175
00176
00177 resp_begin_column();
00178 resp_add("%d", t->consumers[j].alive);
00179 resp_end_column();
00180
00181
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
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
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
00225
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
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 * )
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
00291 if (state == HP_INIT) {
00292 state = HP_RUN;
00293
00294
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
00324
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
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
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 *)
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
00389
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 , void * )
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
00476 for (int i = 0; i < HTTP_LIST_BUCKETS; i++) {
00477 HttpSMList[i].mutex = new_ProxyMutex();
00478 }
00479
00480 }