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  */
40 void PStatMonitor::
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  */
54 void PStatMonitor::
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  */
69 void PStatMonitor::
71  _client_data = client_data;
72  initialized();
73 }
74 
75 /**
76  * Returns true if the client is alive and connected, false otherwise.
77  */
78 bool PStatMonitor::
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  */
90 void PStatMonitor::
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  */
193 void PStatMonitor::
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  */
201 void PStatMonitor::
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  */
212 void PStatMonitor::
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  */
223 void PStatMonitor::
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  */
234 void PStatMonitor::
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  */
245 void PStatMonitor::
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  */
254 void PStatMonitor::
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  */
262 void PStatMonitor::
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  */
270 bool PStatMonitor::
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  */
283 bool PStatMonitor::
285  return false;
286 }
287 
288 /**
289  * Called when the user guide bars have been changed.
290  */
291 void PStatMonitor::
293 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
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.
virtual bool is_thread_safe()
Should be redefined to return true if this monitor class can handle running in a sub-thread.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
A View boils down the frame data to a linear list of times spent in a number of different Collectors,...
Definition: pStatView.h:31
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:36
void hello_from(const std::string &hostname, const std::string &progname)
Called shortly after startup time with the greeting from the client.
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.