Panda3D
 All Classes Functions Variables Enumerations
pStatMonitor.cxx
00001 // Filename: pStatMonitor.cxx
00002 // Created by:  drose (09Jul00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "pStatMonitor.h"
00016 
00017 #include "pStatCollectorDef.h"
00018 
00019 
00020 ////////////////////////////////////////////////////////////////////
00021 //     Function: PStatMonitor::Constructor
00022 //       Access: Public
00023 //  Description:
00024 ////////////////////////////////////////////////////////////////////
00025 PStatMonitor::
00026 PStatMonitor(PStatServer *server) : _server(server) {
00027   _client_known = false;
00028 }
00029 
00030 ////////////////////////////////////////////////////////////////////
00031 //     Function: PStatMonitor::Destructor
00032 //       Access: Public, Virtual
00033 //  Description:
00034 ////////////////////////////////////////////////////////////////////
00035 PStatMonitor::
00036 ~PStatMonitor() {
00037 }
00038 
00039 ////////////////////////////////////////////////////////////////////
00040 //     Function: PStatMonitor::hello_from
00041 //       Access: Public
00042 //  Description: Called shortly after startup time with the greeting
00043 //               from the client.  This indicates the client's
00044 //               reported hostname and program name.
00045 ////////////////////////////////////////////////////////////////////
00046 void PStatMonitor::
00047 hello_from(const string &hostname, const string &progname) {
00048   _client_known = true;
00049   _client_hostname = hostname;
00050   _client_progname = progname;
00051   got_hello();
00052 }
00053 
00054 ////////////////////////////////////////////////////////////////////
00055 //     Function: PStatMonitor::bad_version
00056 //       Access: Public
00057 //  Description: Called shortly after startup time with the greeting
00058 //               from the client.  In this case, the client seems to
00059 //               have an incompatible version and will be
00060 //               automatically disconnected; the server should issue a
00061 //               message to that effect.
00062 ////////////////////////////////////////////////////////////////////
00063 void PStatMonitor::
00064 bad_version(const string &hostname, const string &progname,
00065             int client_major, int client_minor,
00066             int server_major, int server_minor) {
00067   _client_known = true;
00068   _client_hostname = hostname;
00069   _client_progname = progname;
00070   got_bad_version(client_major, client_minor,
00071                   server_major, server_minor);
00072 }
00073 
00074 ////////////////////////////////////////////////////////////////////
00075 //     Function: PStatMonitor::set_client_data
00076 //       Access: Public
00077 //  Description: Called by the PStatServer at setup time to set the
00078 //               new data pointer for the first time.
00079 ////////////////////////////////////////////////////////////////////
00080 void PStatMonitor::
00081 set_client_data(PStatClientData *client_data) {
00082   _client_data = client_data;
00083   initialized();
00084 }
00085 
00086 ////////////////////////////////////////////////////////////////////
00087 //     Function: PStatMonitor::is_alive
00088 //       Access: Public
00089 //  Description: Returns true if the client is alive and connected,
00090 //               false otherwise.
00091 ////////////////////////////////////////////////////////////////////
00092 bool PStatMonitor::
00093 is_alive() const {
00094   if (_client_data.is_null()) {
00095     // Not yet, but in a second probably.
00096     return false;
00097   }
00098   return _client_data->is_alive();
00099 }
00100 
00101 ////////////////////////////////////////////////////////////////////
00102 //     Function: PStatMonitor::close
00103 //       Access: Public
00104 //  Description: Closes the client connection if it is active.
00105 ////////////////////////////////////////////////////////////////////
00106 void PStatMonitor::
00107 close() {
00108   if (!_client_data.is_null()) {
00109     _client_data->close();
00110   }
00111 }
00112 
00113 ////////////////////////////////////////////////////////////////////
00114 //     Function: PStatMonitor::get_collector_color
00115 //       Access: Public
00116 //  Description: Returns the color associated with the indicated
00117 //               collector.  If the collector has no associated color,
00118 //               or is unknown, a new color will be made up on the
00119 //               spot and associated with this collector for the rest
00120 //               of the session.
00121 ////////////////////////////////////////////////////////////////////
00122 const LRGBColor &PStatMonitor::
00123 get_collector_color(int collector_index) {
00124   Colors::iterator ci;
00125   ci = _colors.find(collector_index);
00126   if (ci != _colors.end()) {
00127     return (*ci).second;
00128   }
00129 
00130   // Ask the client data about the color.
00131   if (!_client_data.is_null() &&
00132       _client_data->has_collector(collector_index)) {
00133     const PStatCollectorDef &def =
00134       _client_data->get_collector_def(collector_index);
00135 
00136     LRGBColor sc(def._suggested_color.r,
00137                  def._suggested_color.g,
00138                  def._suggested_color.b);
00139     if (sc != LRGBColor::zero()) {
00140       ci = _colors.insert(Colors::value_type(collector_index, sc)).first;
00141       return (*ci).second;
00142     }
00143 
00144     // Use the fullname of the collector as a hash to seed the random
00145     // number generator (consulted below), so we get the same color
00146     // for a given name across sessions.
00147     string fullname = _client_data->get_collector_fullname(collector_index);
00148     unsigned int hash = 0;
00149     for (string::const_iterator ci = fullname.begin(); ci != fullname.end(); ++ci) {
00150       hash = hash * 37 + (unsigned int)(*ci);
00151     }
00152     srand(hash);
00153   }
00154 
00155   // We didn't have a color for the collector; make one up.
00156   LRGBColor random_color;
00157   random_color[0] = (double)rand() / (double)RAND_MAX;
00158   random_color[1] = (double)rand() / (double)RAND_MAX;
00159   random_color[2] = (double)rand() / (double)RAND_MAX;
00160 
00161   ci = _colors.insert(Colors::value_type(collector_index, random_color)).first;
00162   return (*ci).second;
00163 }
00164 
00165 ////////////////////////////////////////////////////////////////////
00166 //     Function: PStatMonitor::get_view
00167 //       Access: Public
00168 //  Description: Returns a view on the given thread index.  If there
00169 //               is no such view already for the indicated thread,
00170 //               this will create one.  This view can be used to
00171 //               examine the accumulated data for the given thread.
00172 ////////////////////////////////////////////////////////////////////
00173 PStatView &PStatMonitor::
00174 get_view(int thread_index) {
00175   Views::iterator vi;
00176   vi = _views.find(thread_index);
00177   if (vi == _views.end()) {
00178     vi = _views.insert(Views::value_type(thread_index, PStatView())).first;
00179     (*vi).second.set_thread_data(_client_data->get_thread_data(thread_index));
00180   }
00181   return (*vi).second;
00182 }
00183 
00184 ////////////////////////////////////////////////////////////////////
00185 //     Function: PStatMonitor::get_level_view
00186 //       Access: Public
00187 //  Description: Returns a view on the level value (as opposed to
00188 //               elapsed time) for the given collector over the given
00189 //               thread.  If there is no such view already for the
00190 //               indicated thread, this will create one.
00191 ////////////////////////////////////////////////////////////////////
00192 PStatView &PStatMonitor::
00193 get_level_view(int collector_index, int thread_index) {
00194   LevelViews::iterator lvi;
00195   lvi = _level_views.find(collector_index);
00196   if (lvi == _level_views.end()) {
00197     lvi = _level_views.insert(LevelViews::value_type(collector_index, Views())).first;
00198   }
00199   Views &views = (*lvi).second;
00200 
00201   Views::iterator vi;
00202   vi = views.find(thread_index);
00203   if (vi == views.end()) {
00204     vi = views.insert(Views::value_type(thread_index, PStatView())).first;
00205     (*vi).second.set_thread_data(_client_data->get_thread_data(thread_index));
00206     (*vi).second.constrain(collector_index, true);
00207   }
00208   return (*vi).second;
00209 }
00210 
00211 ////////////////////////////////////////////////////////////////////
00212 //     Function: PStatMonitor::initialized
00213 //       Access: Public, Virtual
00214 //  Description: Called after the monitor has been fully set up.  At
00215 //               this time, it will have a valid _client_data pointer,
00216 //               and things like is_alive() and close() will be
00217 //               meaningful.  However, we may not yet know who we're
00218 //               connected to (is_client_known() may return false),
00219 //               and we may not know anything about the threads or
00220 //               collectors we're about to get data on.
00221 ////////////////////////////////////////////////////////////////////
00222 void PStatMonitor::
00223 initialized() {
00224 }
00225 
00226 ////////////////////////////////////////////////////////////////////
00227 //     Function: PStatMonitor::got_hello
00228 //       Access: Public, Virtual
00229 //  Description: Called when the "hello" message has been received
00230 //               from the client.  At this time, the client's hostname
00231 //               and program name will be known.
00232 ////////////////////////////////////////////////////////////////////
00233 void PStatMonitor::
00234 got_hello() {
00235 }
00236 
00237 ////////////////////////////////////////////////////////////////////
00238 //     Function: PStatMonitor::got_bad_version
00239 //       Access: Public, Virtual
00240 //  Description: Like got_hello(), this is called when the "hello"
00241 //               message has been received from the client.  At this
00242 //               time, the client's hostname and program name will be
00243 //               known.  However, the client appears to be an
00244 //               incompatible version and the connection will be
00245 //               terminated; the monitor should issue a message to
00246 //               that effect.
00247 ////////////////////////////////////////////////////////////////////
00248 void PStatMonitor::
00249 got_bad_version(int, int, int, int) {
00250 }
00251 
00252 ////////////////////////////////////////////////////////////////////
00253 //     Function: PStatMonitor::new_collector
00254 //       Access: Public, Virtual
00255 //  Description: Called whenever a new Collector definition is
00256 //               received from the client.  Generally, the client will
00257 //               send all of its collectors over shortly after
00258 //               connecting, but there's no guarantee that they will
00259 //               all be received before the first frames are received.
00260 //               The monitor should be prepared to accept new Collector
00261 //               definitions midstream.
00262 ////////////////////////////////////////////////////////////////////
00263 void PStatMonitor::
00264 new_collector(int) {
00265 }
00266 
00267 ////////////////////////////////////////////////////////////////////
00268 //     Function: PStatMonitor::new_thread
00269 //       Access: Public, Virtual
00270 //  Description: Called whenever a new Thread definition is
00271 //               received from the client.  Generally, the client will
00272 //               send all of its threads over shortly after
00273 //               connecting, but there's no guarantee that they will
00274 //               all be received before the first frames are received.
00275 //               The monitor should be prepared to accept new Thread
00276 //               definitions midstream.
00277 ////////////////////////////////////////////////////////////////////
00278 void PStatMonitor::
00279 new_thread(int) {
00280 }
00281 
00282 ////////////////////////////////////////////////////////////////////
00283 //     Function: PStatMonitor::new_data
00284 //       Access: Public, Virtual
00285 //  Description: Called as each frame's data is made available.  There
00286 //               is no guarantee the frames will arrive in order, or
00287 //               that all of them will arrive at all.  The monitor
00288 //               should be prepared to accept frames received
00289 //               out-of-order or missing.  The use of the
00290 //               PStatFrameData / PStatView objects to report the data
00291 //               will facilitate this.
00292 ////////////////////////////////////////////////////////////////////
00293 void PStatMonitor::
00294 new_data(int, int) {
00295 }
00296 
00297 ////////////////////////////////////////////////////////////////////
00298 //     Function: PStatMonitor::lost_connection
00299 //       Access: Public, Virtual
00300 //  Description: Called whenever the connection to the client has been
00301 //               lost.  This is a permanent state change.  The monitor
00302 //               should update its display to represent this, and may
00303 //               choose to close down automatically.
00304 ////////////////////////////////////////////////////////////////////
00305 void PStatMonitor::
00306 lost_connection() {
00307 }
00308 
00309 ////////////////////////////////////////////////////////////////////
00310 //     Function: PStatMonitor::idle
00311 //       Access: Public, Virtual
00312 //  Description: If has_idle() returns true, this will be called
00313 //               periodically to allow the monitor to update its
00314 //               display or whatever it needs to do.
00315 ////////////////////////////////////////////////////////////////////
00316 void PStatMonitor::
00317 idle() {
00318 }
00319 
00320 ////////////////////////////////////////////////////////////////////
00321 //     Function: PStatMonitor::has_idle
00322 //       Access: Public, Virtual
00323 //  Description: Should be redefined to return true if you want to
00324 //               redefine idle() and expect it to be called.
00325 ////////////////////////////////////////////////////////////////////
00326 bool PStatMonitor::
00327 has_idle() {
00328   return false;
00329 }
00330 
00331 ////////////////////////////////////////////////////////////////////
00332 //     Function: PStatMonitor::is_thread_safe
00333 //       Access: Public, Virtual
00334 //  Description: Should be redefined to return true if this monitor
00335 //               class can handle running in a sub-thread.
00336 //
00337 //               This is not related to the question of whether it can
00338 //               handle multiple different PStatThreadDatas; this is
00339 //               strictly a question of whether or not the monitor
00340 //               itself wants to run in a sub-thread.
00341 ////////////////////////////////////////////////////////////////////
00342 bool PStatMonitor::
00343 is_thread_safe() {
00344   return false;
00345 }
00346 
00347 ////////////////////////////////////////////////////////////////////
00348 //     Function: PStatMonitor::user_guide_bars_changed
00349 //       Access: Public, Virtual
00350 //  Description: Called when the user guide bars have been changed.
00351 ////////////////////////////////////////////////////////////////////
00352 void PStatMonitor::
00353 user_guide_bars_changed() {
00354 }
 All Classes Functions Variables Enumerations