1 /* Copyright (C) 2021 Free Software Foundation, Inc.
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 
type()69 template<> VecType Vector<int>::type ()
70 {
71   return VEC_INTEGER;
72 }
73 
type()74 template<> VecType Vector<unsigned>::type ()
75 {
76   return VEC_INTEGER;
77 }
78 
type()79 template<> VecType Vector<char>::type ()
80 {
81   return VEC_CHAR;
82 }
83 
type()84 template<> VecType Vector<bool>::type ()
85 {
86   return VEC_BOOL;
87 }
88 
type()89 template<> VecType Vector<double>::type ()
90 {
91   return VEC_DOUBLE;
92 }
93 
type()94 template<> VecType Vector<long long>::type ()
95 {
96   return VEC_LLONG;
97 }
98 
type()99 template<> VecType Vector<uint64_t>::type ()
100 {
101   return VEC_LLONG;
102 }
103 
type()104 template<> VecType Vector<void*>::type ()
105 {
106   return VEC_VOIDARR;
107 }
108 
type()109 template<> VecType Vector<char*>::type ()
110 {
111   return VEC_STRING;
112 }
113 
type()114 template<> VecType Vector<Vector<int>*>::type ()
115 {
116   return VEC_INTARR;
117 }
118 
type()119 template<> VecType Vector<Vector<char*>*>::type ()
120 {
121   return VEC_STRINGARR;
122 }
123 
type()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 *
dsp_type_to_string(int t)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 *
getDbeView(int dbevindex)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*> *
dbeGetInitMessages()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*> *
dbeGetExpPreview(int,char * exp_name)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 *
dbeGetExpParams(int,char * exp_name)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 *
dbeGetFileAttributes(const char * filename,const char * format)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 *
dbeGetFiles(const char * dirname,const char * format)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 *
dbeCreateDirectories(const char * dirname)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 *
dbeDeleteFile(const char * pathname)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*> *
dbeReadFile(const char * pathname)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
dbeWriteFile(const char * pathname,const char * contents)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 *
dbeGetRunningProcesses(const char * format)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 *
dbeOpenExperimentList(int,Vector<Vector<char * > * > * groups,bool sessionRestart)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 *
dbeDropExperiment(int,Vector<int> * drop_index)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 *
dbeReadRCFile(int dbevindex,char * path)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 *
dbeSetExperimentsGroups(Vector<Vector<char * > * > * groups)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*>*> *
dbeGetExperimensGroups()512 dbeGetExperimensGroups ()
513 {
514   Vector<Vector<char*>*> *grops = dbeSession->getExperimensGroups ();
515   return grops;
516 }
517 
518 Vector<int> *
dbeGetFounderExpId(Vector<int> * expIds)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> *
dbeGetUserExpId(Vector<int> * expIds)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> *
dbeGetExpGroupId(Vector<int> * expIds)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*> *
dbeGetExpsProperty(const char * prop_name)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*> *
dbeGetExpName(int)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> *
dbeGetExpState(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> *
dbeGetExpEnable(int dbevindex)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
dbeSetExpEnable(int dbevindex,Vector<bool> * enable)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*> *
dbeGetExpInfo(int dbevindex)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
dbeGetViewModeEnable()759 dbeGetViewModeEnable ()
760 {
761   return dbeSession->has_ompavail () || dbeSession->has_java ();
762 }
763 
764 bool
dbeGetJavaEnable()765 dbeGetJavaEnable ()
766 {
767   return dbeSession->has_java ();
768 }
769 
770 int
dbeUpdateNotes(int dbevindex,int exp_id,int type,char * text,bool handle_file)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*> *
dbeGetLoadObjectName(int)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*> *
dbeGetTabList(int)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*> *
dbeGetTabListInfo(int dbevindex)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> *
dbeGetTabSelectionState(int dbevindex)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
dbeSetTabSelectionState(int dbevindex,Vector<bool> * selected)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> *
dbeGetMemTabSelectionState(int dbevindex)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
dbeSetMemTabSelectionState(int dbevindex,Vector<bool> * selected)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> *
dbeGetIndxTabSelectionState(int dbevindex)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
dbeSetIndxTabSelectionState(int dbevindex,Vector<bool> * selected)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*> *
dbeGetSearchPath(int)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
dbeSetSearchPath(int,Vector<char * > * path)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*> *
dbeGetPathmaps(int)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 *
dbeSetPathmaps(Vector<char * > * from,Vector<char * > * to)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 *
dbeAddPathmap(int,char * from,char * to)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 *
dbeGetMsg(int dbevindex,int type)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
dbeInitView(int id,int cloneid)1084 dbeInitView (int id, int cloneid)
1085 {
1086   return dbeSession->createView (id, cloneid);
1087 }
1088 
1089 
1090 // Delete a DbeView
1091 void
dbeDeleteView(int dbevindex)1092 dbeDeleteView (int dbevindex)
1093 {
1094   dbeSession->dropView (dbevindex);
1095   return;
1096 } // dbeDeleteView
1097 
1098 MetricList *
dbeGetMetricListV2(int dbevindex,MetricType mtype,Vector<int> * type,Vector<int> * subtype,Vector<bool> * sort,Vector<int> * vis,Vector<char * > * cmd,Vector<char * > * expr_spec,Vector<char * > * legends)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*> *
dbeGetMetricList(MetricList * mlist)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*> *
dbeGetRefMetricsV2()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*> *
dbeGetCurMetricsV2(int dbevindex,MetricType mtype)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
convert_visbits_to_gui_checkbox_bits(BaseMetric * bm,const int visbits)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*> *
dbeGetMetricTreeNode(BaseMetricTreeNode * curr,MetricList * mlist,bool include_unregistered,bool has_clock_profiling_data)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*> *
dbeGetRefMetricTree(int dbevindex,bool include_unregistered)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
dbeCalcGroupDuration(int grInd)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
dbeCalcGroupGCDuration(int grInd)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*> *
dbeGetRefMetricTreeValues(int dbevindex,Vector<char * > * metric_cmds,Vector<char * > * non_metric_cmds)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*> *
dbeGetOverviewText(int dbevindex)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])
1947 	info->append (dbe_sprintf (GTXT ("  Host          : %s (%s, %s)"),
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>")));
1953       time_t start_sec = (time_t) exp->start_sec;
1954       char *p = ctime (&start_sec);
1955       hrtime_t tot_time = dbeCalcGroupDuration (grInd);
1956       double seconds = tot_time * 1.e-9;
1957       info->append (dbe_sprintf (
1958 		GTXT ("  Start Time    : %s  Duration      : %0.3f Seconds"),
1959 		p, seconds));
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
dbeSetSort(int dbevindex,int sort_index,MetricType mtype,bool reverse)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> *
dbeGetAnoValue(int dbevindex)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
dbeSetAnoValue(int dbevindex,Vector<int> * set)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
dbeGetNameFormat(int dbevindex)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
dbeGetSoName(int dbevindex)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
dbeSetNameFormat(int dbevindex,int nformat,bool soname)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
dbeGetViewMode(int dbevindex)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
dbeSetViewMode(int dbevindex,int nmode)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*> *
dbeGetTLValue(int dbevindex)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
dbeSetTLValue(int dbevindex,const char * tldata_cmd,int entitiy_prop_id,int stackalign,int stackdepth)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*> *
dbeGetExpFounderDescendants()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*> *
dbeGetExpSelection(int dbevindex)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
dbeValidateFilterExpression(char * str_expr)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*> *
dbeGetFilterKeywords(int)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*> *
dbeGetFilters(int dbevindex,int nexp)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 *
dbeSetFilterStr(int dbevindex,char * filter_str)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 *
dbeGetFilterStr(int dbevindex)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
dbeUpdateFilters(int dbevindex,Vector<bool> * selected,Vector<char * > * pattern_str)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 *
dbeComposeFilterClause(int dbevindex,int type,int subtype,Vector<int> * selections)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 *> *
dbeGetLoadObjectList(int dbevindex)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> *
dbeGetLoadObjectState(int dbevindex)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
dbeSetLoadObjectState(int dbevindex,Vector<int> * selected)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
dbeSetLoadObjectDefaults(int dbevindex)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*>*
dbeGetCPUVerMachineModel(int dbevindex)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
dbeDetectLoadMachineModel(int dbevindex)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 *
dbeDefineMemObj(char * name,char * index_expr,char * machinemodel,char * sdesc,char * ldesc)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 *
dbeDeleteMemObj(char * name)2835 dbeDeleteMemObj (char *name)
2836 {
2837   return MemorySpace::mobj_delete (name);
2838 }
2839 
2840 Vector<void*> *
dbeGetMemObjects(int)2841 dbeGetMemObjects (int /*dbevindex*/)
2842 {
2843   Vector<void*> *res = MemorySpace::getMemObjects ();
2844   return res;
2845 }
2846 
2847 // Managing machine model
2848 char *
dbeLoadMachineModel(char * name)2849 dbeLoadMachineModel (char *name)
2850 {
2851   return dbeSession->load_mach_model (name);
2852 }
2853 
2854 char *
dbeGetMachineModel()2855 dbeGetMachineModel ()
2856 {
2857   return dbeSession->get_mach_model ();
2858 }
2859 
2860 Vector <char *> *
dbeListMachineModels()2861 dbeListMachineModels ()
2862 {
2863   return dbeSession->list_mach_models ();
2864 }
2865 
2866 // Managing Index Objects
2867 char *
dbeDefineIndxObj(char * name,char * index_expr,char * sdesc,char * ldesc)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*> *
dbeGetIndxObjDescriptions(int)2874 dbeGetIndxObjDescriptions (int /*dbevindex*/)
2875 {
2876   Vector<void*> *res = dbeSession->getIndxObjDescriptions ();
2877   return res;
2878 }
2879 
2880 Vector<void*> *
dbeGetCustomIndxObjects(int)2881 dbeGetCustomIndxObjects (int /*dbevindex*/)
2882 {
2883   Vector<void*> *res = dbeSession->getCustomIndxObjects ();
2884   return res;
2885 }
2886 
2887 void
dbeSetSelObj(int dbevindex,Obj sel_obj_or_ind,int type,int subtype)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
dbeSetSelObjV2(int dbevindex,uint64_t id)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
dbeGetSelObj(int dbevindex,int type,int subtype)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
dbeConvertSelObj(Obj obj,int type)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
dbeGetSelObjV2(int dbevindex,char * typeStr)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> *
dbeGetSelObjsIO(int dbevindex,Vector<uint64_t> * ids,int type)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> *
dbeGetSelObjIO(int dbevindex,uint64_t id,int type)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
dbeGetSelObjHeapTimestamp(int dbevindex,uint64_t id)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
dbeGetSelObjHeapUserExpId(int dbevindex,uint64_t id)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
dbeGetSelIndex(int dbevindex,Obj sel_obj,int type,int subtype)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 *
dbePrintData(int dbevindex,int type,int subtype,char * printer,char * fname,FILE * outfile)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 (&params) == 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 *
dbeSetPrintLimit(int dbevindex,int limit)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
dbeGetPrintLimit(int dbevindex)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 *
dbeSetPrintMode(int dbevindex,char * pmode)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
dbeGetPrintMode(int dbevindex)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 *
dbeGetPrintModeString(int dbevindex)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
dbeGetPrintDelim(int dbevindex)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
set_file_names(Function * func,char * names[3])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
dbeSetFuncData(int dbevindex,Obj sel_obj,int type,int subtype)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*>*
dbeGetTotals(int dbevindex,int dsptype,int subtype)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*>*
dbeGetHotMarks(int dbevindex,int type)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*>*
dbeGetHotMarksInc(int dbevindex,int type)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*>*
dbeGetSummaryHotMarks(int dbevindex,Vector<Obj> * sel_objs,int type)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>*
dbeGetFuncId(int dbevindex,int type,int begin,int length)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*>*
dbeGetFuncCallerInfo(int dbevindex,int type,Vector<int> * idxs,int groupId)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*>*
dbeGetFuncCallerInfoById(int dbevindex,int type,int idx)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*>*
dbeGetFuncCalleeInfo(int dbevindex,int type,Vector<int> * idxs,int groupId)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*>*
dbeGetFuncCalleeInfoById(int dbevindex,int type,int idx)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*> *
dbeGetFuncListMini(int dbevindex,int type,int)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*> *
dbeGetFuncList(int dbevindex,int type,int subtype)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> *
dbeGetComparableObjsV2(int,Obj sel_obj,int type)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 *> *
dbeGetFuncListV2(int dbevindex,int mtype,Obj sel_obj,int type,int subtype)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*> *
dbeGetTableDataV2(int dbevindex,char * mlistStr,char * modeStr,char * typeStr,char * subtypeStr,Vector<uint64_t> * ids)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*> *
dbeGetTableDataV2Data(DbeView *,Hist_data * data)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*> *
dbeGetTableDataOneColumn(Hist_data * data,int met_ind)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*> *
dbeGetTableDataOneColumn(DbeView * dbev,Vector<Hist_data::HistItem * > * data,ValueTag vtype,int metricColumnNumber)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
dbeGetCallTreeNumLevels(int dbevindex)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*>*
dbeGetCallTreeLevel(int dbevindex,char * mcmd,int level)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*>*
dbeGetCallTreeLevels(int dbevindex,char * mcmd)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*>*
dbeGetCallTreeLevelFuncs(int dbevindex,int start_level,int end_level)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*> *
dbeGetCallTreeFuncs(int dbevindex)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*>*
dbeGetCallTreeChildren(int dbevindex,char * mcmd,Vector<int> * node_idxs)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> *
dbeGetGroupIds(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*> *
dbeGetNames(int dbevindex,int type,Obj sel_obj)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*> *
dbeGetTotalMax(int dbevindex,int type,int subtype)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*> *
dbeGetStatisOverviewList(int dbevindex)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*> *
dbeGetStatisList(int dbevindex)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
setSummary(Vector<Histable * > * objs,Vector<int> * saligns,Vector<char> * mnemonic,Vector<char * > * jlabels,Vector<char * > * jvalues)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
setMemSummary(Vector<Histable * > * objs,Vector<int> * saligns,Vector<char> * mnemonic,Vector<char * > * jlabels,Vector<char * > * jvalues)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
setIndxSummary(Vector<Histable * > * objs,Vector<int> * saligns,Vector<char> * mnemonic,Vector<char * > * jlabels,Vector<char * > * jvalues)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
setIOActivitySummary(Vector<Histable * > * objs,Vector<int> * saligns,Vector<char> * mnemonic,Vector<char * > * jlabels,Vector<char * > * jvalues)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
setHeapActivitySummary(Vector<Histable * > * objs,Vector<int> * saligns,Vector<char> * mnemonic,Vector<char * > * jlabels,Vector<char * > * jvalues)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
setDataSummary(Vector<Histable * > * objs,Vector<int> * saligns,Vector<char> * mnemonic,Vector<char * > * jlabels,Vector<char * > * jvalues)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*> *
dbeGetSummaryV2(int dbevindex,Vector<Obj> * sel_objs,int type,int subtype)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*> *
dbeGetSummary(int dbevindex,Vector<Obj> * sel_objs,int type,int subtype)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 *
dbeGetExpName(int,char * dir_name)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*>*> *
dbeGetHwcSets(int,bool forKernel)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*> *
dbeGetHwcs(Hwcentry ** hwcs)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 *> *
dbeGetHwcsAll(int,bool forKernel)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*> *
dbeGetHwcHelp(int,bool forKernel)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*> *
dbeGetHwcAttrList(int,bool forKernel)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
dbeGetHwcMaxConcurrent(int,bool forKernel)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*> *
dbeGetIfreqData(int dbevindex)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*> *
dbeGetLeakListInfo(int dbevindex,bool leakflag)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
dbeGetObject(int dbevindex,Obj sel_func,Obj sel_pc)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 *
dbeGetName(int,int exp_id)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*> *
dbeGetExpVerboseName(Vector<int> * exp_ids)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
dbeGetStartTime(int,int exp_id)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
dbeGetRelativeStartTime(int,int exp_id)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
dbeGetEndTime(int,int exp_id)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
dbeGetClock(int,int exp_id)7390 dbeGetClock (int /*dbevindex*/, int exp_id)
7391 {
7392   return dbeSession->get_clock (exp_id);
7393 }
7394 
7395 long long
dbeGetWallStartSec(int,int exp_id)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 *
dbeGetHostname(int,int exp_id)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 *
getTimelinePackets(int dbevindex,int exp_id,int data_id,int entity_prop_id)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
getIdxByVals(DataView * packets,int aux,int entity_prop_val,uint64_t time,DataView::Relation rel)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
isValidIdx(DataView * packets,int entity_prop_id,int aux,int entity_prop_val,long idx)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
hasInvisbleTLEvents(Experiment * exp,VMode view_mode)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
isVisibleTLEvent(Experiment * exp,VMode view_mode,DataView * packets,long idx)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
getTLVisibleIdxByStepping(Experiment * exp,VMode view_mode,int entity_prop_id,DataView * packets,int aux,int entity_prop_val,long idx,long move_count,int direction)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
getTLVisibleIdxByVals(Experiment * exp,VMode view_mode,int entity_prop_id,DataView * packets,int aux,int entity_prop_val,uint64_t time,DataView::Relation rel)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*
getThreadRootFuncName(int,int,int,int,VMode)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*> *
dbeGetEntityProps(int dbevindex)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*> *
dbeGetEntities(int dbevindex,int exp_id,int entity_prop_id)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*> *
dbeGetEntitiesV2(int dbevindex,Vector<int> * exp_ids,int entity_prop_id)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*> *
getTLDetailValues(int dbevindex,Experiment * exp,int data_id,VMode view_mode,DataView * packets,long idx)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*> *
dbeGetTLDetails(int dbevindex,int exp_id,int data_id,int entity_prop_id,Obj event_id)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> *
dbeGetStackFunctions(int dbevindex,Obj stack)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*> *
dbeGetStacksFunctions(int dbevindex,Vector<Obj> * stacks)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> *
dbeGetStackPCs(int dbevindex,Obj stack)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*> *
dbeGetStackNames(int dbevindex,Obj stack)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*> *
dbeGetSamples(int dbevindex,int exp_id,int64_t lo_idx,int64_t hi_idx)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*> *
dbeGetGCEvents(int dbevindex,int exp_id,int64_t lo_idx,int64_t hi_idx)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*>*>*
dbeGetIOStatistics(int dbevindex)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*>*>*
dbeGetHeapStatistics(int dbevindex)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*> *
dbeGetFuncNames(int dbevindex,Vector<Obj> * funcs)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*> *
dbeGetObjNamesV2(int dbevindex,Vector<uint64_t> * ids)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 *
dbeGetFuncName(int dbevindex,Obj func)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> *
dbeGetFuncIds(int dbevindex,Vector<Obj> * funcs)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
dbeGetFuncId(int dbevindex,Obj func)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 *
dbeGetObjNameV2(int dbevindex,uint64_t id)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 *
dbeGetDataspaceTypeDesc(int,Obj stack)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*> *
dbeGetDataDescriptorsV2(int exp_id)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*> *
dbeGetDataPropertiesV2(int exp_id,int data_id)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 *> *
dbeGetExperimentTimeInfo(Vector<int> * exp_ids)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 *> *
dbeGetExperimentDataDescriptors(Vector<int> * exp_ids)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
dbeHasTLData(int dbevindex,int exp_id,int data_id,int entity_prop_id,int entity_prop_value,int aux)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> *
dbeHasTLData(int dbev_index,Vector<int> * exp_ids,Vector<int> * data_ids,Vector<int> * entity_prop_ids,Vector<int> * entity_prop_values,Vector<int> * auxs)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 *> *
dbeGetTLData(int dbevindex,int exp_id,int data_id,int entity_prop_id,int entity_prop_value,int aux,hrtime_t param_start_ts,hrtime_t param_delta,int param_numDeltas,bool getRepresentatives,Vector<char * > * chartProps)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 *> *
dbeGetTLDataRepVals(VMode view_mode,hrtime_t start_ts,hrtime_t delta,int numDeltas,DataView * packets,Vector<long> * representativeEvents,bool showDuration)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> *
dbeGetTLEventCenterTime(int dbevindex,int exp_id,int data_id,int entity_prop_id,int entity_prop_val,int aux,long long event_id,long long move_count)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
dbeGetTLEventIdxNearTime(int dbevindex,int exp_id,int data_id,int entity_prop_id,int entity_prop_val,int aux,int searchDirection,long long tstamp)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
getAggrFunc(char * aname)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
computeAggrVal(DefaultMap<long long,long long> * fval_map,Aggr_type agrfn)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> *
dbeGetAggregatedValue(int data_id,char * lfilter,char * fexpr,char * pname_ts,hrtime_t start_ts,hrtime_t delta,int num,char * pname_key,char * aggr_func)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*> *
dbeGetLineInfo(Obj pc)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
dbeSetAlias(char * name,char * uname,char * expr)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*> *
dbeGetAlias(char * name)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
key_cmp(const void * p1,const void * p2)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>*> *
dbeGetXYPlotData(int data_id,char * lfilter,char * arg,char * func1,char * aggr1,char * func2,char * aggr2,char * func3,char * aggr3)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
dbeGetSignalValue(char * signal)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 *
dbeSendSignal(pid_t p,int signum)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 *
dbeGetCollectorControlValue(char * control)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 *
dbeSetCollectorControlValue(char * control,char * value)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 *
dbeUnsetCollectorControlValue(char * control)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
dbeSetLocation(const char * fname,const char * location)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
dbeSetLocations(Vector<const char * > * fnames,Vector<const char * > * locations)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*> *
dbeResolvedWith_setpath(const char * path)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*> *
dbeResolvedWith_pathmap(const char * old_prefix,const char * new_prefix)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
dbe_archive(Vector<long long> * ids,Vector<const char * > * locations)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 *
dbeCheckConnection(char * str)10366 dbeCheckConnection (char *str)
10367 {
10368   return dbe_strdup (str);
10369 }
10370