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