]>
Commit | Line | Data |
---|---|---|
76bdc726 | 1 | /* Copyright (C) 2021-2023 Free Software Foundation, Inc. |
bb368aad VM |
2 | Contributed by Oracle. |
3 | ||
4 | This file is part of GNU Binutils. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 3, or (at your option) | |
9 | any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, 51 Franklin Street - Fifth Floor, Boston, | |
19 | MA 02110-1301, USA. */ | |
20 | ||
21 | #include "config.h" | |
22 | #include <errno.h> | |
23 | #include <sys/types.h> // open, chmod | |
24 | #include <signal.h> | |
25 | #include <fcntl.h> // open | |
26 | #include <strings.h> | |
27 | #include <unistd.h> | |
28 | ||
29 | #include "util.h" | |
30 | #include "Histable.h" | |
31 | #include "DbeSession.h" | |
32 | #include "DbeView.h" | |
33 | #include "BaseMetric.h" | |
34 | #include "CallStack.h" | |
35 | #include "collctrl.h" | |
36 | #include "Command.h" | |
37 | #include "Dbe.h" | |
38 | #include "DbeApplication.h" | |
39 | #include "DefaultMap.h" | |
40 | #include "LoadObject.h" | |
41 | #include "Experiment.h" | |
42 | #include "IndexObject.h" | |
43 | #include "IOActivity.h" | |
44 | #include "PreviewExp.h" | |
45 | #include "Function.h" | |
46 | #include "Hist_data.h" | |
47 | #include "MetricList.h" | |
48 | #include "Module.h" | |
49 | #include "DataSpace.h" | |
50 | #include "MemorySpace.h" | |
51 | #include "DataObject.h" | |
52 | #include "MemObject.h" | |
53 | #include "Filter.h" | |
54 | #include "FilterSet.h" | |
55 | #include "FilterExp.h" | |
56 | #include "Sample.h" | |
57 | #include "Print.h" | |
58 | #include "StringBuilder.h" | |
59 | #include "dbe_types.h" | |
60 | #include "ExpGroup.h" | |
61 | #include "vec.h" | |
62 | #include "UserLabel.h" | |
63 | #include "DbeFile.h" | |
64 | #include "PathTree.h" | |
65 | ||
66 | // Data structures for managing the collector control info for Collection GUI | |
67 | static Coll_Ctrl *col_ctr = NULL; | |
68 | ||
69 | template<> VecType Vector<int>::type () | |
70 | { | |
71 | return VEC_INTEGER; | |
72 | } | |
73 | ||
74 | template<> VecType Vector<unsigned>::type () | |
75 | { | |
76 | return VEC_INTEGER; | |
77 | } | |
78 | ||
79 | template<> VecType Vector<char>::type () | |
80 | { | |
81 | return VEC_CHAR; | |
82 | } | |
83 | ||
84 | template<> VecType Vector<bool>::type () | |
85 | { | |
86 | return VEC_BOOL; | |
87 | } | |
88 | ||
89 | template<> VecType Vector<double>::type () | |
90 | { | |
91 | return VEC_DOUBLE; | |
92 | } | |
93 | ||
94 | template<> VecType Vector<long long>::type () | |
95 | { | |
96 | return VEC_LLONG; | |
97 | } | |
98 | ||
99 | template<> VecType Vector<uint64_t>::type () | |
100 | { | |
101 | return VEC_LLONG; | |
102 | } | |
103 | ||
104 | template<> VecType Vector<void*>::type () | |
105 | { | |
106 | return VEC_VOIDARR; | |
107 | } | |
108 | ||
109 | template<> VecType Vector<char*>::type () | |
110 | { | |
111 | return VEC_STRING; | |
112 | } | |
113 | ||
114 | template<> VecType Vector<Vector<int>*>::type () | |
115 | { | |
116 | return VEC_INTARR; | |
117 | } | |
118 | ||
119 | template<> VecType Vector<Vector<char*>*>::type () | |
120 | { | |
121 | return VEC_STRINGARR; | |
122 | } | |
123 | ||
124 | template<> VecType Vector<Vector<long long>*>::type () | |
125 | { | |
126 | return VEC_LLONGARR; | |
127 | } | |
128 | ||
129 | // gcc won't instantiate Vector<unsigned>::type() without it | |
130 | Vector<unsigned> __dummy_unsigned_vector; | |
131 | ||
132 | #define CASE_S(x) case x: return #x | |
133 | static const char * | |
134 | dsp_type_to_string (int t) | |
135 | { | |
136 | switch (t) | |
137 | { | |
138 | CASE_S (DSP_FUNCTION); | |
139 | CASE_S (DSP_LINE); | |
140 | CASE_S (DSP_PC); | |
141 | CASE_S (DSP_SOURCE); | |
142 | CASE_S (DSP_DISASM); | |
143 | CASE_S (DSP_SELF); | |
144 | CASE_S (DSP_CALLER); | |
145 | CASE_S (DSP_CALLEE); | |
146 | CASE_S (DSP_CALLTREE); | |
147 | CASE_S (DSP_TIMELINE); | |
148 | CASE_S (DSP_STATIS); | |
149 | CASE_S (DSP_EXP); | |
150 | CASE_S (DSP_LEAKLIST); | |
151 | CASE_S (DSP_MEMOBJ); | |
152 | CASE_S (DSP_DATAOBJ); | |
153 | CASE_S (DSP_DLAYOUT); | |
154 | CASE_S (DSP_SRC_FILE); | |
155 | CASE_S (DSP_IFREQ); | |
156 | CASE_S (DSP_RACES); | |
157 | CASE_S (DSP_INDXOBJ); | |
158 | CASE_S (DSP_DUALSOURCE); | |
159 | CASE_S (DSP_SOURCE_DISASM); | |
160 | CASE_S (DSP_DEADLOCKS); | |
161 | CASE_S (DSP_SOURCE_V2); | |
162 | CASE_S (DSP_DISASM_V2); | |
163 | CASE_S (DSP_IOACTIVITY); | |
164 | CASE_S (DSP_OVERVIEW); | |
165 | CASE_S (DSP_IOCALLSTACK); | |
166 | CASE_S (DSP_HEAPCALLSTACK); | |
167 | CASE_S (DSP_SAMPLE); | |
168 | default: | |
169 | break; | |
170 | } | |
171 | return NTXT ("ERROR"); | |
172 | } | |
173 | ||
174 | enum | |
175 | { | |
176 | COMPARE_BIT = 1 << 8, | |
177 | MTYPE_MASK = (1 << 8) - 1, | |
178 | GROUP_ID_SHIFT = 16 | |
179 | }; | |
180 | ||
181 | static DbeView * | |
182 | getDbeView (int dbevindex) | |
183 | { | |
184 | DbeView *dbev = dbeSession->getView (dbevindex); | |
185 | if (dbev == NULL) | |
186 | abort (); | |
187 | return dbev; | |
188 | } | |
189 | ||
190 | ||
191 | Vector<char*> * | |
192 | dbeGetInitMessages () | |
193 | { | |
194 | // If any comments from the .rc files, send them to the GUI | |
195 | Emsg *msg = theDbeApplication->fetch_comments (); | |
196 | int size = 0; | |
197 | while (msg != NULL) | |
198 | { | |
199 | size++; | |
200 | msg = msg->next; | |
201 | } | |
202 | ||
203 | // Initialize Java String array | |
204 | Vector<char*> *list = new Vector<char*>(size); | |
205 | msg = theDbeApplication->fetch_comments (); | |
206 | size = 0; | |
207 | int i = 0; | |
208 | while (msg != NULL) | |
209 | { | |
210 | char *str = msg->get_msg (); | |
211 | list->store (i, dbe_strdup (str)); | |
212 | i++; | |
213 | msg = msg->next; | |
214 | } | |
215 | ||
216 | // now delete the comments | |
217 | theDbeApplication->delete_comments (); | |
218 | return list; | |
219 | } | |
220 | ||
221 | Vector<char*> * | |
222 | dbeGetExpPreview (int /*dbevindex*/, char *exp_name) | |
223 | { | |
224 | PreviewExp *preview = new PreviewExp (); | |
225 | preview->experiment_open (exp_name); | |
226 | preview->open_epilogue (); | |
227 | ||
228 | // Initialize Java String array | |
229 | Vector<char*> *info = preview->preview_info (); | |
230 | int size = info->size (); | |
231 | Vector<char*> *list = new Vector<char*>(size); | |
232 | ||
233 | // Get experiment names | |
234 | for (int i = 0; i < size; i++) | |
235 | { | |
236 | char *str = info->fetch (i); | |
237 | if (str == NULL) | |
238 | str = GTXT ("N/A"); | |
239 | list->store (i, dbe_strdup (str)); | |
240 | } | |
241 | delete info; | |
242 | delete preview; | |
243 | return list; | |
244 | } | |
245 | ||
246 | char * | |
247 | dbeGetExpParams (int /*dbevindex*/, char *exp_name) | |
248 | { | |
249 | PreviewExp *preview = new PreviewExp (); | |
250 | preview->experiment_open (exp_name); | |
251 | ||
252 | // Initialize Java String array | |
253 | char *arg_list = dbe_strdup (preview->getArgList ()); | |
254 | delete preview; | |
255 | return arg_list; | |
256 | } | |
257 | ||
258 | /** | |
259 | * Gets File Attributes according to the specified format | |
260 | * Supported formats: | |
261 | * "/bin/ls -dl " - see 'man ls' for details | |
262 | * @param filename | |
263 | * @param format | |
264 | * @return char * attributes | |
265 | */ | |
266 | char * | |
267 | dbeGetFileAttributes (const char *filename, const char *format) | |
268 | { | |
269 | if (format != NULL) | |
270 | { | |
271 | if (!strcmp (format, NTXT ("/bin/ls -dl "))) | |
272 | { | |
273 | // A kind of "/bin/ls -dl " simulation | |
274 | struct stat64 sbuf; | |
275 | sbuf.st_mode = 0; | |
276 | dbe_stat (filename, &sbuf); | |
277 | if (S_IREAD & sbuf.st_mode) | |
278 | { // Readable | |
279 | if (S_ISDIR (sbuf.st_mode) != 0) | |
280 | return dbe_sprintf (NTXT ("%s %s\n"), NTXT ("drwxrwxr-x"), filename); | |
281 | else if (S_ISREG (sbuf.st_mode) != 0) | |
282 | return dbe_sprintf (NTXT ("%s %s\n"), NTXT ("-rwxrwxr-x"), filename); | |
283 | } | |
284 | } | |
285 | } | |
286 | return dbe_strdup (NTXT ("")); | |
287 | } | |
288 | ||
289 | /** | |
290 | * Gets list of files for specified directory according to the specified format | |
291 | * Supported formats: | |
292 | * "/bin/ls -a" - see 'man ls' for details | |
293 | * "/bin/ls -aF" - see 'man ls' for details | |
294 | * @param dirname | |
295 | * @param format | |
296 | * @return char * files | |
297 | */ | |
298 | char * | |
299 | dbeGetFiles (const char *dirname, const char *format) | |
300 | { | |
301 | if (format != NULL) | |
302 | return dbe_read_dir (dirname, format); | |
303 | return dbe_strdup (NTXT ("")); | |
304 | } | |
305 | ||
306 | /** | |
307 | * Creates the directory named by this full path name, including any | |
308 | * necessary but nonexistent parent directories. | |
309 | * @param dirname | |
310 | * @return result | |
311 | */ | |
312 | char * | |
313 | dbeCreateDirectories (const char *dirname) | |
314 | { | |
315 | if (dirname != NULL) | |
316 | { | |
317 | char *res = dbe_create_directories (dirname); | |
318 | if (res != NULL) | |
319 | return res; | |
320 | } | |
321 | return dbe_strdup (NTXT ("")); | |
322 | } | |
323 | ||
324 | /** | |
325 | * Deletes the file or the directory named by the specified path name. | |
326 | * If this pathname denotes a directory, then the directory must be empty in order to be deleted. | |
327 | * @param const char *pathname | |
328 | * @return int result | |
329 | */ | |
330 | char * | |
331 | dbeDeleteFile (const char *pathname) | |
332 | { | |
333 | // return unlink(pathname); | |
334 | if (pathname != NULL) | |
335 | { | |
336 | char *res = dbe_delete_file (pathname); | |
337 | if (res != NULL) | |
338 | return res; | |
339 | } | |
340 | return dbe_strdup (NTXT ("")); | |
341 | } | |
342 | ||
343 | /** | |
344 | * Reads the file named by the specified path name. | |
345 | * Temporary limitation: file should be "text only" and its size should be less than the 1 MB limit. | |
346 | * If the operation was successful, the contents is in the first element, and second element is NULL. | |
347 | * If the operation failed, then first element is NULL, and second element contains the error message. | |
348 | * @param const char *pathname | |
349 | * @return Vector<char*> *result | |
350 | */ | |
351 | Vector<char*> * | |
352 | dbeReadFile (const char *pathname) | |
353 | { | |
354 | Vector<char*> *result = new Vector<char*>(2); | |
355 | int limit = 1024 * 1024; // Temporary limit: 1 MB | |
356 | char * contents = (char *) malloc (limit); | |
357 | StringBuilder sb; | |
358 | if (NULL == contents) | |
359 | { | |
360 | sb.sprintf (NTXT ("\nError: Cannot allocate %d bytes\n"), limit); | |
361 | result->store (0, NULL); | |
362 | result->store (1, sb.toString ()); // failure | |
363 | return result; | |
364 | } | |
365 | int fd = open (pathname, O_RDONLY); | |
366 | if (fd >= 0) | |
367 | { | |
368 | int64_t bytes = read_from_file (fd, contents, limit); | |
369 | close (fd); | |
370 | if (bytes >= limit) | |
371 | { | |
372 | sb.sprintf (NTXT ("\nError: file size is greater than the limit (%d bytes)\n"), limit); | |
373 | result->store (0, NULL); | |
374 | result->store (1, sb.toString ()); // failure | |
375 | } | |
376 | else | |
377 | { | |
378 | contents[bytes] = '\0'; // add string terminator | |
379 | result->store (0, contents); | |
380 | result->store (1, NULL); // success | |
381 | } | |
382 | } | |
383 | else | |
384 | { | |
385 | sb.sprintf (NTXT ("\nError: Cannot open file %s\n"), pathname); | |
386 | result->store (0, NULL); | |
387 | result->store (1, sb.toString ()); // failure | |
388 | free (contents); | |
389 | } | |
390 | return result; | |
391 | } | |
392 | ||
393 | /** | |
394 | * Writes the file named by the specified path name. | |
395 | * Temporary limitation: file should be "text only" and its size should be less than the 1 MB limit. | |
396 | * If the operation failed, then -1 is returned. | |
397 | * @param const char *pathname | |
398 | * @return int result (written bytes) | |
399 | */ | |
400 | int | |
401 | dbeWriteFile (const char *pathname, const char *contents) | |
402 | { | |
403 | int result = -1; // error | |
404 | size_t len = 0; | |
405 | if (NULL != contents) | |
406 | len = strlen (contents); | |
407 | size_t limit = 1024 * 1024; // Temporary limit: 1 MB | |
408 | if (len > limit) return result; | |
409 | unlink (pathname); | |
410 | mode_t mode = S_IRUSR | S_IWUSR; | |
411 | int fd = open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode); | |
412 | if (fd >= 0) | |
413 | { // replace file contents | |
414 | chmod (pathname, /*S_IRUSR || S_IWUSR*/ 0600); // rw for owner only | |
415 | ssize_t bytes = 0; | |
416 | if (len > 0) | |
417 | bytes = write (fd, contents, len); | |
418 | close (fd); | |
419 | result = (int) bytes; | |
420 | } | |
421 | return result; | |
422 | } | |
423 | ||
424 | /** | |
425 | * Gets list of running processes according to the specified format | |
426 | * Supported formats: | |
427 | * "/bin/ps -ef" - see 'man ps' for details | |
428 | * @param format | |
429 | * @return char * processes | |
430 | */ | |
431 | char * | |
432 | dbeGetRunningProcesses (const char *format) | |
433 | { | |
434 | if (format != NULL) | |
435 | return dbe_get_processes (format); | |
436 | return dbe_strdup (NTXT ("")); | |
437 | } | |
438 | ||
439 | // | |
440 | // Open experiment | |
441 | // | |
442 | char * | |
443 | dbeOpenExperimentList (int /* dbevindex */, Vector<Vector<char*>*> *groups, | |
444 | bool sessionRestart) | |
445 | { | |
446 | if (sessionRestart) | |
447 | dbeSession->reset (); | |
448 | char *errstr; | |
449 | // Open experiments | |
450 | try | |
451 | { | |
452 | errstr = dbeSession->setExperimentsGroups (groups); | |
453 | } | |
454 | catch (ExperimentLoadCancelException *) | |
455 | { | |
456 | errstr = dbe_strdup (NTXT ("Experiment Load Cancelled")); | |
457 | } | |
458 | return errstr; | |
459 | } | |
460 | ||
461 | // | |
462 | // Drop experiments | |
463 | // | |
464 | char * | |
465 | dbeDropExperiment (int /* dbevindex */, Vector<int> *drop_index) | |
466 | { | |
467 | for (int i = drop_index->size () - 1; i >= 0; i--) | |
468 | { | |
469 | char *ret = dbeSession->drop_experiment (drop_index->fetch (i)); | |
470 | if (ret != NULL) | |
471 | return ret; | |
472 | } | |
473 | return NULL; | |
474 | } | |
475 | ||
476 | /** | |
477 | * Read .er.rc file from the specified location | |
478 | * @param path | |
479 | * @return | |
480 | */ | |
481 | char * | |
482 | dbeReadRCFile (int dbevindex, char* path) | |
483 | { | |
484 | DbeView *dbev = getDbeView (dbevindex); | |
485 | char *err_msg = dbev->get_settings ()->read_rc (path); | |
486 | return err_msg; | |
487 | } | |
488 | ||
489 | char * | |
490 | dbeSetExperimentsGroups (Vector<Vector<char*>*> *groups) | |
491 | { | |
492 | int cmp_mode = dbeSession->get_settings ()->get_compare_mode (); | |
493 | if (groups->size () < 2) | |
494 | cmp_mode = CMP_DISABLE; | |
495 | else if (cmp_mode == CMP_DISABLE) | |
496 | cmp_mode = CMP_ENABLE; | |
497 | for (int i = 0;; i++) | |
498 | { | |
499 | DbeView *dbev = dbeSession->getView (i); | |
500 | if (dbev == NULL) | |
501 | break; | |
502 | dbev->get_settings ()->set_compare_mode (cmp_mode); | |
503 | } | |
504 | char *err_msg = dbeSession->setExperimentsGroups (groups); | |
505 | ||
506 | // automatically load machine model if applicable | |
507 | dbeDetectLoadMachineModel (0); | |
508 | return err_msg; | |
509 | } | |
510 | ||
511 | Vector<Vector<char*>*> * | |
512 | dbeGetExperimensGroups () | |
513 | { | |
514 | Vector<Vector<char*>*> *grops = dbeSession->getExperimensGroups (); | |
515 | return grops; | |
516 | } | |
517 | ||
518 | Vector<int> * | |
519 | dbeGetFounderExpId (Vector<int> *expIds) | |
520 | { | |
521 | Vector<int> *ret = new Vector<int>(expIds->size ()); | |
522 | for (int i = 0; i < expIds->size (); i++) | |
523 | { | |
524 | int expId = expIds->fetch (i); | |
525 | Experiment *exp = dbeSession->get_exp (expId); | |
526 | if (exp != NULL) | |
527 | { | |
528 | int founderExpId = exp->getBaseFounder ()->getExpIdx (); | |
529 | ret->store (i, founderExpId); | |
530 | } | |
531 | else | |
532 | ret->store (i, -1); | |
533 | } | |
534 | return ret; | |
535 | } | |
536 | ||
537 | Vector<int> * | |
538 | dbeGetUserExpId (Vector<int> *expIds) | |
539 | { | |
540 | // returns "User Visible" ids used for EXPID filters and timeline processes | |
541 | Vector<int> *ret = new Vector<int>(expIds->size ()); | |
542 | for (int i = 0; i < expIds->size (); i++) | |
543 | { | |
544 | int expId = expIds->fetch (i); | |
545 | Experiment *exp = dbeSession->get_exp (expId); | |
546 | if (exp != NULL) | |
547 | { | |
548 | int userExpId = exp->getUserExpId (); | |
549 | ret->store (i, userExpId); | |
550 | } | |
551 | else | |
552 | ret->store (i, -1); | |
553 | } | |
554 | return ret; | |
555 | } | |
556 | ||
557 | // | |
558 | // Get experiment groupid | |
559 | // | |
560 | Vector<int> * | |
561 | dbeGetExpGroupId (Vector<int> *expIds) | |
562 | { | |
563 | Vector<int> *ret = new Vector<int>(expIds->size ()); | |
564 | for (int i = 0; i < expIds->size (); i++) | |
565 | { | |
566 | int expId = expIds->fetch (i); | |
567 | Experiment *exp = dbeSession->get_exp (expId); | |
568 | if (exp != NULL) | |
569 | { | |
570 | int gId = exp->groupId; | |
571 | ret->store (i, gId); | |
572 | } | |
573 | else | |
574 | ret->store (i, -1); | |
575 | } | |
576 | return ret; | |
577 | } | |
578 | ||
579 | Vector<char*> * | |
580 | dbeGetExpsProperty (const char *prop_name) | |
581 | { | |
582 | long nexps = dbeSession->nexps (); | |
583 | if (prop_name == NULL || nexps == 0) | |
584 | return NULL; | |
585 | Vector<char*> *list = new Vector<char*>(nexps); | |
586 | StringBuilder sb; | |
587 | int empty = 1; | |
588 | int prop = 99; | |
589 | if (strcasecmp (prop_name, NTXT ("ERRORS")) == 0) | |
590 | prop = 1; | |
591 | else if (strcasecmp (prop_name, NTXT ("WARNINGS")) == 0) | |
592 | prop = 2; | |
593 | if (prop < 3) | |
594 | { | |
595 | for (long i = 0; i < nexps; i++) | |
596 | { | |
597 | Experiment *exp = dbeSession->get_exp (i); | |
598 | char *nm = exp->get_expt_name (); | |
599 | sb.setLength (0); | |
600 | for (Emsg *emsg = (prop == 1) ? exp->fetch_errors () : exp->fetch_warnings (); | |
601 | emsg; emsg = emsg->next) | |
602 | sb.appendf (NTXT ("%s: %s\n"), STR (nm), STR (emsg->get_msg ())); | |
603 | char *s = NULL; | |
604 | if (sb.length () > 0) | |
605 | { | |
606 | s = sb.toString (); | |
607 | empty = 0; | |
608 | } | |
609 | list->append (s); | |
610 | } | |
611 | } | |
612 | if (empty) | |
613 | { | |
614 | delete list; | |
615 | list = NULL; | |
616 | } | |
617 | return list; | |
618 | } | |
619 | ||
620 | // | |
621 | // Get experiment names | |
622 | // | |
623 | Vector<char*> * | |
624 | dbeGetExpName (int /*dbevindex*/) | |
625 | { | |
626 | int size = dbeSession->nexps (); | |
627 | if (size == 0) | |
628 | return NULL; | |
629 | // Initialize Java String array | |
630 | Vector<char*> *list = new Vector<char*>(size); | |
631 | ||
632 | // Get experiment names | |
633 | for (int i = 0; i < size; i++) | |
634 | { | |
635 | Experiment *texp = dbeSession->get_exp (i); | |
636 | char *buf = dbe_sprintf (NTXT ("%s [%s]"), texp->get_expt_name (), | |
637 | texp->utargname != NULL ? texp->utargname : GTXT ("(unknown)")); | |
638 | list->store (i, buf); | |
639 | } | |
640 | return list; | |
641 | } | |
642 | ||
643 | // | |
644 | // Get experiment state | |
645 | // | |
646 | Vector<int> * | |
647 | dbeGetExpState (int /* dbevindex */) | |
648 | { | |
649 | int size = dbeSession->nexps (); | |
650 | if (size == 0) | |
651 | return NULL; | |
652 | // Initialize Java array | |
653 | Vector<int> *state = new Vector<int>(size); | |
654 | ||
655 | // Get experiment state | |
656 | for (int i = 0; i < size; i++) | |
657 | { | |
658 | Experiment *exp = dbeSession->get_exp (i); | |
659 | int set = EXP_SUCCESS; | |
660 | if (exp->get_status () == Experiment::FAILURE) | |
661 | set |= EXP_FAILURE; | |
662 | if (exp->get_status () == Experiment::INCOMPLETE) | |
663 | set |= EXP_INCOMPLETE; | |
664 | if (exp->broken) | |
665 | set |= EXP_BROKEN; | |
666 | if (exp->obsolete) | |
667 | set |= EXP_OBSOLETE; | |
668 | state->store (i, set); | |
669 | } | |
670 | return state; | |
671 | } | |
672 | ||
673 | // | |
674 | // Get enabled experiment indices | |
675 | // | |
676 | Vector<bool> * | |
677 | dbeGetExpEnable (int dbevindex) | |
678 | { | |
679 | DbeView *dbev = getDbeView (dbevindex); | |
680 | int size = dbeSession->nexps (); | |
681 | if (dbev == NULL || size == 0) | |
682 | return NULL; | |
683 | ||
684 | // Get enabled experiment | |
685 | Vector<bool> *enable = new Vector<bool>(size); | |
686 | for (int i = 0; i < size; i++) | |
687 | { | |
688 | bool val = dbev->get_exp_enable (i) && !dbeSession->get_exp (i)->broken; | |
689 | enable->store (i, val); | |
690 | } | |
691 | return enable; | |
692 | } | |
693 | ||
694 | // | |
695 | // Get enabled experiment indices | |
696 | // | |
697 | bool | |
698 | dbeSetExpEnable (int dbevindex, Vector<bool> *enable) | |
699 | { | |
700 | DbeView *dbev = getDbeView (dbevindex); | |
701 | bool ret = false; | |
702 | int size = dbeSession->nexps (); | |
703 | if (dbev == NULL || size == 0) | |
704 | return false; | |
705 | ||
706 | // set enable, as per input vector | |
707 | for (int i = 0; i < size; i++) | |
708 | if (!dbeSession->get_exp (i)->broken | |
709 | && dbev->get_exp_enable (i) != enable->fetch (i)) | |
710 | { | |
711 | dbev->set_exp_enable (i, enable->fetch (i)); | |
712 | ret = true; | |
713 | } | |
714 | return ret; | |
715 | } | |
716 | ||
717 | // | |
718 | // Get experiment info | |
719 | // | |
720 | Vector<char*> * | |
721 | dbeGetExpInfo (int dbevindex) | |
722 | { | |
723 | DbeView *dbev = dbeSession->getView (dbevindex); | |
724 | if (dbev == NULL) | |
725 | abort (); | |
726 | int size = dbeSession->nexps (); | |
727 | if (size == 0) | |
728 | return NULL; | |
729 | ||
730 | // Initialize Java String array | |
731 | Vector<char*> *list = new Vector<char*>(size * 2 + 1); | |
732 | ||
733 | // Get experiment names | |
734 | Vector<LoadObject*> *text_segments = dbeSession->get_text_segments (); | |
735 | char *msg = pr_load_objects (text_segments, NTXT ("")); | |
736 | delete text_segments; | |
737 | list->store (0, msg); | |
738 | int k = 1; | |
739 | for (int i = 0; i < size; i++) | |
740 | { | |
741 | Experiment *exp = dbeSession->get_exp (i); | |
742 | char *msg0 = pr_mesgs (exp->fetch_notes (), NTXT (""), NTXT ("")); | |
743 | char *msg1 = pr_mesgs (exp->fetch_errors (), GTXT ("No errors\n"), NTXT ("")); | |
744 | char *msg2 = pr_mesgs (exp->fetch_warnings (), GTXT ("No warnings\n"), NTXT ("")); | |
745 | char *msg3 = pr_mesgs (exp->fetch_comments (), NTXT (""), NTXT ("")); | |
746 | char *msg4 = pr_mesgs (exp->fetch_pprocq (), NTXT (""), NTXT ("")); | |
747 | msg = dbe_sprintf (NTXT ("%s%s%s%s"), msg1, msg2, msg3, msg4); | |
748 | list->store (k++, msg0); | |
749 | list->store (k++, msg); | |
750 | free (msg1); | |
751 | free (msg2); | |
752 | free (msg3); | |
753 | free (msg4); | |
754 | } | |
755 | return list; | |
756 | } | |
757 | ||
758 | bool | |
759 | dbeGetViewModeEnable () | |
760 | { | |
761 | return dbeSession->has_ompavail () || dbeSession->has_java (); | |
762 | } | |
763 | ||
764 | bool | |
765 | dbeGetJavaEnable () | |
766 | { | |
767 | return dbeSession->has_java (); | |
768 | } | |
769 | ||
770 | int | |
771 | dbeUpdateNotes (int dbevindex, int exp_id, int type, char* text, bool handle_file) | |
772 | { | |
773 | DbeView *dbev = dbeSession->getView (dbevindex); | |
774 | if (dbev == NULL) | |
775 | abort (); | |
776 | int size = dbeSession->nexps (); | |
777 | if (size == 0) | |
778 | return -1; | |
779 | Experiment *exp = dbeSession->get_exp (exp_id); | |
780 | return (type == 0) ? exp->save_notes (text, handle_file) : exp->delete_notes (handle_file); | |
781 | } | |
782 | ||
783 | // | |
784 | // Get load object names | |
785 | // | |
786 | Vector<char*> * | |
787 | dbeGetLoadObjectName (int /* dbevindex */) | |
788 | { | |
789 | Vector<LoadObject*> *lobjs = dbeSession->get_text_segments (); | |
790 | int size = lobjs->size (); | |
791 | ||
792 | // Initialize Java String array | |
793 | Vector<char*> *list = new Vector<char*>(size); | |
794 | ||
795 | // Get load object names | |
796 | LoadObject *lo; | |
797 | int index; | |
798 | Vec_loop (LoadObject*, lobjs, index, lo) | |
799 | { | |
800 | list->store (index, dbe_strdup (lo->get_name ())); | |
801 | } | |
802 | delete lobjs; | |
803 | return list; | |
804 | } | |
805 | ||
806 | // XXX Will use later when order has to be passed too, | |
807 | // Get complete List of tabs | |
808 | // | |
809 | Vector<void*> * | |
810 | dbeGetTabList (int /* dbevindex */) | |
811 | { | |
812 | //DbeView *dbev = getDbeView (dbevindex); | |
813 | //Vector<void*> *tabs = dbeSession->get_TabList(); | |
814 | //return tabs; | |
815 | return NULL; | |
816 | } | |
817 | ||
818 | // | |
819 | // Returns list of available tabs | |
820 | // | |
821 | Vector<void*> * | |
822 | dbeGetTabListInfo (int dbevindex) | |
823 | { | |
824 | int index; | |
825 | DispTab *dsptab; | |
826 | DbeView *dbev = getDbeView (dbevindex); | |
827 | ||
828 | // make sure the tabs are initialized properly | |
829 | dbev->get_settings ()->proc_tabs (theDbeApplication->rdtMode); | |
830 | Vector<DispTab*> *tabs = dbev->get_TabList (); | |
831 | ||
832 | // Get number of available tabs | |
833 | int size = 0; | |
834 | Vec_loop (DispTab*, tabs, index, dsptab) | |
835 | { | |
836 | if (!dsptab->available) | |
837 | continue; | |
838 | size++; | |
839 | } | |
840 | Vector<void*> *data = new Vector<void*>(2); | |
841 | Vector<int> *typelist = new Vector<int>(size); | |
842 | Vector<char*> *cmdlist = new Vector<char*>(size); | |
843 | Vector<int> *ordlist = new Vector<int>(size); | |
844 | ||
845 | // Build list of avaliable tabs | |
846 | int i = 0; | |
847 | ||
848 | Vec_loop (DispTab*, tabs, index, dsptab) | |
849 | { | |
850 | if (!dsptab->available) | |
851 | continue; | |
852 | typelist->store (i, dsptab->type); | |
853 | cmdlist->store (i, dbe_strdup (Command::get_cmd_str (dsptab->cmdtoken))); | |
854 | ordlist->store (i, dsptab->order); | |
855 | i++; | |
856 | } | |
857 | data->store (0, typelist); | |
858 | data->store (1, cmdlist); | |
859 | data->store (2, ordlist); | |
860 | return data; | |
861 | } | |
862 | ||
863 | // Return visibility state for all available tabs | |
864 | // | |
865 | Vector<bool> * | |
866 | dbeGetTabSelectionState (int dbevindex) | |
867 | { | |
868 | int index; | |
869 | DispTab *dsptab; | |
870 | DbeView *dbev = getDbeView (dbevindex); | |
871 | Vector<DispTab*> *tabs = dbev->get_TabList (); | |
872 | ||
873 | // Get number of available tabs | |
874 | int size = 0; | |
875 | Vec_loop (DispTab*, tabs, index, dsptab) | |
876 | { | |
877 | if (!dsptab->available) | |
878 | continue; | |
879 | size++; | |
880 | } | |
881 | Vector<bool> *states = new Vector<bool>(size); | |
882 | ||
883 | // Get visibility bit for all available tabs | |
884 | int i = 0; | |
885 | Vec_loop (DispTab*, tabs, index, dsptab) | |
886 | { | |
887 | if (!dsptab->available) | |
888 | continue; | |
889 | states->store (i++, dsptab->visible); | |
890 | } | |
891 | return states; | |
892 | } | |
893 | ||
894 | // Set visibility bit for a tab | |
895 | void | |
896 | dbeSetTabSelectionState (int dbevindex, Vector<bool> *selected) | |
897 | { | |
898 | int index; | |
899 | DispTab *dsptab; | |
900 | DbeView *dbev = getDbeView (dbevindex); | |
901 | Vector<DispTab*> *tabs = dbev->get_TabList (); | |
902 | int i = 0; | |
903 | Vec_loop (DispTab*, tabs, index, dsptab) | |
904 | { | |
905 | if (!dsptab->available) | |
906 | continue; | |
907 | dsptab->visible = selected->fetch (i++); | |
908 | } | |
909 | } | |
910 | ||
911 | // Return visibility state for all available MemObj tabs | |
912 | Vector<bool> * | |
913 | dbeGetMemTabSelectionState (int dbevindex) | |
914 | { | |
915 | int index; | |
916 | bool dsptab; | |
917 | DbeView *dbev = getDbeView (dbevindex); | |
918 | Vector<bool> *memtabs = dbev->get_MemTabState (); | |
919 | ||
920 | // set the output vector | |
921 | int size = memtabs->size (); | |
922 | Vector<bool> *states = new Vector<bool>(size); | |
923 | ||
924 | // Get visibility bit for all available tabs | |
925 | int i = 0; | |
926 | Vec_loop (bool, memtabs, index, dsptab) | |
927 | { | |
928 | states->store (i++, dsptab); | |
929 | } | |
930 | return states; | |
931 | } | |
932 | ||
933 | // Set visibility bit for a memory tab | |
934 | // | |
935 | void | |
936 | dbeSetMemTabSelectionState (int dbevindex, Vector<bool> *selected) | |
937 | { | |
938 | DbeView *dbev = dbeSession->getView (dbevindex); | |
939 | if (dbev == NULL) | |
940 | abort (); | |
941 | dbev->set_MemTabState (selected); | |
942 | } | |
943 | ||
944 | // Return visibility state for all available index tabs | |
945 | Vector<bool> * | |
946 | dbeGetIndxTabSelectionState (int dbevindex) | |
947 | { | |
948 | int index; | |
949 | bool dsptab; | |
950 | DbeView *dbev = dbeSession->getView (dbevindex); | |
951 | if (dbev == NULL) | |
952 | abort (); | |
953 | Vector<bool> *indxtabs = dbev->get_IndxTabState (); | |
954 | ||
955 | // set the output vector | |
956 | int size = indxtabs->size (); | |
957 | Vector<bool> *states = new Vector<bool>(size); | |
958 | ||
959 | // Get visibility bit for all available tabs | |
960 | int i = 0; | |
961 | Vec_loop (bool, indxtabs, index, dsptab) | |
962 | { | |
963 | states->store (i++, dsptab); | |
964 | } | |
965 | return states; | |
966 | } | |
967 | ||
968 | // Set visibility bit for a index tab | |
969 | void | |
970 | dbeSetIndxTabSelectionState (int dbevindex, Vector<bool> *selected) | |
971 | { | |
972 | DbeView *dbev = dbeSession->getView (dbevindex); | |
973 | if (dbev == NULL) | |
974 | abort (); | |
975 | dbev->set_IndxTabState (selected); | |
976 | } | |
977 | ||
978 | // | |
979 | // Get search path | |
980 | // | |
981 | Vector<char*> * | |
982 | dbeGetSearchPath (int /*dbevindex*/) | |
983 | { | |
984 | Vector<char*> *path = dbeSession->get_search_path (); | |
985 | int size = path->size (); | |
986 | Vector<char*> *list = new Vector<char*>(size); | |
987 | int index; | |
988 | char *name; | |
989 | Vec_loop (char*, path, index, name) | |
990 | { | |
991 | list->store (index, dbe_strdup (name)); | |
992 | } | |
993 | return list; | |
994 | } | |
995 | ||
996 | // | |
997 | // Set search path | |
998 | // | |
999 | void | |
1000 | dbeSetSearchPath (int /*dbevindex*/, Vector<char*> *path) | |
1001 | { | |
1002 | dbeSession->set_search_path (path, true); | |
1003 | return; | |
1004 | } | |
1005 | ||
1006 | // | |
1007 | // Get pathmaps | |
1008 | // | |
1009 | Vector<void*> * | |
1010 | dbeGetPathmaps (int /*dbevindex*/) | |
1011 | { | |
1012 | int index; | |
1013 | pathmap_t *pthmap; | |
1014 | Vector<pathmap_t*> *path = dbeSession->get_pathmaps (); | |
1015 | int size = path->size (); | |
1016 | Vector<void*> *data = new Vector<void*>(2); | |
1017 | Vector<char*> *oldlist = new Vector<char*>(size); | |
1018 | Vector<char*> *newlist = new Vector<char*>(size); | |
1019 | ||
1020 | int i = 0; | |
1021 | Vec_loop (pathmap_t*, path, index, pthmap) | |
1022 | { | |
1023 | oldlist->store (i, dbe_strdup (pthmap->old_prefix)); | |
1024 | newlist->store (i, dbe_strdup (pthmap->new_prefix)); | |
1025 | i++; | |
1026 | } | |
1027 | data->store (0, oldlist); | |
1028 | data->store (1, newlist); | |
1029 | return data; | |
1030 | } // dbeGetPathmaps | |
1031 | ||
1032 | char * | |
1033 | dbeSetPathmaps (Vector<char*> *from, Vector<char*> *to) | |
1034 | { | |
1035 | if (from == NULL || to == NULL || from->size () != to->size ()) | |
1036 | return dbe_strdup ("dbeSetPathmaps: size of 'from' does not match for size of 'to'\n"); | |
1037 | Vector<pathmap_t*> *newPath = new Vector<pathmap_t*>(from->size ()); | |
1038 | for (int i = 0, sz = from->size (); i < sz; i++) | |
1039 | { | |
1040 | char *err = Settings::add_pathmap (newPath, from->get (i), to->get (i)); | |
1041 | if (err) | |
1042 | { | |
1043 | newPath->destroy (); | |
1044 | delete newPath; | |
1045 | return err; | |
1046 | } | |
1047 | } | |
1048 | dbeSession->set_pathmaps (newPath); | |
1049 | return NULL; | |
1050 | } | |
1051 | ||
1052 | // | |
1053 | // Add pathmap | |
1054 | char * | |
1055 | dbeAddPathmap (int /* dbevindex */, char *from, char *to) | |
1056 | { | |
1057 | Vector<pathmap_t*> *pmp = dbeSession->get_pathmaps (); | |
1058 | char *err = Settings::add_pathmap (pmp, from, to); | |
1059 | return err; | |
1060 | } | |
1061 | ||
1062 | // | |
1063 | // Get error/warning string of data | |
1064 | char * | |
1065 | dbeGetMsg (int dbevindex, int type) | |
1066 | { | |
1067 | DbeView *dbev = dbeSession->getView (dbevindex); | |
1068 | if (dbev == NULL) | |
1069 | abort (); | |
1070 | char *msgstr = NULL; | |
1071 | if (type == ERROR_MSG) | |
1072 | msgstr = dbev->get_error_msg (); | |
1073 | else if (type == WARNING_MSG) | |
1074 | msgstr = dbev->get_warning_msg (); | |
1075 | else if (type == PSTAT_MSG) | |
1076 | msgstr = dbev->get_processor_msg (PSTAT_MSG); | |
1077 | else if (type == PWARN_MSG) | |
1078 | msgstr = dbev->get_processor_msg (PWARN_MSG); | |
1079 | return msgstr ? dbe_strdup (msgstr) : NULL; | |
1080 | } | |
1081 | ||
1082 | // Create a DbeView, given new index, and index of view to clone | |
1083 | int | |
1084 | dbeInitView (int id, int cloneid) | |
1085 | { | |
1086 | return dbeSession->createView (id, cloneid); | |
1087 | } | |
1088 | ||
1089 | ||
1090 | // Delete a DbeView | |
1091 | void | |
1092 | dbeDeleteView (int dbevindex) | |
1093 | { | |
1094 | dbeSession->dropView (dbevindex); | |
1095 | return; | |
1096 | } // dbeDeleteView | |
1097 | ||
1098 | MetricList * | |
1099 | dbeGetMetricListV2 (int dbevindex, MetricType mtype, | |
1100 | Vector<int> *type, Vector<int> *subtype, Vector<bool> *sort, | |
1101 | Vector<int> *vis, Vector<char*> *cmd, | |
1102 | Vector<char*> *expr_spec, Vector<char*> *legends) | |
1103 | { | |
1104 | DbeView *dbev = dbeSession->getView (dbevindex); | |
1105 | MetricList *mlist = new MetricList (mtype); | |
1106 | for (int i = 0, msize = type->size (); i < msize; i++) | |
1107 | { | |
1108 | BaseMetric *bm = dbev->register_metric_expr ((BaseMetric::Type) type->fetch (i), | |
1109 | cmd->fetch (i), | |
1110 | expr_spec->fetch (i)); | |
1111 | Metric *m = new Metric (bm, (Metric::SubType) subtype->fetch (i)); | |
1112 | m->set_raw_visbits (vis->fetch (i)); | |
1113 | if (m->legend == NULL) | |
1114 | m->legend = dbe_strdup (legends->fetch (i)); | |
1115 | mlist->append (m); | |
1116 | if (sort->fetch (i)) | |
1117 | { | |
1118 | mlist->set_sort_ref_index (i); | |
1119 | } | |
1120 | } | |
1121 | return mlist; | |
1122 | } | |
1123 | ||
1124 | static Vector<void*> * | |
1125 | dbeGetMetricList (MetricList *mlist) | |
1126 | { | |
1127 | int clock_val = dbeSession->get_clock (-1); | |
1128 | Vector<Metric*> *items = mlist->get_items (); | |
1129 | int size = items->size (); | |
1130 | ||
1131 | Vector<int> *type = new Vector<int>(size); | |
1132 | Vector<int> *subtype = new Vector<int>(size); | |
1133 | Vector<int> *clock = new Vector<int>(size); | |
1134 | Vector<int> *flavors = new Vector<int>(size); | |
1135 | Vector<int> *vis = new Vector<int>(size); | |
1136 | Vector<bool> *sorted = new Vector<bool>(size); | |
1137 | Vector<int> *value_styles = new Vector<int>(size); | |
1138 | Vector<char*> *aux = new Vector<char*>(size); | |
1139 | Vector<char*> *name = new Vector<char*>(size); | |
1140 | Vector<char*> *abbr = new Vector<char*>(size); | |
1141 | Vector<char*> *comd = new Vector<char*>(size); | |
1142 | Vector<char*> *unit = new Vector<char*>(size); | |
1143 | Vector<char*> *user_name = new Vector<char*>(size); | |
1144 | Vector<char*> *expr_spec = new Vector<char*>(size); | |
1145 | Vector<char*> *legend = new Vector<char*>(size); | |
1146 | Vector<int> *valtype = new Vector<int>(size); | |
1147 | Vector<char*> *data_type_name = new Vector<char*>(size); | |
1148 | Vector<char*> *data_type_uname = new Vector<char*>(size); | |
1149 | Vector<char*> *short_desc = new Vector<char*>(size); | |
1150 | ||
1151 | int sort_index = mlist->get_sort_ref_index (); | |
1152 | // Fill metric elements | |
1153 | for (int i = 0; i < size; i++) | |
1154 | { | |
1155 | Metric *m = items->fetch (i); | |
1156 | type->append (m->get_type ()); | |
1157 | subtype->append (m->get_subtype ()); | |
1158 | flavors->append (m->get_flavors ()); | |
1159 | abbr->append (dbe_strdup (m->get_abbr ())); | |
1160 | char *s = m->get_abbr_unit (); | |
1161 | if ((m->get_visbits () & VAL_RATIO) != 0) | |
1162 | s = NULL; | |
1163 | unit->append (dbe_strdup (s ? s : NTXT (""))); | |
1164 | value_styles->append (m->get_value_styles ()); | |
1165 | vis->append (m->get_visbits ()); | |
1166 | sorted->append (i == sort_index); | |
1167 | clock->append (m->get_type () == Metric::HWCNTR ? clock_val | |
1168 | : m->get_clock_unit ()); | |
1169 | aux->append (dbe_strdup (m->get_aux ())); | |
1170 | name->append (dbe_strdup (m->get_name ())); | |
1171 | comd->append (dbe_strdup (m->get_cmd ())); | |
1172 | user_name->append (dbe_strdup (m->get_username ())); | |
1173 | expr_spec->append (dbe_strdup (m->get_expr_spec ())); | |
1174 | legend->append (dbe_strdup (m->legend)); | |
1175 | valtype->append (m->get_vtype2 ()); | |
1176 | ||
1177 | char* _data_type_name = NULL; | |
1178 | char* _data_type_uname = NULL; | |
1179 | int data_type = m->get_packet_type (); | |
1180 | if (data_type >= 0 && data_type < DATA_LAST) | |
1181 | { | |
1182 | _data_type_name = dbe_strdup (get_prof_data_type_name (data_type)); | |
1183 | _data_type_uname = dbe_strdup (get_prof_data_type_uname (data_type)); | |
1184 | } | |
1185 | data_type_name->append (_data_type_name); | |
1186 | data_type_uname->append (_data_type_uname); | |
1187 | ||
1188 | char* _short_desc = NULL; | |
1189 | if (m->get_type () == Metric::HWCNTR) | |
1190 | { | |
1191 | Hwcentry * hwctr = m->get_hw_ctr (); | |
1192 | if (hwctr) | |
1193 | _short_desc = dbe_strdup (hwctr->short_desc); | |
1194 | } | |
1195 | short_desc->append (_short_desc); | |
1196 | } | |
1197 | ||
1198 | // Set Java array | |
1199 | Vector<void*> *data = new Vector<void*>(16); | |
1200 | data->append (type); | |
1201 | data->append (subtype); | |
1202 | data->append (clock); | |
1203 | data->append (flavors); | |
1204 | data->append (value_styles); | |
1205 | data->append (user_name); | |
1206 | data->append (expr_spec); | |
1207 | data->append (aux); | |
1208 | data->append (name); | |
1209 | data->append (abbr); | |
1210 | data->append (comd); | |
1211 | data->append (unit); | |
1212 | data->append (vis); | |
1213 | data->append (sorted); | |
1214 | data->append (legend); | |
1215 | data->append (valtype); | |
1216 | data->append (data_type_name); | |
1217 | data->append (data_type_uname); | |
1218 | data->append (short_desc); | |
1219 | return data; | |
1220 | } | |
1221 | ||
1222 | Vector<void*> * | |
1223 | dbeGetRefMetricsV2 () | |
1224 | { | |
1225 | MetricList *mlist = new MetricList (MET_NORMAL); | |
1226 | Vector<BaseMetric*> *base_metrics = dbeSession->get_base_reg_metrics (); | |
1227 | for (long i = 0, sz = base_metrics->size (); i < sz; i++) | |
1228 | { | |
1229 | BaseMetric *bm = base_metrics->fetch (i); | |
1230 | Metric *m; | |
1231 | if (bm->get_flavors () & Metric::EXCLUSIVE) | |
1232 | { | |
1233 | m = new Metric (bm, Metric::EXCLUSIVE); | |
1234 | m->enable_all_visbits (); | |
1235 | mlist->append (m); | |
1236 | } | |
1237 | else if (bm->get_flavors () & BaseMetric::STATIC) | |
1238 | { | |
1239 | m = new Metric (bm, BaseMetric::STATIC); | |
1240 | m->enable_all_visbits (); | |
1241 | mlist->append (m); | |
1242 | } | |
1243 | } | |
1244 | Vector<void*> *data = dbeGetMetricList (mlist); | |
1245 | delete mlist; | |
1246 | return data; | |
1247 | } | |
1248 | ||
1249 | Vector<void*> * | |
1250 | dbeGetCurMetricsV2 (int dbevindex, MetricType mtype) | |
1251 | { | |
1252 | DbeView *dbev = dbeSession->getView (dbevindex); | |
1253 | MetricList *mlist = dbev->get_metric_list (mtype); | |
1254 | Vector<void*> *data = dbeGetMetricList (mlist); | |
1255 | return data; | |
1256 | } | |
1257 | ||
1258 | // YXXX we should refactor Metrics/BaseMetrics so that it no longer uses VAL_VALUE to enable time. | |
1259 | static int | |
1260 | convert_visbits_to_gui_checkbox_bits (BaseMetric *bm, const int visbits) | |
1261 | { | |
1262 | // The purpose of this function is to handle the following case: | |
1263 | // When bm->get_value_styles() supports VAL_TIMEVAL but not VAL_VALUE | |
1264 | // Metric and BaseMetric use (visbits&VAL_VALUE) to enable time. | |
1265 | // However, the Overview expects the VAL_TIMEVAL bit to enable time. | |
1266 | // Inputs: visbits as returned by BaseMetric->get_default_visbits(); | |
1267 | // Returns: valuebits, as used for checks in GUI checkboxes | |
1268 | int valuebits = visbits; | |
1269 | const int value_styles = bm->get_value_styles (); | |
1270 | if ((value_styles & VAL_TIMEVAL) && // supports time | |
1271 | !(value_styles & VAL_VALUE)) | |
1272 | { // but not value | |
1273 | unsigned mask = ~(VAL_VALUE | VAL_TIMEVAL); | |
1274 | valuebits = (unsigned) valuebits & mask; // clear bits | |
1275 | if (visbits & VAL_VALUE) | |
1276 | valuebits |= VAL_TIMEVAL; // set VAL_TIMEVAL | |
1277 | if (visbits & VAL_TIMEVAL) | |
1278 | valuebits |= VAL_TIMEVAL; // weird, this should never happen. | |
1279 | } | |
1280 | return valuebits; | |
1281 | } | |
1282 | ||
1283 | static Vector<void*> * | |
1284 | dbeGetMetricTreeNode (BaseMetricTreeNode* curr, MetricList *mlist, | |
1285 | bool include_unregistered, bool has_clock_profiling_data) | |
1286 | { | |
1287 | Vector<void*> *data = new Vector<void*>(2); | |
1288 | ||
1289 | // ----- fields | |
1290 | Vector<void*> *fields = new Vector<void*>(); | |
1291 | Vector<char*> *name = new Vector<char*>(1); | |
1292 | Vector<char*> *username = new Vector<char*>(1); | |
1293 | Vector<char*> *description = new Vector<char*>(1); | |
1294 | Vector<int> * flavors = new Vector<int>(1); | |
1295 | Vector<int> * vtype = new Vector<int>(1); | |
1296 | Vector<int> * vstyles_capable = new Vector<int>(1); | |
1297 | ||
1298 | // Specifies which default styles should be enabled when a metric is enabled. | |
1299 | // Also, specifies if metric should start enabled | |
1300 | Vector<int> *vstyles_e_defaults = new Vector<int>(1); | |
1301 | Vector<int> *vstyles_i_defaults = new Vector<int>(1); | |
1302 | Vector<bool> *registered = new Vector<bool>(1); | |
1303 | Vector<bool> *aggregation = new Vector<bool>(1); | |
1304 | Vector<bool> *has_value = new Vector<bool>(1); | |
1305 | Vector<char*> *unit = new Vector<char*>(1); | |
1306 | Vector<char*> *unit_uname = new Vector<char*>(1); | |
1307 | ||
1308 | char *_name = NULL; | |
1309 | char *_username = NULL; | |
1310 | char *_description = dbe_strdup (curr->get_description ()); | |
1311 | ||
1312 | // BaseMetric fields | |
1313 | int _flavors = 0; // SubType bitmask: (e.g. EXCLUSIVE) | |
1314 | int _vtype = 0; // ValueTag: e.g. VT_INT, VT_FLOAT, ... | |
1315 | int _vstyles_capable = 0; // ValueType bitmask, e.g. VAL_TIMEVAL | |
1316 | int _vstyles_e_default_values = 0; // default visibility settings, exclusive/static | |
1317 | int _vstyles_i_derault_values = 0; // default visibility settings, inclusive | |
1318 | bool _registered = curr->is_registered () | |
1319 | || curr->get_num_registered_descendents () > 0; | |
1320 | bool _aggregation = curr->is_composite_metric () | |
1321 | && curr->get_num_registered_descendents () > 0; | |
1322 | bool _has_value = false; //not used yet; for nodes that don't have metrics | |
1323 | char *_unit = NULL; | |
1324 | char *_unit_uname = NULL; | |
1325 | ||
1326 | BaseMetric *bm = curr->get_BaseMetric (); | |
1327 | if (bm) | |
1328 | { | |
1329 | _name = dbe_strdup (bm->get_cmd ()); | |
1330 | _username = dbe_strdup (bm->get_username ()); | |
1331 | if (!include_unregistered && !curr->is_registered ()) | |
1332 | abort (); | |
1333 | _flavors = bm->get_flavors (); | |
1334 | _vtype = bm->get_vtype (); | |
1335 | _vstyles_capable = bm->get_value_styles (); | |
1336 | int e_visbits = bm->get_default_visbits (BaseMetric::EXCLUSIVE); | |
1337 | int i_visbits = bm->get_default_visbits (BaseMetric::INCLUSIVE); | |
1338 | _vstyles_e_default_values = convert_visbits_to_gui_checkbox_bits (bm, e_visbits); | |
1339 | _vstyles_i_derault_values = convert_visbits_to_gui_checkbox_bits (bm, i_visbits); | |
1340 | // not all metrics shown in er_print cmd line should be selected in the GUI at startup: | |
1341 | if (has_clock_profiling_data && bm->get_hw_ctr ()) | |
1342 | { | |
1343 | bool hide = true; // by default, hide HWCs | |
1344 | if (dbe_strcmp (bm->get_hw_ctr ()->name, NTXT ("c_stalls")) == 0 || | |
1345 | dbe_strcmp (bm->get_hw_ctr ()->name, NTXT ("K_c_stalls")) == 0) | |
1346 | { | |
1347 | bool is_time = (bm->get_value_styles () & VAL_TIMEVAL) != 0; | |
1348 | if (is_time) | |
1349 | // By default, show time variant of c_stalls | |
1350 | hide = false; | |
1351 | } | |
1352 | if (hide) | |
1353 | { | |
1354 | _vstyles_e_default_values |= VAL_HIDE_ALL; | |
1355 | _vstyles_i_derault_values |= VAL_HIDE_ALL; | |
1356 | } | |
1357 | } | |
1358 | } | |
1359 | else | |
1360 | { | |
1361 | // not a base metric | |
1362 | _name = dbe_strdup (curr->get_name ()); | |
1363 | _username = dbe_strdup (curr->get_user_name ()); | |
1364 | if (curr->get_unit ()) | |
1365 | { // represents a value | |
1366 | _has_value = true; | |
1367 | _unit = dbe_strdup (curr->get_unit ()); | |
1368 | _unit_uname = dbe_strdup (curr->get_unit_uname ()); | |
1369 | } | |
1370 | } | |
1371 | name->append (_name); // unique id string (dmetrics cmd) | |
1372 | username->append (_username); // user-visible name | |
1373 | description->append (_description); | |
1374 | flavors->append (_flavors); // SubType bitmask: (e.g. EXCLUSIVE) | |
1375 | vtype->append (_vtype); // ValueTag: e.g. VT_INT, VT_FLOAT, ... | |
1376 | vstyles_capable->append (_vstyles_capable); // ValueType bitmask, e.g. VAL_TIMEVAL | |
1377 | vstyles_e_defaults->append (_vstyles_e_default_values); | |
1378 | vstyles_i_defaults->append (_vstyles_i_derault_values); | |
1379 | registered->append (_registered); // is a "live" metric | |
1380 | aggregation->append (_aggregation); // value derived from children nodes | |
1381 | has_value->append (_has_value); // value generated from other source | |
1382 | unit->append (_unit); // See BaseMetric.h, e.g. UNIT_SECONDS | |
1383 | unit_uname->append (_unit_uname); //See BaseMetric.h, | |
1384 | ||
1385 | fields->append (name); | |
1386 | fields->append (username); | |
1387 | fields->append (description); | |
1388 | fields->append (flavors); | |
1389 | fields->append (vtype); | |
1390 | fields->append (vstyles_capable); | |
1391 | fields->append (vstyles_e_defaults); | |
1392 | fields->append (vstyles_i_defaults); | |
1393 | fields->append (registered); | |
1394 | fields->append (aggregation); | |
1395 | fields->append (has_value); | |
1396 | fields->append (unit); | |
1397 | fields->append (unit_uname); | |
1398 | data->append (fields); | |
1399 | ||
1400 | // ----- children | |
1401 | Vector<BaseMetricTreeNode*> *children = curr->get_children (); | |
1402 | int num_children = children->size (); | |
1403 | Vector<void*> *children_list = new Vector<void*>(num_children); | |
1404 | BaseMetricTreeNode *child_node; | |
1405 | int index; | |
1406 | ||
1407 | Vec_loop (BaseMetricTreeNode*, children, index, child_node) | |
1408 | { | |
1409 | if (include_unregistered /* fetch everything */ | |
1410 | || child_node->is_registered () | |
1411 | || child_node->get_num_registered_descendents () > 0) | |
1412 | { | |
1413 | //Special case for metrics that aren't registered | |
1414 | // but have registered children | |
1415 | // Linux example: Total Time is unregistered, CPU Time is registered | |
1416 | if (!include_unregistered && /* not fetching everything */ | |
1417 | !child_node->is_registered () && | |
1418 | (child_node->get_BaseMetric () != NULL || | |
1419 | child_node->is_composite_metric ())) | |
1420 | { | |
1421 | Vector<BaseMetricTreeNode*> *registered_descendents = | |
1422 | new Vector<BaseMetricTreeNode*>(); | |
1423 | child_node->get_nearest_registered_descendents (registered_descendents); | |
1424 | int idx2; | |
1425 | BaseMetricTreeNode*desc_node; | |
1426 | Vec_loop (BaseMetricTreeNode*, registered_descendents, idx2, desc_node) | |
1427 | { | |
1428 | Vector<void*> *desc_data; | |
1429 | desc_data = dbeGetMetricTreeNode (desc_node, mlist, | |
1430 | include_unregistered, has_clock_profiling_data); | |
1431 | children_list->append (desc_data); | |
1432 | } | |
1433 | delete registered_descendents; | |
1434 | continue; | |
1435 | } | |
1436 | Vector<void*> *child_data; | |
1437 | child_data = dbeGetMetricTreeNode (child_node, mlist, | |
1438 | include_unregistered, has_clock_profiling_data); | |
1439 | children_list->append (child_data); | |
1440 | } | |
1441 | } | |
1442 | data->append (children_list); | |
1443 | return data; | |
1444 | } | |
1445 | ||
1446 | Vector<void*> * | |
1447 | dbeGetRefMetricTree (int dbevindex, bool include_unregistered) | |
1448 | { | |
1449 | DbeView *dbev = dbeSession->getView (dbevindex); | |
1450 | MetricList *mlist = dbev->get_metric_list (MET_NORMAL); | |
1451 | bool has_clock_profiling_data = false; | |
1452 | for (long i = 0, sz = mlist->get_items ()->size (); i < sz; i++) | |
1453 | { | |
1454 | Metric *m = mlist->get_items ()->fetch (i); | |
1455 | if (m->get_packet_type () == DATA_CLOCK) | |
1456 | { | |
1457 | has_clock_profiling_data = true; | |
1458 | break; | |
1459 | } | |
1460 | } | |
1461 | BaseMetricTreeNode *curr = dbeSession->get_reg_metrics_tree (); | |
1462 | return dbeGetMetricTreeNode (curr, mlist, include_unregistered, has_clock_profiling_data); | |
1463 | } | |
1464 | ||
1465 | static Vector<void*> * | |
1466 | dbeGetTableDataV2Data (DbeView *dbev, Hist_data *data); | |
1467 | ||
1468 | static Vector<void*> *dbeGetTableDataOneColumn (Hist_data *data, int met_ind); | |
1469 | static Vector<void*> * | |
1470 | dbeGetTableDataOneColumn (DbeView *dbev, Vector<Hist_data::HistItem*> *data, | |
1471 | ValueTag vtype, int metricColumnNumber); | |
1472 | ||
1473 | static hrtime_t | |
1474 | dbeCalcGroupDuration (int grInd) | |
1475 | { | |
1476 | int thisGroupSize = 1; | |
1477 | hrtime_t max_time = 0; | |
1478 | Experiment *exp; | |
1479 | if (dbeSession->expGroups->size () > 0) | |
1480 | { | |
1481 | ExpGroup *grp = dbeSession->expGroups->fetch (grInd); | |
1482 | thisGroupSize = grp->exps->size (); | |
1483 | for (int ii = 0; ii < thisGroupSize; ii++) | |
1484 | { | |
1485 | exp = grp->exps->fetch (ii); | |
1486 | Vector<DataDescriptor*> *ddscr = exp->getDataDescriptors (); | |
1487 | delete ddscr;// getDataDescriptors() forces reading of experiment data | |
1488 | if (exp != NULL) | |
1489 | { | |
1490 | hrtime_t tot_time = exp->getLastEvent () - exp->getStartTime () | |
1491 | + exp->getRelativeStartTime (); | |
1492 | if (max_time < tot_time) | |
1493 | max_time = tot_time; | |
1494 | } | |
1495 | } | |
1496 | } | |
1497 | else | |
1498 | { | |
1499 | exp = dbeSession->get_exp (0); | |
1500 | if (exp != NULL) | |
1501 | max_time = exp->getLastEvent () - exp->getStartTime (); | |
1502 | } | |
1503 | return max_time; //nanoseconds | |
1504 | } | |
1505 | ||
1506 | static hrtime_t | |
1507 | dbeCalcGroupGCDuration (int grInd) | |
1508 | { | |
1509 | int thisGroupSize = 1; | |
1510 | hrtime_t tot_time = 0; | |
1511 | Experiment *exp; | |
1512 | if (dbeSession->expGroups->size () > 0) | |
1513 | { | |
1514 | ExpGroup *grp = dbeSession->expGroups->fetch (grInd); | |
1515 | thisGroupSize = grp->exps->size (); | |
1516 | for (int ii = 0; ii < thisGroupSize; ii++) | |
1517 | { | |
1518 | exp = grp->exps->fetch (ii); | |
1519 | Vector<DataDescriptor*> *ddscr = exp->getDataDescriptors (); | |
1520 | delete ddscr; // getDataDescriptors() forces reading of experiment data | |
1521 | if (exp != NULL) | |
1522 | tot_time += exp->getGCDuration (); | |
1523 | } | |
1524 | } | |
1525 | else | |
1526 | { | |
1527 | exp = dbeSession->get_exp (0); | |
1528 | if (exp != NULL) | |
1529 | tot_time = exp->getGCDuration (); | |
1530 | } | |
1531 | return tot_time; //nanoseconds | |
1532 | } | |
1533 | ||
1534 | Vector<void*> * | |
1535 | dbeGetRefMetricTreeValues (int dbevindex, Vector<char *> *metric_cmds, | |
1536 | Vector<char *> *non_metric_cmds) | |
1537 | { | |
1538 | DbeView *dbev = dbeSession->getView (dbevindex); | |
1539 | // valueTable will have N "columns" of values, where N is the number of | |
1540 | // requested metrics and non-metrics. | |
1541 | // Each column will be a vector with M "rows", where M is the number of | |
1542 | // compare groups. | |
1543 | // highlightTable mirrors the structure of valueTable. Each cell indicates | |
1544 | // if the corresponding valueTable cell is "hot" (interesting) | |
1545 | int numMetrics = metric_cmds->size (); | |
1546 | int numNonMetrics = non_metric_cmds->size (); | |
1547 | int totalColumns = numMetrics + numNonMetrics; // Columns | |
1548 | Vector<void*> *valueTable = new Vector<void*>(totalColumns); | |
1549 | Vector<void*> *highlightTable = new Vector<void*>(totalColumns); | |
1550 | ||
1551 | // the return value consists of the two tables discussed above. | |
1552 | Vector<void*> *rc = new Vector<void*>(2); | |
1553 | rc->append (valueTable); | |
1554 | rc->append (highlightTable); | |
1555 | if (dbeSession->nexps () == 0) | |
1556 | { // no experiments are loaded | |
1557 | for (int jj = 0; jj < totalColumns; jj++) | |
1558 | { | |
1559 | Vector<void *> *columnData = new Vector<void *>(); | |
1560 | valueTable->append (columnData); | |
1561 | highlightTable->append (columnData); | |
1562 | } | |
1563 | return rc; | |
1564 | } | |
1565 | ||
1566 | int ngroups = dbeSession->expGroups->size (); // Rows (one per compare group) | |
1567 | if (ngroups == 0 || !dbev->comparingExperiments ()) | |
1568 | ngroups = 1; | |
1569 | ||
1570 | Vector<double> *groupTotalTime = new Vector<double>(ngroups); | |
1571 | Vector<double> *groupCpuTime = new Vector<double>(ngroups); | |
1572 | // initialize highlight table | |
1573 | for (int ii = 0; ii < totalColumns; ii++) | |
1574 | { // metrics | |
1575 | Vector<bool> *columnData = new Vector<bool>(ngroups); | |
1576 | highlightTable->append (columnData); | |
1577 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1578 | columnData->store (grInd, false); // non-highlight | |
1579 | } | |
1580 | ||
1581 | if (numMetrics > 0) | |
1582 | { | |
1583 | MetricList *bmlist; | |
1584 | // set bmlist to list of requested base metrics | |
1585 | BaseMetricTreeNode *root = dbeSession->get_reg_metrics_tree (); | |
1586 | int index; | |
1587 | char *mcmd; | |
1588 | Vector<BaseMetric*> *base_metrics = new Vector<BaseMetric*>(); | |
1589 | Vec_loop (char *, metric_cmds, index, mcmd) | |
1590 | { | |
1591 | BaseMetricTreeNode *bmt_node = root->find (mcmd); | |
1592 | if (!bmt_node) | |
1593 | abort (); //YXXX weird | |
1594 | BaseMetric * baseNetric = bmt_node->get_BaseMetric (); | |
1595 | if (!baseNetric) | |
1596 | abort (); | |
1597 | base_metrics->append (baseNetric); | |
1598 | } | |
1599 | ||
1600 | // MET_INDX will create MetricList of Exclusive metrics | |
1601 | bmlist = new MetricList (base_metrics, MET_SRCDIS); | |
1602 | ||
1603 | // Use the Function List to fetch <Total> values | |
1604 | // A temporary table, v_totals, stores <total> by group | |
1605 | Vector<Hist_data::HistItem *> *v_totals = new Vector<Hist_data::HistItem *>(ngroups); | |
1606 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1607 | { | |
1608 | MetricList *mlist; | |
1609 | if (ngroups > 1) | |
1610 | mlist = dbev->get_compare_mlist (bmlist, grInd); | |
1611 | else | |
1612 | mlist = bmlist; | |
1613 | if (mlist->size () != numMetrics) | |
1614 | abort (); | |
1615 | ||
1616 | Hist_data *data; | |
1617 | data = dbev->get_hist_data (mlist, Histable::FUNCTION, 0, | |
1618 | Hist_data::ALL); | |
1619 | Hist_data::HistItem * totals = data->get_totals (); | |
1620 | v_totals->append (totals); | |
1621 | } | |
1622 | ||
1623 | // store the Hist_data totals in valueTable | |
1624 | { | |
1625 | Metric *mitem; | |
1626 | int index; | |
1627 | Vec_loop (Metric*, bmlist->get_items (), index, mitem) | |
1628 | { | |
1629 | Vector<void*> * columnData = dbeGetTableDataOneColumn (dbev, | |
1630 | v_totals, mitem->get_vtype (), index); | |
1631 | valueTable->append (columnData); | |
1632 | } | |
1633 | } | |
1634 | ||
1635 | // 7207285: hack for hwc profiling cycles conversion: | |
1636 | { | |
1637 | Metric *mitem; | |
1638 | int index; | |
1639 | Vec_loop (Metric*, bmlist->get_items (), index, mitem) | |
1640 | { | |
1641 | if (mitem->is_time_val () | |
1642 | && mitem->get_vtype () == VT_ULLONG) | |
1643 | { | |
1644 | Vector<long long> *cycleValues = (Vector<long long> *)valueTable->fetch (index); | |
1645 | Vector<double> *timeValues = new Vector<double>(ngroups); | |
1646 | assert (cycleValues->size () == ngroups); | |
1647 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1648 | { | |
1649 | long long cycles = cycleValues->fetch (grInd); | |
1650 | int expId; | |
1651 | if (dbeSession->expGroups->size () > 0) | |
1652 | { | |
1653 | ExpGroup *gr = dbeSession->expGroups->fetch (grInd); | |
1654 | Experiment *exp = gr->exps->fetch (0); | |
1655 | expId = exp->getExpIdx (); | |
1656 | } | |
1657 | else | |
1658 | expId = -1; | |
1659 | int clock = dbeSession->get_clock (expId); | |
1660 | double time; | |
1661 | if (clock) | |
1662 | time = cycles / (1.e+6 * clock); | |
1663 | else | |
1664 | time = cycles; //weird | |
1665 | timeValues->store (grInd, time); | |
1666 | } | |
1667 | delete cycleValues; | |
1668 | valueTable->store (index, timeValues); | |
1669 | } | |
1670 | } | |
1671 | } | |
1672 | ||
1673 | // Scan metrics for best measure of CPU time | |
1674 | int bestCpuTimeIndx = -1; | |
1675 | { | |
1676 | Metric *mitem; | |
1677 | int index; | |
1678 | Vec_loop (Metric*, bmlist->get_items (), index, mitem) | |
1679 | { | |
1680 | BaseMetric::Type type = mitem->get_type (); | |
1681 | if (type == BaseMetric::CP_KERNEL_CPU) | |
1682 | { | |
1683 | bestCpuTimeIndx = index; | |
1684 | break; // CP_KERNEL_CPU trumps other measures | |
1685 | } | |
1686 | if (type == BaseMetric::CP_TOTAL_CPU) | |
1687 | { | |
1688 | // clock profiling CPU time | |
1689 | bestCpuTimeIndx = index; | |
1690 | // keep looking in case CP_KERNEL_CPU also exists | |
1691 | continue; | |
1692 | } | |
1693 | ||
1694 | bool isTime = ((mitem->get_value_styles () & VAL_TIMEVAL) != 0); | |
1695 | bool isHwcCycles = (type == BaseMetric::HWCNTR | |
1696 | && (dbe_strcmp (mitem->get_aux (), "cycles") == 0) | |
1697 | && isTime); | |
1698 | if (isHwcCycles) | |
1699 | if (bestCpuTimeIndx < 0) | |
1700 | bestCpuTimeIndx = index; | |
1701 | } | |
1702 | if (bestCpuTimeIndx >= 0) | |
1703 | { | |
1704 | Vector<double> *timeValues = (Vector<double> *)valueTable->fetch (bestCpuTimeIndx); | |
1705 | if (timeValues->type () == VEC_DOUBLE) | |
1706 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1707 | { | |
1708 | double time = timeValues->fetch (grInd); | |
1709 | groupCpuTime->append (time); | |
1710 | } | |
1711 | } | |
1712 | } | |
1713 | ||
1714 | // Scan metrics for Total Thread time | |
1715 | { | |
1716 | Metric *mitem; | |
1717 | int index; | |
1718 | Vec_loop (Metric*, bmlist->get_items (), index, mitem) | |
1719 | { | |
1720 | BaseMetric::Type type = mitem->get_type (); | |
1721 | if (type == BaseMetric::CP_TOTAL) | |
1722 | { | |
1723 | Vector<double> *timeValues = (Vector<double> *)valueTable->fetch (index); | |
1724 | if (timeValues->type () != VEC_DOUBLE) | |
1725 | continue; // weird | |
1726 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1727 | { | |
1728 | double time = timeValues->fetch (grInd); | |
1729 | groupTotalTime->append (time); | |
1730 | } | |
1731 | break; | |
1732 | } | |
1733 | } | |
1734 | } | |
1735 | ||
1736 | // highlight metrics based on cpu time | |
1737 | #define CPUSEC_PERCENT_THRESHOLD 10.0 | |
1738 | #define HWC_OVERFLOWS_PER_CPUSEC_THRESHOLD 15 | |
1739 | { | |
1740 | Metric *mitem; | |
1741 | int index; | |
1742 | Vec_loop (Metric*, bmlist->get_items (), index, mitem) | |
1743 | { | |
1744 | BaseMetric::Type type = mitem->get_type (); | |
1745 | Vector<bool> * columnHilites = (Vector<bool> *)highlightTable->fetch (index); | |
1746 | ||
1747 | // always highlight the following | |
1748 | if (index == bestCpuTimeIndx) | |
1749 | { | |
1750 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1751 | columnHilites->store (grInd, true); | |
1752 | continue; | |
1753 | } | |
1754 | ||
1755 | // skip certain types | |
1756 | bool typeIsCycles = (type == BaseMetric::HWCNTR | |
1757 | && dbe_strcmp (mitem->get_aux (), NTXT ("cycles")) == 0); | |
1758 | bool typeIsInsts = (type == BaseMetric::HWCNTR | |
1759 | && dbe_strcmp (mitem->get_aux (), NTXT ("insts")) == 0); | |
1760 | if (type == BaseMetric::CP_TOTAL | |
1761 | || type == BaseMetric::CP_TOTAL_CPU | |
1762 | || type == BaseMetric::CP_LMS_USER | |
1763 | || type == BaseMetric::CP_LMS_SYSTEM | |
1764 | || type == BaseMetric::CP_LMS_TRAP | |
1765 | || type == BaseMetric::CP_LMS_USER_LOCK | |
1766 | || type == BaseMetric::CP_LMS_SLEEP | |
1767 | || type == BaseMetric::CP_KERNEL_CPU | |
1768 | || type == BaseMetric::OMP_WORK | |
1769 | || typeIsCycles | |
1770 | || typeIsInsts | |
1771 | // || type == BaseMetric::CP_TOTAL_WAIT | |
1772 | ) | |
1773 | continue; // types we never highlight | |
1774 | ||
1775 | // for time values, compare against CPUSEC_PERCENT_THRESHOLD | |
1776 | bool isTime = ((mitem->get_value_styles () & VAL_TIMEVAL) != 0); | |
1777 | if (isTime) | |
1778 | { | |
1779 | if (groupCpuTime->size () == 0) | |
1780 | continue; // no time to use as reference | |
1781 | Vector<double> *timeValues = (Vector<double> *)valueTable->fetch (index); | |
1782 | if (timeValues->type () != VEC_DOUBLE) | |
1783 | continue; // weird | |
1784 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1785 | { | |
1786 | double thistime = timeValues->fetch (grInd); | |
1787 | double usertime = groupCpuTime->fetch (grInd); | |
1788 | if (thistime / (CPUSEC_PERCENT_THRESHOLD / 100) > usertime) | |
1789 | columnHilites->store (grInd, true); | |
1790 | } | |
1791 | continue; | |
1792 | } | |
1793 | ||
1794 | // for HWC event counts, look at rate of events | |
1795 | if (type == BaseMetric::HWCNTR) | |
1796 | { | |
1797 | Hwcentry *hwctr = mitem->get_hw_ctr (); | |
1798 | if (!hwctr) | |
1799 | continue; // weird | |
1800 | if (!hwctr->metric) | |
1801 | continue; // raw counter | |
1802 | if (groupCpuTime->size () == 0) | |
1803 | continue; // no time to use as reference | |
1804 | if (mitem->get_base_metric ()->get_dependent_bm ()) | |
1805 | continue; // has a derived time metric, only flag time version | |
1806 | Vector<long long> *llValues = (Vector<long long> *)valueTable->fetch (index); | |
1807 | if (llValues->type () != VEC_LLONG) | |
1808 | continue; // weird | |
1809 | int overflowVal = hwctr->val; //overflow count | |
1810 | if (!overflowVal) | |
1811 | continue; // weird | |
1812 | if (overflowVal > (4000000)) | |
1813 | // cut off events that are very frequent like loads/stores | |
1814 | // 4Ghz * (0.01 seconds/event) / (4000000 events/overflow) = 10 cycles | |
1815 | continue; | |
1816 | // for HWCs we could base it on the overflow rate | |
1817 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1818 | { | |
1819 | double thisVal = llValues->fetch (grInd); | |
1820 | thisVal /= overflowVal; | |
1821 | double usertime = groupCpuTime->fetch (grInd); | |
1822 | if (thisVal > usertime * HWC_OVERFLOWS_PER_CPUSEC_THRESHOLD) | |
1823 | columnHilites->store (grInd, true); | |
1824 | } | |
1825 | continue; | |
1826 | } | |
1827 | ||
1828 | // check for non-zero counts of the following | |
1829 | if (type == BaseMetric::DEADLOCKS || | |
1830 | type == BaseMetric::RACCESS || | |
1831 | type == BaseMetric::HEAP_ALLOC_BYTES || | |
1832 | type == BaseMetric::HEAP_LEAK_BYTES) | |
1833 | { | |
1834 | Vector<long long> *llValues = (Vector<long long> *)valueTable->fetch (index); | |
1835 | if (llValues->type () != VEC_LLONG) | |
1836 | continue; // weird | |
1837 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1838 | { | |
1839 | long long thisVal = llValues->fetch (grInd); | |
1840 | if (thisVal) | |
1841 | columnHilites->store (grInd, true); | |
1842 | } | |
1843 | continue; | |
1844 | } | |
1845 | // continue adding cases as needed | |
1846 | } | |
1847 | } | |
1848 | } | |
1849 | ||
1850 | if (numNonMetrics > 0) | |
1851 | { | |
1852 | int index; | |
1853 | char *mcmd; | |
1854 | Vec_loop (char *, non_metric_cmds, index, mcmd) | |
1855 | { | |
1856 | if (dbe_strcmp (mcmd, NTXT ("YXXX_TOTAL_TIME_PLUS_THREADS")) == 0 | |
1857 | && groupCpuTime->size () == ngroups) | |
1858 | { | |
1859 | Vector<char *> *columnData = new Vector<char *>(ngroups); | |
1860 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1861 | { | |
1862 | double totaltime = groupTotalTime->fetch (grInd); | |
1863 | columnData->append (dbe_sprintf (NTXT ("%0.3f %s"), totaltime, GTXT ("Seconds"))); | |
1864 | } | |
1865 | valueTable->append (columnData); | |
1866 | } | |
1867 | else if (dbe_strcmp (mcmd, L1_DURATION) == 0) | |
1868 | { | |
1869 | Vector<double> *columnData = new Vector<double>(ngroups); | |
1870 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1871 | { | |
1872 | hrtime_t duration = dbeCalcGroupDuration (grInd); | |
1873 | double seconds = duration * 1.e-9; | |
1874 | columnData->append (seconds); | |
1875 | } | |
1876 | valueTable->append (columnData); | |
1877 | } | |
1878 | else if (dbe_strcmp (mcmd, L1_GCDURATION) == 0) | |
1879 | { | |
1880 | Vector<double> *columnData = new Vector<double>(ngroups); | |
1881 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1882 | { | |
1883 | hrtime_t duration = dbeCalcGroupGCDuration (grInd); | |
1884 | double seconds = duration * 1.e-9; | |
1885 | columnData->append (seconds); | |
1886 | } | |
1887 | valueTable->append (columnData); | |
1888 | } | |
1889 | else | |
1890 | { | |
1891 | Vector<char *> *columnData = new Vector<char *>(ngroups); | |
1892 | char * valueString = NTXT ("<unknown>"); | |
1893 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1894 | columnData->append (dbe_strdup (valueString)); | |
1895 | valueTable->append (columnData); | |
1896 | } | |
1897 | } | |
1898 | } | |
1899 | return rc; | |
1900 | } | |
1901 | ||
1902 | Vector<char*> * | |
1903 | dbeGetOverviewText (int dbevindex) | |
1904 | { | |
1905 | DbeView *dbev = dbeSession->getView (dbevindex); | |
1906 | Vector<char*> *info = new Vector<char*>; | |
1907 | char *field; | |
1908 | int ngroups = dbeSession->expGroups->size (); // Rows (one per compare group) | |
1909 | if (ngroups == 0 || !dbev->comparingExperiments ()) | |
1910 | ngroups = 1; | |
1911 | for (int grInd = 0; grInd < ngroups; grInd++) | |
1912 | { | |
1913 | int thisGroupSize = 1; | |
1914 | Experiment *exp; | |
1915 | if (dbeSession->expGroups->size () > 0) | |
1916 | { | |
1917 | ExpGroup *gr = dbeSession->expGroups->fetch (grInd); | |
1918 | exp = gr->exps->fetch (0); | |
1919 | thisGroupSize = gr->exps->size (); | |
1920 | } | |
1921 | else | |
1922 | { | |
1923 | if (dbeSession->nexps () == 0) | |
1924 | return info; | |
1925 | exp = dbeSession->get_exp (0); | |
1926 | } | |
1927 | char * expHeader; | |
1928 | if (ngroups == 1) | |
1929 | expHeader = dbe_strdup (GTXT ("Experiment :")); | |
1930 | else if (grInd == 0) | |
1931 | expHeader = dbe_strdup (GTXT ("Base Group : ")); | |
1932 | else if (ngroups == 2) | |
1933 | expHeader = dbe_strdup (GTXT ("Compare Group : ")); | |
1934 | else | |
1935 | expHeader = dbe_sprintf (GTXT ("Compare Group %d : "), grInd); | |
1936 | if (thisGroupSize == 1) | |
1937 | info->append (dbe_sprintf ("%s%s", expHeader, exp->get_expt_name ())); | |
1938 | else | |
1939 | info->append (dbe_sprintf ("%s%s (plus %d more)", | |
1940 | expHeader, exp->get_expt_name (), thisGroupSize - 1)); | |
1941 | free (expHeader); | |
1942 | field = exp->uarglist; | |
1943 | if (field && field[0]) | |
1944 | info->append (dbe_sprintf (GTXT (" Target : '%s'"), field)); | |
1945 | field = exp->hostname; | |
1946 | if (field && field[0]) | |
6094a48e | 1947 | info->append (dbe_sprintf (GTXT (" Host : %s (%s, %s)"), |
bb368aad VM |
1948 | field, |
1949 | exp->architecture ? exp->architecture | |
1950 | : GTXT ("<CPU architecture not recorded>"), | |
1951 | exp->os_version ? exp->os_version | |
1952 | : GTXT ("<OS version not recorded>"))); | |
6094a48e VM |
1953 | time_t start_sec = (time_t) exp->start_sec; |
1954 | char *p = ctime (&start_sec); | |
bb368aad VM |
1955 | hrtime_t tot_time = dbeCalcGroupDuration (grInd); |
1956 | double seconds = tot_time * 1.e-9; | |
6094a48e VM |
1957 | info->append (dbe_sprintf ( |
1958 | GTXT (" Start Time : %s Duration : %0.3f Seconds"), | |
1959 | p, seconds)); | |
bb368aad VM |
1960 | // Number of descendants/processes would be nice |
1961 | info->append (dbe_strdup (NTXT (""))); | |
1962 | } | |
1963 | return info; | |
1964 | } | |
1965 | ||
1966 | //-------------------------------------------------------------------------- | |
1967 | // Set Sort by index | |
1968 | // | |
1969 | void | |
1970 | dbeSetSort (int dbevindex, int sort_index, MetricType mtype, bool reverse) | |
1971 | { | |
1972 | DbeView *dbev; | |
1973 | ||
1974 | dbev = dbeSession->getView (dbevindex); | |
1975 | if (dbev == NULL) | |
1976 | abort (); | |
1977 | dbev->setSort (sort_index, mtype, reverse); | |
1978 | return; | |
1979 | } | |
1980 | ||
1981 | // | |
1982 | // Get annotation setting | |
1983 | // | |
1984 | Vector<int> * | |
1985 | dbeGetAnoValue (int dbevindex) | |
1986 | { | |
1987 | DbeView *dbev = dbeSession->getView (dbevindex); | |
1988 | if (dbev == NULL) | |
1989 | abort (); | |
1990 | Vector<int> *set = new Vector<int>(9); | |
1991 | set->store (0, dbev->get_src_compcom ()); | |
1992 | set->store (1, dbev->get_dis_compcom ()); | |
1993 | set->store (2, dbev->get_thresh_src ()); | |
1994 | set->store (3, dbev->get_thresh_src ()); | |
1995 | set->store (4, dbev->get_src_visible ()); | |
1996 | set->store (5, (int) dbev->get_srcmetric_visible ()); | |
1997 | set->store (6, (int) dbev->get_hex_visible ()); | |
1998 | set->store (7, (int) dbev->get_cmpline_visible ()); | |
1999 | set->store (8, (int) dbev->get_func_scope ()); | |
2000 | return set; | |
2001 | } | |
2002 | ||
2003 | // | |
2004 | // Set annotation setting | |
2005 | // | |
2006 | void | |
2007 | dbeSetAnoValue (int dbevindex, Vector<int> *set) | |
2008 | { | |
2009 | DbeView *dbev; | |
2010 | dbev = dbeSession->getView (dbevindex); | |
2011 | if (dbev == NULL) | |
2012 | abort (); | |
2013 | if (set->size () != 10) | |
2014 | return; | |
2015 | dbev->set_src_compcom (set->fetch (0)); | |
2016 | dbev->set_dis_compcom (set->fetch (1)); | |
2017 | dbev->set_thresh_src (set->fetch (2)); | |
2018 | dbev->set_thresh_dis (set->fetch (3)); | |
2019 | dbev->set_src_visible (set->fetch (4)); | |
2020 | dbev->set_srcmetric_visible ((bool)set->fetch (5)); | |
2021 | dbev->set_hex_visible ((bool)set->fetch (6)); | |
2022 | dbev->set_cmpline_visible ((bool)set->fetch (7)); | |
2023 | dbev->set_func_scope (set->fetch (8)); | |
2024 | dbev->set_funcline_visible ((bool)set->fetch (9)); | |
2025 | return; | |
2026 | } | |
2027 | ||
2028 | // | |
2029 | // Get name formats | |
2030 | // | |
2031 | int | |
2032 | dbeGetNameFormat (int dbevindex) | |
2033 | { | |
2034 | DbeView *dbev; | |
2035 | dbev = dbeSession->getView (dbevindex); | |
2036 | if (dbev == NULL) | |
2037 | abort (); | |
2038 | Histable::NameFormat fmt = dbev->get_name_format (); | |
2039 | return Histable::fname_fmt (fmt); | |
2040 | } | |
2041 | ||
2042 | bool | |
2043 | dbeGetSoName (int dbevindex) | |
2044 | { | |
2045 | DbeView *dbev; | |
2046 | dbev = dbeSession->getView (dbevindex); | |
2047 | if (dbev == NULL) | |
2048 | abort (); | |
2049 | Histable::NameFormat fmt = dbev->get_name_format (); | |
2050 | return Histable::soname_fmt (fmt); | |
2051 | } | |
2052 | ||
2053 | // | |
2054 | // Set name formats | |
2055 | // | |
2056 | void | |
2057 | dbeSetNameFormat (int dbevindex, int nformat, bool soname) | |
2058 | { | |
2059 | DbeView *dbev; | |
2060 | dbev = dbeSession->getView (dbevindex); | |
2061 | if (dbev == NULL) | |
2062 | abort (); | |
2063 | dbev->set_name_format (nformat, soname); | |
2064 | } | |
2065 | ||
2066 | // | |
2067 | // Get View mode | |
2068 | // | |
2069 | int | |
2070 | dbeGetViewMode (int dbevindex) | |
2071 | { | |
2072 | DbeView *dbev; | |
2073 | dbev = dbeSession->getView (dbevindex); | |
2074 | if (dbev == NULL) | |
2075 | abort (); | |
2076 | return (int) dbev->get_view_mode (); | |
2077 | } | |
2078 | ||
2079 | // Set View mode | |
2080 | void | |
2081 | dbeSetViewMode (int dbevindex, int nmode) | |
2082 | { | |
2083 | DbeView *dbev; | |
2084 | dbev = dbeSession->getView (dbevindex); | |
2085 | if (dbev == NULL) | |
2086 | abort (); | |
2087 | dbev->set_view_mode ((VMode) nmode); | |
2088 | return; | |
2089 | } | |
2090 | ||
2091 | // Get timeline setting | |
2092 | // | |
2093 | Vector<void*> * | |
2094 | dbeGetTLValue (int dbevindex) | |
2095 | { | |
2096 | DbeView *dbev; | |
2097 | dbev = dbeSession->getView (dbevindex); | |
2098 | if (dbev == NULL) | |
2099 | abort (); | |
2100 | Vector<char *> *strings = new Vector<char *>(); | |
2101 | char *tldata_cmd = dbev->get_tldata (); | |
2102 | strings->store (0, tldata_cmd); | |
2103 | ||
2104 | Vector<int> *ints = new Vector<int>(3); | |
2105 | int val; | |
2106 | val = dbev->get_tlmode (); | |
2107 | ints->store (0, val); | |
2108 | val = dbev->get_stack_align (); | |
2109 | ints->store (1, val); | |
2110 | val = dbev->get_stack_depth (); | |
2111 | ints->store (2, val); | |
2112 | ||
2113 | Vector<void*> *objs = new Vector<void*>(2); | |
2114 | objs->store (0, strings); | |
2115 | objs->store (1, ints); | |
2116 | return objs; | |
2117 | } | |
2118 | ||
2119 | // | |
2120 | // Set timeline setting | |
2121 | // | |
2122 | void | |
2123 | dbeSetTLValue (int dbevindex, const char *tldata_cmd, | |
2124 | int entitiy_prop_id, int stackalign, int stackdepth) | |
2125 | { | |
2126 | DbeView *dbev; | |
2127 | dbev = dbeSession->getView (dbevindex); | |
2128 | if (dbev == NULL) | |
2129 | abort (); | |
2130 | dbev->set_tldata (tldata_cmd); | |
2131 | dbev->set_tlmode (entitiy_prop_id); | |
2132 | dbev->set_stack_align (stackalign); | |
2133 | dbev->set_stack_depth (stackdepth); | |
2134 | return; | |
2135 | } | |
2136 | ||
2137 | // | |
2138 | // Get founder experiments and their descendants | |
2139 | // | |
2140 | Vector<void*> * | |
2141 | dbeGetExpFounderDescendants () | |
2142 | { | |
2143 | int size = dbeSession->nexps (); | |
2144 | if (size == 0) | |
2145 | return NULL; | |
2146 | Vector<void*> *table = new Vector<void*>(2); | |
2147 | Vector<int> *founderExpIds = new Vector<int>(); | |
2148 | Vector<Vector<int> *> *subExpIds = new Vector<Vector<int>*>(); | |
2149 | for (int index = 0; index < size; index++) | |
2150 | { | |
2151 | Experiment *exp = dbeSession->get_exp (index); | |
2152 | if (exp->founder_exp == NULL) | |
2153 | { | |
2154 | founderExpIds->append (exp->getExpIdx ()); | |
2155 | Vector<int> *subExps = new Vector<int>(); | |
2156 | for (int i = 0; i < exp->children_exps->size (); i++) | |
2157 | { | |
2158 | Experiment * subExp = exp->children_exps->fetch (i); | |
2159 | subExps->append (subExp->getExpIdx ()); | |
2160 | } | |
2161 | subExpIds->append (subExps); | |
2162 | } | |
2163 | } | |
2164 | table->store (0, founderExpIds); | |
2165 | table->store (1, subExpIds); | |
2166 | return table; | |
2167 | } | |
2168 | ||
2169 | // | |
2170 | // Get experiment selection | |
2171 | // | |
2172 | Vector<void*> * | |
2173 | dbeGetExpSelection (int dbevindex) | |
2174 | { | |
2175 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2176 | if (dbev == NULL) | |
2177 | abort (); | |
2178 | int size = dbeSession->nexps (); | |
2179 | if (size == 0) | |
2180 | return NULL; | |
2181 | Vector<void*> *table = new Vector<void*>(3); | |
2182 | Vector<char*> *names = new Vector<char*>(size); | |
2183 | Vector<bool> *enable = new Vector<bool>(size); | |
2184 | Vector<int> *userExpIds = new Vector<int>(size); | |
2185 | ||
2186 | // Get experiment names | |
2187 | for (int index = 0; index < size; index++) | |
2188 | { | |
2189 | Experiment *exp = dbeSession->get_exp (index); | |
2190 | char *buf = dbeGetName (dbevindex, index); | |
2191 | names->store (index, buf); | |
2192 | bool val; | |
2193 | val = dbev->get_exp_enable (index); | |
2194 | enable->store (index, val); | |
2195 | userExpIds->store (index, exp->getUserExpId ()); | |
2196 | } | |
2197 | table->store (0, names); | |
2198 | table->store (1, enable); | |
2199 | table->store (2, userExpIds); | |
2200 | return table; | |
2201 | } | |
2202 | ||
2203 | int | |
2204 | dbeValidateFilterExpression (char *str_expr) | |
2205 | { | |
2206 | if (str_expr == NULL) | |
2207 | return 0; | |
2208 | Expression *expr = dbeSession->ql_parse (str_expr); | |
2209 | if (expr == NULL) | |
2210 | return 0; | |
2211 | delete expr; | |
2212 | return 1; | |
2213 | } | |
2214 | ||
2215 | Vector<void*> * | |
2216 | dbeGetFilterKeywords (int /* dbevindex */) | |
2217 | { | |
2218 | Vector <char*> *kwCategory = new Vector<char *>(); | |
2219 | Vector <char*> *kwCategoryI18N = new Vector<char *>(); | |
2220 | Vector <char*> *kwDataType = new Vector<char *>(); | |
2221 | Vector <char*> *kwKeyword = new Vector<char *>(); | |
2222 | Vector <char*> *kwFormula = new Vector<char *>(); | |
2223 | Vector <char*> *kwDescription = new Vector<char *>(); | |
2224 | Vector <void*> *kwEnumDescs = new Vector<void *>(); | |
2225 | ||
2226 | Vector<void*> *res = new Vector<void*>(7); | |
2227 | res->append (kwCategory); | |
2228 | res->append (kwCategoryI18N); | |
2229 | res->append (kwDataType); | |
2230 | res->append (kwKeyword); | |
2231 | res->append (kwFormula); | |
2232 | res->append (kwDescription); | |
2233 | res->append (kwEnumDescs); | |
2234 | ||
2235 | char *vtypeNames[] = VTYPE_TYPE_NAMES; | |
2236 | // section header for global definitions | |
2237 | kwCategory->append (dbe_strdup (NTXT ("FK_SECTION"))); | |
2238 | kwCategoryI18N->append (dbe_strdup (GTXT ("Global Definitions"))); | |
2239 | kwDataType->append (NULL); | |
2240 | kwKeyword->append (NULL); | |
2241 | kwFormula->append (NULL); | |
2242 | kwDescription->append (NULL); | |
2243 | kwEnumDescs->append (NULL); | |
2244 | dbeSession->get_filter_keywords (res); | |
2245 | MemorySpace::get_filter_keywords (res); | |
2246 | ||
2247 | // loop thru all founder experiments | |
2248 | int nexp = dbeSession->nexps (); | |
2249 | for (int ii = 0; ii < nexp; ++ii) | |
2250 | { | |
2251 | Experiment* fexp = dbeSession->get_exp (ii); | |
2252 | if (fexp->founder_exp != NULL) | |
2253 | continue; // is a child; should be covered when we get to founder | |
2254 | ||
2255 | // section header for each founder | |
2256 | // section header for founder experiment | |
2257 | kwCategory->append (dbe_strdup (NTXT ("FK_SECTION"))); | |
2258 | kwCategoryI18N->append (dbe_sprintf (NTXT ("%s [EXPGRID==%d]"), | |
2259 | fexp->get_expt_name (), | |
2260 | fexp->groupId)); | |
2261 | kwDataType->append (NULL); | |
2262 | kwKeyword->append (NULL); | |
2263 | kwFormula->append (NULL); | |
2264 | kwDescription->append (NULL); | |
2265 | kwEnumDescs->append (NULL); | |
2266 | ||
2267 | int nchildren = fexp->children_exps->size (); | |
2268 | Experiment *exp; | |
2269 | // category header: Experiments | |
2270 | { | |
2271 | char *propUName = dbeSession->getPropUName (PROP_EXPID); | |
2272 | ||
2273 | // store list of subexperiments in kwEnumDescs | |
2274 | Vector <char*> *enumDescs = new Vector<char *>(); | |
2275 | int jj = 0; | |
2276 | exp = fexp; | |
2277 | while (1) | |
2278 | { | |
2279 | char * expBasename = get_basename (exp->get_expt_name ()); | |
2280 | char * targetName = exp->utargname ? exp->utargname | |
2281 | : (char *) GTXT ("(unknown)"); | |
2282 | enumDescs->append (dbe_sprintf (NTXT ("(%d) -> %s [%s, PID %d]"), | |
2283 | exp->getUserExpId (), expBasename, | |
2284 | targetName, exp->getPID ())); | |
2285 | if (jj >= nchildren) | |
2286 | break; | |
2287 | exp = fexp->children_exps->fetch (jj); | |
2288 | jj++; | |
2289 | } | |
2290 | kwCategory->append (dbe_strdup (NTXT ("FK_EXPLIST"))); | |
2291 | kwCategoryI18N->append (dbe_strdup (GTXT ("Experiments"))); | |
2292 | kwDataType->append (dbe_strdup (vtypeNames[TYPE_INT32])); | |
2293 | kwKeyword->append (dbe_strdup (NTXT ("EXPID"))); | |
2294 | kwFormula->append (NULL); | |
2295 | kwDescription->append (propUName); | |
2296 | kwEnumDescs->append (enumDescs); | |
2297 | } | |
2298 | ||
2299 | // select representative experiment | |
2300 | if (nchildren == 0) | |
2301 | exp = fexp; // founder | |
2302 | else | |
2303 | exp = fexp->children_exps->fetch (0); // first child | |
2304 | int expIdx = exp->getExpIdx (); | |
2305 | Vector<void*> *data = dbeGetDataDescriptorsV2 (expIdx); | |
2306 | if (data == NULL) | |
2307 | continue; | |
2308 | Vector<int> *dataId = (Vector<int>*)data->fetch (0); | |
2309 | Vector<char*> *dataName = (Vector<char*>*)data->fetch (1); | |
2310 | Vector<char*> *dataUName = (Vector<char*>*)data->fetch (2); | |
2311 | if (dataId == NULL || dataName == NULL) | |
2312 | { | |
2313 | destroy (data); | |
2314 | continue; | |
2315 | } | |
2316 | // loop thru data descriptors | |
2317 | int ndata = dataId->size (); | |
2318 | for (int j = 0; j < ndata; ++j) | |
2319 | { | |
2320 | // category: data name (e.g. Clock Profiling) | |
2321 | char * catName = dataName->fetch (j); | |
2322 | char * dUname = dataUName ? dataUName->fetch (j) : catName; | |
2323 | char * catUname = dUname ? dUname : catName; | |
2324 | ||
2325 | Vector<void*> *props = dbeGetDataPropertiesV2 (expIdx, dataId->fetch (j)); | |
2326 | if (props == NULL) | |
2327 | continue; | |
2328 | Vector<char*> *propUName = (Vector<char*>*)props->fetch (1); | |
2329 | Vector<int> *propTypeId = (Vector<int> *)props->fetch (2); | |
2330 | Vector<char*> *propType = (Vector<char*>*)props->fetch (3); | |
2331 | Vector<char*> *propName = (Vector<char*>*)props->fetch (5); | |
2332 | Vector<Vector<char*>*> *propStateNames = | |
2333 | (Vector<Vector<char*>*> *)props->fetch (6); | |
2334 | Vector<Vector<char*>*> *propStateUNames = | |
2335 | (Vector<Vector<char*>*> *)props->fetch (7); | |
2336 | if (propName == NULL || propUName == NULL || propType == NULL | |
2337 | || propName->size () <= 0) | |
2338 | { | |
2339 | destroy (props); | |
2340 | continue; | |
2341 | } | |
2342 | int nprop = propName->size (); | |
2343 | for (int k = 0; k < nprop; ++k) | |
2344 | { | |
2345 | if (propTypeId->fetch (k) == TYPE_OBJ) | |
2346 | continue; | |
2347 | if (dbe_strcmp (propName->fetch (k), NTXT ("FRINFO")) == 0) | |
2348 | continue; | |
2349 | ||
2350 | // store list of states in kwEnumDescs | |
2351 | Vector<char*> *enumDescs = new Vector<char *>(); | |
2352 | Vector<char*>* stateNames = propStateNames->fetch (k); | |
2353 | Vector<char*>* stateUNames = propStateUNames->fetch (k); | |
2354 | int nStates = stateNames ? stateNames->size () : 0; | |
2355 | for (int kk = 0; kk < nStates; ++kk) | |
2356 | { | |
2357 | const char *stateName = stateNames->fetch (kk); | |
2358 | if (stateName == NULL || strlen (stateName) == 0) | |
2359 | continue; | |
2360 | const char *stateUName = stateUNames->fetch (kk); | |
2361 | if (stateUName == NULL || strlen (stateUName) == 0) | |
2362 | stateUName = stateName; | |
2363 | enumDescs->append (dbe_sprintf (NTXT ("(%d) -> %s"), kk, stateUName)); | |
2364 | } | |
2365 | kwCategory->append (dbe_strdup (catName)); | |
2366 | kwCategoryI18N->append (dbe_strdup (catUname)); | |
2367 | kwDataType->append (dbe_strdup (propType->fetch (k))); | |
2368 | kwKeyword->append (dbe_strdup (propName->fetch (k))); | |
2369 | kwFormula->append (NULL); | |
2370 | kwDescription->append (dbe_strdup (propUName->fetch (k))); | |
2371 | kwEnumDescs->append (enumDescs); | |
2372 | } | |
2373 | destroy (props); | |
2374 | } | |
2375 | destroy (data); | |
2376 | } | |
2377 | return (res); | |
2378 | } | |
2379 | ||
2380 | // GetFilters -- returns the list of filters for the indexed experiment | |
2381 | // returns false if there's a problem; true otherwise | |
2382 | // | |
2383 | Vector<void*> * | |
2384 | dbeGetFilters (int dbevindex, int nexp) | |
2385 | { | |
2386 | FilterNumeric *filt; | |
2387 | int index; | |
2388 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2389 | if (dbev == NULL) | |
2390 | abort (); | |
2391 | Vector<FilterNumeric *>*filters = dbev->get_all_filters (nexp); | |
2392 | if (filters == NULL) | |
2393 | return NULL; | |
2394 | ||
2395 | // return an array of filter data for that experiment | |
2396 | Vector <int> *findex = new Vector<int>(); // index of the filters | |
2397 | Vector <char*> *shortname = new Vector<char *>(); | |
2398 | // short name of filter | |
2399 | Vector <char*> *i18n_name = new Vector<char *>(); | |
2400 | // External I18N'd name of filter | |
2401 | Vector <char*> *pattern = new Vector<char *>(); | |
2402 | // current setting string | |
2403 | Vector <char*> *status = new Vector<char *>(); | |
2404 | // current status of filter (%, range, etc.) | |
2405 | ||
2406 | Vec_loop (FilterNumeric *, filters, index, filt) | |
2407 | { | |
2408 | findex->append (index); | |
2409 | shortname->append (dbe_strdup (filt->get_cmd ())); | |
2410 | i18n_name->append (dbe_strdup (filt->get_name ())); | |
2411 | pattern->append (dbe_strdup (filt->get_pattern ())); | |
2412 | status->append (dbe_strdup (filt->get_status ())); | |
2413 | } | |
2414 | Vector<void*> *res = new Vector<void*>(5); | |
2415 | res->store (0, findex); | |
2416 | res->store (1, shortname); | |
2417 | res->store (2, i18n_name); | |
2418 | res->store (3, pattern); | |
2419 | res->store (4, status); | |
2420 | return (res); | |
2421 | } | |
2422 | ||
2423 | // Set a filter string for a view | |
2424 | // Returns NULL if OK, error message if not | |
2425 | ||
2426 | char * | |
2427 | dbeSetFilterStr (int dbevindex, char *filter_str) | |
2428 | { | |
2429 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2430 | if (dbev == NULL) | |
2431 | abort (); | |
2432 | dbev->clear_error_msg (); | |
2433 | dbev->clear_warning_msg (); | |
2434 | char *ret = dbev->set_filter (filter_str); | |
2435 | return ret; | |
2436 | } | |
2437 | ||
2438 | // Get the current filter setting for the view | |
2439 | char * | |
2440 | dbeGetFilterStr (int dbevindex) | |
2441 | { | |
2442 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2443 | if (dbev == NULL) | |
2444 | abort (); | |
2445 | char *ret = dbev->get_filter (); | |
2446 | return ret; | |
2447 | } | |
2448 | ||
2449 | // Update a filters for a single experiment | |
2450 | // Returns true if any filter->set_pattern() returns true, | |
2451 | // implying rereading the data is needed (i.e., a filter changed) | |
2452 | // | |
2453 | bool | |
2454 | dbeUpdateFilters (int dbevindex, Vector<bool> *selected, Vector<char *> *pattern_str) | |
2455 | { | |
2456 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2457 | if (dbev == NULL) | |
2458 | abort (); | |
2459 | dbev->clear_error_msg (); | |
2460 | dbev->clear_warning_msg (); | |
2461 | ||
2462 | // Get index of first selected experiment | |
2463 | int size = selected->size (); | |
2464 | int nselexp = -1; | |
2465 | for (int index = 0; index < size; index++) | |
2466 | { | |
2467 | if (selected->fetch (index) == true) | |
2468 | { | |
2469 | nselexp = index; | |
2470 | break; | |
2471 | } | |
2472 | } | |
2473 | if (nselexp == -1) // No experiment selected | |
2474 | return false; | |
2475 | ||
2476 | bool ret = false; | |
2477 | for (int j = 0; j < size; j++) | |
2478 | { | |
2479 | if (selected->fetch (j) == false) | |
2480 | continue; | |
2481 | bool error; | |
2482 | if (dbev->set_pattern (j, pattern_str, &error)) | |
2483 | ret = true; | |
2484 | } | |
2485 | dbev->update_advanced_filter (); | |
2486 | return ret; | |
2487 | } | |
2488 | ||
2489 | char * | |
2490 | dbeComposeFilterClause (int dbevindex, int type, int subtype, Vector<int> *selections) | |
2491 | { | |
2492 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2493 | if (dbev == NULL) | |
2494 | abort (); | |
2495 | // ask the cached data to generate the string | |
2496 | Hist_data *data; | |
2497 | switch (type) | |
2498 | { | |
2499 | case DSP_FUNCTION: | |
2500 | data = dbev->func_data; | |
2501 | break; | |
2502 | case DSP_DLAYOUT: | |
2503 | data = dbev->dlay_data; | |
2504 | break; | |
2505 | case DSP_DATAOBJ: | |
2506 | data = dbev->dobj_data; | |
2507 | break; | |
2508 | case DSP_MEMOBJ: | |
2509 | case DSP_INDXOBJ: | |
2510 | data = dbev->get_indxobj_data (subtype); | |
2511 | break; | |
2512 | case DSP_LINE: | |
2513 | data = dbev->line_data; | |
2514 | break; | |
2515 | case DSP_PC: | |
2516 | data = dbev->pc_data; | |
2517 | break; | |
2518 | case DSP_SOURCE: | |
2519 | data = dbev->src_data; | |
2520 | break; | |
2521 | case DSP_DISASM: | |
2522 | data = dbev->dis_data; | |
2523 | break; | |
2524 | case DSP_IOACTIVITY: | |
2525 | data = dbev->iofile_data; | |
2526 | break; | |
2527 | case DSP_IOVFD: | |
2528 | data = dbev->iovfd_data; | |
2529 | break; | |
2530 | case DSP_IOCALLSTACK: | |
2531 | data = dbev->iocs_data; | |
2532 | break; | |
2533 | case DSP_HEAPCALLSTACK: | |
2534 | data = dbev->heapcs_data; | |
2535 | break; | |
2536 | default: | |
2537 | return NULL; | |
2538 | } | |
2539 | if (data == NULL) | |
2540 | return NULL; | |
2541 | ||
2542 | // Get array of object indices, and compose filter string | |
2543 | Vector<uint64_t> *obj_ids = data->get_object_indices (selections); | |
2544 | if (obj_ids == NULL || obj_ids->size () == 0) | |
2545 | return NULL; | |
2546 | ||
2547 | uint64_t sel; | |
2548 | int index; | |
2549 | int found = 0; | |
2550 | char buf[128]; | |
2551 | StringBuilder sb; | |
2552 | sb.append ('('); | |
2553 | switch (type) | |
2554 | { | |
2555 | case DSP_LINE: | |
2556 | case DSP_PC: | |
2557 | case DSP_SOURCE: | |
2558 | case DSP_DISASM: | |
2559 | case DSP_FUNCTION: | |
2560 | sb.append (NTXT ("LEAF IN ")); | |
2561 | break; | |
2562 | case DSP_MEMOBJ: | |
2563 | case DSP_INDXOBJ: | |
2564 | sb.append (dbeSession->getIndexSpaceName (subtype)); | |
2565 | sb.append (NTXT (" IN ")); | |
2566 | break; | |
2567 | } | |
2568 | Vec_loop (uint64_t, obj_ids, index, sel) | |
2569 | { | |
2570 | if (found == 0) | |
2571 | { | |
2572 | found = 1; | |
2573 | sb.append ('('); | |
2574 | } | |
2575 | else | |
2576 | sb.append (NTXT (", ")); | |
2577 | snprintf (buf, sizeof (buf), NTXT ("%llu"), (long long) sel); | |
2578 | sb.append (buf); | |
2579 | } | |
2580 | if (found == 1) | |
2581 | sb.append (')'); | |
2582 | ||
2583 | switch (type) | |
2584 | { | |
2585 | case DSP_DLAYOUT: | |
2586 | case DSP_DATAOBJ: | |
2587 | sb.append (NTXT (" SOME IN DOBJ")); | |
2588 | break; | |
2589 | } | |
2590 | sb.append (')'); | |
2591 | return sb.toString (); | |
2592 | } | |
2593 | ||
2594 | // | |
2595 | // Get load object states | |
2596 | // | |
2597 | Vector<void *> * | |
2598 | dbeGetLoadObjectList (int dbevindex) | |
2599 | { | |
2600 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2601 | if (dbev == NULL) | |
2602 | abort (); | |
2603 | Vector<LoadObject*> *lobjs = dbeSession->get_text_segments (); | |
2604 | int size = lobjs->size (); | |
2605 | ||
2606 | // Initialize Java boolean array | |
2607 | Vector<char *> *names = new Vector<char *>(size); | |
2608 | Vector<int> *states = new Vector<int>(size); | |
2609 | Vector<int> *indices = new Vector<int>(size); | |
2610 | Vector<char *> *paths = new Vector<char *>(size); | |
2611 | Vector<int> *isJava = new Vector<int>(size); | |
2612 | ||
2613 | // Get load object states | |
2614 | int index; | |
2615 | LoadObject *lo; | |
2616 | char *lo_name; | |
2617 | ||
2618 | // lobjectsNoJava is a trimmed list of indices provided to front-end skipping the Java | |
2619 | // classes. lobjectsNoJava preserves the mapping of the index into the complete lobjs | |
2620 | // vector. What front-end sees as lobj[i] is really lobj[lobjectsNoJava[i]]; | |
2621 | ||
2622 | // This list is constructed every time GetLoadObjectList() or GetLoadObjectState() is | |
2623 | // called. Possibility of further optimization by making it more persistent. | |
2624 | // Only consumer of this list is dbeSetLoadObjectState | |
2625 | int new_index = 0; | |
2626 | if (dbev->lobjectsNoJava == NULL) | |
2627 | dbev->lobjectsNoJava = new Vector<int>(1); | |
2628 | else | |
2629 | dbev->lobjectsNoJava->reset (); | |
2630 | ||
2631 | Vec_loop (LoadObject*, lobjs, index, lo) | |
2632 | { | |
2633 | // Set 0, 1, or 2 for show/hide/api | |
2634 | enum LibExpand expand = dbev->get_lo_expand (lo->seg_idx); | |
2635 | ||
2636 | lo_name = lo->get_name (); | |
2637 | if (lo_name != NULL) | |
2638 | { | |
2639 | size_t len = strlen (lo_name); | |
2640 | if (len > 7 && streq (lo_name + len - 7, NTXT (".class>"))) | |
2641 | isJava->store (new_index, 1); | |
2642 | else | |
2643 | isJava->store (new_index, 0); | |
2644 | } | |
2645 | else | |
2646 | isJava->store (new_index, 0); | |
2647 | dbev->lobjectsNoJava->append (index); | |
2648 | ||
2649 | names->store (new_index, dbe_sprintf (NTXT ("%s"), lo_name)); | |
2650 | states->store (new_index, (int) expand); | |
2651 | indices->store (new_index, (int) lo->seg_idx); | |
2652 | paths->store (new_index, dbe_sprintf (NTXT ("%s"), lo->get_pathname ())); | |
2653 | new_index++; | |
2654 | } | |
2655 | Vector<void*> *res = new Vector<void*>(5); | |
2656 | res->store (0, names); | |
2657 | res->store (1, states); | |
2658 | res->store (2, indices); | |
2659 | res->store (3, paths); | |
2660 | res->store (4, isJava); | |
2661 | delete lobjs; | |
2662 | return res; | |
2663 | } | |
2664 | ||
2665 | Vector<int> * | |
2666 | dbeGetLoadObjectState (int dbevindex) | |
2667 | { | |
2668 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2669 | if (dbev == NULL) | |
2670 | abort (); | |
2671 | Vector<LoadObject*> *lobjs = dbeSession->get_text_segments (); | |
2672 | int size = lobjs->size (); | |
2673 | ||
2674 | // Initialize Java boolean array | |
2675 | Vector<int> *states = new Vector<int>(size); | |
2676 | char *lo_name; | |
2677 | ||
2678 | // lobjectsNoJava is a trimmed list of indices provided to front-end skipping the Java | |
2679 | // classes. lobjectsNoJava preserves the mapping of the index into the complete lobjs | |
2680 | // vector. What front-end sees as lobj[i] is really lobj[lobjectsNoJava[i]]; | |
2681 | ||
2682 | // This list is constructed every time GetLoadObjectList() or GetLoadObjectState() is | |
2683 | // called. Possibility of further optimization by making it more persistent. | |
2684 | // Only consumer of this list is dbeSetLoadObjectState | |
2685 | int new_index = 0; | |
2686 | if (dbev->lobjectsNoJava == NULL) | |
2687 | dbev->lobjectsNoJava = new Vector<int>(1); | |
2688 | else | |
2689 | dbev->lobjectsNoJava->reset (); | |
2690 | ||
2691 | // Get load object states | |
2692 | int index; | |
2693 | LoadObject *lo; | |
2694 | ||
2695 | Vec_loop (LoadObject*, lobjs, index, lo) | |
2696 | { | |
2697 | // Set 0, 1, or 2 for show/hide/api | |
2698 | lo_name = lo->get_name (); | |
2699 | if (lo_name != NULL) | |
2700 | { | |
2701 | size_t len = strlen (lo_name); | |
2702 | if (len > 7 && streq (lo_name + len - 7, NTXT (".class>"))) | |
2703 | continue; | |
2704 | } | |
2705 | else | |
2706 | dbev->lobjectsNoJava->append (index); | |
2707 | ||
2708 | enum LibExpand expand = dbev->get_lo_expand (lo->seg_idx); | |
2709 | states->store (new_index, (int) expand); | |
2710 | new_index++; | |
2711 | } | |
2712 | delete lobjs; | |
2713 | return states; | |
2714 | } | |
2715 | ||
2716 | // Set load object states | |
2717 | void | |
2718 | dbeSetLoadObjectState (int dbevindex, Vector<int> *selected) | |
2719 | { | |
2720 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2721 | if (dbev == NULL) | |
2722 | abort (); | |
2723 | Vector<LoadObject*> *lobjs = dbeSession->get_text_segments (); | |
2724 | ||
2725 | int index; | |
2726 | bool changed = false; | |
2727 | ||
2728 | LoadObject *lo; | |
2729 | int new_index = 0; | |
2730 | dbev->setShowAll (); | |
2731 | Vec_loop (LoadObject*, lobjs, index, lo) | |
2732 | { | |
2733 | if (dbev->lobjectsNoJava != NULL) | |
2734 | { | |
2735 | // This loadobject is a java class and was skipped | |
2736 | if (dbev->lobjectsNoJava->fetch (new_index) != index) | |
2737 | continue; | |
2738 | } | |
2739 | // Get array of settings | |
2740 | enum LibExpand expand = (enum LibExpand) selected->fetch (new_index); | |
2741 | if (expand == LIBEX_HIDE) | |
2742 | { | |
2743 | dbev->resetShowAll (); | |
2744 | dbeSession->set_lib_visibility_used (); | |
2745 | } | |
2746 | changed = changed | dbev->set_libexpand (lo->get_pathname (), expand); | |
2747 | new_index++; | |
2748 | } | |
2749 | delete lobjs; | |
2750 | if (changed == true) | |
2751 | { | |
2752 | dbev->setShowHideChanged (); | |
2753 | dbev->update_lo_expands (); | |
2754 | } | |
2755 | ||
2756 | return; | |
2757 | } | |
2758 | ||
2759 | // Reset load object states | |
2760 | void | |
2761 | dbeSetLoadObjectDefaults (int dbevindex) | |
2762 | { | |
2763 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2764 | if (dbev == NULL) | |
2765 | abort (); | |
2766 | dbev->set_libdefaults (); | |
2767 | } | |
2768 | ||
2769 | // Get Machine model | |
2770 | Vector<char*>* | |
2771 | dbeGetCPUVerMachineModel (int dbevindex) | |
2772 | { | |
2773 | Vector<char*>* table = new Vector<char*>(); | |
2774 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2775 | char * mach_model = dbev->get_settings ()->get_machinemodel (); | |
2776 | if (mach_model != NULL) | |
2777 | { | |
2778 | table->append (mach_model); | |
2779 | return table; | |
2780 | } | |
2781 | int grsize = dbeSession->expGroups->size (); | |
2782 | for (int j = 0; j < grsize; j++) | |
2783 | { | |
2784 | ExpGroup *gr = dbeSession->expGroups->fetch (j); | |
2785 | Vector<Experiment*> *exps = gr->exps; | |
2786 | for (int i = 0, sz = exps->size (); i < sz; i++) | |
2787 | { | |
2788 | Experiment *exp = exps->fetch (i); | |
2789 | char *model = exp->machinemodel; | |
2790 | if (model != NULL) | |
2791 | table->append (dbe_strdup (model)); | |
2792 | } | |
2793 | } | |
2794 | return table; | |
2795 | } | |
2796 | ||
2797 | // automatically load machine model if applicable | |
2798 | void | |
2799 | dbeDetectLoadMachineModel (int dbevindex) | |
2800 | { | |
2801 | if (dbeSession->is_datamode_available ()) | |
2802 | { | |
2803 | char *model = dbeGetMachineModel (); | |
2804 | if (model == NULL) | |
2805 | { | |
2806 | Vector<char*>* models = dbeGetCPUVerMachineModel (dbevindex); | |
2807 | char * machineModel = NTXT ("generic"); | |
2808 | if (models->size () > 0) | |
2809 | { | |
2810 | machineModel = models->get (0); | |
2811 | for (int i = 1; i < models->size (); i++) | |
2812 | { | |
2813 | if (strncmp (models->get (i), machineModel, strlen (machineModel)) == 0) | |
2814 | { | |
2815 | machineModel = NTXT ("generic"); | |
2816 | break; | |
2817 | } | |
2818 | } | |
2819 | dbeLoadMachineModel (machineModel); | |
2820 | } | |
2821 | delete models; | |
2822 | } | |
2823 | } | |
2824 | } | |
2825 | ||
2826 | // Managing Memory Objects | |
2827 | char * | |
2828 | dbeDefineMemObj (char *name, char *index_expr, char *machinemodel, | |
2829 | char *sdesc, char *ldesc) | |
2830 | { | |
2831 | return MemorySpace::mobj_define (name, index_expr, machinemodel, sdesc, ldesc); | |
2832 | } | |
2833 | ||
2834 | char * | |
2835 | dbeDeleteMemObj (char *name) | |
2836 | { | |
2837 | return MemorySpace::mobj_delete (name); | |
2838 | } | |
2839 | ||
2840 | Vector<void*> * | |
2841 | dbeGetMemObjects (int /*dbevindex*/) | |
2842 | { | |
2843 | Vector<void*> *res = MemorySpace::getMemObjects (); | |
2844 | return res; | |
2845 | } | |
2846 | ||
2847 | // Managing machine model | |
2848 | char * | |
2849 | dbeLoadMachineModel (char *name) | |
2850 | { | |
2851 | return dbeSession->load_mach_model (name); | |
2852 | } | |
2853 | ||
2854 | char * | |
2855 | dbeGetMachineModel () | |
2856 | { | |
2857 | return dbeSession->get_mach_model (); | |
2858 | } | |
2859 | ||
2860 | Vector <char *> * | |
2861 | dbeListMachineModels () | |
2862 | { | |
2863 | return dbeSession->list_mach_models (); | |
2864 | } | |
2865 | ||
2866 | // Managing Index Objects | |
2867 | char * | |
2868 | dbeDefineIndxObj (char *name, char *index_expr, char *sdesc, char *ldesc) | |
2869 | { | |
2870 | return dbeSession->indxobj_define (name, NULL, index_expr, sdesc, ldesc); | |
2871 | } | |
2872 | ||
2873 | Vector<void*> * | |
2874 | dbeGetIndxObjDescriptions (int /*dbevindex*/) | |
2875 | { | |
2876 | Vector<void*> *res = dbeSession->getIndxObjDescriptions (); | |
2877 | return res; | |
2878 | } | |
2879 | ||
2880 | Vector<void*> * | |
2881 | dbeGetCustomIndxObjects (int /*dbevindex*/) | |
2882 | { | |
2883 | Vector<void*> *res = dbeSession->getCustomIndxObjects (); | |
2884 | return res; | |
2885 | } | |
2886 | ||
2887 | void | |
2888 | dbeSetSelObj (int dbevindex, Obj sel_obj_or_ind, int type, int subtype) | |
2889 | { | |
2890 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2891 | if (dbev == NULL) | |
2892 | abort (); | |
2893 | Histable *sel_obj; | |
2894 | Hist_data *data; | |
2895 | int sel_ind = (int) sel_obj_or_ind; | |
2896 | ||
2897 | switch (type) | |
2898 | { | |
2899 | case DSP_FUNCTION: | |
2900 | data = dbev->func_data; | |
2901 | break; | |
2902 | case DSP_LINE: | |
2903 | data = dbev->line_data; | |
2904 | break; | |
2905 | case DSP_PC: | |
2906 | data = dbev->pc_data; | |
2907 | break; | |
2908 | case DSP_CALLER: | |
2909 | data = dbev->callers; | |
2910 | break; | |
2911 | case DSP_CALLEE: | |
2912 | data = dbev->callees; | |
2913 | break; | |
2914 | case DSP_SOURCE: | |
2915 | data = dbev->src_data; | |
2916 | break; | |
2917 | case DSP_DISASM: | |
2918 | data = dbev->dis_data; | |
2919 | break; | |
2920 | case DSP_DLAYOUT: | |
2921 | data = dbev->dlay_data; | |
2922 | if (data == NULL) | |
2923 | { | |
2924 | dbev->sel_binctx = NULL; | |
2925 | return; | |
2926 | } | |
2927 | if (sel_ind >= 0 && sel_ind < dbev->dlay_data->size ()) | |
2928 | dbev->sel_dobj = dbev->dlay_data->fetch (sel_ind)->obj; | |
2929 | return; | |
2930 | case DSP_DATAOBJ: | |
2931 | data = dbev->dobj_data; | |
2932 | if (data == NULL) | |
2933 | { | |
2934 | dbev->sel_binctx = NULL; | |
2935 | return; | |
2936 | } | |
2937 | if (sel_ind >= 0 && sel_ind < dbev->dobj_data->size ()) | |
2938 | dbev->sel_dobj = dbev->dobj_data->fetch (sel_ind)->obj; | |
2939 | return; | |
2940 | case DSP_MEMOBJ: | |
2941 | case DSP_INDXOBJ: | |
2942 | dbev->set_indxobj_sel (subtype, sel_ind); | |
2943 | sel_obj = dbev->get_indxobj_sel (subtype); | |
2944 | if (sel_obj && sel_obj->get_type () == Histable::INDEXOBJ) | |
2945 | dbev->set_sel_obj (((IndexObject*) sel_obj)->get_obj ()); | |
2946 | return; | |
2947 | case DSP_SOURCE_V2: | |
2948 | case DSP_DISASM_V2: | |
2949 | case DSP_TIMELINE: | |
2950 | case DSP_LEAKLIST: | |
2951 | case DSP_RACES: | |
2952 | case DSP_DEADLOCKS: | |
2953 | case DSP_DUALSOURCE: | |
2954 | case DSP_SOURCE_DISASM: | |
2955 | case DSP_IOACTIVITY: | |
2956 | case DSP_IOVFD: | |
2957 | case DSP_IOCALLSTACK: | |
2958 | case DSP_HEAPCALLSTACK: | |
2959 | case DSP_MINICALLER: | |
2960 | dbev->set_sel_obj ((Histable *) sel_obj_or_ind); | |
2961 | return; | |
2962 | default: | |
2963 | // abort(); | |
2964 | return; | |
2965 | } | |
2966 | if (type != DSP_SOURCE && type != DSP_DISASM && type != DSP_SOURCE_V2 | |
2967 | && type != DSP_DISASM_V2) | |
2968 | dbev->sel_binctx = NULL; | |
2969 | ||
2970 | if (data == NULL || data->get_status () != Hist_data::SUCCESS | |
2971 | || sel_ind >= data->size ()) | |
2972 | return; | |
2973 | ||
2974 | if (sel_ind >= 0 && sel_ind < data->size ()) | |
2975 | dbev->set_sel_obj (data->fetch (sel_ind)->obj); | |
2976 | } | |
2977 | ||
2978 | void | |
2979 | dbeSetSelObjV2 (int dbevindex, uint64_t id) | |
2980 | { | |
2981 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2982 | if (dbev == NULL) | |
2983 | abort (); | |
2984 | dbev->set_sel_obj (dbeSession->findObjectById (id)); | |
2985 | } | |
2986 | ||
2987 | Obj | |
2988 | dbeGetSelObj (int dbevindex, int type, int subtype) | |
2989 | { | |
2990 | DbeView *dbev = dbeSession->getView (dbevindex); | |
2991 | Histable *sel_obj = NULL; | |
2992 | switch (type) | |
2993 | { | |
2994 | case DSP_FUNCTION: | |
2995 | sel_obj = dbev->get_sel_obj (Histable::FUNCTION); | |
2996 | break; | |
2997 | case DSP_LINE: | |
2998 | case DSP_SOURCE: | |
2999 | case DSP_SOURCE_V2: | |
3000 | sel_obj = dbev->get_sel_obj (Histable::LINE); | |
3001 | break; | |
3002 | case DSP_PC: | |
3003 | case DSP_DISASM: | |
3004 | case DSP_DISASM_V2: | |
3005 | sel_obj = dbev->get_sel_obj (Histable::INSTR); | |
3006 | break; | |
3007 | case DSP_SRC_FILE: | |
3008 | sel_obj = dbev->get_sel_obj (Histable::SOURCEFILE); | |
3009 | break; | |
3010 | case DSP_DATAOBJ: | |
3011 | case DSP_DLAYOUT: | |
3012 | if (dbev->sel_dobj) | |
3013 | sel_obj = dbev->sel_dobj->convertto (Histable::DOBJECT); | |
3014 | break; | |
3015 | case DSP_MEMOBJ: | |
3016 | case DSP_INDXOBJ: | |
3017 | sel_obj = dbev->get_indxobj_sel (subtype); | |
3018 | break; | |
3019 | default: | |
3020 | abort (); | |
3021 | } | |
3022 | Dprintf (DEBUG_DBE, NTXT ("### dbeGetSelObj: Dbe.cc:%d %s (%d) returns %s\n"), | |
3023 | __LINE__, dsp_type_to_string (type), type, sel_obj ? sel_obj->dump () : "NULL"); | |
3024 | return (Obj) sel_obj; | |
3025 | } | |
3026 | ||
3027 | Obj | |
3028 | dbeConvertSelObj (Obj obj, int type) | |
3029 | { | |
3030 | Histable *sel_obj = (Histable *) obj; | |
3031 | Dprintf (DEBUG_DBE, NTXT ("### dbeConvertSelObj: Dbe.cc:%d %s (%d) sel_obj=%s\n"), | |
3032 | __LINE__, dsp_type_to_string (type), type, sel_obj ? sel_obj->dump () | |
3033 | : "NULL"); | |
3034 | if (sel_obj == NULL) | |
3035 | return (Obj) NULL; | |
3036 | switch (type) | |
3037 | { | |
3038 | case DSP_FUNCTION: | |
3039 | return (Obj) sel_obj->convertto (Histable::FUNCTION); | |
3040 | case DSP_LINE: | |
3041 | return (Obj) sel_obj->convertto (Histable::LINE); | |
3042 | case DSP_SOURCE: | |
3043 | case DSP_SOURCE_V2: | |
3044 | { | |
3045 | SourceFile* srcCtx = NULL; | |
3046 | if (sel_obj->get_type () == Histable::INSTR) | |
3047 | { | |
3048 | DbeInstr* dbei = (DbeInstr *) sel_obj; | |
3049 | srcCtx = (SourceFile*) dbei->convertto (Histable::SOURCEFILE); | |
3050 | } | |
3051 | else if (sel_obj->get_type () == Histable::LINE) | |
3052 | { | |
3053 | DbeLine * dbel = (DbeLine *) sel_obj; | |
3054 | srcCtx = dbel->sourceFile; | |
3055 | } | |
3056 | sel_obj = sel_obj->convertto (Histable::LINE, srcCtx); | |
3057 | Dprintf (DEBUG_DBE, NTXT ("### dbeConvertSelObj: Dbe.cc:%d %s (%d) returns %s\n"), | |
3058 | __LINE__, dsp_type_to_string (type), type, sel_obj ? sel_obj->dump () : "NULL"); | |
3059 | if (sel_obj && sel_obj->get_type () == Histable::LINE) | |
3060 | { | |
3061 | DbeLine * dbel = (DbeLine *) sel_obj; | |
3062 | return (Obj) dbel->dbeline_base; | |
3063 | } | |
3064 | return (Obj) sel_obj->convertto (Histable::LINE, srcCtx); | |
3065 | } | |
3066 | case DSP_PC: | |
3067 | case DSP_DISASM: | |
3068 | case DSP_DISASM_V2: | |
3069 | return (Obj) sel_obj->convertto (Histable::INSTR); | |
3070 | case DSP_SRC_FILE: | |
3071 | return (Obj) sel_obj->convertto (Histable::SOURCEFILE); | |
3072 | default: | |
3073 | abort (); | |
3074 | } | |
3075 | return (Obj) NULL; | |
3076 | } | |
3077 | ||
3078 | uint64_t | |
3079 | dbeGetSelObjV2 (int dbevindex, char *typeStr) | |
3080 | { | |
3081 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3082 | if (dbev == NULL) | |
3083 | abort (); | |
3084 | Histable *obj = NULL; | |
3085 | if (typeStr != NULL) | |
3086 | { | |
3087 | if (streq (typeStr, NTXT ("FUNCTION"))) | |
3088 | obj = dbev->get_sel_obj (Histable::FUNCTION); | |
3089 | else if (streq (typeStr, NTXT ("INSTRUCTION"))) | |
3090 | obj = dbev->get_sel_obj (Histable::INSTR); | |
3091 | else if (streq (typeStr, NTXT ("SOURCELINE"))) | |
3092 | obj = dbev->get_sel_obj (Histable::LINE); | |
3093 | else if (streq (typeStr, NTXT ("SOURCEFILE"))) | |
3094 | obj = dbev->get_sel_obj (Histable::SOURCEFILE); | |
3095 | } | |
3096 | Dprintf (DEBUG_DBE, NTXT ("### dbeGetSelObjV2: Dbe.cc:%d %s returns %s\n"), | |
3097 | __LINE__, STR (typeStr), obj ? obj->dump () : "NULL"); | |
3098 | return obj != NULL ? obj->id : (uint64_t) - 1; | |
3099 | } | |
3100 | ||
3101 | Vector<uint64_t> * | |
3102 | dbeGetSelObjsIO (int dbevindex, Vector<uint64_t> *ids, int type) | |
3103 | { | |
3104 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3105 | if (dbev == NULL) | |
3106 | abort (); | |
3107 | Vector<uint64_t> *res = NULL; | |
3108 | Vector<uint64_t> *result = new Vector<uint64_t>(); | |
3109 | for (int i = 0; i < ids->size (); i++) | |
3110 | { | |
3111 | res = dbeGetSelObjIO (dbevindex, ids->fetch (i), type); | |
3112 | if (res != NULL) | |
3113 | { | |
3114 | result->addAll (res); | |
3115 | delete res; | |
3116 | } | |
3117 | } | |
3118 | return result; | |
3119 | } | |
3120 | ||
3121 | Vector<uint64_t> * | |
3122 | dbeGetSelObjIO (int dbevindex, uint64_t id, int type) | |
3123 | { | |
3124 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3125 | if (dbev == NULL) | |
3126 | abort (); | |
3127 | Histable *obj = NULL; | |
3128 | Vector<uint64_t> *res = NULL; | |
3129 | int size = 0; | |
3130 | switch (type) | |
3131 | { | |
3132 | case DSP_IOACTIVITY: | |
3133 | obj = dbev->get_sel_obj_io (id, Histable::IOACTFILE); | |
3134 | size = obj != NULL ? ((FileData*) obj)->getVirtualFds ()->size () : 0; | |
3135 | if (size) | |
3136 | { | |
3137 | res = new Vector<uint64_t>(); | |
3138 | Vector<int64_t> *vfds = ((FileData*) obj)->getVirtualFds (); | |
3139 | for (int i = 0; i < size; i++) | |
3140 | res->append (vfds->fetch (i)); | |
3141 | } | |
3142 | break; | |
3143 | case DSP_IOVFD: | |
3144 | obj = dbev->get_sel_obj_io (id, Histable::IOACTVFD); | |
3145 | if (obj) | |
3146 | { | |
3147 | res = new Vector<uint64_t>(); | |
3148 | res->append (obj->id); | |
3149 | } | |
3150 | break; | |
3151 | case DSP_IOCALLSTACK: | |
3152 | obj = dbev->get_sel_obj_io (id, Histable::IOCALLSTACK); | |
3153 | if (obj) | |
3154 | { | |
3155 | Vector<Obj> *instrs = dbeGetStackPCs (dbevindex, obj->id); | |
3156 | if (instrs == NULL) | |
3157 | return NULL; | |
3158 | int stsize = instrs->size (); | |
3159 | res = new Vector<uint64_t>(stsize); | |
3160 | for (int i = 0; i < stsize; i++) | |
3161 | { | |
3162 | Histable *objFunc = (DbeInstr*) (instrs->fetch (i)); | |
3163 | if (objFunc->get_type () != Histable::LINE) | |
3164 | { | |
3165 | objFunc = objFunc->convertto (Histable::FUNCTION); | |
3166 | res->insert (0, objFunc->id); | |
3167 | } | |
3168 | } | |
3169 | delete instrs; | |
3170 | } | |
3171 | break; | |
3172 | default: | |
3173 | break; | |
3174 | } | |
3175 | return res; | |
3176 | } | |
3177 | ||
3178 | uint64_t | |
3179 | dbeGetSelObjHeapTimestamp (int dbevindex, uint64_t id) | |
3180 | { | |
3181 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3182 | if (dbev == NULL) | |
3183 | abort (); | |
3184 | Histable *obj = NULL; | |
3185 | uint64_t res = 0; | |
3186 | Vector<uint64_t> *peakStackIds; | |
3187 | Vector<hrtime_t> *peakTimestamps; | |
3188 | ||
3189 | // Find and return the timestamp for the peak | |
3190 | bool foundPeakId = false; | |
3191 | if (id > 0) | |
3192 | { | |
3193 | obj = dbev->get_sel_obj_heap (0); | |
3194 | if (obj != NULL) | |
3195 | { | |
3196 | peakStackIds = ((HeapData*) obj)->getPeakStackIds (); | |
3197 | peakTimestamps = ((HeapData*) obj)->getPeakTimestamps (); | |
3198 | for (int i = 0; i < peakStackIds->size (); i++) | |
3199 | { | |
3200 | if (id == peakStackIds->fetch (i)) | |
3201 | { | |
3202 | res = peakTimestamps->fetch (i); | |
3203 | foundPeakId = true; | |
3204 | break; | |
3205 | } | |
3206 | } | |
3207 | } | |
3208 | } | |
3209 | ||
3210 | // Return the first timestamp for the peak | |
3211 | // if the callstack id is zero or it | |
3212 | // doesn't match with the peak stack id | |
3213 | if (id == 0 || !foundPeakId) | |
3214 | { | |
3215 | obj = dbev->get_sel_obj_heap (0); | |
3216 | res = obj != NULL ? ((HeapData*) obj)->getPeakTimestamps ()->fetch (0) : 0; | |
3217 | } | |
3218 | return res; | |
3219 | } | |
3220 | ||
3221 | int | |
3222 | dbeGetSelObjHeapUserExpId (int dbevindex, uint64_t id) | |
3223 | { | |
3224 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3225 | if (dbev == NULL) | |
3226 | abort (); | |
3227 | Histable *obj = NULL; | |
3228 | int res = 0; | |
3229 | obj = dbev->get_sel_obj_heap (id); | |
3230 | res = obj != NULL ? ((HeapData*) obj)->getUserExpId () : 0; | |
3231 | return res; | |
3232 | } | |
3233 | ||
3234 | // | |
3235 | // Get index of selected function/object | |
3236 | // | |
3237 | int | |
3238 | dbeGetSelIndex (int dbevindex, Obj sel_obj, int type, int subtype) | |
3239 | { | |
3240 | Hist_data *data; | |
3241 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3242 | if (dbev == NULL) | |
3243 | abort (); | |
3244 | switch (type) | |
3245 | { | |
3246 | case DSP_FUNCTION: | |
3247 | data = dbev->func_data; | |
3248 | break; | |
3249 | case DSP_LINE: | |
3250 | data = dbev->line_data; | |
3251 | break; | |
3252 | case DSP_PC: | |
3253 | data = dbev->pc_data; | |
3254 | break; | |
3255 | case DSP_SOURCE: | |
3256 | case DSP_SOURCE_V2: | |
3257 | data = dbev->src_data; | |
3258 | break; | |
3259 | case DSP_DISASM: | |
3260 | case DSP_DISASM_V2: | |
3261 | data = dbev->dis_data; | |
3262 | break; | |
3263 | case DSP_DLAYOUT: | |
3264 | data = dbev->dlay_data; | |
3265 | break; | |
3266 | case DSP_DATAOBJ: | |
3267 | data = dbev->dobj_data; | |
3268 | break; | |
3269 | case DSP_MEMOBJ: | |
3270 | case DSP_INDXOBJ: | |
3271 | data = dbev->get_indxobj_data (subtype); | |
3272 | break; | |
3273 | default: | |
3274 | data = NULL; | |
3275 | break; | |
3276 | } | |
3277 | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | |
3278 | return -1; | |
3279 | ||
3280 | Histable *chk_obj = (Histable *) sel_obj; | |
3281 | Vector<Hist_data::HistItem*> *histItems = data->get_hist_items (); | |
3282 | if (histItems == NULL || chk_obj == NULL) | |
3283 | return -1; | |
3284 | for (int i = 0, sz = histItems->size (); i < sz; i++) | |
3285 | { | |
3286 | if (histItems->get (i)->obj == chk_obj) | |
3287 | return i; | |
3288 | if (histItems->get (i)->obj == NULL) | |
3289 | continue; | |
3290 | if (histItems->get (i)->obj->get_type () == Histable::LINE | |
3291 | && chk_obj->get_type () == Histable::LINE) | |
3292 | { | |
3293 | if (((DbeLine*) histItems->get (i)->obj)->convertto (Histable::FUNCTION) | |
3294 | == ((DbeLine*) chk_obj)->convertto (Histable::FUNCTION) | |
3295 | && ((DbeLine*) histItems->get (i)->obj)->lineno | |
3296 | == ((DbeLine*) chk_obj)->lineno) | |
3297 | return i; | |
3298 | } | |
3299 | else if (histItems->get (i)->obj->get_type () == Histable::INSTR | |
3300 | && chk_obj->get_type () == Histable::INSTR) | |
3301 | if (((DbeInstr*) histItems->get (i)->obj)->convertto (Histable::FUNCTION) | |
3302 | == ((DbeInstr*) chk_obj)->convertto (Histable::FUNCTION) | |
3303 | && ((DbeInstr*) histItems->get (i)->obj)->addr | |
3304 | == ((DbeInstr*) chk_obj)->addr) | |
3305 | return i; | |
3306 | } | |
3307 | ||
3308 | Histable *chk_obj1 = NULL; | |
3309 | switch (type) | |
3310 | { | |
3311 | case DSP_FUNCTION: | |
3312 | chk_obj1 = chk_obj->convertto (Histable::FUNCTION); | |
3313 | break; | |
3314 | case DSP_LINE: | |
3315 | case DSP_SOURCE: | |
3316 | case DSP_SOURCE_V2: | |
3317 | chk_obj1 = chk_obj->convertto (Histable::LINE); | |
3318 | break; | |
3319 | case DSP_PC: | |
3320 | case DSP_DISASM: | |
3321 | case DSP_DISASM_V2: | |
3322 | chk_obj1 = chk_obj->convertto (Histable::INSTR); | |
3323 | break; | |
3324 | } | |
3325 | if (chk_obj1 && chk_obj != chk_obj1) | |
3326 | for (int i = 0, sz = histItems->size (); i < sz; i++) | |
3327 | if (histItems->get (i)->obj == chk_obj1) | |
3328 | return i; | |
3329 | ||
3330 | if (type == DSP_LINE) | |
3331 | { | |
3332 | for (int i = 0, sz = histItems->size (); i < sz; i++) | |
3333 | if (histItems->get (i)->obj != NULL | |
3334 | && chk_obj->convertto (Histable::FUNCTION) | |
3335 | == histItems->get (i)->obj->convertto (Histable::FUNCTION)) | |
3336 | return i; | |
3337 | } | |
3338 | else if (type == DSP_PC) | |
3339 | { | |
3340 | for (int i = 0, sz = histItems->size (); i < sz; i++) | |
3341 | if (histItems->get (i)->obj != NULL | |
3342 | && (histItems->get (i)->obj)->convertto (Histable::FUNCTION) | |
3343 | == (chk_obj)->convertto (Histable::FUNCTION) | |
3344 | && ((DbeLine*) histItems->get (i)->obj->convertto (Histable::LINE))->lineno | |
3345 | == ((DbeLine*) chk_obj->convertto (Histable::LINE))->lineno) | |
3346 | return i; | |
3347 | for (int i = 0, sz = histItems->size (); i < sz; i++) | |
3348 | if (histItems->get (i)->obj != NULL | |
3349 | && (histItems->get (i)->obj)->convertto (Histable::FUNCTION) | |
3350 | == (chk_obj)->convertto (Histable::FUNCTION)) | |
3351 | return i; | |
3352 | } | |
3353 | ||
3354 | // If we clicked on an mfunction line in the called-by call mini in user mode for omp | |
3355 | // we might not find that function in func data | |
3356 | if (dbev->isOmpDisMode () && type == DSP_FUNCTION) | |
3357 | { | |
3358 | int p = dbeGetSelIndex (dbevindex, sel_obj, DSP_DISASM, subtype); | |
3359 | if (p != -1) | |
3360 | return p; | |
3361 | } | |
3362 | return -1; | |
3363 | } | |
3364 | ||
3365 | // Print data | |
3366 | // | |
3367 | char * | |
3368 | dbePrintData (int dbevindex, int type, int subtype, char *printer, | |
3369 | char *fname, FILE *outfile) | |
3370 | { | |
3371 | Histable *current_obj; | |
3372 | Function *func; | |
3373 | Module *module; | |
3374 | MetricList *mlist_orig; | |
3375 | bool header; | |
3376 | Print_params params; | |
3377 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3378 | if (dbev == NULL) | |
3379 | abort (); | |
3380 | ||
3381 | // Set print parameters | |
3382 | if (printer != NULL) | |
3383 | { | |
3384 | params.dest = DEST_PRINTER; | |
3385 | params.name = printer; | |
3386 | } | |
3387 | else if (outfile != NULL) | |
3388 | { | |
3389 | params.dest = DEST_OPEN_FILE; | |
3390 | params.openfile = outfile; | |
3391 | params.name = NULL; | |
3392 | } | |
3393 | else | |
3394 | { | |
3395 | params.dest = DEST_FILE; | |
3396 | params.name = fname; | |
3397 | if (*(params.name) == '\0') | |
3398 | { | |
3399 | free (params.name); | |
3400 | return dbe_strdup (GTXT ("Please enter the name of the file to which to print")); | |
3401 | } | |
3402 | } | |
3403 | params.ncopies = 1; | |
3404 | if (outfile != NULL) | |
3405 | header = false; | |
3406 | else | |
3407 | header = !(type == DSP_SOURCE || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2); | |
3408 | ||
3409 | params.header = header; | |
3410 | ||
3411 | // figure out what kind of metrics to use | |
3412 | if (type == DSP_SELF || type == DSP_CALLER || type == DSP_CALLEE | |
3413 | || type == DSP_CALLTREE) | |
3414 | mlist_orig = dbev->get_metric_list (MET_CALL); | |
3415 | else if (type == DSP_DATAOBJ || type == DSP_DLAYOUT || type == DSP_MEMOBJ) | |
3416 | mlist_orig = dbev->get_metric_list (MET_DATA); | |
3417 | else if (type == DSP_INDXOBJ) | |
3418 | mlist_orig = dbev->get_metric_list (MET_INDX); | |
3419 | else if (type == DSP_IOACTIVITY || type == DSP_IOVFD | |
3420 | || type == DSP_IOCALLSTACK) | |
3421 | mlist_orig = dbev->get_metric_list (MET_IO); | |
3422 | else if (type == DSP_HEAPCALLSTACK) | |
3423 | mlist_orig = dbev->get_metric_list (MET_HEAP); | |
3424 | else | |
3425 | mlist_orig = dbev->get_metric_list (MET_NORMAL); | |
3426 | ||
3427 | // make a compacted version of the input list | |
3428 | // the list will either be moved to the generated data, | |
3429 | // or freed below if it wasn't needed | |
3430 | MetricList *mlist = new MetricList (mlist_orig); | |
3431 | Hist_data *data = NULL; | |
3432 | er_print_common_display *cd = NULL; | |
3433 | int ix; | |
3434 | // Set data | |
3435 | switch (type) | |
3436 | { | |
3437 | case DSP_FUNCTION: | |
3438 | case DSP_LINE: | |
3439 | case DSP_PC: | |
3440 | case DSP_MEMOBJ: | |
3441 | case DSP_INDXOBJ: | |
3442 | case DSP_DATAOBJ: | |
3443 | data = dbev->get_hist_data (mlist, | |
3444 | ((type == DSP_FUNCTION) ? Histable::FUNCTION : | |
3445 | (type == DSP_LINE) ? Histable::LINE : | |
3446 | (type == DSP_PC) ? Histable::INSTR : | |
3447 | (type == DSP_INDXOBJ) ? Histable::INDEXOBJ : | |
3448 | (type == DSP_MEMOBJ) ? Histable::MEMOBJ | |
3449 | : Histable::DOBJECT), | |
3450 | subtype, Hist_data::ALL); | |
3451 | if (data->get_status () != Hist_data::SUCCESS) | |
3452 | return DbeView::status_str (DbeView::DBEVIEW_NO_DATA); // no strdup() | |
3453 | ||
3454 | cd = new er_print_histogram (dbev, data, mlist, MODE_LIST, | |
3455 | dbev->get_limit (), | |
3456 | mlist->get_sort_name (), NULL, true, true); | |
3457 | break; | |
3458 | case DSP_DLAYOUT: | |
3459 | { | |
3460 | data = dbev->get_hist_data (mlist, Histable::DOBJECT, 0, Hist_data::LAYOUT); | |
3461 | if (data->get_status () != Hist_data::SUCCESS) | |
3462 | return DbeView::status_str (DbeView::DBEVIEW_NO_DATA); // no strdup() | |
3463 | cd = new er_print_histogram (dbev, data, mlist, MODE_ANNOTATED, | |
3464 | dbev->get_thresh_dis (), | |
3465 | mlist->get_sort_name (), NULL, true, true); | |
3466 | break; | |
3467 | } | |
3468 | ||
3469 | // source and disassembly | |
3470 | case DSP_SOURCE: | |
3471 | case DSP_DISASM: | |
3472 | case DSP_SOURCE_V2: | |
3473 | case DSP_DISASM_V2: | |
3474 | if (dbev->sel_obj == NULL) | |
3475 | return NULL; | |
3476 | current_obj = dbev->sel_obj->convertto (Histable::FUNCTION); | |
3477 | if (current_obj->get_type () != Histable::FUNCTION) | |
3478 | return dbe_strdup (GTXT ("Not a real function; no source or disassembly available.")); | |
3479 | func = (Function*) current_obj->convertto (Histable::FUNCTION); | |
3480 | if (func->flags & FUNC_FLAG_SIMULATED) | |
3481 | return dbe_strdup (GTXT ("Not a real function; no source or disassembly available.")); | |
3482 | if (func->get_name () == NULL) | |
3483 | return dbe_strdup (GTXT ("Source location not recorded in experiment")); | |
3484 | module = func->module; | |
3485 | if (module == NULL || module->get_name () == NULL) | |
3486 | return dbe_strdup (GTXT ("Object name not recorded in experiment")); | |
3487 | ix = module->loadobject->seg_idx; | |
3488 | if (dbev->get_lo_expand (ix) == LIBEX_HIDE) | |
3489 | return dbe_strdup (GTXT ("No source or disassembly available for hidden object")); | |
3490 | cd = new er_print_histogram (dbev, dbev->func_data, mlist, MODE_ANNOTATED, | |
3491 | type == DSP_DISASM || type == DSP_DISASM_V2, | |
3492 | mlist->get_sort_name (), | |
3493 | func, false, false); | |
3494 | break; | |
3495 | ||
3496 | // callers-callees | |
3497 | case DSP_SELF: | |
3498 | case DSP_CALLER: | |
3499 | case DSP_CALLEE: | |
3500 | if (dbev->sel_obj == NULL) | |
3501 | return NULL; | |
3502 | current_obj = dbev->sel_obj->convertto (Histable::FUNCTION); | |
3503 | cd = new er_print_histogram (dbev, dbev->func_data, mlist, MODE_GPROF, 1, | |
3504 | mlist->get_sort_name (), current_obj, | |
3505 | false, false); | |
3506 | break; | |
3507 | ||
3508 | // statistics; this won't use the metric list copied above, so delete it | |
3509 | case DSP_STATIS: | |
3510 | cd = new er_print_experiment (dbev, 0, dbeSession->nexps () - 1, | |
3511 | true, true, true, true, false); | |
3512 | delete mlist; | |
3513 | break; | |
3514 | case DSP_EXP: | |
3515 | cd = new er_print_experiment (dbev, 0, dbeSession->nexps () - 1, | |
3516 | true, true, false, false, false); | |
3517 | delete mlist; | |
3518 | break; | |
3519 | case DSP_LEAKLIST: | |
3520 | cd = new er_print_leaklist (dbev, true, true, dbev->get_limit ()); | |
3521 | delete mlist; | |
3522 | break; | |
3523 | case DSP_HEAPCALLSTACK: | |
3524 | cd = new er_print_heapactivity (dbev, Histable::HEAPCALLSTACK, false, | |
3525 | dbev->get_limit ()); | |
3526 | delete mlist; | |
3527 | break; | |
3528 | case DSP_IOACTIVITY: | |
3529 | cd = new er_print_ioactivity (dbev, Histable::IOACTFILE, false, | |
3530 | dbev->get_limit ()); | |
3531 | delete mlist; | |
3532 | break; | |
3533 | case DSP_IOVFD: | |
3534 | cd = new er_print_ioactivity (dbev, Histable::IOACTVFD, false, | |
3535 | dbev->get_limit ()); | |
3536 | delete mlist; | |
3537 | break; | |
3538 | ||
3539 | // the io call stack | |
3540 | case DSP_IOCALLSTACK: | |
3541 | cd = new er_print_ioactivity (dbev, Histable::IOCALLSTACK, false, | |
3542 | dbev->get_limit ()); | |
3543 | delete mlist; | |
3544 | break; | |
3545 | ||
3546 | // some unknown panel -- return an error string | |
3547 | default: | |
3548 | delete mlist; | |
3549 | return dbe_strdup (GTXT ("Print not available")); | |
3550 | } | |
3551 | ||
3552 | // Start printing | |
3553 | char *buf = NULL; | |
3554 | ||
3555 | // first open the file/device/whatever | |
3556 | if (cd->open (¶ms) == 0) | |
3557 | { | |
3558 | // now call the actual print routine | |
3559 | cd->data_dump (); | |
3560 | if (params.dest == DEST_PRINTER) | |
3561 | { | |
3562 | if (streq ((char *) params.name, NTXT ("-"))) | |
3563 | { | |
3564 | // Special case - return report to the GUI | |
3565 | int maxbytes = 2 * 1024 * 1024; // IPC large buffer limit | |
3566 | char *report = cd->get_output (maxbytes); | |
3567 | delete data; | |
3568 | delete cd; | |
3569 | return report; // TEMPORARY | |
3570 | } | |
3571 | } | |
3572 | if (cd->print_output () == false) | |
3573 | buf = dbe_sprintf (NTXT ("%s: %s"), | |
3574 | GTXT ("Unable to submit print request to"), | |
3575 | params.name); | |
3576 | } | |
3577 | else | |
3578 | // if unable to set up the print, return an error | |
3579 | buf = dbe_sprintf (NTXT ("%s: %s"), | |
3580 | GTXT ("Unable to open file"), | |
3581 | params.name); | |
3582 | ||
3583 | // dbe_free((void *) params.name); XXX when should this happen? | |
3584 | if (data) | |
3585 | if (data->isViewOwned () == false) | |
3586 | delete data; | |
3587 | delete cd; | |
3588 | return buf; | |
3589 | } | |
3590 | ||
3591 | // Set limit for print data | |
3592 | // | |
3593 | char * | |
3594 | dbeSetPrintLimit (int dbevindex, int limit) | |
3595 | { | |
3596 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3597 | if (dbev == NULL) | |
3598 | abort (); | |
3599 | return (dbev->set_limit (limit)); | |
3600 | } | |
3601 | ||
3602 | // get limit for print data | |
3603 | int | |
3604 | dbeGetPrintLimit (int dbevindex) | |
3605 | { | |
3606 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3607 | if (dbev == NULL) | |
3608 | abort (); | |
3609 | int limit = dbev->get_limit (); | |
3610 | return limit; | |
3611 | } | |
3612 | ||
3613 | // set printmode for data | |
3614 | char * | |
3615 | dbeSetPrintMode (int dbevindex, char * pmode) | |
3616 | { | |
3617 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3618 | if (dbev == NULL) | |
3619 | abort (); | |
3620 | char *r = dbev->set_printmode (pmode); | |
3621 | return r; | |
3622 | } | |
3623 | ||
3624 | // get printmode for data | |
3625 | int | |
3626 | dbeGetPrintMode (int dbevindex) | |
3627 | { | |
3628 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3629 | if (dbev == NULL) | |
3630 | abort (); | |
3631 | return (dbev->get_printmode ()); | |
3632 | } | |
3633 | ||
3634 | // get printmode for data | |
3635 | char * | |
3636 | dbeGetPrintModeString (int dbevindex) | |
3637 | { | |
3638 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3639 | if (dbev == NULL) | |
3640 | abort (); | |
3641 | return ( dbev->get_printmode_str ()); | |
3642 | } | |
3643 | ||
3644 | // get print delimiter for csv data | |
3645 | char | |
3646 | dbeGetPrintDelim (int dbevindex) | |
3647 | { | |
3648 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3649 | if (dbev == NULL) | |
3650 | abort (); | |
3651 | return (dbev->get_printdelimiter ()); | |
3652 | } | |
3653 | ||
3654 | // Set Source/Object/Load-Object file names | |
3655 | static void | |
3656 | set_file_names (Function *func, char *names[3]) | |
3657 | { | |
3658 | Module *module = func->module; | |
3659 | LoadObject *loadobject = module->loadobject; | |
3660 | if (loadobject == NULL) | |
3661 | loadobject = dbeSession->get_Unknown_LoadObject (); | |
3662 | free (names[0]); | |
3663 | free (names[1]); | |
3664 | free (names[2]); | |
3665 | SourceFile *sf = func->getDefSrc (); | |
3666 | char *src_name = sf->dbeFile->get_location_info (); | |
3667 | DbeFile *df = module->dbeFile; | |
3668 | if (df == NULL || (df->filetype & DbeFile::F_JAVACLASS) == 0) | |
3669 | df = module->loadobject->dbeFile; | |
3670 | char *lo_name = df->get_location_info (); | |
3671 | char *dot_o_name = lo_name; | |
3672 | if (module->dot_o_file) | |
3673 | dot_o_name = module->dot_o_file->dbeFile->get_location_info (); | |
3674 | names[0] = dbe_sprintf (NTXT ("%s: %s"), GTXT ("Source File"), src_name); | |
3675 | names[1] = dbe_sprintf (NTXT ("%s: %s"), GTXT ("Object File"), dot_o_name); | |
3676 | names[2] = dbe_sprintf (NTXT ("%s: %s"), GTXT ("Load Object"), lo_name); | |
3677 | } | |
3678 | ||
3679 | // dbeSetFuncData | |
3680 | // Master function to generate all Tab data for the analyzer | |
3681 | // Returns the index of the selected item in the specified list | |
3682 | // | |
3683 | // After calling it to set up, the Analyzer calls dbeGetFuncList | |
3684 | // to format the generated data and return the table | |
3685 | // Most of the data is destined for a JTable | |
3686 | // | |
3687 | int | |
3688 | dbeSetFuncData (int dbevindex, Obj sel_obj, int type, int subtype) | |
3689 | { | |
3690 | MetricList *_mlist; | |
3691 | Histable *org_obj; | |
3692 | Hist_data *data = NULL; | |
3693 | int index, sel_index; | |
3694 | Function *func; | |
3695 | char *name; | |
3696 | int ix; | |
3697 | ||
3698 | DbeView *dbev = dbeSession->getView (dbevindex); | |
3699 | sel_index = -1; | |
3700 | dbev->resetOmpDisMode (); | |
3701 | dbev->error_msg = dbev->warning_msg = NULL; | |
3702 | ||
3703 | // get metric list, make a compact duplicate | |
3704 | _mlist = dbev->get_metric_list (MET_NORMAL); | |
3705 | MetricList *mlist = new MetricList (_mlist); | |
3706 | ||
3707 | // Remove old function/obj list data & Get new function/obj list data | |
3708 | org_obj = (Histable *) sel_obj; | |
3709 | ||
3710 | // Figure out which "function" data is being asked for, i.e., | |
3711 | // which of the analyzer displays is asking for data | |
3712 | switch (type) | |
3713 | { | |
3714 | // the various tables: functions, lines, PCs, DataObjects, IndexObjects | |
3715 | case DSP_FUNCTION: | |
3716 | case DSP_LINE: | |
3717 | case DSP_PC: | |
3718 | case DSP_DATAOBJ: | |
3719 | case DSP_MEMOBJ: | |
3720 | case DSP_INDXOBJ: | |
3721 | switch (type) | |
3722 | { | |
3723 | case DSP_FUNCTION: | |
3724 | if (dbev->func_data) | |
3725 | delete dbev->func_data; | |
3726 | dbev->func_data = data = dbev->get_hist_data (mlist, | |
3727 | Histable::FUNCTION, subtype, Hist_data::ALL); | |
3728 | break; | |
3729 | case DSP_LINE: | |
3730 | if (dbev->line_data) | |
3731 | delete dbev->line_data; | |
3732 | dbev->line_data = data = dbev->get_hist_data (mlist, | |
3733 | Histable::LINE, subtype, Hist_data::ALL); | |
3734 | break; | |
3735 | case DSP_PC: | |
3736 | if (dbev->pc_data) | |
3737 | delete dbev->pc_data; | |
3738 | dbev->pc_data = data = dbev->get_hist_data (mlist, | |
3739 | Histable::INSTR, subtype, Hist_data::ALL); | |
3740 | break; | |
3741 | case DSP_DATAOBJ: | |
3742 | if (dbev->dobj_data) | |
3743 | delete dbev->dobj_data; | |
3744 | mlist = dbev->get_metric_list (MET_DATA); | |
3745 | dbev->dobj_data = data = dbev->get_hist_data (mlist, | |
3746 | Histable::DOBJECT, subtype, Hist_data::ALL); | |
3747 | break; | |
3748 | case DSP_MEMOBJ: | |
3749 | mlist = dbev->get_metric_list (MET_DATA); | |
3750 | data = dbev->get_hist_data (mlist, Histable::MEMOBJ, subtype, | |
3751 | Hist_data::ALL); | |
3752 | dbev->indx_data->store (subtype, data); | |
3753 | break; | |
3754 | case DSP_INDXOBJ: | |
3755 | mlist = dbev->get_metric_list (MET_INDX); | |
3756 | data = dbev->get_hist_data (mlist, Histable::INDEXOBJ, subtype, | |
3757 | Hist_data::ALL); | |
3758 | dbev->indx_data->store (subtype, data); | |
3759 | break; | |
3760 | default: | |
3761 | break; | |
3762 | } | |
3763 | ||
3764 | // Set the selection of row item | |
3765 | if (data->get_status () == Hist_data::SUCCESS) | |
3766 | { | |
3767 | // otherwise, look for it | |
3768 | sel_index = -1; | |
3769 | if (org_obj) | |
3770 | { | |
3771 | Hist_data::HistItem *hi; | |
3772 | Vec_loop (Hist_data::HistItem*, data->get_hist_items (), index, hi) | |
3773 | { | |
3774 | if (hi->obj == org_obj) | |
3775 | { | |
3776 | sel_index = index; | |
3777 | break; | |
3778 | } | |
3779 | } | |
3780 | if (sel_index == -1 && (type == DSP_LINE || type == DSP_PC)) | |
3781 | { | |
3782 | Vec_loop (Hist_data::HistItem*, data->get_hist_items (), index, hi) | |
3783 | { | |
3784 | name = hi->obj->get_name (); | |
3785 | if (strcmp (name, NTXT ("<Total>")) && | |
3786 | strcmp (name, GTXT ("<Unknown>"))) | |
3787 | { | |
3788 | int done = 0; | |
3789 | switch (type) | |
3790 | { | |
3791 | case DSP_LINE: | |
3792 | if (org_obj->convertto (Histable::FUNCTION) | |
3793 | == hi->obj->convertto (Histable::FUNCTION)) | |
3794 | { | |
3795 | sel_index = index; | |
3796 | done = 1; | |
3797 | } | |
3798 | break; | |
3799 | case DSP_PC: | |
3800 | if (hi->obj->convertto (Histable::FUNCTION) | |
3801 | == org_obj->convertto (Histable::FUNCTION) | |
3802 | && ((DbeLine*) hi->obj->convertto (Histable::LINE))->lineno | |
3803 | == ((DbeLine*) org_obj->convertto (Histable::LINE))->lineno) | |
3804 | { | |
3805 | sel_index = index; | |
3806 | done = 1; | |
3807 | } | |
3808 | break; | |
3809 | } | |
3810 | if (done) | |
3811 | break; | |
3812 | } | |
3813 | } | |
3814 | } | |
3815 | if (sel_index == -1 && type == DSP_PC) | |
3816 | { | |
3817 | Vec_loop (Hist_data::HistItem*, data->get_hist_items (), index, hi) | |
3818 | { | |
3819 | name = hi->obj->get_name (); | |
3820 | if (strcmp (name, NTXT ("<Total>")) && | |
3821 | strcmp (name, GTXT ("<Unknown>"))) | |
3822 | { | |
3823 | int done = 0; | |
3824 | if (hi->obj->convertto (Histable::FUNCTION) == | |
3825 | org_obj->convertto (Histable::FUNCTION)) | |
3826 | { | |
3827 | sel_index = index; | |
3828 | done = 1; | |
3829 | } | |
3830 | if (done) | |
3831 | break; | |
3832 | } | |
3833 | } | |
3834 | } | |
3835 | } | |
3836 | if (sel_index == -1) | |
3837 | { | |
3838 | Hist_data::HistItem *hi; | |
3839 | Vec_loop (Hist_data::HistItem*, data->get_hist_items (), index, hi) | |
3840 | { | |
3841 | name = hi->obj->get_name (); | |
3842 | if (strcmp (name, NTXT ("<Total>")) && | |
3843 | strcmp (name, GTXT ("<Unknown>"))) | |
3844 | { | |
3845 | sel_index = index; | |
3846 | break; | |
3847 | } | |
3848 | } | |
3849 | } | |
3850 | } | |
3851 | else | |
3852 | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA); | |
3853 | return sel_index; | |
3854 | // the end of the code for the regular tables | |
3855 | ||
3856 | // Data Layout | |
3857 | case DSP_DLAYOUT: | |
3858 | if (dbev->dlay_data) | |
3859 | delete dbev->dlay_data; | |
3860 | dbev->marks->reset (); | |
3861 | mlist = dbev->get_metric_list (MET_DATA); | |
3862 | ||
3863 | // initial dobj list ... | |
3864 | data = dbev->get_hist_data (mlist, Histable::DOBJECT, subtype, | |
3865 | Hist_data::LAYOUT); | |
3866 | // .. provides metric data for layout | |
3867 | dbev->dlay_data = data = dbev->get_data_space ()->get_layout_data (data, | |
3868 | dbev->marks, dbev->get_thresh_dis ()); | |
3869 | if (data->get_status () != Hist_data::SUCCESS) | |
3870 | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA); | |
3871 | return sel_index; | |
3872 | ||
3873 | // Source or disassembly | |
3874 | case DSP_SOURCE_V2: | |
3875 | case DSP_DISASM_V2: | |
3876 | case DSP_SOURCE: | |
3877 | case DSP_DISASM: | |
3878 | { | |
3879 | if (org_obj == NULL) | |
3880 | { | |
3881 | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_SEL_OBJ); | |
3882 | return sel_index; | |
3883 | } | |
3884 | if (org_obj->get_type () != Histable::FUNCTION) | |
3885 | { | |
3886 | dbev->error_msg = dbe_strdup ( | |
3887 | GTXT ("Not a real function; no source or disassembly available.")); | |
3888 | return sel_index; | |
3889 | } | |
3890 | func = (Function *) org_obj; | |
3891 | if (func->flags & FUNC_FLAG_SIMULATED) | |
3892 | { | |
3893 | dbev->error_msg = dbe_strdup ( | |
3894 | GTXT ("Not a real function; no source or disassembly available.")); | |
3895 | return sel_index; | |
3896 | } | |
3897 | if (func->get_name () == NULL) | |
3898 | { | |
3899 | dbev->error_msg = dbe_strdup ( | |
3900 | GTXT ("Source location not recorded in experiment")); | |
3901 | return sel_index; | |
3902 | } | |
3903 | Module *module = func->module; | |
3904 | if ((module == NULL) || (module->get_name () == NULL)) | |
3905 | { | |
3906 | dbev->error_msg = dbe_strdup ( | |
3907 | GTXT ("Object name not recorded in experiment")); | |
3908 | return sel_index; | |
3909 | } | |
3910 | ix = module->loadobject->seg_idx; | |
3911 | if (dbev->get_lo_expand (ix) == LIBEX_HIDE) | |
3912 | { | |
3913 | dbev->error_msg = dbe_strdup ( | |
3914 | GTXT ("No source or disassembly available for hidden object")); | |
3915 | return sel_index; | |
3916 | } | |
3917 | ||
3918 | if ((type == DSP_DISASM || type == DSP_DISASM_V2) | |
3919 | && dbev->get_view_mode () == VMODE_USER | |
3920 | && dbeSession->is_omp_available ()) | |
3921 | dbev->setOmpDisMode (); | |
3922 | ||
3923 | dbev->marks->reset (); | |
3924 | SourceFile *srcContext = NULL; | |
3925 | switch (dbev->sel_obj->get_type ()) | |
3926 | { | |
3927 | case Histable::FUNCTION: | |
3928 | { | |
3929 | Function *f = (Function *) dbev->sel_obj; | |
3930 | srcContext = f->getDefSrc (); | |
3931 | dbev->sel_binctx = f->module; | |
3932 | break; | |
3933 | } | |
3934 | case Histable::LINE: | |
3935 | { | |
3936 | DbeLine *dl = (DbeLine *) dbev->sel_obj; | |
3937 | srcContext = dl->sourceFile; | |
3938 | Function *f = dl->func; | |
3939 | if (f) | |
3940 | dbev->sel_binctx = f; | |
3941 | break; | |
3942 | } | |
3943 | case Histable::INSTR: | |
3944 | { | |
3945 | Function *f = (Function *) dbev->sel_obj->convertto (Histable::FUNCTION); | |
3946 | if (f) | |
3947 | { | |
3948 | dbev->sel_binctx = f; | |
3949 | srcContext = f->getDefSrc (); | |
3950 | } | |
3951 | break; | |
3952 | } | |
3953 | default: | |
3954 | break; | |
3955 | } | |
3956 | mlist = dbev->get_metric_list (MET_SRCDIS); | |
3957 | ||
3958 | // for source and disassembly the name needs to be invisible, | |
3959 | // but that's handled in the module code | |
3960 | if (type == DSP_SOURCE) | |
3961 | { | |
3962 | if (dbev->src_data) | |
3963 | delete dbev->src_data; | |
3964 | ||
3965 | // func_data computation needed for get_totals | |
3966 | if (dbev->func_data == NULL) | |
3967 | dbev->func_data = data = dbev->get_hist_data (mlist, | |
3968 | Histable::FUNCTION, subtype, Hist_data::ALL); | |
3969 | dbev->marks2dsrc->reset (); | |
3970 | dbev->marks2dsrc_inc->reset (); | |
3971 | data = dbev->src_data = module->get_data (dbev, mlist, | |
3972 | Histable::LINE, dbev->func_data->get_totals ()->value, | |
3973 | srcContext, func, dbev->marks, | |
3974 | dbev->get_thresh_src (), dbev->get_src_compcom (), | |
3975 | dbev->get_src_visible (), dbev->get_hex_visible (), | |
3976 | false, false, dbev->marks2dsrc, dbev->marks2dsrc_inc); | |
3977 | set_file_names (func, dbev->names_src); | |
3978 | if (srcContext) | |
3979 | { | |
3980 | free (dbev->names_src[0]); | |
3981 | dbev->names_src[0] = dbe_sprintf (GTXT ("Source File: %s"), | |
3982 | srcContext->dbeFile->get_location_info ()); | |
3983 | } | |
3984 | Obj obj = (Obj) func->convertto (Histable::LINE, srcContext); | |
3985 | sel_index = dbeGetSelIndex (dbevindex, obj, type, subtype); | |
3986 | } | |
3987 | else | |
3988 | { /* type == DSP_DISASM */ | |
3989 | if (dbev->dis_data) | |
3990 | delete dbev->dis_data; | |
3991 | ||
3992 | // func_data computation needed for get_totals | |
3993 | if (dbev->func_data == NULL) | |
3994 | dbev->func_data = data = dbev->get_hist_data (mlist, | |
3995 | Histable::FUNCTION, subtype, Hist_data::ALL); | |
3996 | dbev->marks2ddis->reset (); | |
3997 | dbev->marks2ddis_inc->reset (); | |
3998 | data = dbev->dis_data = module->get_data (dbev, mlist, | |
3999 | Histable::INSTR, dbev->func_data->get_totals ()->value, | |
4000 | srcContext, func, dbev->marks, dbev->get_thresh_dis (), | |
4001 | dbev->get_dis_compcom (), dbev->get_src_visible (), | |
4002 | dbev->get_hex_visible (), dbev->get_func_scope (), | |
4003 | false, dbev->marks2ddis, dbev->marks2ddis_inc); | |
4004 | set_file_names (func, dbev->names_dis); | |
4005 | if (srcContext) | |
4006 | { | |
4007 | free (dbev->names_dis[0]); | |
4008 | dbev->names_dis[0] = dbe_sprintf (GTXT ("Source File: %s"), | |
4009 | srcContext->dbeFile->get_location_info ()); | |
4010 | } | |
4011 | Obj obj = (Obj) func->convertto (Histable::INSTR); | |
4012 | sel_index = dbeGetSelIndex (dbevindex, obj, type, subtype); | |
4013 | } | |
4014 | return sel_index; | |
4015 | } | |
4016 | ||
4017 | // the three cases for caller-callee | |
4018 | case DSP_SELF: | |
4019 | case DSP_CALLER: | |
4020 | case DSP_CALLEE: | |
4021 | if (org_obj == NULL) | |
4022 | { | |
4023 | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_SEL_OBJ); | |
4024 | return sel_index; | |
4025 | } | |
4026 | ||
4027 | // Caller data | |
4028 | if (dbev->callers) | |
4029 | delete dbev->callers; | |
4030 | mlist = dbev->get_metric_list (MET_CALL); | |
4031 | dbev->callers = dbev->get_hist_data (mlist, Histable::FUNCTION, subtype, | |
4032 | Hist_data::CALLERS, org_obj); | |
4033 | if (dbev->callers->get_status () != Hist_data::SUCCESS) | |
4034 | { | |
4035 | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA); | |
4036 | return sel_index; | |
4037 | } | |
4038 | ||
4039 | // Callee data | |
4040 | if (dbev->callees) | |
4041 | delete dbev->callees; | |
4042 | dbev->callees = dbev->get_hist_data (mlist, Histable::FUNCTION, subtype, | |
4043 | Hist_data::CALLEES, org_obj); | |
4044 | if (dbev->callees->get_status () != Hist_data::SUCCESS) | |
4045 | { | |
4046 | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA); | |
4047 | return sel_index; | |
4048 | } | |
4049 | ||
4050 | // Center Function item | |
4051 | if (dbev->fitem_data) | |
4052 | delete dbev->fitem_data; | |
4053 | dbev->fitem_data = dbev->get_hist_data (mlist, Histable::FUNCTION, subtype, | |
4054 | Hist_data::SELF, org_obj); | |
4055 | if (dbev->fitem_data->get_status () != Hist_data::SUCCESS) | |
4056 | { | |
4057 | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA); | |
4058 | return sel_index; | |
4059 | } | |
4060 | return sel_index; | |
4061 | default: | |
4062 | abort (); | |
4063 | } | |
4064 | return sel_index; | |
4065 | } | |
4066 | ||
4067 | Vector<void*>* | |
4068 | dbeGetTotals (int dbevindex, int dsptype, int subtype) | |
4069 | { | |
4070 | DbeView *dbev = dbeSession->getView (dbevindex); | |
4071 | MetricList *mlist = dbev->get_metric_list (dsptype, subtype); | |
4072 | Hist_data *data = dbev->get_hist_data (mlist, Histable::FUNCTION, 0, | |
4073 | Hist_data::ALL); | |
4074 | Hist_data::HistItem *totals = data->get_totals (); | |
4075 | Vector<void*> *tbl = new Vector<void*>(mlist->size ()); | |
4076 | for (long i = 0, sz = mlist->size (); i < sz; i++) | |
4077 | { | |
4078 | Metric *m = mlist->get (i); | |
4079 | switch (m->get_vtype ()) | |
4080 | { | |
4081 | case VT_DOUBLE: | |
4082 | { | |
4083 | Vector<double> *lst = new Vector<double>(1); | |
4084 | lst->append (totals->value[i].d); | |
4085 | tbl->append (lst); | |
4086 | break; | |
4087 | } | |
4088 | case VT_INT: | |
4089 | { | |
4090 | Vector<int> *lst = new Vector<int>(1); | |
4091 | lst->append (totals->value[i].i); | |
4092 | tbl->append (lst); | |
4093 | break; | |
4094 | } | |
4095 | case VT_LLONG: | |
4096 | case VT_ULLONG: | |
4097 | case VT_ADDRESS: | |
4098 | { | |
4099 | Vector<long long> *lst = new Vector<long long>(1); | |
4100 | lst->append (totals->value[i].ll); | |
4101 | tbl->append (lst); | |
4102 | break; | |
4103 | } | |
4104 | case VT_LABEL: | |
4105 | { | |
4106 | Vector<char *> *lst = new Vector<char *>(1); | |
4107 | Histable::NameFormat nfmt = dbev->get_name_format (); | |
4108 | lst->append (dbe_strdup (totals->obj->get_name (nfmt))); | |
4109 | tbl->append (lst); | |
4110 | break; | |
4111 | } | |
4112 | default: | |
4113 | abort (); | |
4114 | } | |
4115 | } | |
4116 | Vector<void*> *res = new Vector<void*>(2); | |
4117 | res->append (dbeGetMetricList (mlist)); | |
4118 | res->append (tbl); | |
4119 | return res; | |
4120 | } | |
4121 | ||
4122 | Vector<void*>* | |
4123 | dbeGetHotMarks (int dbevindex, int type) | |
4124 | { | |
4125 | Vector<void*>* table = new Vector<void*>(2); | |
4126 | Vector<int>* table0 = new Vector<int> (); | |
4127 | Vector<int>* table1 = new Vector<int> (); | |
4128 | DbeView *dbev = dbeSession->getView (dbevindex); | |
4129 | if (dbev == NULL) | |
4130 | return NULL; | |
4131 | ||
4132 | switch (type) | |
4133 | { | |
4134 | case DSP_SOURCE: | |
4135 | case DSP_SOURCE_V2: | |
4136 | for (int i = 0; i < dbev->marks2dsrc->size (); i++) | |
4137 | { | |
4138 | table0->append (dbev->marks2dsrc->fetch (i).index1); | |
4139 | table1->append (dbev->marks2dsrc->fetch (i).index2); | |
4140 | } | |
4141 | break; | |
4142 | case DSP_DISASM: | |
4143 | case DSP_DISASM_V2: | |
4144 | for (int i = 0; i < dbev->marks2ddis->size (); i++) | |
4145 | { | |
4146 | table0->append (dbev->marks2ddis->fetch (i).index1); | |
4147 | table1->append (dbev->marks2ddis->fetch (i).index2); | |
4148 | } | |
4149 | break; | |
4150 | default: | |
4151 | break; | |
4152 | } | |
4153 | table->store (0, table0); | |
4154 | table->store (1, table1); | |
4155 | return table; | |
4156 | } | |
4157 | ||
4158 | Vector<void*>* | |
4159 | dbeGetHotMarksInc (int dbevindex, int type) | |
4160 | { | |
4161 | Vector<void*>* table = new Vector<void*>(2); | |
4162 | Vector<int>* table0 = new Vector<int> (); | |
4163 | Vector<int>* table1 = new Vector<int> (); | |
4164 | DbeView *dbev = dbeSession->getView (dbevindex); | |
4165 | if (dbev == NULL) | |
4166 | return NULL; | |
4167 | ||
4168 | switch (type) | |
4169 | { | |
4170 | case DSP_SOURCE: | |
4171 | case DSP_SOURCE_V2: | |
4172 | for (int i = 0; i < dbev->marks2dsrc_inc->size (); i++) | |
4173 | { | |
4174 | table0->append (dbev->marks2dsrc_inc->fetch (i).index1); | |
4175 | table1->append (dbev->marks2dsrc_inc->fetch (i).index2); | |
4176 | } | |
4177 | break; | |
4178 | case DSP_DISASM: | |
4179 | case DSP_DISASM_V2: | |
4180 | for (int i = 0; i < dbev->marks2ddis_inc->size (); i++) | |
4181 | { | |
4182 | table0->append (dbev->marks2ddis_inc->fetch (i).index1); | |
4183 | table1->append (dbev->marks2ddis_inc->fetch (i).index2); | |
4184 | } | |
4185 | break; | |
4186 | default: | |
4187 | break; | |
4188 | } | |
4189 | table->store (0, table0); | |
4190 | table->store (1, table1); | |
4191 | return table; | |
4192 | } | |
4193 | ||
4194 | Vector<void*>* | |
4195 | dbeGetSummaryHotMarks (int dbevindex, Vector<Obj> *sel_objs, int type) | |
4196 | { | |
4197 | Vector<void*>* table = new Vector<void*>(2); | |
4198 | Vector<int>* table0 = new Vector<int> (); | |
4199 | Vector<int>* table1 = new Vector<int> (); | |
4200 | DbeView *dbev = dbeSession->getView (dbevindex); | |
4201 | if (dbev == NULL) | |
4202 | return NULL; | |
4203 | if (sel_objs == NULL || sel_objs->size () == 0) | |
4204 | return NULL; | |
4205 | ||
4206 | Hist_data *data; | |
4207 | Vector<int_pair_t> *marks2d; | |
4208 | Vector<int_pair_t>* marks2d_inc; | |
4209 | switch (type) | |
4210 | { | |
4211 | case DSP_SOURCE: | |
4212 | case DSP_SOURCE_V2: | |
4213 | data = dbev->src_data; | |
4214 | marks2d = dbev->marks2dsrc; | |
4215 | marks2d_inc = dbev->marks2dsrc_inc; | |
4216 | break; | |
4217 | case DSP_DISASM: | |
4218 | case DSP_DISASM_V2: | |
4219 | data = dbev->dis_data; | |
4220 | marks2d = dbev->marks2ddis; | |
4221 | marks2d_inc = dbev->marks2ddis_inc; | |
4222 | break; | |
4223 | default: | |
4224 | data = NULL; | |
4225 | marks2d = NULL; | |
4226 | marks2d_inc = NULL; | |
4227 | break; | |
4228 | } | |
4229 | if (data == NULL || data->get_status () != Hist_data::SUCCESS | |
4230 | || marks2d_inc == NULL || marks2d == NULL) | |
4231 | return NULL; | |
4232 | ||
4233 | MetricList *orig_mlist = data->get_metric_list (); | |
4234 | MetricList *prop_mlist = new MetricList (dbev->get_metric_ref (MET_NORMAL)); | |
4235 | if (prop_mlist && dbev->comparingExperiments ()) | |
4236 | prop_mlist = dbev->get_compare_mlist (prop_mlist, 0); | |
4237 | Metric *mitem; | |
4238 | int index, index2; | |
4239 | index2 = 0; | |
4240 | Vec_loop (Metric*, prop_mlist->get_items (), index, mitem) | |
4241 | { | |
4242 | if (mitem->get_subtype () == Metric::STATIC) | |
4243 | continue; | |
4244 | ||
4245 | for (int i = 0; i < marks2d_inc->size (); i++) | |
4246 | { | |
4247 | int found = 0; | |
4248 | for (int j = 0; j < sel_objs->size (); j++) | |
4249 | { | |
4250 | int sel_index = (int) sel_objs->fetch (j); | |
4251 | int marked_index = marks2d_inc->fetch (i).index1; | |
4252 | if (sel_index == marked_index) | |
4253 | { | |
4254 | found = 1; | |
4255 | break; | |
4256 | } | |
4257 | } | |
4258 | if (!found) | |
4259 | continue; | |
4260 | int mindex = marks2d_inc->fetch (i).index2; | |
4261 | Metric *orig_metric = orig_mlist->get_items ()->fetch (mindex); | |
4262 | if (orig_metric->get_id () == mitem->get_id () | |
4263 | && mitem->get_subtype () == Metric::INCLUSIVE) | |
4264 | { | |
4265 | table0->append (index2); | |
4266 | table1->append (1); | |
4267 | } | |
4268 | } | |
4269 | ||
4270 | for (int i = 0; i < marks2d->size (); i++) | |
4271 | { | |
4272 | int found = 0; | |
4273 | for (int j = 0; j < sel_objs->size (); j++) | |
4274 | { | |
4275 | int sel_index = (int) sel_objs->fetch (j); | |
4276 | int marked_index = marks2d->fetch (i).index1; | |
4277 | if (sel_index == marked_index) | |
4278 | { | |
4279 | found = 1; | |
4280 | break; | |
4281 | } | |
4282 | } | |
4283 | if (!found) | |
4284 | continue; | |
4285 | int mindex = marks2d->fetch (i).index2; | |
4286 | Metric *orig_metric = orig_mlist->get_items ()->fetch (mindex); | |
4287 | if (orig_metric->get_id () == mitem->get_id () | |
4288 | && mitem->get_subtype () == Metric::EXCLUSIVE) | |
4289 | { | |
4290 | table0->append (index2); | |
4291 | table1->append (0); | |
4292 | } | |
4293 | } | |
4294 | if (!(mitem->get_subtype () == Metric::EXCLUSIVE | |
4295 | || mitem->get_subtype () == Metric::DATASPACE)) | |
4296 | index2++; | |
4297 | } | |
4298 | table->store (0, table0); | |
4299 | table->store (1, table1); | |
4300 | return table; | |
4301 | } | |
4302 | ||
4303 | // Get a vector of function ids of data(begin, begin + length - 1) | |
4304 | // Currently only support source/disassembly view | |
4305 | Vector<uint64_t>* | |
4306 | dbeGetFuncId (int dbevindex, int type, int begin, int length) | |
4307 | { | |
4308 | Vector<uint64_t>* table = new Vector<uint64_t > (); | |
4309 | DbeView *dbev = dbeSession->getView (dbevindex); | |
4310 | if (dbev == NULL) | |
4311 | abort (); | |
4312 | ||
4313 | Hist_data *data; | |
4314 | Function* given_func = NULL; | |
4315 | switch (type) | |
4316 | { | |
4317 | case DSP_SOURCE: | |
4318 | case DSP_SOURCE_V2: | |
4319 | data = dbev->src_data; | |
4320 | break; | |
4321 | case DSP_DISASM: | |
4322 | case DSP_DISASM_V2: | |
4323 | data = dbev->dis_data; | |
4324 | break; | |
4325 | default: | |
4326 | data = NULL; | |
4327 | abort (); | |
4328 | } | |
4329 | ||
4330 | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | |
4331 | return NULL; | |
4332 | ||
4333 | if (begin < 0 || begin + length > data->size ()) | |
4334 | return NULL; | |
4335 | ||
4336 | switch (type) | |
4337 | { | |
4338 | case DSP_SOURCE: | |
4339 | case DSP_SOURCE_V2: | |
4340 | case DSP_DISASM: | |
4341 | case DSP_DISASM_V2: | |
4342 | { | |
4343 | for (int i = begin; i < begin + length; i++) | |
4344 | { | |
4345 | given_func = NULL; | |
4346 | Histable * sel_obj = data->fetch (i)->obj; | |
4347 | if (sel_obj != NULL) | |
4348 | given_func = (Function*) (sel_obj)->convertto (Histable::FUNCTION, (Histable*) dbev); | |
4349 | if (given_func == NULL) | |
4350 | table->append (0); | |
4351 | else | |
4352 | table->append (given_func->id); | |
4353 | } | |
4354 | } | |
4355 | break; | |
4356 | default: | |
4357 | abort (); | |
4358 | } | |
4359 | return table; | |
4360 | } | |
4361 | ||
4362 | Vector<void*>* | |
4363 | dbeGetFuncCallerInfo (int dbevindex, int type, Vector<int>* idxs, int groupId) | |
4364 | { | |
4365 | Vector<void*>* data = new Vector<void*>(); | |
4366 | if (type == DSP_SOURCE_V2 || type == DSP_DISASM_V2) | |
4367 | { | |
4368 | Obj sel_func = dbeGetSelObj (dbevindex, DSP_FUNCTION, 0); | |
4369 | if (sel_func == 0) | |
4370 | return data; | |
4371 | Vector<Obj> * cmpObjs = dbeGetComparableObjsV2 (dbevindex, sel_func, type); | |
4372 | if (cmpObjs == NULL) | |
4373 | return data; | |
4374 | DbeView *dbev = dbeSession->getView (dbevindex); | |
4375 | int mtype = MET_COMMON | COMPARE_BIT | ((groupId + 1) << GROUP_ID_SHIFT); | |
4376 | MetricList *mlist = dbev->get_metric_list ((MetricType) (mtype & MTYPE_MASK), | |
4377 | (mtype & COMPARE_BIT) != 0, | |
4378 | mtype >> GROUP_ID_SHIFT); | |
4379 | Histable *selObj = (Histable *) cmpObjs->fetch (groupId); | |
4380 | int subtype = 0; | |
4381 | Hist_data *hist_data = dbev->get_data (mlist, selObj, type, subtype); | |
4382 | if (hist_data == NULL) | |
4383 | return data; | |
4384 | } | |
4385 | for (int i = 0; i < idxs->size (); i++) | |
4386 | data->append (dbeGetFuncCallerInfoById (dbevindex, type, idxs->fetch (i))); | |
4387 | return data; | |
4388 | } | |
4389 | ||
4390 | // | |
4391 | // Get Table of Caller info: | |
4392 | // param: idx -- selected AT_FUNC row | |
4393 | // return: callsite_id, callsite_name (function: file: line) | |
4394 | Vector<void*>* | |
4395 | dbeGetFuncCallerInfoById (int dbevindex, int type, int idx) | |
4396 | { | |
4397 | Vector<void*>* table = new Vector<void*>(3); | |
4398 | Vector<uint64_t>* table0 = new Vector<uint64_t> (); | |
4399 | Vector<int>* table1 = new Vector<int> (); | |
4400 | Vector<char*>* table2 = new Vector<char*>(); | |
4401 | ||
4402 | DbeView *dbev = dbeSession->getView (dbevindex); | |
4403 | if (dbev == NULL) | |
4404 | abort (); | |
4405 | Hist_data *data; | |
4406 | Function* given_func = NULL; | |
4407 | Vector<Histable*> *instr_info = NULL; | |
4408 | switch (type) | |
4409 | { | |
4410 | case DSP_SOURCE: | |
4411 | case DSP_SOURCE_V2: | |
4412 | data = dbev->src_data; | |
4413 | break; | |
4414 | case DSP_DISASM: | |
4415 | case DSP_DISASM_V2: | |
4416 | data = dbev->dis_data; | |
4417 | break; | |
4418 | default: | |
4419 | data = NULL; | |
4420 | abort (); | |
4421 | } | |
4422 | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | |
4423 | return NULL; | |
4424 | ||
4425 | if (idx < 0 || idx >= data->size ()) | |
4426 | return NULL; | |
4427 | switch (type) | |
4428 | { | |
4429 | case DSP_SOURCE: | |
4430 | case DSP_SOURCE_V2: | |
4431 | case DSP_DISASM: | |
4432 | case DSP_DISASM_V2: | |
4433 | { | |
4434 | Histable * sel_obj = data->fetch (idx)->obj; | |
4435 | if (sel_obj == NULL) | |
4436 | return NULL; | |
4437 | given_func = (Function*) (sel_obj)->convertto (Histable::FUNCTION, (Histable*) dbev); | |
4438 | if (given_func == NULL) | |
4439 | return NULL; | |
4440 | PathTree * ptree = dbev->get_path_tree (); | |
4441 | if (ptree == NULL) | |
4442 | return NULL; | |
4443 | instr_info = ptree->get_clr_instr (given_func); | |
4444 | DefaultMap<uint64_t, int> * line_seen = new DefaultMap<uint64_t, int>(); | |
4445 | for (int j = 0; j < ((Vector<Histable*>*)instr_info)->size (); j++) | |
4446 | { | |
4447 | Histable *instr = ((Vector<Histable*>*)instr_info)->fetch (j); | |
4448 | Function *cur_func = NULL; | |
4449 | if (instr->get_type () == Histable::INSTR) | |
4450 | cur_func = ((DbeInstr*) instr)->func; | |
4451 | else if (instr->get_type () == Histable::LINE) | |
4452 | cur_func = ((DbeLine*) instr)->func; | |
4453 | if (cur_func == NULL || (cur_func->flags & FUNC_FLAG_SIMULATED)) | |
4454 | continue; // skip functions like <Total> | |
4455 | Histable* line; | |
4456 | switch (type) | |
4457 | { | |
4458 | case DSP_SOURCE: | |
4459 | case DSP_SOURCE_V2: | |
4460 | if (cur_func != NULL) | |
4461 | { | |
4462 | SourceFile *sourceFile = cur_func->getDefSrc (); | |
4463 | if (sourceFile == NULL || | |
4464 | (sourceFile->flags & SOURCE_FLAG_UNKNOWN) != 0) | |
4465 | continue; // skip functions like <Function: %s, instructions without line numbers> | |
4466 | } | |
4467 | line = instr->convertto (Histable::LINE, NULL); | |
4468 | break; | |
4469 | case DSP_DISASM: | |
4470 | case DSP_DISASM_V2: | |
4471 | line = instr->convertto (Histable::INSTR, NULL); | |
4472 | break; | |
4473 | default: | |
4474 | abort (); | |
4475 | } | |
4476 | uint64_t func_id = cur_func->id; | |
4477 | uint64_t line_id = instr->id; | |
4478 | int is_null = 0; | |
4479 | int line_no = -1; | |
4480 | switch (type) | |
4481 | { | |
4482 | case DSP_SOURCE: | |
4483 | case DSP_SOURCE_V2: | |
4484 | is_null = (((DbeLine*) line)->func == NULL) ? 1 : 0; | |
4485 | if (is_null) | |
4486 | ((DbeLine*) line)->func = cur_func; | |
4487 | line_no = ((DbeLine*) line)->lineno; | |
4488 | if (line_seen->get (line_id) == 0) | |
4489 | { | |
4490 | line_seen->put (line_id, 1); | |
4491 | table0->append (func_id); | |
4492 | table1->append (line_no); | |
4493 | Histable::NameFormat nfmt = dbev->get_name_format (); | |
4494 | table2->append (dbe_strdup (line->get_name (nfmt))); | |
4495 | } | |
4496 | if (is_null) | |
4497 | ((DbeLine*) line)->func = NULL; | |
4498 | break; | |
4499 | case DSP_DISASM: | |
4500 | case DSP_DISASM_V2: | |
4501 | is_null = (((DbeInstr*) line)->func == NULL) ? 1 : 0; | |
4502 | if (is_null) | |
4503 | ((DbeInstr*) line)->func = cur_func; | |
4504 | line_no = ((DbeInstr*) line)->addr; | |
4505 | if (line_seen->get (line_id) == 0) | |
4506 | { | |
4507 | line_seen->put (line_id, 1); | |
4508 | table0->append (func_id); | |
4509 | table1->append (line_no); | |
4510 | Histable::NameFormat nfmt = dbev->get_name_format (); | |
4511 | table2->append (dbe_strdup (line->get_name (nfmt))); | |
4512 | } | |
4513 | if (is_null) | |
4514 | ((DbeInstr*) line)->func = NULL; | |
4515 | break; | |
4516 | default: | |
4517 | abort (); | |
4518 | } | |
4519 | } | |
4520 | delete line_seen; | |
4521 | delete instr_info; | |
4522 | } | |
4523 | break; | |
4524 | default: | |
4525 | abort (); | |
4526 | } | |
4527 | table->store (0, table0); | |
4528 | table->store (1, table1); | |
4529 | table->store (2, table2); | |
4530 | return table; | |
4531 | } | |
4532 | ||
4533 | Vector<void*>* | |
4534 | dbeGetFuncCalleeInfo (int dbevindex, int type, Vector<int>* idxs, int groupId) | |
4535 | { | |
4536 | Vector<void*>* data = new Vector<void*>(); | |
4537 | if (type == DSP_SOURCE_V2 || type == DSP_DISASM_V2) | |
4538 | { | |
4539 | Obj sel_func = dbeGetSelObj (dbevindex, DSP_FUNCTION, 0); | |
4540 | if (sel_func == 0) | |
4541 | return data; | |
4542 | Vector<Obj> * cmpObjs = dbeGetComparableObjsV2 (dbevindex, sel_func, type); | |
4543 | if (cmpObjs == NULL) | |
4544 | return data; | |
4545 | DbeView *dbev = dbeSession->getView (dbevindex); | |
4546 | int mtype = MET_COMMON | COMPARE_BIT | ((groupId + 1) << GROUP_ID_SHIFT); | |
4547 | MetricList *mlist = dbev->get_metric_list ((MetricType) (mtype & MTYPE_MASK), | |
4548 | (mtype & COMPARE_BIT) != 0, | |
4549 | mtype >> GROUP_ID_SHIFT); | |
4550 | Histable *selObj = (Histable *) cmpObjs->fetch (groupId); | |
4551 | int subtype = 0; | |
4552 | Hist_data *hist_data = dbev->get_data (mlist, selObj, type, subtype); | |
4553 | if (hist_data == NULL) | |
4554 | return data; | |
4555 | } | |
4556 | ||
4557 | for (int i = 0; i < idxs->size (); i++) | |
4558 | data->append (dbeGetFuncCalleeInfoById (dbevindex, type, idxs->fetch (i))); | |
4559 | return data; | |
4560 | } | |
4561 | ||
4562 | // | |
4563 | // Get Table of Callee info: | |
4564 | // param: idx -- selected AT_FUNC row | |
4565 | // return: callsite_row, callee_id, callee_name | |
4566 | // | |
4567 | Vector<void*>* | |
4568 | dbeGetFuncCalleeInfoById (int dbevindex, int type, int idx) | |
4569 | { | |
4570 | Vector<void*>* table = new Vector<void*>(3); | |
4571 | Vector<int>* table0 = new Vector<int>(); | |
4572 | Vector<uint64_t>* table1 = new Vector<uint64_t > (); | |
4573 | Vector<char*>* table2 = new Vector<char*>(); | |
4574 | DbeView *dbev = dbeSession->getView (dbevindex); | |
4575 | if (dbev == NULL) | |
4576 | abort (); | |
4577 | Hist_data *data; | |
4578 | Function* given_func = NULL; | |
4579 | Vector<Histable*> *instr_info = NULL; | |
4580 | Vector<void*> *func_info = NULL; | |
4581 | ||
4582 | switch (type) | |
4583 | { | |
4584 | case DSP_SOURCE: | |
4585 | case DSP_SOURCE_V2: | |
4586 | data = dbev->src_data; | |
4587 | break; | |
4588 | case DSP_DISASM: | |
4589 | case DSP_DISASM_V2: | |
4590 | data = dbev->dis_data; | |
4591 | break; | |
4592 | default: | |
4593 | data = NULL; | |
4594 | abort (); | |
4595 | } | |
4596 | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | |
4597 | return NULL; | |
4598 | if (idx < 0 || idx >= data->size ()) | |
4599 | return NULL; | |
4600 | switch (type) | |
4601 | { | |
4602 | case DSP_SOURCE: | |
4603 | case DSP_SOURCE_V2: | |
4604 | case DSP_DISASM: | |
4605 | case DSP_DISASM_V2: | |
4606 | { | |
4607 | Histable * sel_obj = data->fetch (idx)->obj; | |
4608 | if (sel_obj == NULL) | |
4609 | return NULL; | |
4610 | given_func = (Function*) (sel_obj)->convertto (Histable::FUNCTION, (Histable*) dbev); | |
4611 | if (given_func == NULL) | |
4612 | return NULL; | |
4613 | PathTree * ptree = dbev->get_path_tree (); | |
4614 | if (ptree == NULL) | |
4615 | return NULL; | |
4616 | Vector<Histable*> *instrs = NULL; | |
4617 | Vector<void*> *callee_instrs = ptree->get_cle_instr (given_func, instrs); | |
4618 | func_info = new Vector<void*>(); | |
4619 | instr_info = new Vector<Histable*>(); | |
4620 | for (long a = 0, sz_a = callee_instrs ? callee_instrs->size () : 0; a < sz_a; a++) | |
4621 | { | |
4622 | Vector<Histable*> *temp = ((Vector<Vector<Histable*>*>*)callee_instrs)->get (a); | |
4623 | DefaultMap<Function*, int> * func_seen = new DefaultMap<Function*, int>(); | |
4624 | Histable* instr0 = (Histable*) instrs->fetch (a); | |
4625 | for (long b = 0, sz_b = temp ? temp->size () : 0; b < sz_b; b++) | |
4626 | { | |
4627 | Histable *instr = temp->get (b); | |
4628 | if (instr->get_type () == Histable::INSTR) | |
4629 | { | |
4630 | Function* func1 = ((DbeInstr *) instr)->func; | |
4631 | func_seen->put (func1, 1); | |
4632 | } | |
4633 | else if (instr->get_type () == Histable::LINE) | |
4634 | { | |
4635 | Function* func1 = ((DbeLine *) instr)->func; | |
4636 | func_seen->put (func1, 1); | |
4637 | } | |
4638 | } | |
4639 | Vector<Function*> *funcs = func_seen->keySet (); | |
4640 | delete func_seen; | |
4641 | if (funcs->size () > 0) | |
4642 | { | |
4643 | instr_info->append (instr0); | |
4644 | func_info->append (funcs); | |
4645 | } | |
4646 | } | |
4647 | delete instrs; | |
4648 | destroy (callee_instrs); | |
4649 | ||
4650 | DefaultMap<uint64_t, Vector<int>* > * instr_idxs = new DefaultMap<uint64_t, Vector<int>* >(); | |
4651 | DefaultMap<uint64_t, int> * func_idxs = new DefaultMap<uint64_t, int>(); | |
4652 | for (long j = 0, sz_j = instr_info ? instr_info->size () : 0; j < sz_j; j++) | |
4653 | { | |
4654 | Histable *instr = instr_info->get (j); | |
4655 | Function *cur_func = NULL; | |
4656 | if (instr->get_type () == Histable::INSTR) | |
4657 | cur_func = ((DbeInstr*) instr)->func; | |
4658 | else if (instr->get_type () == Histable::LINE) | |
4659 | cur_func = ((DbeLine*) instr)->func; | |
4660 | if (cur_func != NULL && (cur_func->flags & FUNC_FLAG_SIMULATED)) | |
4661 | continue; // skip functions like <Total> | |
4662 | Histable* line; | |
4663 | switch (type) | |
4664 | { | |
4665 | case DSP_SOURCE: | |
4666 | case DSP_SOURCE_V2: | |
4667 | if (cur_func != NULL) | |
4668 | { | |
4669 | SourceFile *sourceFile = cur_func->getDefSrc (); | |
4670 | if (sourceFile == NULL || | |
4671 | (sourceFile->flags & SOURCE_FLAG_UNKNOWN) != 0) | |
4672 | // skip functions like <Function: %s, instructions without line numbers> | |
4673 | continue; | |
4674 | } | |
4675 | line = instr->convertto (Histable::LINE, NULL); | |
4676 | if (type == DSP_SOURCE_V2) | |
4677 | line = dbev->get_compare_obj (line); | |
4678 | break; | |
4679 | case DSP_DISASM: | |
4680 | case DSP_DISASM_V2: | |
4681 | line = instr; | |
4682 | if (type == DSP_DISASM_V2) | |
4683 | line = dbev->get_compare_obj (line); | |
4684 | break; | |
4685 | default: | |
4686 | abort (); | |
4687 | } | |
4688 | if (func_idxs->get (line->id) == 0) | |
4689 | { | |
4690 | func_idxs->put (line->id, 1); | |
4691 | Vector<int> *temp_idx = new Vector<int>(); | |
4692 | temp_idx->append (j); | |
4693 | instr_idxs->put (line->id, temp_idx); | |
4694 | } | |
4695 | else | |
4696 | { | |
4697 | Vector<int> *temp_idx = instr_idxs->get (line->id); | |
4698 | temp_idx->append (j); | |
4699 | } | |
4700 | } | |
4701 | for (long i = 0; i < data->size (); i++) | |
4702 | { | |
4703 | Histable* line = data->fetch (i)->obj; | |
4704 | if (line == NULL) | |
4705 | continue; | |
4706 | Vector<int> * instr_idx = instr_idxs->get (line->id); | |
4707 | if (instr_idx == NULL) | |
4708 | continue; | |
4709 | for (long j = 0; j < instr_idx->size (); j++) | |
4710 | { | |
4711 | Vector<void*>* callee_funcs_vec = (Vector<void*>*)func_info; | |
4712 | if (callee_funcs_vec->size () == 0) | |
4713 | continue; | |
4714 | Vector<Function*>* callee_funcs_value = (Vector<Function*>*)callee_funcs_vec->fetch (instr_idx->fetch (j)); | |
4715 | for (int k = 0; callee_funcs_value != NULL && k < callee_funcs_value->size (); k++) | |
4716 | { | |
4717 | uint64_t funcobj_id = ((Function*) callee_funcs_value->fetch (k))->id; | |
4718 | int old_size = table0->size (); | |
4719 | if (old_size > 0 && i == table0->fetch (old_size - 1) | |
4720 | && funcobj_id == table1->fetch (old_size - 1)) | |
4721 | continue; | |
4722 | table0->append (i); | |
4723 | table1->append (funcobj_id); | |
4724 | table2->append (dbe_strdup (((Function*) callee_funcs_value->fetch (k))->get_name ())); | |
4725 | } | |
4726 | } | |
4727 | } | |
4728 | delete instr_idxs; | |
4729 | delete func_idxs; | |
4730 | destroy (func_info); | |
4731 | delete instr_info; | |
4732 | } | |
4733 | break; | |
4734 | default: | |
4735 | abort (); | |
4736 | } | |
4737 | table->store (0, table0); | |
4738 | table->store (1, table1); | |
4739 | table->store (2, table2); | |
4740 | return table; | |
4741 | } | |
4742 | ||
4743 | // | |
4744 | // Get Table of Function List data with only total values | |
4745 | // | |
4746 | Vector<void*> * | |
4747 | dbeGetFuncListMini (int dbevindex, int type, int /*subtype*/) | |
4748 | { | |
4749 | Hist_data *data; | |
4750 | DbeView *dbev = dbeSession->getView (dbevindex); | |
4751 | switch (type) | |
4752 | { | |
4753 | case DSP_FUNCTION: | |
4754 | data = dbev->func_data; | |
4755 | break; | |
4756 | default: | |
4757 | data = NULL; | |
4758 | break; | |
4759 | } | |
4760 | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | |
4761 | return NULL; | |
4762 | ||
4763 | MetricList *mlist = data->get_metric_list (); | |
4764 | ||
4765 | // Get table size: count visible metrics | |
4766 | int nvisible = 0; | |
4767 | for (long i = 0, sz = mlist->size (); i < sz; i++) | |
4768 | { | |
4769 | Metric *m = mlist->get (i); | |
4770 | if (m->is_visible () || m->is_tvisible () || m->is_pvisible ()) | |
4771 | nvisible++; | |
4772 | } | |
4773 | Vector<void*> *table = new Vector<void*>(nvisible + 1); | |
4774 | ||
4775 | // Fill function list elements | |
4776 | Hist_data::HistItem *totals = data->get_totals (); | |
4777 | for (long i = 0, sz = mlist->size (); i < sz; i++) | |
4778 | { | |
4779 | Metric *m = mlist->get (i); | |
4780 | if (!m->is_visible () && !m->is_tvisible () && !m->is_pvisible ()) | |
4781 | continue; | |
4782 | TValue res; | |
4783 | TValue *v = data->get_value (&res, i, totals); | |
4784 | if ((m->get_visbits () & VAL_RATIO) != 0) | |
4785 | { | |
4786 | Vector<double> *col = new Vector<double>(1); | |
4787 | double d = (v->tag != VT_LABEL) ? v->to_double () : 100.; // NaN | |
4788 | col->append (d); | |
4789 | table->append (col); | |
4790 | continue; | |
4791 | } | |
4792 | switch (m->get_vtype ()) | |
4793 | { | |
4794 | case VT_INT: | |
4795 | { | |
4796 | Vector<int> *col = new Vector<int>(1); | |
4797 | col->append (v->i); | |
4798 | table->append (col); | |
4799 | break; | |
4800 | } | |
4801 | case VT_ADDRESS: | |
4802 | case VT_ULLONG: | |
4803 | case VT_LLONG: | |
4804 | { | |
4805 | Vector<long long> *col = new Vector<long long>(1); | |
4806 | col->append (v->ll); | |
4807 | table->append (col); | |
4808 | break; | |
4809 | } | |
4810 | case VT_LABEL: | |
4811 | { | |
4812 | Vector<char *> *col = new Vector<char *>(1); | |
4813 | col->append (dbe_strdup (v->l)); | |
4814 | table->append (col); | |
4815 | break; | |
4816 | } | |
4817 | case VT_DOUBLE: | |
4818 | default: | |
4819 | { | |
4820 | Vector<double> *col = new Vector<double>(1); | |
4821 | col->append (v->d); | |
4822 | table->append (col); | |
4823 | break; | |
4824 | } | |
4825 | } | |
4826 | } | |
4827 | table->append (NULL); | |
4828 | return table; | |
4829 | } | |
4830 | ||
4831 | // Get Table of Function List data | |
4832 | Vector<void*> * | |
4833 | dbeGetFuncList (int dbevindex, int type, int subtype) | |
4834 | { | |
4835 | MetricList *mlist; | |
4836 | Metric *mitem; | |
4837 | int nitems, nvisible; | |
4838 | int index, index2, nv; | |
4839 | char *cell; | |
4840 | Vector<int> *ji_list; | |
4841 | Hist_data *data; | |
4842 | Hist_data::HistItem *item; | |
4843 | ||
4844 | DbeView *dbev = dbeSession->getView (dbevindex); | |
4845 | if (dbev == NULL) | |
4846 | abort (); | |
4847 | ||
4848 | // fprintf(stderr, NTXT("XXX dbeGetFuncList, FuncListDisp_type = %d\n"), type); | |
4849 | switch (type) | |
4850 | { | |
4851 | case DSP_FUNCTION: | |
4852 | data = dbev->func_data; | |
4853 | break; | |
4854 | case DSP_LINE: | |
4855 | data = dbev->line_data; | |
4856 | break; | |
4857 | case DSP_PC: | |
4858 | data = dbev->pc_data; | |
4859 | break; | |
4860 | case DSP_SOURCE: | |
4861 | case DSP_SOURCE_V2: | |
4862 | data = dbev->src_data; | |
4863 | break; | |
4864 | case DSP_DISASM: | |
4865 | case DSP_DISASM_V2: | |
4866 | data = dbev->dis_data; | |
4867 | break; | |
4868 | case DSP_SELF: | |
4869 | data = dbev->fitem_data; | |
4870 | break; | |
4871 | case DSP_CALLER: | |
4872 | data = dbev->callers; | |
4873 | break; | |
4874 | case DSP_CALLEE: | |
4875 | data = dbev->callees; | |
4876 | break; | |
4877 | case DSP_DLAYOUT: | |
4878 | data = dbev->dlay_data; | |
4879 | break; | |
4880 | case DSP_DATAOBJ: | |
4881 | data = dbev->dobj_data; | |
4882 | break; | |
4883 | case DSP_MEMOBJ: | |
4884 | case DSP_INDXOBJ: | |
4885 | data = dbev->get_indxobj_data (subtype); | |
4886 | break; | |
4887 | default: | |
4888 | data = NULL; | |
4889 | break; | |
4890 | } | |
4891 | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | |
4892 | return NULL; | |
4893 | mlist = data->get_metric_list (); | |
4894 | ||
4895 | // Get table size: count visible metrics | |
4896 | nitems = data->size (); | |
4897 | nvisible = 0; | |
4898 | Vec_loop (Metric*, mlist->get_items (), index, mitem) | |
4899 | { | |
4900 | if (mitem->is_visible () || mitem->is_tvisible () || mitem->is_pvisible ()) | |
4901 | nvisible++; | |
4902 | } | |
4903 | ||
4904 | // Initialize Java String array | |
4905 | Vector<void*> *table = new Vector<void*>(nvisible + 1); | |
4906 | ||
4907 | // Mark Hi-value metric items for annotated src/dis/layout | |
4908 | if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_DLAYOUT | |
4909 | || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2) | |
4910 | { | |
4911 | ji_list = new Vector<int>(nitems); | |
4912 | ||
4913 | if (dbev->marks->size () > 0) | |
4914 | index = dbev->marks->fetch (0); | |
4915 | else | |
4916 | index = -1; | |
4917 | int mindex = 0; | |
4918 | for (index2 = 0; index2 < nitems; index2++) | |
4919 | { | |
4920 | item = data->fetch (index2); | |
4921 | if (index2 == index) | |
4922 | { | |
4923 | ji_list->store (index2, -item->type); | |
4924 | if (++mindex < dbev->marks->size ()) | |
4925 | index = dbev->marks->fetch (mindex); | |
4926 | else | |
4927 | index = -1; | |
4928 | } | |
4929 | else | |
4930 | ji_list->store (index2, item->type); | |
4931 | } | |
4932 | table->store (nvisible, ji_list); | |
4933 | } | |
4934 | else | |
4935 | table->store (nvisible, NULL); | |
4936 | ||
4937 | // Fill function list elements | |
4938 | nv = 0; | |
4939 | ||
4940 | Vec_loop (Metric*, mlist->get_items (), index, mitem) | |
4941 | { | |
4942 | if (!mitem->is_visible () && !mitem->is_tvisible () && | |
4943 | !mitem->is_pvisible ()) | |
4944 | continue; | |
4945 | ||
4946 | // Fill values | |
4947 | switch (mitem->get_vtype ()) | |
4948 | { | |
4949 | case VT_LABEL: | |
4950 | { | |
4951 | Vector<char*> *jobjects = new Vector<char*>(nitems); | |
4952 | char *buf = NULL; | |
4953 | size_t bufsz = 0; | |
4954 | int lspace = 0; | |
4955 | if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 | |
4956 | || type == DSP_DISASM_V2) | |
4957 | { | |
4958 | // if this is source or disassembly, where we'll insert | |
4959 | // a preface into the output line, figure out how wide | |
4960 | // it needs to be | |
4961 | // first, scan all the lines, to get the maximum line number | |
4962 | bufsz = 1024; | |
4963 | buf = (char *) malloc (bufsz); | |
4964 | int max_lineno = 0; | |
4965 | int hidx; | |
4966 | Hist_data::HistItem *hitem; | |
4967 | Vec_loop (Hist_data::HistItem*, data, hidx, hitem) | |
4968 | { | |
4969 | if (!hitem->obj) | |
4970 | continue; | |
4971 | if (hitem->obj->get_type () == Histable::LINE && | |
4972 | ((DbeLine*) hitem->obj)->lineno > max_lineno) | |
4973 | max_lineno = ((DbeLine*) hitem->obj)->lineno; | |
4974 | else if (hitem->obj->get_type () == Histable::INSTR | |
4975 | && ((DbeInstr*) hitem->obj)->lineno > max_lineno) | |
4976 | max_lineno = ((DbeInstr*) hitem->obj)->lineno; | |
4977 | } | |
4978 | ||
4979 | // we have the maximum integer over all linenumbers in the file | |
4980 | // figure out how many digits are needed | |
4981 | lspace = snprintf (buf, bufsz, NTXT ("%d"), max_lineno); | |
4982 | } | |
4983 | for (index2 = 0; index2 < nitems; index2++) | |
4984 | { | |
4985 | item = data->fetch (index2); | |
4986 | if (type == DSP_DLAYOUT) | |
4987 | cell = dbe_strdup (((DataObject*) (item->obj))->get_offset_name ()); | |
4988 | else if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2) | |
4989 | { | |
4990 | // This code is duplicated in output.cc, yet it's | |
4991 | // intended for presentation purpose and thus is | |
4992 | // potentially different for er_print and analyzer. | |
4993 | switch (item->type) | |
4994 | { | |
4995 | case Module::AT_SRC_ONLY: | |
4996 | case Module::AT_SRC: | |
4997 | if (item->obj == NULL) | |
4998 | snprintf (buf, bufsz, NTXT (" %*c. "), lspace, ' '); | |
4999 | else | |
5000 | snprintf (buf, bufsz, NTXT (" %*d. "), lspace, ((DbeLine*) item->obj)->lineno); | |
5001 | break; | |
5002 | case Module::AT_FUNC: | |
5003 | case Module::AT_QUOTE: | |
5004 | snprintf (buf, bufsz, NTXT ("%*c"), lspace + 3, ' '); | |
5005 | break; | |
5006 | case Module::AT_DIS: | |
5007 | case Module::AT_DIS_ONLY: | |
5008 | if (item->obj == NULL || ((DbeInstr*) item->obj)->lineno == -1) | |
5009 | snprintf (buf, bufsz, NTXT ("%*c[%*s] "), lspace + 3, ' ', lspace, NTXT ("?")); | |
5010 | else | |
5011 | snprintf (buf, bufsz, NTXT ("%*c[%*d] "), lspace + 3, ' ', lspace, | |
5012 | ((DbeInstr*) item->obj)->lineno); | |
5013 | break; | |
5014 | case Module::AT_COM: | |
5015 | case Module::AT_EMPTY: | |
5016 | *buf = (char) 0; | |
5017 | break; | |
5018 | } | |
5019 | // get the line's text | |
5020 | char *s = item->value[index].l; | |
5021 | if (s != NULL) | |
5022 | { | |
5023 | // copy the string expanding all tabulations | |
5024 | // (JTable doesn't render them) | |
5025 | char *d = buf + strlen (buf); | |
5026 | char c; | |
5027 | size_t column = 0; | |
5028 | do | |
5029 | { | |
5030 | c = *s++; | |
5031 | if (c == '\t') | |
5032 | { | |
5033 | do | |
5034 | { | |
5035 | *d++ = ' '; | |
5036 | column++; | |
5037 | } | |
5038 | while (column & 07); | |
5039 | } | |
5040 | else | |
5041 | { | |
5042 | *d++ = c; | |
5043 | column++; | |
5044 | } | |
5045 | if (column + 32 > bufsz) | |
5046 | { | |
5047 | // Reallocate the buffer | |
5048 | size_t curlen = d - buf; | |
5049 | bufsz += 1024; | |
5050 | char *buf_new = (char *) malloc (bufsz); | |
5051 | strncpy (buf_new, buf, curlen); | |
5052 | buf_new[curlen] = '\0'; | |
5053 | free (buf); | |
5054 | buf = buf_new; | |
5055 | d = buf + curlen; | |
5056 | } | |
5057 | } | |
5058 | while (c != (char) 0); | |
5059 | } | |
5060 | cell = dbe_strdup (buf); | |
5061 | free (item->value[index].l); | |
5062 | item->value[index].l = NULL; //YXXX missing from dbeGetFuncListV2 | |
5063 | } | |
5064 | else | |
5065 | { | |
5066 | // omazur: why don't we have it as metric value | |
5067 | Histable::NameFormat nfmt = dbev->get_name_format (); | |
5068 | cell = dbe_strdup (item->obj->get_name (nfmt)); | |
5069 | } | |
5070 | jobjects->store (index2, cell); | |
5071 | } | |
5072 | if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 | |
5073 | || type == DSP_DISASM_V2) | |
5074 | free (buf); | |
5075 | table->store (nv++, jobjects); | |
5076 | break; | |
5077 | } | |
5078 | default: | |
5079 | table->store (nv++, dbeGetTableDataOneColumn (data, index)); | |
5080 | break; | |
5081 | } | |
5082 | } | |
5083 | return table; | |
5084 | } | |
5085 | ||
5086 | Vector<Obj> * | |
5087 | dbeGetComparableObjsV2 (int /* dbevindex */, Obj sel_obj, int type) | |
5088 | { | |
5089 | long grsize = dbeSession->expGroups->size (); | |
5090 | Vector<Obj> *res = new Vector<Obj> (grsize + 1); | |
5091 | for (long j = 0; j < grsize; j++) | |
5092 | res->append ((Obj) NULL); | |
5093 | res->append (sel_obj); | |
5094 | Histable *obj = (Histable *) sel_obj; | |
5095 | if (obj == NULL) | |
5096 | return res; | |
5097 | Function *func = (Function *) obj->convertto (Histable::FUNCTION); | |
5098 | if (func == NULL) | |
5099 | return res; | |
5100 | Vector<Histable *> *cmpObjs = func->get_comparable_objs (); | |
5101 | if (cmpObjs == NULL || cmpObjs->size () != grsize) | |
5102 | return res; | |
5103 | ||
5104 | Histable::Type conv_type = (type == DSP_SOURCE || type == DSP_SOURCE_V2) ? | |
5105 | Histable::LINE : Histable::INSTR; | |
5106 | switch (obj->get_type ()) | |
5107 | { | |
5108 | case Histable::FUNCTION: | |
5109 | for (long j = 0; j < grsize; j++) | |
5110 | res->store (j, (Obj) cmpObjs->get (j)); | |
5111 | return res; | |
5112 | case Histable::INSTR: | |
5113 | case Histable::LINE: | |
5114 | { | |
5115 | SourceFile *srcContext = (SourceFile *) obj->convertto (Histable::SOURCEFILE); | |
5116 | char *bname = get_basename (srcContext->get_name ()); | |
5117 | for (long j = 0; j < grsize; j++) | |
5118 | { | |
5119 | Function *func1 = (Function *) cmpObjs->get (j); | |
5120 | if (func == func1) | |
5121 | { | |
5122 | if (conv_type == Histable::LINE) | |
5123 | res->store (j, (Obj) obj); | |
5124 | else | |
5125 | res->store (j, (Obj) obj->convertto (conv_type, srcContext)); | |
5126 | continue; | |
5127 | } | |
5128 | if (func1 == NULL) | |
5129 | continue; | |
5130 | Vector<SourceFile*> *sources = func1->get_sources (); | |
5131 | SourceFile *sf = NULL; | |
5132 | for (long j1 = 0, sz1 = sources ? sources->size () : 0; j1 < sz1; j1++) | |
5133 | { | |
5134 | SourceFile *sf1 = sources->get (j1); | |
5135 | if (sf1 == srcContext) | |
5136 | { // the same file | |
5137 | sf = srcContext; | |
5138 | break; | |
5139 | } | |
5140 | else if (sf == NULL) | |
5141 | { | |
5142 | char *bname1 = get_basename (sf1->get_name ()); | |
5143 | if (dbe_strcmp (bname, bname1) == 0) | |
5144 | sf = sf1; | |
5145 | } | |
5146 | } | |
5147 | res->store (j, (Obj) func1->convertto (conv_type, srcContext)); | |
5148 | } | |
5149 | break; | |
5150 | } | |
5151 | default: | |
5152 | break; | |
5153 | } | |
5154 | return res; | |
5155 | } | |
5156 | ||
5157 | // Get Table of Function List data | |
5158 | Vector<void *> * | |
5159 | dbeGetFuncListV2 (int dbevindex, int mtype, Obj sel_obj, int type, int subtype) | |
5160 | { | |
5161 | Metric *mitem; | |
5162 | int nitems, nvisible; | |
5163 | int index, index2, nv; | |
5164 | char *cell; | |
5165 | Hist_data::HistItem *item; | |
5166 | DbeView *dbev = dbeSession->getView (dbevindex); | |
5167 | dbev->error_msg = dbev->warning_msg = NULL; | |
5168 | MetricList *mlist = dbev->get_metric_list ((MetricType) (mtype & MTYPE_MASK), | |
5169 | (mtype & COMPARE_BIT) != 0, | |
5170 | mtype >> GROUP_ID_SHIFT); | |
5171 | Histable *selObj = (Histable *) sel_obj; | |
5172 | int old_compare_mode = dbev->get_compare_mode (); | |
5173 | if ((mtype & COMPARE_BIT) != 0) | |
5174 | dbev->reset_compare_mode (CMP_DISABLE); | |
5175 | Hist_data *data = dbev->get_data (mlist, selObj, type, subtype); | |
5176 | dbev->reset_compare_mode (old_compare_mode); | |
5177 | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | |
5178 | return NULL; | |
5179 | nitems = data->size (); | |
5180 | nvisible = mlist->get_items ()->size (); | |
5181 | ||
5182 | // Initialize Java String array | |
5183 | Vector<void*> *table = new Vector<void*>(nvisible + 3); | |
5184 | // Mark Hi-value metric items for annotated src/dis/layout | |
5185 | if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_DLAYOUT | |
5186 | || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2) | |
5187 | { | |
5188 | Vector<int> *types = new Vector<int>(nitems); | |
5189 | Vector<Obj> *ids = new Vector<Obj > (nitems); | |
5190 | if (dbev->marks->size () > 0) | |
5191 | index = dbev->marks->fetch (0); | |
5192 | else | |
5193 | index = -1; | |
5194 | int mindex = 0; | |
5195 | for (int i = 0; i < nitems; i++) | |
5196 | { | |
5197 | item = data->fetch (i); | |
5198 | ids->store (i, (Obj) item->obj); | |
5199 | if (i == index) | |
5200 | { | |
5201 | types->store (i, -item->type); | |
5202 | if (++mindex < dbev->marks->size ()) | |
5203 | index = dbev->marks->fetch (mindex); | |
5204 | else | |
5205 | index = -1; | |
5206 | } | |
5207 | else | |
5208 | types->store (i, item->type); | |
5209 | } | |
5210 | table->store (nvisible, types); | |
5211 | table->store (nvisible + 1, ids); | |
5212 | } | |
5213 | else | |
5214 | { | |
5215 | table->store (nvisible, NULL); | |
5216 | table->store (nvisible + 1, NULL); | |
5217 | } | |
5218 | ||
5219 | // Fill function list elements | |
5220 | nv = 0; | |
5221 | Vec_loop (Metric*, mlist->get_items (), index, mitem) | |
5222 | { | |
5223 | if (!mitem->is_visible () && !mitem->is_tvisible () && | |
5224 | !mitem->is_pvisible ()) | |
5225 | continue; | |
5226 | ||
5227 | // Fill values | |
5228 | switch (mitem->get_vtype ()) | |
5229 | { | |
5230 | default: | |
5231 | table->store (nv++, dbeGetTableDataOneColumn (data, index)); | |
5232 | break; | |
5233 | case VT_LABEL: | |
5234 | Vector<char*> *jobjects = new Vector<char*>(nitems); | |
5235 | char *buf = NULL; | |
5236 | size_t bufsz = 0; | |
5237 | int lspace = 0; | |
5238 | if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 | |
5239 | || type == DSP_DISASM_V2) | |
5240 | { | |
5241 | // if this is source or disassembly, where we'll insert | |
5242 | // a preface into the output line, figure out how wide | |
5243 | // it needs to be | |
5244 | // first, scan all the lines, to get the maximum line number | |
5245 | bufsz = 1024; | |
5246 | buf = (char *) malloc (bufsz); | |
5247 | int max_lineno = 0; | |
5248 | int hidx; | |
5249 | Hist_data::HistItem *hitem; | |
5250 | Vec_loop (Hist_data::HistItem*, data, hidx, hitem) | |
5251 | { | |
5252 | if (!hitem->obj) | |
5253 | continue; | |
5254 | if (hitem->obj->get_type () == Histable::LINE && | |
5255 | ((DbeLine*) hitem->obj)->lineno > max_lineno) | |
5256 | max_lineno = ((DbeLine*) hitem->obj)->lineno; | |
5257 | else if (hitem->obj->get_type () == Histable::INSTR | |
5258 | && ((DbeInstr*) hitem->obj)->lineno > max_lineno) | |
5259 | max_lineno = ((DbeInstr*) hitem->obj)->lineno; | |
5260 | } | |
5261 | ||
5262 | // we have the maximum integer over all linenumbers in the file | |
5263 | // figure out how many digits are needed | |
5264 | lspace = snprintf (buf, bufsz, NTXT ("%d"), max_lineno); | |
5265 | } | |
5266 | ||
5267 | for (index2 = 0; index2 < nitems; index2++) | |
5268 | { | |
5269 | item = data->fetch (index2); | |
5270 | if (type == DSP_DLAYOUT) | |
5271 | cell = dbe_strdup (((DataObject*) (item->obj))->get_offset_name ()); | |
5272 | else if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2) | |
5273 | { | |
5274 | // This code is duplicated in output.cc, yet it's | |
5275 | // intended for presentation purpose and thus is | |
5276 | // potentially different for er_print and analyzer. | |
5277 | switch (item->type) | |
5278 | { | |
5279 | case Module::AT_SRC_ONLY: | |
5280 | case Module::AT_SRC: | |
5281 | if (item->obj == NULL) | |
5282 | snprintf (buf, bufsz, NTXT (" %*c. "), lspace, ' '); | |
5283 | else | |
5284 | snprintf (buf, bufsz, NTXT (" %*d. "), lspace, | |
5285 | ((DbeLine*) item->obj)->lineno); | |
5286 | break; | |
5287 | case Module::AT_FUNC: | |
5288 | case Module::AT_QUOTE: | |
5289 | snprintf (buf, bufsz, NTXT ("%*c"), lspace + 3, ' '); | |
5290 | break; | |
5291 | case Module::AT_DIS: | |
5292 | case Module::AT_DIS_ONLY: | |
5293 | if (item->obj == NULL || ((DbeInstr*) item->obj)->lineno == -1) | |
5294 | snprintf (buf, bufsz, NTXT ("%*c[%*s] "), lspace + 3, ' ', | |
5295 | lspace, NTXT ("?")); | |
5296 | else | |
5297 | snprintf (buf, bufsz, NTXT ("%*c[%*d] "), lspace + 3, ' ', | |
5298 | lspace, | |
5299 | ((DbeInstr*) item->obj)->lineno); | |
5300 | break; | |
5301 | case Module::AT_COM: | |
5302 | case Module::AT_EMPTY: | |
5303 | *buf = (char) 0; | |
5304 | break; | |
5305 | } | |
5306 | // get the line's text | |
5307 | char *s = item->value[index].l; | |
5308 | if (s != NULL) | |
5309 | { | |
5310 | // copy the string expanding all tabulations | |
5311 | // (JTable doesn't render them) | |
5312 | char *d = buf + strlen (buf); | |
5313 | char c; | |
5314 | size_t column = 0; | |
5315 | do | |
5316 | { | |
5317 | c = *s++; | |
5318 | if (c == '\t') | |
5319 | { | |
5320 | do | |
5321 | { | |
5322 | *d++ = ' '; | |
5323 | column++; | |
5324 | } | |
5325 | while (column & 07); | |
5326 | } | |
5327 | else | |
5328 | { | |
5329 | *d++ = c; | |
5330 | column++; | |
5331 | } | |
5332 | if (column + 32 > bufsz) | |
5333 | { | |
5334 | // Reallocate the buffer | |
5335 | size_t curlen = d - buf; | |
5336 | bufsz += 1024; | |
5337 | char *buf_new = (char *) malloc (bufsz); | |
5338 | strncpy (buf_new, buf, curlen); | |
5339 | buf_new[curlen] = '\0'; | |
5340 | free (buf); | |
5341 | buf = buf_new; | |
5342 | d = buf + curlen; | |
5343 | } | |
5344 | } | |
5345 | while (c != (char) 0); | |
5346 | } | |
5347 | cell = dbe_strdup (buf); | |
5348 | } | |
5349 | else | |
5350 | { | |
5351 | Histable::NameFormat nfmt = dbev->get_name_format (); | |
5352 | cell = dbe_strdup (item->obj->get_name (nfmt)); | |
5353 | } | |
5354 | jobjects->store (index2, cell); | |
5355 | } | |
5356 | ||
5357 | if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 | |
5358 | || type == DSP_DISASM_V2) | |
5359 | free (buf); | |
5360 | table->store (nv++, jobjects); | |
5361 | break; | |
5362 | } | |
5363 | } | |
5364 | table->append (dbeGetMetricList (mlist)); | |
5365 | return table; | |
5366 | } // dbeGetFuncListV2 | |
5367 | ||
5368 | // | |
5369 | // Get Table DataV2 | |
5370 | // | |
5371 | Vector<void*> * | |
5372 | dbeGetTableDataV2 (int dbevindex, char *mlistStr, char *modeStr, char *typeStr, | |
5373 | char *subtypeStr, Vector<uint64_t> *ids) | |
5374 | { | |
5375 | DbeView *dbev = dbeSession->getView (dbevindex); | |
5376 | if (dbev == NULL) | |
5377 | abort (); | |
5378 | ||
5379 | // Process metric list specification | |
5380 | if (mlistStr == NULL) | |
5381 | return NULL; | |
5382 | bool met_call = false; | |
5383 | MetricList *mlist = NULL; | |
5384 | if (streq (mlistStr, NTXT ("MET_NORMAL"))) | |
5385 | mlist = dbev->get_metric_list (MET_NORMAL); | |
5386 | else if (streq (mlistStr, NTXT ("MET_CALL"))) | |
5387 | { | |
5388 | met_call = true; | |
5389 | mlist = dbev->get_metric_list (MET_CALL); | |
5390 | } | |
5391 | else if (streq (mlistStr, NTXT ("MET_CALL_AGR"))) | |
5392 | mlist = dbev->get_metric_list (MET_CALL_AGR); | |
5393 | else if (streq (mlistStr, NTXT ("MET_DATA"))) | |
5394 | mlist = dbev->get_metric_list (MET_DATA); | |
5395 | else if (streq (mlistStr, NTXT ("MET_INDX"))) | |
5396 | mlist = dbev->get_metric_list (MET_INDX); | |
5397 | else if (streq (mlistStr, NTXT ("MET_IO"))) | |
5398 | mlist = dbev->get_metric_list (MET_IO); | |
5399 | else if (streq (mlistStr, NTXT ("MET_HEAP"))) | |
5400 | mlist = dbev->get_metric_list (MET_HEAP); | |
5401 | else | |
5402 | return NULL; | |
5403 | ||
5404 | // Process mode specification | |
5405 | if (modeStr == NULL) | |
5406 | return NULL; | |
5407 | Hist_data::Mode mode = (Hist_data::Mode)0; | |
5408 | if (streq (modeStr, NTXT ("CALLERS"))) | |
5409 | mode = Hist_data::CALLERS; | |
5410 | else if (streq (modeStr, NTXT ("CALLEES"))) | |
5411 | mode = Hist_data::CALLEES; | |
5412 | else if (streq (modeStr, NTXT ("SELF"))) | |
5413 | mode = Hist_data::SELF; | |
5414 | else if (streq (modeStr, NTXT ("ALL"))) | |
5415 | mode = Hist_data::ALL; | |
5416 | else | |
5417 | return NULL; | |
5418 | ||
5419 | // Process type specification | |
5420 | if (typeStr == NULL) | |
5421 | return NULL; | |
5422 | Histable::Type type = Histable::OTHER; | |
5423 | if (streq (typeStr, NTXT ("FUNCTION"))) | |
5424 | type = Histable::FUNCTION; | |
5425 | else if (streq (typeStr, NTXT ("INDEXOBJ"))) | |
5426 | type = Histable::INDEXOBJ; | |
5427 | else if (streq (typeStr, NTXT ("IOACTFILE"))) | |
5428 | type = Histable::IOACTFILE; | |
5429 | else if (streq (typeStr, NTXT ("IOACTVFD"))) | |
5430 | type = Histable::IOACTVFD; | |
5431 | else if (streq (typeStr, NTXT ("IOCALLSTACK"))) | |
5432 | type = Histable::IOCALLSTACK; | |
5433 | else if (streq (typeStr, NTXT ("HEAPCALLSTACK"))) | |
5434 | type = Histable::HEAPCALLSTACK; | |
5435 | else if (streq (typeStr, NTXT ("LINE"))) | |
5436 | type = Histable::LINE; | |
5437 | else if (streq (typeStr, NTXT ("INSTR"))) | |
5438 | type = Histable::INSTR; | |
5439 | else | |
5440 | // XXX Accepting objects other than above may require a different | |
5441 | // implementation of the id -> Histable mapping below | |
5442 | return NULL; | |
5443 | ||
5444 | // Process subtype specification | |
5445 | int subtype = 0; | |
5446 | if (subtypeStr != NULL) | |
5447 | subtype = atoi (subtypeStr); | |
5448 | Vector<Histable*> *hobjs = NULL; | |
5449 | if (ids != NULL) | |
5450 | { | |
5451 | hobjs = new Vector<Histable*>(); | |
5452 | for (int i = 0; i < ids->size (); ++i) | |
5453 | { | |
5454 | Histable::Type obj_type = type; | |
5455 | if ((obj_type == Histable::LINE || obj_type == Histable::INSTR) | |
5456 | && subtype == 0) | |
5457 | obj_type = Histable::FUNCTION; | |
5458 | Histable *hobj = dbeSession->findObjectById (obj_type, subtype, ids->fetch (i)); | |
5459 | if ((obj_type == Histable::LINE || obj_type == Histable::INSTR) | |
5460 | && subtype == 0 && hobj == NULL) | |
5461 | return NULL; | |
5462 | hobjs->append (hobj); | |
5463 | } | |
5464 | } | |
5465 | ||
5466 | PathTree::PtreeComputeOption flag = PathTree::COMPUTEOPT_NONE; | |
5467 | if (dbev->isOmpDisMode () && type == Histable::FUNCTION | |
5468 | && mode == Hist_data::CALLEES && met_call) | |
5469 | flag = PathTree::COMPUTEOPT_OMP_CALLEE; | |
5470 | ||
5471 | Hist_data *data = dbev->get_hist_data (mlist, type, subtype, mode, hobjs, NULL, NULL, flag); | |
5472 | return dbeGetTableDataV2Data (dbev, data); | |
5473 | } | |
5474 | ||
5475 | static Vector<void*> * | |
5476 | dbeGetTableDataV2Data (DbeView * /*dbev*/, Hist_data *data) | |
5477 | { | |
5478 | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | |
5479 | return NULL; | |
5480 | MetricList *mlist; | |
5481 | mlist = data->get_metric_list (); | |
5482 | int nitems = data->size (); | |
5483 | ||
5484 | // Initialize Java String array | |
5485 | Vector<void*> *table = new Vector<void*>(mlist->size () + 1); | |
5486 | ||
5487 | // Fill function list elements | |
5488 | for (long i = 0, sz = mlist->size (); i < sz; i++) | |
5489 | { | |
5490 | Metric *mitem = mlist->get (i); | |
5491 | if (!mitem->is_visible () && !mitem->is_tvisible () && | |
5492 | !mitem->is_pvisible ()) | |
5493 | continue; | |
5494 | table->append (dbeGetTableDataOneColumn (data, i)); | |
5495 | } | |
5496 | ||
5497 | // Add an array of Histable IDs | |
5498 | Vector<uint64_t> *idList = new Vector<uint64_t>(nitems); | |
5499 | for (int i = 0; i < nitems; ++i) | |
5500 | { | |
5501 | Hist_data::HistItem *item = data->fetch (i); | |
5502 | if (item->obj->get_type () == Histable::LINE | |
5503 | || item->obj->get_type () == Histable::INSTR) | |
5504 | idList->store (i, (uint64_t) (item->obj)); | |
5505 | else | |
5506 | idList->store (i, item->obj->id); | |
5507 | } | |
5508 | table->append (idList); | |
5509 | return table; | |
5510 | } // dbeGetTableData | |
5511 | ||
5512 | //YXXX try to use the following to consolidate similar cut/paste code | |
5513 | ||
5514 | static Vector<void*> * | |
5515 | dbeGetTableDataOneColumn (Hist_data *data, int met_ind) | |
5516 | { | |
5517 | // Allocates a vector and fills it with metric values for one column | |
5518 | TValue res; | |
5519 | Metric *m = data->get_metric_list ()->get (met_ind); | |
5520 | if ((m->get_visbits () & VAL_RATIO) != 0) | |
5521 | { | |
5522 | Vector<double> *col = new Vector<double>(data->size ()); | |
5523 | for (long row = 0, sz_row = data->size (); row < sz_row; row++) | |
5524 | { | |
5525 | TValue *v = data->get_value (&res, met_ind, row); | |
5526 | double d = (v->tag != VT_LABEL) ? v->to_double () : 100.; // NaN | |
5527 | col->append (d); | |
5528 | } | |
5529 | return (Vector<void*> *) col; | |
5530 | } | |
5531 | ||
5532 | switch (m->get_vtype ()) | |
5533 | { | |
5534 | case VT_DOUBLE: | |
5535 | { | |
5536 | Vector<double> *col = new Vector<double>(data->size ()); | |
5537 | for (long row = 0, sz_row = data->size (); row < sz_row; row++) | |
5538 | { | |
5539 | TValue *v = data->get_value (&res, met_ind, row); | |
5540 | col->append (v->d); | |
5541 | } | |
5542 | return (Vector<void*> *) col; | |
5543 | } | |
5544 | case VT_INT: | |
5545 | { | |
5546 | Vector<int> *col = new Vector<int>(data->size ()); | |
5547 | for (long row = 0, sz_row = data->size (); row < sz_row; row++) | |
5548 | { | |
5549 | TValue *v = data->get_value (&res, met_ind, row); | |
5550 | col->append (v->i); | |
5551 | } | |
5552 | return (Vector<void*> *) col; | |
5553 | } | |
5554 | case VT_ULLONG: | |
5555 | case VT_LLONG: | |
5556 | { | |
5557 | Vector<long long> *col = new Vector<long long>(data->size ()); | |
5558 | for (long row = 0, sz_row = data->size (); row < sz_row; row++) | |
5559 | { | |
5560 | TValue *v = data->get_value (&res, met_ind, row); | |
5561 | col->append (v->ll); | |
5562 | } | |
5563 | return (Vector<void*> *) col; | |
5564 | } | |
5565 | case VT_ADDRESS: | |
5566 | { | |
5567 | Vector<long long> *col = new Vector<long long>(data->size ()); | |
5568 | for (long row = 0, sz_row = data->size (); row < sz_row; row++) | |
5569 | { | |
5570 | TValue *v = data->get_value (&res, met_ind, row); | |
5571 | // set the highest bit to mark this jlong as | |
5572 | // a VT_ADDRESS (rather than a regular VT_LLONG) | |
5573 | col->append (v->ll | 0x8000000000000000ULL); | |
5574 | } | |
5575 | return (Vector<void*> *) col; | |
5576 | } | |
5577 | case VT_LABEL: | |
5578 | { | |
5579 | Vector<char *> *col = new Vector<char *>(data->size ()); | |
5580 | for (long row = 0, sz_row = data->size (); row < sz_row; row++) | |
5581 | { | |
5582 | TValue *v = data->get_value (&res, met_ind, row); | |
5583 | col->append (dbe_strdup (v->l)); | |
5584 | } | |
5585 | return (Vector<void*> *) col; | |
5586 | } | |
5587 | default: | |
5588 | return NULL; | |
5589 | } | |
5590 | } | |
5591 | ||
5592 | static Vector<void*> * | |
5593 | dbeGetTableDataOneColumn (DbeView *dbev, Vector<Hist_data::HistItem*> *data, | |
5594 | ValueTag vtype, int metricColumnNumber) | |
5595 | // Allocates a vector and fills it with metric values for one column | |
5596 | { | |
5597 | Vector<void*> *column_data = NULL; | |
5598 | int nitems = data->size (); // number of rows | |
5599 | int index = metricColumnNumber; | |
5600 | switch (vtype) | |
5601 | { | |
5602 | case VT_DOUBLE: | |
5603 | { | |
5604 | Vector<double> *jd_list = new Vector<double>(nitems); | |
5605 | for (int index2 = 0; index2 < nitems; index2++) | |
5606 | { | |
5607 | Hist_data::HistItem *item = data->fetch (index2); | |
5608 | jd_list->store (index2, item->value[index].d); | |
5609 | } | |
5610 | column_data = (Vector<void*> *)jd_list; | |
5611 | break; | |
5612 | } | |
5613 | case VT_INT: | |
5614 | { | |
5615 | Vector<int> *ji_list = new Vector<int>(nitems); | |
5616 | for (int index2 = 0; index2 < nitems; index2++) | |
5617 | { | |
5618 | Hist_data::HistItem *item = data->fetch (index2); | |
5619 | ji_list->store (index2, item->value[index].i); | |
5620 | } | |
5621 | column_data = (Vector<void*> *)ji_list; | |
5622 | break; | |
5623 | } | |
5624 | case VT_ULLONG: | |
5625 | case VT_LLONG: | |
5626 | { | |
5627 | Vector<long long> *jl_list = new Vector<long long>(nitems); | |
5628 | for (int index2 = 0; index2 < nitems; index2++) | |
5629 | { | |
5630 | Hist_data::HistItem *item = data->fetch (index2); | |
5631 | jl_list->store (index2, item->value[index].ll); | |
5632 | } | |
5633 | column_data = (Vector<void*> *)jl_list; | |
5634 | break; | |
5635 | } | |
5636 | case VT_ADDRESS: | |
5637 | { | |
5638 | Vector<long long> *jl_list = new Vector<long long>(nitems); | |
5639 | for (int index2 = 0; index2 < nitems; index2++) | |
5640 | { | |
5641 | Hist_data::HistItem *item = data->fetch (index2); | |
5642 | ||
5643 | // set the highest bit to mark this jlong as | |
5644 | // a VT_ADDRESS (rather than a regular VT_LLONG) | |
5645 | uint64_t addr = item->value[index].ll; | |
5646 | addr |= 0x8000000000000000ULL; | |
5647 | jl_list->store (index2, addr); | |
5648 | } | |
5649 | column_data = (Vector<void*> *)jl_list; | |
5650 | break; | |
5651 | } | |
5652 | case VT_LABEL: | |
5653 | { | |
5654 | Vector<char*> *jobjects = new Vector<char*>(nitems); | |
5655 | for (int index2 = 0; index2 < nitems; index2++) | |
5656 | { | |
5657 | Hist_data::HistItem *item = data->fetch (index2); | |
5658 | ||
5659 | // omazur: why don't we have it as metric value | |
5660 | Histable::NameFormat nfmt = dbev->get_name_format (); | |
5661 | char *str = dbe_strdup (item->obj->get_name (nfmt)); | |
5662 | jobjects->store (index2, str); | |
5663 | } | |
5664 | column_data = (Vector<void*> *)jobjects; | |
5665 | break; | |
5666 | } | |
5667 | default: | |
5668 | abort (); | |
5669 | } | |
5670 | return column_data; | |
5671 | } | |
5672 | ||
5673 | int | |
5674 | dbeGetCallTreeNumLevels (int dbevindex) | |
5675 | { | |
5676 | DbeView *dbev = dbeSession->getView (dbevindex); | |
5677 | if (dbev == NULL) | |
5678 | abort (); | |
5679 | PathTree * ptree = dbev->get_path_tree (); | |
5680 | if (ptree == NULL) | |
5681 | return 0; | |
5682 | return ptree->get_ftree_depth (); | |
5683 | } | |
5684 | ||
5685 | Vector<void*>* | |
5686 | dbeGetCallTreeLevel (int dbevindex, char *mcmd, int level) | |
5687 | { | |
5688 | DbeView *dbev = dbeSession->getView (dbevindex); | |
5689 | if (dbev == NULL) | |
5690 | abort (); | |
5691 | PathTree * ptree = dbev->get_path_tree (); | |
5692 | if (ptree == NULL) | |
5693 | return NULL; | |
5694 | if (mcmd == NULL) | |
5695 | return NULL; | |
5696 | BaseMetric *bm = dbeSession->find_base_reg_metric (mcmd); | |
5697 | if (bm == NULL) | |
5698 | return NULL; | |
5699 | return ptree->get_ftree_level (bm, level); | |
5700 | } | |
5701 | ||
5702 | Vector<void*>* | |
5703 | dbeGetCallTreeLevels (int dbevindex, char *mcmd) | |
5704 | { | |
5705 | DbeView *dbev = dbeSession->getView (dbevindex); | |
5706 | if (dbev == NULL) | |
5707 | abort (); | |
5708 | PathTree * ptree = dbev->get_path_tree (); | |
5709 | if (ptree == NULL) | |
5710 | return NULL; | |
5711 | if (mcmd == NULL) | |
5712 | return NULL; | |
5713 | BaseMetric *bm = dbeSession->find_base_reg_metric (mcmd); | |
5714 | if (bm == NULL) | |
5715 | return NULL; | |
5716 | ||
5717 | int depth = ptree->get_ftree_depth (); | |
5718 | Vector<void*> *results = new Vector<void*>(depth); | |
5719 | for (int ii = 0; ii < depth; ii++) | |
5720 | results->append (ptree->get_ftree_level (bm, ii)); | |
5721 | return results; | |
5722 | } | |
5723 | ||
5724 | Vector<void*>* | |
5725 | dbeGetCallTreeLevelFuncs (int dbevindex, int start_level, int end_level) | |
5726 | { // (0,-1) -> all levels | |
5727 | DbeView *dbev = dbeSession->getView (dbevindex); | |
5728 | if (dbev == NULL) | |
5729 | abort (); | |
5730 | PathTree * ptree = dbev->get_path_tree (); | |
5731 | if (ptree == NULL) | |
5732 | return NULL; | |
5733 | ||
5734 | int depth = ptree->get_ftree_depth (); | |
5735 | if (start_level < 0) | |
5736 | start_level = 0; | |
5737 | if (end_level < 0 || end_level >= depth) | |
5738 | end_level = depth - 1; | |
5739 | ||
5740 | Histable::NameFormat nfmt = dbev->get_name_format (); //YXXX or fixed format? | |
5741 | Vector<char*> *funcNames = new Vector<char*>(); | |
5742 | Vector<long long> *funcIds = new Vector<long long>(); | |
5743 | Vector<Obj> *funcObjs = new Vector<Obj>(); | |
5744 | ||
5745 | if (start_level == 0 && end_level == depth - 1) | |
5746 | return dbeGetCallTreeFuncs (dbevindex); | |
5747 | else | |
5748 | { | |
5749 | for (int ii = start_level; ii <= end_level; ii++) | |
5750 | { | |
5751 | Vector<void*> *info = ptree->get_ftree_level (NULL, ii); /*no metric*/ | |
5752 | if (!info) | |
5753 | continue; | |
5754 | Vector<long long> *fids = (Vector<long long> *)info->get (2); | |
5755 | if (!fids) | |
5756 | continue; | |
5757 | int index; | |
5758 | long long fid; | |
5759 | Vec_loop (long long, fids, index, fid) | |
5760 | { | |
5761 | funcIds->append (fid); | |
5762 | Histable *obj = dbeSession->findObjectById (fid); | |
5763 | char * fname = obj ? dbe_strdup (obj->get_name (nfmt)) : NULL; | |
5764 | funcNames->append (fname); | |
5765 | funcObjs->append ((unsigned long) obj); // avoiding sign extension | |
5766 | } | |
5767 | destroy (info); | |
5768 | } | |
5769 | } | |
5770 | Vector<void*> *results = new Vector<void*>(3); | |
5771 | results->append (funcIds); | |
5772 | results->append (funcNames); | |
5773 | results->append (funcObjs); | |
5774 | return results; | |
5775 | } | |
5776 | ||
5777 | Vector<void*> * | |
5778 | dbeGetCallTreeFuncs (int dbevindex) | |
5779 | { // does not require ptree->get_ftree_level() to be computed | |
5780 | DbeView *dbev = dbeSession->getView (dbevindex); | |
5781 | if (dbev == NULL) | |
5782 | abort (); | |
5783 | PathTree * ptree = dbev->get_path_tree (); | |
5784 | if (ptree == NULL) | |
5785 | return 0; | |
5786 | Vector<Function*>* funcs = ptree->get_funcs (); // Unique functions in tree | |
5787 | if (funcs == NULL) | |
5788 | return NULL; | |
5789 | ||
5790 | long sz = funcs->size (); | |
5791 | Vector<void*> *results = new Vector<void*>(3); | |
5792 | Vector<long long> *funcIds = new Vector<long long>(sz); | |
5793 | Vector<char*> *funcNames = new Vector<char*>(sz); | |
5794 | Vector<Obj> *funcObjs = new Vector<Obj>(sz); | |
5795 | ||
5796 | int index; | |
5797 | Function * func; | |
5798 | Histable::NameFormat nfmt = dbev->get_name_format (); //YXXX or fixed format? | |
5799 | Vec_loop (Function *, funcs, index, func) | |
5800 | { | |
5801 | funcIds->append (func->id); // do we need IDs? | |
5802 | char *fname = dbe_strdup (func->get_name (nfmt)); | |
5803 | funcNames->append (fname); | |
5804 | funcObjs->append ((unsigned long) func); // avoiding sign extension | |
5805 | } | |
5806 | results->put (0, funcIds); | |
5807 | results->put (1, funcNames); | |
5808 | results->put (2, funcObjs); | |
5809 | destroy (funcs); | |
5810 | return results; | |
5811 | } | |
5812 | ||
5813 | Vector<void*>* | |
5814 | dbeGetCallTreeChildren (int dbevindex, char *mcmd, Vector<int /*NodeIdx*/>*node_idxs) | |
5815 | { | |
5816 | DbeView *dbev = dbeSession->getView (dbevindex); | |
5817 | if (dbev == NULL) | |
5818 | abort (); | |
5819 | if (node_idxs == NULL || node_idxs->size () == 0) | |
5820 | return NULL; | |
5821 | long sz = node_idxs->size (); | |
5822 | PathTree * ptree = dbev->get_path_tree (); | |
5823 | if (ptree == NULL) | |
5824 | return NULL; | |
5825 | if (mcmd == NULL) | |
5826 | return NULL; | |
5827 | BaseMetric *bm = dbeSession->find_base_reg_metric (mcmd); | |
5828 | if (bm == NULL) | |
5829 | return NULL; | |
5830 | ||
5831 | Vector<void*> *results = new Vector<void*>(sz); | |
5832 | for (long ii = 0; ii < sz; ii++) | |
5833 | { | |
5834 | PathTree::NodeIdx nodeIdx = node_idxs->get (ii); // upcasted from int | |
5835 | results->append (ptree->get_ftree_node_children (bm, nodeIdx)); | |
5836 | } | |
5837 | return results; | |
5838 | } | |
5839 | ||
5840 | Vector<int> * | |
5841 | dbeGetGroupIds (int /*dbevindex*/) | |
5842 | { | |
5843 | Vector<ExpGroup*> *groups = dbeSession->expGroups; | |
5844 | int sz = groups->size (); | |
5845 | Vector<int> *grIds = new Vector<int>(sz); | |
5846 | for (int i = 0; i < sz; i++) | |
5847 | grIds->store (i, groups->fetch (i)->groupId); | |
5848 | return grIds; | |
5849 | } | |
5850 | ||
5851 | // | |
5852 | // Get label for name column | |
5853 | // | |
5854 | Vector<char*> * | |
5855 | dbeGetNames (int dbevindex, int type, Obj sel_obj) | |
5856 | { | |
5857 | char *s0, *s1, *s2; | |
5858 | bool need_strdup = true; | |
5859 | switch (type) | |
5860 | { | |
5861 | case DSP_SOURCE_V2: | |
5862 | case DSP_DISASM_V2: | |
5863 | case DSP_SOURCE: | |
5864 | case DSP_DISASM: | |
5865 | { | |
5866 | if (sel_obj) | |
5867 | { | |
5868 | Histable *selObj = (Histable*) sel_obj; | |
5869 | Function *func = (Function *) selObj->convertto (Histable::FUNCTION); | |
5870 | if (func) | |
5871 | { | |
5872 | char *names[3] = {NULL, NULL, NULL}; | |
5873 | set_file_names (func, names); | |
5874 | s0 = names[0]; | |
5875 | s1 = names[1]; | |
5876 | s2 = names[2]; | |
5877 | need_strdup = false; | |
5878 | break; | |
5879 | } | |
5880 | } | |
5881 | DbeView *dbev = dbeSession->getView (dbevindex); | |
5882 | char **names = type == DSP_SOURCE || type == DSP_SOURCE_V2 ? dbev->names_src : dbev->names_dis; | |
5883 | s0 = names[0]; | |
5884 | s1 = names[1]; | |
5885 | s2 = names[2]; | |
5886 | break; | |
5887 | } | |
5888 | case DSP_LINE: | |
5889 | s0 = GTXT ("Lines"); | |
5890 | s1 = GTXT ("Function, line # in \"sourcefile\""); | |
5891 | s2 = NTXT (""); | |
5892 | break; | |
5893 | case DSP_PC: | |
5894 | s0 = GTXT ("PCs"); | |
5895 | s1 = GTXT ("Function + offset"); | |
5896 | s2 = NTXT (""); | |
5897 | break; | |
5898 | case DSP_DLAYOUT: | |
5899 | s0 = GTXT ("Name"); | |
5900 | s1 = GTXT ("* +offset .element"); | |
5901 | s2 = NTXT (""); | |
5902 | break; | |
5903 | default: | |
5904 | s0 = GTXT ("Name"); | |
5905 | s1 = s2 = NTXT (""); | |
5906 | break; | |
5907 | } | |
5908 | if (need_strdup) | |
5909 | { | |
5910 | s0 = dbe_strdup (s0); | |
5911 | s1 = dbe_strdup (s1); | |
5912 | s2 = dbe_strdup (s2); | |
5913 | } | |
5914 | Vector<char*> *table = new Vector<char*>(3); | |
5915 | table->store (0, s0); | |
5916 | table->store (1, s1); | |
5917 | table->store (2, s2); | |
5918 | return table; | |
5919 | } | |
5920 | ||
5921 | // | |
5922 | // Get Total/Maximum element of Function List | |
5923 | // | |
5924 | Vector<void*> * | |
5925 | dbeGetTotalMax (int dbevindex, int type, int subtype) | |
5926 | { | |
5927 | Hist_data *data; | |
5928 | int index; | |
5929 | Hist_data::HistItem *total_item, *maximum_item; | |
5930 | DbeView *dbev = dbeSession->getView (dbevindex); | |
5931 | if (dbev == NULL) | |
5932 | abort (); | |
5933 | ||
5934 | switch (type) | |
5935 | { | |
5936 | case DSP_LINE: | |
5937 | data = dbev->line_data; | |
5938 | break; | |
5939 | case DSP_PC: | |
5940 | data = dbev->pc_data; | |
5941 | break; | |
5942 | case DSP_CALLER: | |
5943 | data = dbev->callers; | |
5944 | break; | |
5945 | case DSP_SELF: | |
5946 | case DSP_CALLEE: | |
5947 | data = dbev->callees; | |
5948 | break; | |
5949 | case DSP_DLAYOUT: | |
5950 | data = dbev->dlay_data; | |
5951 | break; | |
5952 | case DSP_DATAOBJ: | |
5953 | data = dbev->dobj_data; | |
5954 | break; | |
5955 | case DSP_MEMOBJ: | |
5956 | data = dbev->get_indxobj_data (subtype); | |
5957 | break; | |
5958 | case DSP_INDXOBJ: | |
5959 | data = dbev->get_indxobj_data (subtype); | |
5960 | break; | |
5961 | case DSP_FUNCTION: // annotated src/dis use func total/max | |
5962 | case DSP_SOURCE: | |
5963 | case DSP_DISASM: | |
5964 | case DSP_SOURCE_V2: | |
5965 | case DSP_DISASM_V2: | |
5966 | data = dbev->func_data; | |
5967 | break; | |
5968 | default: | |
5969 | abort (); | |
5970 | } | |
5971 | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | |
5972 | return NULL; | |
5973 | ||
5974 | // Get list size | |
5975 | // XXX -- the original list has all items, visible or not; | |
5976 | // XXX -- the one from Hist_data has only visible items, | |
5977 | // XXX -- and should be the only ones computed | |
5978 | // XXX -- Analyzer got confused (yesterday), when we used the shorter list | |
5979 | // XXX -- Why can we fetch total/max for metrics never | |
5980 | // XXX -- computed without core dumping? | |
5981 | MetricList *mlist2 = data->get_metric_list (); | |
5982 | int size = mlist2->get_items ()->size (); | |
5983 | ||
5984 | // Initialize Java array | |
5985 | Vector<void*> *total_max = new Vector<void*>(2); | |
5986 | Vector<double> *total = new Vector<double>(size); | |
5987 | Vector<double> *maximum = new Vector<double>(size); | |
5988 | ||
5989 | // Fill total/maximum element | |
5990 | total_item = data->get_totals (); | |
5991 | maximum_item = data->get_maximums (); | |
5992 | ||
5993 | for (index = 0; index < size; index++) | |
5994 | { | |
5995 | total->store (index, total_item->value[index].to_double ()); | |
5996 | maximum->store (index, maximum_item->value[index].to_double ()); | |
5997 | } | |
5998 | total_max->store (0, total); | |
5999 | total_max->store (1, maximum); | |
6000 | return total_max; | |
6001 | } | |
6002 | ||
6003 | // | |
6004 | // Get Table of Overview List | |
6005 | Vector<void*> * | |
6006 | dbeGetStatisOverviewList (int dbevindex) | |
6007 | { | |
6008 | int size; | |
6009 | Ovw_data **data; | |
6010 | Ovw_data::Ovw_item labels, *totals; | |
6011 | int nitems; | |
6012 | int index, index2; | |
6013 | ||
6014 | DbeView *dbev = dbeSession->getView (dbevindex); | |
6015 | if (dbev == NULL) | |
6016 | abort (); | |
6017 | dbev->error_msg = dbev->warning_msg = NULL; | |
6018 | ||
6019 | size = dbeSession->nexps (); | |
6020 | totals = new Ovw_data::Ovw_item[size + 1]; | |
6021 | data = new Ovw_data*[size + 1]; | |
6022 | data[0] = new Ovw_data (); | |
6023 | ||
6024 | for (index = 1; index <= size; index++) | |
6025 | { | |
6026 | data[index] = dbev->get_ovw_data (index - 1); | |
6027 | if (data[index] == NULL) | |
6028 | { | |
6029 | Ovw_data::reset_item (&totals[index]); // set contents to zeros | |
6030 | continue; | |
6031 | } | |
6032 | data[0]->sum (data[index]); | |
6033 | totals[index] = data[index]->get_totals (); //shallow copy! | |
6034 | } | |
6035 | totals[0] = data[0]->get_totals (); | |
6036 | ||
6037 | // Get table size | |
6038 | labels = data[0]->get_labels (); | |
6039 | nitems = labels.size + 4; | |
6040 | ||
6041 | // Initialize Java String array | |
6042 | Vector<void*> *table = new Vector<void*>(size + 4); | |
6043 | Vector<char*> *jobjects = new Vector<char*>(nitems); | |
6044 | ||
6045 | // Set the label | |
6046 | jobjects->store (0, dbe_strdup (GTXT ("Start Time (sec.)"))); | |
6047 | jobjects->store (1, dbe_strdup (GTXT ("End Time (sec.)"))); | |
6048 | jobjects->store (2, dbe_strdup (GTXT ("Duration (sec.)"))); | |
6049 | jobjects->store (3, dbe_strdup (GTXT ("Total Thread Time (sec.)"))); | |
6050 | jobjects->store (4, dbe_strdup (GTXT ("Average number of Threads"))); | |
6051 | ||
6052 | for (index2 = 5; index2 < nitems; index2++) | |
6053 | jobjects->store (index2, dbe_strdup (labels.values[index2 - 4].l)); | |
6054 | table->store (0, jobjects); | |
6055 | ||
6056 | // Set the data | |
6057 | for (index = 0; index <= size; index++) | |
6058 | { | |
6059 | Vector<double> *jd_list = new Vector<double>(nitems); | |
6060 | jd_list->store (0, tstodouble (totals[index].start)); | |
6061 | jd_list->store (1, tstodouble (totals[index].end)); | |
6062 | jd_list->store (2, tstodouble (totals[index].duration)); | |
6063 | jd_list->store (3, tstodouble (totals[index].tlwp)); | |
6064 | jd_list->store (4, totals[index].nlwp); | |
6065 | for (index2 = 5; index2 < nitems; index2++) | |
6066 | jd_list->store (index2, tstodouble (totals[index].values[index2 - 4].t)); | |
6067 | table->store (index + 1, jd_list); | |
6068 | } | |
6069 | for (index = 0; index <= size; index++) | |
6070 | delete data[index]; | |
6071 | delete[] data; | |
6072 | delete[] totals; | |
6073 | return table; | |
6074 | } | |
6075 | ||
6076 | // Get Table of Statistics List | |
6077 | Vector<void*> * | |
6078 | dbeGetStatisList (int dbevindex) | |
6079 | { | |
6080 | int size; | |
6081 | Stats_data **data; | |
6082 | int nitems; | |
6083 | int index, index2; | |
6084 | DbeView *dbev = dbeSession->getView (dbevindex); | |
6085 | if (dbev == NULL) | |
6086 | abort (); | |
6087 | dbev->error_msg = dbev->warning_msg = NULL; | |
6088 | if ((size = dbeSession->nexps ()) == 0) | |
6089 | return NULL; | |
6090 | ||
6091 | // Get statistics data | |
6092 | data = (Stats_data **) malloc ((size + 1) * sizeof (Stats_data *)); | |
6093 | data[0] = new Stats_data (); | |
6094 | for (index = 1; index <= size; index++) | |
6095 | { | |
6096 | data[index] = dbev->get_stats_data (index - 1); | |
6097 | if (data[index] == NULL) | |
6098 | continue; | |
6099 | data[0]->sum (data[index]); | |
6100 | } | |
6101 | ||
6102 | // Get table size | |
6103 | nitems = data[0]->size (); | |
6104 | ||
6105 | // Initialize Java String array | |
6106 | Vector<void*> *table = new Vector<void*>(size + 2); | |
6107 | Vector<char*> *jobjects = new Vector<char*>(nitems); | |
6108 | ||
6109 | // Set the label | |
6110 | for (index2 = 0; index2 < nitems; index2++) | |
6111 | jobjects->store (index2, dbe_strdup (data[0]->fetch (index2).label)); | |
6112 | table->store (0, jobjects); | |
6113 | ||
6114 | // Set the data | |
6115 | for (index = 0; index <= size; index++) | |
6116 | { | |
6117 | Vector<double> *jd_list = new Vector<double>(nitems); | |
6118 | for (index2 = 0; index2 < nitems; index2++) | |
6119 | { | |
6120 | double val = 0; | |
6121 | if (data[index]) | |
6122 | val = data[index]->fetch (index2).value.to_double (); | |
6123 | jd_list->store (index2, val); | |
6124 | } | |
6125 | table->store (index + 1, jd_list); | |
6126 | } | |
6127 | if (data) | |
6128 | { | |
6129 | for (index = 0; index <= size; index++) | |
6130 | delete data[index]; | |
6131 | free (data); | |
6132 | } | |
6133 | return table; | |
6134 | } | |
6135 | ||
6136 | ||
6137 | // | |
6138 | // Set summary list | |
6139 | // | |
6140 | static void | |
6141 | setSummary (Vector<Histable*> *objs, Vector<int> *saligns, | |
6142 | Vector<char> *mnemonic, Vector<char*> *jlabels, Vector<char*> *jvalues) | |
6143 | { | |
6144 | char *sname = NULL, *oname = NULL, *lname = NULL, *alias = NULL, | |
6145 | *mangle = NULL, *address = NULL, *size = NULL, | |
6146 | *name_0 = NULL, *sname_0 = NULL, *oname_0 = NULL, *lname_0 = NULL, | |
6147 | *alias_0 = NULL, *mangle_0 = NULL; | |
6148 | Function *func, *last_func = NULL; | |
6149 | int one_func = 1; | |
6150 | ||
6151 | // Get the source/object/load-object files & aliases | |
6152 | long long ll_size = 0; | |
6153 | for (long i = 0; i < objs->size (); i++) | |
6154 | { | |
6155 | Histable *current_obj = objs->fetch (i); | |
6156 | Histable::Type htype = current_obj->get_type (); | |
6157 | if (htype == Histable::LOADOBJECT) | |
6158 | lname = ((LoadObject *) current_obj)->dbeFile->get_location_info (); | |
6159 | else if ((func = (Function*) current_obj->convertto (Histable::FUNCTION)) != NULL) | |
6160 | { | |
6161 | if (one_func && last_func != NULL && last_func != func) | |
6162 | one_func = 0; | |
6163 | last_func = func; | |
6164 | sname = NULL; | |
6165 | DbeLine *dbeline = (DbeLine*) current_obj->convertto (Histable::LINE); | |
6166 | if (dbeline) | |
6167 | { | |
6168 | SourceFile *sf; | |
6169 | if (dbeline->lineno == 0 && dbeline->include != NULL) | |
6170 | sf = dbeline->include; | |
6171 | else if (dbeline->sourceFile != NULL) | |
6172 | sf = dbeline->sourceFile; | |
6173 | else | |
6174 | sf = func->getDefSrc (); | |
6175 | if (sf) | |
6176 | sname = sf->dbeFile->get_location_info (); | |
6177 | } | |
6178 | char *func_name = func->get_name (); | |
6179 | mangle = func->get_mangled_name (); | |
6180 | if (mangle && streq (func_name, mangle)) | |
6181 | mangle = NULL; | |
6182 | Module *module = func->module; | |
6183 | if (module != NULL) | |
6184 | { | |
6185 | module->read_stabs (); | |
6186 | if (sname == NULL || strlen (sname) == 0) | |
6187 | { | |
6188 | SourceFile *sf = module->getMainSrc (); | |
6189 | sname = sf->dbeFile->get_location_info (); | |
6190 | } | |
6191 | DbeFile *df = module->dbeFile; | |
6192 | if (df == NULL || (df->filetype & DbeFile::F_JAVACLASS) == 0) | |
6193 | df = module->loadobject->dbeFile; | |
6194 | lname = df->get_location_info (); | |
6195 | oname = lname; | |
6196 | if (module->dot_o_file) | |
6197 | oname = module->dot_o_file->dbeFile->get_location_info (); | |
6198 | } | |
6199 | ||
6200 | if (htype == Histable::INSTR && dbeSession->is_datamode_available ()) | |
6201 | alias = ((DbeInstr*) current_obj)->get_descriptor (); | |
6202 | } | |
6203 | ||
6204 | char *name = current_obj->get_name (); | |
6205 | if (i == 0) | |
6206 | { | |
6207 | name_0 = name; | |
6208 | lname_0 = lname; | |
6209 | sname_0 = sname; | |
6210 | oname_0 = oname; | |
6211 | mangle_0 = mangle; | |
6212 | alias_0 = alias; | |
6213 | if (objs->size () == 1) | |
6214 | { | |
6215 | uint64_t addr = current_obj->get_addr (); | |
6216 | address = dbe_sprintf (NTXT ("%lld:0x%08llX"), | |
6217 | (long long) ADDRESS_SEG (addr), | |
6218 | (long long) ADDRESS_OFF (addr)); | |
6219 | } | |
6220 | } | |
6221 | else | |
6222 | { | |
6223 | if (name_0 != name) | |
6224 | name_0 = NULL; | |
6225 | if (lname_0 != lname) | |
6226 | lname_0 = NULL; | |
6227 | if (sname_0 != sname) | |
6228 | sname_0 = NULL; | |
6229 | if (oname_0 != oname) | |
6230 | oname_0 = NULL; | |
6231 | if (mangle_0 != mangle) | |
6232 | mangle_0 = NULL; | |
6233 | if (alias_0 != alias) | |
6234 | alias_0 = NULL; | |
6235 | } | |
6236 | if (current_obj->get_size () == -1) | |
6237 | { | |
6238 | if (size == NULL) | |
6239 | size = dbe_strdup (GTXT ("(Unknown)")); | |
6240 | } | |
6241 | else | |
6242 | ll_size += current_obj->get_size (); | |
6243 | } | |
6244 | if (size == NULL) | |
6245 | size = dbe_sprintf (NTXT ("%lld"), ll_size); | |
6246 | if (name_0 == NULL) | |
6247 | { | |
6248 | if (objs->size () > 1) | |
6249 | { | |
6250 | char *func_name = last_func == NULL ? NULL : | |
6251 | (one_func == 0 ? NULL : last_func->get_name ()); | |
6252 | name_0 = dbe_sprintf (NTXT ("%s%s%s (%lld %s)"), | |
6253 | func_name == NULL ? "" : func_name, | |
6254 | func_name == NULL ? "" : ": ", | |
6255 | GTXT ("Multiple Selection"), | |
6256 | (long long) objs->size (), | |
6257 | GTXT ("objects")); | |
6258 | } | |
6259 | } | |
6260 | else | |
6261 | name_0 = dbe_strdup (name_0); | |
6262 | ||
6263 | // Set the name area | |
6264 | saligns->store (0, TEXT_LEFT); | |
6265 | mnemonic->store (0, 'N'); | |
6266 | jlabels->store (0, dbe_strdup (GTXT ("Name"))); | |
6267 | jvalues->store (0, name_0); | |
6268 | ||
6269 | saligns->store (1, TEXT_LEFT); | |
6270 | mnemonic->store (1, 'P'); | |
6271 | jlabels->store (1, dbe_strdup (GTXT ("PC Address"))); | |
6272 | jvalues->store (1, address); | |
6273 | ||
6274 | saligns->store (2, TEXT_LEFT); | |
6275 | mnemonic->store (2, 'z'); | |
6276 | jlabels->store (2, dbe_strdup (GTXT ("Size"))); | |
6277 | jvalues->store (2, size); | |
6278 | ||
6279 | saligns->store (3, TEXT_RIGHT); | |
6280 | mnemonic->store (3, 'r'); | |
6281 | jlabels->store (3, dbe_strdup (GTXT ("Source File"))); | |
6282 | jvalues->store (3, dbe_strdup (sname_0)); | |
6283 | ||
6284 | saligns->store (4, TEXT_RIGHT); | |
6285 | mnemonic->store (4, 'b'); | |
6286 | jlabels->store (4, dbe_strdup (GTXT ("Object File"))); | |
6287 | jvalues->store (4, dbe_strdup (oname_0)); | |
6288 | ||
6289 | saligns->store (5, TEXT_LEFT); | |
6290 | mnemonic->store (5, 'j'); | |
6291 | jlabels->store (5, dbe_strdup (GTXT ("Load Object"))); | |
6292 | jvalues->store (5, dbe_strdup (lname_0)); | |
6293 | ||
6294 | saligns->store (6, TEXT_LEFT); | |
6295 | mnemonic->store (6, 'm'); | |
6296 | jlabels->store (6, dbe_strdup (GTXT ("Mangled Name"))); | |
6297 | jvalues->store (6, dbe_strdup (mangle_0)); | |
6298 | ||
6299 | saligns->store (7, TEXT_LEFT); | |
6300 | mnemonic->store (7, 'A'); | |
6301 | jlabels->store (7, dbe_strdup (GTXT ("Aliases"))); | |
6302 | jvalues->store (7, dbe_strdup (alias_0)); | |
6303 | } | |
6304 | ||
6305 | // Set memory-object summary list | |
6306 | // | |
6307 | static void | |
6308 | setMemSummary (Vector<Histable*> *objs, Vector<int> *saligns, | |
6309 | Vector<char> *mnemonic, Vector<char*> *jlabels, | |
6310 | Vector<char*> *jvalues) | |
6311 | { | |
6312 | saligns->store (0, TEXT_LEFT); | |
6313 | mnemonic->store (0, 'M'); | |
6314 | jlabels->store (0, dbe_strdup (GTXT ("Memory Object"))); | |
6315 | if (objs->size () == 1) | |
6316 | { | |
6317 | Histable *current_obj = objs->fetch (0); | |
6318 | jvalues->store (0, dbe_strdup (current_obj->get_name ())); | |
6319 | } | |
6320 | else | |
6321 | { | |
6322 | char *name = dbe_sprintf (NTXT ("%s (%lld %s)"), | |
6323 | GTXT ("Multiple Selection"), | |
6324 | (long long) objs->size (), GTXT ("objects")); | |
6325 | jvalues->store (0, name); | |
6326 | } | |
6327 | } | |
6328 | ||
6329 | // Set index-object summary list | |
6330 | // | |
6331 | static void | |
6332 | setIndxSummary (Vector<Histable*> *objs, Vector<int> *saligns, | |
6333 | Vector<char> *mnemonic, Vector<char*> *jlabels, | |
6334 | Vector<char*> *jvalues) | |
6335 | { | |
6336 | saligns->store (0, TEXT_LEFT); | |
6337 | mnemonic->store (0, 'I'); | |
6338 | jlabels->store (0, dbe_strdup (GTXT ("Index Object"))); | |
6339 | ||
6340 | if (objs->size () == 1) | |
6341 | { | |
6342 | Histable *current_obj = objs->fetch (0); | |
6343 | jvalues->store (0, dbe_strdup (current_obj->get_name ())); | |
6344 | } | |
6345 | else | |
6346 | { | |
6347 | char *name = dbe_sprintf (NTXT ("%s (%lld %s)"), GTXT ("Multiple Selection"), | |
6348 | (long long) objs->size (), GTXT ("objects")); | |
6349 | jvalues->store (0, name); | |
6350 | } | |
6351 | } | |
6352 | ||
6353 | // Set I/O activity summary list | |
6354 | // | |
6355 | static void | |
6356 | setIOActivitySummary (Vector<Histable*> *objs, Vector<int> *saligns, | |
6357 | Vector<char> *mnemonic, Vector<char*> *jlabels, | |
6358 | Vector<char*> *jvalues) | |
6359 | { | |
6360 | saligns->store (0, TEXT_LEFT); | |
6361 | mnemonic->store (0, 'O'); | |
6362 | jlabels->store (0, dbe_strdup (GTXT ("I/O Activity"))); | |
6363 | if (objs->size () == 1) | |
6364 | { | |
6365 | Histable *current_obj = objs->fetch (0); | |
6366 | jvalues->store (0, dbe_strdup (current_obj->get_name ())); | |
6367 | } | |
6368 | else | |
6369 | { | |
6370 | char *name = dbe_sprintf (NTXT ("%s (%lld %s)"), GTXT ("Multiple Selection"), | |
6371 | (long long) objs->size (), GTXT ("objects")); | |
6372 | jvalues->store (0, name); | |
6373 | } | |
6374 | } | |
6375 | ||
6376 | // Set heap activity summary list | |
6377 | // | |
6378 | static void | |
6379 | setHeapActivitySummary (Vector<Histable*> *objs, Vector<int> *saligns, | |
6380 | Vector<char> *mnemonic, Vector<char*> *jlabels, | |
6381 | Vector<char*> *jvalues) | |
6382 | { | |
6383 | saligns->store (0, TEXT_LEFT); | |
6384 | mnemonic->store (0, 'O'); | |
6385 | jlabels->store (0, dbe_strdup (GTXT ("Heap Activity"))); | |
6386 | ||
6387 | if (objs->size () == 1) | |
6388 | { | |
6389 | Histable *current_obj = objs->fetch (0); | |
6390 | jvalues->store (0, dbe_strdup (current_obj->get_name ())); | |
6391 | } | |
6392 | else | |
6393 | { | |
6394 | char *name = dbe_sprintf (NTXT ("%s (%lld %s)"), GTXT ("Multiple Selection"), | |
6395 | (long long) objs->size (), GTXT ("objects")); | |
6396 | jvalues->store (0, name); | |
6397 | } | |
6398 | } | |
6399 | ||
6400 | // | |
6401 | // Set data-object summary list | |
6402 | // | |
6403 | static void | |
6404 | setDataSummary (Vector<Histable*> *objs, Vector<int> *saligns, | |
6405 | Vector<char> *mnemonic, Vector<char*> *jlabels, | |
6406 | Vector<char*> *jvalues) | |
6407 | { | |
6408 | char *name, *type, *member, *elist; | |
6409 | DataObject *dobj; | |
6410 | Vector<DataObject *> *delem; | |
6411 | Histable *scope; | |
6412 | int index; | |
6413 | char *size, *offset, *elements, *scopename; | |
6414 | ||
6415 | // Get the data object elements | |
6416 | member = elist = type = size = offset = elements = scopename = NULL; | |
6417 | ||
6418 | if (objs->size () == 1) | |
6419 | { | |
6420 | Histable *current_obj = objs->fetch (0); | |
6421 | name = dbe_strdup (current_obj->get_name ()); | |
6422 | dobj = (DataObject *) current_obj; | |
6423 | type = dobj->get_typename (); | |
6424 | scope = dobj->get_scope (); | |
6425 | delem = dbeSession->get_dobj_elements (dobj); | |
6426 | if (type == NULL) | |
6427 | type = GTXT ("(Synthetic)"); | |
6428 | if (!scope) | |
6429 | scopename = dbe_strdup (GTXT ("(Global)")); | |
6430 | else | |
6431 | { | |
6432 | switch (scope->get_type ()) | |
6433 | { | |
6434 | case Histable::FUNCTION: | |
6435 | scopename = dbe_sprintf (NTXT ("%s(%s)"), | |
6436 | ((Function*) scope)->module->get_name (), | |
6437 | scope->get_name ()); | |
6438 | break; | |
6439 | case Histable::LOADOBJECT: | |
6440 | case Histable::MODULE: | |
6441 | default: | |
6442 | scopename = dbe_strdup (scope->get_name ()); | |
6443 | break; | |
6444 | } | |
6445 | } | |
6446 | ||
6447 | if (dobj->get_offset () != -1) | |
6448 | { | |
6449 | if (dobj->get_parent ()) | |
6450 | member = dbe_strdup (dobj->get_parent ()->get_name ()); | |
6451 | offset = dbe_sprintf (NTXT ("%lld"), (long long) dobj->get_offset ()); | |
6452 | } | |
6453 | size = dbe_sprintf ("%lld", (long long) dobj->get_size ()); | |
6454 | ||
6455 | if (delem->size () > 0) | |
6456 | { | |
6457 | elements = dbe_sprintf (NTXT ("%lld"), (long long) delem->size ()); | |
6458 | StringBuilder sb_tmp, sb; | |
6459 | sb.append (GTXT ("Offset Size Name\n")); | |
6460 | for (index = 0; index < delem->size (); index++) | |
6461 | { | |
6462 | DataObject *ditem = delem->fetch (index); | |
6463 | sb_tmp.sprintf (NTXT ("%6lld %5lld %s\n"), | |
6464 | (long long) ditem->get_offset (), | |
6465 | (long long) ditem->get_size (), ditem->get_name ()); | |
6466 | sb.append (&sb_tmp); | |
6467 | } | |
6468 | if (sb.charAt (sb.length () - 1) == '\n') | |
6469 | sb.setLength (sb.length () - 1); | |
6470 | elist = sb.toString (); | |
6471 | } | |
6472 | } | |
6473 | else | |
6474 | name = dbe_sprintf (NTXT ("%s (%lld %s)"), GTXT ("Multiple Selection"), | |
6475 | (long long) objs->size (), GTXT ("objects")); | |
6476 | ||
6477 | saligns->store (0, TEXT_LEFT); | |
6478 | mnemonic->store (0, 'D'); | |
6479 | jlabels->store (0, dbe_strdup (GTXT ("Data Object"))); | |
6480 | jvalues->store (0, name); | |
6481 | ||
6482 | saligns->store (1, TEXT_LEFT); | |
6483 | mnemonic->store (1, 'S'); | |
6484 | jlabels->store (1, dbe_strdup (GTXT ("Scope"))); | |
6485 | jvalues->store (1, scopename); | |
6486 | ||
6487 | saligns->store (2, TEXT_LEFT); | |
6488 | mnemonic->store (2, 'T'); | |
6489 | jlabels->store (2, dbe_strdup (GTXT ("Type"))); | |
6490 | jvalues->store (2, dbe_strdup (type)); | |
6491 | ||
6492 | saligns->store (3, TEXT_LEFT); | |
6493 | mnemonic->store (3, 'M'); | |
6494 | jlabels->store (3, dbe_strdup (GTXT ("Member of"))); | |
6495 | jvalues->store (3, member); | |
6496 | ||
6497 | saligns->store (4, TEXT_LEFT); | |
6498 | mnemonic->store (4, 'O'); | |
6499 | jlabels->store (4, dbe_strdup (GTXT ("Offset"))); | |
6500 | jvalues->store (4, offset); | |
6501 | ||
6502 | saligns->store (5, TEXT_LEFT); | |
6503 | mnemonic->store (5, 'z'); | |
6504 | jlabels->store (5, dbe_strdup (GTXT ("Size"))); | |
6505 | jvalues->store (5, size); | |
6506 | ||
6507 | saligns->store (6, TEXT_LEFT); | |
6508 | mnemonic->store (6, 'E'); | |
6509 | jlabels->store (6, dbe_strdup (GTXT ("Elements"))); | |
6510 | jvalues->store (6, elements); | |
6511 | ||
6512 | saligns->store (7, TEXT_LEFT); | |
6513 | mnemonic->store (7, 'L'); | |
6514 | jlabels->store (7, dbe_strdup (GTXT ("List"))); | |
6515 | jvalues->store (7, elist); | |
6516 | } | |
6517 | ||
6518 | #define SUMMARY_NAME 8 | |
6519 | #define DSUMMARY_NAME 8 | |
6520 | #define LSUMMARY_NAME 7 | |
6521 | #define IMSUMMARY_NAME 1 | |
6522 | ||
6523 | Vector<void*> * | |
6524 | dbeGetSummaryV2 (int dbevindex, Vector<Obj> *sel_objs, int type, int subtype) | |
6525 | { | |
6526 | if (sel_objs == NULL || sel_objs->size () == 0) | |
6527 | return NULL; | |
6528 | DbeView *dbev = dbeSession->getView (dbevindex); | |
6529 | Vector<Histable*>*objs = new Vector<Histable*>(sel_objs->size ()); | |
6530 | for (int i = 0; i < sel_objs->size (); i++) | |
6531 | { | |
6532 | Histable *obj = (Histable *) sel_objs->fetch (i); | |
6533 | if (obj == NULL) | |
6534 | continue; | |
6535 | char *nm = obj->get_name (); | |
6536 | if (streq (nm, NTXT ("<Total>"))) | |
6537 | { | |
6538 | // Special case for 'Total'. | |
6539 | // Multi selection which includes 'Total' is only 'Total' | |
6540 | objs->reset (); | |
6541 | objs->append (obj); | |
6542 | break; | |
6543 | } | |
6544 | objs->append (obj); | |
6545 | } | |
6546 | if (objs->size () == 0) | |
6547 | return NULL; | |
6548 | ||
6549 | // Set name area | |
6550 | int nname = SUMMARY_NAME; | |
6551 | Vector<int> *saligns = new Vector<int>(nname); | |
6552 | Vector<char>*mnemonic = new Vector<char>(nname); | |
6553 | Vector<char*> *jlabels = new Vector<char*>(nname); | |
6554 | Vector<char*> *jvalues = new Vector<char*>(nname); | |
6555 | Vector<void*> *name_objs = new Vector<void*>(4); | |
6556 | name_objs->store (0, saligns); | |
6557 | name_objs->store (1, mnemonic); | |
6558 | name_objs->store (2, jlabels); | |
6559 | name_objs->store (3, jvalues); | |
6560 | setSummary (objs, saligns, mnemonic, jlabels, jvalues); | |
6561 | ||
6562 | MetricList *prop_mlist = new MetricList (dbev->get_metric_ref (MET_NORMAL)); | |
6563 | if (prop_mlist && dbev->comparingExperiments ()) | |
6564 | prop_mlist = dbev->get_compare_mlist (prop_mlist, 0); | |
6565 | ||
6566 | int nitems = prop_mlist->get_items ()->size (); | |
6567 | ||
6568 | // Set the metrics area | |
6569 | jlabels = new Vector<char*>(nitems); | |
6570 | Vector<double> *clock_list = new Vector<double>(nitems); | |
6571 | Vector<double> *excl_list = new Vector<double>(nitems); | |
6572 | Vector<double> *ep_list = new Vector<double>(nitems); | |
6573 | Vector<double> *incl_list = new Vector<double>(nitems); | |
6574 | Vector<double> *ip_list = new Vector<double>(nitems); | |
6575 | Vector<int> *vtype = new Vector<int>(nitems); | |
6576 | ||
6577 | // Initialize Java String array | |
6578 | Vector<void*> *metric_objs = new Vector<void*>(8); | |
6579 | metric_objs->store (0, jlabels); | |
6580 | metric_objs->store (1, clock_list); | |
6581 | metric_objs->store (2, excl_list); | |
6582 | metric_objs->store (3, ep_list); | |
6583 | metric_objs->store (4, incl_list); | |
6584 | metric_objs->store (5, ip_list); | |
6585 | metric_objs->store (6, vtype); | |
6586 | ||
6587 | int last_init = -1; | |
6588 | for (int i = 0; i < objs->size (); i++) | |
6589 | { | |
6590 | Histable *obj = objs->fetch (i); | |
6591 | // Get the data to be displayed | |
6592 | Hist_data *data = dbev->get_hist_data (prop_mlist, obj->get_type (), subtype, | |
6593 | Hist_data::SELF, obj, dbev->sel_binctx, objs); | |
6594 | ||
6595 | if (data->get_status () != Hist_data::SUCCESS) | |
6596 | { | |
6597 | if (type != DSP_DLAYOUT) | |
6598 | { // For data_layout, rows with zero metrics are OK | |
6599 | delete data; | |
6600 | continue; | |
6601 | } | |
6602 | } | |
6603 | TValue *values = NULL; | |
6604 | if (data->get_status () == Hist_data::SUCCESS) | |
6605 | { | |
6606 | Hist_data::HistItem *hi = data->fetch (0); | |
6607 | if (hi) | |
6608 | values = hi->value; | |
6609 | } | |
6610 | Hist_data::HistItem *total = data->get_totals (); | |
6611 | int index2 = 0; | |
6612 | char *tstr = GTXT (" Time"); | |
6613 | char *estr = GTXT ("Exclusive "); | |
6614 | size_t len = strlen (estr); | |
6615 | ||
6616 | // get the metric list from the data | |
6617 | MetricList *mlist = data->get_metric_list (); | |
6618 | int index; | |
6619 | Metric *mitem; | |
6620 | double clock; | |
6621 | Vec_loop (Metric*, mlist->get_items (), index, mitem) | |
6622 | { | |
6623 | if (mitem->get_subtype () == Metric::STATIC) | |
6624 | continue; | |
6625 | if (last_init < index2) | |
6626 | { | |
6627 | last_init = index2; | |
6628 | jlabels->store (index2, NULL); | |
6629 | clock_list->store (index2, 0.0); | |
6630 | excl_list->store (index2, 0.0); | |
6631 | ep_list->store (index2, 0.0); | |
6632 | incl_list->store (index2, 0.0); | |
6633 | ip_list->store (index2, 0.0); | |
6634 | vtype->store (index2, 0); | |
6635 | } | |
6636 | double dvalue = (values != NULL) ? values[index].to_double () : 0.0; | |
6637 | double dtotal = total->value[index].to_double (); | |
6638 | if (mitem->is_time_val ()) | |
6639 | clock = 1.e+6 * dbeSession->get_clock (-1); | |
6640 | else | |
6641 | clock = 0.0; | |
6642 | ||
6643 | clock_list->store (index2, clock); | |
6644 | if ((mitem->get_subtype () == Metric::EXCLUSIVE) || | |
6645 | (mitem->get_subtype () == Metric::DATASPACE)) | |
6646 | { | |
6647 | if (i == 0) | |
6648 | { | |
6649 | char *sstr = mitem->get_name (); | |
6650 | if (!strncmp (sstr, estr, len)) | |
6651 | sstr += len; | |
6652 | char *buf, *lstr = strstr (sstr, tstr); | |
6653 | if (lstr) | |
6654 | buf = dbe_strndup (sstr, lstr - sstr); | |
6655 | else | |
6656 | buf = dbe_strdup (sstr); | |
6657 | jlabels->store (index2, buf); | |
6658 | vtype->store (index2, mitem->get_vtype ()); | |
6659 | } | |
6660 | dvalue += excl_list->fetch (index2); | |
6661 | double percent = dtotal == 0.0 ? dtotal : (dvalue / dtotal) * 100; | |
6662 | excl_list->store (index2, dvalue); | |
6663 | ep_list->store (index2, percent); | |
6664 | } | |
6665 | else | |
6666 | { | |
6667 | dvalue += incl_list->fetch (index2); | |
6668 | if (dvalue > dtotal) | |
6669 | dvalue = dtotal; // temporary correction | |
6670 | double percent = dtotal == 0.0 ? dtotal : (dvalue / dtotal) * 100; | |
6671 | incl_list->store (index2, dvalue); | |
6672 | ip_list->store (index2, percent); | |
6673 | index2++; | |
6674 | } | |
6675 | } | |
6676 | delete data; | |
6677 | } | |
6678 | delete prop_mlist; | |
6679 | Vector<void*> *summary = new Vector<void*>(2); | |
6680 | summary->store (0, name_objs); | |
6681 | summary->store (1, metric_objs); | |
6682 | return summary; | |
6683 | } | |
6684 | ||
6685 | // Get Summary List | |
6686 | Vector<void*> * | |
6687 | dbeGetSummary (int dbevindex, Vector<Obj> *sel_objs, int type, int subtype) | |
6688 | { | |
6689 | bool is_data, is_mem, is_indx, is_iodata, is_heapdata; | |
6690 | Hist_data::HistItem *total; | |
6691 | MetricList *prop_mlist; // as passed to get_hist_data | |
6692 | MetricList *mlist; // as stored in the data | |
6693 | Metric *mitem; | |
6694 | int i, nname, nitems, index, index2; | |
6695 | TValue *values; | |
6696 | double dvalue, clock; | |
6697 | Hist_data *data; | |
6698 | Vector<double> *percent_scale; | |
6699 | ||
6700 | DbeView *dbev = dbeSession->getView (dbevindex); | |
6701 | if (dbev == NULL) | |
6702 | abort (); | |
6703 | if (sel_objs == NULL || sel_objs->size () == 0) | |
6704 | return NULL; | |
6705 | ||
6706 | is_mem = false; | |
6707 | is_data = false; | |
6708 | is_indx = false; | |
6709 | is_iodata = false; | |
6710 | is_heapdata = false; | |
6711 | nname = SUMMARY_NAME; | |
6712 | Vector<Histable*>*objs = new Vector<Histable*>(sel_objs->size ()); | |
6713 | if (type == DSP_TIMELINE) | |
6714 | objs->append ((Histable *) sel_objs->fetch (0)); | |
6715 | else | |
6716 | { | |
6717 | switch (type) | |
6718 | { | |
6719 | case DSP_FUNCTION: | |
6720 | data = dbev->func_data; | |
6721 | break; | |
6722 | case DSP_LINE: | |
6723 | data = dbev->line_data; | |
6724 | break; | |
6725 | case DSP_PC: | |
6726 | data = dbev->pc_data; | |
6727 | break; | |
6728 | case DSP_SELF: | |
6729 | data = dbev->fitem_data; | |
6730 | break; | |
6731 | case DSP_SOURCE: | |
6732 | case DSP_SOURCE_V2: | |
6733 | data = dbev->src_data; | |
6734 | break; | |
6735 | case DSP_DISASM: | |
6736 | case DSP_DISASM_V2: | |
6737 | data = dbev->dis_data; | |
6738 | break; | |
6739 | case DSP_DLAYOUT: | |
6740 | is_data = true; | |
6741 | nname = LSUMMARY_NAME; | |
6742 | data = dbev->dlay_data; | |
6743 | break; | |
6744 | case DSP_DATAOBJ: | |
6745 | is_data = true; | |
6746 | nname = DSUMMARY_NAME; | |
6747 | data = dbev->dobj_data; | |
6748 | break; | |
6749 | case DSP_MEMOBJ: | |
6750 | is_data = true; | |
6751 | is_mem = true; | |
6752 | nname = IMSUMMARY_NAME; | |
6753 | data = dbev->get_indxobj_data (subtype); | |
6754 | break; | |
6755 | case DSP_INDXOBJ: | |
6756 | is_indx = true; | |
6757 | nname = IMSUMMARY_NAME; | |
6758 | data = dbev->get_indxobj_data (subtype); | |
6759 | break; | |
6760 | case DSP_IOACTIVITY: | |
6761 | is_iodata = true; | |
6762 | nname = IMSUMMARY_NAME; | |
6763 | data = dbev->iofile_data; | |
6764 | break; | |
6765 | case DSP_IOVFD: | |
6766 | is_iodata = true; | |
6767 | nname = IMSUMMARY_NAME; | |
6768 | data = dbev->iovfd_data; | |
6769 | break; | |
6770 | case DSP_IOCALLSTACK: | |
6771 | is_iodata = true; | |
6772 | nname = IMSUMMARY_NAME; | |
6773 | data = dbev->iocs_data; | |
6774 | break; | |
6775 | case DSP_HEAPCALLSTACK: | |
6776 | is_heapdata = true; | |
6777 | nname = IMSUMMARY_NAME; | |
6778 | data = dbev->heapcs_data; | |
6779 | break; | |
6780 | default: | |
6781 | data = NULL; | |
6782 | break; | |
6783 | } | |
6784 | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | |
6785 | return NULL; | |
6786 | ||
6787 | Hist_data::HistItem *current_item; | |
6788 | for (i = 0; i < sel_objs->size (); i++) | |
6789 | { | |
6790 | int sel_index = (int) sel_objs->fetch (i); | |
6791 | if (type != DSP_IOACTIVITY && type != DSP_IOVFD && | |
6792 | type != DSP_IOCALLSTACK && type != DSP_HEAPCALLSTACK) | |
6793 | { | |
6794 | if (sel_index < 0 || sel_index >= data->size ()) | |
6795 | continue; | |
6796 | current_item = data->fetch (sel_index); | |
6797 | if (current_item->obj == NULL) | |
6798 | continue; | |
6799 | } | |
6800 | else | |
6801 | { | |
6802 | if (sel_index < 0) | |
6803 | continue; | |
6804 | bool found = false; | |
6805 | for (int j = 0; j < data->size (); j++) | |
6806 | { | |
6807 | current_item = data->fetch (j); | |
6808 | if ((current_item->obj != NULL) && (current_item->obj->id == sel_index)) | |
6809 | { | |
6810 | found = true; | |
6811 | break; | |
6812 | } | |
6813 | } | |
6814 | if (!found) | |
6815 | continue; | |
6816 | } | |
6817 | char *nm = current_item->obj->get_name (); | |
6818 | if (streq (nm, NTXT ("<Total>"))) | |
6819 | { | |
6820 | // Special case for 'Total'. | |
6821 | // Multi selection which includes 'Total' is only 'Total' | |
6822 | objs->reset (); | |
6823 | objs->append (current_item->obj); | |
6824 | break; | |
6825 | } | |
6826 | objs->append (current_item->obj); | |
6827 | } | |
6828 | } | |
6829 | if (objs->size () == 0) | |
6830 | return NULL; | |
6831 | ||
6832 | // Set name area | |
6833 | Vector<int> *saligns = new Vector<int>(nname); | |
6834 | Vector<char>*mnemonic = new Vector<char>(nname); | |
6835 | Vector<char*> *jlabels = new Vector<char*>(nname); | |
6836 | Vector<char*> *jvalues = new Vector<char*>(nname); | |
6837 | Vector<void*> *name_objs = new Vector<void*>(4); | |
6838 | name_objs->store (0, saligns); | |
6839 | name_objs->store (1, mnemonic); | |
6840 | name_objs->store (2, jlabels); | |
6841 | name_objs->store (3, jvalues); | |
6842 | if (is_mem) | |
6843 | setMemSummary (objs, saligns, mnemonic, jlabels, jvalues); | |
6844 | else if (is_indx) | |
6845 | setIndxSummary (objs, saligns, mnemonic, jlabels, jvalues); | |
6846 | else if (is_data) | |
6847 | setDataSummary (objs, saligns, mnemonic, jlabels, jvalues); | |
6848 | else if (is_iodata) | |
6849 | setIOActivitySummary (objs, saligns, mnemonic, jlabels, jvalues); | |
6850 | else if (is_heapdata) | |
6851 | setHeapActivitySummary (objs, saligns, mnemonic, jlabels, jvalues); | |
6852 | else | |
6853 | setSummary (objs, saligns, mnemonic, jlabels, jvalues); | |
6854 | ||
6855 | // Get the reference metrics | |
6856 | if (is_data) | |
6857 | prop_mlist = new MetricList (dbev->get_metric_ref (MET_DATA)); | |
6858 | else if (is_indx) | |
6859 | prop_mlist = new MetricList (dbev->get_metric_ref (MET_INDX)); | |
6860 | else if (is_iodata) | |
6861 | prop_mlist = new MetricList (dbev->get_metric_ref (MET_IO)); | |
6862 | else if (is_heapdata) | |
6863 | prop_mlist = new MetricList (dbev->get_metric_ref (MET_HEAP)); | |
6864 | else | |
6865 | prop_mlist = new MetricList (dbev->get_metric_ref (MET_NORMAL)); | |
6866 | ||
6867 | // XXXX a workaround to avoid aggregated data for compare mode, only show base experiment data | |
6868 | if (prop_mlist && dbev->comparingExperiments ()) | |
6869 | prop_mlist = dbev->get_compare_mlist (prop_mlist, 0); | |
6870 | nitems = prop_mlist->get_items ()->size (); | |
6871 | ||
6872 | // Set the metrics area | |
6873 | jlabels = new Vector<char*>(nitems); | |
6874 | Vector<double> *clock_list = new Vector<double>(nitems); | |
6875 | Vector<double> *excl_list = new Vector<double>(nitems); | |
6876 | Vector<double> *ep_list = new Vector<double>(nitems); | |
6877 | Vector<double> *incl_list = new Vector<double>(nitems); | |
6878 | Vector<double> *ip_list = new Vector<double>(nitems); | |
6879 | Vector<int> *vtype = new Vector<int>(nitems); | |
6880 | ||
6881 | // Initialize Java String array | |
6882 | Vector<void*> *metric_objs = new Vector<void*>(8); | |
6883 | metric_objs->store (0, jlabels); | |
6884 | metric_objs->store (1, clock_list); | |
6885 | metric_objs->store (2, excl_list); | |
6886 | metric_objs->store (3, ep_list); | |
6887 | metric_objs->store (4, incl_list); | |
6888 | metric_objs->store (5, ip_list); | |
6889 | metric_objs->store (6, vtype); | |
6890 | percent_scale = new Vector<double>(); | |
6891 | int last_init = -1; | |
6892 | for (i = 0; i < objs->size (); i++) | |
6893 | { | |
6894 | Histable *current_obj = objs->fetch (i); | |
6895 | // Get the data to be displayed | |
6896 | data = dbev->get_hist_data (prop_mlist, current_obj->get_type (), subtype, | |
6897 | Hist_data::SELF, current_obj, dbev->sel_binctx, objs); | |
6898 | if (data->get_status () != Hist_data::SUCCESS) | |
6899 | { | |
6900 | if (type != DSP_DLAYOUT) | |
6901 | { // For data_layout, rows with zero metrics are OK | |
6902 | delete data; | |
6903 | continue; | |
6904 | } | |
6905 | } | |
6906 | Hist_data::HistItem *hi = data->fetch (0); | |
6907 | values = hi ? hi->value : NULL; | |
6908 | total = data->get_totals (); | |
6909 | index2 = 0; | |
6910 | ||
6911 | // get the metric list from the data | |
6912 | mlist = data->get_metric_list (); | |
6913 | ||
6914 | // We loop over the metrics in mlist. | |
6915 | // We construct index2, which tells us | |
6916 | // the corresponding entry in the metric_objs lists. | |
6917 | // We need this mapping multiple times. | |
6918 | // So, if you change the looping in any way here, | |
6919 | // do so as well in other similar loops. | |
6920 | // All such loops are marked so: | |
6921 | // See discussion on "mlist-to-index2 mapping". | |
6922 | ||
6923 | Vec_loop (Metric*, mlist->get_items (), index, mitem) | |
6924 | { | |
6925 | if (mitem->get_subtype () == Metric::STATIC) | |
6926 | continue; | |
6927 | if (last_init < index2) | |
6928 | { | |
6929 | last_init = index2; | |
6930 | jlabels->store (index2, NULL); | |
6931 | clock_list->store (index2, 0.0); | |
6932 | excl_list->store (index2, 0.0); | |
6933 | ep_list->store (index2, 0.0); | |
6934 | incl_list->store (index2, 0.0); | |
6935 | ip_list->store (index2, 0.0); | |
6936 | vtype->store (index2, 0); | |
6937 | } | |
6938 | dvalue = (values != NULL) ? values[index].to_double () : 0.0; | |
6939 | double dtotal = total->value[index].to_double (); | |
6940 | percent_scale->store (index, dtotal == 0. ? 0. : 100. / dtotal); | |
6941 | if (mitem->is_time_val ()) | |
6942 | clock = 1.e+6 * dbeSession->get_clock (-1); | |
6943 | else | |
6944 | clock = 0.0; | |
6945 | ||
6946 | clock_list->store (index2, clock); | |
6947 | if (mitem->get_subtype () == Metric::EXCLUSIVE || | |
6948 | mitem->get_subtype () == Metric::DATASPACE) | |
6949 | { | |
6950 | if (i == 0) | |
6951 | { | |
6952 | char *sstr = mitem->get_username (); | |
6953 | char *buf = dbe_strdup (sstr); | |
6954 | jlabels->store (index2, buf); | |
6955 | vtype->store (index2, mitem->get_vtype ()); | |
6956 | } | |
6957 | dvalue += excl_list->fetch (index2); | |
6958 | double percent = dvalue * percent_scale->fetch (index); | |
6959 | excl_list->store (index2, dvalue); | |
6960 | ep_list->store (index2, percent); | |
6961 | if (is_data || is_indx || is_iodata || is_heapdata) | |
6962 | // move to next row, except if there's inclusive data, too | |
6963 | index2++; | |
6964 | } | |
6965 | else | |
6966 | { | |
6967 | dvalue += incl_list->fetch (index2); | |
6968 | if (dvalue > dtotal && mitem->get_type () != BaseMetric::DERIVED) | |
6969 | dvalue = dtotal; // temporary correction | |
6970 | double percent = dvalue * percent_scale->fetch (index); | |
6971 | incl_list->store (index2, dvalue); | |
6972 | ip_list->store (index2, percent); | |
6973 | index2++; | |
6974 | } | |
6975 | } | |
6976 | delete data; | |
6977 | } | |
6978 | ||
6979 | // for multi-selection, we have to recompute the derived metrics | |
6980 | if (objs->size () > 1 && | |
6981 | dbev->get_derived_metrics () != NULL && | |
6982 | dbev->get_derived_metrics ()->get_items () != NULL && | |
6983 | dbev->get_derived_metrics ()->get_items ()->size () > 0) | |
6984 | { | |
6985 | // See discussion on "mlist-to-index2 mapping". | |
6986 | Vector<Metric*> *mvec = new Vector<Metric*>(nitems); | |
6987 | index2 = 0; | |
6988 | Vec_loop (Metric*, prop_mlist->get_items (), index, mitem) | |
6989 | { | |
6990 | if (mitem->get_subtype () == Metric::STATIC) | |
6991 | continue; | |
6992 | if (mitem->get_subtype () == Metric::EXCLUSIVE || | |
6993 | mitem->get_subtype () == Metric::DATASPACE) | |
6994 | { | |
6995 | mvec->store (index2, mitem); | |
6996 | if (is_data || is_indx || is_iodata || is_heapdata) | |
6997 | index2++; | |
6998 | } | |
6999 | else | |
7000 | { | |
7001 | assert (strcmp (mvec->fetch (index2)->get_cmd (), mitem->get_cmd ()) == 0); | |
7002 | index2++; | |
7003 | } | |
7004 | } | |
7005 | int *map = dbev->get_derived_metrics ()->construct_map (mvec, BaseMetric::EXCLUSIVE, mvec->fetch (0)->get_expr_spec ()); | |
7006 | if (map != NULL) | |
7007 | { | |
7008 | int nmetrics = mvec->size (); | |
7009 | double *evalues = (double *) malloc (nmetrics * sizeof (double)); | |
7010 | double *ivalues = (double *) malloc (nmetrics * sizeof (double)); | |
7011 | for (index2 = 0; index2 < nmetrics; index2++) | |
7012 | { | |
7013 | evalues[index2] = excl_list->fetch (index2); | |
7014 | ivalues[index2] = incl_list->fetch (index2); | |
7015 | } | |
7016 | ||
7017 | // evaluate derived metrics | |
7018 | dbev->get_derived_metrics ()->eval (map, evalues); | |
7019 | dbev->get_derived_metrics ()->eval (map, ivalues); | |
7020 | for (index2 = 0; index2 < nmetrics; index2++) | |
7021 | { | |
7022 | excl_list->store (index2, evalues[index2]); | |
7023 | incl_list->store (index2, ivalues[index2]); | |
7024 | } | |
7025 | ||
7026 | // recompute percentages for derived metrics EUGENE maybe all percentage computations should be moved here | |
7027 | // See discussion on "mlist-to-index2 mapping". | |
7028 | index2 = 0; | |
7029 | Vec_loop (Metric*, prop_mlist->get_items (), index, mitem) | |
7030 | { | |
7031 | if (mitem->get_subtype () == Metric::STATIC) | |
7032 | continue; | |
7033 | if (mitem->get_subtype () == Metric::EXCLUSIVE || | |
7034 | mitem->get_subtype () == Metric::DATASPACE) | |
7035 | { | |
7036 | if (mitem->get_type () == BaseMetric::DERIVED) | |
7037 | ep_list->store (index2, excl_list->fetch (index2) * percent_scale->fetch (index)); | |
7038 | if (is_data || is_indx || is_iodata || is_heapdata) | |
7039 | index2++; | |
7040 | } | |
7041 | else | |
7042 | { | |
7043 | if (mitem->get_type () == BaseMetric::DERIVED) | |
7044 | ip_list->store (index2, incl_list->fetch (index2) * percent_scale->fetch (index)); | |
7045 | index2++; | |
7046 | } | |
7047 | } | |
7048 | free (evalues); | |
7049 | free (ivalues); | |
7050 | free (map); | |
7051 | } | |
7052 | delete mvec; | |
7053 | } | |
7054 | delete prop_mlist; | |
7055 | Vector<void*> *summary = new Vector<void*>(2); | |
7056 | summary->store (0, name_objs); | |
7057 | summary->store (1, metric_objs); | |
7058 | delete objs; | |
7059 | delete percent_scale; | |
7060 | return summary; | |
7061 | } | |
7062 | ||
7063 | char * | |
7064 | dbeGetExpName (int /*dbevindex*/, char *dir_name) | |
7065 | { | |
7066 | char *ret; | |
7067 | char *warn; | |
7068 | if (col_ctr == NULL) | |
7069 | col_ctr = new Coll_Ctrl (1); // Potential race condition? | |
7070 | if (dir_name != NULL) | |
7071 | { | |
7072 | ret = col_ctr->set_directory (dir_name, &warn); | |
7073 | // note that the warning and error msgs are written to stderr, not returned to caller | |
7074 | if (warn != NULL) | |
7075 | fprintf (stderr, NTXT ("%s"), warn); | |
7076 | if (ret != NULL) | |
7077 | fprintf (stderr, NTXT ("%s"), ret); | |
7078 | } | |
7079 | return dbe_strdup (col_ctr->get_expt ()); | |
7080 | } | |
7081 | ||
7082 | // === CollectDialog HWC info === | |
7083 | ||
7084 | Vector<Vector<char*>*> * | |
7085 | dbeGetHwcSets (int /*dbevindex*/, bool forKernel) | |
7086 | { | |
7087 | Vector<Vector<char*>*> *list = new Vector<Vector<char*>*>(2); | |
7088 | char * defctrs = hwc_get_default_cntrs2 (forKernel, 1); | |
7089 | Vector<char*> *i18n = new Vector<char*>(1); // User name | |
7090 | Vector<char*> *name = new Vector<char*>(1); // Internal name | |
7091 | if (NULL != defctrs) | |
7092 | { | |
7093 | i18n->store (0, strdup (defctrs)); | |
7094 | name->store (0, strdup (NTXT ("default"))); | |
7095 | } | |
7096 | list->store (0, i18n); | |
7097 | list->store (1, name); | |
7098 | return list; | |
7099 | } | |
7100 | ||
7101 | static Vector<void*> * | |
7102 | dbeGetHwcs (Hwcentry **hwcs) | |
7103 | { | |
7104 | int sz; | |
7105 | for (sz = 0; hwcs && hwcs[sz]; sz++) | |
7106 | ; | |
7107 | Vector<void*> *list = new Vector<void*>(9); | |
7108 | Vector<char*> *i18n = new Vector<char*>(sz); | |
7109 | Vector<char*> *name = new Vector<char*>(sz); | |
7110 | Vector<char*> *int_name = new Vector<char*>(sz); | |
7111 | Vector<char*> *metric = new Vector<char*>(sz); | |
7112 | Vector<long long> *val = new Vector<long long>(sz); | |
7113 | Vector<int> *timecvt = new Vector<int>(sz); | |
7114 | Vector<int> *memop = new Vector<int>(sz); | |
7115 | Vector<char*> *short_desc = new Vector<char*>(sz); | |
7116 | Vector<Vector<int>*> *reglist_v = new Vector<Vector<int>*>(sz); | |
7117 | Vector<bool> *supportsAttrs = new Vector<bool>(sz); | |
7118 | Vector<bool> *supportsMemspace = new Vector<bool>(sz); | |
7119 | ||
7120 | for (int i = 0; i < sz; i++) | |
7121 | { | |
7122 | Hwcentry *ctr = hwcs[i]; | |
7123 | Vector<int> *registers = new Vector<int>(MAX_PICS); | |
7124 | regno_t *reglist = ctr->reg_list; | |
7125 | for (int k = 0; !REG_LIST_EOL (reglist[k]) && k < MAX_PICS; k++) | |
7126 | registers->store (k, reglist[k]); | |
7127 | ||
7128 | i18n->store (i, dbe_strdup (hwc_i18n_metric (ctr))); | |
7129 | name->store (i, dbe_strdup (ctr->name)); | |
7130 | int_name->store (i, dbe_strdup (ctr->int_name)); | |
7131 | metric->store (i, dbe_strdup (ctr->metric)); | |
7132 | val->store (i, ctr->val); // signed promotion from int | |
7133 | timecvt->store (i, ctr->timecvt); | |
7134 | memop->store (i, ctr->memop); | |
7135 | reglist_v->store (i, registers); | |
7136 | short_desc->store (i, dbe_strdup (ctr->short_desc)); | |
7137 | supportsAttrs->store (i, true); | |
7138 | supportsMemspace->store (i, ABST_MEMSPACE_ENABLED (ctr->memop)); | |
7139 | } | |
7140 | list->store (0, i18n); | |
7141 | list->store (1, name); | |
7142 | list->store (2, int_name); | |
7143 | list->store (3, metric); | |
7144 | list->store (4, val); | |
7145 | list->store (5, timecvt); | |
7146 | list->store (6, memop); | |
7147 | list->store (7, short_desc); | |
7148 | list->store (8, reglist_v); | |
7149 | list->store (9, supportsAttrs); | |
7150 | list->store (10, supportsMemspace); | |
7151 | return list; | |
7152 | } | |
7153 | ||
7154 | Vector<void *> * | |
7155 | dbeGetHwcsAll (int /*dbevindex*/, bool forKernel) | |
7156 | { | |
7157 | Vector<void*> *list = new Vector<void*>(2); | |
7158 | list->store (0, dbeGetHwcs (hwc_get_std_ctrs (forKernel))); | |
7159 | list->store (1, dbeGetHwcs (hwc_get_raw_ctrs (forKernel))); | |
7160 | return list; | |
7161 | } | |
7162 | ||
7163 | Vector<char*> * | |
7164 | dbeGetHwcHelp (int /*dbevindex*/, bool forKernel) | |
7165 | { | |
7166 | Vector<char*> *strings = new Vector<char*>(32); | |
7167 | FILE *f = tmpfile (); | |
7168 | hwc_usage_f (forKernel, f, "", 0, 0, 1); // writes to f | |
7169 | fflush (f); | |
7170 | fseek (f, 0, SEEK_SET); | |
7171 | #define MAX_LINE_LEN 2048 | |
7172 | char buff[MAX_LINE_LEN]; | |
7173 | int ii = 0; | |
7174 | while (fgets (buff, MAX_LINE_LEN, f)) | |
7175 | strings->store (ii++, dbe_strdup (buff)); | |
7176 | fclose (f); | |
7177 | return strings; | |
7178 | } | |
7179 | ||
7180 | Vector<char*> * | |
7181 | dbeGetHwcAttrList (int /*dbevindex*/, bool forKernel) | |
7182 | { | |
7183 | char ** attr_list = hwc_get_attrs (forKernel); // Get Attribute list | |
7184 | int size; | |
7185 | for (size = 0; attr_list && attr_list[size]; size++) | |
7186 | ; | |
7187 | ||
7188 | Vector<char*> *name = new Vector<char*>(size); | |
7189 | for (int i = 0; i < size; i++) | |
7190 | name->store (i, dbe_strdup (attr_list[i])); | |
7191 | return name; | |
7192 | } | |
7193 | ||
7194 | //Get maximum number of simultaneous counters | |
7195 | int | |
7196 | dbeGetHwcMaxConcurrent (int /*dbevindex*/, bool forKernel) | |
7197 | { | |
7198 | return hwc_get_max_concurrent (forKernel); | |
7199 | } | |
7200 | ||
7201 | // === End CollectDialog HWC info === | |
7202 | ||
7203 | ||
7204 | // Instruction-frequency data | |
7205 | Vector<char*> * | |
7206 | dbeGetIfreqData (int dbevindex) | |
7207 | { | |
7208 | DbeView *dbev = dbeSession->getView (dbevindex); | |
7209 | if (dbev == NULL) | |
7210 | abort (); | |
7211 | if (!dbeSession->is_ifreq_available ()) | |
7212 | return NULL; | |
7213 | int size = dbeSession->nexps (); | |
7214 | if (size == 0) | |
7215 | return NULL; | |
7216 | ||
7217 | // Initialize Java String array | |
7218 | Vector<char*> *list = new Vector<char*>(); | |
7219 | for (int i = 0; i < size; i++) | |
7220 | { | |
7221 | Experiment *exp = dbeSession->get_exp (i); | |
7222 | if (exp->broken || !dbev->get_exp_enable (i) || !exp->ifreqavail) | |
7223 | continue; | |
7224 | // write a header for the experiment | |
7225 | list->append (dbe_sprintf (GTXT ("Instruction frequency data from experiment %s\n\n"), | |
7226 | exp->get_expt_name ())); | |
7227 | // add its instruction frequency messages | |
7228 | char *ifreq = pr_mesgs (exp->fetch_ifreq (), NTXT (""), NTXT ("")); | |
7229 | list->append (ifreq); | |
7230 | } | |
7231 | return list; | |
7232 | } | |
7233 | ||
7234 | // LeakList related methods | |
7235 | // | |
7236 | Vector<void*> * | |
7237 | dbeGetLeakListInfo (int dbevindex, bool leakflag) | |
7238 | { | |
7239 | DbeView *dbev = dbeSession->getView (dbevindex); | |
7240 | if (dbev == NULL) | |
7241 | abort (); | |
7242 | MetricList *origmlist = dbev->get_metric_list (MET_NORMAL); | |
7243 | MetricList *nmlist = new MetricList (origmlist); | |
7244 | if (leakflag) | |
7245 | nmlist->set_metrics (NTXT ("e.heapleakbytes:e.heapleakcnt:name"), true, | |
7246 | dbev->get_derived_metrics ()); | |
7247 | else | |
7248 | nmlist->set_metrics (NTXT ("e.heapallocbytes:e.heapalloccnt:name"), true, | |
7249 | dbev->get_derived_metrics ()); | |
7250 | MetricList *mlist = new MetricList (nmlist); | |
7251 | delete nmlist; | |
7252 | ||
7253 | CStack_data *lam = dbev->get_cstack_data (mlist); | |
7254 | if (lam == NULL || lam->size () == 0) | |
7255 | { | |
7256 | delete lam; | |
7257 | delete mlist; | |
7258 | return NULL; | |
7259 | } | |
7260 | Vector<Vector<Obj>*> *evalue = new Vector<Vector<Obj>*>(lam->size ()); | |
7261 | Vector<Vector<Obj>*> *pcstack = new Vector<Vector<Obj>*>(lam->size ()); | |
7262 | Vector<Vector<Obj>*> *offstack = new Vector<Vector<Obj>*>(lam->size ()); | |
7263 | Vector<Vector<Obj>*> *fpcstack = new Vector<Vector<Obj>*>(lam->size ()); | |
7264 | Vector<Vector<Obj>*> *sumval = new Vector<Vector<Obj>*>(lam->size ()); | |
7265 | ||
7266 | int index; | |
7267 | CStack_data::CStack_item *lae; | |
7268 | Vec_loop (CStack_data::CStack_item*, lam->cstack_items, index, lae) | |
7269 | { | |
7270 | Vector<Obj> *jivals = NULL; | |
7271 | if (lae != NULL) | |
7272 | { | |
7273 | jivals = new Vector<Obj>(4); | |
7274 | jivals->store (0, (Obj) (index + 1)); | |
7275 | jivals->store (1, (Obj) lae->value[1].ll); | |
7276 | jivals->store (2, (Obj) lae->value[0].ll); | |
7277 | jivals->store (3, (Obj) (leakflag ? 1 : 2)); | |
7278 | } | |
7279 | evalue->store (index, jivals); | |
7280 | int snum = lae->stack->size (); | |
7281 | Vector<Obj> *jivals1 = new Vector<Obj>(snum); | |
7282 | Vector<Obj> *jivals2 = new Vector<Obj>(snum); | |
7283 | Vector<Obj> *jivals3 = new Vector<Obj>(snum); | |
7284 | if (lae->stack != NULL) | |
7285 | { | |
7286 | for (int i = lae->stack->size () - 1; i >= 0; i--) | |
7287 | { | |
7288 | DbeInstr *instr = lae->stack->fetch (i); | |
7289 | jivals1->store (i, (Obj) instr); | |
7290 | jivals2->store (i, (Obj) instr->func); | |
7291 | jivals3->store (i, (Obj) instr->addr); | |
7292 | } | |
7293 | } | |
7294 | fpcstack->store (index, jivals1); | |
7295 | pcstack->store (index, jivals2); | |
7296 | offstack->store (index, jivals3); | |
7297 | lae++; | |
7298 | } | |
7299 | Vector<Obj> *jivals4 = new Vector<Obj>(3); | |
7300 | jivals4->store (0, (Obj) lam->size ()); | |
7301 | jivals4->store (1, (Obj) lam->total->value[1].ll); | |
7302 | jivals4->store (2, (Obj) lam->total->value[0].ll); | |
7303 | sumval->store (0, jivals4); | |
7304 | delete lam; | |
7305 | delete mlist; | |
7306 | Vector<void*> *earray = new Vector<void*>(5); | |
7307 | earray->store (0, evalue); | |
7308 | earray->store (1, pcstack); | |
7309 | earray->store (2, offstack); | |
7310 | earray->store (3, fpcstack); | |
7311 | earray->store (4, sumval); | |
7312 | return earray; | |
7313 | } | |
7314 | ||
7315 | // Map timeline address to function instr | |
7316 | // | |
7317 | Obj | |
7318 | dbeGetObject (int dbevindex, Obj sel_func, Obj sel_pc) | |
7319 | { | |
7320 | DbeView *dbev = dbeSession->getView (dbevindex); | |
7321 | if (dbev == NULL) | |
7322 | abort (); | |
7323 | if (sel_pc) | |
7324 | return sel_pc; | |
7325 | return sel_func; | |
7326 | } | |
7327 | ||
7328 | char * | |
7329 | dbeGetName (int /*dbevindex*/, int exp_id) | |
7330 | // This function's name is not descriptive enough - it returns a string | |
7331 | // containing the full experiment name with path, process name, and PID. | |
7332 | // There are various dbe functions that provide experiment name and experiment | |
7333 | // details, and they should probably be consolidated/refactored. (TBR) | |
7334 | // For another example of similar output formatting, see dbeGetExpName(). | |
7335 | { | |
7336 | int id = (exp_id < 0) ? 0 : exp_id; | |
7337 | Experiment *exp = dbeSession->get_exp (id); | |
7338 | if (exp == NULL) | |
7339 | return NULL; | |
7340 | char *buf = | |
7341 | dbe_sprintf (NTXT ("%s [%s, PID %d]"), | |
7342 | exp->get_expt_name (), | |
7343 | exp->utargname != NULL ? exp->utargname : GTXT ("(unknown)"), | |
7344 | exp->getPID ()); | |
7345 | return buf; | |
7346 | } | |
7347 | ||
7348 | Vector<char*> * | |
7349 | dbeGetExpVerboseName (Vector<int> *exp_ids) | |
7350 | { | |
7351 | int len = exp_ids->size (); | |
7352 | Vector<char*> *list = new Vector<char*>(len); | |
7353 | for (int i = 0; i < len; i++) | |
7354 | { | |
7355 | char * verboseName = dbeGetName (0, exp_ids->fetch (i)); // no strdup() | |
7356 | list->store (i, verboseName); | |
7357 | } | |
7358 | return list; | |
7359 | } | |
7360 | ||
7361 | long long | |
7362 | dbeGetStartTime (int /*dbevindex*/, int exp_id) | |
7363 | { | |
7364 | int id = (exp_id < 0) ? 0 : exp_id; | |
7365 | Experiment *exp = dbeSession->get_exp (id); | |
7366 | return exp ? exp->getStartTime () : (long long) 0; | |
7367 | } | |
7368 | ||
7369 | long long | |
7370 | dbeGetRelativeStartTime (int /*dbevindex*/, int exp_id) | |
7371 | { | |
7372 | int id = (exp_id < 0) ? 0 : exp_id; | |
7373 | Experiment *exp = dbeSession->get_exp (id); | |
7374 | return exp ? exp->getRelativeStartTime () : (long long) 0; | |
7375 | } | |
7376 | ||
7377 | long long | |
7378 | dbeGetEndTime (int /*dbevindex*/, int exp_id) | |
7379 | { | |
7380 | int id = (exp_id < 0) ? 0 : exp_id; | |
7381 | Experiment *exp = dbeSession->get_exp (id); | |
7382 | ||
7383 | // Experiment::getEndTime was initially implemented as | |
7384 | // returning exp->last_event. To preserve the semantics | |
7385 | // new Experiment::getLastEvent() is used here. | |
7386 | return exp ? exp->getLastEvent () : (long long) 0; | |
7387 | } | |
7388 | ||
7389 | int | |
7390 | dbeGetClock (int /*dbevindex*/, int exp_id) | |
7391 | { | |
7392 | return dbeSession->get_clock (exp_id); | |
7393 | } | |
7394 | ||
7395 | long long | |
7396 | dbeGetWallStartSec (int /*dbevindex*/, int exp_id) | |
7397 | { | |
7398 | int id = (exp_id < 0) ? 0 : exp_id; | |
7399 | Experiment *exp = dbeSession->get_exp (id); | |
7400 | return exp ? exp->getWallStartSec () : 0ll; | |
7401 | } | |
7402 | ||
7403 | char * | |
7404 | dbeGetHostname (int /*dbevindex*/, int exp_id) | |
7405 | { | |
7406 | int id = (exp_id < 0) ? 0 : exp_id; | |
7407 | Experiment *exp = dbeSession->get_exp (id); | |
7408 | return exp ? dbe_strdup (exp->hostname) : NULL; | |
7409 | } | |
7410 | ||
7411 | static DataView * | |
7412 | getTimelinePackets (int dbevindex, int exp_id, int data_id, int entity_prop_id) | |
7413 | { | |
7414 | DbeView *dbev = dbeSession->getView (dbevindex); | |
7415 | if (dbev == NULL) | |
7416 | abort (); | |
7417 | const int sortprop_count = 3; | |
7418 | const int sortprops[sortprop_count] = { | |
7419 | PROP_HWCTAG, // aux | |
7420 | entity_prop_id, | |
7421 | PROP_TSTAMP | |
7422 | }; | |
7423 | DataView *packets = dbev->get_filtered_events (exp_id, data_id, | |
7424 | sortprops, sortprop_count); | |
7425 | return packets; | |
7426 | } | |
7427 | ||
7428 | static long | |
7429 | getIdxByVals (DataView * packets, int aux, int entity_prop_val, | |
7430 | uint64_t time, DataView::Relation rel) | |
7431 | { | |
7432 | const int sortprop_count = 3; | |
7433 | Datum tval[sortprop_count]; | |
7434 | tval[0].setUINT32 (aux); | |
7435 | tval[1].setUINT32 (entity_prop_val); //CPUID, LWPID, THRID are downsized to 32 | |
7436 | tval[2].setUINT64 (time); | |
7437 | long idx = packets->getIdxByVals (tval, rel); | |
7438 | return idx; | |
7439 | } | |
7440 | ||
7441 | static bool | |
7442 | isValidIdx (DataView * packets, int entity_prop_id, | |
7443 | int aux, int entity_prop_val, long idx) | |
7444 | { | |
7445 | if (idx < 0 || idx >= packets->getSize ()) | |
7446 | return false; | |
7447 | int pkt_aux = packets->getIntValue (PROP_HWCTAG, idx); | |
7448 | if (pkt_aux != aux) | |
7449 | return false; | |
7450 | if (entity_prop_id == PROP_EXPID) | |
7451 | return true; // not a packet property; we know the packet is in this experiment | |
7452 | if (entity_prop_id == PROP_NONE) | |
7453 | return true; // not a packet property; we know the packet is in this experiment | |
7454 | int pkt_ent = packets->getIntValue (entity_prop_id, idx); | |
7455 | if (pkt_ent != entity_prop_val) | |
7456 | return false; | |
7457 | return true; | |
7458 | } | |
7459 | ||
7460 | static bool | |
7461 | hasInvisbleTLEvents (Experiment *exp, VMode view_mode) | |
7462 | { | |
7463 | if (exp->has_java && view_mode == VMODE_USER) | |
7464 | return true; | |
7465 | return false; | |
7466 | } | |
7467 | ||
7468 | static bool | |
7469 | isVisibleTLEvent (Experiment *exp, VMode view_mode, DataView* packets, long idx) | |
7470 | { | |
7471 | if (hasInvisbleTLEvents (exp, view_mode)) | |
7472 | { | |
7473 | JThread *jthread = (JThread*) packets->getObjValue (PROP_JTHREAD, idx); | |
7474 | if (jthread == JTHREAD_NONE || (jthread != NULL && jthread->is_system ())) | |
7475 | return false; | |
7476 | } | |
7477 | return true; | |
7478 | } | |
7479 | ||
7480 | static long | |
7481 | getTLVisibleIdxByStepping (Experiment *exp, VMode view_mode, int entity_prop_id, | |
7482 | DataView * packets, int aux, int entity_prop_val, | |
7483 | long idx, long move_count, int direction) | |
7484 | { | |
7485 | assert (move_count >= 0); | |
7486 | assert (direction == 1 || direction == -1 || direction == 0); | |
7487 | if (direction == 0 /* precise hit required */) | |
7488 | move_count = 0; | |
7489 | do | |
7490 | { | |
7491 | if (!isValidIdx (packets, entity_prop_id, aux, entity_prop_val, idx)) | |
7492 | return -1; | |
7493 | if (isVisibleTLEvent (exp, view_mode, packets, idx)) | |
7494 | { | |
7495 | if (move_count <= 0) | |
7496 | break; | |
7497 | move_count--; | |
7498 | } | |
7499 | if (direction == 0) | |
7500 | return -1; | |
7501 | idx += direction; | |
7502 | } | |
7503 | while (1); | |
7504 | return idx; | |
7505 | } | |
7506 | ||
7507 | static long | |
7508 | getTLVisibleIdxByVals (Experiment *exp, VMode view_mode, int entity_prop_id, | |
7509 | DataView * packets, | |
7510 | int aux, int entity_prop_val, uint64_t time, DataView::Relation rel) | |
7511 | { | |
7512 | long idx = getIdxByVals (packets, aux, entity_prop_val, time, rel); | |
7513 | if (!hasInvisbleTLEvents (exp, view_mode)) | |
7514 | return idx; | |
7515 | if (idx < 0) | |
7516 | return idx; | |
7517 | if (rel == DataView::REL_EQ) | |
7518 | return -1; // would require bi-directional search... not supported for now | |
7519 | int direction = (rel == DataView::REL_LT || rel == DataView::REL_LTEQ) ? -1 : 1; | |
7520 | idx = getTLVisibleIdxByStepping (exp, view_mode, entity_prop_id, packets, | |
7521 | aux, entity_prop_val, | |
7522 | idx, 0 /* first match */, direction); | |
7523 | return idx; | |
7524 | } | |
7525 | ||
7526 | // In thread mode, the entity name for non Java thread should be the 1st func | |
7527 | // from the current thread's stack. See #4961315 | |
7528 | static char* | |
7529 | getThreadRootFuncName (int, int, int, int, VMode) | |
7530 | { | |
7531 | return NULL; // until we figure out what we want to show... YXXX | |
7532 | } | |
7533 | ||
7534 | Vector<void*> * | |
7535 | dbeGetEntityProps (int dbevindex) //YXXX TBD, should this be exp-specific? | |
7536 | { | |
7537 | DbeView *dbev = dbeSession->getView (dbevindex); | |
7538 | if (dbev == NULL) | |
7539 | abort (); | |
7540 | Vector<int> *prop_id = new Vector<int>(); | |
7541 | Vector<char*> *prop_name = new Vector<char*>(); | |
7542 | Vector<char*> *prop_uname = new Vector<char*>(); | |
7543 | Vector<char*> *prop_cname = new Vector<char*>(); //must match TLModeCmd vals! | |
7544 | ||
7545 | prop_id->append (PROP_NONE); | |
7546 | prop_name->append (dbe_strdup (GTXT ("NONE"))); | |
7547 | prop_uname->append (dbe_strdup (GTXT ("Unknown"))); | |
7548 | prop_cname->append (dbe_strdup (NTXT ("unknown"))); | |
7549 | ||
7550 | prop_id->append (PROP_LWPID); | |
7551 | prop_name->append (dbe_strdup (GTXT ("LWPID"))); | |
7552 | prop_uname->append (dbe_strdup (GTXT ("LWP"))); | |
7553 | prop_cname->append (dbe_strdup (NTXT ("lwp"))); | |
7554 | ||
7555 | prop_id->append (PROP_THRID); | |
7556 | prop_name->append (dbe_strdup (GTXT ("THRID"))); | |
7557 | prop_uname->append (dbe_strdup (GTXT ("Thread"))); | |
7558 | prop_cname->append (dbe_strdup (NTXT ("thread"))); | |
7559 | ||
7560 | prop_id->append (PROP_CPUID); | |
7561 | prop_name->append (dbe_strdup (GTXT ("CPUID"))); | |
7562 | prop_uname->append (dbe_strdup (GTXT ("CPU"))); | |
7563 | prop_cname->append (dbe_strdup (NTXT ("cpu"))); | |
7564 | ||
7565 | prop_id->append (PROP_EXPID); | |
7566 | prop_name->append (dbe_strdup (GTXT ("EXPID"))); | |
7567 | prop_uname->append (dbe_strdup (GTXT ("Process"))); // placeholder... | |
7568 | // ...until we finalize how to expose user-level Experiments, descendents | |
7569 | prop_cname->append (dbe_strdup (NTXT ("experiment"))); | |
7570 | Vector<void*> *darray = new Vector<void*>(); | |
7571 | darray->store (0, prop_id); | |
7572 | darray->store (1, prop_name); | |
7573 | darray->store (2, prop_uname); | |
7574 | darray->store (3, prop_cname); | |
7575 | return darray; | |
7576 | } | |
7577 | ||
7578 | Vector<void*> * | |
7579 | dbeGetEntities (int dbevindex, int exp_id, int entity_prop_id) | |
7580 | { | |
7581 | DbeView *dbev = dbeSession->getView (dbevindex); | |
7582 | if (dbev == NULL) | |
7583 | abort (); | |
7584 | Experiment *exp = dbeSession->get_exp (exp_id); | |
7585 | if (exp == NULL) | |
7586 | return NULL; | |
7587 | ||
7588 | // Recognize and skip faketime experiments | |
7589 | if (exp->timelineavail == false) | |
7590 | return NULL; | |
7591 | Vector<Histable*> *tagObjs = exp->getTagObjs ((Prop_type) entity_prop_id); | |
7592 | int total_nelem; | |
7593 | if (tagObjs) | |
7594 | total_nelem = (int) tagObjs->size (); | |
7595 | else | |
7596 | total_nelem = 0; | |
7597 | const VMode view_mode = dbev->get_view_mode (); | |
7598 | bool show_java_threadnames = (entity_prop_id == PROP_THRID && | |
7599 | view_mode != VMODE_MACHINE); | |
7600 | // allocate the structures for the return | |
7601 | Vector<int> *entity_prop_vals = new Vector<int>(); | |
7602 | Vector<char*> *jthr_names = new Vector<char*>(); | |
7603 | Vector<char*> *jthr_g_names = new Vector<char*>(); | |
7604 | Vector<char*> *jthr_p_names = new Vector<char*>(); | |
7605 | ||
7606 | // now walk the tagObjs from the experiment, and check for filtering | |
7607 | for (int tagObjsIdx = 0; tagObjsIdx < total_nelem; tagObjsIdx++) | |
7608 | { | |
7609 | int entity_prop_val = (int) ((Other *) tagObjs->fetch (tagObjsIdx))->tag; | |
7610 | entity_prop_vals->append (entity_prop_val); | |
7611 | char *jname, *jgname, *jpname; | |
7612 | JThread *jthread = NULL; | |
7613 | bool has_java_threadnames = false; | |
7614 | if (show_java_threadnames) | |
7615 | { | |
7616 | jthread = exp->get_jthread (entity_prop_val); | |
7617 | has_java_threadnames = (jthread != JTHREAD_DEFAULT | |
7618 | && jthread != JTHREAD_NONE); | |
7619 | } | |
7620 | if (!has_java_threadnames) | |
7621 | { | |
7622 | jname = jgname = jpname = NULL; | |
7623 | if (entity_prop_id == PROP_THRID || entity_prop_id == PROP_LWPID) | |
7624 | // if non Java thread, set thread name to the 1st func | |
7625 | // from the current thread's stack. see #4961315 | |
7626 | jname = getThreadRootFuncName (dbevindex, exp_id, entity_prop_id, | |
7627 | entity_prop_val, view_mode); | |
7628 | } | |
7629 | else | |
7630 | { | |
7631 | jname = dbe_strdup (jthread->name); | |
7632 | jgname = dbe_strdup (jthread->group_name); | |
7633 | jpname = dbe_strdup (jthread->parent_name); | |
7634 | } | |
7635 | jthr_names->append (jname); | |
7636 | jthr_g_names->append (jgname); | |
7637 | jthr_p_names->append (jpname); | |
7638 | } | |
7639 | Vector<char*> *entity_prop_name_v = new Vector<char*>(); | |
7640 | char* entity_prop_name = dbeSession->getPropName (entity_prop_id); | |
7641 | entity_prop_name_v->append (entity_prop_name); | |
7642 | Vector<void*> *darray = new Vector<void*>(5); | |
7643 | darray->store (0, entity_prop_vals); | |
7644 | darray->store (1, jthr_names); | |
7645 | darray->store (2, jthr_g_names); | |
7646 | darray->store (3, jthr_p_names); | |
7647 | darray->store (4, entity_prop_name_v); // vector only has 1 element | |
7648 | return darray; | |
7649 | } | |
7650 | ||
7651 | // TBR: dbeGetEntities() can be set to private now that we have dbeGetEntitiesV2() | |
7652 | Vector<void*> * | |
7653 | dbeGetEntitiesV2 (int dbevindex, Vector<int> *exp_ids, int entity_prop_id) | |
7654 | { | |
7655 | int sz = exp_ids->size (); | |
7656 | Vector<void*> *res = new Vector<void*>(sz); | |
7657 | for (int ii = 0; ii < sz; ii++) | |
7658 | { | |
7659 | int expIdx = exp_ids->fetch (ii); | |
7660 | Vector<void*>* ents = dbeGetEntities (dbevindex, expIdx, entity_prop_id); | |
7661 | res->store (ii, ents); | |
7662 | } | |
7663 | return res; | |
7664 | } | |
7665 | ||
7666 | //YXXX old-tl packets still used for details | |
7667 | static Vector<void*> * | |
7668 | getTLDetailValues (int dbevindex, Experiment * exp, int data_id, | |
7669 | VMode view_mode, DataView *packets, long idx) | |
7670 | { | |
7671 | Vector<long long> *value = new Vector<long long>(15); | |
7672 | long i = idx; | |
7673 | if (data_id == DATA_SAMPLE || data_id == DATA_GCEVENT) | |
7674 | { | |
7675 | //YXXX DATA_SAMPLE not handled but could be. | |
7676 | } | |
7677 | Obj stack = (unsigned long) getStack (view_mode, packets, i); | |
7678 | Vector<Obj> *funcs = stack ? dbeGetStackFunctions (dbevindex, stack) : NULL; | |
7679 | Function *func = (Function*) | |
7680 | getStackPC (0, view_mode, packets, i)->convertto (Histable::FUNCTION); | |
7681 | // Fill common data | |
7682 | value->store (0, packets->getIntValue (PROP_LWPID, i)); | |
7683 | value->store (1, packets->getIntValue (PROP_THRID, i)); | |
7684 | value->store (2, packets->getIntValue (PROP_CPUID, i)); | |
7685 | value->store (3, packets->getLongValue (PROP_TSTAMP, i)); | |
7686 | value->store (4, (unsigned long) stack); | |
7687 | value->store (5, (unsigned long) func); | |
7688 | ||
7689 | // Fill specific data | |
7690 | switch (data_id) | |
7691 | { | |
7692 | case DATA_CLOCK: | |
7693 | value->store (6, packets->getIntValue (PROP_MSTATE, i)); | |
7694 | { | |
7695 | hrtime_t interval = exp->get_params ()->ptimer_usec * 1000LL // nanoseconds | |
7696 | * packets->getLongValue (PROP_NTICK, i); | |
7697 | value->store (7, interval); | |
7698 | } | |
7699 | value->store (8, packets->getIntValue (PROP_OMPSTATE, i)); | |
7700 | value->store (9, packets->getLongValue (PROP_EVT_TIME, i)); // visual duration | |
7701 | break; | |
7702 | case DATA_SYNCH: | |
7703 | value->store (6, packets->getLongValue (PROP_EVT_TIME, i)); | |
7704 | value->store (7, packets->getLongValue (PROP_SOBJ, i)); | |
7705 | break; | |
7706 | case DATA_HWC: | |
7707 | value->store (6, packets->getLongValue (PROP_HWCINT, i)); | |
7708 | value->store (7, packets->getLongValue (PROP_VADDR, i)); // data vaddr | |
7709 | value->store (8, packets->getLongValue (PROP_PADDR, i)); // data paddr | |
7710 | value->store (9, packets->getLongValue (PROP_VIRTPC, i)); // pc paddr | |
7711 | value->store (10, packets->getLongValue (PROP_PHYSPC, i)); // pc vaddr | |
7712 | break; | |
7713 | case DATA_RACE: | |
7714 | value->store (6, packets->getIntValue (PROP_RTYPE, i)); | |
7715 | value->store (7, packets->getIntValue (PROP_RID, i)); | |
7716 | value->store (8, packets->getLongValue (PROP_RVADDR, i)); | |
7717 | break; | |
7718 | case DATA_DLCK: | |
7719 | value->store (6, packets->getIntValue (PROP_DTYPE, i)); | |
7720 | value->store (7, packets->getIntValue (PROP_DLTYPE, i)); | |
7721 | value->store (8, packets->getIntValue (PROP_DID, i)); | |
7722 | value->store (9, packets->getLongValue (PROP_DVADDR, i)); | |
7723 | break; | |
7724 | case DATA_HEAP: | |
7725 | case DATA_HEAPSZ: | |
7726 | value->store (6, packets->getIntValue (PROP_HTYPE, i)); | |
7727 | value->store (7, packets->getLongValue (PROP_HSIZE, i)); | |
7728 | value->store (8, packets->getLongValue (PROP_HVADDR, i)); | |
7729 | value->store (9, packets->getLongValue (PROP_HOVADDR, i)); | |
7730 | value->store (10, packets->getLongValue (PROP_HLEAKED, i)); | |
7731 | value->store (11, packets->getLongValue (PROP_HFREED, i)); | |
7732 | value->store (12, packets->getLongValue (PROP_HCUR_ALLOCS, i)); // signed int64_t | |
7733 | value->store (13, packets->getLongValue (PROP_HCUR_LEAKS, i)); | |
7734 | break; | |
7735 | case DATA_IOTRACE: | |
7736 | value->store (6, packets->getIntValue (PROP_IOTYPE, i)); | |
7737 | value->store (7, packets->getIntValue (PROP_IOFD, i)); | |
7738 | value->store (8, packets->getLongValue (PROP_IONBYTE, i)); | |
7739 | value->store (9, packets->getLongValue (PROP_EVT_TIME, i)); | |
7740 | value->store (10, packets->getIntValue (PROP_IOVFD, i)); | |
7741 | break; | |
7742 | } | |
7743 | Vector<void*> *result = new Vector<void*>(5); | |
7744 | result->store (0, value); | |
7745 | result->store (1, funcs); // Histable::Function* | |
7746 | result->store (2, funcs ? dbeGetFuncNames (dbevindex, funcs) : 0); // formatted func names | |
7747 | result->store (3, stack ? dbeGetStackPCs (dbevindex, stack) : 0); // Histable::DbeInstr* | |
7748 | result->store (4, stack ? dbeGetStackNames (dbevindex, stack) : 0); // formatted pc names | |
7749 | return result; | |
7750 | } | |
7751 | ||
7752 | Vector<void*> * | |
7753 | dbeGetTLDetails (int dbevindex, int exp_id, int data_id, | |
7754 | int entity_prop_id, Obj event_id) | |
7755 | { | |
7756 | DbeView *dbev = dbeSession->getView (dbevindex); | |
7757 | if (dbev == NULL) | |
7758 | abort (); | |
7759 | Experiment *exp = dbeSession->get_exp (exp_id < 0 ? 0 : exp_id); | |
7760 | if (exp == NULL) | |
7761 | return NULL; | |
7762 | DataView *packets = | |
7763 | getTimelinePackets (dbevindex, exp_id, data_id, entity_prop_id); | |
7764 | if (!packets) | |
7765 | return NULL; | |
7766 | ||
7767 | VMode view_mode = dbev->get_view_mode (); | |
7768 | long idx = (long) event_id; | |
7769 | Vector<void*> *values = getTLDetailValues (dbevindex, exp, data_id, view_mode, packets, idx); | |
7770 | return values; | |
7771 | } | |
7772 | ||
7773 | Vector<Obj> * | |
7774 | dbeGetStackFunctions (int dbevindex, Obj stack) | |
7775 | { | |
7776 | Vector<Obj> *instrs = dbeGetStackPCs (dbevindex, stack); | |
7777 | if (instrs == NULL) | |
7778 | return NULL; | |
7779 | int stsize = instrs->size (); | |
7780 | Vector<Obj> *jivals = new Vector<Obj>(stsize); | |
7781 | for (int i = 0; i < stsize; i++) | |
7782 | { | |
7783 | Histable *obj = (Histable*) instrs->fetch (i); | |
7784 | // if ( obj->get_type() != Histable::LINE ) {//YXXX what is this? | |
7785 | // Remove the above check: why not do this conversion for lines - | |
7786 | // otherwise filtering in timeline by function stack in omp user mode is broken | |
7787 | obj = obj->convertto (Histable::FUNCTION); | |
7788 | jivals->store (i, (Obj) obj); | |
7789 | } | |
7790 | delete instrs; | |
7791 | return jivals; | |
7792 | } | |
7793 | ||
7794 | Vector<void*> * | |
7795 | dbeGetStacksFunctions (int dbevindex, Vector<Obj> *stacks) | |
7796 | { | |
7797 | long sz = stacks->size (); | |
7798 | Vector<void*> *res = new Vector<void*>(sz); | |
7799 | for (int ii = 0; ii < sz; ii++) | |
7800 | { | |
7801 | Obj stack = stacks->fetch (ii); | |
7802 | Vector<Obj> *jivals = dbeGetStackFunctions (dbevindex, stack); | |
7803 | res->store (ii, jivals); | |
7804 | } | |
7805 | return res; | |
7806 | } | |
7807 | ||
7808 | Vector<Obj> * | |
7809 | dbeGetStackPCs (int dbevindex, Obj stack) | |
7810 | { | |
7811 | DbeView *dbev = dbeSession->getView (dbevindex); | |
7812 | if (dbev == NULL) | |
7813 | abort (); | |
7814 | if (stack == 0) | |
7815 | return NULL; | |
7816 | ||
7817 | bool show_all = dbev->isShowAll (); | |
7818 | Vector<Histable*> *instrs = CallStack::getStackPCs ((void *) stack, !show_all); | |
7819 | int stsize = instrs->size (); | |
7820 | int istart = 0; | |
7821 | bool showAll = dbev->isShowAll (); | |
7822 | for (int i = 0; i < stsize - 1; i++) | |
7823 | { | |
7824 | Function *func = (Function*) instrs->fetch (i)->convertto (Histable::FUNCTION); | |
7825 | int ix = func->module->loadobject->seg_idx; | |
7826 | if (showAll && dbev->get_lo_expand (ix) == LIBEX_API) | |
7827 | // truncate stack here: LIBRARY_VISIBILITY if we are using API only but no hide | |
7828 | istart = i; | |
7829 | } | |
7830 | stsize = stsize - istart; | |
7831 | Vector<Obj> *jlvals = new Vector<Obj>(stsize); | |
7832 | for (int i = 0; i < stsize; i++) | |
7833 | { | |
7834 | Histable *instr = instrs->fetch (i + istart); | |
7835 | jlvals->store (i, (Obj) instr); | |
7836 | } | |
7837 | delete instrs; | |
7838 | return jlvals; | |
7839 | } | |
7840 | ||
7841 | Vector<char*> * | |
7842 | dbeGetStackNames (int dbevindex, Obj stack) | |
7843 | { | |
7844 | DbeView *dbev = dbeSession->getView (dbevindex); | |
7845 | Vector<Obj> *instrs = dbeGetStackPCs (dbevindex, stack); | |
7846 | if (instrs == NULL) | |
7847 | return NULL; | |
7848 | int stsize = instrs->size (); | |
7849 | Vector<char*> *list = new Vector<char*>(stsize); | |
7850 | bool showAll = dbev->isShowAll (); | |
7851 | for (int i = 0; i < stsize; i++) | |
7852 | { | |
7853 | Histable* instr = (Histable*) instrs->fetch (i); | |
7854 | if (!showAll) | |
7855 | { | |
7856 | // LIBRARY_VISIBILITY | |
7857 | Function *func = (Function*) instr->convertto (Histable::FUNCTION); | |
7858 | LoadObject *lo = ((Function*) func)->module->loadobject; | |
7859 | if (dbev->get_lo_expand (lo->seg_idx) == LIBEX_HIDE) | |
7860 | { | |
7861 | list->store (i, dbe_strdup (lo->get_name ())); | |
7862 | continue; | |
7863 | } | |
7864 | } | |
7865 | list->store (i, dbe_strdup (instr->get_name (dbev->get_name_format ()))); | |
7866 | } | |
7867 | delete instrs; | |
7868 | return list; | |
7869 | } | |
7870 | ||
7871 | Vector<void*> * | |
7872 | dbeGetSamples (int dbevindex, int exp_id, int64_t lo_idx, int64_t hi_idx) | |
7873 | { | |
7874 | DataView * packets = | |
7875 | getTimelinePackets (dbevindex, exp_id, DATA_SAMPLE, PROP_EXPID); | |
7876 | if (packets == NULL || packets->getSize () == 0) | |
7877 | return NULL; | |
7878 | long lo; | |
7879 | if (lo_idx < 0) | |
7880 | lo = 0; | |
7881 | else | |
7882 | lo = (long) lo_idx; | |
7883 | ||
7884 | long long max = packets->getSize () - 1; | |
7885 | long hi; | |
7886 | if (hi_idx < 0 || hi_idx > max) | |
7887 | hi = (long) max; | |
7888 | else | |
7889 | hi = (long) hi_idx; | |
7890 | ||
7891 | Vector<Vector<long long>*> *sarray = new Vector<Vector<long long>*>; | |
7892 | Vector<long long>* starts = new Vector<long long>; | |
7893 | Vector<long long>* ends = new Vector<long long>; | |
7894 | Vector<long long>* rtimes = new Vector<long long>; | |
7895 | Vector<char*> *startNames = new Vector<char*>; | |
7896 | Vector<char*> *endNames = new Vector<char*>; | |
7897 | Vector<int> *sampId = new Vector<int>; | |
7898 | ||
7899 | for (long index = lo; index <= hi; index++) | |
7900 | { | |
7901 | Sample *sample = (Sample*) packets->getObjValue (PROP_SMPLOBJ, index); | |
7902 | PrUsage *prusage = sample->get_usage (); | |
7903 | if (prusage == NULL) | |
7904 | prusage = new PrUsage; | |
7905 | Vector<long long> *states = prusage->getMstateValues (); | |
7906 | sarray->append (states); | |
7907 | starts->append (sample->get_start_time ()); | |
7908 | ends->append (sample->get_end_time ()); | |
7909 | rtimes->append (prusage->pr_rtime); | |
7910 | startNames->append (dbe_strdup (sample->get_start_label ())); | |
7911 | endNames->append (dbe_strdup (sample->get_end_label ())); | |
7912 | sampId->append (sample->get_number ()); | |
7913 | } | |
7914 | Vector<void *> *res = new Vector<void*>(6); | |
7915 | res->store (0, sarray); | |
7916 | res->store (1, starts); | |
7917 | res->store (2, ends); | |
7918 | res->store (3, rtimes); | |
7919 | res->store (4, startNames); | |
7920 | res->store (5, endNames); | |
7921 | res->store (6, sampId); | |
7922 | return res; | |
7923 | } | |
7924 | ||
7925 | Vector<void*> * | |
7926 | dbeGetGCEvents (int dbevindex, int exp_id, int64_t lo_idx, int64_t hi_idx) | |
7927 | { | |
7928 | DataView *packets = | |
7929 | getTimelinePackets (dbevindex, exp_id, DATA_GCEVENT, PROP_EXPID); | |
7930 | if (packets == NULL || packets->getSize () == 0) | |
7931 | return NULL; | |
7932 | ||
7933 | long lo; | |
7934 | if (lo_idx < 0) | |
7935 | lo = 0; | |
7936 | else | |
7937 | lo = (long) lo_idx; | |
7938 | long long max = packets->getSize () - 1; | |
7939 | long hi; | |
7940 | if (hi_idx < 0 || hi_idx > max) | |
7941 | hi = (long) max; | |
7942 | else | |
7943 | hi = (long) hi_idx; | |
7944 | ||
7945 | Vector<long long>* starts = new Vector<long long>; | |
7946 | Vector<long long>* ends = new Vector<long long>; | |
7947 | Vector<int> *eventId = new Vector<int>; | |
7948 | for (long index = lo; index <= hi; index++) | |
7949 | { | |
7950 | GCEvent *gcevent = (GCEvent*) packets->getObjValue (PROP_GCEVENTOBJ, index); | |
7951 | if (gcevent) | |
7952 | { | |
7953 | starts->append (gcevent->start); | |
7954 | ends->append (gcevent->end); | |
7955 | eventId->append (gcevent->id); | |
7956 | } | |
7957 | } | |
7958 | Vector<void *> *res = new Vector<void*>(3); | |
7959 | res->store (0, starts); | |
7960 | res->store (1, ends); | |
7961 | res->store (2, eventId); | |
7962 | return res; | |
7963 | } | |
7964 | ||
7965 | Vector<Vector<char*>*>* | |
7966 | dbeGetIOStatistics (int dbevindex) | |
7967 | { | |
7968 | DbeView *dbev = dbeSession->getView (dbevindex); | |
7969 | Hist_data *hist_data; | |
7970 | Hist_data::HistItem *hi; | |
7971 | FileData *fDataTotal; | |
7972 | ||
7973 | hist_data = dbev->iofile_data; | |
7974 | if (hist_data == NULL) | |
7975 | return NULL; | |
7976 | hi = hist_data->fetch (0); | |
7977 | fDataTotal = (FileData*) hi->obj; | |
7978 | ||
7979 | Vector<char*> *writeStat = new Vector<char*>; | |
7980 | Vector<char*> *readStat = new Vector<char*>; | |
7981 | Vector<char*> *otherStat = new Vector<char*>; | |
7982 | Vector<char*> *errorStat = new Vector<char*>; | |
7983 | ||
7984 | writeStat->append (dbe_strdup (GTXT ("Write Statistics"))); | |
7985 | readStat->append (dbe_strdup (GTXT ("Read Statistics"))); | |
7986 | otherStat->append (dbe_strdup (GTXT ("Other I/O Statistics"))); | |
7987 | errorStat->append (dbe_strdup (GTXT ("I/O Error Statistics"))); | |
7988 | ||
7989 | StringBuilder sb; | |
7990 | if (fDataTotal->getWriteCnt () > 0) | |
7991 | { | |
7992 | if (fDataTotal->getW0KB1KBCnt () > 0) | |
7993 | { | |
7994 | sb.sprintf (GTXT ("0KB - 1KB")); | |
7995 | writeStat->append (sb.toString ()); | |
7996 | sb.sprintf (NTXT ("%d"), fDataTotal->getW0KB1KBCnt ()); | |
7997 | writeStat->append (sb.toString ()); | |
7998 | } | |
7999 | if (fDataTotal->getW1KB8KBCnt () > 0) | |
8000 | { | |
8001 | sb.sprintf (GTXT ("1KB - 8KB")); | |
8002 | writeStat->append (sb.toString ()); | |
8003 | sb.sprintf (NTXT ("%d"), fDataTotal->getW1KB8KBCnt ()); | |
8004 | writeStat->append (sb.toString ()); | |
8005 | } | |
8006 | if (fDataTotal->getW8KB32KBCnt () > 0) | |
8007 | { | |
8008 | sb.sprintf (GTXT ("8KB - 32KB")); | |
8009 | writeStat->append (sb.toString ()); | |
8010 | sb.sprintf (NTXT ("%d"), fDataTotal->getW8KB32KBCnt ()); | |
8011 | writeStat->append (sb.toString ()); | |
8012 | } | |
8013 | if (fDataTotal->getW32KB128KBCnt () > 0) | |
8014 | { | |
8015 | sb.sprintf (GTXT ("32KB - 128KB")); | |
8016 | writeStat->append (sb.toString ()); | |
8017 | sb.sprintf (NTXT ("%d"), fDataTotal->getW32KB128KBCnt ()); | |
8018 | writeStat->append (sb.toString ()); | |
8019 | } | |
8020 | if (fDataTotal->getW128KB256KBCnt () > 0) | |
8021 | { | |
8022 | sb.sprintf (GTXT ("128KB - 256KB")); | |
8023 | writeStat->append (sb.toString ()); | |
8024 | sb.sprintf (NTXT ("%d"), fDataTotal->getW128KB256KBCnt ()); | |
8025 | writeStat->append (sb.toString ()); | |
8026 | } | |
8027 | if (fDataTotal->getW256KB512KBCnt () > 0) | |
8028 | { | |
8029 | sb.sprintf (GTXT ("256KB - 512KB")); | |
8030 | writeStat->append (sb.toString ()); | |
8031 | sb.sprintf (NTXT ("%d"), fDataTotal->getW256KB512KBCnt ()); | |
8032 | writeStat->append (sb.toString ()); | |
8033 | } | |
8034 | if (fDataTotal->getW512KB1000KBCnt () > 0) | |
8035 | { | |
8036 | sb.sprintf (GTXT ("512KB - 1000KB")); | |
8037 | writeStat->append (sb.toString ()); | |
8038 | sb.sprintf (NTXT ("%d"), fDataTotal->getW512KB1000KBCnt ()); | |
8039 | writeStat->append (sb.toString ()); | |
8040 | } | |
8041 | if (fDataTotal->getW1000KB10MBCnt () > 0) | |
8042 | { | |
8043 | sb.sprintf (GTXT ("1000KB - 10MB")); | |
8044 | writeStat->append (sb.toString ()); | |
8045 | sb.sprintf (NTXT ("%d"), fDataTotal->getW1000KB10MBCnt ()); | |
8046 | writeStat->append (sb.toString ()); | |
8047 | } | |
8048 | if (fDataTotal->getW10MB100MBCnt () > 0) | |
8049 | { | |
8050 | sb.sprintf (GTXT ("10MB - 100MB")); | |
8051 | writeStat->append (sb.toString ()); | |
8052 | sb.sprintf (NTXT ("%d"), fDataTotal->getW10MB100MBCnt ()); | |
8053 | writeStat->append (sb.toString ()); | |
8054 | } | |
8055 | if (fDataTotal->getW100MB1GBCnt () > 0) | |
8056 | { | |
8057 | sb.sprintf (GTXT ("100MB - 1GB")); | |
8058 | writeStat->append (sb.toString ()); | |
8059 | sb.sprintf (NTXT ("%d"), fDataTotal->getW100MB1GBCnt ()); | |
8060 | writeStat->append (sb.toString ()); | |
8061 | } | |
8062 | if (fDataTotal->getW1GB10GBCnt () > 0) | |
8063 | { | |
8064 | sb.sprintf (GTXT ("1GB - 10GB")); | |
8065 | writeStat->append (sb.toString ()); | |
8066 | sb.sprintf (NTXT ("%d"), fDataTotal->getW1GB10GBCnt ()); | |
8067 | writeStat->append (sb.toString ()); | |
8068 | } | |
8069 | if (fDataTotal->getW10GB100GBCnt () > 0) | |
8070 | { | |
8071 | sb.sprintf (GTXT ("10GB - 100GB")); | |
8072 | writeStat->append (sb.toString ()); | |
8073 | sb.sprintf (NTXT ("%d"), fDataTotal->getW10GB100GBCnt ()); | |
8074 | writeStat->append (sb.toString ()); | |
8075 | } | |
8076 | if (fDataTotal->getW100GB1TBCnt () > 0) | |
8077 | { | |
8078 | sb.sprintf (GTXT ("100GB - 1TB")); | |
8079 | writeStat->append (sb.toString ()); | |
8080 | sb.sprintf (NTXT ("%d"), fDataTotal->getW100GB1TBCnt ()); | |
8081 | writeStat->append (sb.toString ()); | |
8082 | } | |
8083 | if (fDataTotal->getW1TB10TBCnt () > 0) | |
8084 | { | |
8085 | sb.sprintf (GTXT ("1TB - 10TB")); | |
8086 | writeStat->append (sb.toString ()); | |
8087 | sb.sprintf (NTXT ("%d"), fDataTotal->getW1TB10TBCnt ()); | |
8088 | writeStat->append (sb.toString ()); | |
8089 | } | |
8090 | ||
8091 | sb.sprintf (GTXT ("Longest write")); | |
8092 | writeStat->append (sb.toString ()); | |
8093 | sb.sprintf (NTXT ("%.6f (secs.)"), | |
8094 | (double) (fDataTotal->getWSlowestBytes () / (double) NANOSEC)); | |
8095 | writeStat->append (sb.toString ()); | |
8096 | ||
8097 | sb.sprintf (GTXT ("Smallest write bytes")); | |
8098 | writeStat->append (sb.toString ()); | |
8099 | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getWSmallestBytes ())); | |
8100 | writeStat->append (sb.toString ()); | |
8101 | ||
8102 | sb.sprintf (GTXT ("Largest write bytes")); | |
8103 | writeStat->append (sb.toString ()); | |
8104 | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getWLargestBytes ())); | |
8105 | writeStat->append (sb.toString ()); | |
8106 | ||
8107 | sb.sprintf (GTXT ("Total time")); | |
8108 | writeStat->append (sb.toString ()); | |
8109 | sb.sprintf (NTXT ("%.6f (secs.)"), | |
8110 | (double) (fDataTotal->getWriteTime () / (double) NANOSEC)); | |
8111 | writeStat->append (sb.toString ()); | |
8112 | ||
8113 | sb.sprintf (GTXT ("Total calls")); | |
8114 | writeStat->append (sb.toString ()); | |
8115 | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getWriteCnt ())); | |
8116 | writeStat->append (sb.toString ()); | |
8117 | ||
8118 | sb.sprintf (GTXT ("Total bytes")); | |
8119 | writeStat->append (sb.toString ()); | |
8120 | sb.sprintf (NTXT ("%lld"), (long long) (fDataTotal->getWriteBytes ())); | |
8121 | writeStat->append (sb.toString ()); | |
8122 | } | |
8123 | ||
8124 | if (fDataTotal->getReadCnt () > 0) | |
8125 | { | |
8126 | if (fDataTotal->getR0KB1KBCnt () > 0) | |
8127 | { | |
8128 | sb.sprintf (GTXT ("0KB - 1KB")); | |
8129 | readStat->append (sb.toString ()); | |
8130 | sb.sprintf (NTXT ("%d"), fDataTotal->getR0KB1KBCnt ()); | |
8131 | readStat->append (sb.toString ()); | |
8132 | } | |
8133 | if (fDataTotal->getR1KB8KBCnt () > 0) | |
8134 | { | |
8135 | sb.sprintf (GTXT ("1KB - 8KB")); | |
8136 | readStat->append (sb.toString ()); | |
8137 | sb.sprintf (NTXT ("%d"), fDataTotal->getR1KB8KBCnt ()); | |
8138 | readStat->append (sb.toString ()); | |
8139 | } | |
8140 | if (fDataTotal->getR8KB32KBCnt () > 0) | |
8141 | { | |
8142 | sb.sprintf (GTXT ("8KB - 32KB")); | |
8143 | readStat->append (sb.toString ()); | |
8144 | sb.sprintf (NTXT ("%d"), fDataTotal->getR8KB32KBCnt ()); | |
8145 | readStat->append (sb.toString ()); | |
8146 | } | |
8147 | if (fDataTotal->getR32KB128KBCnt () > 0) | |
8148 | { | |
8149 | sb.sprintf (GTXT ("32KB - 128KB")); | |
8150 | readStat->append (sb.toString ()); | |
8151 | sb.sprintf (NTXT ("%d"), fDataTotal->getR32KB128KBCnt ()); | |
8152 | readStat->append (sb.toString ()); | |
8153 | } | |
8154 | if (fDataTotal->getR128KB256KBCnt () > 0) | |
8155 | { | |
8156 | sb.sprintf (GTXT ("128KB - 256KB")); | |
8157 | readStat->append (sb.toString ()); | |
8158 | sb.sprintf (NTXT ("%d"), fDataTotal->getR128KB256KBCnt ()); | |
8159 | readStat->append (sb.toString ()); | |
8160 | } | |
8161 | if (fDataTotal->getR256KB512KBCnt () > 0) | |
8162 | { | |
8163 | sb.sprintf (GTXT ("256KB - 512KB")); | |
8164 | readStat->append (sb.toString ()); | |
8165 | sb.sprintf (NTXT ("%d"), fDataTotal->getR256KB512KBCnt ()); | |
8166 | readStat->append (sb.toString ()); | |
8167 | } | |
8168 | if (fDataTotal->getR512KB1000KBCnt () > 0) | |
8169 | { | |
8170 | sb.sprintf (GTXT ("512KB - 1000KB")); | |
8171 | readStat->append (sb.toString ()); | |
8172 | sb.sprintf (NTXT ("%d"), fDataTotal->getR512KB1000KBCnt ()); | |
8173 | readStat->append (sb.toString ()); | |
8174 | } | |
8175 | if (fDataTotal->getR1000KB10MBCnt () > 0) | |
8176 | { | |
8177 | sb.sprintf (GTXT ("1000KB - 10MB")); | |
8178 | readStat->append (sb.toString ()); | |
8179 | sb.sprintf (NTXT ("%d"), fDataTotal->getR1000KB10MBCnt ()); | |
8180 | readStat->append (sb.toString ()); | |
8181 | } | |
8182 | if (fDataTotal->getR10MB100MBCnt () > 0) | |
8183 | { | |
8184 | sb.sprintf (GTXT ("10MB - 100MB")); | |
8185 | readStat->append (sb.toString ()); | |
8186 | sb.sprintf (NTXT ("%d"), fDataTotal->getR10MB100MBCnt ()); | |
8187 | readStat->append (sb.toString ()); | |
8188 | } | |
8189 | if (fDataTotal->getR100MB1GBCnt () > 0) | |
8190 | { | |
8191 | sb.sprintf (GTXT ("100MB - 1GB")); | |
8192 | readStat->append (sb.toString ()); | |
8193 | sb.sprintf (NTXT ("%d"), fDataTotal->getR100MB1GBCnt ()); | |
8194 | readStat->append (sb.toString ()); | |
8195 | } | |
8196 | if (fDataTotal->getR1GB10GBCnt () > 0) | |
8197 | { | |
8198 | sb.sprintf (GTXT ("1GB - 10GB")); | |
8199 | readStat->append (sb.toString ()); | |
8200 | sb.sprintf (NTXT ("%d"), fDataTotal->getR1GB10GBCnt ()); | |
8201 | readStat->append (sb.toString ()); | |
8202 | } | |
8203 | if (fDataTotal->getR10GB100GBCnt () > 0) | |
8204 | { | |
8205 | sb.sprintf (GTXT ("10GB - 100GB")); | |
8206 | readStat->append (sb.toString ()); | |
8207 | sb.sprintf (NTXT ("%d"), fDataTotal->getR10GB100GBCnt ()); | |
8208 | readStat->append (sb.toString ()); | |
8209 | } | |
8210 | if (fDataTotal->getR100GB1TBCnt () > 0) | |
8211 | { | |
8212 | sb.sprintf (GTXT ("100GB - 1TB")); | |
8213 | readStat->append (sb.toString ()); | |
8214 | sb.sprintf (NTXT ("%d"), fDataTotal->getR100GB1TBCnt ()); | |
8215 | readStat->append (sb.toString ()); | |
8216 | } | |
8217 | if (fDataTotal->getR1TB10TBCnt () > 0) | |
8218 | { | |
8219 | sb.sprintf (GTXT ("1TB - 10TB")); | |
8220 | readStat->append (sb.toString ()); | |
8221 | sb.sprintf (NTXT ("%d"), fDataTotal->getR1TB10TBCnt ()); | |
8222 | readStat->append (sb.toString ()); | |
8223 | } | |
8224 | ||
8225 | sb.sprintf (GTXT ("Longest read")); | |
8226 | readStat->append (sb.toString ()); | |
8227 | sb.sprintf (NTXT ("%.6f (secs.)"), | |
8228 | (double) (fDataTotal->getRSlowestBytes () / (double) NANOSEC)); | |
8229 | readStat->append (sb.toString ()); | |
8230 | ||
8231 | sb.sprintf (GTXT ("Smallest read bytes")); | |
8232 | readStat->append (sb.toString ()); | |
8233 | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getRSmallestBytes ())); | |
8234 | readStat->append (sb.toString ()); | |
8235 | ||
8236 | sb.sprintf (GTXT ("Largest read bytes")); | |
8237 | readStat->append (sb.toString ()); | |
8238 | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getRLargestBytes ())); | |
8239 | readStat->append (sb.toString ()); | |
8240 | ||
8241 | sb.sprintf (GTXT ("Total time")); | |
8242 | readStat->append (sb.toString ()); | |
8243 | sb.sprintf (NTXT ("%.6f (secs.)"), | |
8244 | (double) (fDataTotal->getReadTime () / (double) NANOSEC)); | |
8245 | readStat->append (sb.toString ()); | |
8246 | ||
8247 | sb.sprintf (GTXT ("Total calls")); | |
8248 | readStat->append (sb.toString ()); | |
8249 | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getReadCnt ())); | |
8250 | readStat->append (sb.toString ()); | |
8251 | ||
8252 | sb.sprintf (GTXT ("Total bytes")); | |
8253 | readStat->append (sb.toString ()); | |
8254 | sb.sprintf (NTXT ("%lld"), (long long) (fDataTotal->getReadBytes ())); | |
8255 | readStat->append (sb.toString ()); | |
8256 | } | |
8257 | ||
8258 | if (fDataTotal->getOtherCnt () > 0) | |
8259 | { | |
8260 | sb.sprintf (GTXT ("Total time")); | |
8261 | otherStat->append (sb.toString ()); | |
8262 | sb.sprintf (NTXT ("%.6f (secs.)"), | |
8263 | (double) (fDataTotal->getOtherTime () / (double) NANOSEC)); | |
8264 | otherStat->append (sb.toString ()); | |
8265 | ||
8266 | sb.sprintf (GTXT ("Total calls")); | |
8267 | otherStat->append (sb.toString ()); | |
8268 | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getOtherCnt ())); | |
8269 | otherStat->append (sb.toString ()); | |
8270 | } | |
8271 | ||
8272 | if (fDataTotal->getErrorCnt () > 0) | |
8273 | { | |
8274 | sb.sprintf (GTXT ("Total time")); | |
8275 | errorStat->append (sb.toString ()); | |
8276 | sb.sprintf (NTXT ("%.6f (secs.)"), | |
8277 | (double) (fDataTotal->getErrorTime () / (double) NANOSEC)); | |
8278 | errorStat->append (sb.toString ()); | |
8279 | ||
8280 | sb.sprintf (GTXT ("Total calls")); | |
8281 | errorStat->append (sb.toString ()); | |
8282 | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getErrorCnt ())); | |
8283 | errorStat->append (sb.toString ()); | |
8284 | } | |
8285 | Vector<Vector<char*>*>* statisticsData = new Vector<Vector<char*>*>(4); | |
8286 | statisticsData->store (0, writeStat); | |
8287 | statisticsData->store (1, readStat); | |
8288 | statisticsData->store (2, otherStat); | |
8289 | statisticsData->store (3, errorStat); | |
8290 | return statisticsData; | |
8291 | } | |
8292 | ||
8293 | Vector<Vector<char*>*>* | |
8294 | dbeGetHeapStatistics (int dbevindex) | |
8295 | { | |
8296 | DbeView *dbev = dbeSession->getView (dbevindex); | |
8297 | Hist_data *hist_data; | |
8298 | Hist_data::HistItem *hi; | |
8299 | HeapData *hDataTotal; | |
8300 | hist_data = dbev->heapcs_data; | |
8301 | if (hist_data == NULL) | |
8302 | return NULL; | |
8303 | ||
8304 | hi = hist_data->fetch (0); | |
8305 | hDataTotal = (HeapData*) hi->obj; | |
8306 | Vector<char*> *memoryUsage = new Vector<char*>; | |
8307 | Vector<char*> *allocStat = new Vector<char*>; | |
8308 | Vector<char*> *leakStat = new Vector<char*>; | |
8309 | ||
8310 | memoryUsage->append (dbe_strdup (GTXT ("Process With Highest Peak Memory Usage"))); | |
8311 | allocStat->append (dbe_strdup (GTXT ("Memory Allocations Statistics"))); | |
8312 | leakStat->append (dbe_strdup (GTXT ("Memory Leaks Statistics"))); | |
8313 | StringBuilder sb; | |
8314 | if (hDataTotal->getPeakMemUsage () > 0) | |
8315 | { | |
8316 | sb.sprintf (GTXT ("Heap size bytes")); | |
8317 | memoryUsage->append (sb.toString ()); | |
8318 | sb.sprintf (NTXT ("%lld"), (long long) (hDataTotal->getPeakMemUsage ())); | |
8319 | memoryUsage->append (sb.toString ()); | |
8320 | ||
8321 | sb.sprintf (GTXT ("Experiment Id")); | |
8322 | memoryUsage->append (sb.toString ()); | |
8323 | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getUserExpId ())); | |
8324 | memoryUsage->append (sb.toString ()); | |
8325 | ||
8326 | sb.sprintf (GTXT ("Process Id")); | |
8327 | memoryUsage->append (sb.toString ()); | |
8328 | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getPid ())); | |
8329 | memoryUsage->append (sb.toString ()); | |
8330 | ||
8331 | Vector<hrtime_t> *pTimestamps; | |
8332 | pTimestamps = hDataTotal->getPeakTimestamps (); | |
8333 | if (pTimestamps != NULL) | |
8334 | { | |
8335 | for (int i = 0; i < pTimestamps->size (); i++) | |
8336 | { | |
8337 | sb.sprintf (GTXT ("Time of peak")); | |
8338 | memoryUsage->append (sb.toString ()); | |
8339 | sb.sprintf (NTXT ("%.3f (secs.)"), (double) (pTimestamps->fetch (i) / (double) NANOSEC)); | |
8340 | memoryUsage->append (sb.toString ()); | |
8341 | } | |
8342 | } | |
8343 | } | |
8344 | ||
8345 | if (hDataTotal->getAllocCnt () > 0) | |
8346 | { | |
8347 | if (hDataTotal->getA0KB1KBCnt () > 0) | |
8348 | { | |
8349 | sb.sprintf (GTXT ("0KB - 1KB")); | |
8350 | allocStat->append (sb.toString ()); | |
8351 | sb.sprintf (NTXT ("%d"), hDataTotal->getA0KB1KBCnt ()); | |
8352 | allocStat->append (sb.toString ()); | |
8353 | } | |
8354 | if (hDataTotal->getA1KB8KBCnt () > 0) | |
8355 | { | |
8356 | sb.sprintf (GTXT ("1KB - 8KB")); | |
8357 | allocStat->append (sb.toString ()); | |
8358 | sb.sprintf (NTXT ("%d"), hDataTotal->getA1KB8KBCnt ()); | |
8359 | allocStat->append (sb.toString ()); | |
8360 | } | |
8361 | if (hDataTotal->getA8KB32KBCnt () > 0) | |
8362 | { | |
8363 | sb.sprintf (GTXT ("8KB - 32KB")); | |
8364 | allocStat->append (sb.toString ()); | |
8365 | sb.sprintf (NTXT ("%d"), hDataTotal->getA8KB32KBCnt ()); | |
8366 | allocStat->append (sb.toString ()); | |
8367 | } | |
8368 | if (hDataTotal->getA32KB128KBCnt () > 0) | |
8369 | { | |
8370 | sb.sprintf (GTXT ("32KB - 128KB")); | |
8371 | allocStat->append (sb.toString ()); | |
8372 | sb.sprintf (NTXT ("%d"), hDataTotal->getA32KB128KBCnt ()); | |
8373 | allocStat->append (sb.toString ()); | |
8374 | } | |
8375 | if (hDataTotal->getA128KB256KBCnt () > 0) | |
8376 | { | |
8377 | sb.sprintf (GTXT ("128KB - 256KB")); | |
8378 | allocStat->append (sb.toString ()); | |
8379 | sb.sprintf (NTXT ("%d"), hDataTotal->getA128KB256KBCnt ()); | |
8380 | allocStat->append (sb.toString ()); | |
8381 | } | |
8382 | if (hDataTotal->getA256KB512KBCnt () > 0) | |
8383 | { | |
8384 | sb.sprintf (GTXT ("256KB - 512KB")); | |
8385 | allocStat->append (sb.toString ()); | |
8386 | sb.sprintf (NTXT ("%d"), hDataTotal->getA256KB512KBCnt ()); | |
8387 | allocStat->append (sb.toString ()); | |
8388 | } | |
8389 | if (hDataTotal->getA512KB1000KBCnt () > 0) | |
8390 | { | |
8391 | sb.sprintf (GTXT ("512KB - 1000KB")); | |
8392 | allocStat->append (sb.toString ()); | |
8393 | sb.sprintf (NTXT ("%d"), hDataTotal->getA512KB1000KBCnt ()); | |
8394 | allocStat->append (sb.toString ()); | |
8395 | } | |
8396 | if (hDataTotal->getA1000KB10MBCnt () > 0) | |
8397 | { | |
8398 | sb.sprintf (GTXT ("1000KB - 10MB")); | |
8399 | allocStat->append (sb.toString ()); | |
8400 | sb.sprintf (NTXT ("%d"), hDataTotal->getA1000KB10MBCnt ()); | |
8401 | allocStat->append (sb.toString ()); | |
8402 | } | |
8403 | if (hDataTotal->getA10MB100MBCnt () > 0) | |
8404 | { | |
8405 | sb.sprintf (GTXT ("10MB - 100MB")); | |
8406 | allocStat->append (sb.toString ()); | |
8407 | sb.sprintf (NTXT ("%d"), hDataTotal->getA10MB100MBCnt ()); | |
8408 | allocStat->append (sb.toString ()); | |
8409 | } | |
8410 | if (hDataTotal->getA100MB1GBCnt () > 0) | |
8411 | { | |
8412 | sb.sprintf (GTXT ("100MB - 1GB")); | |
8413 | allocStat->append (sb.toString ()); | |
8414 | sb.sprintf (NTXT ("%d"), hDataTotal->getA100MB1GBCnt ()); | |
8415 | allocStat->append (sb.toString ()); | |
8416 | } | |
8417 | if (hDataTotal->getA1GB10GBCnt () > 0) | |
8418 | { | |
8419 | sb.sprintf (GTXT ("1GB - 10GB")); | |
8420 | allocStat->append (sb.toString ()); | |
8421 | sb.sprintf (NTXT ("%d"), hDataTotal->getA1GB10GBCnt ()); | |
8422 | allocStat->append (sb.toString ()); | |
8423 | } | |
8424 | if (hDataTotal->getA10GB100GBCnt () > 0) | |
8425 | { | |
8426 | sb.sprintf (GTXT ("10GB - 100GB")); | |
8427 | allocStat->append (sb.toString ()); | |
8428 | sb.sprintf (NTXT ("%d"), hDataTotal->getA10GB100GBCnt ()); | |
8429 | allocStat->append (sb.toString ()); | |
8430 | } | |
8431 | if (hDataTotal->getA100GB1TBCnt () > 0) | |
8432 | { | |
8433 | sb.sprintf (GTXT ("100GB - 1TB")); | |
8434 | allocStat->append (sb.toString ()); | |
8435 | sb.sprintf (NTXT ("%d"), hDataTotal->getA100GB1TBCnt ()); | |
8436 | allocStat->append (sb.toString ()); | |
8437 | } | |
8438 | if (hDataTotal->getA1TB10TBCnt () > 0) | |
8439 | { | |
8440 | sb.sprintf (GTXT ("1TB - 10TB")); | |
8441 | allocStat->append (sb.toString ()); | |
8442 | sb.sprintf (NTXT ("%d"), hDataTotal->getA1TB10TBCnt ()); | |
8443 | allocStat->append (sb.toString ()); | |
8444 | } | |
8445 | ||
8446 | sb.sprintf (GTXT ("Smallest allocation bytes")); | |
8447 | allocStat->append (sb.toString ()); | |
8448 | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getASmallestBytes ())); | |
8449 | allocStat->append (sb.toString ()); | |
8450 | ||
8451 | sb.sprintf (GTXT ("Largest allocation bytes")); | |
8452 | allocStat->append (sb.toString ()); | |
8453 | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getALargestBytes ())); | |
8454 | allocStat->append (sb.toString ()); | |
8455 | ||
8456 | sb.sprintf (GTXT ("Total allocations")); | |
8457 | allocStat->append (sb.toString ()); | |
8458 | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getAllocCnt ())); | |
8459 | allocStat->append (sb.toString ()); | |
8460 | ||
8461 | sb.sprintf (GTXT ("Total bytes")); | |
8462 | allocStat->append (sb.toString ()); | |
8463 | sb.sprintf (NTXT ("%lld"), (long long) (hDataTotal->getAllocBytes ())); | |
8464 | allocStat->append (sb.toString ()); | |
8465 | } | |
8466 | ||
8467 | if (hDataTotal->getLeakCnt () > 0) | |
8468 | { | |
8469 | if (hDataTotal->getL0KB1KBCnt () > 0) | |
8470 | { | |
8471 | sb.sprintf (GTXT ("0KB - 1KB")); | |
8472 | leakStat->append (sb.toString ()); | |
8473 | sb.sprintf (NTXT ("%d"), hDataTotal->getL0KB1KBCnt ()); | |
8474 | leakStat->append (sb.toString ()); | |
8475 | } | |
8476 | if (hDataTotal->getL1KB8KBCnt () > 0) | |
8477 | { | |
8478 | sb.sprintf (GTXT ("1KB - 8KB")); | |
8479 | leakStat->append (sb.toString ()); | |
8480 | sb.sprintf (NTXT ("%d"), hDataTotal->getL1KB8KBCnt ()); | |
8481 | leakStat->append (sb.toString ()); | |
8482 | } | |
8483 | if (hDataTotal->getL8KB32KBCnt () > 0) | |
8484 | { | |
8485 | sb.sprintf (GTXT ("8KB - 32KB")); | |
8486 | leakStat->append (sb.toString ()); | |
8487 | sb.sprintf (NTXT ("%d"), hDataTotal->getL8KB32KBCnt ()); | |
8488 | leakStat->append (sb.toString ()); | |
8489 | } | |
8490 | if (hDataTotal->getL32KB128KBCnt () > 0) | |
8491 | { | |
8492 | sb.sprintf (GTXT ("32KB - 128KB")); | |
8493 | leakStat->append (sb.toString ()); | |
8494 | sb.sprintf (NTXT ("%d"), hDataTotal->getL32KB128KBCnt ()); | |
8495 | leakStat->append (sb.toString ()); | |
8496 | } | |
8497 | if (hDataTotal->getL128KB256KBCnt () > 0) | |
8498 | { | |
8499 | sb.sprintf (GTXT ("128KB - 256KB")); | |
8500 | leakStat->append (sb.toString ()); | |
8501 | sb.sprintf (NTXT ("%d"), hDataTotal->getL128KB256KBCnt ()); | |
8502 | leakStat->append (sb.toString ()); | |
8503 | } | |
8504 | if (hDataTotal->getL256KB512KBCnt () > 0) | |
8505 | { | |
8506 | sb.sprintf (GTXT ("256KB - 512KB")); | |
8507 | leakStat->append (sb.toString ()); | |
8508 | sb.sprintf (NTXT ("%d"), hDataTotal->getL256KB512KBCnt ()); | |
8509 | leakStat->append (sb.toString ()); | |
8510 | } | |
8511 | if (hDataTotal->getL512KB1000KBCnt () > 0) | |
8512 | { | |
8513 | sb.sprintf (GTXT ("512KB - 1000KB")); | |
8514 | leakStat->append (sb.toString ()); | |
8515 | sb.sprintf (NTXT ("%d"), hDataTotal->getL512KB1000KBCnt ()); | |
8516 | leakStat->append (sb.toString ()); | |
8517 | } | |
8518 | if (hDataTotal->getL1000KB10MBCnt () > 0) | |
8519 | { | |
8520 | sb.sprintf (GTXT ("1000KB - 10MB")); | |
8521 | leakStat->append (sb.toString ()); | |
8522 | sb.sprintf (NTXT ("%d"), hDataTotal->getL1000KB10MBCnt ()); | |
8523 | leakStat->append (sb.toString ()); | |
8524 | } | |
8525 | if (hDataTotal->getL10MB100MBCnt () > 0) | |
8526 | { | |
8527 | sb.sprintf (GTXT ("10MB - 100MB")); | |
8528 | leakStat->append (sb.toString ()); | |
8529 | sb.sprintf (NTXT ("%d"), hDataTotal->getL10MB100MBCnt ()); | |
8530 | leakStat->append (sb.toString ()); | |
8531 | } | |
8532 | if (hDataTotal->getL100MB1GBCnt () > 0) | |
8533 | { | |
8534 | sb.sprintf (GTXT ("100MB - 1GB")); | |
8535 | leakStat->append (sb.toString ()); | |
8536 | sb.sprintf (NTXT ("%d"), hDataTotal->getL100MB1GBCnt ()); | |
8537 | leakStat->append (sb.toString ()); | |
8538 | } | |
8539 | if (hDataTotal->getL1GB10GBCnt () > 0) | |
8540 | { | |
8541 | sb.sprintf (GTXT ("1GB - 10GB")); | |
8542 | leakStat->append (sb.toString ()); | |
8543 | sb.sprintf (NTXT ("%d"), hDataTotal->getL1GB10GBCnt ()); | |
8544 | leakStat->append (sb.toString ()); | |
8545 | } | |
8546 | if (hDataTotal->getL10GB100GBCnt () > 0) | |
8547 | { | |
8548 | sb.sprintf (GTXT ("10GB - 100GB")); | |
8549 | leakStat->append (sb.toString ()); | |
8550 | sb.sprintf (NTXT ("%d"), hDataTotal->getL10GB100GBCnt ()); | |
8551 | leakStat->append (sb.toString ()); | |
8552 | } | |
8553 | if (hDataTotal->getL100GB1TBCnt () > 0) | |
8554 | { | |
8555 | sb.sprintf (GTXT ("100GB - 1TB")); | |
8556 | leakStat->append (sb.toString ()); | |
8557 | sb.sprintf (NTXT ("%d"), hDataTotal->getL100GB1TBCnt ()); | |
8558 | leakStat->append (sb.toString ()); | |
8559 | } | |
8560 | if (hDataTotal->getL1TB10TBCnt () > 0) | |
8561 | { | |
8562 | sb.sprintf (GTXT ("1TB - 10TB")); | |
8563 | leakStat->append (sb.toString ()); | |
8564 | sb.sprintf (NTXT ("%d"), hDataTotal->getL1TB10TBCnt ()); | |
8565 | leakStat->append (sb.toString ()); | |
8566 | } | |
8567 | ||
8568 | sb.sprintf (GTXT ("Smallest leaked bytes")); | |
8569 | leakStat->append (sb.toString ()); | |
8570 | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getLSmallestBytes ())); | |
8571 | leakStat->append (sb.toString ()); | |
8572 | ||
8573 | sb.sprintf (GTXT ("Largest leaked bytes")); | |
8574 | leakStat->append (sb.toString ()); | |
8575 | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getLLargestBytes ())); | |
8576 | leakStat->append (sb.toString ()); | |
8577 | ||
8578 | sb.sprintf (GTXT ("Total leaked")); | |
8579 | leakStat->append (sb.toString ()); | |
8580 | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getLeakCnt ())); | |
8581 | leakStat->append (sb.toString ()); | |
8582 | ||
8583 | sb.sprintf (GTXT ("Total bytes")); | |
8584 | leakStat->append (sb.toString ()); | |
8585 | sb.sprintf (NTXT ("%lld"), (long long) (hDataTotal->getLeakBytes ())); | |
8586 | leakStat->append (sb.toString ()); | |
8587 | } | |
8588 | Vector<Vector<char*>*>* statisticsData = new Vector<Vector<char*>*>(3); | |
8589 | statisticsData->store (0, memoryUsage); | |
8590 | statisticsData->store (1, allocStat); | |
8591 | statisticsData->store (2, leakStat); | |
8592 | return statisticsData; | |
8593 | } | |
8594 | ||
8595 | Vector<char*> * | |
8596 | dbeGetFuncNames (int dbevindex, Vector<Obj> *funcs) | |
8597 | { | |
8598 | int len = funcs->size (); | |
8599 | Vector<char*> *list = new Vector<char*>(len); | |
8600 | for (int i = 0; i < len; i++) | |
8601 | list->store (i, dbeGetFuncName (dbevindex, funcs->fetch (i))); // no strdup() | |
8602 | return list; | |
8603 | } | |
8604 | ||
8605 | Vector<char*> * | |
8606 | dbeGetObjNamesV2 (int dbevindex, Vector<uint64_t> *ids) | |
8607 | { | |
8608 | int len = ids->size (); | |
8609 | Vector<char*> *list = new Vector<char*>(len); | |
8610 | for (int i = 0; i < len; i++) | |
8611 | list->store (i, dbeGetObjNameV2 (dbevindex, ids->fetch (i))); // no strdup() | |
8612 | return list; | |
8613 | } | |
8614 | ||
8615 | char * | |
8616 | dbeGetFuncName (int dbevindex, Obj func) | |
8617 | { | |
8618 | DbeView *dbev = dbeSession->getView (dbevindex); | |
8619 | if (dbev == NULL) | |
8620 | abort (); | |
8621 | if (func == 0) | |
8622 | return NULL; | |
8623 | char *fname; | |
8624 | fname = ((Histable *) func)->get_name (dbev->get_name_format ()); | |
8625 | return fname ? dbe_strdup (fname) : NULL; | |
8626 | } | |
8627 | ||
8628 | Vector<uint64_t> * | |
8629 | dbeGetFuncIds (int dbevindex, Vector<Obj> *funcs) | |
8630 | { | |
8631 | int len = funcs->size (); | |
8632 | Vector<uint64_t> *list = new Vector<uint64_t>(len); | |
8633 | for (int i = 0; i < len; i++) | |
8634 | list->store (i, dbeGetFuncId (dbevindex, funcs->fetch (i))); | |
8635 | return list; | |
8636 | } | |
8637 | ||
8638 | uint64_t | |
8639 | dbeGetFuncId (int dbevindex, Obj func) | |
8640 | { | |
8641 | DbeView *dbev = dbeSession->getView (dbevindex); | |
8642 | if (dbev == NULL) | |
8643 | abort (); | |
8644 | if (func == 0) | |
8645 | return 0; | |
8646 | uint64_t id = ((Histable *) func)->id; | |
8647 | return id; | |
8648 | } | |
8649 | ||
8650 | char * | |
8651 | dbeGetObjNameV2 (int dbevindex, uint64_t id) | |
8652 | { | |
8653 | DbeView *dbev = dbeSession->getView (dbevindex); | |
8654 | if (dbev == NULL) | |
8655 | abort (); | |
8656 | Histable *obj = dbeSession->findObjectById (id); | |
8657 | if (obj == NULL) | |
8658 | return NULL; | |
8659 | char *fname = obj->get_name (dbev->get_name_format ()); | |
8660 | return fname ? dbe_strdup (fname) : NULL; | |
8661 | } | |
8662 | ||
8663 | char * | |
8664 | dbeGetDataspaceTypeDesc (int /*dbevindex*/, Obj stack) | |
8665 | { | |
8666 | if (stack == 0) | |
8667 | return NULL; | |
8668 | Histable *hist = CallStack::getStackPC ((void *) stack, 0); | |
8669 | DbeInstr *instr; | |
8670 | Histable::Type type = hist->get_type (); | |
8671 | if (type != Histable::INSTR) | |
8672 | return NULL; | |
8673 | else | |
8674 | instr = (DbeInstr *) hist; | |
8675 | char *descriptor = instr->get_descriptor (); | |
8676 | return descriptor ? dbe_strdup (descriptor) : NULL; | |
8677 | } | |
8678 | ||
8679 | Vector<void*> * | |
8680 | dbeGetDataDescriptorsV2 (int exp_id) | |
8681 | { | |
8682 | Experiment *exp = dbeSession->get_exp (exp_id); | |
8683 | if (exp == NULL) | |
8684 | return NULL; | |
8685 | Vector<int> *dataId = new Vector<int>; | |
8686 | Vector<char*> *dataName = new Vector<char*>; | |
8687 | Vector<char*> *dataUName = new Vector<char*>; | |
8688 | Vector<int> *auxProp = new Vector<int>; | |
8689 | Vector<DataDescriptor*> *ddscr = exp->getDataDescriptors (); | |
8690 | for (int i = 0; i < ddscr->size (); i++) | |
8691 | { | |
8692 | DataDescriptor *dataDscr = ddscr->fetch (i); | |
8693 | if (dataDscr->getFlags () & DDFLAG_NOSHOW) | |
8694 | continue; | |
8695 | int data_id = dataDscr->getId (); | |
8696 | int aux_prop_id = (data_id == DATA_HWC) ? PROP_HWCTAG : PROP_NONE; | |
8697 | dataId->append (data_id); | |
8698 | dataName->append (strdup (dataDscr->getName ())); | |
8699 | dataUName->append (strdup (dataDscr->getUName ())); | |
8700 | auxProp->append (aux_prop_id); | |
8701 | } | |
8702 | delete ddscr; | |
8703 | Vector<void*> *res = new Vector<void*>(3); | |
8704 | res->store (0, dataId); | |
8705 | res->store (1, dataName); | |
8706 | res->store (2, dataUName); | |
8707 | res->store (3, auxProp); | |
8708 | return res; | |
8709 | } | |
8710 | ||
8711 | Vector<void*> * | |
8712 | dbeGetDataPropertiesV2 (int exp_id, int data_id) | |
8713 | { | |
8714 | Experiment *exp = dbeSession->get_exp (exp_id); | |
8715 | if (exp == NULL) | |
8716 | return NULL; | |
8717 | DataDescriptor *dataDscr = exp->get_raw_events (data_id); | |
8718 | if (dataDscr == NULL) | |
8719 | return NULL; | |
8720 | Vector<PropDescr*> *props = dataDscr->getProps (); | |
8721 | Vector<int> *propId = new Vector<int>(props->size ()); | |
8722 | Vector<char*> *propUName = new Vector<char*>(props->size ()); | |
8723 | Vector<int> *propTypeId = new Vector<int>(props->size ()); | |
8724 | Vector<char*> *propTypeName = new Vector<char*>(props->size ()); | |
8725 | Vector<int> *propFlags = new Vector<int>(props->size ()); | |
8726 | Vector<char*> *propName = new Vector<char*>(props->size ()); | |
8727 | Vector<void*> *propStateNames = new Vector<void*>(props->size ()); | |
8728 | Vector<void*> *propStateUNames = new Vector<void*>(props->size ()); | |
8729 | ||
8730 | for (int i = 0; i < props->size (); i++) | |
8731 | { | |
8732 | PropDescr *prop = props->fetch (i); | |
8733 | char *pname = prop->name; | |
8734 | if (pname == NULL) | |
8735 | pname = NTXT (""); | |
8736 | char *uname = prop->uname; | |
8737 | if (uname == NULL) | |
8738 | uname = pname; | |
8739 | int vtypeNum = prop->vtype; | |
8740 | if (vtypeNum < 0 || vtypeNum >= TYPE_LAST) | |
8741 | vtypeNum = TYPE_NONE; | |
8742 | const char * vtypeNames[] = VTYPE_TYPE_NAMES; | |
8743 | const char *vtype = vtypeNames[prop->vtype]; | |
8744 | Vector<char*> *stateNames = NULL; | |
8745 | Vector<char*> *stateUNames = NULL; | |
8746 | int nStates = prop->getMaxState (); | |
8747 | if (nStates > 0) | |
8748 | { | |
8749 | stateNames = new Vector<char*>(nStates); | |
8750 | stateUNames = new Vector<char*>(nStates); | |
8751 | for (int kk = 0; kk < nStates; kk++) | |
8752 | { | |
8753 | const char * stateName = prop->getStateName (kk); | |
8754 | stateNames->store (kk, dbe_strdup (stateName)); | |
8755 | const char * Uname = prop->getStateUName (kk); | |
8756 | stateUNames->store (kk, dbe_strdup (Uname)); | |
8757 | } | |
8758 | } | |
8759 | propId->store (i, prop->propID); | |
8760 | propUName->store (i, dbe_strdup (uname)); | |
8761 | propTypeId->store (i, prop->vtype); | |
8762 | propTypeName->store (i, dbe_strdup (vtype)); | |
8763 | propFlags->store (i, prop->flags); | |
8764 | propName->store (i, dbe_strdup (pname)); | |
8765 | propStateNames->store (i, stateNames); | |
8766 | propStateUNames->store (i, stateUNames); | |
8767 | } | |
8768 | Vector<void*> *res = new Vector<void*>(7); | |
8769 | res->store (0, propId); | |
8770 | res->store (1, propUName); | |
8771 | res->store (2, propTypeId); | |
8772 | res->store (3, propTypeName); | |
8773 | res->store (4, propFlags); | |
8774 | res->store (5, propName); | |
8775 | res->store (6, propStateNames); | |
8776 | res->store (7, propStateUNames); | |
8777 | return res; | |
8778 | } | |
8779 | ||
8780 | Vector<void *> * | |
8781 | dbeGetExperimentTimeInfo (Vector<int> *exp_ids) | |
8782 | { | |
8783 | int sz = exp_ids->size (); | |
8784 | Vector<long long> *offset_time = new Vector<long long> (sz); | |
8785 | Vector<long long> *start_time = new Vector<long long> (sz); | |
8786 | Vector<long long> *end_time = new Vector<long long> (sz); | |
8787 | Vector<long long> *start_wall_sec = new Vector<long long> (sz); | |
8788 | Vector<char* > *hostname = new Vector<char*> (sz); | |
8789 | Vector<int> *cpu_freq = new Vector<int> (sz); | |
8790 | for (int ii = 0; ii < sz; ii++) | |
8791 | { | |
8792 | int expIdx = exp_ids->fetch (ii); | |
8793 | { // update end_time by forcing fetch of experiment data | |
8794 | // workaround until dbeGetEndTime() is more robust | |
8795 | int id = (expIdx < 0) ? 0 : expIdx; | |
8796 | Experiment *exp = dbeSession->get_exp (id); | |
8797 | if (exp) | |
8798 | { | |
8799 | Vector<DataDescriptor*> *ddscr = exp->getDataDescriptors (); | |
8800 | delete ddscr; | |
8801 | } | |
8802 | } | |
8803 | offset_time->store (ii, dbeGetRelativeStartTime (0, expIdx)); | |
8804 | start_time->store (ii, dbeGetStartTime (0, expIdx)); | |
8805 | end_time->store (ii, dbeGetEndTime (0, expIdx)); | |
8806 | start_wall_sec->store (ii, dbeGetWallStartSec (0, expIdx)); | |
8807 | hostname->store (ii, dbeGetHostname (0, expIdx)); | |
8808 | cpu_freq->store (ii, dbeGetClock (0, expIdx)); | |
8809 | } | |
8810 | Vector<void*> *res = new Vector<void*>(4); | |
8811 | res->store (0, offset_time); | |
8812 | res->store (1, start_time); | |
8813 | res->store (2, end_time); | |
8814 | res->store (3, start_wall_sec); | |
8815 | res->store (4, hostname); | |
8816 | res->store (5, cpu_freq); | |
8817 | return res; | |
8818 | } | |
8819 | ||
8820 | Vector<void *> * | |
8821 | dbeGetExperimentDataDescriptors (Vector<int> *exp_ids) | |
8822 | { | |
8823 | int sz = exp_ids->size (); | |
8824 | Vector<void*> *exp_dscr_info = new Vector<void*> (sz); | |
8825 | Vector<void*> *exp_dscr_props = new Vector<void*> (sz); | |
8826 | ||
8827 | for (int ii = 0; ii < sz; ii++) | |
8828 | { | |
8829 | int expIdx = exp_ids->fetch (ii); | |
8830 | Vector<void*> *ddscrInfo = dbeGetDataDescriptorsV2 (expIdx); | |
8831 | Vector<void*> *ddscrProps = new Vector<void*> (); // one entry per ddscrInfo | |
8832 | if (ddscrInfo) | |
8833 | { | |
8834 | Vector<int> *dataId = (Vector<int>*)ddscrInfo->fetch (0); | |
8835 | if (dataId) | |
8836 | { | |
8837 | // loop thru data descriptors | |
8838 | int ndata = dataId->size (); | |
8839 | for (int j = 0; j < ndata; ++j) | |
8840 | { | |
8841 | Vector<void*> *props = dbeGetDataPropertiesV2 (expIdx, dataId->fetch (j)); | |
8842 | ddscrProps->store (j, props); | |
8843 | } | |
8844 | } | |
8845 | } | |
8846 | exp_dscr_info->store (ii, ddscrInfo); | |
8847 | exp_dscr_props->store (ii, ddscrProps); | |
8848 | } | |
8849 | Vector<void*> *res = new Vector<void*>(2); | |
8850 | res->store (0, exp_dscr_info); | |
8851 | res->store (1, exp_dscr_props); | |
8852 | return res; | |
8853 | } | |
8854 | ||
8855 | static Vector<void *> * | |
8856 | dbeGetTLDataRepVals (VMode view_mode, hrtime_t start_ts, hrtime_t delta, | |
8857 | int numDeltas, DataView*packets, | |
8858 | Vector<long> *representativeEvents, bool showDuration); | |
8859 | ||
8860 | static bool | |
8861 | dbeHasTLData (int dbevindex, int exp_id, int data_id, int entity_prop_id, | |
8862 | int entity_prop_value, int aux) | |
8863 | { | |
8864 | DataView *packets = | |
8865 | getTimelinePackets (dbevindex, exp_id, data_id, entity_prop_id); | |
8866 | if (!packets || packets->getSize () == 0) | |
8867 | return false; | |
8868 | long start_ind = getIdxByVals (packets, aux, entity_prop_value, | |
8869 | 0, DataView::REL_GTEQ); // time >= 0 | |
8870 | if (start_ind < 0) | |
8871 | return false; | |
8872 | ||
8873 | DbeView *dbev = dbeSession->getView (dbevindex); | |
8874 | VMode view_mode = dbev->get_view_mode (); | |
8875 | Experiment *exp = dbeSession->get_exp (exp_id); | |
8876 | if (!hasInvisbleTLEvents (exp, view_mode)) | |
8877 | return true; // all events are visible, no further checking required | |
8878 | long end_ind = getIdxByVals (packets, aux, entity_prop_value, | |
8879 | MAX_TIME, DataView::REL_LTEQ); | |
8880 | for (long ii = start_ind; ii <= end_ind; ii++) | |
8881 | { | |
8882 | if (!isVisibleTLEvent (exp, view_mode, packets, ii)) | |
8883 | continue; | |
8884 | return true; // first visible packet => has data | |
8885 | } | |
8886 | return false; | |
8887 | } | |
8888 | ||
8889 | Vector<bool> * | |
8890 | dbeHasTLData (int dbev_index, Vector<int> *exp_ids, Vector<int> *data_ids, | |
8891 | Vector<int> *entity_prop_ids, // LWP,CPU,THR, etc | |
8892 | Vector<int> *entity_prop_values, Vector<int> *auxs) | |
8893 | { | |
8894 | DbeView *dbev = dbeSession->getView (dbev_index); | |
8895 | if (!dbev->isShowAll () && (dbev->isShowHideChanged () | |
8896 | || dbev->isNewViewMode ())) | |
8897 | { | |
8898 | // LIBRARY_VISIBILITY | |
8899 | dbev->resetAndConstructShowHideStacks (); | |
8900 | if (dbev->isNewViewMode ()) | |
8901 | dbev->resetNewViewMode (); | |
8902 | if (dbev->isShowHideChanged ()) | |
8903 | dbev->resetShowHideChanged (); | |
8904 | } | |
8905 | ||
8906 | int sz = exp_ids->size (); | |
8907 | Vector<bool> *hasVec = new Vector<bool>(sz); | |
8908 | for (int ii = 0; ii < sz; ii++) | |
8909 | { | |
8910 | bool hasData = dbeHasTLData (dbev_index, exp_ids->fetch (ii), | |
8911 | data_ids->fetch (ii), | |
8912 | entity_prop_ids->fetch (ii), | |
8913 | entity_prop_values->fetch (ii), | |
8914 | auxs->fetch (ii)); | |
8915 | hasVec->store (ii, hasData); | |
8916 | } | |
8917 | return hasVec; | |
8918 | } | |
8919 | ||
8920 | /* | |
8921 | * dbeGetTLData implements: | |
8922 | * FROM data_id | |
8923 | * DURATION >= delta AND ( start_ts <= TSTAMP < start_ts+num*delta OR | |
8924 | * start_ts <= TSTAMP-DURATION < start_ts+num*delta ) | |
8925 | * OR | |
8926 | * FAIR( DURATION < delta AND ( start_ts <= TSTAMP < start_ts+num*delta ) ) | |
8927 | * WHERE lfilter | |
8928 | */ | |
8929 | ||
8930 | Vector<void *> * | |
8931 | dbeGetTLData ( | |
8932 | int dbevindex, | |
8933 | int exp_id, | |
8934 | int data_id, // DATA_* | |
8935 | int entity_prop_id, // Show PROP_LWPID, PROP_CPUID, PROP_THRID, PROP_EXPID, or N/A | |
8936 | int entity_prop_value, // which LWPID, CPUID, THRID, EXPID for this request | |
8937 | int aux, | |
8938 | hrtime_t param_start_ts, | |
8939 | hrtime_t param_delta, | |
8940 | int param_numDeltas, | |
8941 | bool getRepresentatives, // fetch TL representatives | |
8942 | Vector<char *> *chartProps) // calculate sums for these property vals | |
8943 | { | |
8944 | const hrtime_t start_ts = param_start_ts; | |
8945 | const hrtime_t delta = param_delta; | |
8946 | const int numDeltas = param_numDeltas; | |
8947 | DbeView *dbev = dbeSession->getView (dbevindex); | |
8948 | if (dbev == NULL) | |
8949 | abort (); | |
8950 | Experiment *exp = dbeSession->get_exp (exp_id); | |
8951 | if (exp == NULL) | |
8952 | return NULL; | |
8953 | if (getRepresentatives == false && chartProps == NULL) | |
8954 | return NULL; | |
8955 | if (delta <= 0) | |
8956 | return NULL; | |
8957 | ||
8958 | hrtime_t tmp_ts = start_ts + delta * numDeltas; | |
8959 | if (tmp_ts < start_ts) | |
8960 | tmp_ts = MAX_TIME; | |
8961 | const hrtime_t end_ts = tmp_ts; | |
8962 | if (exp->get_status () == Experiment::INCOMPLETE && | |
8963 | exp->getLastEvent () < end_ts) | |
8964 | exp->update (); | |
8965 | DataView *packets = | |
8966 | getTimelinePackets (dbevindex, exp_id, data_id, entity_prop_id); | |
8967 | if (packets == NULL) | |
8968 | return NULL; // strange, no data view? | |
8969 | ||
8970 | VMode view_mode = dbev->get_view_mode (); // user, expert, machine //YXXX yuck | |
8971 | ||
8972 | // storage for calculating timeline representative events | |
8973 | Vector<long> *representativeEvents = NULL; | |
8974 | // list of representative events to be displayed on TL | |
8975 | Vector<int> *binRepIdx = NULL; | |
8976 | // for each bin, index of current "best" representativeEvent | |
8977 | Vector<void*> *representativeVals = NULL; | |
8978 | // TL representative packets' values | |
8979 | ||
8980 | // storage for calculating charts | |
8981 | Vector<int> *propIds = NULL; // [propIdx], which prop to measure | |
8982 | Vector<void*> *propVals = NULL; // [propIdx][bin], prop vals | |
8983 | Vector<int> *propNumStates = NULL; // [propIdx], how many states for prop? | |
8984 | Vector<bool> *propCumulativeChart = NULL; // [propIdx], data represents cumulative totals | |
8985 | Vector<long long> *propCumulativeRecentBinLastVal = NULL; // [propIdx], most recent value | |
8986 | Vector<long long> *propCumulativeRecentBinHighVal = NULL; // [propIdx], highest value for propCumulativeRecentBin | |
8987 | Vector<int> *propCumulativeRecentBin = NULL; // [propIdx], most recent bin | |
8988 | ||
8989 | // determine when to show duration of events | |
8990 | bool tmp_repsShowDuration = false; | |
8991 | bool tmp_statesUseDuration = false; | |
8992 | bool tmp_extendMicrostates = false; | |
8993 | const hrtime_t ptimerTickDuration = exp->get_params ()->ptimer_usec * 1000LL; // nanoseconds per tick | |
8994 | const bool hasDuration = packets->getProp (PROP_EVT_TIME) ? true : false; | |
8995 | if (hasDuration) | |
8996 | { | |
8997 | switch (entity_prop_id) | |
8998 | { | |
8999 | case PROP_CPUID: | |
9000 | tmp_repsShowDuration = false; | |
9001 | tmp_statesUseDuration = false; | |
9002 | break; | |
9003 | case PROP_THRID: | |
9004 | case PROP_LWPID: | |
9005 | tmp_repsShowDuration = true; | |
9006 | tmp_statesUseDuration = true; | |
9007 | tmp_extendMicrostates = (DATA_CLOCK == data_id) && (ptimerTickDuration < param_delta); | |
9008 | break; | |
9009 | case PROP_EXPID: | |
9010 | case PROP_NONE: // experiment summary row uses this | |
9011 | default: | |
9012 | if (DATA_SAMPLE == data_id) | |
9013 | { | |
9014 | tmp_repsShowDuration = true; | |
9015 | tmp_statesUseDuration = true; | |
9016 | } | |
9017 | else if (DATA_GCEVENT == data_id) | |
9018 | { | |
9019 | tmp_repsShowDuration = true; | |
9020 | tmp_statesUseDuration = true; | |
9021 | } | |
9022 | else if (DATA_CLOCK == data_id) | |
9023 | { | |
9024 | tmp_repsShowDuration = false; | |
9025 | tmp_statesUseDuration = true; | |
9026 | tmp_extendMicrostates = true; | |
9027 | } | |
9028 | else | |
9029 | { | |
9030 | tmp_repsShowDuration = false; | |
9031 | tmp_statesUseDuration = true; | |
9032 | } | |
9033 | break; | |
9034 | } | |
9035 | } | |
9036 | const bool repsShowDuration = tmp_repsShowDuration; // show stretched callstacks | |
9037 | const bool statesUseDuration = tmp_statesUseDuration; // use duration to calculate state charts | |
9038 | const bool extendMicrostates = tmp_extendMicrostates; // we show discrete profiling microstates with | |
9039 | // width=(tick-1), but for computing | |
9040 | // zoomed-out graphs we need to extend to | |
9041 | // account for all ticks, width=(ntick) | |
9042 | const bool reverseScan = repsShowDuration || extendMicrostates; // scan packets in reverse | |
9043 | ||
9044 | // determine range of packet indices (lo_pkt_idx, hi_pkt_idx) | |
9045 | long lo_pkt_idx, hi_pkt_idx; | |
9046 | if (extendMicrostates && !(entity_prop_id == PROP_THRID || entity_prop_id == PROP_LWPID)) | |
9047 | { | |
9048 | // merging data from multiple threads, need to scan all packets with timestamp [start_ts, exp end] | |
9049 | hrtime_t exp_end_time = exp->getLastEvent () + 1; | |
9050 | hi_pkt_idx = getIdxByVals (packets, aux, entity_prop_value, | |
9051 | exp_end_time, DataView::REL_LT); // last item | |
9052 | } | |
9053 | else | |
9054 | hi_pkt_idx = getIdxByVals (packets, aux, entity_prop_value, | |
9055 | end_ts, DataView::REL_LT); | |
9056 | if (repsShowDuration) | |
9057 | { | |
9058 | // There are two issues to deal with | |
9059 | // 1. events that end "off screen" to the right | |
9060 | // 2. overlapping events | |
9061 | ||
9062 | // 1. events that end "off screen" to the right | |
9063 | // For now, we only consistently handle the case where events don't overlap. | |
9064 | // Note that packet timestamps mark end of duration, not start. | |
9065 | // This means that the rightmost event won't be within hi_pkt_idx. | |
9066 | // Solution: Check if end+1 packet _started_ in-range | |
9067 | // Caveat: because we only look ahead by one packet, if there are | |
9068 | // overlapping duration events (e.g. EXPID aggregation)), zoom level | |
9069 | // and panning combo may cause events with TSTAMP>end_ts | |
9070 | // to appear/disappear. A complete solution would involve | |
9071 | // a solution to 2. | |
9072 | ||
9073 | // 2. overlapping events | |
9074 | // For now, we have a simplistic solution that makes "wide" events win. However, | |
9075 | // a future solution for deterministically dealing with overlap might look like this: | |
9076 | // - find all packets that touch the visible time range | |
9077 | // - possibly use two DataViews: one with TSTAMP_HI sort and one with TSTAMP_LO | |
9078 | // sort to allow efficient determination of packets with HI and LO endpoints in-range | |
9079 | // - create buckets to capture "winning" event for each bin (each pixel, that is) | |
9080 | // - sort the new list of packets by TSTAMP_HI (for example) | |
9081 | // - looping thru the packets that are in-range, update every bin it touches with it's id | |
9082 | // - if there is overlap, earlier packets will be kicked out of bins | |
9083 | // - On the GUI side, paint one event at a time, as normal. | |
9084 | // - However, for selections, recognize that duration of event may span many bins | |
9085 | // | |
9086 | long idx; | |
9087 | if (hi_pkt_idx >= 0) | |
9088 | // a packet was found to the left of the end time | |
9089 | idx = hi_pkt_idx + 1; // attempt to go one packet right | |
9090 | else | |
9091 | idx = getIdxByVals (packets, aux, entity_prop_value, | |
9092 | end_ts, DataView::REL_GTEQ); | |
9093 | if (isValidIdx (packets, entity_prop_id, aux, entity_prop_value, idx)) | |
9094 | { | |
9095 | int64_t pkt_ts = packets->getLongValue (PROP_TSTAMP, idx); | |
9096 | int64_t duration = packets->getLongValue (PROP_EVT_TIME, idx); | |
9097 | pkt_ts -= duration; | |
9098 | if (pkt_ts < end_ts) | |
9099 | hi_pkt_idx = idx; | |
9100 | } | |
9101 | } | |
9102 | lo_pkt_idx = getIdxByVals (packets, aux, entity_prop_value, | |
9103 | start_ts, DataView::REL_GTEQ); | |
9104 | ||
9105 | // allocate structs that return chart data | |
9106 | bool hasCumulativeCharts = false; | |
9107 | if (chartProps && chartProps->size () > 0) | |
9108 | { | |
9109 | int nprops = chartProps->size (); | |
9110 | // pre-allocate storage | |
9111 | propIds = new Vector<int> (nprops); | |
9112 | propVals = new Vector<void*>(nprops); | |
9113 | propNumStates = new Vector<int> (nprops); | |
9114 | propCumulativeChart = new Vector<bool>(nprops); | |
9115 | propCumulativeRecentBinLastVal = new Vector<long long>(nprops); | |
9116 | propCumulativeRecentBinHighVal = new Vector<long long>(nprops); | |
9117 | propCumulativeRecentBin = new Vector<int>(nprops); | |
9118 | for (int propNum = 0; propNum < nprops; propNum++) | |
9119 | { | |
9120 | const char* propStr = chartProps->fetch (propNum); | |
9121 | int items_per_prop = 0; | |
9122 | int prop_id = PROP_NONE; | |
9123 | if (!strcmp (propStr, "EVT_COUNT")) | |
9124 | items_per_prop = 1; // use PROP_NONE for counting packets | |
9125 | else | |
9126 | { | |
9127 | int lookup_prop_id = dbeSession->getPropIdByName (propStr); | |
9128 | PropDescr *propDscr = packets->getProp (lookup_prop_id); | |
9129 | if (propDscr != NULL) | |
9130 | { | |
9131 | switch (propDscr->vtype) | |
9132 | { | |
9133 | case TYPE_INT32: | |
9134 | case TYPE_UINT32: | |
9135 | case TYPE_INT64: | |
9136 | case TYPE_UINT64: | |
9137 | items_per_prop = propDscr->getMaxState () + 1; | |
9138 | // add extra slot to store values with out-of-range idx | |
9139 | prop_id = lookup_prop_id; | |
9140 | break; | |
9141 | case TYPE_DOUBLE: | |
9142 | break; // not implemented yet | |
9143 | case TYPE_STRING: | |
9144 | case TYPE_OBJ: | |
9145 | case TYPE_DATE: | |
9146 | default: | |
9147 | break; | |
9148 | } | |
9149 | } | |
9150 | } | |
9151 | void *vals; | |
9152 | if (!items_per_prop) | |
9153 | vals = NULL; | |
9154 | else if (items_per_prop == 1) | |
9155 | { | |
9156 | Vector<long long> *longVals = new Vector<long long> (); | |
9157 | longVals->store (numDeltas - 1, 0); // initialize all elements | |
9158 | vals = longVals; | |
9159 | } | |
9160 | else | |
9161 | { | |
9162 | Vector<Vector<long long>*> *stateVals = | |
9163 | new Vector<Vector<long long>*> (); | |
9164 | vals = stateVals; | |
9165 | // initialize only on-demand, some may not be needed | |
9166 | } | |
9167 | ||
9168 | bool isCumulativeChart; | |
9169 | #define YXXX_HEAP_VS_TIME 1 // YXXX add data meaning to properties? | |
9170 | #if YXXX_HEAP_VS_TIME | |
9171 | isCumulativeChart = (prop_id == PROP_HCUR_LEAKS || prop_id == PROP_HCUR_ALLOCS); | |
9172 | #endif | |
9173 | if (isCumulativeChart) | |
9174 | hasCumulativeCharts = true; | |
9175 | propIds->store (propNum, prop_id); | |
9176 | propVals->store (propNum, vals); | |
9177 | propNumStates->store (propNum, items_per_prop); | |
9178 | propCumulativeRecentBinLastVal->store (propNum, 0); | |
9179 | propCumulativeRecentBinHighVal->store (propNum, 0); | |
9180 | propCumulativeRecentBin->store (propNum, 0); | |
9181 | propCumulativeChart->store (propNum, isCumulativeChart); | |
9182 | } | |
9183 | } | |
9184 | ||
9185 | // Adjust idx range for calculating 'cumulative charts' e.g. heap size | |
9186 | if (hasCumulativeCharts) | |
9187 | { | |
9188 | // set initial values if earlier packet exists | |
9189 | long lo_idx; | |
9190 | if (lo_pkt_idx >= 0) | |
9191 | // packet was found to the right of start | |
9192 | lo_idx = lo_pkt_idx - 1; // attempt to go left by one event | |
9193 | else | |
9194 | // no packet was to the right of start, look left of start | |
9195 | lo_idx = getIdxByVals (packets, aux, entity_prop_value, | |
9196 | start_ts, DataView::REL_LT); | |
9197 | if (isValidIdx (packets, entity_prop_id, aux, entity_prop_value, lo_idx)) | |
9198 | { | |
9199 | // preceding packet found | |
9200 | // update initial values | |
9201 | int nprops = propCumulativeChart->size (); | |
9202 | for (int propNum = 0; propNum < nprops; propNum++) | |
9203 | { | |
9204 | if (!propCumulativeChart->fetch (propNum)) | |
9205 | continue; | |
9206 | int propId = propIds->fetch (propNum); | |
9207 | long long value = packets->getLongValue (propId, lo_idx); | |
9208 | propCumulativeRecentBinLastVal->store (propNum, value); | |
9209 | propCumulativeRecentBinHighVal->store (propNum, value); | |
9210 | } | |
9211 | // update indices used for iterating | |
9212 | lo_pkt_idx = lo_idx; | |
9213 | if (hi_pkt_idx < lo_pkt_idx) | |
9214 | hi_pkt_idx = lo_pkt_idx; | |
9215 | } | |
9216 | } | |
9217 | if (lo_pkt_idx < 0 || hi_pkt_idx < 0) | |
9218 | goto dbeGetTLData_done; // no data; return empty vectors, not null | |
9219 | ||
9220 | // representative events (subset of callstacks to represent on TL) | |
9221 | if (getRepresentatives) | |
9222 | { | |
9223 | representativeEvents = new Vector<long>(numDeltas); | |
9224 | // per-bin, longest event's index | |
9225 | binRepIdx = new Vector<int>(numDeltas); | |
9226 | for (int ii = 0; ii < numDeltas; ++ii) | |
9227 | binRepIdx->append (-1); | |
9228 | } | |
9229 | // While packets are sorted by _end_ timestamp (TSTAMP), | |
9230 | // after calculating start times for non-zero durations, | |
9231 | // start times are not guaranteed be monotonically increasing. | |
9232 | // For packets with duration, we'll scan them in reverse order to | |
9233 | // take advantage of the monotonically decreasing _end_ timestamps. | |
9234 | long start_idx, idx_inc; | |
9235 | if (!reverseScan) | |
9236 | { | |
9237 | start_idx = lo_pkt_idx; | |
9238 | idx_inc = 1; | |
9239 | } | |
9240 | else | |
9241 | { | |
9242 | start_idx = hi_pkt_idx; | |
9243 | idx_inc = -1; | |
9244 | } | |
9245 | for (long ii = start_idx; ii >= lo_pkt_idx && ii <= hi_pkt_idx; ii += idx_inc) | |
9246 | { | |
9247 | if (!isVisibleTLEvent (exp, view_mode, packets, ii) && !hasCumulativeCharts) | |
9248 | continue; | |
9249 | ||
9250 | // determine packet time duration and start bin | |
9251 | int tmp_start_bin; // packet start bin | |
9252 | int tmp_end_bin; // packet end bin (inclusive) | |
9253 | const hrtime_t pkt_end_ts = packets->getLongValue (PROP_TSTAMP, ii); | |
9254 | const hrtime_t pkt_dur = packets->getLongValue (PROP_EVT_TIME, ii); | |
9255 | const hrtime_t pkt_start_ts = pkt_end_ts - pkt_dur; | |
9256 | if (pkt_end_ts < start_ts && !hasCumulativeCharts) | |
9257 | continue; // weird, should not happen | |
9258 | if (pkt_start_ts >= end_ts) | |
9259 | continue; // could happen | |
9260 | hrtime_t bin_end_ts = pkt_end_ts; | |
9261 | if (bin_end_ts >= end_ts) | |
9262 | bin_end_ts = end_ts - 1; | |
9263 | tmp_end_bin = (int) ((bin_end_ts - start_ts) / delta); | |
9264 | hrtime_t bin_start_ts = pkt_start_ts; | |
9265 | if (bin_start_ts < start_ts) | |
9266 | bin_start_ts = start_ts; // event truncated to left. | |
9267 | tmp_start_bin = (int) ((bin_start_ts - start_ts) / delta); | |
9268 | // By definition | |
9269 | // (end_ts - start_ts) == delta * numDeltas | |
9270 | // and we know | |
9271 | // pkt_start < end_ts | |
9272 | // therefore | |
9273 | // (pkt_start - start_ts) < delta * numDeltas | |
9274 | // (pkt_start - start_ts) / delta < numDeltas | |
9275 | // bin < numDeltas | |
9276 | assert (tmp_end_bin < numDeltas); | |
9277 | assert (tmp_start_bin < numDeltas); | |
9278 | const bool is_offscreen = tmp_end_bin < 0 ? true : false; | |
9279 | if (tmp_end_bin < 0) | |
9280 | tmp_end_bin = 0; | |
9281 | const int pkt_end_bin = tmp_end_bin; // packet end bin (inclusive) | |
9282 | const int pkt_start_bin = tmp_start_bin; | |
9283 | if (getRepresentatives && !is_offscreen) | |
9284 | { // find best representative | |
9285 | // Note: for events with duration, we're scanning packets in order | |
9286 | // of decreasing end-timestamp. This means that the first packet | |
9287 | // that hits a particular _start_ bin will have the longest duration | |
9288 | // of any later packet that might hit that start bin. The | |
9289 | // the first packet will be the best (longest) packet. | |
9290 | const int bin = reverseScan ? pkt_start_bin : pkt_end_bin; | |
9291 | int eventIdx = binRepIdx->fetch (bin); | |
9292 | if (eventIdx == -1) | |
9293 | { | |
9294 | eventIdx = representativeEvents->size (); // append to end | |
9295 | representativeEvents->append (ii); | |
9296 | binRepIdx->store (bin, eventIdx); | |
9297 | } | |
9298 | } | |
9299 | if (propIds) | |
9300 | { // per-bin chart: sum across filtered packets | |
9301 | for (int propNum = 0; propNum < propIds->size (); propNum++) | |
9302 | { | |
9303 | void *thisProp = propVals->fetch (propNum); | |
9304 | if (thisProp == NULL) | |
9305 | continue; // no valid data | |
9306 | if (is_offscreen && !propCumulativeChart->fetch (propNum)) | |
9307 | continue; // offscreen events are only processed for cumulative charts | |
9308 | int propId = propIds->fetch (propNum); | |
9309 | long long val; | |
9310 | if (propId == PROP_NONE) | |
9311 | val = 1; // count | |
9312 | else | |
9313 | val = packets->getLongValue (propId, ii); | |
9314 | long nitems = propNumStates->fetch (propNum); | |
9315 | if (nitems < 1) | |
9316 | continue; | |
9317 | else if (nitems == 1) | |
9318 | { | |
9319 | // chart is not based on not multiple states | |
9320 | Vector<long long>* thisPropVals = | |
9321 | (Vector<long long>*)thisProp; | |
9322 | if (thisPropVals->size () == 0) | |
9323 | thisPropVals->store (numDeltas - 1, 0); | |
9324 | const int bin = statesUseDuration ? pkt_start_bin : pkt_end_bin; | |
9325 | if (!propCumulativeChart->fetch (propNum)) | |
9326 | { | |
9327 | val += thisPropVals->fetch (bin); | |
9328 | thisPropVals->store (bin, val); | |
9329 | } | |
9330 | else | |
9331 | { | |
9332 | // propCumulativeChart | |
9333 | long long high_value = propCumulativeRecentBinHighVal->fetch (propNum); | |
9334 | int last_bin = propCumulativeRecentBin->fetch (propNum); | |
9335 | if (last_bin < bin) | |
9336 | { | |
9337 | // backfill from previous event | |
9338 | // last_bin: store largest value (in case of multiple events) | |
9339 | thisPropVals->store (last_bin, high_value); | |
9340 | // propagate forward the bin's last value | |
9341 | long long last_value = propCumulativeRecentBinLastVal->fetch (propNum); | |
9342 | for (int kk = last_bin + 1; kk < bin; kk++) | |
9343 | thisPropVals->store (kk, last_value); | |
9344 | // prepare new bin for current event | |
9345 | high_value = 0; // high value of next bin is 0. | |
9346 | propCumulativeRecentBinHighVal->store (propNum, high_value); | |
9347 | propCumulativeRecentBin->store (propNum, bin); | |
9348 | } | |
9349 | long long this_value = packets->getLongValue (propId, ii); | |
9350 | propCumulativeRecentBinLastVal->store (propNum, this_value); | |
9351 | if (high_value < this_value) | |
9352 | { | |
9353 | // record the max | |
9354 | high_value = this_value; | |
9355 | propCumulativeRecentBinHighVal->store (propNum, high_value); | |
9356 | } | |
9357 | if (ii == hi_pkt_idx) | |
9358 | { | |
9359 | // bin: show largest value (in case of multiple events | |
9360 | thisPropVals->store (bin, high_value); | |
9361 | //forward fill remaining bins | |
9362 | for (int kk = bin + 1; kk < numDeltas; kk++) | |
9363 | thisPropVals->store (kk, this_value); | |
9364 | } | |
9365 | } | |
9366 | } | |
9367 | else | |
9368 | { | |
9369 | // means val is actually a state # | |
9370 | Vector<Vector<long long>*>* thisPropStateVals = | |
9371 | (Vector<Vector<long long>*>*)thisProp; | |
9372 | if (thisPropStateVals->size () == 0) | |
9373 | thisPropStateVals->store (numDeltas - 1, 0); | |
9374 | long stateNum; | |
9375 | if (val >= 0 && val < nitems) | |
9376 | stateNum = (long) val; | |
9377 | else | |
9378 | stateNum = nitems - 1; // out of range, use last slot | |
9379 | hrtime_t graph_pkt_dur = pkt_dur; | |
9380 | hrtime_t graph_pkt_start_ts = pkt_start_ts; | |
9381 | int tmp2_start_bin = pkt_start_bin; | |
9382 | if (propId == PROP_MSTATE) | |
9383 | { | |
9384 | if (statesUseDuration && extendMicrostates) | |
9385 | { | |
9386 | // microstate stacks are shown and filtered with width=NTICK-1 | |
9387 | // but for microstate graph calcs use width=NTICK. | |
9388 | graph_pkt_dur += ptimerTickDuration; | |
9389 | graph_pkt_start_ts -= ptimerTickDuration; | |
9390 | hrtime_t bin_start_ts = graph_pkt_start_ts; | |
9391 | if (bin_start_ts < start_ts) | |
9392 | bin_start_ts = start_ts; // event truncated to left. | |
9393 | tmp2_start_bin = (int) ((bin_start_ts - start_ts) / delta); | |
9394 | } | |
9395 | } | |
9396 | const int graph_pkt_start_bin = statesUseDuration ? tmp2_start_bin : pkt_end_bin; | |
9397 | ||
9398 | // We will distribute the state's presence evenly over duration of the event. | |
9399 | // When only a 'partial bin' is touched by an event, adjust accordingly. | |
9400 | long long value_per_bin; // weight to be applied to each bin | |
9401 | { | |
9402 | long long weight; | |
9403 | if (propId == PROP_MSTATE) // ticks to nanoseconds | |
9404 | weight = packets->getLongValue (PROP_NTICK, ii) * ptimerTickDuration; | |
9405 | else if (graph_pkt_dur) | |
9406 | weight = graph_pkt_dur; // nanoseconds | |
9407 | else | |
9408 | weight = 1; // no duration; indicate presence | |
9409 | if (graph_pkt_start_bin != pkt_end_bin) | |
9410 | { | |
9411 | // spans multiple bins | |
9412 | double nbins = (double) graph_pkt_dur / delta; | |
9413 | value_per_bin = weight / nbins; | |
9414 | } | |
9415 | else | |
9416 | value_per_bin = weight; | |
9417 | } | |
9418 | for (int evtbin = graph_pkt_start_bin; evtbin <= pkt_end_bin; evtbin++) | |
9419 | { | |
9420 | Vector<long long>* stateValues = | |
9421 | (Vector<long long>*) thisPropStateVals->fetch (evtbin); | |
9422 | if (stateValues == NULL) | |
9423 | { | |
9424 | // on-demand storage | |
9425 | stateValues = new Vector<long long>(nitems); | |
9426 | stateValues->store (nitems - 1, 0); // force memset of full vector | |
9427 | thisPropStateVals->store (evtbin, stateValues); | |
9428 | } | |
9429 | long long new_val = stateValues->fetch (stateNum); | |
9430 | if (graph_pkt_start_bin == pkt_end_bin || | |
9431 | (evtbin > graph_pkt_start_bin && evtbin < pkt_end_bin)) | |
9432 | { | |
9433 | new_val += value_per_bin; | |
9434 | } | |
9435 | else | |
9436 | { | |
9437 | // partial bin | |
9438 | const hrtime_t bin_start = start_ts + evtbin * delta; | |
9439 | const hrtime_t bin_end = start_ts + (evtbin + 1) * delta - 1; | |
9440 | if (evtbin == graph_pkt_start_bin) | |
9441 | { | |
9442 | // leftmost bin | |
9443 | if (graph_pkt_start_ts < bin_start) | |
9444 | new_val += value_per_bin; | |
9445 | else | |
9446 | { | |
9447 | double percent = (double) (bin_end - graph_pkt_start_ts) / delta; | |
9448 | new_val += value_per_bin*percent; | |
9449 | } | |
9450 | } | |
9451 | else | |
9452 | { | |
9453 | // rightmost bin | |
9454 | if (pkt_end_ts > bin_end) | |
9455 | new_val += value_per_bin; | |
9456 | else | |
9457 | { | |
9458 | double percent = (double) (pkt_end_ts - bin_start) / delta; | |
9459 | new_val += value_per_bin*percent; | |
9460 | } | |
9461 | } | |
9462 | } | |
9463 | stateValues->store (stateNum, new_val); | |
9464 | } | |
9465 | } | |
9466 | } | |
9467 | } | |
9468 | } | |
9469 | delete binRepIdx; | |
9470 | delete propIds; | |
9471 | delete propCumulativeChart; | |
9472 | delete propCumulativeRecentBinLastVal; | |
9473 | delete propCumulativeRecentBinHighVal; | |
9474 | delete propCumulativeRecentBin; | |
9475 | if (representativeEvents != NULL && reverseScan) | |
9476 | { | |
9477 | if (repsShowDuration) | |
9478 | { | |
9479 | //YXXX for now prune here, but in the future, let gui decide what to show | |
9480 | // Prune events that are completely obscured long duration events. | |
9481 | // Note: representativeEvents is sorted by decreasing _end_ timestamps. | |
9482 | Vector<long> *prunedEvents = new Vector<long>(numDeltas); | |
9483 | hrtime_t prev_start_ts = MAX_TIME; | |
9484 | long repCnt = representativeEvents->size (); | |
9485 | for (long kk = 0; kk < repCnt; kk++) | |
9486 | { | |
9487 | long ii = representativeEvents->fetch (kk); | |
9488 | hrtime_t tmp_end_ts = packets->getLongValue (PROP_TSTAMP, ii); | |
9489 | hrtime_t tmp_dur = packets->getLongValue (PROP_EVT_TIME, ii); | |
9490 | hrtime_t tmp_start_ts = tmp_end_ts - tmp_dur; | |
9491 | if (tmp_start_ts >= prev_start_ts) | |
9492 | // this event would be completely hidden | |
9493 | // (because of sorting, we know tmp_end_ts <= prev_end_ts) | |
9494 | continue; | |
9495 | prev_start_ts = tmp_start_ts; | |
9496 | prunedEvents->append (ii); | |
9497 | } | |
9498 | // invert order to to get increasing _end_ timestamps | |
9499 | representativeEvents->reset (); | |
9500 | for (long kk = prunedEvents->size () - 1; kk >= 0; kk--) | |
9501 | { | |
9502 | long packet_idx = prunedEvents->fetch (kk); | |
9503 | representativeEvents->append (packet_idx); | |
9504 | } | |
9505 | delete prunedEvents; | |
9506 | } | |
9507 | else | |
9508 | { // !repsShowDuration | |
9509 | // Note: representativeEvents is sorted by decreasing _end_ timestamps. | |
9510 | // Reverse the order: | |
9511 | long hi_idx = representativeEvents->size () - 1; | |
9512 | long lo_idx = 0; | |
9513 | while (hi_idx > lo_idx) | |
9514 | { | |
9515 | // swap | |
9516 | long lo = representativeEvents->fetch (lo_idx); | |
9517 | long hi = representativeEvents->fetch (hi_idx); | |
9518 | representativeEvents->store (lo_idx, hi); | |
9519 | representativeEvents->store (hi_idx, lo); | |
9520 | hi_idx--; | |
9521 | lo_idx++; | |
9522 | } | |
9523 | } | |
9524 | } | |
9525 | ||
9526 | dbeGetTLData_done: | |
9527 | if (getRepresentatives) | |
9528 | { | |
9529 | representativeVals = dbeGetTLDataRepVals (view_mode, start_ts, delta, | |
9530 | numDeltas, packets, representativeEvents, repsShowDuration); | |
9531 | delete representativeEvents; | |
9532 | } | |
9533 | Vector<void*> *results = new Vector<void*> (2); | |
9534 | results->store (0, representativeVals); | |
9535 | results->store (1, propVals); | |
9536 | return results; | |
9537 | } | |
9538 | ||
9539 | // add representative events to return buffer | |
9540 | ||
9541 | static Vector<void *> * | |
9542 | dbeGetTLDataRepVals (VMode view_mode, hrtime_t start_ts, hrtime_t delta, | |
9543 | int numDeltas, DataView*packets, | |
9544 | Vector<long> *representativeEvents, bool showDuration) | |
9545 | { | |
9546 | int numrecs = representativeEvents ? representativeEvents->size () : 0; | |
9547 | // allocate storage for results | |
9548 | Vector<int> *startBins = new Vector<int>(numrecs); | |
9549 | Vector<int> *numBins = new Vector<int>(numrecs); | |
9550 | Vector<Obj> *eventIdxs = new Vector<Obj>(numrecs); | |
9551 | Vector<Obj> *stackIds = NULL; | |
9552 | if (packets->getProp (PROP_FRINFO)) | |
9553 | stackIds = new Vector<Obj>(numrecs); | |
9554 | Vector<int> *mstates = NULL; | |
9555 | if (packets->getProp (PROP_MSTATE)) | |
9556 | mstates = new Vector<int>(numrecs); | |
9557 | Vector<Vector<long long>*> *sampleVals = NULL; | |
9558 | if (packets->getProp (PROP_SMPLOBJ)) | |
9559 | sampleVals = new Vector<Vector<long long>*>(numrecs); | |
9560 | Vector<long long> *timeStart = new Vector<long long>(numrecs); | |
9561 | Vector<long long> *timeEnd = new Vector<long long>(numrecs); | |
9562 | int prevEndBin = -1; // make sure we don't overlap bins | |
9563 | for (int eventIdx = 0; eventIdx < numrecs; eventIdx++) | |
9564 | { | |
9565 | long packetIdx = representativeEvents->fetch (eventIdx); | |
9566 | // long eventId = packets->getIdByIdx( packetIdx ); | |
9567 | const hrtime_t pkt_tstamp = packets->getLongValue (PROP_TSTAMP, packetIdx); | |
9568 | const hrtime_t pkt_dur = showDuration ? packets->getLongValue (PROP_EVT_TIME, packetIdx) : 0; | |
9569 | timeStart->store (eventIdx, pkt_tstamp - pkt_dur); | |
9570 | timeEnd->store (eventIdx, pkt_tstamp); | |
9571 | ||
9572 | // calc startBin | |
9573 | int startBin = (int) ((pkt_tstamp - pkt_dur - start_ts) / delta); | |
9574 | if (startBin <= prevEndBin) | |
9575 | startBin = prevEndBin + 1; | |
9576 | // calc binCnt | |
9577 | int endBin = (int) ((pkt_tstamp - start_ts) / delta); | |
9578 | if (endBin >= numDeltas) | |
9579 | endBin = numDeltas - 1; | |
9580 | int binCnt = endBin - startBin + 1; | |
9581 | prevEndBin = endBin; | |
9582 | startBins->store (eventIdx, startBin); | |
9583 | numBins->store (eventIdx, binCnt); | |
9584 | eventIdxs->store (eventIdx, packetIdx); // store packet's idx | |
9585 | if (stackIds != NULL) | |
9586 | { | |
9587 | void* stackId = getStack (view_mode, packets, packetIdx); | |
9588 | stackIds->store (eventIdx, (Obj) (unsigned long) stackId); | |
9589 | } | |
9590 | if (mstates != NULL) | |
9591 | { | |
9592 | int mstate = packets->getIntValue (PROP_MSTATE, packetIdx); | |
9593 | mstates->store (eventIdx, mstate); | |
9594 | } | |
9595 | if (sampleVals != NULL) | |
9596 | { | |
9597 | Sample* sample = (Sample*) packets->getObjValue (PROP_SMPLOBJ, packetIdx); | |
9598 | if (!sample || !sample->get_usage ()) | |
9599 | sample = sample; | |
9600 | else | |
9601 | { | |
9602 | PrUsage* prusage = sample->get_usage (); | |
9603 | Vector<long long> *mstateVals = prusage->getMstateValues (); | |
9604 | sampleVals->store (eventIdx, mstateVals); | |
9605 | } | |
9606 | } | |
9607 | } | |
9608 | // caller responsible for: delete representativeEvents; | |
9609 | Vector<void*> *results = new Vector<void*> (8); | |
9610 | results->store (0, startBins); | |
9611 | results->store (1, numBins); | |
9612 | results->store (2, eventIdxs); | |
9613 | results->store (3, stackIds); | |
9614 | results->store (4, mstates); | |
9615 | results->store (5, sampleVals); | |
9616 | results->store (6, timeStart); | |
9617 | results->store (7, timeEnd); | |
9618 | return results; | |
9619 | } | |
9620 | ||
9621 | // starting from <event_id> packet idx, step <move_count> visible events | |
9622 | // return the resulting idx and that packet's center time, or null if no event. | |
9623 | Vector<long long> * | |
9624 | dbeGetTLEventCenterTime (int dbevindex, int exp_id, int data_id, | |
9625 | int entity_prop_id, int entity_prop_val, int aux, | |
9626 | long long event_id, long long move_count) | |
9627 | { | |
9628 | DataView *packets = getTimelinePackets (dbevindex, exp_id, data_id, | |
9629 | entity_prop_id); | |
9630 | if (packets == NULL) | |
9631 | return NULL; | |
9632 | long idx = (long) event_id; | |
9633 | ||
9634 | DbeView *dbev = dbeSession->getView (dbevindex); | |
9635 | VMode view_mode = dbev->get_view_mode (); | |
9636 | Experiment *exp = dbeSession->get_exp (exp_id); | |
9637 | int direction; | |
9638 | if (move_count == 0) | |
9639 | direction = 0; | |
9640 | else if (move_count < 0) | |
9641 | { | |
9642 | move_count = -move_count; | |
9643 | direction = -1; | |
9644 | } | |
9645 | else | |
9646 | direction = 1; | |
9647 | idx = getTLVisibleIdxByStepping (exp, view_mode, entity_prop_id, packets, aux, | |
9648 | entity_prop_val, idx, move_count, direction); | |
9649 | if (idx >= 0) | |
9650 | { | |
9651 | long long ts = packets->getLongValue (PROP_TSTAMP, idx); | |
9652 | long long dur = packets->getLongValue (PROP_EVT_TIME, idx); | |
9653 | long long center = ts - dur / 2; | |
9654 | Vector<long long> *results = new Vector<long long> (2); | |
9655 | results->store (0, idx); // result idx | |
9656 | results->store (1, center); // result timestamp | |
9657 | return results; | |
9658 | } | |
9659 | return NULL; | |
9660 | } | |
9661 | ||
9662 | long long | |
9663 | dbeGetTLEventIdxNearTime (int dbevindex, int exp_id, int data_id, | |
9664 | int entity_prop_id, int entity_prop_val, int aux, | |
9665 | int searchDirection, long long tstamp) | |
9666 | { | |
9667 | DataView *packets = getTimelinePackets (dbevindex, exp_id, data_id, | |
9668 | entity_prop_id); | |
9669 | if (packets == NULL) | |
9670 | return -1; | |
9671 | DbeView *dbev = dbeSession->getView (dbevindex); | |
9672 | VMode view_mode = dbev->get_view_mode (); | |
9673 | Experiment *exp = dbeSession->get_exp (exp_id); | |
9674 | if (searchDirection < 0) | |
9675 | { | |
9676 | int idx = getTLVisibleIdxByVals (exp, view_mode, entity_prop_id, | |
9677 | packets, aux, entity_prop_val, tstamp, | |
9678 | DataView::REL_LTEQ); | |
9679 | if (idx != -1) | |
9680 | return idx; | |
9681 | searchDirection = 1; // couldn't find to left, try to right | |
9682 | } | |
9683 | if (searchDirection > 0) | |
9684 | { | |
9685 | int idx = getTLVisibleIdxByVals (exp, view_mode, entity_prop_id, | |
9686 | packets, aux, entity_prop_val, tstamp, | |
9687 | DataView::REL_GTEQ); | |
9688 | if (idx != -1) | |
9689 | return idx; | |
9690 | // couldn't find to right, fall through to generic | |
9691 | } | |
9692 | // search left and right of timestamp | |
9693 | long idx1, idx2; | |
9694 | idx1 = getTLVisibleIdxByVals (exp, view_mode, entity_prop_id, | |
9695 | packets, aux, entity_prop_val, tstamp, | |
9696 | DataView::REL_LT); | |
9697 | idx2 = getTLVisibleIdxByVals (exp, view_mode, entity_prop_id, | |
9698 | packets, aux, entity_prop_val, tstamp, | |
9699 | DataView::REL_GTEQ); | |
9700 | if (idx1 == -1) | |
9701 | return idx2; | |
9702 | else if (idx2 == -1) | |
9703 | return idx1; | |
9704 | ||
9705 | // both valid, so need to compare to see which is closer | |
9706 | long long t1 = packets->getLongValue (PROP_TSTAMP, idx1); | |
9707 | long long t2 = packets->getLongValue (PROP_TSTAMP, idx2); | |
9708 | long long t2dur = packets->getLongValue (PROP_EVT_TIME, idx2); | |
9709 | long long delta1 = tstamp - t1; // should always be positive | |
9710 | long long delta2 = (t2 - t2dur) - tstamp; // if negative, overlaps idx1 | |
9711 | if (delta1 > delta2) | |
9712 | return idx2; | |
9713 | else | |
9714 | return idx1; | |
9715 | } | |
9716 | ||
9717 | enum Aggr_type | |
9718 | { | |
9719 | AGGR_NONE, | |
9720 | AGGR_FAIR, | |
9721 | AGGR_MAX, | |
9722 | AGGR_MIN, | |
9723 | AGGR_CNT, | |
9724 | AGGR_SUM, | |
9725 | AGGR_AVG | |
9726 | }; | |
9727 | ||
9728 | static Aggr_type | |
9729 | getAggrFunc (char *aname) | |
9730 | { | |
9731 | Aggr_type agrfn = AGGR_NONE; | |
9732 | if (aname == NULL) | |
9733 | return agrfn; | |
9734 | if (strcmp (aname, NTXT ("FAIR")) == 0) | |
9735 | agrfn = AGGR_FAIR; | |
9736 | else if (strcmp (aname, NTXT ("MAX")) == 0) | |
9737 | agrfn = AGGR_MAX; | |
9738 | else if (strcmp (aname, NTXT ("MIN")) == 0) | |
9739 | agrfn = AGGR_MIN; | |
9740 | else if (strcmp (aname, NTXT ("CNT")) == 0) | |
9741 | agrfn = AGGR_CNT; | |
9742 | else if (strcmp (aname, NTXT ("SUM")) == 0) | |
9743 | agrfn = AGGR_SUM; | |
9744 | else if (strcmp (aname, NTXT ("AVG")) == 0) | |
9745 | agrfn = AGGR_AVG; | |
9746 | return agrfn; | |
9747 | } | |
9748 | ||
9749 | static long long | |
9750 | computeAggrVal (DefaultMap<long long, long long> *fval_map, Aggr_type agrfn) | |
9751 | { | |
9752 | long long aval = 0; | |
9753 | long cnt = 0; | |
9754 | Vector<long long> *fvals = fval_map->values (); | |
9755 | long nvals = fvals->size (); | |
9756 | for (int i = 0; i < nvals; ++i) | |
9757 | { | |
9758 | long long val = fvals->fetch (i); | |
9759 | switch (agrfn) | |
9760 | { | |
9761 | case AGGR_FAIR: | |
9762 | aval = val; | |
9763 | break; | |
9764 | case AGGR_MAX: | |
9765 | if (aval < val || cnt == 0) | |
9766 | aval = val; | |
9767 | break; | |
9768 | case AGGR_MIN: | |
9769 | if (aval > val || cnt == 0) | |
9770 | aval = val; | |
9771 | break; | |
9772 | case AGGR_CNT: | |
9773 | aval = cnt + 1; | |
9774 | break; | |
9775 | case AGGR_SUM: | |
9776 | case AGGR_AVG: | |
9777 | aval += val; | |
9778 | break; | |
9779 | case AGGR_NONE: | |
9780 | break; | |
9781 | } | |
9782 | if (agrfn == AGGR_FAIR) | |
9783 | break; | |
9784 | cnt += 1; | |
9785 | } | |
9786 | ||
9787 | // Finalize aggregation | |
9788 | if (agrfn == AGGR_AVG) | |
9789 | if (cnt > 0) | |
9790 | aval = (aval + cnt / 2) / cnt; | |
9791 | delete fvals; | |
9792 | return aval; | |
9793 | } | |
9794 | ||
9795 | Vector<long long> * | |
9796 | dbeGetAggregatedValue (int data_id, // data table id | |
9797 | char *lfilter, // local filter | |
9798 | char *fexpr, // function expression | |
9799 | char *pname_ts, // property name for timestamp | |
9800 | hrtime_t start_ts, // start of the first time interval | |
9801 | hrtime_t delta, // time interval length | |
9802 | int num, // number of time intervals | |
9803 | char *pname_key, // property name for aggregation key | |
9804 | char *aggr_func) // aggregation function | |
9805 | { | |
9806 | Vector<long long> *res = new Vector<long long>; | |
9807 | Experiment *exp = dbeSession->get_exp (0); | |
9808 | if (exp == NULL) | |
9809 | return res; | |
9810 | hrtime_t end_ts = start_ts + delta * num; | |
9811 | if (end_ts < start_ts) // check overflow | |
9812 | end_ts = MAX_TIME; | |
9813 | ||
9814 | if (exp->get_status () == Experiment::INCOMPLETE | |
9815 | && exp->getLastEvent () < end_ts) | |
9816 | exp->update (); | |
9817 | ||
9818 | DataDescriptor *dataDscr = exp->get_raw_events (data_id); | |
9819 | if (dataDscr == NULL) | |
9820 | return res; | |
9821 | ||
9822 | // Process timestamp argument | |
9823 | int prop_ts = dbeSession->getPropIdByName (pname_ts); | |
9824 | if (prop_ts == PROP_NONE) | |
9825 | return res; | |
9826 | assert (prop_ts == -1); | |
9827 | ||
9828 | // Parse all expressions | |
9829 | Expression *flt_expr = NULL; | |
9830 | if (lfilter != NULL) | |
9831 | flt_expr = dbeSession->ql_parse (lfilter); | |
9832 | Expression *func_expr = NULL; | |
9833 | if (fexpr != NULL) | |
9834 | func_expr = dbeSession->ql_parse (fexpr); | |
9835 | if (func_expr == NULL) // Not specified or malformed | |
9836 | return res; | |
9837 | ||
9838 | // Process aggregation key argument | |
9839 | int prop_key = PROP_NONE; | |
9840 | Data *data_key = NULL; | |
9841 | if (pname_key != NULL) | |
9842 | { | |
9843 | prop_key = dbeSession->getPropIdByName (pname_key); | |
9844 | data_key = dataDscr->getData (prop_key); | |
9845 | if (data_key == NULL) // Specified but not found | |
9846 | return res; | |
9847 | } | |
9848 | ||
9849 | // Process aggregation function argument | |
9850 | Aggr_type agrfn = AGGR_FAIR; | |
9851 | if (aggr_func != NULL) | |
9852 | { | |
9853 | agrfn = getAggrFunc (aggr_func); | |
9854 | if (agrfn == AGGR_NONE) // Specified but not recognized | |
9855 | return res; | |
9856 | } | |
9857 | DefaultMap<long long, long long> * | |
9858 | fval_map = new DefaultMap<long long, long long>; // key_val -> func_val | |
9859 | Vector<long long> *key_set = NULL; | |
9860 | assert (key_set != NULL); | |
9861 | if (key_set == NULL) | |
9862 | { | |
9863 | key_set = new Vector<long long>; | |
9864 | key_set->append (0L); | |
9865 | } | |
9866 | DefaultMap<long long, int> *key_seen = new DefaultMap<long long, int>; | |
9867 | long idx_prev = -1; | |
9868 | for (int tidx = 0; tidx < num; ++tidx) | |
9869 | { | |
9870 | long idx_cur = -1; | |
9871 | assert (idx_cur != -1); | |
9872 | int left = key_set->size (); | |
9873 | key_seen->clear (); | |
9874 | for (long idx = idx_cur; idx > idx_prev; --idx) | |
9875 | { | |
9876 | long id = 0; | |
9877 | assert (id != 0); | |
9878 | ||
9879 | // Pre-create expression context | |
9880 | Expression::Context ctx (dbeSession->getView (0), exp, NULL, id); | |
9881 | // First use the filter | |
9882 | if (flt_expr != NULL) | |
9883 | if (flt_expr->eval (&ctx) == 0) | |
9884 | continue; | |
9885 | ||
9886 | // Calculate the key | |
9887 | // keys are limited to integral values | |
9888 | long long key = 0; | |
9889 | if (data_key != NULL) | |
9890 | key = data_key->fetchLong (id); | |
9891 | ||
9892 | // Check if already seen | |
9893 | if (key_seen->get (key) == 1) | |
9894 | continue; | |
9895 | key_seen->put (key, 1); | |
9896 | left -= 1; | |
9897 | ||
9898 | // Calculate function value | |
9899 | // function values are limited to integral values | |
9900 | long long fval = func_expr->eval (&ctx); | |
9901 | fval_map->put (key, fval); | |
9902 | if (left == 0) | |
9903 | break; | |
9904 | } | |
9905 | idx_prev = idx_cur; | |
9906 | long long aval = computeAggrVal (fval_map, agrfn); | |
9907 | res->store (tidx, aval); | |
9908 | } | |
9909 | delete key_seen; | |
9910 | delete fval_map; | |
9911 | delete flt_expr; | |
9912 | delete func_expr; | |
9913 | return res; | |
9914 | } | |
9915 | ||
9916 | Vector<char*> * | |
9917 | dbeGetLineInfo (Obj pc) | |
9918 | { | |
9919 | DbeInstr *instr = (DbeInstr*) pc; | |
9920 | if (instr == NULL || instr->get_type () != Histable::INSTR) | |
9921 | return NULL; | |
9922 | DbeLine *dbeline = (DbeLine*) instr->convertto (Histable::LINE); | |
9923 | const char *fname = dbeline ? dbeline->sourceFile->get_name () : NTXT (""); | |
9924 | char lineno[16]; | |
9925 | *lineno = '\0'; | |
9926 | if (dbeline != NULL) | |
9927 | snprintf (lineno, sizeof (lineno), NTXT ("%d"), dbeline->lineno); | |
9928 | Vector<char*> *res = new Vector<char*>(2); | |
9929 | res->store (0, strdup (fname)); | |
9930 | res->store (1, strdup (lineno)); | |
9931 | return res; | |
9932 | } | |
9933 | ||
9934 | int | |
9935 | dbeSetAlias (char *name, char *uname, char *expr) | |
9936 | { | |
9937 | char *res = dbeSession->indxobj_define (name, uname, expr, NULL, NULL); | |
9938 | return res == NULL ? 0 : 1; | |
9939 | } | |
9940 | ||
9941 | Vector<char*> * | |
9942 | dbeGetAlias (char *name) | |
9943 | { | |
9944 | Vector<char*> *res = new Vector<char*>; | |
9945 | int idx = dbeSession->findIndexSpaceByName (name); | |
9946 | if (idx >= 0) | |
9947 | { | |
9948 | char *str = dbeSession->getIndexSpaceDescr (idx); | |
9949 | res->append (dbe_strdup (str)); | |
9950 | str = dbeSession->getIndexSpaceExprStr (idx); | |
9951 | res->append (dbe_strdup (str)); | |
9952 | } | |
9953 | return res; | |
9954 | } | |
9955 | ||
9956 | static int | |
9957 | key_cmp (const void *p1, const void *p2) | |
9958 | { | |
9959 | long long ll1 = *(long long*) p1; | |
9960 | long long ll2 = *(long long*) p2; | |
9961 | return ll1 < ll2 ? -1 : ll1 > ll2 ? 1 : 0; | |
9962 | } | |
9963 | ||
9964 | Vector<Vector<long long>*> * | |
9965 | dbeGetXYPlotData ( | |
9966 | int data_id, // data table id | |
9967 | char *lfilter, // local filter expression | |
9968 | char *arg, // name for the argument | |
9969 | char *func1, // expression for the first axis (x) | |
9970 | char *aggr1, // aggregation function for func1: "SUM","CNT",... | |
9971 | char *func2, // expression for the second axis (y) | |
9972 | char *aggr2, // aggregation function for func2 | |
9973 | char *func3, // expression for the third axis (color) | |
9974 | char *aggr3) // aggregation function for func3 | |
9975 | { | |
9976 | Vector<Vector<long long>*> *res = new Vector<Vector<long long>*>; | |
9977 | Experiment *exp = dbeSession->get_exp (0); | |
9978 | if (exp == NULL) | |
9979 | return res; | |
9980 | if (exp->get_status () == Experiment::INCOMPLETE) | |
9981 | exp->update (); | |
9982 | ||
9983 | DataDescriptor *dataDscr = exp->get_raw_events (data_id); | |
9984 | if (dataDscr == NULL) | |
9985 | return res; | |
9986 | ||
9987 | // Parse all expressions | |
9988 | Vector<Expression*> *funcs = new Vector<Expression*>; | |
9989 | Vector<Aggr_type> *aggrs = new Vector<Aggr_type>; | |
9990 | Vector<DefaultMap<long long, long long>*> *fval_maps = | |
9991 | new Vector<DefaultMap<long long, long long>*>; | |
9992 | Vector<DefaultMap<long long, long>*> *cnt_maps = | |
9993 | new Vector<DefaultMap<long long, long>*>; | |
9994 | if (func1 != NULL) | |
9995 | { | |
9996 | Expression *expr = dbeSession->ql_parse (func1); | |
9997 | funcs->append (expr); | |
9998 | aggrs->append (getAggrFunc (aggr1)); | |
9999 | fval_maps->append (new DefaultMap<long long, long long>); | |
10000 | cnt_maps->append (new DefaultMap<long long, long>); | |
10001 | res->append (new Vector<long long>); | |
10002 | if (func2 != NULL) | |
10003 | { | |
10004 | expr = dbeSession->ql_parse (func2); | |
10005 | funcs->append (expr); | |
10006 | aggrs->append (getAggrFunc (aggr2)); | |
10007 | fval_maps->append (new DefaultMap<long long, long long>); | |
10008 | cnt_maps->append (new DefaultMap<long long, long>); | |
10009 | res->append (new Vector<long long>); | |
10010 | if (func3 != NULL) | |
10011 | { | |
10012 | expr = dbeSession->ql_parse (func3); | |
10013 | funcs->append (expr); | |
10014 | aggrs->append (getAggrFunc (aggr3)); | |
10015 | fval_maps->append (new DefaultMap<long long, long long>); | |
10016 | cnt_maps->append (new DefaultMap<long long, long>); | |
10017 | res->append (new Vector<long long>); | |
10018 | } | |
10019 | } | |
10020 | } | |
10021 | if (funcs->size () == 0) | |
10022 | { | |
10023 | funcs->destroy (); | |
10024 | delete funcs; | |
10025 | fval_maps->destroy (); | |
10026 | delete fval_maps; | |
10027 | cnt_maps->destroy (); | |
10028 | delete cnt_maps; | |
10029 | delete aggrs; | |
10030 | return res; | |
10031 | } | |
10032 | Expression *arg_expr = NULL; | |
10033 | if (arg != NULL) | |
10034 | arg_expr = dbeSession->ql_parse (arg); | |
10035 | if (arg_expr == NULL) | |
10036 | { | |
10037 | funcs->destroy (); | |
10038 | delete funcs; | |
10039 | fval_maps->destroy (); | |
10040 | delete fval_maps; | |
10041 | cnt_maps->destroy (); | |
10042 | delete cnt_maps; | |
10043 | delete aggrs; | |
10044 | return res; | |
10045 | } | |
10046 | Expression *flt_expr = NULL; | |
10047 | if (lfilter != NULL) | |
10048 | flt_expr = dbeSession->ql_parse (lfilter); | |
10049 | Vector<long long> *kidx_map = new Vector<long long>(); // key_idx -> key_val | |
10050 | for (long i = 0; i < dataDscr->getSize (); i++) | |
10051 | { | |
10052 | Expression::Context ctx (dbeSession->getView (0), exp, NULL, i); | |
10053 | // First use the filter | |
10054 | if (flt_expr != NULL) | |
10055 | if (flt_expr->eval (&ctx) == 0) | |
10056 | continue; | |
10057 | ||
10058 | // Compute the argument | |
10059 | long long key = arg_expr->eval (&ctx); | |
10060 | if (kidx_map->find (key) == -1) | |
10061 | kidx_map->append (key); | |
10062 | for (long j = 0; j < funcs->size (); ++j) | |
10063 | { | |
10064 | Expression *func = funcs->fetch (j); | |
10065 | Aggr_type aggr = aggrs->fetch (j); | |
10066 | DefaultMap<long long, long long> *fval_map = fval_maps->fetch (j); | |
10067 | DefaultMap<long long, long> *cnt_map = cnt_maps->fetch (j); | |
10068 | long long fval = func->eval (&ctx); | |
10069 | long long aval = fval_map->get (key); | |
10070 | long cnt = cnt_map->get (key); | |
10071 | switch (aggr) | |
10072 | { | |
10073 | case AGGR_NONE: | |
10074 | case AGGR_FAIR: | |
10075 | if (cnt == 0) | |
10076 | aval = fval; | |
10077 | break; | |
10078 | case AGGR_MAX: | |
10079 | if (aval < fval || cnt == 0) | |
10080 | aval = fval; | |
10081 | break; | |
10082 | case AGGR_MIN: | |
10083 | if (aval > fval || cnt == 0) | |
10084 | aval = fval; | |
10085 | break; | |
10086 | case AGGR_CNT: | |
10087 | aval = cnt + 1; | |
10088 | break; | |
10089 | case AGGR_SUM: | |
10090 | case AGGR_AVG: | |
10091 | aval += fval; | |
10092 | break; | |
10093 | } | |
10094 | cnt_map->put (key, cnt + 1); | |
10095 | fval_map->put (key, aval); | |
10096 | } | |
10097 | } | |
10098 | kidx_map->sort (key_cmp); | |
10099 | ||
10100 | // Finalize aggregation, prepare result | |
10101 | for (long j = 0; j < funcs->size (); ++j) | |
10102 | { | |
10103 | Aggr_type aggr = aggrs->fetch (j); | |
10104 | Vector<long long> *resj = res->fetch (j); | |
10105 | DefaultMap<long long, long long> * | |
10106 | fval_map = fval_maps->fetch (j); | |
10107 | DefaultMap<long long, long> * | |
10108 | cnt_map = cnt_maps->fetch (j); | |
10109 | for (int kidx = 0; kidx < kidx_map->size (); ++kidx) | |
10110 | { | |
10111 | long long key = kidx_map->fetch (kidx); | |
10112 | long long aval = fval_map->get (key); | |
10113 | if (aggr == AGGR_AVG) | |
10114 | { | |
10115 | long cnt = cnt_map->get (key); | |
10116 | if (cnt > 0) | |
10117 | aval = (aval + cnt / 2) / cnt; | |
10118 | } | |
10119 | resj->append (aval); | |
10120 | } | |
10121 | } | |
10122 | delete flt_expr; | |
10123 | funcs->destroy (); | |
10124 | delete funcs; | |
10125 | delete aggrs; | |
10126 | delete arg_expr; | |
10127 | delete kidx_map; | |
10128 | fval_maps->destroy (); | |
10129 | delete fval_maps; | |
10130 | cnt_maps->destroy (); | |
10131 | delete cnt_maps; | |
10132 | return res; | |
10133 | } | |
10134 | ||
10135 | /* ********************************************************************* */ | |
10136 | /* Routines for use by Collector GUI */ | |
10137 | /** | |
10138 | * Returns signal value for provided name. Example of name: "SIGUSR1" | |
10139 | * @param signal | |
10140 | * @return value | |
10141 | */ | |
10142 | int | |
10143 | dbeGetSignalValue (char *signal) | |
10144 | { | |
10145 | int ret = -1; | |
10146 | if (signal == NULL) | |
10147 | return ret; | |
10148 | if (strcmp (signal, "SIGUSR1") == 0) | |
10149 | return (SIGUSR1); | |
10150 | if (strcmp (signal, "SIGUSR2") == 0) | |
10151 | return (SIGUSR2); | |
10152 | if (strcmp (signal, "SIGPROF") == 0) | |
10153 | return (SIGPROF); | |
10154 | return ret; | |
10155 | } | |
10156 | ||
10157 | char * | |
10158 | dbeSendSignal (pid_t p, int signum) | |
10159 | { | |
10160 | int ret = kill (p, signum); | |
10161 | if (p == 0 || p == -1) | |
10162 | return (dbe_sprintf (GTXT ("kill of process %d not supported\n"), p)); | |
10163 | if (ret == 0) | |
10164 | return NULL; | |
10165 | char *msg = dbe_sprintf (GTXT ("kill(%d, %d) failed: %s\n"), p, signum, | |
10166 | strerror (errno)); | |
10167 | return msg; | |
10168 | } | |
10169 | ||
10170 | char * | |
10171 | dbeGetCollectorControlValue (char *control) | |
10172 | { | |
10173 | if (control == NULL) | |
10174 | return NULL; | |
10175 | if (col_ctr == NULL) | |
10176 | col_ctr = new Coll_Ctrl (1); | |
10177 | char *msg = col_ctr->get (control); | |
10178 | return msg; | |
10179 | } | |
10180 | ||
10181 | char * | |
10182 | dbeSetCollectorControlValue (char *control, char * value) | |
10183 | { | |
10184 | if (control == NULL) | |
10185 | return NULL; | |
10186 | if (col_ctr == NULL) | |
10187 | col_ctr = new Coll_Ctrl (1); | |
10188 | char *msg = col_ctr->set (control, value); | |
10189 | return msg; | |
10190 | } | |
10191 | ||
10192 | char * | |
10193 | dbeUnsetCollectorControlValue (char *control) | |
10194 | { | |
10195 | if (control == NULL) | |
10196 | return NULL; | |
10197 | if (col_ctr == NULL) | |
10198 | col_ctr = new Coll_Ctrl (1); | |
10199 | char *msg = col_ctr->unset (control); | |
10200 | return msg; | |
10201 | } | |
10202 | ||
10203 | void | |
10204 | dbeSetLocation (const char *fname, const char *location) | |
10205 | { | |
10206 | Vector<SourceFile*> *sources = dbeSession->get_sources (); | |
10207 | for (long i = 0, sz = sources ? sources->size () : 0; i < sz; i++) | |
10208 | { | |
10209 | SourceFile *src = sources->get (i); | |
10210 | DbeFile *df = src->dbeFile; | |
10211 | if (df && (strcmp (fname, df->get_name ()) == 0)) | |
10212 | { | |
10213 | df->find_file ((char *) location); | |
10214 | break; | |
10215 | } | |
10216 | } | |
10217 | } | |
10218 | ||
10219 | void | |
10220 | dbeSetLocations (Vector<const char *> *fnames, Vector<const char *> *locations) | |
10221 | { | |
10222 | if (fnames == NULL || locations == NULL | |
10223 | || fnames->size () != locations->size ()) | |
10224 | return; | |
10225 | for (long i = 0, sz = fnames->size (); i < sz; i++) | |
10226 | dbeSetLocation (fnames->get (i), locations->get (i)); | |
10227 | } | |
10228 | ||
10229 | Vector<void*> * | |
10230 | dbeResolvedWith_setpath (const char *path) | |
10231 | { | |
10232 | Vector<char*> *names = new Vector<char*>(); | |
10233 | Vector<char*> *pathes = new Vector<char*>(); | |
10234 | Vector<long long> *ids = new Vector<long long>(); | |
10235 | Vector<SourceFile*> *sources = dbeSession->get_sources (); | |
10236 | for (long i = 0, sz = sources ? sources->size () : 0; i < sz; i++) | |
10237 | { | |
10238 | SourceFile *src = sources->get (i); | |
10239 | DbeFile *df = src->dbeFile; | |
10240 | if (df == NULL || (df->filetype & DbeFile::F_FICTION) != 0) | |
10241 | continue; | |
10242 | char *fnm = df->get_name (); | |
10243 | if ((df->filetype & (DbeFile::F_JAVACLASS | DbeFile::F_JAVA_SOURCE)) != 0) | |
10244 | { | |
10245 | char *jnm = dbe_sprintf (NTXT ("%s/%s"), path, fnm); | |
10246 | if (df->check_access (jnm) == DbeFile::F_FILE) | |
10247 | { | |
10248 | names->append (dbe_strdup (fnm)); | |
10249 | pathes->append (jnm); | |
10250 | ids->append (src->id); | |
10251 | continue; | |
10252 | } | |
10253 | free (jnm); | |
10254 | } | |
10255 | char *nm = dbe_sprintf (NTXT ("%s/%s"), path, get_basename (fnm)); | |
10256 | if (df->check_access (nm) == DbeFile::F_FILE) | |
10257 | { | |
10258 | names->append (dbe_strdup (fnm)); | |
10259 | pathes->append (nm); | |
10260 | ids->append (src->id); | |
10261 | continue; | |
10262 | } | |
10263 | free (nm); | |
10264 | } | |
10265 | if (names->size () != 0) | |
10266 | { | |
10267 | Vector<void*> *data = new Vector<void*>(3); | |
10268 | data->append (names); | |
10269 | data->append (pathes); | |
10270 | data->append (ids); | |
10271 | return data; | |
10272 | } | |
10273 | return NULL; | |
10274 | } | |
10275 | ||
10276 | Vector<void*> * | |
10277 | dbeResolvedWith_pathmap (const char *old_prefix, const char *new_prefix) | |
10278 | { | |
10279 | size_t len = strlen (old_prefix); | |
10280 | Vector<char*> *names = new Vector<char*>(); | |
10281 | Vector<char*> *pathes = new Vector<char*>(); | |
10282 | Vector<long long> *ids = new Vector<long long>(); | |
10283 | Vector<SourceFile*> *sources = dbeSession->get_sources (); | |
10284 | for (long i = 0, sz = sources ? sources->size () : 0; i < sz; i++) | |
10285 | { | |
10286 | SourceFile *src = sources->get (i); | |
10287 | DbeFile *df = src->dbeFile; | |
10288 | if (df == NULL || (df->filetype & DbeFile::F_FICTION) != 0) | |
10289 | continue; | |
10290 | char *fnm = df->get_name (); | |
10291 | if (strncmp (old_prefix, fnm, len) == 0 | |
10292 | && (fnm[len] == '/' || fnm[len] == '\0')) | |
10293 | { | |
10294 | char *nm = dbe_sprintf (NTXT ("%s/%s"), new_prefix, fnm + len); | |
10295 | if (df->check_access (nm) == DbeFile::F_FILE) | |
10296 | { | |
10297 | names->append (dbe_strdup (fnm)); | |
10298 | pathes->append (nm); | |
10299 | ids->append (src->id); | |
10300 | continue; | |
10301 | } | |
10302 | if ((df->filetype & DbeFile::F_JAVA_SOURCE) != 0) | |
10303 | { | |
10304 | free (nm); | |
10305 | nm = dbe_sprintf (NTXT ("%s/%s"), new_prefix, fnm); | |
10306 | if (df->check_access (nm) == DbeFile::F_FILE) | |
10307 | { | |
10308 | names->append (dbe_strdup (fnm)); | |
10309 | pathes->append (nm); | |
10310 | ids->append (src->id); | |
10311 | continue; | |
10312 | } | |
10313 | } | |
10314 | free (nm); | |
10315 | } | |
10316 | } | |
10317 | if (names->size () != 0) | |
10318 | { | |
10319 | Vector<void*> *data = new Vector<void*>(3); | |
10320 | data->append (names); | |
10321 | data->append (pathes); | |
10322 | data->append (ids); | |
10323 | return data; | |
10324 | } | |
10325 | return NULL; | |
10326 | } | |
10327 | ||
10328 | void | |
10329 | dbe_archive (Vector<long long> *ids, Vector<const char *> *locations) | |
10330 | { | |
10331 | if (ids == NULL || locations == NULL || ids->size () != locations->size ()) | |
10332 | return; | |
10333 | Experiment *exp = dbeSession->get_exp (0); | |
10334 | if (exp == NULL) | |
10335 | return; | |
10336 | Vector<SourceFile*> *sources = dbeSession->get_sources (); | |
10337 | for (long i1 = 0, sz1 = ids->size (); i1 < sz1; i1++) | |
10338 | { | |
10339 | long long id = ids->get (i1); | |
10340 | for (long i = 0, sz = sources ? sources->size () : 0; i < sz; i++) | |
10341 | { | |
10342 | SourceFile *src = sources->get (i); | |
10343 | if (src->id == id) | |
10344 | { | |
10345 | DbeFile *df = src->dbeFile; | |
10346 | if (df) | |
10347 | { | |
10348 | char *fnm = df->find_file ((char *) locations->get (i1)); | |
10349 | if (fnm) | |
10350 | { | |
10351 | char *nm = df->get_name (); | |
10352 | char *anm = exp->getNameInArchive (nm, false); | |
10353 | exp->copy_file (fnm, anm, true); | |
10354 | free (anm); | |
10355 | } | |
10356 | } | |
10357 | } | |
10358 | } | |
10359 | } | |
10360 | } | |
10361 | ||
10362 | /* ************************************************************************ */ | |
10363 | ||
10364 | /* Routines to check connection between Remote Analyzer Client and er_print */ | |
10365 | char * | |
10366 | dbeCheckConnection (char *str) | |
10367 | { | |
10368 | return dbe_strdup (str); | |
10369 | } |