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