30#if defined(WIN32_VC) || defined(WIN64_VC)
45 _writer(this, pstats_threaded_write ? 1 : 0)
47 _writer.set_max_queue_size(pstats_max_queue_size);
48 _reader.set_tcp_header_size(4);
49 _writer.set_tcp_header_size(4);
50 _is_connected =
false;
51 _got_udp_port =
false;
52 _collectors_reported = 0;
53 _threads_reported = 0;
55 _client_name = pstats_name;
56 _max_rate = pstats_max_rate;
61 if (pstats_tcp_ratio >= 1.0f) {
62 _tcp_count_factor = 0.0f;
63 _udp_count_factor = 1.0f;
65 }
else if (pstats_tcp_ratio <= 0.0f) {
66 _tcp_count_factor = 1.0f;
67 _udp_count_factor = 0.0f;
70 csincos(pstats_tcp_ratio * (3.14159265f / 2.0f),
81 nassertv(!_is_connected);
88client_connect(std::string hostname,
int port) {
89 nassertr(!_is_connected,
true);
91 if (hostname.empty()) {
92 hostname = pstats_host;
98 if (!_server.set_host(hostname, port)) {
100 <<
"Unknown host: " << hostname <<
"\n";
104 _tcp_connection = open_TCP_client_connection(_server, 5000);
106 if (_tcp_connection.is_null()) {
108 <<
"Couldn't connect to PStatServer at " << hostname <<
":"
114 _tcp_connection->set_collect_tcp(
false);
116 _reader.add_connection(_tcp_connection);
117 _is_connected =
true;
119 _udp_connection = open_UDP_connection();
124 MutexDebug::increment_pstats();
127 return _is_connected;
133void PStatClientImpl::
137 MutexDebug::decrement_pstats();
139 _reader.remove_connection(_tcp_connection);
140 close_connection(_tcp_connection);
141 close_connection(_udp_connection);
144 _tcp_connection.clear();
145 _udp_connection.clear();
147 _is_connected =
false;
148 _got_udp_port =
false;
150 _collectors_reported = 0;
151 _threads_reported = 0;
159void PStatClientImpl::
160new_frame(
int thread_index) {
161 nassertv(thread_index >= 0 && thread_index < _client->_num_threads);
163 PStatClient::InternalThread *pthread = _client->get_thread_ptr(thread_index);
167 if (thread_index == 0) {
168 transmit_control_data();
174 pthread->_is_active =
true;
177 if (!pthread->_is_active) {
181 double frame_start = get_real_time();
182 int frame_number = -1;
185 if (!pthread->_frame_data.is_empty()) {
187 _client->stop(0, thread_index, frame_start);
191 int num_collectors = _client->_num_collectors;
192 PStatClient::CollectorPointer *collectors =
193 (PStatClient::CollectorPointer *)_client->_collectors;
194 for (
int i = 0; i < num_collectors; i++) {
195 const PStatClient::PerThreadData &ptd =
196 collectors[i]->_per_thread[thread_index];
197 if (ptd._has_level) {
198 pthread->_frame_data.add_level(i, ptd._level);
201 pthread->_frame_data.swap(frame_data);
202 frame_number = pthread->_frame_number;
205 pthread->_frame_data.clear();
206 pthread->_frame_number++;
207 _client->start(0, thread_index, frame_start);
211 int pstats_index = PStatClient::_pstats_pcollector.get_index();
212 _client->start(pstats_index, current_thread_index, frame_start);
214 if (frame_number != -1) {
215 transmit_frame_data(thread_index, frame_number, frame_data);
217 _client->stop(pstats_index, current_thread_index, get_real_time());
224void PStatClientImpl::
226 nassertv(thread_index >= 0 && thread_index < _client->_num_threads);
228 PStatClient::InternalThread *pthread = _client->get_thread_ptr(thread_index);
232 if (thread_index == 0) {
233 transmit_control_data();
239 pthread->_is_active =
true;
242 if (!pthread->_is_active) {
246 int frame_number = pthread->_frame_number++;
250 int pstats_index = PStatClient::_pstats_pcollector.get_index();
251 _client->start(pstats_index, current_thread_index);
253 if (frame_number != -1) {
254 transmit_frame_data(thread_index, frame_number, frame_data);
256 _client->stop(pstats_index, current_thread_index);
263void PStatClientImpl::
264transmit_frame_data(
int thread_index,
int frame_number,
266 nassertv(thread_index >= 0 && thread_index < _client->_num_threads);
267 PStatClient::InternalThread *thread = _client->get_thread_ptr(thread_index);
268 if (_is_connected && thread->_is_active) {
274 double now = get_real_time();
275 if (now >= thread->_next_packet) {
278 double packet_delay = 1.0 / _max_rate;
296 }
else if (_writer.is_valid_for_udp(datagram)) {
297 if (_udp_count * _udp_count_factor < _tcp_count * _tcp_count_factor) {
299 nassertv(_got_udp_port);
300 sent = _writer.send(datagram, _udp_connection, _server);
303 if (_udp_count == 0) {
311 sent = _writer.send(datagram, _tcp_connection);
314 if (_tcp_count == 0) {
322 sent = _writer.send(datagram, _tcp_connection);
326 (datagram.
get_length() + maximum_udp_datagram - 1) /
327 maximum_udp_datagram;
328 packet_delay *= (double)packet_ratio;
331 thread->_next_packet = now + packet_delay;
334 if (pstats_cat.is_debug()) {
336 <<
"Couldn't send packet.\n";
347void PStatClientImpl::
348transmit_control_data() {
350 while (_is_connected && _reader.data_available()) {
353 if (_reader.get_data(datagram)) {
355 if (message.
decode(datagram)) {
356 handle_server_control_message(message);
360 <<
"Got unexpected message from server.\n";
366 report_new_collectors();
367 report_new_threads();
375std::string PStatClientImpl::
377 if (_hostname.empty()) {
378 char temp_buff[1024];
379 if (gethostname(temp_buff, 1024) == 0) {
380 _hostname = temp_buff;
382 _hostname =
"unknown";
391void PStatClientImpl::
393 nassertv(_is_connected);
396 message._type = PStatClientControlMessage::T_hello;
397 message._client_hostname = get_hostname();
398 message._client_progname = _client_name;
404 if (pstats_python_profiler && message._major_version <= 3) {
405 message._major_version = 3;
406 message._minor_version = std::max(message._minor_version, 1);
411 _writer.send(datagram, _tcp_connection,
true);
418void PStatClientImpl::
419report_new_collectors() {
423 static const int max_collectors_at_once = 700;
425 while (_is_connected && _collectors_reported < _client->_num_collectors) {
427 message._type = PStatClientControlMessage::T_define_collectors;
429 while (_collectors_reported < _client->_num_collectors &&
430 i < max_collectors_at_once) {
431 message._collectors.push_back(_client->get_collector_def(_collectors_reported));
432 _collectors_reported++;
438 _writer.send(datagram, _tcp_connection,
true);
446void PStatClientImpl::
447report_new_threads() {
448 while (_is_connected && _threads_reported < _client->_num_threads) {
450 message._type = PStatClientControlMessage::T_define_threads;
451 message._first_thread_index = _threads_reported;
452 PStatClient::ThreadPointer *threads =
453 (PStatClient::ThreadPointer *)_client->_threads;
454 while (_threads_reported < _client->_num_threads) {
455 message._names.push_back(threads[_threads_reported]->_name);
461 _writer.send(datagram, _tcp_connection,
true);
469void PStatClientImpl::
471 switch (message._type) {
472 case PStatServerControlMessage::T_hello:
474 <<
"Connected to " << message._server_progname <<
" on "
475 << message._server_hostname <<
"\n";
477 _server.set_port(message._udp_port);
478 _got_udp_port =
true;
483 <<
"Invalid control message received from server.\n";
490void PStatClientImpl::
491connection_reset(
const PT(
Connection) &connection,
bool) {
492 if (connection == _tcp_connection) {
494 }
else if (connection == _udp_connection) {
496 <<
"Trouble sending UDP; switching to TCP only.\n";
497 _tcp_count_factor = 0.0f;
498 _udp_count_factor = 1.0f;
501 <<
"Ignoring spurious connection_reset() message\n";
Represents a single TCP or UDP socket for input or output.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void add_uint32(uint32_t value)
Adds an unsigned 32-bit integer to the datagram.
size_t get_length() const
Returns the number of bytes in the datagram.
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
A specific kind of Datagram, especially for sending across or receiving from a network.
This kind of message is sent from the client to the server on the TCP socket to establish critical co...
void encode(Datagram &datagram) const
Writes the message into the indicated datagram.
Manages the communications to report statistics via a network connection to a remote PStatServer.
Contains the raw timing and level data for a single frame.
bool write_datagram(Datagram &destination, PStatClient *client) const
Writes the definition of the FrameData to the datagram.
This kind of message is sent from the server to the client on the TCP socket to establish critical co...
bool decode(const Datagram &datagram)
Extracts the message from the indicated datagram.
get_current_thread
Returns a pointer to the currently-executing Thread object.
An interface to whatever real-time clock we might have available in the current environment.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_current_pstat_major_version()
Returns the current major version number of the PStats protocol.
int get_current_pstat_minor_version()
Returns the current minor version number of the PStats protocol.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.