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