Panda3D
pStatMonitor.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file pStatMonitor.cxx
10  * @author drose
11  * @date 2000-07-09
12  */
13 
14 #include "pStatMonitor.h"
15 
16 #include "pStatCollectorDef.h"
17 
18 using std::string;
19 
20 
21 /**
22  *
23  */
24 PStatMonitor::
25 PStatMonitor(PStatServer *server) : _server(server) {
26  _client_known = false;
27 }
28 
29 /**
30  *
31  */
32 PStatMonitor::
33 ~PStatMonitor() {
34 }
35 
36 /**
37  * Called shortly after startup time with the greeting from the client. This
38  * indicates the client's reported hostname and program name.
39  */
41 hello_from(const string &hostname, const string &progname) {
42  _client_known = true;
43  _client_hostname = hostname;
44  _client_progname = progname;
45  got_hello();
46 }
47 
48 /**
49  * Called shortly after startup time with the greeting from the client. In
50  * this case, the client seems to have an incompatible version and will be
51  * automatically disconnected; the server should issue a message to that
52  * effect.
53  */
55 bad_version(const string &hostname, const string &progname,
56  int client_major, int client_minor,
57  int server_major, int server_minor) {
58  _client_known = true;
59  _client_hostname = hostname;
60  _client_progname = progname;
61  got_bad_version(client_major, client_minor,
62  server_major, server_minor);
63 }
64 
65 /**
66  * Called by the PStatServer at setup time to set the new data pointer for the
67  * first time.
68  */
70 set_client_data(PStatClientData *client_data) {
71  _client_data = client_data;
72  initialized();
73 }
74 
75 /**
76  * Returns true if the client is alive and connected, false otherwise.
77  */
79 is_alive() const {
80  if (_client_data.is_null()) {
81  // Not yet, but in a second probably.
82  return false;
83  }
84  return _client_data->is_alive();
85 }
86 
87 /**
88  * Closes the client connection if it is active.
89  */
91 close() {
92  if (!_client_data.is_null()) {
93  _client_data->close();
94  }
95 }
96 
97 /**
98  * Returns the color associated with the indicated collector. If the
99  * collector has no associated color, or is unknown, a new color will be made
100  * up on the spot and associated with this collector for the rest of the
101  * session.
102  */
103 const LRGBColor &PStatMonitor::
104 get_collector_color(int collector_index) {
105  Colors::iterator ci;
106  ci = _colors.find(collector_index);
107  if (ci != _colors.end()) {
108  return (*ci).second;
109  }
110 
111  // Ask the client data about the color.
112  if (!_client_data.is_null() &&
113  _client_data->has_collector(collector_index)) {
114  const PStatCollectorDef &def =
115  _client_data->get_collector_def(collector_index);
116 
117  LRGBColor sc(def._suggested_color.r,
118  def._suggested_color.g,
119  def._suggested_color.b);
120  if (sc != LRGBColor::zero()) {
121  ci = _colors.insert(Colors::value_type(collector_index, sc)).first;
122  return (*ci).second;
123  }
124 
125  // Use the fullname of the collector as a hash to seed the random number
126  // generator (consulted below), so we get the same color for a given name
127  // across sessions.
128  string fullname = _client_data->get_collector_fullname(collector_index);
129  unsigned int hash = 0;
130  for (string::const_iterator ci = fullname.begin(); ci != fullname.end(); ++ci) {
131  hash = hash * 37 + (unsigned int)(*ci);
132  }
133  srand(hash);
134  }
135 
136  // We didn't have a color for the collector; make one up.
137  LRGBColor random_color;
138  random_color[0] = (double)rand() / (double)RAND_MAX;
139  random_color[1] = (double)rand() / (double)RAND_MAX;
140  random_color[2] = (double)rand() / (double)RAND_MAX;
141 
142  ci = _colors.insert(Colors::value_type(collector_index, random_color)).first;
143  return (*ci).second;
144 }
145 
146 /**
147  * Returns a view on the given thread index. If there is no such view already
148  * for the indicated thread, this will create one. This view can be used to
149  * examine the accumulated data for the given thread.
150  */
152 get_view(int thread_index) {
153  Views::iterator vi;
154  vi = _views.find(thread_index);
155  if (vi == _views.end()) {
156  vi = _views.insert(Views::value_type(thread_index, PStatView())).first;
157  (*vi).second.set_thread_data(_client_data->get_thread_data(thread_index));
158  }
159  return (*vi).second;
160 }
161 
162 /**
163  * Returns a view on the level value (as opposed to elapsed time) for the
164  * given collector over the given thread. If there is no such view already
165  * for the indicated thread, this will create one.
166  */
168 get_level_view(int collector_index, int thread_index) {
169  LevelViews::iterator lvi;
170  lvi = _level_views.find(collector_index);
171  if (lvi == _level_views.end()) {
172  lvi = _level_views.insert(LevelViews::value_type(collector_index, Views())).first;
173  }
174  Views &views = (*lvi).second;
175 
176  Views::iterator vi;
177  vi = views.find(thread_index);
178  if (vi == views.end()) {
179  vi = views.insert(Views::value_type(thread_index, PStatView())).first;
180  (*vi).second.set_thread_data(_client_data->get_thread_data(thread_index));
181  (*vi).second.constrain(collector_index, true);
182  }
183  return (*vi).second;
184 }
185 
186 /**
187  * Called after the monitor has been fully set up. At this time, it will have
188  * a valid _client_data pointer, and things like is_alive() and close() will
189  * be meaningful. However, we may not yet know who we're connected to
190  * (is_client_known() may return false), and we may not know anything about
191  * the threads or collectors we're about to get data on.
192  */
194 initialized() {
195 }
196 
197 /**
198  * Called when the "hello" message has been received from the client. At this
199  * time, the client's hostname and program name will be known.
200  */
202 got_hello() {
203 }
204 
205 /**
206  * Like got_hello(), this is called when the "hello" message has been received
207  * from the client. At this time, the client's hostname and program name will
208  * be known. However, the client appears to be an incompatible version and
209  * the connection will be terminated; the monitor should issue a message to
210  * that effect.
211  */
213 got_bad_version(int, int, int, int) {
214 }
215 
216 /**
217  * Called whenever a new Collector definition is received from the client.
218  * Generally, the client will send all of its collectors over shortly after
219  * connecting, but there's no guarantee that they will all be received before
220  * the first frames are received. The monitor should be prepared to accept
221  * new Collector definitions midstream.
222  */
224 new_collector(int) {
225 }
226 
227 /**
228  * Called whenever a new Thread definition is received from the client.
229  * Generally, the client will send all of its threads over shortly after
230  * connecting, but there's no guarantee that they will all be received before
231  * the first frames are received. The monitor should be prepared to accept
232  * new Thread definitions midstream.
233  */
235 new_thread(int) {
236 }
237 
238 /**
239  * Called as each frame's data is made available. There is no guarantee the
240  * frames will arrive in order, or that all of them will arrive at all. The
241  * monitor should be prepared to accept frames received out-of-order or
242  * missing. The use of the PStatFrameData / PStatView objects to report the
243  * data will facilitate this.
244  */
246 new_data(int, int) {
247 }
248 
249 /**
250  * Called whenever the connection to the client has been lost. This is a
251  * permanent state change. The monitor should update its display to represent
252  * this, and may choose to close down automatically.
253  */
255 lost_connection() {
256 }
257 
258 /**
259  * If has_idle() returns true, this will be called periodically to allow the
260  * monitor to update its display or whatever it needs to do.
261  */
263 idle() {
264 }
265 
266 /**
267  * Should be redefined to return true if you want to redefine idle() and
268  * expect it to be called.
269  */
271 has_idle() {
272  return false;
273 }
274 
275 /**
276  * Should be redefined to return true if this monitor class can handle running
277  * in a sub-thread.
278  *
279  * This is not related to the question of whether it can handle multiple
280  * different PStatThreadDatas; this is strictly a question of whether or not
281  * the monitor itself wants to run in a sub-thread.
282  */
284 is_thread_safe() {
285  return false;
286 }
287 
288 /**
289  * Called when the user guide bars have been changed.
290  */
293 }
PStatMonitor::idle
virtual void idle()
If has_idle() returns true, this will be called periodically to allow the monitor to update its displ...
Definition: pStatMonitor.cxx:263
PStatMonitor::set_client_data
void set_client_data(PStatClientData *client_data)
Called by the PStatServer at setup time to set the new data pointer for the first time.
Definition: pStatMonitor.cxx:70
PStatMonitor::bad_version
void bad_version(const std::string &hostname, const std::string &progname, int client_major, int client_minor, int server_major, int server_minor)
Called shortly after startup time with the greeting from the client.
Definition: pStatMonitor.cxx:55
PStatServer
The overall manager of the network connections.
Definition: pStatServer.h:36
pmap< int, PStatView >
PStatMonitor::get_collector_color
const LRGBColor & get_collector_color(int collector_index)
Returns the color associated with the indicated collector.
Definition: pStatMonitor.cxx:104
PStatMonitor::has_idle
virtual bool has_idle()
Should be redefined to return true if you want to redefine idle() and expect it to be called.
Definition: pStatMonitor.cxx:271
PStatCollectorDef
Defines the details about the Collectors: the name, the suggested color, etc.
Definition: pStatCollectorDef.h:29
PStatMonitor::new_data
virtual void new_data(int thread_index, int frame_number)
Called as each frame's data is made available.
Definition: pStatMonitor.cxx:246
PStatMonitor::got_bad_version
virtual void got_bad_version(int client_major, int client_minor, int server_major, int server_minor)
Like got_hello(), this is called when the "hello" message has been received from the client.
Definition: pStatMonitor.cxx:213
PStatMonitor::hello_from
void hello_from(const std::string &hostname, const std::string &progname)
Called shortly after startup time with the greeting from the client.
Definition: pStatMonitor.cxx:41
PStatClientData
The data associated with a particular client, but not with any one particular frame or thread: the li...
Definition: pStatClientData.h:36
PStatView
A View boils down the frame data to a linear list of times spent in a number of different Collectors,...
Definition: pStatView.h:31
PStatMonitor::get_view
PStatView & get_view(int thread_index)
Returns a view on the given thread index.
Definition: pStatMonitor.cxx:152
PStatMonitor::is_alive
bool is_alive() const
Returns true if the client is alive and connected, false otherwise.
Definition: pStatMonitor.cxx:79
PStatMonitor::close
void close()
Closes the client connection if it is active.
Definition: pStatMonitor.cxx:91
PStatMonitor::new_thread
virtual void new_thread(int thread_index)
Called whenever a new Thread definition is received from the client.
Definition: pStatMonitor.cxx:235
pStatMonitor.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PStatMonitor::lost_connection
virtual void lost_connection()
Called whenever the connection to the client has been lost.
Definition: pStatMonitor.cxx:255
pStatCollectorDef.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PStatMonitor::got_hello
virtual void got_hello()
Called when the "hello" message has been received from the client.
Definition: pStatMonitor.cxx:202
PStatMonitor::is_thread_safe
virtual bool is_thread_safe()
Should be redefined to return true if this monitor class can handle running in a sub-thread.
Definition: pStatMonitor.cxx:284
PStatMonitor::initialized
virtual void initialized()
Called after the monitor has been fully set up.
Definition: pStatMonitor.cxx:194
PStatMonitor::new_collector
virtual void new_collector(int collector_index)
Called whenever a new Collector definition is received from the client.
Definition: pStatMonitor.cxx:224
PStatMonitor::get_level_view
PStatView & get_level_view(int collector_index, int thread_index)
Returns a view on the level value (as opposed to elapsed time) for the given collector over the given...
Definition: pStatMonitor.cxx:168
PStatMonitor::user_guide_bars_changed
virtual void user_guide_bars_changed()
Called when the user guide bars have been changed.
Definition: pStatMonitor.cxx:292