00001 // Filename: pStatClientData.cxx 00002 // Created by: drose (11Jul00) 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 "pStatClientData.h" 00020 #include "pStatReader.h" 00021 00022 #include <pStatCollectorDef.h> 00023 00024 PStatCollectorDef PStatClientData::_null_collector(-1, "Unknown"); 00025 00026 00027 00028 //////////////////////////////////////////////////////////////////// 00029 // Function: PStatClientData::Constructor 00030 // Access: Public 00031 // Description: 00032 //////////////////////////////////////////////////////////////////// 00033 PStatClientData:: 00034 PStatClientData(PStatReader *reader) : 00035 _reader(reader) 00036 { 00037 _is_alive = true; 00038 } 00039 00040 //////////////////////////////////////////////////////////////////// 00041 // Function: PStatClientData::Destructor 00042 // Access: Public 00043 // Description: 00044 //////////////////////////////////////////////////////////////////// 00045 PStatClientData:: 00046 ~PStatClientData() { 00047 Collectors::const_iterator ci; 00048 for (ci = _collectors.begin(); ci != _collectors.end(); ++ci) { 00049 delete (*ci)._def; 00050 } 00051 } 00052 00053 //////////////////////////////////////////////////////////////////// 00054 // Function: PStatClientData::is_alive 00055 // Access: Public 00056 // Description: Returns true if the data is actively getting filled 00057 // by a connected client, or false if the client has 00058 // terminated. 00059 //////////////////////////////////////////////////////////////////// 00060 bool PStatClientData:: 00061 is_alive() const { 00062 return _is_alive; 00063 } 00064 00065 //////////////////////////////////////////////////////////////////// 00066 // Function: PStatClientData::close 00067 // Access: Public 00068 // Description: Closes the client connection if it is open. 00069 //////////////////////////////////////////////////////////////////// 00070 void PStatClientData:: 00071 close() { 00072 if (_is_alive && _reader != (PStatReader *)NULL) { 00073 _reader->close(); 00074 _reader = (PStatReader *)NULL; 00075 _is_alive = false; 00076 } 00077 } 00078 00079 //////////////////////////////////////////////////////////////////// 00080 // Function: PStatClientData::get_num_collectors 00081 // Access: Public 00082 // Description: Returns the total number of collectors the Data 00083 // knows about. 00084 //////////////////////////////////////////////////////////////////// 00085 int PStatClientData:: 00086 get_num_collectors() const { 00087 return _collectors.size(); 00088 } 00089 00090 //////////////////////////////////////////////////////////////////// 00091 // Function: PStatClientData::has_collector 00092 // Access: Public 00093 // Description: Returns true if the indicated collector has been 00094 // defined by the client already, false otherwise. It 00095 // is possible for the client to start streaming data 00096 // before all of the collectors have been defined. 00097 //////////////////////////////////////////////////////////////////// 00098 bool PStatClientData:: 00099 has_collector(int index) const { 00100 return (index >= 0 && index < (int)_collectors.size() && 00101 _collectors[index]._def != (PStatCollectorDef *)NULL); 00102 } 00103 00104 //////////////////////////////////////////////////////////////////// 00105 // Function: PStatClientData::get_collector_def 00106 // Access: Public 00107 // Description: Returns the nth collector definition. 00108 //////////////////////////////////////////////////////////////////// 00109 const PStatCollectorDef &PStatClientData:: 00110 get_collector_def(int index) const { 00111 if (!has_collector(index)) { 00112 return _null_collector; 00113 } 00114 return *_collectors[index]._def; 00115 } 00116 00117 //////////////////////////////////////////////////////////////////// 00118 // Function: PStatClientData::get_collector_name 00119 // Access: Public 00120 // Description: Returns the name of the indicated collector. 00121 //////////////////////////////////////////////////////////////////// 00122 string PStatClientData:: 00123 get_collector_name(int index) const { 00124 if (!has_collector(index)) { 00125 return "Unknown"; 00126 } 00127 const PStatCollectorDef *def = _collectors[index]._def; 00128 return def->_name; 00129 } 00130 00131 //////////////////////////////////////////////////////////////////// 00132 // Function: PStatClientData::get_collector_fullname 00133 // Access: Public 00134 // Description: Returns the "full name" of the indicated collector. 00135 // This will be the concatenation of all of the 00136 // collector's parents' names (except Frame) and the 00137 // collector's own name. 00138 //////////////////////////////////////////////////////////////////// 00139 string PStatClientData:: 00140 get_collector_fullname(int index) const { 00141 if (!has_collector(index)) { 00142 return "Unknown"; 00143 } 00144 00145 const PStatCollectorDef *def = _collectors[index]._def; 00146 if (def->_parent_index == 0) { 00147 return def->_name; 00148 } else { 00149 return get_collector_fullname(def->_parent_index) + ":" + def->_name; 00150 } 00151 } 00152 00153 //////////////////////////////////////////////////////////////////// 00154 // Function: PStatClientData::set_collector_has_level 00155 // Access: Public 00156 // Description: Indicates whether the given collector has level data 00157 // (and consequently, whether it should appear on the 00158 // Levels menu). 00159 //////////////////////////////////////////////////////////////////// 00160 void PStatClientData:: 00161 set_collector_has_level(int index, bool flag) { 00162 slot_collector(index); 00163 nassertv(index >= 0 && index < (int)_collectors.size()); 00164 _collectors[index]._is_level = flag; 00165 } 00166 00167 00168 //////////////////////////////////////////////////////////////////// 00169 // Function: PStatClientData::get_collector_has_level 00170 // Access: Public 00171 // Description: Returns whether the given collector has level data 00172 // (and consequently, whether it should appear on the 00173 // Levels menu). 00174 //////////////////////////////////////////////////////////////////// 00175 bool PStatClientData:: 00176 get_collector_has_level(int index) const { 00177 return (index >= 0 && index < (int)_collectors.size() && 00178 _collectors[index]._is_level); 00179 } 00180 00181 //////////////////////////////////////////////////////////////////// 00182 // Function: PStatClientData::get_num_threads 00183 // Access: Public 00184 // Description: Returns the total number of threads the Data 00185 // knows about. 00186 //////////////////////////////////////////////////////////////////// 00187 int PStatClientData:: 00188 get_num_threads() const { 00189 return _threads.size(); 00190 } 00191 00192 //////////////////////////////////////////////////////////////////// 00193 // Function: PStatClientData::has_thread 00194 // Access: Public 00195 // Description: Returns true if the indicated thread has been 00196 // defined by the client already, false otherwise. It 00197 // is possible for the client to start streaming data 00198 // before all of the threads have been defined. 00199 //////////////////////////////////////////////////////////////////// 00200 bool PStatClientData:: 00201 has_thread(int index) const { 00202 return (index >= 0 && index < (int)_threads.size() && 00203 !_threads[index]._name.empty()); 00204 } 00205 00206 //////////////////////////////////////////////////////////////////// 00207 // Function: PStatClientData::get_thread_name 00208 // Access: Public 00209 // Description: Returns the name of the indicated thread. 00210 //////////////////////////////////////////////////////////////////// 00211 string PStatClientData:: 00212 get_thread_name(int index) const { 00213 if (!has_thread(index)) { 00214 return "Unknown"; 00215 } 00216 return _threads[index]._name; 00217 } 00218 00219 //////////////////////////////////////////////////////////////////// 00220 // Function: PStatClientData::get_thread_data 00221 // Access: Public 00222 // Description: Returns the data associated with the indicated 00223 // thread. This will create a thread definition if it 00224 // does not already exist. 00225 //////////////////////////////////////////////////////////////////// 00226 const PStatThreadData *PStatClientData:: 00227 get_thread_data(int index) const { 00228 ((PStatClientData *)this)->define_thread(index); 00229 nassertr(index >= 0 && index < (int)_threads.size(), NULL); 00230 return _threads[index]._data; 00231 } 00232 00233 //////////////////////////////////////////////////////////////////// 00234 // Function: PStatClientData::get_child_distance 00235 // Access: Public 00236 // Description: Returns the number of Collectors between the 00237 // indicated parent and the child Collector in the 00238 // relationship graph. If child is the same as parent, 00239 // returns zero. If child is an immediate child of 00240 // parent, returns 1. If child is a grandchild of 00241 // parent, returns 2, and so on. If child is not a 00242 // descendant of parent at all, returns -1. 00243 //////////////////////////////////////////////////////////////////// 00244 int PStatClientData:: 00245 get_child_distance(int parent, int child) const { 00246 if (parent == child) { 00247 return 0; 00248 } 00249 if (!has_collector(child) || child == 0) { 00250 return -1; 00251 } 00252 int dist = get_child_distance(parent, get_collector_def(child)._parent_index); 00253 if (dist == -1) { 00254 return -1; 00255 } else { 00256 return dist + 1; 00257 } 00258 } 00259 00260 //////////////////////////////////////////////////////////////////// 00261 // Function: PStatClientData::add_collector 00262 // Access: Public 00263 // Description: Adds a new collector definition to the dataset. 00264 // Presumably this is information just arrived from the 00265 // client. 00266 // 00267 // The pointer will become owned by the PStatClientData 00268 // object and will be freed on destruction. 00269 //////////////////////////////////////////////////////////////////// 00270 void PStatClientData:: 00271 add_collector(PStatCollectorDef *def) { 00272 slot_collector(def->_index); 00273 nassertv(def->_index >= 0 && def->_index < (int)_collectors.size()); 00274 00275 if (_collectors[def->_index]._def != (PStatCollectorDef *)NULL) { 00276 // Free the old definition, if any. 00277 delete _collectors[def->_index]._def; 00278 } 00279 00280 _collectors[def->_index]._def = def; 00281 } 00282 00283 //////////////////////////////////////////////////////////////////// 00284 // Function: PStatClientData::define_thread 00285 // Access: Public 00286 // Description: Adds a new thread definition to the dataset. 00287 // Presumably this is information just arrived from the 00288 // client. 00289 //////////////////////////////////////////////////////////////////// 00290 void PStatClientData:: 00291 define_thread(int thread_index, const string &name) { 00292 // A sanity check on the index number. 00293 nassertv(thread_index < 1000); 00294 00295 // Make sure we have enough slots allocated. 00296 while ((int)_threads.size() <= thread_index) { 00297 _threads.push_back(Thread()); 00298 } 00299 00300 if (!name.empty()) { 00301 _threads[thread_index]._name = name; 00302 } 00303 00304 if (_threads[thread_index]._data.is_null()) { 00305 _threads[thread_index]._data = new PStatThreadData(this); 00306 } 00307 } 00308 00309 00310 //////////////////////////////////////////////////////////////////// 00311 // Function: PStatClientData::record_new_frame 00312 // Access: Public 00313 // Description: Makes room for and stores a new frame's worth of 00314 // data associated with some particular thread (which 00315 // may or may not have already been defined). 00316 // 00317 // The pointer will become owned by the PStatThreadData 00318 // object and will be freed on destruction. 00319 //////////////////////////////////////////////////////////////////// 00320 void PStatClientData:: 00321 record_new_frame(int thread_index, int frame_number, 00322 PStatFrameData *frame_data) { 00323 define_thread(thread_index); 00324 nassertv(thread_index >= 0 && thread_index < (int)_threads.size()); 00325 _threads[thread_index]._data->record_new_frame(frame_number, frame_data); 00326 } 00327 00328 //////////////////////////////////////////////////////////////////// 00329 // Function: PStatClientData::slot_collector 00330 // Access: Private 00331 // Description: Makes sure there is an entry in the array for a 00332 // collector with the given index number. 00333 //////////////////////////////////////////////////////////////////// 00334 void PStatClientData:: 00335 slot_collector(int collector_index) { 00336 // A sanity check on the index number. 00337 nassertv(collector_index < 1000); 00338 00339 while ((int)_collectors.size() <= collector_index) { 00340 Collector collector; 00341 collector._def = (PStatCollectorDef *)NULL; 00342 collector._is_level = false; 00343 _collectors.push_back(collector); 00344 } 00345 }