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 #if !defined (_StatSystem_h_)
00030 #define _StatSystem_h_
00031 
00032 #include "ink_platform.h"
00033 #include "ink_hrtime.h"
00034 #include "ink_atomic.h"
00035 #ifdef USE_LOCKS_FOR_DYN_STATS
00036 #include "Lock.h"
00037 #endif
00038 
00039 #include "ink_apidefs.h"
00040 
00041 #define STATS_MAJOR_VERSION    6        // increment when changing the stats!
00042 #define DEFAULT_SNAP_FILENAME             "stats.snap"
00043 
00044 
00045 
00046 
00047 
00048 
00049 class TransactionMilestones
00050 {
00051 public:
00052   TransactionMilestones()
00053     : ua_begin(0), ua_read_header_done(0), ua_begin_write(0), ua_close(0), server_first_connect(0), server_connect(0),
00054       server_connect_end(0), server_begin_write(0), server_first_read(0), server_read_header_done(0), server_close(0),
00055       cache_open_read_begin(0), cache_open_read_end(0), cache_open_write_begin(0), cache_open_write_end(0),
00056       dns_lookup_begin(0), dns_lookup_end(0), sm_start(0), sm_finish(0)
00057       { }
00058 
00059 
00060 
00061   
00062   
00063   
00064   
00065   
00066   
00067 
00068   ink_hrtime ua_begin;
00069   ink_hrtime ua_read_header_done;
00070   ink_hrtime ua_begin_write;
00071   ink_hrtime ua_close;
00072 
00073 
00074   
00075 
00076   ink_hrtime server_first_connect;
00077   ink_hrtime server_connect;
00078   ink_hrtime server_connect_end;
00079   ink_hrtime server_begin_write;            
00080   ink_hrtime server_first_read; 
00081   ink_hrtime server_read_header_done;   
00082   ink_hrtime server_close;
00083 
00084   ink_hrtime cache_open_read_begin;
00085   ink_hrtime cache_open_read_end;
00086   ink_hrtime cache_open_write_begin;
00087   ink_hrtime cache_open_write_end;
00088 
00089   ink_hrtime dns_lookup_begin;
00090   ink_hrtime dns_lookup_end;
00091 
00092 
00093   
00094 
00095   ink_hrtime sm_start;
00096   ink_hrtime sm_finish;
00097 
00098   
00099   
00100   
00101   
00102   
00103 };
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 #define _HEADER \
00124 typedef enum { \
00125     NO_HTTP_TRANS_STATS = 0,
00126 
00127 #define _FOOTER \
00128     MAX_HTTP_TRANS_STATS \
00129 } HttpTransactionStat_t;
00130 
00131 #if defined(freebsd)
00132 #undef _D
00133 #endif
00134 #define _D(_x) _x,
00135 
00136 #include "HttpTransStats.h"
00137 #undef _HEADER
00138 #undef _FOOTER
00139 #undef _D
00140 
00141 struct HttpTransactionStatsString_t
00142 {
00143   HttpTransactionStat_t i;
00144   char *name;
00145 };
00146 
00147 
00148 
00149 
00150 
00151 #define DYN_STAT_START 2048
00152 #define DYN_STAT_MASK (~(2047UL))
00153 
00154 
00155 
00156 #define _HEADER \
00157 typedef enum { \
00158     NO_DYN_STATS = DYN_STAT_START,
00159 
00160 #define _FOOTER \
00161     MAX_DYN_STATS \
00162 } DynamicStat_t;
00163 
00164 #define _D(_x) _x,
00165 
00166 #include "DynamicStats.h"
00167 
00168 #undef _HEADER
00169 #undef _FOOTER
00170 #undef _D
00171 
00172 struct DynamicStatsString_t
00173 {
00174   DynamicStat_t i;
00175   const char *name;
00176 };
00177 
00178 extern HttpTransactionStatsString_t HttpTransactionStatsStrings[];
00179 extern DynamicStatsString_t DynamicStatsStrings[];
00180 
00181 
00182 
00183 
00184 
00185 
00186 #define ink_stat_lock_t ink_mutex
00187 
00188 typedef int64_t ink_statval_t;
00189 
00190 struct ink_local_stat_t
00191 {
00192   ink_statval_t count;
00193   ink_statval_t value;
00194 };
00195 
00196 struct ink_prot_global_stat_t
00197 {
00198   ink_stat_lock_t access_lock;
00199   ink_statval_t count;
00200   ink_statval_t sum;
00201 
00202   ink_prot_global_stat_t()
00203     : count(0), sum(0)
00204   {
00205     ink_mutex_init(&access_lock, "Stats Access Lock");
00206   }
00207 };
00208 
00209 struct ink_unprot_global_stat_t
00210 {
00211   ink_statval_t count;
00212   ink_statval_t sum;
00213     ink_unprot_global_stat_t():count(0), sum(0)
00214   {
00215   }
00216 };
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 #define CLEAR_DYN_STAT(X) \
00225 { \
00226     ink_assert (X & DYN_STAT_MASK); \
00227     CLEAR_GLOBAL_DYN_STAT(X-DYN_STAT_START); \
00228 }
00229 
00230 #define DECREMENT_DYN_STAT(X) SUM_DYN_STAT(X, (ink_statval_t)-1)
00231 
00232 #define COUNT_DYN_STAT(X,C) \
00233 { \
00234     ink_assert (X & DYN_STAT_MASK); \
00235     ADD_TO_GLOBAL_DYN_COUNT((X-DYN_STAT_START), C); \
00236 }
00237 
00238 #define FSUM_DYN_STAT(X, S) \
00239 { \
00240     ink_assert (X & DYN_STAT_MASK); \
00241     ADD_TO_GLOBAL_DYN_FSUM((X-DYN_STAT_START), S); \
00242 }
00243 
00244 
00245 #define INCREMENT_DYN_STAT(X) SUM_DYN_STAT(X, (ink_statval_t)1)
00246 
00247 
00248 
00249 
00250 
00251 #define READ_DYN_STAT(X,C,S) \
00252 { \
00253     ink_assert (X & DYN_STAT_MASK); \
00254     READ_GLOBAL_DYN_STAT((X-DYN_STAT_START),C,S); \
00255 }
00256 
00257 #define READ_DYN_COUNT(X,C) \
00258 { \
00259     ink_assert (X & DYN_STAT_MASK); \
00260     READ_GLOBAL_DYN_COUNT((X-DYN_STAT_START),C); \
00261 }
00262 
00263 #define READ_DYN_SUM(X,S) \
00264 { \
00265     ink_assert (X & DYN_STAT_MASK); \
00266     READ_GLOBAL_DYN_SUM((X-DYN_STAT_START),S); \
00267 }
00268 
00269 
00270 #define SET_DYN_COUNT(X, V) \
00271 { \
00272     ink_assert (X & DYN_STAT_MASK); \
00273     SET_GLOBAL_DYN_COUNT((X-DYN_STAT_START), V); \
00274 }
00275 
00276 
00277 #define SET_DYN_STAT(X, C, S) \
00278 { \
00279     ink_assert (X & DYN_STAT_MASK); \
00280     SET_GLOBAL_DYN_STAT((X-DYN_STAT_START), C, S); \
00281 }
00282 
00283 
00284 #define SUM_DYN_STAT(X,S) \
00285 { \
00286     ink_assert (X & DYN_STAT_MASK); \
00287     ADD_TO_GLOBAL_DYN_SUM((X-DYN_STAT_START), S); \
00288 }
00289 
00290 
00291 #define SUM_GLOBAL_DYN_STAT(X,S) \
00292 { \
00293     ink_assert (X & DYN_STAT_MASK); \
00294     ADD_TO_GLOBAL_GLOBAL_DYN_SUM((X-DYN_STAT_START), S); \
00295 }
00296 
00297 #define __CLEAR_TRANS_STAT(local_stat_struct_, X) \
00298 { \
00299     ink_assert (!(X & DYN_STAT_MASK)); \
00300     local_stat_struct_[X].count = (ink_statval_t)0; \
00301     local_stat_struct_[X].value = (ink_statval_t)0; \
00302 }
00303 
00304 #define __DECREMENT_TRANS_STAT(local_stat_struct_, X) __SUM_TRANS_STAT(local_stat_struct_, X, (ink_statval_t)-1)
00305 
00306 #define __FSUM_TRANS_STAT(local_stat_struct_, X, S) \
00307 { \
00308     ink_assert (!(X & DYN_STAT_MASK)); \
00309     local_stat_struct_[X].count++; \
00310     (*(double *)&local_stat_struct_[X].value) += S; \
00311 }
00312 
00313 
00314 #define __INCREMENT_TRANS_STAT(local_stat_struct_, X) __SUM_TRANS_STAT(local_stat_struct_, X, (ink_statval_t)1);
00315 
00316 #define __INITIALIZE_LOCAL_STAT_STRUCT(local_stat_struct_, X) __CLEAR_TRANS_STAT(local_stat_struct_, X)
00317 
00318 #define INITIALIZE_GLOBAL_TRANS_STATS(X) \
00319 { \
00320     X.count = (ink_statval_t)0; \
00321     X.sum = (ink_statval_t)0; \
00322 }
00323 
00324 
00325 
00326 
00327 
00328 #define READ_HTTP_TRANS_STAT(X,C,S) \
00329 { \
00330     ink_assert (!(X & DYN_STAT_MASK)); \
00331     READ_GLOBAL_HTTP_TRANS_STAT(X,C,S); \
00332 }
00333 
00334 
00335 #define __SET_TRANS_COUNT(local_stat_struct_, X, V) \
00336 { \
00337     ink_assert (!(X & DYN_STAT_MASK)); \
00338     local_stat_struct_[X].value = (ink_statval_t)V; \
00339 }
00340 
00341 
00342 #define __SET_TRANS_STAT(local_stat_struct_, X, C, S) \
00343 { \
00344     ink_assert (!(X & DYN_STAT_MASK)); \
00345     local_stat_struct_[X].value = (ink_statval_t)S; \
00346 }
00347 
00348 
00349 
00350 
00351 #define __SUM_TRANS_STAT(local_stat_struct_, X,S) \
00352 { \
00353     ink_assert (!(X & DYN_STAT_MASK)); \
00354     local_stat_struct_[X].count += 1; \
00355     local_stat_struct_[X].value += S; \
00356 }
00357 
00358 #define UPDATE_HTTP_TRANS_STATS(local_stat_struct_) \
00359 { \
00360     int i; \
00361     STAT_LOCK_ACQUIRE(&(global_http_trans_stat_lock)); \
00362     for (i=NO_HTTP_TRANS_STATS; i<MAX_HTTP_TRANS_STATS; i++) { \
00363         global_http_trans_stats[i].count += local_stat_struct_[i].count; \
00364         global_http_trans_stats[i].sum += local_stat_struct_[i].value; \
00365     } \
00366     STAT_LOCK_RELEASE(&(global_http_trans_stat_lock)); \
00367 }
00368 
00369 #define STAT_LOCK_ACQUIRE(X) (ink_mutex_acquire(X))
00370 #define STAT_LOCK_RELEASE(X) (ink_mutex_release(X))
00371 #define STAT_LOCK_INIT(X,S) (ink_mutex_init(X,S))
00372 
00373 
00374 
00375 
00376 
00377 #ifndef USE_LOCKS_FOR_DYN_STATS
00378 
00379 #ifdef USE_THREAD_LOCAL_DYN_STATS
00380 
00381 #error "Should not build with USE_THREAD_LOCAL_DYN_STATS"
00382 
00383 
00384 #define ADD_TO_GLOBAL_DYN_COUNT(X,C) \
00385 mutex->thread_holding->global_dyn_stats[X].count += (C)
00386 
00387 #define ADD_TO_GLOBAL_DYN_SUM(X,S) \
00388 mutex->thread_holding->global_dyn_stats[X].count ++; \
00389 mutex->thread_holding->global_dyn_stats[X].sum += (S)
00390 
00391 #define ADD_TO_GLOBAL_GLOBAL_DYN_SUM(X,S) \
00392 ink_atomic_increment(&global_dyn_stats[X].count,(ink_statval_t)1); \
00393 ink_atomic_increment(&global_dyn_stats[X].sum,S)
00394 
00395 
00396 
00397 
00398 
00399 #define ADD_TO_GLOBAL_DYN_FSUM(X,S) \
00400 mutex->thread_holding->global_dyn_stats[X].count++; \
00401 mutex->thread_holding->global_dyn_stats[X].sum += (S)
00402 
00403 #define CLEAR_GLOBAL_DYN_STAT(X) \
00404 global_dyn_stats[X].count = 0; \
00405 global_dyn_stats[X].sum = 0
00406 
00407 #define READ_GLOBAL_DYN_STAT(X,C,S) do { \
00408   ink_unprot_global_stat_t _s = global_dyn_stats[X]; \
00409   for (int _e = 0; _e < eventProcessor.n_ethreads ; _e++) { \
00410     _s.count += eventProcessor.all_ethreads[_e]->global_dyn_stats[X].count; \
00411     _s.sum += eventProcessor.all_ethreads[_e]->global_dyn_stats[X].sum; \
00412   } \
00413   for (int _e = 0; _e < eventProcessor.n_dthreads ; _e++) { \
00414     _s.count += eventProcessor.all_dthreads[_e]->global_dyn_stats[X].count; \
00415     _s.sum += eventProcessor.all_dthreads[_e]->global_dyn_stats[X].sum; \
00416   } \
00417   C = _s.count; \
00418   S = _s.sum; \
00419 } while (0)
00420 
00421 #define READ_GLOBAL_DYN_COUNT(X,C) do { \
00422   ink_statval_t _s = global_dyn_stats[X].count; \
00423   for (int _e = 0; _e < eventProcessor.n_ethreads ; _e++) \
00424     _s += eventProcessor.all_ethreads[_e]->global_dyn_stats[X].count; \
00425   for (int _e = 0; _e < eventProcessor.n_dthreads ; _e++) \
00426     _s += eventProcessor.all_dthreads[_e]->global_dyn_stats[X].count; \
00427   C = _s; \
00428 } while (0)
00429 
00430 #define READ_GLOBAL_DYN_SUM(X,S) do { \
00431   ink_statval_t _s = global_dyn_stats[X].sum; \
00432   for (int _e = 0; _e < eventProcessor.n_ethreads ; _e++) \
00433     _s += eventProcessor.all_ethreads[_e]->global_dyn_stats[X].sum; \
00434   for (int _e = 0; _e < eventProcessor.n_dthreads ; _e++) \
00435     _s += eventProcessor.all_dthreads[_e]->global_dyn_stats[X].sum; \
00436   S = _s; \
00437 } while (0)
00438 
00439 #define READ_GLOBAL_HTTP_TRANS_STAT(X,C,S) \
00440 { \
00441     C = global_http_trans_stats[X].count; \
00442     S = global_http_trans_stats[X].sum; \
00443 }
00444 
00445 #define SET_GLOBAL_DYN_COUNT(X,V) \
00446 global_dyn_stats[X].count = V
00447 
00448 #define SET_GLOBAL_DYN_STAT(X,C,S) \
00449 global_dyn_stats[X].count = C; \
00450 global_dyn_stats[X].sum = S
00451 
00452 #define INITIALIZE_GLOBAL_DYN_STATS(X, T) \
00453 { \
00454     X.count = (ink_statval_t)0; \
00455     X.sum = (ink_statval_t)0; \
00456 }
00457 
00458 #else
00459 
00460 #define ADD_TO_GLOBAL_DYN_COUNT(X,C) \
00461 ink_atomic_increment(&global_dyn_stats[X].count,C)
00462 
00463 #define ADD_TO_GLOBAL_DYN_SUM(X,S) \
00464 ink_atomic_increment(&global_dyn_stats[X].count,(ink_statval_t)1); \
00465 ink_atomic_increment(&global_dyn_stats[X].sum,S)
00466 
00467 #define ADD_TO_GLOBAL_GLOBAL_DYN_SUM(X,S) \
00468 ink_atomic_increment(&global_dyn_stats[X].count,(ink_statval_t)1); \
00469 ink_atomic_increment(&global_dyn_stats[X].sum,S)
00470 
00471 #define ADD_TO_GLOBAL_DYN_FSUM(X,S) \
00472 ink_atomic_increment(&global_dyn_stats[X].count,(ink_statval_t)1); \
00473 (*(double *)&global_dyn_stats[X].sum) += S
00474 
00475 #define CLEAR_GLOBAL_DYN_STAT(X) \
00476 global_dyn_stats[X].count = 0; \
00477 global_dyn_stats[X].sum = 0
00478 
00479 #define READ_GLOBAL_DYN_STAT(X,C,S) \
00480 C = global_dyn_stats[X].count; \
00481 S = global_dyn_stats[X].sum
00482 
00483 #define READ_GLOBAL_DYN_COUNT(X,C) \
00484 C = global_dyn_stats[X].count;
00485 
00486 #define READ_GLOBAL_DYN_SUM(X,S) \
00487 S = global_dyn_stats[X].sum;
00488 
00489 #define READ_GLOBAL_HTTP_TRANS_STAT(X,C,S) \
00490 { \
00491     C = global_http_trans_stats[X].count; \
00492     S = global_http_trans_stats[X].sum; \
00493 }
00494 
00495 #define SET_GLOBAL_DYN_COUNT(X,V) \
00496 global_dyn_stats[X].count = V
00497 
00498 #define SET_GLOBAL_DYN_STAT(X,C,S) \
00499 global_dyn_stats[X].count = C; \
00500 global_dyn_stats[X].sum = S
00501 
00502 #define INITIALIZE_GLOBAL_DYN_STATS(X, T) \
00503 { \
00504     X.count = (ink_statval_t)0; \
00505     X.sum = (ink_statval_t)0; \
00506 }
00507 
00508 #endif 
00509 
00510 #else 
00511 
00512 #define ADD_TO_GLOBAL_DYN_COUNT(X,C) \
00513 { \
00514     STAT_LOCK_ACQUIRE(&(global_dyn_stats[X].access_lock)); \
00515     global_dyn_stats[X].count += C; \
00516     STAT_LOCK_RELEASE(&(global_dyn_stats[X].access_lock)); \
00517 }
00518 #define ADD_TO_GLOBAL_DYN_SUM(X,S) \
00519 { \
00520     STAT_LOCK_ACQUIRE(&(global_dyn_stats[X].access_lock)); \
00521     global_dyn_stats[X].count += 1; \
00522     global_dyn_stats[X].sum += S; \
00523     STAT_LOCK_RELEASE(&(global_dyn_stats[X].access_lock)); \
00524 }
00525 #define ADD_TO_GLOBAL_GLOBAL_DYN_SUM(X,S) \
00526 { \
00527     STAT_LOCK_ACQUIRE(&(global_dyn_stats[X].access_lock)); \
00528     global_dyn_stats[X].count += 1; \
00529     global_dyn_stats[X].sum += S; \
00530     STAT_LOCK_RELEASE(&(global_dyn_stats[X].access_lock)); \
00531 }
00532 #define ADD_TO_GLOBAL_DYN_FSUM(X,S) \
00533 { \
00534     STAT_LOCK_ACQUIRE(&(global_dyn_stats[X].access_lock)); \
00535     global_dyn_stats[X].count += (ink_statval_t)1; \
00536     (*(double *)&global_dyn_stats[X].sum) += S; \
00537     STAT_LOCK_RELEASE(&(global_dyn_stats[X].access_lock)); \
00538 }
00539 #define CLEAR_GLOBAL_DYN_STAT(X) \
00540 { \
00541     STAT_LOCK_ACQUIRE(&(global_dyn_stats[X].access_lock)); \
00542     global_dyn_stats[X].count = (ink_statval_t)0; \
00543     global_dyn_stats[X].sum = (ink_statval_t)0; \
00544     STAT_LOCK_RELEASE(&(global_dyn_stats[X].access_lock)); \
00545 }
00546 #define READ_GLOBAL_DYN_STAT(X,C,S) \
00547 { \
00548     STAT_LOCK_ACQUIRE(&(global_dyn_stats[X].access_lock)); \
00549     C = global_dyn_stats[X].count; \
00550     S = global_dyn_stats[X].sum; \
00551     STAT_LOCK_RELEASE(&(global_dyn_stats[X].access_lock)); \
00552 }
00553 #define READ_GLOBAL_HTTP_TRANS_STAT(X,C,S) \
00554 { \
00555     C = global_http_trans_stats[X].count; \
00556     S = global_http_trans_stats[X].sum; \
00557 }
00558 #define SET_GLOBAL_DYN_COUNT(X,V) \
00559 { \
00560     STAT_LOCK_ACQUIRE(&(global_dyn_stats[X].access_lock)); \
00561     global_dyn_stats[X].count = V; \
00562     STAT_LOCK_RELEASE(&(global_dyn_stats[X].access_lock)); \
00563 }
00564 
00565 #define SET_GLOBAL_DYN_STAT(X,C,S) \
00566 { \
00567     STAT_LOCK_ACQUIRE(&(global_dyn_stats[X].access_lock)); \
00568     global_dyn_stats[X].count = C; \
00569     global_dyn_stats[X].sum = S; \
00570     STAT_LOCK_RELEASE(&(global_dyn_stats[X].access_lock)); \
00571 }
00572 
00573 #define INITIALIZE_GLOBAL_DYN_STATS(X, T) \
00574 { \
00575     STAT_LOCK_INIT(&(X.access_lock), T); \
00576     X.count = (ink_statval_t)0; \
00577     X.sum = (ink_statval_t)0; \
00578 }
00579 
00580 #endif 
00581 
00582 
00583 
00584 
00585 extern void start_stats_snap(void);
00586 void initialize_all_global_stats();
00587 
00588 
00589 
00590 
00591 
00592 void *http_trans_stats_count_cb(void *data, void *res);
00593 void *http_trans_stats_sum_cb(void *data, void *res);
00594 void *http_trans_stats_avg_cb(void *data, void *res);
00595 void *http_trans_stats_fsum_cb(void *data, void *res);
00596 void *http_trans_stats_favg_cb(void *data, void *res);
00597 void *http_trans_stats_time_seconds_cb(void *data, void *res);
00598 void *http_trans_stats_time_mseconds_cb(void *data, void *res);
00599 void *http_trans_stats_time_useconds_cb(void *data, void *res);
00600 
00601 void *dyn_stats_count_cb(void *data, void *res);
00602 inkcoreapi void *dyn_stats_sum_cb(void *data, void *res);
00603 void *dyn_stats_avg_cb(void *data, void *res);
00604 void *dyn_stats_fsum_cb(void *data, void *res);
00605 void *dyn_stats_favg_cb(void *data, void *res);
00606 void *dyn_stats_time_seconds_cb(void *data, void *res);
00607 void *dyn_stats_time_mseconds_cb(void *data, void *res);
00608 void *dyn_stats_time_useconds_cb(void *data, void *res);
00609 void *dyn_stats_int_msecs_to_float_seconds_cb(void *data, void *res);
00610 
00611 
00612 
00613 extern ink_stat_lock_t global_http_trans_stat_lock;
00614 extern ink_unprot_global_stat_t global_http_trans_stats[MAX_HTTP_TRANS_STATS];
00615 #ifndef USE_LOCKS_FOR_DYN_STATS
00616 extern inkcoreapi ink_unprot_global_stat_t global_dyn_stats[MAX_DYN_STATS - DYN_STAT_START];
00617 #else
00618 extern inkcoreapi ink_prot_global_stat_t global_dyn_stats[MAX_DYN_STATS - DYN_STAT_START];
00619 #endif
00620 
00621 #ifdef DEBUG
00622 extern ink_mutex http_time_lock;
00623 extern time_t last_http_local_time;
00624 #endif
00625 
00626 #define MAX_HTTP_HANDLER_EVENTS 25
00627 extern void clear_http_handler_times();
00628 extern void print_http_handler_time(int event);
00629 extern void print_all_http_handler_times();
00630 #ifdef DEBUG
00631 extern ink_hrtime http_handler_times[MAX_HTTP_HANDLER_EVENTS];
00632 extern int http_handler_counts[MAX_HTTP_HANDLER_EVENTS];
00633 #endif
00634 
00635 
00636 #endif