| /** @file |
| |
| A brief file description |
| |
| @section license License |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| /**************************************************************************** |
| |
| StatSystem.cc -- |
| Created On : Fri Apr 3 19:41:39 1998 |
| ****************************************************************************/ |
| #include "Main.h" |
| #include "StatSystem.h" |
| #include "P_EventSystem.h" |
| #include "Error.h" |
| #include "ProcessManager.h" |
| #include "ProxyConfig.h" |
| #include "StatPages.h" |
| #include "HTTP.h" |
| #include "I_Layout.h" |
| |
| // defines |
| |
| #define SNAP_USAGE_PERIOD HRTIME_SECONDS(2) |
| |
| |
| // variables |
| |
| #ifdef DEBUG |
| ink_mutex http_time_lock; |
| time_t last_http_local_time; |
| #endif |
| ink_stat_lock_t global_http_trans_stat_lock; |
| ink_unprot_global_stat_t global_http_trans_stats[MAX_HTTP_TRANS_STATS]; |
| #ifndef USE_LOCKS_FOR_DYN_STATS |
| inkcoreapi ink_unprot_global_stat_t global_dyn_stats[MAX_DYN_STATS - DYN_STAT_START]; |
| #else |
| inkcoreapi ink_prot_global_stat_t global_dyn_stats[MAX_DYN_STATS - DYN_STAT_START]; |
| #endif |
| |
| Ptr<ProxyMutex> rusage_snap_mutex; |
| struct rusage rusage_snap; |
| struct rusage rusage_snap_old; |
| ink_hrtime rusage_snap_time; |
| ink_hrtime rusage_snap_time_old; |
| int snap_stats_every = 60; |
| |
| ink_hrtime http_handler_times[MAX_HTTP_HANDLER_EVENTS]; |
| int http_handler_counts[MAX_HTTP_HANDLER_EVENTS]; |
| |
| |
| char snap_filename[PATH_NAME_MAX+1] = DEFAULT_SNAP_FILENAME; |
| |
| #define DEFAULT_PERSISTENT |
| |
| #ifndef DEFAULT_PERSISTENT |
| static int persistent_stats[] = { |
| http_incoming_requests_stat |
| }; |
| #else |
| static int non_persistent_stats[] = { |
| //////////////////////////// |
| // Start of Cluster stats |
| //////////////////////////// |
| cluster_connections_open_stat, |
| cluster_connections_openned_stat, |
| cluster_con_total_time_stat, |
| cluster_ctrl_msgs_sent_stat, |
| cluster_slow_ctrl_msgs_sent_stat, |
| cluster_ctrl_msgs_recvd_stat, |
| cluster_slow_ctrl_msgs_recvd_stat, |
| cluster_ctrl_msgs_send_time_stat, |
| cluster_ctrl_msgs_recv_time_stat, |
| cluster_read_bytes_stat, |
| cluster_write_bytes_stat, |
| cluster_op_delayed_for_lock_stat, |
| cluster_connections_locked_stat, |
| cluster_connections_bumped_stat, |
| cluster_nodes_stat, |
| cluster_net_backup_stat, |
| cluster_machines_allocated_stat, |
| cluster_machines_freed_stat, |
| cluster_configuration_changes_stat, |
| cluster_delayed_reads_stat, |
| cluster_byte_bank_used_stat, |
| cluster_alloc_data_news_stat, |
| cluster_write_bb_mallocs_stat, |
| cluster_partial_reads_stat, |
| cluster_partial_writes_stat, |
| cluster_cache_outstanding_stat, |
| cluster_remote_op_timeouts_stat, |
| cluster_remote_op_reply_timeouts_stat, |
| cluster_chan_inuse_stat, |
| cluster_open_delays_stat, |
| cluster_open_delay_time_stat, |
| cluster_cache_callbacks_stat, |
| cluster_cache_callback_time_stat, |
| cluster_cache_rmt_callbacks_stat, |
| cluster_cache_rmt_callback_time_stat, |
| cluster_cache_lkrmt_callbacks_stat, |
| cluster_cache_lkrmt_callback_time_stat, |
| cluster_thread_steal_expires_stat, |
| cluster_local_connections_closed_stat, |
| cluster_local_connection_time_stat, |
| cluster_remote_connections_closed_stat, |
| cluster_remote_connection_time_stat, |
| cluster_rdmsg_assemble_time_stat, |
| cluster_ping_time_stat, |
| cluster_setdata_no_clustervc_stat, |
| cluster_setdata_no_tunnel_stat, |
| cluster_setdata_no_cachevc_stat, |
| cluster_setdata_no_cluster_stat, |
| cluster_vc_write_stall_stat, |
| cluster_no_remote_space_stat, |
| cluster_level1_bank_stat, |
| cluster_multilevel_bank_stat, |
| cluster_vc_cache_insert_lock_misses_stat, |
| cluster_vc_cache_inserts_stat, |
| cluster_vc_cache_lookup_lock_misses_stat, |
| cluster_vc_cache_lookup_hits_stat, |
| cluster_vc_cache_lookup_misses_stat, |
| cluster_vc_cache_scans_stat, |
| cluster_vc_cache_scan_lock_misses_stat, |
| cluster_vc_cache_purges_stat, |
| cluster_write_lock_misses_stat, |
| ///////////////////////////////////// |
| // Start of Scheduled Update stats |
| ///////////////////////////////////// |
| // DNS |
| //dns_success_time_stat |
| }; |
| #endif |
| |
| #define _HEADER \ |
| DynamicStatsString_t DynamicStatsStrings[] = { |
| |
| #define _FOOTER }; |
| #define _D(_x) { _x, #_x }, |
| |
| #include "DynamicStats.h" |
| #undef _HEADER |
| #undef _FOOTER |
| #undef _D |
| |
| |
| |
| // functions |
| |
| static int |
| persistent_stat(int i) |
| { |
| #ifndef DEFAULT_PERSISTENT |
| for (int j = 0; j < (int) SIZE(persistent_stats); j++) |
| if (persistent_stats[j] == i) |
| return 1; |
| return 0; |
| #else |
| for (int j = 0; j < (int) SIZE(non_persistent_stats); j++) |
| if (non_persistent_stats[j] == i) |
| return 0; |
| return 1; |
| #endif |
| } |
| |
| static int |
| open_stats_snap() |
| { |
| int fd = socketManager.open(snap_filename, |
| O_CREAT | O_RDWR | _O_ATTRIB_NORMAL); |
| if (fd < 0) { |
| Warning("unable to open %s: %s", snap_filename, strerror(-fd)); |
| return -1; |
| } |
| return fd; |
| } |
| |
| static void |
| clear_stats() |
| { |
| int i = 0; |
| |
| int stats_size = MAX_HTTP_TRANS_STATS - NO_HTTP_TRANS_STATS - 1; |
| for (i = 0; i < stats_size; i++) { |
| if (persistent_stat(i + NO_HTTP_TRANS_STATS)) { |
| global_http_trans_stats[i].sum = 0; |
| global_http_trans_stats[i].count = 0; |
| } |
| } |
| stats_size = MAX_DYN_STATS - NO_DYN_STATS - 1; |
| for (i = 0; i < stats_size; i++) { |
| if (persistent_stat(i + NO_DYN_STATS)) { |
| global_dyn_stats[i].sum = 0; |
| global_dyn_stats[i].count = 0; |
| } |
| } |
| |
| socketManager.unlink(snap_filename); |
| Debug("stats", "clear_stats: clearing statistics"); |
| } |
| |
| static void |
| read_stats_snap() |
| { |
| unsigned int version; |
| unsigned int version_read; |
| int count; |
| int fd = -1; |
| int i = 0; |
| int stats_size = -1; |
| |
| version = STATS_MAJOR_VERSION; |
| |
| if ((fd = open_stats_snap()) < 0) |
| goto Lmissmatch; |
| |
| // read and verify snap |
| if (socketManager.read(fd, (char *) &version_read, sizeof(version_read)) |
| != sizeof(version_read)) |
| goto Lmissmatch; |
| if (version != version_read) |
| goto Lmissmatch; |
| stats_size = MAX_HTTP_TRANS_STATS - NO_HTTP_TRANS_STATS + MAX_DYN_STATS - NO_DYN_STATS; |
| if (socketManager.read(fd, (char *) &count, sizeof(count)) != sizeof(count)) |
| goto Lmissmatch; |
| if (count != stats_size) |
| goto Lmissmatch; |
| |
| stats_size = MAX_HTTP_TRANS_STATS - NO_HTTP_TRANS_STATS; |
| for (i = 0; i < stats_size; i++) { |
| if (socketManager.read(fd, (char *) &global_http_trans_stats[i].sum, sizeof(global_http_trans_stats[i].sum)) |
| != sizeof(global_http_trans_stats[i].sum)) |
| goto Lmissmatch; |
| if (socketManager.read(fd, (char *) &global_http_trans_stats[i].count, sizeof(global_http_trans_stats[i].count)) |
| != sizeof(global_http_trans_stats[i].count)) |
| goto Lmissmatch; |
| } |
| stats_size = MAX_DYN_STATS - NO_DYN_STATS; |
| for (i = 0; i < stats_size; i++) { |
| if (socketManager.read(fd, (char *) &global_dyn_stats[i].sum, sizeof(global_dyn_stats[i].sum)) |
| != sizeof(global_dyn_stats[i].sum)) |
| goto Lmissmatch; |
| if (socketManager.read(fd, (char *) &global_dyn_stats[i].count, sizeof(global_dyn_stats[i].count)) |
| != sizeof(global_dyn_stats[i].count)) |
| goto Lmissmatch; |
| } |
| Debug("stats", "read_stats_snap: read statistics"); |
| |
| // close(fd); |
| socketManager.close(fd); |
| return; |
| |
| Lmissmatch: |
| Note("clearing statistics"); |
| clear_stats(); |
| //close(fd); |
| socketManager.close(fd); |
| } |
| |
| static void |
| write_stats_snap() |
| { |
| int fd = 0; |
| int version = STATS_MAJOR_VERSION; |
| char *buf = NULL; |
| |
| if ((fd = open_stats_snap()) < 0) |
| goto Lerror; |
| |
| { |
| int stats_size = MAX_HTTP_TRANS_STATS - NO_HTTP_TRANS_STATS + MAX_DYN_STATS - NO_DYN_STATS; |
| int buf_size = sizeof(unsigned int) * 3 + stats_size * (sizeof(global_dyn_stats[0].sum) + sizeof(global_dyn_stats[0].count)); |
| buf = (char *) xmalloc(buf_size); |
| char *p = buf; |
| int i = 0; |
| |
| memcpy(p, (char *) &version, sizeof(version)); |
| p += sizeof(version); |
| memcpy(p, (char *) &stats_size, sizeof(stats_size)); |
| p += sizeof(stats_size); |
| |
| stats_size = MAX_HTTP_TRANS_STATS - NO_HTTP_TRANS_STATS; |
| STAT_LOCK_ACQUIRE(&(global_http_trans_stat_lock)); |
| for (i = 0; i < stats_size; i++) { |
| memcpy(p, (char *) &global_http_trans_stats[i].sum, sizeof(global_http_trans_stats[i].sum)); |
| p += sizeof(global_http_trans_stats[i].sum); |
| memcpy(p, (char *) &global_http_trans_stats[i].count, sizeof(global_http_trans_stats[i].count)); |
| p += sizeof(global_http_trans_stats[i].count); |
| } |
| STAT_LOCK_RELEASE(&(global_http_trans_stat_lock)); |
| stats_size = MAX_DYN_STATS - NO_DYN_STATS; |
| for (i = 0; i < stats_size; i++) { |
| // INKqa09981 (Clearing Host Database and DNS Statistics) |
| ink_statval_t count, sum; |
| READ_GLOBAL_DYN_STAT(i, count, sum); |
| memcpy(p, (char *) &sum, sizeof(sum)); |
| p += sizeof(sum); |
| memcpy(p, (char *) &count, sizeof(count)); |
| p += sizeof(count); |
| } |
| memcpy(p, (char *) &version, sizeof(version)); |
| p += sizeof(version); |
| |
| if (socketManager.write(fd, buf, buf_size) != buf_size) |
| goto Lerror; |
| } |
| if (buf) |
| xfree(buf); |
| //close(fd); |
| socketManager.close(fd); |
| Debug("stats", "snapped stats"); |
| return; |
| Lerror: |
| if (buf) |
| xfree(buf); |
| Warning("unable to snap statistics"); |
| //close(fd); |
| socketManager.close(fd); |
| } |
| |
| struct SnapStatsContinuation: public Continuation |
| { |
| int mainEvent(int event, Event * e) |
| { |
| NOWARN_UNUSED(event); |
| write_stats_snap(); |
| e->schedule_every(HRTIME_SECONDS(snap_stats_every)); |
| return EVENT_CONT; |
| } |
| SnapStatsContinuation():Continuation(new_ProxyMutex()) |
| { |
| SET_HANDLER(&SnapStatsContinuation::mainEvent); |
| } |
| }; |
| |
| static void |
| take_rusage_snap() |
| { |
| rusage_snap_old = rusage_snap; |
| rusage_snap_time_old = rusage_snap_time; |
| int retries = 3; |
| while (retries--) { |
| if (getrusage(RUSAGE_SELF, &rusage_snap) < 0) { |
| if (errno == EINTR) |
| continue; |
| Note("getrusage [%d %s]", errno, strerror(errno)); |
| } else |
| rusage_snap_time = ink_get_hrtime(); |
| break; |
| } |
| Debug("rusage", "took rusage snap %d", rusage_snap_time); |
| } |
| |
| struct SnapCont; |
| typedef int (SnapCont::*SnapContHandler) (int, void *); |
| |
| struct SnapCont: public Continuation |
| { |
| int mainEvent(int event, Event * e) |
| { |
| NOWARN_UNUSED(event); |
| take_rusage_snap(); |
| e->schedule_every(SNAP_USAGE_PERIOD); |
| return EVENT_CONT; |
| } |
| SnapCont(ProxyMutex * m):Continuation(m) |
| { |
| SET_HANDLER((SnapContHandler) & SnapCont::mainEvent); |
| } |
| }; |
| |
| void |
| start_stats_snap() |
| { |
| eventProcessor.schedule_every(NEW(new SnapCont(rusage_snap_mutex)), SNAP_USAGE_PERIOD, ET_CALL); |
| if (snap_stats_every) |
| eventProcessor.schedule_every(NEW(new SnapStatsContinuation()), HRTIME_SECONDS(snap_stats_every), ET_CALL); |
| else |
| Warning("disabling statistics snap"); |
| } |
| |
| static Action * |
| stat_callback(Continuation * cont, HTTPHdr * header) |
| { |
| URL *url; |
| int length; |
| const char *path; |
| char *result = NULL; |
| int result_size; |
| bool empty; |
| |
| url = header->url_get(); |
| path = url->path_get(&length); |
| |
| |
| char *buffer = NULL; |
| int buffer_len = 0; |
| int num_prefix_buffer; |
| |
| char *var_prefix = (char *) xmalloc((length + 1) * sizeof(char)); |
| memset(var_prefix, 0, ((length + 1) * sizeof(char))); |
| strncpy(var_prefix, path, length); |
| |
| num_prefix_buffer = RecGetRecordPrefix_Xmalloc(var_prefix, &buffer, &buffer_len); |
| empty = (num_prefix_buffer == 0); |
| xfree(var_prefix); |
| |
| if (!empty) { |
| |
| result_size = (buffer_len + 16) * sizeof(char); |
| result = (char *) xmalloc(result_size); |
| memset(result, 0, result_size); |
| |
| snprintf(result, result_size - 7, "<pre>\n%s", buffer); |
| } |
| |
| |
| if (!empty) { |
| StatPageData data; |
| |
| strncat(result, "</pre>\n", result_size - strlen(result) - 1); |
| |
| data.data = result; |
| data.length = strlen(result); |
| cont->handleEvent(STAT_PAGE_SUCCESS, &data); |
| } else { |
| if (result) { |
| xfree(result); |
| } |
| cont->handleEvent(STAT_PAGE_FAILURE, NULL); |
| } |
| |
| if (buffer) |
| xfree(buffer); |
| |
| return ACTION_RESULT_DONE; |
| } |
| |
| static Action * |
| testpage_callback(Continuation * cont, HTTPHdr *) |
| { |
| const int buf_size = 64000; |
| char *buffer = (char *) xmalloc(buf_size); |
| |
| if (buffer) { |
| for (int i = 0; i < buf_size; i++) { |
| buffer[i] = (char) ('a' + (i % 26)); |
| } |
| buffer[buf_size - 1] = '\0'; |
| |
| StatPageData data; |
| |
| data.data = buffer; |
| data.length = strlen(buffer); |
| cont->handleEvent(STAT_PAGE_SUCCESS, &data); |
| } else { |
| cont->handleEvent(STAT_PAGE_FAILURE, NULL); |
| } |
| return ACTION_RESULT_DONE; |
| } |
| |
| static void |
| testpage_callback_init() |
| { |
| statPagesManager.register_http("test", testpage_callback); |
| } |
| |
| void |
| initialize_all_global_stats() |
| { |
| int istat, i; |
| char snap_file[PATH_NAME_MAX + 1]; |
| char local_state_dir[PATH_NAME_MAX + 1]; |
| |
| // Jira TS-21 |
| REC_ReadConfigString(local_state_dir, "proxy.config.local_state_dir", PATH_NAME_MAX); |
| if (local_state_dir[0] != '/') { |
| // Not an absolute path |
| Layout::get()->relative(local_state_dir, sizeof(local_state_dir), local_state_dir); |
| } |
| if (access(local_state_dir, R_OK | W_OK) == -1) { |
| ink_strlcpy(local_state_dir, system_runtime_dir, sizeof(local_state_dir)); |
| if (access(local_state_dir, R_OK | W_OK) == -1) { |
| Warning("Unable to access() local state directory '%s': %d, %s", local_state_dir, errno, strerror(errno)); |
| Warning(" Please set 'proxy.config.local_state_dir' to allow statistics collection"); |
| } |
| } |
| REC_ReadConfigString(snap_file, "proxy.config.stats.snap_file", PATH_NAME_MAX); |
| Layout::relative_to(snap_filename, sizeof(snap_filename), |
| local_state_dir, snap_file); |
| Debug("stats", "stat snap filename %s", snap_filename); |
| |
| statPagesManager.register_http("stat", stat_callback); |
| |
| testpage_callback_init(); |
| |
| read_stats_snap(); |
| rusage_snap_mutex = new_ProxyMutex(); |
| take_rusage_snap(); |
| take_rusage_snap(); // fill in _old as well |
| |
| STAT_LOCK_INIT(&(global_http_trans_stat_lock), "Global Http Stats Lock"); |
| |
| for (istat = NO_HTTP_TRANS_STATS; istat < MAX_HTTP_TRANS_STATS; istat++) { |
| if (!persistent_stat(istat)) { |
| INITIALIZE_GLOBAL_TRANS_STATS(global_http_trans_stats[istat]); |
| } |
| } |
| |
| for (istat = NO_DYN_STATS; istat < MAX_DYN_STATS; istat++) { |
| if (!persistent_stat(istat)) { |
| i = istat - DYN_STAT_START; |
| INITIALIZE_GLOBAL_DYN_STATS(global_dyn_stats[i], "Dyn Stat Lock"); |
| } |
| } |
| |
| // TODO: HMMMM, wtf does this do? The following is that this |
| // function does: |
| // ink_atomic_swap_ptr(&this->f_update_lock, (void *) func) |
| // |
| // pmgmt->record_data->registerUpdateLockFunc(tmp_stats_lock_function); |
| |
| #ifdef DEBUG |
| ink_mutex_init(&http_time_lock, "Http Time Function Lock"); |
| last_http_local_time = 0; |
| #endif |
| |
| clear_http_handler_times(); |
| } |
| |
| //void * |
| //tmp_stats_lock_function(UpdateLockAction action) |
| //{ |
| // stats_lock_function((void *) (&global_http_trans_stat_lock), action); |
| // |
| // return NULL; |
| //} |
| |
| //void * |
| //stats_lock_function(void *data, UpdateLockAction action) |
| //{ |
| // if (action == UPDATE_LOCK_ACQUIRE) { |
| // STAT_LOCK_ACQUIRE((ink_stat_lock_t *) data); |
| // } else { |
| // STAT_LOCK_RELEASE((ink_stat_lock_t *) data); |
| // } |
| // |
| // return NULL; |
| //} |
| |
| void * |
| dyn_stats_int_msecs_to_float_seconds_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| READ_DYN_STAT((long) data, count, sum); |
| |
| float r; |
| if (count == 0) { |
| r = 0.0; |
| } else { |
| r = ((float) sum) / 1000.0; |
| } |
| *(float *) res = r; |
| return res; |
| } |
| |
| void * |
| dyn_stats_count_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| READ_DYN_STAT((long) data, count, sum); |
| //*(ink_statval_t *)res = count; |
| ink_atomic_swap64((ink_statval_t *) res, count); |
| return res; |
| } |
| |
| void * |
| dyn_stats_sum_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| READ_DYN_STAT((long) data, count, sum); |
| //*(ink_statval_t *)res = sum; |
| ink_atomic_swap64((ink_statval_t *) res, sum); |
| return res; |
| } |
| |
| void * |
| dyn_stats_avg_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| READ_DYN_STAT((long) data, count, sum); |
| if (count == 0) { |
| *(float *) res = 0.0; |
| } else { |
| *(float *) res = (float) sum / (float) count; |
| } |
| return res; |
| } |
| |
| void * |
| dyn_stats_fsum_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| READ_DYN_STAT((long) data, count, sum); |
| *(float *) res = *(double *) ∑ |
| return res; |
| } |
| |
| void * |
| dyn_stats_favg_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| READ_DYN_STAT((long) data, count, sum); |
| if (count == 0) { |
| *(float *) res = 0.0; |
| } else { |
| *(float *) res = *(double *) &sum / *(double *) &count; |
| } |
| return res; |
| } |
| |
| void * |
| dyn_stats_time_seconds_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| float r; |
| READ_DYN_STAT((long) data, count, sum); |
| if (count == 0) { |
| r = 0.0; |
| } else { |
| r = (float) sum / (float) count; |
| r = r / (float) HRTIME_SECOND; |
| } |
| *(float *) res = r; |
| return res; |
| } |
| |
| void * |
| dyn_stats_time_mseconds_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| float r; |
| READ_DYN_STAT((long) data, count, sum); |
| if (count == 0) { |
| r = 0.0; |
| } else { |
| r = (float) sum / (float) count; |
| r = r / (float) HRTIME_MSECOND; |
| } |
| *(float *) res = r; |
| return res; |
| } |
| |
| void * |
| dyn_stats_time_useconds_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| float r; |
| READ_DYN_STAT((long) data, count, sum); |
| if (count == 0) { |
| r = 0.0; |
| } else { |
| r = (float) sum / (float) count; |
| r = r / (float) HRTIME_USECOND; |
| } |
| *(float *) res = r; |
| return res; |
| } |
| |
| // http trans stat functions |
| // there is the implicit assumption that the lock has |
| // been acquired. |
| void * |
| http_trans_stats_int_msecs_to_float_seconds_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| READ_HTTP_TRANS_STAT((long) data, count, sum); |
| |
| float r; |
| if (count == 0) { |
| r = 0.0; |
| } else { |
| r = ((float) sum) / 1000.0; |
| } |
| *(float *) res = r; |
| return res; |
| } |
| |
| void * |
| http_trans_stats_count_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| READ_HTTP_TRANS_STAT((long) data, count, sum); |
| //*(ink_statval_t *)res = count; |
| ink_atomic_swap64((ink_statval_t *) res, count); |
| return res; |
| } |
| |
| void * |
| http_trans_stats_sum_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| READ_HTTP_TRANS_STAT((long) data, count, sum); |
| //*(ink_statval_t *)res = sum; |
| ink_atomic_swap64((ink_statval_t *) res, sum); |
| return res; |
| } |
| |
| void * |
| http_trans_stats_avg_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| READ_HTTP_TRANS_STAT((long) data, count, sum); |
| if (count == 0) { |
| *(float *) res = 0.0; |
| } else { |
| *(float *) res = (float) sum / (float) count; |
| } |
| return res; |
| } |
| |
| void * |
| http_trans_stats_fsum_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| READ_HTTP_TRANS_STAT((long) data, count, sum); |
| *(float *) res = *(double *) ∑ |
| return res; |
| } |
| |
| void * |
| http_trans_stats_favg_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| READ_HTTP_TRANS_STAT((long) data, count, sum); |
| if (count == 0) { |
| *(float *) res = 0.0; |
| } else { |
| *(float *) res = *(double *) &sum / *(double *) &count; |
| } |
| return res; |
| } |
| |
| void * |
| http_trans_stats_time_seconds_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| float r; |
| READ_HTTP_TRANS_STAT((long) data, count, sum); |
| if (count == 0) { |
| r = 0.0; |
| } else { |
| r = (float) sum / (float) count; |
| r = r / (float) HRTIME_SECOND; |
| } |
| *(float *) res = r; |
| return res; |
| } |
| |
| void * |
| http_trans_stats_time_mseconds_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| float r; |
| READ_HTTP_TRANS_STAT((long) data, count, sum); |
| if (count == 0) { |
| r = 0.0; |
| } else { |
| r = (float) sum / (float) count; |
| r = r / (float) HRTIME_MSECOND; |
| } |
| *(float *) res = r; |
| return res; |
| } |
| |
| void * |
| http_trans_stats_time_useconds_cb(void *data, void *res) |
| { |
| ink_statval_t count, sum; |
| float r; |
| READ_HTTP_TRANS_STAT((long) data, count, sum); |
| if (count == 0) { |
| r = 0.0; |
| } else { |
| r = (float) sum / (float) count; |
| r = r / (float) HRTIME_USECOND; |
| } |
| *(float *) res = r; |
| return res; |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // |
| // TransactionMilestones::TransactionMilestones() |
| // |
| ////////////////////////////////////////////////////////////////////////////// |
| TransactionMilestones::TransactionMilestones() |
| : |
| ua_begin(0), ua_read_header_done(0), ua_begin_write(0), ua_close(0), server_first_connect(0), server_connect(0), |
| // server_connect_end(0), |
| // server_begin_write(0), |
| server_first_read(0), server_read_header_done(0), server_close(0), cache_open_read_begin(0), cache_open_read_end(0), |
| // cache_read_begin(0), |
| // cache_read_end(0), |
| // cache_open_write_begin(0), |
| // cache_open_write_end(0), |
| // cache_write_begin(0), |
| // cache_write_end(0), |
| dns_lookup_begin(0), dns_lookup_end(0), sm_start(0), // init |
| sm_finish(0) // kill_this |
| { |
| return; |
| } |