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 #include "Main.h"
00030 #include "StatSystem.h"
00031 #include "P_EventSystem.h"
00032 #include "Error.h"
00033 #include "ProcessManager.h"
00034 #include "ProxyConfig.h"
00035 #include "StatPages.h"
00036 #include "HTTP.h"
00037 #include "I_Layout.h"
00038
00039
00040
00041 #define SNAP_USAGE_PERIOD HRTIME_SECONDS(2)
00042
00043
00044
00045
00046 #ifdef DEBUG
00047 ink_mutex http_time_lock;
00048 time_t last_http_local_time;
00049 #endif
00050 ink_stat_lock_t global_http_trans_stat_lock;
00051 ink_unprot_global_stat_t global_http_trans_stats[MAX_HTTP_TRANS_STATS];
00052 #ifndef USE_LOCKS_FOR_DYN_STATS
00053 inkcoreapi ink_unprot_global_stat_t global_dyn_stats[MAX_DYN_STATS - DYN_STAT_START];
00054 #else
00055 inkcoreapi ink_prot_global_stat_t global_dyn_stats[MAX_DYN_STATS - DYN_STAT_START];
00056 #endif
00057
00058 Ptr<ProxyMutex> rusage_snap_mutex;
00059 struct rusage rusage_snap;
00060 struct rusage rusage_snap_old;
00061 ink_hrtime rusage_snap_time;
00062 ink_hrtime rusage_snap_time_old;
00063 int snap_stats_every = 60;
00064
00065 ink_hrtime http_handler_times[MAX_HTTP_HANDLER_EVENTS];
00066 int http_handler_counts[MAX_HTTP_HANDLER_EVENTS];
00067
00068
00069 char snap_filename[PATH_NAME_MAX+1] = DEFAULT_SNAP_FILENAME;
00070
00071 #define DEFAULT_PERSISTENT
00072
00073 #ifndef DEFAULT_PERSISTENT
00074 static int persistent_stats[] = {
00075 http_incoming_requests_stat
00076 };
00077 #else
00078 static int non_persistent_stats[] = {
00079
00080
00081
00082 cluster_connections_open_stat,
00083 cluster_connections_openned_stat,
00084 cluster_con_total_time_stat,
00085 cluster_ctrl_msgs_sent_stat,
00086 cluster_slow_ctrl_msgs_sent_stat,
00087 cluster_ctrl_msgs_recvd_stat,
00088 cluster_slow_ctrl_msgs_recvd_stat,
00089 cluster_ctrl_msgs_send_time_stat,
00090 cluster_ctrl_msgs_recv_time_stat,
00091 cluster_read_bytes_stat,
00092 cluster_write_bytes_stat,
00093 cluster_op_delayed_for_lock_stat,
00094 cluster_connections_locked_stat,
00095 cluster_connections_bumped_stat,
00096 cluster_nodes_stat,
00097 cluster_net_backup_stat,
00098 cluster_machines_allocated_stat,
00099 cluster_machines_freed_stat,
00100 cluster_configuration_changes_stat,
00101 cluster_delayed_reads_stat,
00102 cluster_byte_bank_used_stat,
00103 cluster_alloc_data_news_stat,
00104 cluster_write_bb_mallocs_stat,
00105 cluster_partial_reads_stat,
00106 cluster_partial_writes_stat,
00107 cluster_cache_outstanding_stat,
00108 cluster_remote_op_timeouts_stat,
00109 cluster_remote_op_reply_timeouts_stat,
00110 cluster_chan_inuse_stat,
00111 cluster_open_delays_stat,
00112 cluster_open_delay_time_stat,
00113 cluster_cache_callbacks_stat,
00114 cluster_cache_callback_time_stat,
00115 cluster_cache_rmt_callbacks_stat,
00116 cluster_cache_rmt_callback_time_stat,
00117 cluster_cache_lkrmt_callbacks_stat,
00118 cluster_cache_lkrmt_callback_time_stat,
00119 cluster_thread_steal_expires_stat,
00120 cluster_local_connections_closed_stat,
00121 cluster_local_connection_time_stat,
00122 cluster_remote_connections_closed_stat,
00123 cluster_remote_connection_time_stat,
00124 cluster_rdmsg_assemble_time_stat,
00125 cluster_ping_time_stat,
00126 cluster_setdata_no_clustervc_stat,
00127 cluster_setdata_no_tunnel_stat,
00128 cluster_setdata_no_cachevc_stat,
00129 cluster_setdata_no_cluster_stat,
00130 cluster_vc_write_stall_stat,
00131 cluster_no_remote_space_stat,
00132 cluster_level1_bank_stat,
00133 cluster_multilevel_bank_stat,
00134 cluster_vc_cache_insert_lock_misses_stat,
00135 cluster_vc_cache_inserts_stat,
00136 cluster_vc_cache_lookup_lock_misses_stat,
00137 cluster_vc_cache_lookup_hits_stat,
00138 cluster_vc_cache_lookup_misses_stat,
00139 cluster_vc_cache_scans_stat,
00140 cluster_vc_cache_scan_lock_misses_stat,
00141 cluster_vc_cache_purges_stat,
00142 cluster_write_lock_misses_stat,
00143
00144
00145
00146
00147
00148 };
00149 #endif
00150
00151 #define _HEADER \
00152 DynamicStatsString_t DynamicStatsStrings[] = {
00153
00154 #define _FOOTER };
00155 #define _D(_x) { _x, #_x },
00156
00157 #include "DynamicStats.h"
00158 #undef _HEADER
00159 #undef _FOOTER
00160 #undef _D
00161
00162
00163
00164
00165
00166 static int
00167 persistent_stat(int i)
00168 {
00169 #ifndef DEFAULT_PERSISTENT
00170 for (unsigned j = 0; j < countof(persistent_stats); j++)
00171 if (persistent_stats[j] == i)
00172 return 1;
00173 return 0;
00174 #else
00175 for (unsigned j = 0; j < countof(non_persistent_stats); j++)
00176 if (non_persistent_stats[j] == i)
00177 return 0;
00178 return 1;
00179 #endif
00180 }
00181
00182 static int
00183 open_stats_snap()
00184 {
00185 int fd = socketManager.open(snap_filename,
00186 O_CREAT | O_RDWR | _O_ATTRIB_NORMAL);
00187 if (fd < 0) {
00188 Warning("unable to open %s: %s", snap_filename, strerror(-fd));
00189 return -1;
00190 }
00191 return fd;
00192 }
00193
00194 static void
00195 clear_stats()
00196 {
00197 int i = 0;
00198
00199 int stats_size = MAX_HTTP_TRANS_STATS - NO_HTTP_TRANS_STATS - 1;
00200 for (i = 0; i < stats_size; i++) {
00201 if (persistent_stat(i + NO_HTTP_TRANS_STATS)) {
00202 global_http_trans_stats[i].sum = 0;
00203 global_http_trans_stats[i].count = 0;
00204 }
00205 }
00206 stats_size = MAX_DYN_STATS - NO_DYN_STATS - 1;
00207 for (i = 0; i < stats_size; i++) {
00208 if (persistent_stat(i + NO_DYN_STATS)) {
00209 global_dyn_stats[i].sum = 0;
00210 global_dyn_stats[i].count = 0;
00211 }
00212 }
00213
00214 socketManager.unlink(snap_filename);
00215 Debug("stats", "clear_stats: clearing statistics");
00216 }
00217
00218 static void
00219 read_stats_snap()
00220 {
00221 unsigned int version;
00222 unsigned int version_read;
00223 int count;
00224 int fd = -1;
00225 int i = 0;
00226 int stats_size = -1;
00227
00228 version = STATS_MAJOR_VERSION;
00229
00230 if ((fd = open_stats_snap()) < 0)
00231 goto Lmissmatch;
00232
00233
00234 if (socketManager.read(fd, (char *) &version_read, sizeof(version_read))
00235 != sizeof(version_read))
00236 goto Lmissmatch;
00237 if (version != version_read)
00238 goto Lmissmatch;
00239 stats_size = MAX_HTTP_TRANS_STATS - NO_HTTP_TRANS_STATS + MAX_DYN_STATS - NO_DYN_STATS;
00240 if (socketManager.read(fd, (char *) &count, sizeof(count)) != sizeof(count))
00241 goto Lmissmatch;
00242 if (count != stats_size)
00243 goto Lmissmatch;
00244
00245 stats_size = MAX_HTTP_TRANS_STATS - NO_HTTP_TRANS_STATS;
00246 for (i = 0; i < stats_size; i++) {
00247 if (socketManager.read(fd, (char *) &global_http_trans_stats[i].sum, sizeof(global_http_trans_stats[i].sum))
00248 != sizeof(global_http_trans_stats[i].sum))
00249 goto Lmissmatch;
00250 if (socketManager.read(fd, (char *) &global_http_trans_stats[i].count, sizeof(global_http_trans_stats[i].count))
00251 != sizeof(global_http_trans_stats[i].count))
00252 goto Lmissmatch;
00253 }
00254 stats_size = MAX_DYN_STATS - NO_DYN_STATS;
00255 for (i = 0; i < stats_size; i++) {
00256 if (socketManager.read(fd, (char *) &global_dyn_stats[i].sum, sizeof(global_dyn_stats[i].sum))
00257 != sizeof(global_dyn_stats[i].sum))
00258 goto Lmissmatch;
00259 if (socketManager.read(fd, (char *) &global_dyn_stats[i].count, sizeof(global_dyn_stats[i].count))
00260 != sizeof(global_dyn_stats[i].count))
00261 goto Lmissmatch;
00262 }
00263 Debug("stats", "read_stats_snap: read statistics");
00264
00265
00266 socketManager.close(fd);
00267 return;
00268
00269 Lmissmatch:
00270 Note("clearing statistics");
00271 clear_stats();
00272
00273 socketManager.close(fd);
00274 }
00275
00276 static void
00277 write_stats_snap()
00278 {
00279 int fd = 0;
00280 int version = STATS_MAJOR_VERSION;
00281 char *buf = NULL;
00282
00283 if ((fd = open_stats_snap()) < 0) {
00284 Warning("unable to snap statistics");
00285 return;
00286 }
00287
00288 {
00289 int stats_size = MAX_HTTP_TRANS_STATS - NO_HTTP_TRANS_STATS + MAX_DYN_STATS - NO_DYN_STATS;
00290 int buf_size = sizeof(unsigned int) * 3 + stats_size * (sizeof(global_dyn_stats[0].sum) + sizeof(global_dyn_stats[0].count));
00291 buf = (char *)ats_malloc(buf_size);
00292 char *p = buf;
00293 int i = 0;
00294
00295 memcpy(p, (char *) &version, sizeof(version));
00296 p += sizeof(version);
00297 memcpy(p, (char *) &stats_size, sizeof(stats_size));
00298 p += sizeof(stats_size);
00299
00300 stats_size = MAX_HTTP_TRANS_STATS - NO_HTTP_TRANS_STATS;
00301 STAT_LOCK_ACQUIRE(&(global_http_trans_stat_lock));
00302 for (i = 0; i < stats_size; i++) {
00303 memcpy(p, (char *) &global_http_trans_stats[i].sum, sizeof(global_http_trans_stats[i].sum));
00304 p += sizeof(global_http_trans_stats[i].sum);
00305 memcpy(p, (char *) &global_http_trans_stats[i].count, sizeof(global_http_trans_stats[i].count));
00306 p += sizeof(global_http_trans_stats[i].count);
00307 }
00308 STAT_LOCK_RELEASE(&(global_http_trans_stat_lock));
00309 stats_size = MAX_DYN_STATS - NO_DYN_STATS;
00310 for (i = 0; i < stats_size; i++) {
00311
00312 ink_statval_t count, sum;
00313 READ_GLOBAL_DYN_STAT(i, count, sum);
00314 memcpy(p, (char *) &sum, sizeof(sum));
00315 p += sizeof(sum);
00316 memcpy(p, (char *) &count, sizeof(count));
00317 p += sizeof(count);
00318 }
00319 memcpy(p, (char *) &version, sizeof(version));
00320
00321 if (socketManager.write(fd, buf, buf_size) != buf_size) {
00322 Warning("unable to snap statistics");
00323 ats_free(buf);
00324 socketManager.close(fd);
00325 return;
00326 }
00327 }
00328 ats_free(buf);
00329 socketManager.close(fd);
00330 Debug("stats", "snapped stats");
00331 }
00332
00333 struct SnapStatsContinuation: public Continuation
00334 {
00335 int mainEvent(int , Event *e ATS_UNUSED)
00336 {
00337 write_stats_snap();
00338 e->schedule_every(HRTIME_SECONDS(snap_stats_every));
00339 return EVENT_CONT;
00340 }
00341 SnapStatsContinuation():Continuation(new_ProxyMutex())
00342 {
00343 SET_HANDLER(&SnapStatsContinuation::mainEvent);
00344 }
00345 };
00346
00347 static void
00348 take_rusage_snap()
00349 {
00350 rusage_snap_old = rusage_snap;
00351 rusage_snap_time_old = rusage_snap_time;
00352 int retries = 3;
00353 while (retries--) {
00354 if (getrusage(RUSAGE_SELF, &rusage_snap) < 0) {
00355 if (errno == EINTR)
00356 continue;
00357 Note("getrusage [%d %s]", errno, strerror(errno));
00358 } else
00359 rusage_snap_time = ink_get_hrtime();
00360 break;
00361 }
00362 Debug("rusage", "took rusage snap %" PRId64"", rusage_snap_time);
00363 }
00364
00365 struct SnapCont;
00366 typedef int (SnapCont::*SnapContHandler) (int, void *);
00367
00368 struct SnapCont: public Continuation
00369 {
00370 int mainEvent(int , Event * e)
00371 {
00372 take_rusage_snap();
00373 e->schedule_every(SNAP_USAGE_PERIOD);
00374 return EVENT_CONT;
00375 }
00376 SnapCont(ProxyMutex * m):Continuation(m)
00377 {
00378 SET_HANDLER((SnapContHandler) & SnapCont::mainEvent);
00379 }
00380 };
00381
00382 void
00383 start_stats_snap()
00384 {
00385 eventProcessor.schedule_every(new SnapCont(rusage_snap_mutex), SNAP_USAGE_PERIOD, ET_CALL);
00386 if (snap_stats_every)
00387 eventProcessor.schedule_every(new SnapStatsContinuation(), HRTIME_SECONDS(snap_stats_every), ET_CALL);
00388 else
00389 Warning("disabling statistics snap");
00390 }
00391
00392 static Action *
00393 stat_callback(Continuation * cont, HTTPHdr * header)
00394 {
00395 URL *url;
00396 int length;
00397 const char *path;
00398 char *result = NULL;
00399 int result_size;
00400 bool empty;
00401
00402 url = header->url_get();
00403 path = url->path_get(&length);
00404
00405 char *buffer = NULL;
00406 int buffer_len = 0;
00407 int num_prefix_buffer;
00408
00409 char *var_prefix = (char *)alloca((length + 1) * sizeof(char));
00410
00411 memset(var_prefix, 0, ((length + 1) * sizeof(char)));
00412 if (path && length > 0)
00413 ink_strlcpy(var_prefix, path, length + 1);
00414
00415 num_prefix_buffer = RecGetRecordPrefix_Xmalloc(var_prefix, &buffer, &buffer_len);
00416 empty = (num_prefix_buffer == 0);
00417
00418 if (!empty) {
00419 result_size = (buffer_len + 16) * sizeof(char);
00420 result = (char *)ats_malloc(result_size);
00421 memset(result, 0, result_size);
00422
00423 snprintf(result, result_size - 7, "<pre>\n%s", buffer);
00424 }
00425
00426
00427 if (!empty) {
00428 StatPageData data;
00429
00430 ink_strlcat(result, "</pre>\n", result_size);
00431
00432 data.data = result;
00433 data.length = strlen(result);
00434 cont->handleEvent(STAT_PAGE_SUCCESS, &data);
00435 } else {
00436 ats_free(result);
00437 cont->handleEvent(STAT_PAGE_FAILURE, NULL);
00438 }
00439 ats_free(buffer);
00440
00441 return ACTION_RESULT_DONE;
00442 }
00443
00444 static Action *
00445 testpage_callback(Continuation * cont, HTTPHdr *)
00446 {
00447 const int buf_size = 64000;
00448 char *buffer = (char *)ats_malloc(buf_size);
00449
00450 for (int i = 0; i < buf_size; i++) {
00451 buffer[i] = (char) ('a' + (i % 26));
00452 }
00453 buffer[buf_size - 1] = '\0';
00454
00455 StatPageData data;
00456
00457 data.data = buffer;
00458 data.length = strlen(buffer);
00459 cont->handleEvent(STAT_PAGE_SUCCESS, &data);
00460
00461 return ACTION_RESULT_DONE;
00462 }
00463
00464 static void
00465 testpage_callback_init()
00466 {
00467 statPagesManager.register_http("test", testpage_callback);
00468 }
00469
00470 void
00471 initialize_all_global_stats()
00472 {
00473 int istat, i;
00474 char snap_file[PATH_NAME_MAX + 1];
00475 ats_scoped_str rundir(RecConfigReadRuntimeDir());
00476
00477 if (access(rundir, R_OK | W_OK) == -1) {
00478 Warning("Unable to access() local state directory '%s': %d, %s", (const char *)rundir, errno, strerror(errno));
00479 Warning(" Please set 'proxy.config.local_state_dir' to allow statistics collection");
00480 }
00481 REC_ReadConfigString(snap_file, "proxy.config.stats.snap_file", PATH_NAME_MAX);
00482 Layout::relative_to(snap_filename, sizeof(snap_filename), (const char *)rundir, snap_file);
00483 Debug("stats", "stat snap filename %s", snap_filename);
00484
00485 statPagesManager.register_http("stat", stat_callback);
00486
00487 testpage_callback_init();
00488
00489 read_stats_snap();
00490 rusage_snap_mutex = new_ProxyMutex();
00491 take_rusage_snap();
00492 take_rusage_snap();
00493
00494 STAT_LOCK_INIT(&(global_http_trans_stat_lock), "Global Http Stats Lock");
00495
00496 for (istat = NO_HTTP_TRANS_STATS; istat < MAX_HTTP_TRANS_STATS; istat++) {
00497 if (!persistent_stat(istat)) {
00498 INITIALIZE_GLOBAL_TRANS_STATS(global_http_trans_stats[istat]);
00499 }
00500 }
00501
00502 for (istat = NO_DYN_STATS; istat < MAX_DYN_STATS; istat++) {
00503 if (!persistent_stat(istat)) {
00504 i = istat - DYN_STAT_START;
00505 INITIALIZE_GLOBAL_DYN_STATS(global_dyn_stats[i], "Dyn Stat Lock");
00506 }
00507 }
00508
00509
00510
00511
00512
00513
00514
00515 #ifdef DEBUG
00516 ink_mutex_init(&http_time_lock, "Http Time Function Lock");
00517 last_http_local_time = 0;
00518 #endif
00519
00520 clear_http_handler_times();
00521 }
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 void *
00544 dyn_stats_int_msecs_to_float_seconds_cb(void *data, void *res)
00545 {
00546 ink_statval_t count, sum;
00547 READ_DYN_STAT((long) data, count, sum);
00548
00549 float r;
00550 if (count == 0) {
00551 r = 0.0;
00552 } else {
00553 r = ((float) sum) / 1000.0;
00554 }
00555 *(float *) res = r;
00556 return res;
00557 }
00558
00559 void *
00560 dyn_stats_count_cb(void *data, void *res)
00561 {
00562 ink_statval_t count, sum;
00563 READ_DYN_STAT((long) data, count, sum);
00564 (void)sum;
00565 ink_atomic_swap((ink_statval_t *) res, count);
00566 return res;
00567 }
00568
00569 void *
00570 dyn_stats_sum_cb(void *data, void *res)
00571 {
00572 ink_statval_t count, sum;
00573 READ_DYN_STAT((long) data, count, sum);
00574 (void)count;
00575 ink_atomic_swap((ink_statval_t *) res, sum);
00576 return res;
00577 }
00578
00579 void *
00580 dyn_stats_avg_cb(void *data, void *res)
00581 {
00582 ink_statval_t count, sum;
00583 READ_DYN_STAT((long) data, count, sum);
00584 if (count == 0) {
00585 *(float *) res = 0.0;
00586 } else {
00587 *(float *) res = (float) sum / (float) count;
00588 }
00589 return res;
00590 }
00591
00592 void *
00593 dyn_stats_fsum_cb(void *data, void *res)
00594 {
00595 ink_statval_t count, sum;
00596 READ_DYN_STAT((long) data, count, sum);
00597 (void)count;
00598 *(float *) res = (double) sum;
00599 return res;
00600 }
00601
00602 void *
00603 dyn_stats_favg_cb(void *data, void *res)
00604 {
00605 ink_statval_t count, sum;
00606 READ_DYN_STAT((long) data, count, sum);
00607 if (count == 0) {
00608 *(float *) res = 0.0;
00609 } else {
00610 *(float *) res = (double) sum / (double) count;
00611 }
00612 return res;
00613 }
00614
00615 void *
00616 dyn_stats_time_seconds_cb(void *data, void *res)
00617 {
00618 ink_statval_t count, sum;
00619 float r;
00620 READ_DYN_STAT((long) data, count, sum);
00621 if (count == 0) {
00622 r = 0.0;
00623 } else {
00624 r = (float) sum / (float) count;
00625 r = r / (float) HRTIME_SECOND;
00626 }
00627 *(float *) res = r;
00628 return res;
00629 }
00630
00631 void *
00632 dyn_stats_time_mseconds_cb(void *data, void *res)
00633 {
00634 ink_statval_t count, sum;
00635 float r;
00636 READ_DYN_STAT((long) data, count, sum);
00637 if (count == 0) {
00638 r = 0.0;
00639 } else {
00640 r = (float) sum / (float) count;
00641 r = r / (float) HRTIME_MSECOND;
00642 }
00643 *(float *) res = r;
00644 return res;
00645 }
00646
00647 void *
00648 dyn_stats_time_useconds_cb(void *data, void *res)
00649 {
00650 ink_statval_t count, sum;
00651 float r;
00652 READ_DYN_STAT((long) data, count, sum);
00653 if (count == 0) {
00654 r = 0.0;
00655 } else {
00656 r = (float) sum / (float) count;
00657 r = r / (float) HRTIME_USECOND;
00658 }
00659 *(float *) res = r;
00660 return res;
00661 }
00662
00663
00664
00665
00666 void *
00667 http_trans_stats_int_msecs_to_float_seconds_cb(void *data, void *res)
00668 {
00669 ink_statval_t count, sum;
00670 READ_HTTP_TRANS_STAT((long) data, count, sum);
00671
00672 float r;
00673 if (count == 0) {
00674 r = 0.0;
00675 } else {
00676 r = ((float) sum) / 1000.0;
00677 }
00678 *(float *) res = r;
00679 return res;
00680 }
00681
00682 void *
00683 http_trans_stats_count_cb(void *data, void *res)
00684 {
00685 ink_statval_t count, sum;
00686 READ_HTTP_TRANS_STAT((long) data, count, sum);
00687 (void)sum;
00688 ink_atomic_swap((ink_statval_t *) res, count);
00689 return res;
00690 }
00691
00692 void *
00693 http_trans_stats_sum_cb(void *data, void *res)
00694 {
00695 ink_statval_t count, sum;
00696 READ_HTTP_TRANS_STAT((long) data, count, sum);
00697 (void)count;
00698 ink_atomic_swap((ink_statval_t *) res, sum);
00699 return res;
00700 }
00701
00702 void *
00703 http_trans_stats_avg_cb(void *data, void *res)
00704 {
00705 ink_statval_t count, sum;
00706 READ_HTTP_TRANS_STAT((long) data, count, sum);
00707 if (count == 0) {
00708 *(float *) res = 0.0;
00709 } else {
00710 *(float *) res = (float) sum / (float) count;
00711 }
00712 return res;
00713 }
00714
00715 void *
00716 http_trans_stats_fsum_cb(void *data, void *res)
00717 {
00718 ink_statval_t count, sum;
00719 READ_HTTP_TRANS_STAT((long) data, count, sum);
00720 (void)count;
00721 *(float *) res = (double) sum;
00722 return res;
00723 }
00724
00725 void *
00726 http_trans_stats_favg_cb(void *data, void *res)
00727 {
00728 ink_statval_t count, sum;
00729 READ_HTTP_TRANS_STAT((long) data, count, sum);
00730 if (count == 0) {
00731 *(float *) res = 0.0;
00732 } else {
00733 *(float *) res = (double) sum / (double) count;
00734 }
00735 return res;
00736 }
00737
00738 void *
00739 http_trans_stats_time_seconds_cb(void *data, void *res)
00740 {
00741 ink_statval_t count, sum;
00742 float r;
00743 READ_HTTP_TRANS_STAT((long) data, count, sum);
00744 if (count == 0) {
00745 r = 0.0;
00746 } else {
00747 r = (float) sum / (float) count;
00748 r = r / (float) HRTIME_SECOND;
00749 }
00750 *(float *) res = r;
00751 return res;
00752 }
00753
00754 void *
00755 http_trans_stats_time_mseconds_cb(void *data, void *res)
00756 {
00757 ink_statval_t count, sum;
00758 float r;
00759 READ_HTTP_TRANS_STAT((long) data, count, sum);
00760 if (count == 0) {
00761 r = 0.0;
00762 } else {
00763 r = (float) sum / (float) count;
00764 r = r / (float) HRTIME_MSECOND;
00765 }
00766 *(float *) res = r;
00767 return res;
00768 }
00769
00770 void *
00771 http_trans_stats_time_useconds_cb(void *data, void *res)
00772 {
00773 ink_statval_t count, sum;
00774 float r;
00775 READ_HTTP_TRANS_STAT((long) data, count, sum);
00776 if (count == 0) {
00777 r = 0.0;
00778 } else {
00779 r = (float) sum / (float) count;
00780 r = r / (float) HRTIME_USECOND;
00781 }
00782 *(float *) res = r;
00783 return res;
00784 }