mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
split out PStatClientImpl
This commit is contained in:
parent
7d5ae1e3f6
commit
db8cdc119d
@ -10,7 +10,9 @@
|
||||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
|
||||
|
||||
#define SOURCES \
|
||||
config_pstats.h pStatClient.I pStatClient.h pStatClientVersion.I \
|
||||
config_pstats.h pStatClient.I pStatClient.h \
|
||||
pStatClientImpl.I pStatClientImpl.h \
|
||||
pStatClientVersion.I \
|
||||
pStatClientVersion.h pStatClientControlMessage.h \
|
||||
pStatCollector.I pStatCollector.h pStatCollectorDef.h \
|
||||
pStatFrameData.I pStatFrameData.h pStatProperties.h \
|
||||
@ -18,13 +20,15 @@
|
||||
pStatTimer.I pStatTimer.h
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
config_pstats.cxx pStatClient.cxx pStatClientVersion.cxx \
|
||||
config_pstats.cxx pStatClient.cxx pStatClientImpl.cxx \
|
||||
pStatClientVersion.cxx \
|
||||
pStatClientControlMessage.cxx pStatCollectorDef.cxx \
|
||||
pStatFrameData.cxx pStatProperties.cxx \
|
||||
pStatServerControlMessage.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
config_pstats.h pStatClient.I pStatClient.h \
|
||||
pStatClientImpl.I pStatClientImpl.h \
|
||||
pStatClientVersion.I pStatClientVersion.h \
|
||||
pStatClientControlMessage.h pStatCollector.I pStatCollector.h \
|
||||
pStatCollectorDef.h pStatFrameData.I pStatFrameData.h \
|
||||
|
@ -19,29 +19,29 @@
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::set_client_name
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Sets the name of the client. This is reported to the
|
||||
// PStatsServer, and will presumably be written in the
|
||||
// title bar or something.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatClient::
|
||||
set_client_name(const string &name) {
|
||||
_client_name = name;
|
||||
get_impl()->set_client_name(name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_client_name
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Retrieves the name of the client as set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string PStatClient::
|
||||
get_client_name() const {
|
||||
return _client_name;
|
||||
return get_impl()->get_client_name();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::set_max_rate
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Controls the number of packets that will be sent to
|
||||
// the server. Normally, one packet is sent per frame,
|
||||
// but this can flood the server with more packets than
|
||||
@ -56,24 +56,71 @@ get_client_name() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatClient::
|
||||
set_max_rate(float rate) {
|
||||
_max_rate = rate;
|
||||
get_impl()->set_max_rate(rate);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_max_rate
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns the maximum number of packets that will be
|
||||
// sent to the server per second, per thread. See
|
||||
// set_max_rate().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float PStatClient::
|
||||
get_max_rate() const {
|
||||
return _max_rate;
|
||||
return get_impl()->get_max_rate();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_num_collectors
|
||||
// Access: Published
|
||||
// Description: Returns the total number of collectors the Client
|
||||
// knows about.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PStatClient::
|
||||
get_num_collectors() const {
|
||||
return _collectors.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_num_threads
|
||||
// Access: Published
|
||||
// Description: Returns the total number of threads the Client
|
||||
// knows about.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PStatClient::
|
||||
get_num_threads() const {
|
||||
return _threads.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_thread_name
|
||||
// Access: Published
|
||||
// Description: Returns the name of the indicated thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string PStatClient::
|
||||
get_thread_name(int index) const {
|
||||
nassertr(index >= 0 && index < (int)_threads.size(), string());
|
||||
return _threads[index]._name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_clock
|
||||
// Access: Published
|
||||
// Description: Returns a reference to the PStatClient's clock
|
||||
// object. It keeps its own clock, instead of using the
|
||||
// global clock object, so the stats won't get mucked up
|
||||
// if you put the global clock in non-real-time mode or
|
||||
// something.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const ClockObject &PStatClient::
|
||||
get_clock() const {
|
||||
return get_impl()->get_clock();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::connect
|
||||
// Access: Published
|
||||
// Access: Published, Static
|
||||
// Description: Attempts to establish a connection to the indicated
|
||||
// PStatServer. Returns true if successful, false on
|
||||
// failure.
|
||||
@ -85,7 +132,7 @@ connect(const string &hostname, int port) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::disconnect
|
||||
// Access: Published
|
||||
// Access: Published, Static
|
||||
// Description: Closes the connection previously established.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatClient::
|
||||
@ -95,7 +142,7 @@ disconnect() {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::is_connected
|
||||
// Access: Published
|
||||
// Access: Published, Static
|
||||
// Description: Returns true if the client believes it is connected
|
||||
// to a working PStatServer, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -106,7 +153,7 @@ is_connected() {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::resume_after_pause
|
||||
// Access: Published
|
||||
// Access: Published, Static
|
||||
// Description: Resumes the PStatClient after the simulation has been
|
||||
// paused for a while. This allows the stats to
|
||||
// continue exactly where it left off, instead of
|
||||
@ -116,3 +163,78 @@ INLINE void PStatClient::
|
||||
resume_after_pause() {
|
||||
get_global_pstats()->client_resume_after_pause();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::client_connect
|
||||
// Access: Published
|
||||
// Description: The nonstatic implementation of connect().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PStatClient::
|
||||
client_connect(string hostname, int port) {
|
||||
client_disconnect();
|
||||
return get_impl()->client_connect(hostname, port);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::client_is_connected
|
||||
// Access: Published
|
||||
// Description: The nonstatic implementation of is_connected().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PStatClient::
|
||||
client_is_connected() const {
|
||||
return has_impl() && _impl->client_is_connected();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::client_resume_after_pause
|
||||
// Access: Published
|
||||
// Description: Resumes the PStatClient after the simulation has been
|
||||
// paused for a while. This allows the stats to
|
||||
// continue exactly where it left off, instead of
|
||||
// leaving a big gap that would represent a chug.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatClient::
|
||||
client_resume_after_pause() {
|
||||
if (has_impl()) {
|
||||
_impl->client_resume_after_pause();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::has_impl
|
||||
// Access: Private
|
||||
// Description: Returns true if the PStatClientImpl object has been
|
||||
// created for this object yet, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PStatClient::
|
||||
has_impl() const {
|
||||
return (_impl != (PStatClientImpl *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_impl
|
||||
// Access: Private
|
||||
// Description: Returns the PStatClientImpl object for this object.
|
||||
// If the PStatClientImpl object has not yet been
|
||||
// created, implicitly creates it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PStatClientImpl *PStatClient::
|
||||
get_impl() {
|
||||
if (_impl == (PStatClientImpl *)NULL) {
|
||||
_impl = new PStatClientImpl(this);
|
||||
}
|
||||
|
||||
return _impl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_impl
|
||||
// Access: Private
|
||||
// Description: Returns the PStatClientImpl object for this object.
|
||||
// If the PStatClientImpl object has not yet been
|
||||
// created, implicitly creates it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const PStatClientImpl *PStatClient::
|
||||
get_impl() const {
|
||||
return ((PStatClient *)this)->get_impl();
|
||||
}
|
||||
|
@ -22,29 +22,21 @@
|
||||
// This file only defines anything interesting if DO_PSTATS is
|
||||
// defined.
|
||||
|
||||
#include "pStatClientImpl.h"
|
||||
#include "pStatClientControlMessage.h"
|
||||
#include "pStatServerControlMessage.h"
|
||||
#include "pStatCollector.h"
|
||||
#include "pStatThread.h"
|
||||
#include "config_pstats.h"
|
||||
#include "pStatProperties.h"
|
||||
#include "cmath.h"
|
||||
#include "mathNumbers.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef WIN32_VC
|
||||
#define WINDOWS_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef WINDOWS_LEAN_AND_MEAN
|
||||
#endif
|
||||
PStatCollector PStatClient::_total_size_pcollector("Memory usage");
|
||||
PStatCollector PStatClient::_cpp_size_pcollector("Memory usage:C++");
|
||||
PStatCollector PStatClient::_interpreter_size_pcollector("Memory usage:Interpreter");
|
||||
PStatCollector PStatClient::_pstats_pcollector("App:PStats");
|
||||
|
||||
PStatClient *PStatClient::_global_pstats = NULL;
|
||||
|
||||
PStatCollector _total_size_pcollector("Memory usage");
|
||||
PStatCollector _cpp_size_pcollector("Memory usage:C++");
|
||||
PStatCollector _interpreter_size_pcollector("Memory usage:Interpreter");
|
||||
PStatCollector _pstats_pcollector("App:PStats");
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::PerThreadData::Constructor
|
||||
@ -65,17 +57,8 @@ PerThreadData() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatClient::
|
||||
PStatClient() :
|
||||
_reader(this, 0),
|
||||
_writer(this, get_pstats_threaded_write() ? 1 : 0)
|
||||
_impl(NULL)
|
||||
{
|
||||
_is_connected = false;
|
||||
_got_udp_port = false;
|
||||
_collectors_reported = 0;
|
||||
_threads_reported = 0;
|
||||
|
||||
// Make sure our clock is in "normal" mode.
|
||||
_clock.set_mode(ClockObject::M_normal);
|
||||
|
||||
// We always have a collector at index 0 named "Frame". This tracks
|
||||
// the total frame time and is the root of all other collectors. We
|
||||
// have to make this one by hand since it's the root.
|
||||
@ -87,28 +70,6 @@ PStatClient() :
|
||||
|
||||
// We also always have a thread at index 0 named "Main".
|
||||
make_thread("Main");
|
||||
|
||||
_client_name = get_pstats_name();
|
||||
_max_rate = get_pstats_max_rate();
|
||||
|
||||
_tcp_count = 1;
|
||||
_udp_count = 1;
|
||||
|
||||
double pstats_tcp_ratio = get_pstats_tcp_ratio();
|
||||
|
||||
if (pstats_tcp_ratio >= 1.0f) {
|
||||
_tcp_count_factor = 0.0f;
|
||||
_udp_count_factor = 1.0f;
|
||||
|
||||
} else if (pstats_tcp_ratio <= 0.0f) {
|
||||
_tcp_count_factor = 1.0f;
|
||||
_udp_count_factor = 0.0f;
|
||||
|
||||
} else {
|
||||
csincos(pstats_tcp_ratio * MathNumbers::pi_f / 2.0f,
|
||||
&_udp_count_factor,
|
||||
&_tcp_count_factor);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -119,22 +80,15 @@ PStatClient() :
|
||||
PStatClient::
|
||||
~PStatClient() {
|
||||
disconnect();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_num_collectors
|
||||
// Access: Public
|
||||
// Description: Returns the total number of collectors the Client
|
||||
// knows about.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PStatClient::
|
||||
get_num_collectors() const {
|
||||
return _collectors.size();
|
||||
if (has_impl()) {
|
||||
delete _impl;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_collector
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns the nth collector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatCollector PStatClient::
|
||||
@ -145,7 +99,7 @@ get_collector(int index) const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_collector_def
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns the definition body of the nth collector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const PStatCollectorDef &PStatClient::
|
||||
@ -160,7 +114,7 @@ get_collector_def(int index) const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_collector_name
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns the name of the indicated collector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PStatClient::
|
||||
@ -173,7 +127,7 @@ get_collector_name(int index) const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_collector_fullname
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns the "full name" of the indicated collector.
|
||||
// This will be the concatenation of all of the
|
||||
// collector's parents' names (except Frame) and the
|
||||
@ -191,20 +145,9 @@ get_collector_fullname(int index) const {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_num_threads
|
||||
// Access: Public
|
||||
// Description: Returns the total number of threads the Client
|
||||
// knows about.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PStatClient::
|
||||
get_num_threads() const {
|
||||
return _threads.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_thread
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns the nth thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatThread PStatClient::
|
||||
@ -213,38 +156,9 @@ get_thread(int index) const {
|
||||
return PStatThread((PStatClient *)this, index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_thread_name
|
||||
// Access: Public
|
||||
// Description: Returns the name of the indicated thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PStatClient::
|
||||
get_thread_name(int index) const {
|
||||
nassertr(index >= 0 && index < (int)_threads.size(), string());
|
||||
return _threads[index]._name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_clock
|
||||
// Access: Public
|
||||
// Description: Returns a reference to the PStatClient's clock
|
||||
// object. It keeps its own clock, instead of using the
|
||||
// global clock object, so the stats won't get mucked up
|
||||
// if you put the global clock in non-real-time mode or
|
||||
// something.
|
||||
//
|
||||
// On second thought, it works better to use the global
|
||||
// clock, so we don't lose a lot of time in the stats
|
||||
// while we're waiting at the prompt.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const ClockObject &PStatClient::
|
||||
get_clock() const {
|
||||
return _clock;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_main_thread
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns a handle to the client's "Main", or default,
|
||||
// thread. This is where collectors will be started and
|
||||
// stopped if they don't specify otherwise.
|
||||
@ -254,6 +168,94 @@ get_main_thread() const {
|
||||
return PStatThread((PStatClient *)this, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::main_tick
|
||||
// Access: Published, Static
|
||||
// Description: A convenience function to call new_frame() on the
|
||||
// global PStatClient's main thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
main_tick() {
|
||||
// We have code here to report the memory usage. We can't put this
|
||||
// code inside the MemoryUsage class, where it fits a little better,
|
||||
// simply because MemoryUsage is a very low-level class that doesn't
|
||||
// know about PStatClient.
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
if (MemoryUsage::has_total_size()) {
|
||||
_total_size_pcollector.set_level(MemoryUsage::get_total_size());
|
||||
}
|
||||
if (MemoryUsage::has_cpp_size()) {
|
||||
_cpp_size_pcollector.set_level(MemoryUsage::get_cpp_size());
|
||||
}
|
||||
if (MemoryUsage::has_interpreter_size()) {
|
||||
_interpreter_size_pcollector.set_level(MemoryUsage::get_interpreter_size());
|
||||
}
|
||||
#endif
|
||||
|
||||
get_global_pstats()->client_main_tick();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::client_main_tick
|
||||
// Access: Published
|
||||
// Description: A convenience function to call new_frame() on the
|
||||
// the given client's main thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
client_main_tick() {
|
||||
if (has_impl()) {
|
||||
_impl->client_main_tick();
|
||||
}
|
||||
get_main_thread().new_frame();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::client_disconnect
|
||||
// Access: Published
|
||||
// Description: The nonstatic implementation of disconnect().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
client_disconnect() {
|
||||
if (has_impl()) {
|
||||
_impl->client_disconnect();
|
||||
}
|
||||
|
||||
Threads::iterator ti;
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
(*ti)._frame_number = 0;
|
||||
(*ti)._is_active = false;
|
||||
(*ti)._next_packet = 0.0;
|
||||
(*ti)._frame_data.clear();
|
||||
}
|
||||
|
||||
Collectors::iterator ci;
|
||||
for (ci = _collectors.begin(); ci != _collectors.end(); ++ci) {
|
||||
PerThread::iterator ii;
|
||||
for (ii = (*ci)._per_thread.begin();
|
||||
ii != (*ci)._per_thread.end();
|
||||
++ii) {
|
||||
(*ii)._nested_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_global_pstats
|
||||
// Access: Published, Static
|
||||
// Description: Returns a pointer to the global PStatClient object.
|
||||
// It's legal to declare your own PStatClient locally,
|
||||
// but it's also convenient to have a global one that
|
||||
// everyone can register with. This is the global one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatClient *PStatClient::
|
||||
get_global_pstats() {
|
||||
if (_global_pstats == (PStatClient *)NULL) {
|
||||
_global_pstats = new PStatClient;
|
||||
}
|
||||
return _global_pstats;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::make_collector_with_relname
|
||||
// Access: Private
|
||||
@ -388,175 +390,6 @@ make_thread(const string &name) {
|
||||
return PStatThread(this, new_index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::main_tick
|
||||
// Access: Public, Static
|
||||
// Description: A convenience function to call new_frame() on the
|
||||
// global PStatClient's main thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
main_tick() {
|
||||
// We have code here to report the memory usage. We can't put this
|
||||
// code inside the MemoryUsage class, where it fits a little better,
|
||||
// simply because MemoryUsage is a very low-level class that doesn't
|
||||
// know about PStatClient.
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
if (MemoryUsage::has_total_size()) {
|
||||
_total_size_pcollector.set_level(MemoryUsage::get_total_size());
|
||||
}
|
||||
if (MemoryUsage::has_cpp_size()) {
|
||||
_cpp_size_pcollector.set_level(MemoryUsage::get_cpp_size());
|
||||
}
|
||||
if (MemoryUsage::has_interpreter_size()) {
|
||||
_interpreter_size_pcollector.set_level(MemoryUsage::get_interpreter_size());
|
||||
}
|
||||
#endif
|
||||
|
||||
get_global_pstats()->client_main_tick();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::main_tick
|
||||
// Access: Public, Static
|
||||
// Description: A convenience function to call new_frame() on the
|
||||
// the given client's main thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
client_main_tick() {
|
||||
_clock.tick();
|
||||
get_main_thread().new_frame();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_global_pstats
|
||||
// Access: Public, Static
|
||||
// Description: Returns a pointer to the global PStatClient object.
|
||||
// It's legal to declare your own PStatClient locally,
|
||||
// but it's also convenient to have a global one that
|
||||
// everyone can register with. This is the global one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatClient *PStatClient::
|
||||
get_global_pstats() {
|
||||
if (_global_pstats == (PStatClient *)NULL) {
|
||||
_global_pstats = new PStatClient;
|
||||
}
|
||||
return _global_pstats;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::client_connect
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of connect().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PStatClient::
|
||||
client_connect(string hostname, int port) {
|
||||
client_disconnect();
|
||||
|
||||
if (hostname.empty()) {
|
||||
hostname = pstats_host;
|
||||
}
|
||||
if (port < 0) {
|
||||
port = pstats_port;
|
||||
}
|
||||
|
||||
if (!_server.set_host(hostname, port)) {
|
||||
pstats_cat.error()
|
||||
<< "Unknown host: " << hostname << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
_tcp_connection = open_TCP_client_connection(_server, 5000);
|
||||
|
||||
if (_tcp_connection.is_null()) {
|
||||
pstats_cat.error()
|
||||
<< "Couldn't connect to PStatServer at " << hostname << ":"
|
||||
<< port << "\n";
|
||||
return false;
|
||||
}
|
||||
// Make sure we're not queuing up multiple TCP sockets--we expect
|
||||
// immediate writes of our TCP datagrams.
|
||||
_tcp_connection->set_collect_tcp(false);
|
||||
|
||||
_reader.add_connection(_tcp_connection);
|
||||
_is_connected = true;
|
||||
|
||||
_udp_connection = open_UDP_connection();
|
||||
|
||||
send_hello();
|
||||
|
||||
return _is_connected;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::client_disconnect
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of disconnect().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
client_disconnect() {
|
||||
if (_is_connected) {
|
||||
_reader.remove_connection(_tcp_connection);
|
||||
close_connection(_tcp_connection);
|
||||
close_connection(_udp_connection);
|
||||
}
|
||||
|
||||
_tcp_connection.clear();
|
||||
_udp_connection.clear();
|
||||
|
||||
_is_connected = false;
|
||||
_got_udp_port = false;
|
||||
|
||||
_collectors_reported = 0;
|
||||
_threads_reported = 0;
|
||||
|
||||
Threads::iterator ti;
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
(*ti)._frame_number = 0;
|
||||
(*ti)._is_active = false;
|
||||
(*ti)._next_packet = 0.0;
|
||||
(*ti)._frame_data.clear();
|
||||
}
|
||||
|
||||
Collectors::iterator ci;
|
||||
for (ci = _collectors.begin(); ci != _collectors.end(); ++ci) {
|
||||
PerThread::iterator ii;
|
||||
for (ii = (*ci)._per_thread.begin();
|
||||
ii != (*ci)._per_thread.end();
|
||||
++ii) {
|
||||
(*ii)._nested_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::client_is_connected
|
||||
// Access: Public
|
||||
// Description: The nonstatic implementation of is_connected().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PStatClient::
|
||||
client_is_connected() const {
|
||||
return _is_connected;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::client_resume_after_pause
|
||||
// Access: Published
|
||||
// Description: Resumes the PStatClient after the simulation has been
|
||||
// paused for a while. This allows the stats to
|
||||
// continue exactly where it left off, instead of
|
||||
// leaving a big gap that would represent a chug.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
client_resume_after_pause() {
|
||||
// Simply reset the clock to the beginning of the last frame. This
|
||||
// may lose a frame, but on the other hand we won't skip a whole
|
||||
// slew of frames either.
|
||||
|
||||
double frame_time = _clock.get_frame_time();
|
||||
_clock.set_real_time(frame_time);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::is_active
|
||||
// Access: Private
|
||||
@ -572,7 +405,7 @@ is_active(int collector_index, int thread_index) const {
|
||||
nassertr(collector_index >= 0 && collector_index < (int)_collectors.size(), false);
|
||||
nassertr(thread_index >= 0 && thread_index < (int)_threads.size(), false);
|
||||
|
||||
return (_is_connected &&
|
||||
return (client_is_connected() &&
|
||||
_collectors[collector_index]._def->_is_active &&
|
||||
_threads[thread_index]._is_active);
|
||||
}
|
||||
@ -610,13 +443,14 @@ start(int collector_index, int thread_index) {
|
||||
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
||||
#endif
|
||||
|
||||
if (_collectors[collector_index]._def->_is_active &&
|
||||
if (client_is_connected() &&
|
||||
_collectors[collector_index]._def->_is_active &&
|
||||
_threads[thread_index]._is_active) {
|
||||
if (_collectors[collector_index]._per_thread[thread_index]._nested_count == 0) {
|
||||
// This collector wasn't already started in this thread; record
|
||||
// a new data point.
|
||||
_threads[thread_index]._frame_data.add_start(collector_index,
|
||||
_clock.get_real_time());
|
||||
get_clock().get_real_time());
|
||||
}
|
||||
_collectors[collector_index]._per_thread[thread_index]._nested_count++;
|
||||
}
|
||||
@ -636,7 +470,8 @@ start(int collector_index, int thread_index, float as_of) {
|
||||
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
||||
#endif
|
||||
|
||||
if (_collectors[collector_index]._def->_is_active &&
|
||||
if (client_is_connected() &&
|
||||
_collectors[collector_index]._def->_is_active &&
|
||||
_threads[thread_index]._is_active) {
|
||||
if (_collectors[collector_index]._per_thread[thread_index]._nested_count == 0) {
|
||||
// This collector wasn't already started in this thread; record
|
||||
@ -661,7 +496,8 @@ stop(int collector_index, int thread_index) {
|
||||
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
||||
#endif
|
||||
|
||||
if (_collectors[collector_index]._def->_is_active &&
|
||||
if (client_is_connected() &&
|
||||
_collectors[collector_index]._def->_is_active &&
|
||||
_threads[thread_index]._is_active) {
|
||||
if (_collectors[collector_index]._per_thread[thread_index]._nested_count == 0) {
|
||||
pstats_cat.warning()
|
||||
@ -677,7 +513,7 @@ stop(int collector_index, int thread_index) {
|
||||
// This collector has now been completely stopped; record a new
|
||||
// data point.
|
||||
_threads[thread_index]._frame_data.add_stop(collector_index,
|
||||
_clock.get_real_time());
|
||||
get_clock().get_real_time());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -696,7 +532,8 @@ stop(int collector_index, int thread_index, float as_of) {
|
||||
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
||||
#endif
|
||||
|
||||
if (_collectors[collector_index]._def->_is_active &&
|
||||
if (client_is_connected() &&
|
||||
_collectors[collector_index]._def->_is_active &&
|
||||
_threads[thread_index]._is_active) {
|
||||
if (_collectors[collector_index]._per_thread[thread_index]._nested_count == 0) {
|
||||
pstats_cat.warning()
|
||||
@ -745,7 +582,7 @@ clear_level(int collector_index, int thread_index) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
set_level(int collector_index, int thread_index, float level) {
|
||||
if (_collectors[collector_index]._def->_is_active) {
|
||||
if (client_is_connected() && _collectors[collector_index]._def->_is_active) {
|
||||
level *= _collectors[collector_index]._def->_factor;
|
||||
_collectors[collector_index]._per_thread[thread_index]._has_level = true;
|
||||
_collectors[collector_index]._per_thread[thread_index]._level = level;
|
||||
@ -765,7 +602,7 @@ set_level(int collector_index, int thread_index, float level) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
add_level(int collector_index, int thread_index, float increment) {
|
||||
if (_collectors[collector_index]._def->_is_active) {
|
||||
if (client_is_connected() && _collectors[collector_index]._def->_is_active) {
|
||||
increment *= _collectors[collector_index]._def->_factor;
|
||||
_collectors[collector_index]._per_thread[thread_index]._has_level = true;
|
||||
_collectors[collector_index]._per_thread[thread_index]._level += increment;
|
||||
@ -786,291 +623,4 @@ get_level(int collector_index, int thread_index) const {
|
||||
_collectors[collector_index]._def->_factor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::new_frame
|
||||
// Access: Private
|
||||
// Description: Called by the PStatThread interface at the beginning
|
||||
// of every frame, for each thread. This resets the
|
||||
// clocks for the new frame and transmits the data for
|
||||
// the previous frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
new_frame(int thread_index) {
|
||||
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
||||
|
||||
Thread &thread = _threads[thread_index];
|
||||
|
||||
// If we're the main thread, we should exchange control packets with
|
||||
// the server.
|
||||
if (thread_index == 0) {
|
||||
transmit_control_data();
|
||||
}
|
||||
|
||||
// If we've got the UDP port by the time the frame starts, it's
|
||||
// time to become active and start actually tracking data.
|
||||
if (_got_udp_port) {
|
||||
thread._is_active = true;
|
||||
}
|
||||
|
||||
if (!thread._is_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
float frame_start = _clock.get_real_time();
|
||||
|
||||
if (!thread._frame_data.is_empty()) {
|
||||
// Collector 0 is the whole frame.
|
||||
stop(0, thread_index, frame_start);
|
||||
|
||||
// Fill up the level data for all the collectors who have level
|
||||
// data for this thread.
|
||||
int num_collectors = _collectors.size();
|
||||
for (int i = 0; i < num_collectors; i++) {
|
||||
const PerThreadData &ptd = _collectors[i]._per_thread[thread_index];
|
||||
if (ptd._has_level) {
|
||||
thread._frame_data.add_level(i, ptd._level);
|
||||
}
|
||||
}
|
||||
transmit_frame_data(thread_index);
|
||||
}
|
||||
|
||||
thread._frame_data.clear();
|
||||
thread._frame_number++;
|
||||
start(0, thread_index, frame_start);
|
||||
|
||||
// Also record the time for the PStats operation itself.
|
||||
start(_pstats_pcollector.get_index(), thread_index, frame_start);
|
||||
stop(_pstats_pcollector.get_index(), thread_index, _clock.get_real_time());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::transmit_frame_data
|
||||
// Access: Private
|
||||
// Description: Should be called once per frame per thread to
|
||||
// transmit the latest data to the PStatServer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
transmit_frame_data(int thread_index) {
|
||||
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
||||
if (_is_connected && _threads[thread_index]._is_active) {
|
||||
|
||||
// We don't want to send too many packets in a hurry and flood the
|
||||
// server. Check that enough time has elapsed for us to send a
|
||||
// new packet. If not, we'll drop this packet on the floor and
|
||||
// send a new one next time around.
|
||||
float now = _clock.get_real_time();
|
||||
if (now >= _threads[thread_index]._next_packet) {
|
||||
// We don't want to send more than _max_rate UDP-size packets
|
||||
// per second, per thread.
|
||||
float packet_delay = 1.0 / _max_rate;
|
||||
|
||||
// Send new data.
|
||||
NetDatagram datagram;
|
||||
// We always start with a zero byte, to differentiate it from a
|
||||
// control message.
|
||||
datagram.add_uint8(0);
|
||||
|
||||
datagram.add_uint16(thread_index);
|
||||
datagram.add_uint32(_threads[thread_index]._frame_number);
|
||||
_threads[thread_index]._frame_data.write_datagram(datagram);
|
||||
|
||||
if (_writer.is_valid_for_udp(datagram)) {
|
||||
if (_udp_count * _udp_count_factor < _tcp_count * _tcp_count_factor) {
|
||||
// Send this one as a UDP packet.
|
||||
nassertv(_got_udp_port);
|
||||
_writer.send(datagram, _udp_connection, _server);
|
||||
_udp_count++;
|
||||
|
||||
if (_udp_count == 0) {
|
||||
// Wraparound!
|
||||
_udp_count = 1;
|
||||
_tcp_count = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Send this one as a TCP packet.
|
||||
_writer.send(datagram, _tcp_connection);
|
||||
_tcp_count++;
|
||||
|
||||
if (_tcp_count == 0) {
|
||||
// Wraparound!
|
||||
_udp_count = 1;
|
||||
_tcp_count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
_writer.send(datagram, _tcp_connection);
|
||||
// If our packets are so large that we must ship them via TCP,
|
||||
// then artificially slow down the packet rate even further.
|
||||
int packet_ratio =
|
||||
(datagram.get_length() + maximum_udp_datagram - 1) /
|
||||
maximum_udp_datagram;
|
||||
packet_delay *= (float)packet_ratio;
|
||||
}
|
||||
|
||||
_threads[thread_index]._next_packet = now + packet_delay;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::transmit_control_data
|
||||
// Access: Private
|
||||
// Description: Should be called once a frame to exchange control
|
||||
// information with the server.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
transmit_control_data() {
|
||||
// Check for new messages from the server.
|
||||
while (_is_connected && _reader.data_available()) {
|
||||
NetDatagram datagram;
|
||||
|
||||
if (_reader.get_data(datagram)) {
|
||||
PStatServerControlMessage message;
|
||||
if (message.decode(datagram)) {
|
||||
handle_server_control_message(message);
|
||||
|
||||
} else {
|
||||
pstats_cat.error()
|
||||
<< "Got unexpected message from server.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_is_connected) {
|
||||
report_new_collectors();
|
||||
report_new_threads();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_hostname
|
||||
// Access: Private
|
||||
// Description: Returns the current machine's hostname.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PStatClient::
|
||||
get_hostname() {
|
||||
if (_hostname.empty()) {
|
||||
char temp_buff[1024];
|
||||
if (gethostname(temp_buff, 1024) == 0) {
|
||||
_hostname = temp_buff;
|
||||
} else {
|
||||
_hostname = "unknown";
|
||||
}
|
||||
}
|
||||
return _hostname;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::send_hello
|
||||
// Access: Private
|
||||
// Description: Sends the initial greeting message to the server.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
send_hello() {
|
||||
nassertv(_is_connected);
|
||||
|
||||
PStatClientControlMessage message;
|
||||
message._type = PStatClientControlMessage::T_hello;
|
||||
message._client_hostname = get_hostname();
|
||||
message._client_progname = _client_name;
|
||||
message._major_version = get_current_pstat_major_version();
|
||||
message._minor_version = get_current_pstat_minor_version();
|
||||
|
||||
Datagram datagram;
|
||||
message.encode(datagram);
|
||||
_writer.send(datagram, _tcp_connection);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::report_new_collectors
|
||||
// Access: Private
|
||||
// Description: Sends over any information about new Collectors that
|
||||
// the user code might have recently created.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
report_new_collectors() {
|
||||
nassertv(_is_connected);
|
||||
|
||||
if (_collectors_reported < (int)_collectors.size()) {
|
||||
PStatClientControlMessage message;
|
||||
message._type = PStatClientControlMessage::T_define_collectors;
|
||||
while (_collectors_reported < (int)_collectors.size()) {
|
||||
message._collectors.push_back(_collectors[_collectors_reported]._def);
|
||||
_collectors_reported++;
|
||||
}
|
||||
|
||||
Datagram datagram;
|
||||
message.encode(datagram);
|
||||
_writer.send(datagram, _tcp_connection);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::report_new_threads
|
||||
// Access: Private
|
||||
// Description: Sends over any information about new Threads that
|
||||
// the user code might have recently created.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
report_new_threads() {
|
||||
nassertv(_is_connected);
|
||||
|
||||
if (_threads_reported < (int)_threads.size()) {
|
||||
PStatClientControlMessage message;
|
||||
message._type = PStatClientControlMessage::T_define_threads;
|
||||
message._first_thread_index = _threads_reported;
|
||||
while (_threads_reported < (int)_threads.size()) {
|
||||
message._names.push_back(_threads[_threads_reported]._name);
|
||||
_threads_reported++;
|
||||
}
|
||||
|
||||
Datagram datagram;
|
||||
message.encode(datagram);
|
||||
_writer.send(datagram, _tcp_connection);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::handle_server_control_message
|
||||
// Access: Private
|
||||
// Description: Called when a control message has been received by
|
||||
// the server over the TCP connection.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
handle_server_control_message(const PStatServerControlMessage &message) {
|
||||
switch (message._type) {
|
||||
case PStatServerControlMessage::T_hello:
|
||||
pstats_cat.info()
|
||||
<< "Connected to " << message._server_progname << " on "
|
||||
<< message._server_hostname << "\n";
|
||||
|
||||
_server.set_port(message._udp_port);
|
||||
_got_udp_port = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
pstats_cat.error()
|
||||
<< "Invalid control message received from server.\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::connection_reset
|
||||
// Access: Private, Virtual
|
||||
// Description: Called by the internal net code when the connection
|
||||
// has been lost.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
connection_reset(const PT(Connection) &connection, PRErrorCode) {
|
||||
if (connection == _tcp_connection) {
|
||||
disconnect();
|
||||
} else {
|
||||
pstats_cat.warning()
|
||||
<< "Ignoring spurious connection_reset() message\n";
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DO_PSTATS
|
||||
|
@ -22,19 +22,10 @@
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "pStatFrameData.h"
|
||||
|
||||
#include "clockObject.h"
|
||||
#include "pStatClientImpl.h"
|
||||
#include "luse.h"
|
||||
#include "pmap.h"
|
||||
|
||||
#ifdef HAVE_NET
|
||||
#include "connectionManager.h"
|
||||
#include "queuedConnectionReader.h"
|
||||
#include "connectionWriter.h"
|
||||
#include "netAddress.h"
|
||||
#endif
|
||||
|
||||
class PStatServerControlMessage;
|
||||
class PStatCollector;
|
||||
class PStatCollectorDef;
|
||||
class PStatThread;
|
||||
@ -62,25 +53,26 @@ public:
|
||||
PStatClient();
|
||||
~PStatClient();
|
||||
|
||||
PUBLISHED:
|
||||
INLINE void set_client_name(const string &name);
|
||||
INLINE string get_client_name() const;
|
||||
INLINE void set_max_rate(float rate);
|
||||
INLINE float get_max_rate() const;
|
||||
|
||||
int get_num_collectors() const;
|
||||
INLINE int get_num_collectors() const;
|
||||
PStatCollector get_collector(int index) const;
|
||||
const PStatCollectorDef &get_collector_def(int index) const;
|
||||
string get_collector_name(int index) const;
|
||||
string get_collector_fullname(int index) const;
|
||||
|
||||
int get_num_threads() const;
|
||||
INLINE int get_num_threads() const;
|
||||
PStatThread get_thread(int index) const;
|
||||
string get_thread_name(int index) const;
|
||||
INLINE string get_thread_name(int index) const;
|
||||
|
||||
const ClockObject &get_clock() const;
|
||||
PStatThread get_main_thread() const;
|
||||
|
||||
PUBLISHED:
|
||||
INLINE const ClockObject &get_clock() const;
|
||||
|
||||
INLINE static bool connect(const string &hostname = string(), int port = -1);
|
||||
INLINE static void disconnect();
|
||||
INLINE static bool is_connected();
|
||||
@ -89,17 +81,20 @@ PUBLISHED:
|
||||
|
||||
static void main_tick();
|
||||
|
||||
public:
|
||||
void client_main_tick();
|
||||
INLINE bool client_connect(string hostname, int port);
|
||||
void client_disconnect();
|
||||
INLINE bool client_is_connected() const;
|
||||
|
||||
INLINE void client_resume_after_pause();
|
||||
|
||||
static PStatClient *get_global_pstats();
|
||||
|
||||
void client_main_tick();
|
||||
bool client_connect(string hostname, int port);
|
||||
void client_disconnect();
|
||||
bool client_is_connected() const;
|
||||
|
||||
void client_resume_after_pause();
|
||||
|
||||
private:
|
||||
INLINE bool has_impl() const;
|
||||
INLINE PStatClientImpl *get_impl();
|
||||
INLINE const PStatClientImpl *get_impl() const;
|
||||
|
||||
PStatCollector make_collector_with_relname(int parent_index, string relname);
|
||||
PStatCollector make_collector_with_name(int parent_index, const string &name);
|
||||
PStatThread make_thread(const string &name);
|
||||
@ -117,14 +112,6 @@ private:
|
||||
void add_level(int collector_index, int thread_index, float increment);
|
||||
float get_level(int collector_index, int thread_index) const;
|
||||
|
||||
void new_frame(int thread_index);
|
||||
void transmit_frame_data(int thread_index);
|
||||
|
||||
void transmit_control_data();
|
||||
|
||||
// Stats collecting stuff
|
||||
ClockObject _clock;
|
||||
|
||||
// Not a phash_map, so the threads remain sorted by name.
|
||||
typedef pmap<string, int> ThingsByName;
|
||||
ThingsByName _threads_by_name;
|
||||
@ -167,43 +154,18 @@ private:
|
||||
typedef pvector<Thread> Threads;
|
||||
Threads _threads;
|
||||
|
||||
PStatClientImpl *_impl;
|
||||
|
||||
private:
|
||||
// Networking stuff
|
||||
string get_hostname();
|
||||
void send_hello();
|
||||
void report_new_collectors();
|
||||
void report_new_threads();
|
||||
void handle_server_control_message(const PStatServerControlMessage &message);
|
||||
|
||||
virtual void connection_reset(const PT(Connection) &connection,
|
||||
PRErrorCode errcode);
|
||||
|
||||
bool _is_connected;
|
||||
bool _got_udp_port;
|
||||
|
||||
NetAddress _server;
|
||||
QueuedConnectionReader _reader;
|
||||
ConnectionWriter _writer;
|
||||
|
||||
PT(Connection) _tcp_connection;
|
||||
PT(Connection) _udp_connection;
|
||||
|
||||
int _collectors_reported;
|
||||
int _threads_reported;
|
||||
|
||||
string _hostname;
|
||||
string _client_name;
|
||||
float _max_rate;
|
||||
|
||||
float _tcp_count_factor;
|
||||
float _udp_count_factor;
|
||||
unsigned int _tcp_count;
|
||||
unsigned int _udp_count;
|
||||
static PStatCollector _total_size_pcollector;
|
||||
static PStatCollector _cpp_size_pcollector;
|
||||
static PStatCollector _interpreter_size_pcollector;
|
||||
static PStatCollector _pstats_pcollector;
|
||||
|
||||
static PStatClient *_global_pstats;
|
||||
|
||||
friend class PStatCollector;
|
||||
friend class PStatThread;
|
||||
friend class PStatClientImpl;
|
||||
};
|
||||
|
||||
#include "pStatClient.I"
|
||||
|
121
panda/src/pstatclient/pStatClientImpl.I
Normal file
121
panda/src/pstatclient/pStatClientImpl.I
Normal file
@ -0,0 +1,121 @@
|
||||
// Filename: pStatClientImpl.I
|
||||
// Created by: drose (23Dec04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::set_client_name
|
||||
// Access: Public
|
||||
// Description: Sets the name of the client. This is reported to the
|
||||
// PStatsServer, and will presumably be written in the
|
||||
// title bar or something.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatClientImpl::
|
||||
set_client_name(const string &name) {
|
||||
_client_name = name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::get_client_name
|
||||
// Access: Public
|
||||
// Description: Retrieves the name of the client as set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string PStatClientImpl::
|
||||
get_client_name() const {
|
||||
return _client_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::set_max_rate
|
||||
// Access: Public
|
||||
// Description: Controls the number of packets that will be sent to
|
||||
// the server. Normally, one packet is sent per frame,
|
||||
// but this can flood the server with more packets than
|
||||
// it can handle if the frame rate is especially good
|
||||
// (e.g. if nothing is onscreen at the moment). Set
|
||||
// this parameter to a reasonable number to prevent this
|
||||
// from happening.
|
||||
//
|
||||
// This number specifies the maximum number of packets
|
||||
// that will be sent to the server per second, per
|
||||
// thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatClientImpl::
|
||||
set_max_rate(float rate) {
|
||||
_max_rate = rate;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::get_max_rate
|
||||
// Access: Public
|
||||
// Description: Returns the maximum number of packets that will be
|
||||
// sent to the server per second, per thread. See
|
||||
// set_max_rate().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float PStatClientImpl::
|
||||
get_max_rate() const {
|
||||
return _max_rate;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::get_clock
|
||||
// Access: Public
|
||||
// Description: Returns a reference to the PStatClientImpl's clock
|
||||
// object. It keeps its own clock, instead of using the
|
||||
// global clock object, so the stats won't get mucked up
|
||||
// if you put the global clock in non-real-time mode or
|
||||
// something.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const ClockObject &PStatClientImpl::
|
||||
get_clock() const {
|
||||
return _clock;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::client_main_tick
|
||||
// Access: Public
|
||||
// Description: Called only by PStatClient::client_main_tick().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatClientImpl::
|
||||
client_main_tick() {
|
||||
_clock.tick();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::client_is_connected
|
||||
// Access: Public
|
||||
// Description: Called only by PStatClient::client_is_connected().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PStatClientImpl::
|
||||
client_is_connected() const {
|
||||
return _is_connected;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::client_resume_after_pause
|
||||
// Access: Public
|
||||
// Description: Called only by PStatClient::client_resume_after_pause().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatClientImpl::
|
||||
client_resume_after_pause() {
|
||||
// Simply reset the clock to the beginning of the last frame. This
|
||||
// may lose a frame, but on the other hand we won't skip a whole
|
||||
// slew of frames either.
|
||||
|
||||
double frame_time = _clock.get_frame_time();
|
||||
_clock.set_real_time(frame_time);
|
||||
}
|
448
panda/src/pstatclient/pStatClientImpl.cxx
Normal file
448
panda/src/pstatclient/pStatClientImpl.cxx
Normal file
@ -0,0 +1,448 @@
|
||||
// Filename: pStatClientImpl.cxx
|
||||
// Created by: drose (23Dec04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pStatClientImpl.h"
|
||||
|
||||
// This file only defines anything if DO_PSTATS is defined.
|
||||
#ifdef DO_PSTATS
|
||||
|
||||
#include "pStatClient.h"
|
||||
#include "pStatClientControlMessage.h"
|
||||
#include "pStatServerControlMessage.h"
|
||||
#include "pStatCollector.h"
|
||||
#include "pStatThread.h"
|
||||
#include "config_pstats.h"
|
||||
#include "pStatProperties.h"
|
||||
#include "cmath.h"
|
||||
#include "mathNumbers.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef WIN32_VC
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatClientImpl::
|
||||
PStatClientImpl(PStatClient *client) :
|
||||
_client(client),
|
||||
_reader(this, 0),
|
||||
_writer(this, get_pstats_threaded_write() ? 1 : 0)
|
||||
{
|
||||
_is_connected = false;
|
||||
_got_udp_port = false;
|
||||
_collectors_reported = 0;
|
||||
_threads_reported = 0;
|
||||
|
||||
// Make sure our clock is in "normal" mode.
|
||||
_clock.set_mode(ClockObject::M_normal);
|
||||
|
||||
_client_name = get_pstats_name();
|
||||
_max_rate = get_pstats_max_rate();
|
||||
|
||||
_tcp_count = 1;
|
||||
_udp_count = 1;
|
||||
|
||||
double pstats_tcp_ratio = get_pstats_tcp_ratio();
|
||||
|
||||
if (pstats_tcp_ratio >= 1.0f) {
|
||||
_tcp_count_factor = 0.0f;
|
||||
_udp_count_factor = 1.0f;
|
||||
|
||||
} else if (pstats_tcp_ratio <= 0.0f) {
|
||||
_tcp_count_factor = 1.0f;
|
||||
_udp_count_factor = 0.0f;
|
||||
|
||||
} else {
|
||||
csincos(pstats_tcp_ratio * MathNumbers::pi_f / 2.0f,
|
||||
&_udp_count_factor,
|
||||
&_tcp_count_factor);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatClientImpl::
|
||||
~PStatClientImpl() {
|
||||
nassertv(!_is_connected);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::client_connect
|
||||
// Access: Public
|
||||
// Description: Called only by PStatClient::client_connect().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PStatClientImpl::
|
||||
client_connect(string hostname, int port) {
|
||||
nassertr(!_is_connected, true);
|
||||
|
||||
if (hostname.empty()) {
|
||||
hostname = pstats_host;
|
||||
}
|
||||
if (port < 0) {
|
||||
port = pstats_port;
|
||||
}
|
||||
|
||||
if (!_server.set_host(hostname, port)) {
|
||||
pstats_cat.error()
|
||||
<< "Unknown host: " << hostname << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
_tcp_connection = open_TCP_client_connection(_server, 5000);
|
||||
|
||||
if (_tcp_connection.is_null()) {
|
||||
pstats_cat.error()
|
||||
<< "Couldn't connect to PStatServer at " << hostname << ":"
|
||||
<< port << "\n";
|
||||
return false;
|
||||
}
|
||||
// Make sure we're not queuing up multiple TCP sockets--we expect
|
||||
// immediate writes of our TCP datagrams.
|
||||
_tcp_connection->set_collect_tcp(false);
|
||||
|
||||
_reader.add_connection(_tcp_connection);
|
||||
_is_connected = true;
|
||||
|
||||
_udp_connection = open_UDP_connection();
|
||||
|
||||
send_hello();
|
||||
|
||||
return _is_connected;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::client_disconnect
|
||||
// Access: Public
|
||||
// Description: Called only by PStatClient::client_disconnect().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClientImpl::
|
||||
client_disconnect() {
|
||||
if (_is_connected) {
|
||||
_reader.remove_connection(_tcp_connection);
|
||||
close_connection(_tcp_connection);
|
||||
close_connection(_udp_connection);
|
||||
}
|
||||
|
||||
_tcp_connection.clear();
|
||||
_udp_connection.clear();
|
||||
|
||||
_is_connected = false;
|
||||
_got_udp_port = false;
|
||||
|
||||
_collectors_reported = 0;
|
||||
_threads_reported = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::new_frame
|
||||
// Access: Public
|
||||
// Description: Called by the PStatThread interface at the beginning
|
||||
// of every frame, for each thread. This resets the
|
||||
// clocks for the new frame and transmits the data for
|
||||
// the previous frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClientImpl::
|
||||
new_frame(int thread_index) {
|
||||
nassertv(thread_index >= 0 && thread_index < (int)_client->_threads.size());
|
||||
|
||||
PStatClient::Thread &thread = _client->_threads[thread_index];
|
||||
|
||||
// If we're the main thread, we should exchange control packets with
|
||||
// the server.
|
||||
if (thread_index == 0) {
|
||||
transmit_control_data();
|
||||
}
|
||||
|
||||
// If we've got the UDP port by the time the frame starts, it's
|
||||
// time to become active and start actually tracking data.
|
||||
if (_got_udp_port) {
|
||||
thread._is_active = true;
|
||||
}
|
||||
|
||||
if (!thread._is_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
float frame_start = _clock.get_real_time();
|
||||
|
||||
if (!thread._frame_data.is_empty()) {
|
||||
// Collector 0 is the whole frame.
|
||||
_client->stop(0, thread_index, frame_start);
|
||||
|
||||
// Fill up the level data for all the collectors who have level
|
||||
// data for this thread.
|
||||
int num_collectors = _client->_collectors.size();
|
||||
for (int i = 0; i < num_collectors; i++) {
|
||||
const PStatClient::PerThreadData &ptd =
|
||||
_client->_collectors[i]._per_thread[thread_index];
|
||||
if (ptd._has_level) {
|
||||
thread._frame_data.add_level(i, ptd._level);
|
||||
}
|
||||
}
|
||||
transmit_frame_data(thread_index);
|
||||
}
|
||||
|
||||
thread._frame_data.clear();
|
||||
thread._frame_number++;
|
||||
_client->start(0, thread_index, frame_start);
|
||||
|
||||
// Also record the time for the PStats operation itself.
|
||||
int pstats_index = PStatClient::_pstats_pcollector.get_index();
|
||||
_client->start(pstats_index, thread_index, frame_start);
|
||||
_client->stop(pstats_index, thread_index, _clock.get_real_time());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::transmit_frame_data
|
||||
// Access: Private
|
||||
// Description: Should be called once per frame per thread to
|
||||
// transmit the latest data to the PStatServer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClientImpl::
|
||||
transmit_frame_data(int thread_index) {
|
||||
nassertv(thread_index >= 0 && thread_index < (int)_client->_threads.size());
|
||||
if (_is_connected && _client->_threads[thread_index]._is_active) {
|
||||
|
||||
// We don't want to send too many packets in a hurry and flood the
|
||||
// server. Check that enough time has elapsed for us to send a
|
||||
// new packet. If not, we'll drop this packet on the floor and
|
||||
// send a new one next time around.
|
||||
float now = _clock.get_real_time();
|
||||
if (now >= _client->_threads[thread_index]._next_packet) {
|
||||
// We don't want to send more than _max_rate UDP-size packets
|
||||
// per second, per thread.
|
||||
float packet_delay = 1.0 / _max_rate;
|
||||
|
||||
// Send new data.
|
||||
NetDatagram datagram;
|
||||
// We always start with a zero byte, to differentiate it from a
|
||||
// control message.
|
||||
datagram.add_uint8(0);
|
||||
|
||||
datagram.add_uint16(thread_index);
|
||||
datagram.add_uint32(_client->_threads[thread_index]._frame_number);
|
||||
_client->_threads[thread_index]._frame_data.write_datagram(datagram);
|
||||
|
||||
if (_writer.is_valid_for_udp(datagram)) {
|
||||
if (_udp_count * _udp_count_factor < _tcp_count * _tcp_count_factor) {
|
||||
// Send this one as a UDP packet.
|
||||
nassertv(_got_udp_port);
|
||||
_writer.send(datagram, _udp_connection, _server);
|
||||
_udp_count++;
|
||||
|
||||
if (_udp_count == 0) {
|
||||
// Wraparound!
|
||||
_udp_count = 1;
|
||||
_tcp_count = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Send this one as a TCP packet.
|
||||
_writer.send(datagram, _tcp_connection);
|
||||
_tcp_count++;
|
||||
|
||||
if (_tcp_count == 0) {
|
||||
// Wraparound!
|
||||
_udp_count = 1;
|
||||
_tcp_count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
_writer.send(datagram, _tcp_connection);
|
||||
// If our packets are so large that we must ship them via TCP,
|
||||
// then artificially slow down the packet rate even further.
|
||||
int packet_ratio =
|
||||
(datagram.get_length() + maximum_udp_datagram - 1) /
|
||||
maximum_udp_datagram;
|
||||
packet_delay *= (float)packet_ratio;
|
||||
}
|
||||
|
||||
_client->_threads[thread_index]._next_packet = now + packet_delay;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::transmit_control_data
|
||||
// Access: Private
|
||||
// Description: Should be called once a frame to exchange control
|
||||
// information with the server.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClientImpl::
|
||||
transmit_control_data() {
|
||||
// Check for new messages from the server.
|
||||
while (_is_connected && _reader.data_available()) {
|
||||
NetDatagram datagram;
|
||||
|
||||
if (_reader.get_data(datagram)) {
|
||||
PStatServerControlMessage message;
|
||||
if (message.decode(datagram)) {
|
||||
handle_server_control_message(message);
|
||||
|
||||
} else {
|
||||
pstats_cat.error()
|
||||
<< "Got unexpected message from server.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_is_connected) {
|
||||
report_new_collectors();
|
||||
report_new_threads();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::get_hostname
|
||||
// Access: Private
|
||||
// Description: Returns the current machine's hostname.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PStatClientImpl::
|
||||
get_hostname() {
|
||||
if (_hostname.empty()) {
|
||||
char temp_buff[1024];
|
||||
if (gethostname(temp_buff, 1024) == 0) {
|
||||
_hostname = temp_buff;
|
||||
} else {
|
||||
_hostname = "unknown";
|
||||
}
|
||||
}
|
||||
return _hostname;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::send_hello
|
||||
// Access: Private
|
||||
// Description: Sends the initial greeting message to the server.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClientImpl::
|
||||
send_hello() {
|
||||
nassertv(_is_connected);
|
||||
|
||||
PStatClientControlMessage message;
|
||||
message._type = PStatClientControlMessage::T_hello;
|
||||
message._client_hostname = get_hostname();
|
||||
message._client_progname = _client_name;
|
||||
message._major_version = get_current_pstat_major_version();
|
||||
message._minor_version = get_current_pstat_minor_version();
|
||||
|
||||
Datagram datagram;
|
||||
message.encode(datagram);
|
||||
_writer.send(datagram, _tcp_connection);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::report_new_collectors
|
||||
// Access: Private
|
||||
// Description: Sends over any information about new Collectors that
|
||||
// the user code might have recently created.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClientImpl::
|
||||
report_new_collectors() {
|
||||
nassertv(_is_connected);
|
||||
|
||||
if (_collectors_reported < (int)_client->_collectors.size()) {
|
||||
PStatClientControlMessage message;
|
||||
message._type = PStatClientControlMessage::T_define_collectors;
|
||||
while (_collectors_reported < (int)_client->_collectors.size()) {
|
||||
message._collectors.push_back(_client->_collectors[_collectors_reported]._def);
|
||||
_collectors_reported++;
|
||||
}
|
||||
|
||||
Datagram datagram;
|
||||
message.encode(datagram);
|
||||
_writer.send(datagram, _tcp_connection);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::report_new_threads
|
||||
// Access: Private
|
||||
// Description: Sends over any information about new Threads that
|
||||
// the user code might have recently created.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClientImpl::
|
||||
report_new_threads() {
|
||||
nassertv(_is_connected);
|
||||
|
||||
if (_threads_reported < (int)_client->_threads.size()) {
|
||||
PStatClientControlMessage message;
|
||||
message._type = PStatClientControlMessage::T_define_threads;
|
||||
message._first_thread_index = _threads_reported;
|
||||
while (_threads_reported < (int)_client->_threads.size()) {
|
||||
message._names.push_back(_client->_threads[_threads_reported]._name);
|
||||
_threads_reported++;
|
||||
}
|
||||
|
||||
Datagram datagram;
|
||||
message.encode(datagram);
|
||||
_writer.send(datagram, _tcp_connection);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::handle_server_control_message
|
||||
// Access: Private
|
||||
// Description: Called when a control message has been received by
|
||||
// the server over the TCP connection.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClientImpl::
|
||||
handle_server_control_message(const PStatServerControlMessage &message) {
|
||||
switch (message._type) {
|
||||
case PStatServerControlMessage::T_hello:
|
||||
pstats_cat.info()
|
||||
<< "Connected to " << message._server_progname << " on "
|
||||
<< message._server_hostname << "\n";
|
||||
|
||||
_server.set_port(message._udp_port);
|
||||
_got_udp_port = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
pstats_cat.error()
|
||||
<< "Invalid control message received from server.\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientImpl::connection_reset
|
||||
// Access: Private, Virtual
|
||||
// Description: Called by the internal net code when the connection
|
||||
// has been lost.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClientImpl::
|
||||
connection_reset(const PT(Connection) &connection, PRErrorCode) {
|
||||
if (connection == _tcp_connection) {
|
||||
_client->client_disconnect();
|
||||
} else {
|
||||
pstats_cat.warning()
|
||||
<< "Ignoring spurious connection_reset() message\n";
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DO_PSTATS
|
129
panda/src/pstatclient/pStatClientImpl.h
Normal file
129
panda/src/pstatclient/pStatClientImpl.h
Normal file
@ -0,0 +1,129 @@
|
||||
// Filename: pStatClientImpl.h
|
||||
// Created by: drose (23Dec04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PSTATCLIENTIMPL_H
|
||||
#define PSTATCLIENTIMPL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
// This class doesn't exist at all unless DO_PSTATS is defined.
|
||||
#ifdef DO_PSTATS
|
||||
|
||||
#include "pStatFrameData.h"
|
||||
#include "connectionManager.h"
|
||||
#include "queuedConnectionReader.h"
|
||||
#include "connectionWriter.h"
|
||||
#include "netAddress.h"
|
||||
|
||||
#include "clockObject.h"
|
||||
#include "luse.h"
|
||||
#include "pmap.h"
|
||||
|
||||
class PStatClient;
|
||||
class PStatServerControlMessage;
|
||||
class PStatCollector;
|
||||
class PStatCollectorDef;
|
||||
class PStatThread;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PStatClientImpl
|
||||
// Description : This class is the implementation of the actual
|
||||
// PStatClient class (which is just for interface). All
|
||||
// of the stuff to manage sending stats up to the server
|
||||
// is handled by this class.
|
||||
//
|
||||
// This separation between PStatClient and
|
||||
// PStatClientImpl allows the global PStatClient to be
|
||||
// constructed at static init time, without having to
|
||||
// consult any config variables at that time. We don't
|
||||
// actually do any real work until someone explicitly
|
||||
// calls PStatClient::connect().
|
||||
//
|
||||
// This class doesn't exist at all unless DO_PSTATS is
|
||||
// defined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA PStatClientImpl : public ConnectionManager {
|
||||
public:
|
||||
PStatClientImpl(PStatClient *client);
|
||||
~PStatClientImpl();
|
||||
|
||||
INLINE void set_client_name(const string &name);
|
||||
INLINE string get_client_name() const;
|
||||
INLINE void set_max_rate(float rate);
|
||||
INLINE float get_max_rate() const;
|
||||
|
||||
INLINE const ClockObject &get_clock() const;
|
||||
|
||||
INLINE void client_main_tick();
|
||||
bool client_connect(string hostname, int port);
|
||||
void client_disconnect();
|
||||
INLINE bool client_is_connected() const;
|
||||
|
||||
INLINE void client_resume_after_pause();
|
||||
|
||||
void new_frame(int thread_index);
|
||||
|
||||
private:
|
||||
void transmit_frame_data(int thread_index);
|
||||
|
||||
void transmit_control_data();
|
||||
|
||||
// Stats collecting stuff
|
||||
ClockObject _clock;
|
||||
|
||||
// Networking stuff
|
||||
string get_hostname();
|
||||
void send_hello();
|
||||
void report_new_collectors();
|
||||
void report_new_threads();
|
||||
void handle_server_control_message(const PStatServerControlMessage &message);
|
||||
|
||||
virtual void connection_reset(const PT(Connection) &connection,
|
||||
PRErrorCode errcode);
|
||||
|
||||
PStatClient *_client;
|
||||
|
||||
bool _is_connected;
|
||||
bool _got_udp_port;
|
||||
|
||||
NetAddress _server;
|
||||
QueuedConnectionReader _reader;
|
||||
ConnectionWriter _writer;
|
||||
|
||||
PT(Connection) _tcp_connection;
|
||||
PT(Connection) _udp_connection;
|
||||
|
||||
int _collectors_reported;
|
||||
int _threads_reported;
|
||||
|
||||
string _hostname;
|
||||
string _client_name;
|
||||
float _max_rate;
|
||||
|
||||
float _tcp_count_factor;
|
||||
float _udp_count_factor;
|
||||
unsigned int _tcp_count;
|
||||
unsigned int _udp_count;
|
||||
};
|
||||
|
||||
#include "pStatClientImpl.I"
|
||||
|
||||
#endif // DO_PSTATS
|
||||
|
||||
#endif
|
||||
|
@ -99,6 +99,6 @@ operator = (const PStatThread ©) {
|
||||
INLINE void PStatThread::
|
||||
new_frame() {
|
||||
#ifdef DO_PSTATS
|
||||
_client->new_frame(_index);
|
||||
_client->get_impl()->new_frame(_index);
|
||||
#endif
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
#include "config_pstats.cxx"
|
||||
#include "pStatClient.cxx"
|
||||
#include "pStatClientImpl.cxx"
|
||||
#include "pStatClientVersion.cxx"
|
||||
#include "pStatClientControlMessage.cxx"
|
||||
|
Loading…
x
Reference in New Issue
Block a user