Panda3D
Loading...
Searching...
No Matches
pStatClientData.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 pStatClientData.cxx
10 * @author drose
11 * @date 2000-07-11
12 */
13
14#include "pStatClientData.h"
15#include "pStatReader.h"
16
17#include "pStatCollectorDef.h"
18
19using std::string;
20
21PStatCollectorDef PStatClientData::_null_collector(-1, "Unknown");
22
23
24
25/**
26 *
27 */
28PStatClientData::
29PStatClientData(PStatReader *reader) :
30 _reader(reader)
31{
32 _is_alive = true;
33}
34
35/**
36 *
37 */
38PStatClientData::
39~PStatClientData() {
40 Collectors::const_iterator ci;
41 for (ci = _collectors.begin(); ci != _collectors.end(); ++ci) {
42 delete (*ci)._def;
43 }
44}
45
46/**
47 * Returns true if the data is actively getting filled by a connected client,
48 * or false if the client has terminated.
49 */
51is_alive() const {
52 return _is_alive;
53}
54
55/**
56 * Closes the client connection if it is open.
57 */
59close() {
60 if (_is_alive && _reader != nullptr) {
61 _reader->close();
62 _reader = nullptr;
63 _is_alive = false;
64 }
65}
66
67/**
68 * Returns the total number of collectors the Data knows about.
69 */
71get_num_collectors() const {
72 return _collectors.size();
73}
74
75/**
76 * Returns true if the indicated collector has been defined by the client
77 * already, false otherwise. It is possible for the client to start streaming
78 * data before all of the collectors have been defined.
79 */
81has_collector(int index) const {
82 return (index >= 0 && index < (int)_collectors.size() &&
83 _collectors[index]._def != nullptr);
84}
85
86/**
87 * Returns the nth collector definition.
88 */
90get_collector_def(int index) const {
91 if (!has_collector(index)) {
92 return _null_collector;
93 }
94 return *_collectors[index]._def;
95}
96
97/**
98 * Returns the name of the indicated collector.
99 */
101get_collector_name(int index) const {
102 if (!has_collector(index)) {
103 return "Unknown";
104 }
105 const PStatCollectorDef *def = _collectors[index]._def;
106 return def->_name;
107}
108
109/**
110 * Returns the "full name" of the indicated collector. This will be the
111 * concatenation of all of the collector's parents' names (except Frame) and
112 * the collector's own name.
113 */
115get_collector_fullname(int index) const {
116 if (!has_collector(index)) {
117 return "Unknown";
118 }
119
120 const PStatCollectorDef *def = _collectors[index]._def;
121 if (def->_parent_index == 0) {
122 return def->_name;
123 } else {
124 return get_collector_fullname(def->_parent_index) + ":" + def->_name;
125 }
126}
127
128/**
129 * Indicates whether the given collector has level data (and consequently,
130 * whether it should appear on the Levels menu).
131 *
132 * The return value is true if anything changed, false otherwise.
133 */
135set_collector_has_level(int index, int thread_index, bool flag) {
136 bool any_changed = false;
137 slot_collector(index);
138 nassertr(index >= 0 && index < (int)_collectors.size(), false);
139
140 if (_collectors[index]._is_level.get_bit(thread_index) != flag) {
141 any_changed = true;
142 _collectors[index]._is_level.set_bit_to(thread_index, flag);
143 }
144
145 // Turning this on for a given collector also implicitly turns all of its
146 // ancestors.
147 if (flag) {
148 PStatCollectorDef *def = _collectors[index]._def;
149 if (def != nullptr && def->_parent_index != 0) {
150 if (set_collector_has_level(def->_parent_index, thread_index, flag)) {
151 any_changed = true;
152 }
153 }
154 }
155
156 return any_changed;
157}
158
159
160/**
161 * Returns whether the given collector has level data (and consequently,
162 * whether it should appear on the Levels menu).
163 */
165get_collector_has_level(int index, int thread_index) const {
166 return (index >= 0 && index < (int)_collectors.size() &&
167 _collectors[index]._is_level.get_bit(thread_index));
168}
169
170/**
171 * Returns the total number of collectors that are toplevel collectors. These
172 * are the collectors that are the children of "Frame", which is collector 0.
173 */
176 return _toplevel_collectors.size();
177}
178
179/**
180 * Returns the collector index of the nth toplevel collector. Use this
181 * function to iterate through the n toplevel collectors indicated by
182 * get_num_toplevel_collectors().
183 */
185get_toplevel_collector(int n) const {
186 nassertr(n >= 0 && n < (int)_toplevel_collectors.size(), 0);
187 return _toplevel_collectors[n];
188}
189
190/**
191 * Returns the total number of threads the Data knows about.
192 */
194get_num_threads() const {
195 return _threads.size();
196}
197
198/**
199 * Returns true if the indicated thread has been defined by the client
200 * already, false otherwise. It is possible for the client to start streaming
201 * data before all of the threads have been defined.
202 */
204has_thread(int index) const {
205 return (index >= 0 && index < (int)_threads.size() &&
206 !_threads[index]._name.empty());
207}
208
209/**
210 * Returns the name of the indicated thread.
211 */
213get_thread_name(int index) const {
214 if (!has_thread(index)) {
215 return "Unknown";
216 }
217 return _threads[index]._name;
218}
219
220/**
221 * Returns the data associated with the indicated thread. This will create a
222 * thread definition if it does not already exist.
223 */
225get_thread_data(int index) const {
226 ((PStatClientData *)this)->define_thread(index);
227 nassertr(index >= 0 && index < (int)_threads.size(), nullptr);
228 return _threads[index]._data;
229}
230
231/**
232 * Returns the number of Collectors between the indicated parent and the child
233 * Collector in the relationship graph. If child is the same as parent,
234 * returns zero. If child is an immediate child of parent, returns 1. If
235 * child is a grandchild of parent, returns 2, and so on. If child is not a
236 * descendant of parent at all, returns -1.
237 */
239get_child_distance(int parent, int child) const {
240 if (parent == child) {
241 return 0;
242 }
243 if (!has_collector(child) || child == 0) {
244 return -1;
245 }
246 int dist = get_child_distance(parent, get_collector_def(child)._parent_index);
247 if (dist == -1) {
248 return -1;
249 } else {
250 return dist + 1;
251 }
252}
253
254/**
255 * Adds a new collector definition to the dataset. Presumably this is
256 * information just arrived from the client.
257 *
258 * The pointer will become owned by the PStatClientData object and will be
259 * freed on destruction.
260 */
263 slot_collector(def->_index);
264 nassertv(def->_index >= 0 && def->_index < (int)_collectors.size());
265
266 if (_collectors[def->_index]._def != nullptr) {
267 // Free the old definition, if any.
268 delete _collectors[def->_index]._def;
269 }
270
271 _collectors[def->_index]._def = def;
272 update_toplevel_collectors();
273
274 // If we already had the _is_level flag set, it should be immediately
275 // applied to all ancestors.
276 const BitArray &is_level = _collectors[def->_index]._is_level;
277 int max_threads = is_level.get_num_bits();
278 for (int thread_index = 0; thread_index < max_threads; ++thread_index) {
279 if (is_level.get_bit(thread_index)) {
280 set_collector_has_level(def->_parent_index, thread_index, true);
281 }
282 }
283}
284
285/**
286 * Adds a new thread definition to the dataset. Presumably this is
287 * information just arrived from the client.
288 */
290define_thread(int thread_index, const string &name) {
291 // A sanity check on the index number.
292 nassertv(thread_index < 1000);
293
294 // Make sure we have enough slots allocated.
295 while ((int)_threads.size() <= thread_index) {
296 _threads.push_back(Thread());
297 }
298
299 if (!name.empty()) {
300 _threads[thread_index]._name = name;
301 }
302
303 if (_threads[thread_index]._data.is_null()) {
304 _threads[thread_index]._data = new PStatThreadData(this);
305 }
306}
307
308
309/**
310 * Makes room for and stores a new frame's worth of data associated with some
311 * particular thread (which may or may not have already been defined).
312 *
313 * The pointer will become owned by the PStatThreadData object and will be
314 * freed on destruction.
315 */
317record_new_frame(int thread_index, int frame_number,
318 PStatFrameData *frame_data) {
319 define_thread(thread_index);
320 nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
321 _threads[thread_index]._data->record_new_frame(frame_number, frame_data);
322}
323
324/**
325 * Makes sure there is an entry in the array for a collector with the given
326 * index number.
327 */
328void PStatClientData::
329slot_collector(int collector_index) {
330 // A sanity check on the index number.
331 nassertv(collector_index < 100000);
332
333 while ((int)_collectors.size() <= collector_index) {
334 Collector collector;
335 collector._def = nullptr;
336 _collectors.push_back(collector);
337 }
338}
339
340/**
341 * Rebuilds the list of toplevel collectors.
342 */
343void PStatClientData::
344update_toplevel_collectors() {
345 _toplevel_collectors.clear();
346
347 Collectors::const_iterator ci;
348 for (ci = _collectors.begin(); ci != _collectors.end(); ++ci) {
349 PStatCollectorDef *def = (*ci)._def;
350 if (def != nullptr && def->_parent_index == 0) {
351 _toplevel_collectors.push_back(def->_index);
352 }
353 }
354}
A dynamic array with an unlimited number of bits.
Definition bitArray.h:40
size_t get_num_bits() const
Returns the current number of possibly different bits in this array.
Definition bitArray.I:89
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
Definition bitArray.I:99
The data associated with a particular client, but not with any one particular frame or thread: the li...
int get_child_distance(int parent, int child) const
Returns the number of Collectors between the indicated parent and the child Collector in the relation...
std::string get_collector_fullname(int index) const
Returns the "full name" of the indicated collector.
bool has_thread(int index) const
Returns true if the indicated thread has been defined by the client already, false otherwise.
void record_new_frame(int thread_index, int frame_number, PStatFrameData *frame_data)
Makes room for and stores a new frame's worth of data associated with some particular thread (which m...
const PStatCollectorDef & get_collector_def(int index) const
Returns the nth collector definition.
int get_num_threads() const
Returns the total number of threads the Data knows about.
bool is_alive() const
Returns true if the data is actively getting filled by a connected client, or false if the client has...
const PStatThreadData * get_thread_data(int index) const
Returns the data associated with the indicated thread.
void close()
Closes the client connection if it is open.
std::string get_thread_name(int index) const
Returns the name of the indicated thread.
bool set_collector_has_level(int index, int thread_index, bool flag)
Indicates whether the given collector has level data (and consequently, whether it should appear on t...
int get_num_toplevel_collectors() const
Returns the total number of collectors that are toplevel collectors.
int get_num_collectors() const
Returns the total number of collectors the Data knows about.
void define_thread(int thread_index, const std::string &name=std::string())
Adds a new thread definition to the dataset.
bool has_collector(int index) const
Returns true if the indicated collector has been defined by the client already, false otherwise.
int get_toplevel_collector(int index) const
Returns the collector index of the nth toplevel collector.
bool get_collector_has_level(int index, int thread_index) const
Returns whether the given collector has level data (and consequently, whether it should appear on the...
void add_collector(PStatCollectorDef *def)
Adds a new collector definition to the dataset.
std::string get_collector_name(int index) const
Returns the name of the indicated collector.
Defines the details about the Collectors: the name, the suggested color, etc.
Contains the raw timing and level data for a single frame.
This is the class that does all the work for handling communications from a single Panda client.
Definition pStatReader.h:41
void close()
This will be called by the PStatClientData in response to its close() call.
A collection of FrameData structures for recently-received frames within a particular thread.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.