1// 2// detail/impl/handler_tracking.ipp 3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4// 5// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6// 7// Distributed under the Boost Software License, Version 1.0. (See accompanying 8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9// 10 11#ifndef ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP 12#define ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP 13 14 15#include "asio/detail/config.hpp" 16 17#if defined(ASIO_ENABLE_HANDLER_TRACKING) 18 19#include <cstdarg> 20#include <cstdio> 21#include "asio/detail/handler_tracking.hpp" 22 23# include <chrono> 24# include "asio/detail/chrono_time_traits.hpp" 25# include "asio/wait_traits.hpp" 26 27# include <unistd.h> 28 29#include "asio/detail/push_options.hpp" 30 31namespace asio { 32namespace detail { 33 34struct handler_tracking_timestamp 35{ 36 uint64_t seconds; 37 uint64_t microseconds; 38 39 handler_tracking_timestamp() 40 { 41 typedef chrono_time_traits<std::chrono::system_clock, 42 asio::wait_traits<std::chrono::system_clock> > traits_helper; 43 traits_helper::posix_time_duration now( 44 std::chrono::system_clock::now().time_since_epoch()); 45 seconds = static_cast<uint64_t>(now.total_seconds()); 46 microseconds = static_cast<uint64_t>(now.total_microseconds() % 1000000); 47 } 48}; 49 50struct handler_tracking::tracking_state 51{ 52 static_mutex mutex_; 53 uint64_t next_id_; 54 tss_ptr<completion>* current_completion_; 55}; 56 57handler_tracking::tracking_state* handler_tracking::get_state() 58{ 59 static tracking_state state = { ASIO_STATIC_MUTEX_INIT, 1, 0 }; 60 return &state; 61} 62 63void handler_tracking::init() 64{ 65 static tracking_state* state = get_state(); 66 67 state->mutex_.init(); 68 69 static_mutex::scoped_lock lock(state->mutex_); 70 if (state->current_completion_ == 0) 71 state->current_completion_ = new tss_ptr<completion>; 72} 73 74void handler_tracking::creation(handler_tracking::tracked_handler* h, 75 const char* object_type, void* object, const char* op_name) 76{ 77 static tracking_state* state = get_state(); 78 79 static_mutex::scoped_lock lock(state->mutex_); 80 h->id_ = state->next_id_++; 81 lock.unlock(); 82 83 handler_tracking_timestamp timestamp; 84 85 uint64_t current_id = 0; 86 if (completion* current_completion = *state->current_completion_) 87 current_id = current_completion->id_; 88 89 write_line( 90 "@asio|%llu.%06llu|%llu*%llu|%.20s@%p.%.50s\n", 91 timestamp.seconds, timestamp.microseconds, 92 current_id, h->id_, object_type, object, op_name); 93} 94 95handler_tracking::completion::completion(handler_tracking::tracked_handler* h) 96 : id_(h->id_), 97 invoked_(false), 98 next_(*get_state()->current_completion_) 99{ 100 *get_state()->current_completion_ = this; 101} 102 103handler_tracking::completion::~completion() 104{ 105 if (id_) 106 { 107 handler_tracking_timestamp timestamp; 108 109 write_line( 110 "@asio|%llu.%06llu|%c%llu|\n", 111 timestamp.seconds, timestamp.microseconds, 112 invoked_ ? '!' : '~', id_); 113 } 114 115 *get_state()->current_completion_ = next_; 116} 117 118void handler_tracking::completion::invocation_begin() 119{ 120 handler_tracking_timestamp timestamp; 121 122 write_line( 123 "@asio|%llu.%06llu|>%llu|\n", 124 timestamp.seconds, timestamp.microseconds, id_); 125 126 invoked_ = true; 127} 128 129void handler_tracking::completion::invocation_begin( 130 const asio::error_code& ec) 131{ 132 handler_tracking_timestamp timestamp; 133 134 write_line( 135 "@asio|%llu.%06llu|>%llu|ec=%.20s:%d\n", 136 timestamp.seconds, timestamp.microseconds, 137 id_, ec.category().name(), ec.value()); 138 139 invoked_ = true; 140} 141 142void handler_tracking::completion::invocation_begin( 143 const asio::error_code& ec, std::size_t bytes_transferred) 144{ 145 handler_tracking_timestamp timestamp; 146 147 write_line( 148 "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,bytes_transferred=%llu\n", 149 timestamp.seconds, timestamp.microseconds, 150 id_, ec.category().name(), ec.value(), 151 static_cast<uint64_t>(bytes_transferred)); 152 153 invoked_ = true; 154} 155 156void handler_tracking::completion::invocation_begin( 157 const asio::error_code& ec, int signal_number) 158{ 159 handler_tracking_timestamp timestamp; 160 161 write_line( 162 "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,signal_number=%d\n", 163 timestamp.seconds, timestamp.microseconds, 164 id_, ec.category().name(), ec.value(), signal_number); 165 166 invoked_ = true; 167} 168 169void handler_tracking::completion::invocation_begin( 170 const asio::error_code& ec, const char* arg) 171{ 172 handler_tracking_timestamp timestamp; 173 174 write_line( 175 "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,%.50s\n", 176 timestamp.seconds, timestamp.microseconds, 177 id_, ec.category().name(), ec.value(), arg); 178 179 invoked_ = true; 180} 181 182void handler_tracking::completion::invocation_end() 183{ 184 if (id_) 185 { 186 handler_tracking_timestamp timestamp; 187 188 write_line( 189 "@asio|%llu.%06llu|<%llu|\n", 190 timestamp.seconds, timestamp.microseconds, id_); 191 192 id_ = 0; 193 } 194} 195 196void handler_tracking::operation(const char* object_type, 197 void* object, const char* op_name) 198{ 199 static tracking_state* state = get_state(); 200 201 handler_tracking_timestamp timestamp; 202 203 unsigned long long current_id = 0; 204 if (completion* current_completion = *state->current_completion_) 205 current_id = current_completion->id_; 206 207 write_line( 208 "@asio|%llu.%06llu|%llu|%.20s@%p.%.50s\n", 209 timestamp.seconds, timestamp.microseconds, 210 current_id, object_type, object, op_name); 211} 212 213void handler_tracking::write_line(const char* format, ...) 214{ 215 using namespace std; // For sprintf (or equivalent). 216 217 va_list args; 218 va_start(args, format); 219 220 char line[256] = ""; 221#if defined(ASIO_HAS_SECURE_RTL) 222 int length = vsprintf_s(line, sizeof(line), format, args); 223#else // defined(ASIO_HAS_SECURE_RTL) 224 int length = vsprintf(line, format, args); 225#endif // defined(ASIO_HAS_SECURE_RTL) 226 227 va_end(args); 228 229 ::write(STDERR_FILENO, line, length); 230} 231 232} // namespace detail 233} // namespace asio 234 235#include "asio/detail/pop_options.hpp" 236 237#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) 238 239#endif // ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP 240