]> Git Repo - binutils.git/blob - gprofng/src/Dbe.cc
Automatic date update in version.in
[binutils.git] / gprofng / src / Dbe.cc
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
69 template<> VecType Vector<int>::type ()
70 {
71   return VEC_INTEGER;
72 }
73
74 template<> VecType Vector<unsigned>::type ()
75 {
76   return VEC_INTEGER;
77 }
78
79 template<> VecType Vector<char>::type ()
80 {
81   return VEC_CHAR;
82 }
83
84 template<> VecType Vector<bool>::type ()
85 {
86   return VEC_BOOL;
87 }
88
89 template<> VecType Vector<double>::type ()
90 {
91   return VEC_DOUBLE;
92 }
93
94 template<> VecType Vector<long long>::type ()
95 {
96   return VEC_LLONG;
97 }
98
99 template<> VecType Vector<uint64_t>::type ()
100 {
101   return VEC_LLONG;
102 }
103
104 template<> VecType Vector<void*>::type ()
105 {
106   return VEC_VOIDARR;
107 }
108
109 template<> VecType Vector<char*>::type ()
110 {
111   return VEC_STRING;
112 }
113
114 template<> VecType Vector<Vector<int>*>::type ()
115 {
116   return VEC_INTARR;
117 }
118
119 template<> VecType Vector<Vector<char*>*>::type ()
120 {
121   return VEC_STRINGARR;
122 }
123
124 template<> VecType Vector<Vector<long long>*>::type ()
125 {
126   return VEC_LLONGARR;
127 }
128
129 // gcc won't instantiate Vector<unsigned>::type() without it
130 Vector<unsigned> __dummy_unsigned_vector;
131
132 #define CASE_S(x)   case x: return #x
133 static const char *
134 dsp_type_to_string (int t)
135 {
136   switch (t)
137     {
138       CASE_S (DSP_FUNCTION);
139       CASE_S (DSP_LINE);
140       CASE_S (DSP_PC);
141       CASE_S (DSP_SOURCE);
142       CASE_S (DSP_DISASM);
143       CASE_S (DSP_SELF);
144       CASE_S (DSP_CALLER);
145       CASE_S (DSP_CALLEE);
146       CASE_S (DSP_CALLTREE);
147       CASE_S (DSP_TIMELINE);
148       CASE_S (DSP_STATIS);
149       CASE_S (DSP_EXP);
150       CASE_S (DSP_LEAKLIST);
151       CASE_S (DSP_MEMOBJ);
152       CASE_S (DSP_DATAOBJ);
153       CASE_S (DSP_DLAYOUT);
154       CASE_S (DSP_SRC_FILE);
155       CASE_S (DSP_IFREQ);
156       CASE_S (DSP_RACES);
157       CASE_S (DSP_INDXOBJ);
158       CASE_S (DSP_DUALSOURCE);
159       CASE_S (DSP_SOURCE_DISASM);
160       CASE_S (DSP_DEADLOCKS);
161       CASE_S (DSP_SOURCE_V2);
162       CASE_S (DSP_DISASM_V2);
163       CASE_S (DSP_IOACTIVITY);
164       CASE_S (DSP_OVERVIEW);
165       CASE_S (DSP_IOCALLSTACK);
166       CASE_S (DSP_HEAPCALLSTACK);
167       CASE_S (DSP_SAMPLE);
168     default:
169       break;
170     }
171   return NTXT ("ERROR");
172 }
173
174 enum
175 {
176   COMPARE_BIT       = 1 << 8,
177   MTYPE_MASK        = (1 << 8) - 1,
178   GROUP_ID_SHIFT    = 16
179 };
180
181 static DbeView *
182 getDbeView (int dbevindex)
183 {
184   DbeView *dbev = dbeSession->getView (dbevindex);
185   if (dbev == NULL)
186     abort ();
187   return dbev;
188 }
189
190
191 Vector<char*> *
192 dbeGetInitMessages ()
193 {
194   // If any comments from the .rc files, send them to the GUI
195   Emsg *msg = theDbeApplication->fetch_comments ();
196   int size = 0;
197   while (msg != NULL)
198     {
199       size++;
200       msg = msg->next;
201     }
202
203   // Initialize Java String array
204   Vector<char*> *list = new Vector<char*>(size);
205   msg = theDbeApplication->fetch_comments ();
206   size = 0;
207   int i = 0;
208   while (msg != NULL)
209     {
210       char *str = msg->get_msg ();
211       list->store (i, dbe_strdup (str));
212       i++;
213       msg = msg->next;
214     }
215
216   // now delete the comments
217   theDbeApplication->delete_comments ();
218   return list;
219 }
220
221 Vector<char*> *
222 dbeGetExpPreview (int /*dbevindex*/, char *exp_name)
223 {
224   PreviewExp *preview = new PreviewExp ();
225   preview->experiment_open (exp_name);
226   preview->open_epilogue ();
227
228   // Initialize Java String array
229   Vector<char*> *info = preview->preview_info ();
230   int size = info->size ();
231   Vector<char*> *list = new Vector<char*>(size);
232
233   // Get experiment names
234   for (int i = 0; i < size; i++)
235     {
236       char *str = info->fetch (i);
237       if (str == NULL)
238         str = GTXT ("N/A");
239       list->store (i, dbe_strdup (str));
240     }
241   delete info;
242   delete preview;
243   return list;
244 }
245
246 char *
247 dbeGetExpParams (int /*dbevindex*/, char *exp_name)
248 {
249   PreviewExp *preview = new PreviewExp ();
250   preview->experiment_open (exp_name);
251
252   // Initialize Java String array
253   char *arg_list = dbe_strdup (preview->getArgList ());
254   delete preview;
255   return arg_list;
256 }
257
258 /**
259  * Gets File Attributes according to the specified format
260  * Supported formats:
261  * "/bin/ls -dl " - see 'man ls' for details
262  * @param filename
263  * @param format
264  * @return char * attributes
265  */
266 char *
267 dbeGetFileAttributes (const char *filename, const char *format)
268 {
269   if (format != NULL)
270     {
271       if (!strcmp (format, NTXT ("/bin/ls -dl ")))
272         {
273           // A kind of "/bin/ls -dl " simulation
274           struct stat64 sbuf;
275           sbuf.st_mode = 0;
276           dbe_stat (filename, &sbuf);
277           if (S_IREAD & sbuf.st_mode)
278             { // Readable
279               if (S_ISDIR (sbuf.st_mode) != 0)
280                 return dbe_sprintf (NTXT ("%s %s\n"), NTXT ("drwxrwxr-x"), filename);
281               else if (S_ISREG (sbuf.st_mode) != 0)
282                 return dbe_sprintf (NTXT ("%s %s\n"), NTXT ("-rwxrwxr-x"), filename);
283             }
284         }
285     }
286   return dbe_strdup (NTXT (""));
287 }
288
289 /**
290  * Gets list of files for specified directory according to the specified format
291  * Supported formats:
292  * "/bin/ls -a" - see 'man ls' for details
293  * "/bin/ls -aF" - see 'man ls' for details
294  * @param dirname
295  * @param format
296  * @return char * files
297  */
298 char *
299 dbeGetFiles (const char *dirname, const char *format)
300 {
301   if (format != NULL)
302     return dbe_read_dir (dirname, format);
303   return dbe_strdup (NTXT (""));
304 }
305
306 /**
307  * Creates the directory named by this full path name, including any
308  * necessary but nonexistent parent directories.
309  * @param dirname
310  * @return result
311  */
312 char *
313 dbeCreateDirectories (const char *dirname)
314 {
315   if (dirname != NULL)
316     {
317       char *res = dbe_create_directories (dirname);
318       if (res != NULL)
319         return res;
320     }
321   return dbe_strdup (NTXT (""));
322 }
323
324 /**
325  * Deletes the file or the directory named by the specified path name.
326  * If this pathname denotes a directory, then the directory must be empty in order to be deleted.
327  * @param const char *pathname
328  * @return int result
329  */
330 char *
331 dbeDeleteFile (const char *pathname)
332 {
333   // return unlink(pathname);
334   if (pathname != NULL)
335     {
336       char *res = dbe_delete_file (pathname);
337       if (res != NULL)
338         return res;
339     }
340   return dbe_strdup (NTXT (""));
341 }
342
343 /**
344  * Reads the file named by the specified path name.
345  * Temporary limitation: file should be "text only" and its size should be less than the 1 MB limit.
346  * If the operation was successful, the contents is in the first element, and second element is NULL.
347  * If the operation failed, then first element is NULL, and second element contains the error message.
348  * @param const char *pathname
349  * @return Vector<char*> *result
350  */
351 Vector<char*> *
352 dbeReadFile (const char *pathname)
353 {
354   Vector<char*> *result = new Vector<char*>(2);
355   int limit = 1024 * 1024; // Temporary limit: 1 MB
356   char * contents = (char *) malloc (limit);
357   StringBuilder sb;
358   if (NULL == contents)
359     {
360       sb.sprintf (NTXT ("\nError: Cannot allocate %d bytes\n"), limit);
361       result->store (0, NULL);
362       result->store (1, sb.toString ()); // failure
363       return result;
364     }
365   int fd = open (pathname, O_RDONLY);
366   if (fd >= 0)
367     {
368       int64_t bytes = read_from_file (fd, contents, limit);
369       close (fd);
370       if (bytes >= limit)
371         {
372           sb.sprintf (NTXT ("\nError: file size is greater than the limit (%d bytes)\n"), limit);
373           result->store (0, NULL);
374           result->store (1, sb.toString ()); // failure
375         }
376       else
377         {
378           contents[bytes] = '\0'; // add string terminator
379           result->store (0, contents);
380           result->store (1, NULL); // success
381         }
382     }
383   else
384     {
385       sb.sprintf (NTXT ("\nError: Cannot open file %s\n"), pathname);
386       result->store (0, NULL);
387       result->store (1, sb.toString ()); // failure
388       free (contents);
389     }
390   return result;
391 }
392
393 /**
394  * Writes the file named by the specified path name.
395  * Temporary limitation: file should be "text only" and its size should be less than the 1 MB limit.
396  * If the operation failed, then -1 is returned.
397  * @param const char *pathname
398  * @return int result  (written bytes)
399  */
400 int
401 dbeWriteFile (const char *pathname, const char *contents)
402 {
403   int result = -1; // error
404   size_t len = 0;
405   if (NULL != contents)
406     len = strlen (contents);
407   size_t limit = 1024 * 1024; // Temporary limit: 1 MB
408   if (len > limit) return result;
409   unlink (pathname);
410   mode_t mode = S_IRUSR | S_IWUSR;
411   int fd = open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);
412   if (fd >= 0)
413     {  // replace file contents
414       chmod (pathname, /*S_IRUSR || S_IWUSR*/ 0600); // rw for owner only
415       ssize_t bytes = 0;
416       if (len > 0)
417         bytes = write (fd, contents, len);
418       close (fd);
419       result = (int) bytes;
420     }
421   return result;
422 }
423
424 /**
425  * Gets list of running processes according to the specified format
426  * Supported formats:
427  * "/bin/ps -ef" - see 'man ps' for details
428  * @param format
429  * @return char * processes
430  */
431 char *
432 dbeGetRunningProcesses (const char *format)
433 {
434   if (format != NULL)
435     return dbe_get_processes (format);
436   return dbe_strdup (NTXT (""));
437 }
438
439 //
440 // Open experiment
441 //
442 char *
443 dbeOpenExperimentList (int /* dbevindex */, Vector<Vector<char*>*> *groups,
444                        bool sessionRestart)
445 {
446   if (sessionRestart)
447     dbeSession->reset ();
448   char *errstr;
449   // Open experiments
450   try
451     {
452       errstr = dbeSession->setExperimentsGroups (groups);
453     }
454   catch (ExperimentLoadCancelException *)
455     {
456       errstr = dbe_strdup (NTXT ("Experiment Load Cancelled"));
457     }
458   return errstr;
459 }
460
461 //
462 // Drop experiments
463 //
464 char *
465 dbeDropExperiment (int /* dbevindex */, Vector<int> *drop_index)
466 {
467   for (int i = drop_index->size () - 1; i >= 0; i--)
468     {
469       char *ret = dbeSession->drop_experiment (drop_index->fetch (i));
470       if (ret != NULL)
471           return ret;
472     }
473   return NULL;
474 }
475
476 /**
477  * Read .er.rc file from the specified location
478  * @param path
479  * @return
480  */
481 char *
482 dbeReadRCFile (int dbevindex, char* path)
483 {
484   DbeView *dbev = getDbeView (dbevindex);
485   char *err_msg = dbev->get_settings ()->read_rc (path);
486   return err_msg;
487 }
488
489 char *
490 dbeSetExperimentsGroups (Vector<Vector<char*>*> *groups)
491 {
492   int cmp_mode = dbeSession->get_settings ()->get_compare_mode ();
493   if (groups->size () < 2)
494     cmp_mode = CMP_DISABLE;
495   else if (cmp_mode == CMP_DISABLE)
496     cmp_mode = CMP_ENABLE;
497   for (int i = 0;; i++)
498     {
499       DbeView *dbev = dbeSession->getView (i);
500       if (dbev == NULL)
501         break;
502       dbev->get_settings ()->set_compare_mode (cmp_mode);
503     }
504   char *err_msg = dbeSession->setExperimentsGroups (groups);
505
506   // automatically load machine model if applicable
507   dbeDetectLoadMachineModel (0);
508   return err_msg;
509 }
510
511 Vector<Vector<char*>*> *
512 dbeGetExperimensGroups ()
513 {
514   Vector<Vector<char*>*> *grops = dbeSession->getExperimensGroups ();
515   return grops;
516 }
517
518 Vector<int> *
519 dbeGetFounderExpId (Vector<int> *expIds)
520 {
521   Vector<int> *ret = new Vector<int>(expIds->size ());
522   for (int i = 0; i < expIds->size (); i++)
523     {
524       int expId = expIds->fetch (i);
525       Experiment *exp = dbeSession->get_exp (expId);
526       if (exp != NULL)
527         {
528           int founderExpId = exp->getBaseFounder ()->getExpIdx ();
529           ret->store (i, founderExpId);
530         }
531       else
532         ret->store (i, -1);
533     }
534   return ret;
535 }
536
537 Vector<int> *
538 dbeGetUserExpId (Vector<int> *expIds)
539 {
540   // returns "User Visible" ids used for EXPID filters and timeline processes
541   Vector<int> *ret = new Vector<int>(expIds->size ());
542   for (int i = 0; i < expIds->size (); i++)
543     {
544       int expId = expIds->fetch (i);
545       Experiment *exp = dbeSession->get_exp (expId);
546       if (exp != NULL)
547         {
548           int userExpId = exp->getUserExpId ();
549           ret->store (i, userExpId);
550         }
551       else
552         ret->store (i, -1);
553     }
554   return ret;
555 }
556
557 //
558 // Get experiment groupid
559 //
560 Vector<int> *
561 dbeGetExpGroupId (Vector<int> *expIds)
562 {
563   Vector<int> *ret = new Vector<int>(expIds->size ());
564   for (int i = 0; i < expIds->size (); i++)
565     {
566       int expId = expIds->fetch (i);
567       Experiment *exp = dbeSession->get_exp (expId);
568       if (exp != NULL)
569         {
570           int gId = exp->groupId;
571           ret->store (i, gId);
572         }
573       else
574         ret->store (i, -1);
575     }
576   return ret;
577 }
578
579 Vector<char*> *
580 dbeGetExpsProperty (const char *prop_name)
581 {
582   long nexps = dbeSession->nexps ();
583   if (prop_name == NULL || nexps == 0)
584     return NULL;
585   Vector<char*> *list = new Vector<char*>(nexps);
586   StringBuilder sb;
587   int empty = 1;
588   int prop = 99;
589   if (strcasecmp (prop_name, NTXT ("ERRORS")) == 0)
590     prop = 1;
591   else if (strcasecmp (prop_name, NTXT ("WARNINGS")) == 0)
592     prop = 2;
593   if (prop < 3)
594     {
595       for (long i = 0; i < nexps; i++)
596         {
597           Experiment *exp = dbeSession->get_exp (i);
598           char *nm = exp->get_expt_name ();
599           sb.setLength (0);
600           for (Emsg *emsg = (prop == 1) ? exp->fetch_errors () : exp->fetch_warnings ();
601                   emsg; emsg = emsg->next)
602             sb.appendf (NTXT ("%s: %s\n"), STR (nm), STR (emsg->get_msg ()));
603           char *s = NULL;
604           if (sb.length () > 0)
605             {
606               s = sb.toString ();
607               empty = 0;
608             }
609           list->append (s);
610         }
611     }
612   if (empty)
613     {
614       delete list;
615       list = NULL;
616     }
617   return list;
618 }
619
620 //
621 // Get experiment names
622 //
623 Vector<char*> *
624 dbeGetExpName (int /*dbevindex*/)
625 {
626   int size = dbeSession->nexps ();
627   if (size == 0)
628     return NULL;
629   // Initialize Java String array
630   Vector<char*> *list = new Vector<char*>(size);
631
632   // Get experiment names
633   for (int i = 0; i < size; i++)
634     {
635       Experiment *texp = dbeSession->get_exp (i);
636       char *buf = dbe_sprintf (NTXT ("%s [%s]"), texp->get_expt_name (),
637                                texp->utargname != NULL ? texp->utargname : GTXT ("(unknown)"));
638       list->store (i, buf);
639     }
640   return list;
641 }
642
643 //
644 // Get experiment state
645 //
646 Vector<int> *
647 dbeGetExpState (int /* dbevindex */)
648 {
649   int size = dbeSession->nexps ();
650   if (size == 0)
651     return NULL;
652   // Initialize Java array
653   Vector<int> *state = new Vector<int>(size);
654
655   // Get experiment state
656   for (int i = 0; i < size; i++)
657     {
658       Experiment *exp = dbeSession->get_exp (i);
659       int set = EXP_SUCCESS;
660       if (exp->get_status () == Experiment::FAILURE)
661         set |= EXP_FAILURE;
662       if (exp->get_status () == Experiment::INCOMPLETE)
663         set |= EXP_INCOMPLETE;
664       if (exp->broken)
665         set |= EXP_BROKEN;
666       if (exp->obsolete)
667         set |= EXP_OBSOLETE;
668       state->store (i, set);
669     }
670   return state;
671 }
672
673 //
674 // Get enabled experiment indices
675 //
676 Vector<bool> *
677 dbeGetExpEnable (int dbevindex)
678 {
679   DbeView *dbev = getDbeView (dbevindex);
680   int size = dbeSession->nexps ();
681   if (dbev == NULL || size == 0)
682     return NULL;
683
684   // Get enabled experiment
685   Vector<bool> *enable = new Vector<bool>(size);
686   for (int i = 0; i < size; i++)
687     {
688       bool val = dbev->get_exp_enable (i) && !dbeSession->get_exp (i)->broken;
689       enable->store (i, val);
690     }
691   return enable;
692 }
693
694 //
695 // Get enabled experiment indices
696 //
697 bool
698 dbeSetExpEnable (int dbevindex, Vector<bool> *enable)
699 {
700   DbeView *dbev = getDbeView (dbevindex);
701   bool ret = false;
702   int size = dbeSession->nexps ();
703   if (dbev == NULL || size == 0)
704     return false;
705
706   // set enable, as per input vector
707   for (int i = 0; i < size; i++)
708     if (!dbeSession->get_exp (i)->broken
709         && dbev->get_exp_enable (i) != enable->fetch (i))
710       {
711         dbev->set_exp_enable (i, enable->fetch (i));
712         ret = true;
713       }
714   return ret;
715 }
716
717 //
718 // Get experiment info
719 //
720 Vector<char*> *
721 dbeGetExpInfo (int dbevindex)
722 {
723   DbeView *dbev = dbeSession->getView (dbevindex);
724   if (dbev == NULL)
725     abort ();
726   int size = dbeSession->nexps ();
727   if (size == 0)
728     return NULL;
729
730   // Initialize Java String array
731   Vector<char*> *list = new Vector<char*>(size * 2 + 1);
732
733   // Get experiment names
734   Vector<LoadObject*> *text_segments = dbeSession->get_text_segments ();
735   char *msg = pr_load_objects (text_segments, NTXT (""));
736   delete text_segments;
737   list->store (0, msg);
738   int k = 1;
739   for (int i = 0; i < size; i++)
740     {
741       Experiment *exp = dbeSession->get_exp (i);
742       char *msg0 = pr_mesgs (exp->fetch_notes (), NTXT (""), NTXT (""));
743       char *msg1 = pr_mesgs (exp->fetch_errors (), GTXT ("No errors\n"), NTXT (""));
744       char *msg2 = pr_mesgs (exp->fetch_warnings (), GTXT ("No warnings\n"), NTXT (""));
745       char *msg3 = pr_mesgs (exp->fetch_comments (), NTXT (""), NTXT (""));
746       char *msg4 = pr_mesgs (exp->fetch_pprocq (), NTXT (""), NTXT (""));
747       msg = dbe_sprintf (NTXT ("%s%s%s%s"), msg1, msg2, msg3, msg4);
748       list->store (k++, msg0);
749       list->store (k++, msg);
750       free (msg1);
751       free (msg2);
752       free (msg3);
753       free (msg4);
754     }
755   return list;
756 }
757
758 bool
759 dbeGetViewModeEnable ()
760 {
761   return dbeSession->has_ompavail () || dbeSession->has_java ();
762 }
763
764 bool
765 dbeGetJavaEnable ()
766 {
767   return dbeSession->has_java ();
768 }
769
770 int
771 dbeUpdateNotes (int dbevindex, int exp_id, int type, char* text, bool handle_file)
772 {
773   DbeView *dbev = dbeSession->getView (dbevindex);
774   if (dbev == NULL)
775     abort ();
776   int size = dbeSession->nexps ();
777   if (size == 0)
778     return -1;
779   Experiment *exp = dbeSession->get_exp (exp_id);
780   return (type == 0) ? exp->save_notes (text, handle_file) : exp->delete_notes (handle_file);
781 }
782
783 //
784 // Get load object names
785 //
786 Vector<char*> *
787 dbeGetLoadObjectName (int /* dbevindex */)
788 {
789   Vector<LoadObject*> *lobjs = dbeSession->get_text_segments ();
790   int size = lobjs->size ();
791
792   // Initialize Java String array
793   Vector<char*> *list = new Vector<char*>(size);
794
795   // Get load object names
796   LoadObject *lo;
797   int index;
798   Vec_loop (LoadObject*, lobjs, index, lo)
799   {
800     list->store (index, dbe_strdup (lo->get_name ()));
801   }
802   delete lobjs;
803   return list;
804 }
805
806 // XXX Will use later when order has to be passed too,
807 // Get complete List of tabs
808 //
809 Vector<void*> *
810 dbeGetTabList (int /* dbevindex */)
811 {
812   //DbeView *dbev = getDbeView (dbevindex);
813   //Vector<void*> *tabs = dbeSession->get_TabList();
814   //return tabs;
815   return NULL;
816 }
817
818 //
819 // Returns list of available tabs
820 //
821 Vector<void*> *
822 dbeGetTabListInfo (int dbevindex)
823 {
824   int index;
825   DispTab *dsptab;
826   DbeView *dbev = getDbeView (dbevindex);
827
828   // make sure the tabs are initialized properly
829   dbev->get_settings ()->proc_tabs (theDbeApplication->rdtMode);
830   Vector<DispTab*> *tabs = dbev->get_TabList ();
831
832   // Get number of available tabs
833   int size = 0;
834   Vec_loop (DispTab*, tabs, index, dsptab)
835   {
836     if (!dsptab->available)
837       continue;
838     size++;
839   }
840   Vector<void*> *data = new Vector<void*>(2);
841   Vector<int> *typelist = new Vector<int>(size);
842   Vector<char*> *cmdlist = new Vector<char*>(size);
843   Vector<int> *ordlist = new Vector<int>(size);
844
845   // Build list of avaliable tabs
846   int i = 0;
847
848   Vec_loop (DispTab*, tabs, index, dsptab)
849   {
850     if (!dsptab->available)
851       continue;
852     typelist->store (i, dsptab->type);
853     cmdlist->store (i, dbe_strdup (Command::get_cmd_str (dsptab->cmdtoken)));
854     ordlist->store (i, dsptab->order);
855     i++;
856   }
857   data->store (0, typelist);
858   data->store (1, cmdlist);
859   data->store (2, ordlist);
860   return data;
861 }
862
863 // Return visibility state for all available tabs
864 //
865 Vector<bool> *
866 dbeGetTabSelectionState (int dbevindex)
867 {
868   int index;
869   DispTab *dsptab;
870   DbeView *dbev = getDbeView (dbevindex);
871   Vector<DispTab*> *tabs = dbev->get_TabList ();
872
873   // Get number of available tabs
874   int size = 0;
875   Vec_loop (DispTab*, tabs, index, dsptab)
876   {
877     if (!dsptab->available)
878       continue;
879     size++;
880   }
881   Vector<bool> *states = new Vector<bool>(size);
882
883   // Get visibility bit for all available tabs
884   int i = 0;
885   Vec_loop (DispTab*, tabs, index, dsptab)
886   {
887     if (!dsptab->available)
888       continue;
889     states->store (i++, dsptab->visible);
890   }
891   return states;
892 }
893
894 // Set visibility bit for a tab
895 void
896 dbeSetTabSelectionState (int dbevindex, Vector<bool> *selected)
897 {
898   int index;
899   DispTab *dsptab;
900   DbeView *dbev = getDbeView (dbevindex);
901   Vector<DispTab*> *tabs = dbev->get_TabList ();
902   int i = 0;
903   Vec_loop (DispTab*, tabs, index, dsptab)
904   {
905     if (!dsptab->available)
906       continue;
907     dsptab->visible = selected->fetch (i++);
908   }
909 }
910
911 // Return visibility state for all available MemObj tabs
912 Vector<bool> *
913 dbeGetMemTabSelectionState (int dbevindex)
914 {
915   int index;
916   bool dsptab;
917   DbeView *dbev = getDbeView (dbevindex);
918   Vector<bool> *memtabs = dbev->get_MemTabState ();
919
920   // set the output vector
921   int size = memtabs->size ();
922   Vector<bool> *states = new Vector<bool>(size);
923
924   // Get visibility bit for all available tabs
925   int i = 0;
926   Vec_loop (bool, memtabs, index, dsptab)
927   {
928     states->store (i++, dsptab);
929   }
930   return states;
931 }
932
933 // Set visibility bit for a memory tab
934 //
935 void
936 dbeSetMemTabSelectionState (int dbevindex, Vector<bool> *selected)
937 {
938   DbeView *dbev = dbeSession->getView (dbevindex);
939   if (dbev == NULL)
940     abort ();
941   dbev->set_MemTabState (selected);
942 }
943
944 // Return visibility state for all available index tabs
945 Vector<bool> *
946 dbeGetIndxTabSelectionState (int dbevindex)
947 {
948   int index;
949   bool dsptab;
950   DbeView *dbev = dbeSession->getView (dbevindex);
951   if (dbev == NULL)
952     abort ();
953   Vector<bool> *indxtabs = dbev->get_IndxTabState ();
954
955   // set the output vector
956   int size = indxtabs->size ();
957   Vector<bool> *states = new Vector<bool>(size);
958
959   // Get visibility bit for all available tabs
960   int i = 0;
961   Vec_loop (bool, indxtabs, index, dsptab)
962   {
963     states->store (i++, dsptab);
964   }
965   return states;
966 }
967
968 // Set visibility bit for a index tab
969 void
970 dbeSetIndxTabSelectionState (int dbevindex, Vector<bool> *selected)
971 {
972   DbeView *dbev = dbeSession->getView (dbevindex);
973   if (dbev == NULL)
974     abort ();
975   dbev->set_IndxTabState (selected);
976 }
977
978 //
979 // Get search path
980 //
981 Vector<char*> *
982 dbeGetSearchPath (int /*dbevindex*/)
983 {
984   Vector<char*> *path = dbeSession->get_search_path ();
985   int size = path->size ();
986   Vector<char*> *list = new Vector<char*>(size);
987   int index;
988   char *name;
989   Vec_loop (char*, path, index, name)
990   {
991     list->store (index, dbe_strdup (name));
992   }
993   return list;
994 }
995
996 //
997 // Set search path
998 //
999 void
1000 dbeSetSearchPath (int /*dbevindex*/, Vector<char*> *path)
1001 {
1002   dbeSession->set_search_path (path, true);
1003   return;
1004 }
1005
1006 //
1007 // Get pathmaps
1008 //
1009 Vector<void*> *
1010 dbeGetPathmaps (int /*dbevindex*/)
1011 {
1012   int index;
1013   pathmap_t *pthmap;
1014   Vector<pathmap_t*> *path = dbeSession->get_pathmaps ();
1015   int size = path->size ();
1016   Vector<void*> *data = new Vector<void*>(2);
1017   Vector<char*> *oldlist = new Vector<char*>(size);
1018   Vector<char*> *newlist = new Vector<char*>(size);
1019
1020   int i = 0;
1021   Vec_loop (pathmap_t*, path, index, pthmap)
1022   {
1023     oldlist->store (i, dbe_strdup (pthmap->old_prefix));
1024     newlist->store (i, dbe_strdup (pthmap->new_prefix));
1025     i++;
1026   }
1027   data->store (0, oldlist);
1028   data->store (1, newlist);
1029   return data;
1030 } // dbeGetPathmaps
1031
1032 char *
1033 dbeSetPathmaps (Vector<char*> *from, Vector<char*> *to)
1034 {
1035   if (from == NULL || to == NULL || from->size () != to->size ())
1036     return dbe_strdup ("dbeSetPathmaps: size of 'from' does not match for size of 'to'\n");
1037   Vector<pathmap_t*> *newPath = new Vector<pathmap_t*>(from->size ());
1038   for (int i = 0, sz = from->size (); i < sz; i++)
1039     {
1040       char *err = Settings::add_pathmap (newPath, from->get (i), to->get (i));
1041       if (err)
1042         {
1043           newPath->destroy ();
1044           delete newPath;
1045           return err;
1046         }
1047     }
1048   dbeSession->set_pathmaps (newPath);
1049   return NULL;
1050 }
1051
1052 //
1053 // Add pathmap
1054 char *
1055 dbeAddPathmap (int /* dbevindex */, char *from, char *to)
1056 {
1057   Vector<pathmap_t*> *pmp = dbeSession->get_pathmaps ();
1058   char *err = Settings::add_pathmap (pmp, from, to);
1059   return err;
1060 }
1061
1062 //
1063 // Get error/warning string of data
1064 char *
1065 dbeGetMsg (int dbevindex, int type)
1066 {
1067   DbeView *dbev = dbeSession->getView (dbevindex);
1068   if (dbev == NULL)
1069     abort ();
1070   char *msgstr = NULL;
1071   if (type == ERROR_MSG)
1072     msgstr = dbev->get_error_msg ();
1073   else if (type == WARNING_MSG)
1074     msgstr = dbev->get_warning_msg ();
1075   else if (type == PSTAT_MSG)
1076     msgstr = dbev->get_processor_msg (PSTAT_MSG);
1077   else if (type == PWARN_MSG)
1078     msgstr = dbev->get_processor_msg (PWARN_MSG);
1079   return msgstr ? dbe_strdup (msgstr) : NULL;
1080 }
1081
1082 // Create a DbeView, given new index, and index of view to clone
1083 int
1084 dbeInitView (int id, int cloneid)
1085 {
1086   return dbeSession->createView (id, cloneid);
1087 }
1088
1089
1090 // Delete a DbeView
1091 void
1092 dbeDeleteView (int dbevindex)
1093 {
1094   dbeSession->dropView (dbevindex);
1095   return;
1096 } // dbeDeleteView
1097
1098 MetricList *
1099 dbeGetMetricListV2 (int dbevindex, MetricType mtype,
1100                     Vector<int> *type, Vector<int> *subtype, Vector<bool> *sort,
1101                     Vector<int> *vis, Vector<char*> *cmd,
1102                     Vector<char*> *expr_spec, Vector<char*> *legends)
1103 {
1104   DbeView *dbev = dbeSession->getView (dbevindex);
1105   MetricList *mlist = new MetricList (mtype);
1106   for (int i = 0, msize = type->size (); i < msize; i++)
1107     {
1108       BaseMetric *bm = dbev->register_metric_expr ((BaseMetric::Type) type->fetch (i),
1109                                                    cmd->fetch (i),
1110                                                    expr_spec->fetch (i));
1111       Metric *m = new Metric (bm, (Metric::SubType) subtype->fetch (i));
1112       m->set_raw_visbits (vis->fetch (i));
1113       if (m->legend == NULL)
1114         m->legend = dbe_strdup (legends->fetch (i));
1115       mlist->append (m);
1116       if (sort->fetch (i))
1117         {
1118           mlist->set_sort_ref_index (i);
1119         }
1120     }
1121   return mlist;
1122 }
1123
1124 static Vector<void*> *
1125 dbeGetMetricList (MetricList *mlist)
1126 {
1127   int clock_val = dbeSession->get_clock (-1);
1128   Vector<Metric*> *items = mlist->get_items ();
1129   int size = items->size ();
1130
1131   Vector<int> *type = new Vector<int>(size);
1132   Vector<int> *subtype = new Vector<int>(size);
1133   Vector<int> *clock = new Vector<int>(size);
1134   Vector<int> *flavors = new Vector<int>(size);
1135   Vector<int> *vis = new Vector<int>(size);
1136   Vector<bool> *sorted = new Vector<bool>(size);
1137   Vector<int> *value_styles = new Vector<int>(size);
1138   Vector<char*> *aux = new Vector<char*>(size);
1139   Vector<char*> *name = new Vector<char*>(size);
1140   Vector<char*> *abbr = new Vector<char*>(size);
1141   Vector<char*> *comd = new Vector<char*>(size);
1142   Vector<char*> *unit = new Vector<char*>(size);
1143   Vector<char*> *user_name = new Vector<char*>(size);
1144   Vector<char*> *expr_spec = new Vector<char*>(size);
1145   Vector<char*> *legend = new Vector<char*>(size);
1146   Vector<int> *valtype = new Vector<int>(size);
1147   Vector<char*> *data_type_name = new Vector<char*>(size);
1148   Vector<char*> *data_type_uname = new Vector<char*>(size);
1149   Vector<char*> *short_desc = new Vector<char*>(size);
1150
1151   int sort_index = mlist->get_sort_ref_index ();
1152   // Fill metric elements
1153   for (int i = 0; i < size; i++)
1154     {
1155       Metric *m = items->fetch (i);
1156       type->append (m->get_type ());
1157       subtype->append (m->get_subtype ());
1158       flavors->append (m->get_flavors ());
1159       abbr->append (dbe_strdup (m->get_abbr ()));
1160       char *s = m->get_abbr_unit ();
1161       if ((m->get_visbits () & VAL_RATIO) != 0)
1162         s = NULL;
1163       unit->append (dbe_strdup (s ? s : NTXT ("")));
1164       value_styles->append (m->get_value_styles ());
1165       vis->append (m->get_visbits ());
1166       sorted->append (i == sort_index);
1167       clock->append (m->get_type () == Metric::HWCNTR ? clock_val
1168                      : m->get_clock_unit ());
1169       aux->append (dbe_strdup (m->get_aux ()));
1170       name->append (dbe_strdup (m->get_name ()));
1171       comd->append (dbe_strdup (m->get_cmd ()));
1172       user_name->append (dbe_strdup (m->get_username ()));
1173       expr_spec->append (dbe_strdup (m->get_expr_spec ()));
1174       legend->append (dbe_strdup (m->legend));
1175       valtype->append (m->get_vtype2 ());
1176
1177       char* _data_type_name = NULL;
1178       char* _data_type_uname = NULL;
1179       int data_type = m->get_packet_type ();
1180       if (data_type >= 0 && data_type < DATA_LAST)
1181         {
1182           _data_type_name = dbe_strdup (get_prof_data_type_name (data_type));
1183           _data_type_uname = dbe_strdup (get_prof_data_type_uname (data_type));
1184         }
1185       data_type_name->append (_data_type_name);
1186       data_type_uname->append (_data_type_uname);
1187
1188       char* _short_desc = NULL;
1189       if (m->get_type () == Metric::HWCNTR)
1190         {
1191           Hwcentry * hwctr = m->get_hw_ctr ();
1192           if (hwctr)
1193             _short_desc = dbe_strdup (hwctr->short_desc);
1194         }
1195       short_desc->append (_short_desc);
1196     }
1197
1198   // Set Java array
1199   Vector<void*> *data = new Vector<void*>(16);
1200   data->append (type);
1201   data->append (subtype);
1202   data->append (clock);
1203   data->append (flavors);
1204   data->append (value_styles);
1205   data->append (user_name);
1206   data->append (expr_spec);
1207   data->append (aux);
1208   data->append (name);
1209   data->append (abbr);
1210   data->append (comd);
1211   data->append (unit);
1212   data->append (vis);
1213   data->append (sorted);
1214   data->append (legend);
1215   data->append (valtype);
1216   data->append (data_type_name);
1217   data->append (data_type_uname);
1218   data->append (short_desc);
1219   return data;
1220 }
1221
1222 Vector<void*> *
1223 dbeGetRefMetricsV2 ()
1224 {
1225   MetricList *mlist = new MetricList (MET_NORMAL);
1226   Vector<BaseMetric*> *base_metrics = dbeSession->get_base_reg_metrics ();
1227   for (long i = 0, sz = base_metrics->size (); i < sz; i++)
1228     {
1229       BaseMetric *bm = base_metrics->fetch (i);
1230       Metric *m;
1231       if (bm->get_flavors () & Metric::EXCLUSIVE)
1232         {
1233           m = new Metric (bm, Metric::EXCLUSIVE);
1234           m->enable_all_visbits ();
1235           mlist->append (m);
1236         }
1237       else if (bm->get_flavors () & BaseMetric::STATIC)
1238         {
1239           m = new Metric (bm, BaseMetric::STATIC);
1240           m->enable_all_visbits ();
1241           mlist->append (m);
1242         }
1243     }
1244   Vector<void*> *data = dbeGetMetricList (mlist);
1245   delete mlist;
1246   return data;
1247 }
1248
1249 Vector<void*> *
1250 dbeGetCurMetricsV2 (int dbevindex, MetricType mtype)
1251 {
1252   DbeView *dbev = dbeSession->getView (dbevindex);
1253   MetricList *mlist = dbev->get_metric_list (mtype);
1254   Vector<void*> *data = dbeGetMetricList (mlist);
1255   return data;
1256 }
1257
1258 // YXXX we should refactor Metrics/BaseMetrics so that it no longer uses VAL_VALUE to enable time.
1259 static int
1260 convert_visbits_to_gui_checkbox_bits (BaseMetric *bm, const int visbits)
1261 {
1262   // The purpose of this function is to handle the following case:
1263   //    When bm->get_value_styles() supports VAL_TIMEVAL but not VAL_VALUE
1264   //        Metric and BaseMetric use (visbits&VAL_VALUE) to enable time.
1265   //    However, the Overview expects the VAL_TIMEVAL bit to enable time.
1266   // Inputs: visbits as returned by BaseMetric->get_default_visbits();
1267   // Returns: valuebits, as used for checks in GUI checkboxes
1268   int valuebits = visbits;
1269   const int value_styles = bm->get_value_styles ();
1270   if ((value_styles & VAL_TIMEVAL) && // supports time
1271       !(value_styles & VAL_VALUE))
1272     { // but not value
1273       unsigned mask = ~(VAL_VALUE | VAL_TIMEVAL);
1274       valuebits = (unsigned) valuebits & mask; // clear bits
1275       if (visbits & VAL_VALUE)
1276         valuebits |= VAL_TIMEVAL; // set VAL_TIMEVAL
1277       if (visbits & VAL_TIMEVAL)
1278         valuebits |= VAL_TIMEVAL; // weird, this should never happen.
1279     }
1280   return valuebits;
1281 }
1282
1283 static Vector<void*> *
1284 dbeGetMetricTreeNode (BaseMetricTreeNode* curr, MetricList *mlist,
1285                       bool include_unregistered, bool has_clock_profiling_data)
1286 {
1287   Vector<void*> *data = new Vector<void*>(2);
1288
1289   // ----- fields
1290   Vector<void*> *fields = new Vector<void*>();
1291   Vector<char*> *name = new Vector<char*>(1);
1292   Vector<char*> *username = new Vector<char*>(1);
1293   Vector<char*> *description = new Vector<char*>(1);
1294   Vector<int> * flavors = new Vector<int>(1);
1295   Vector<int> * vtype = new Vector<int>(1);
1296   Vector<int> * vstyles_capable = new Vector<int>(1);
1297
1298   // Specifies which default styles should be enabled when a metric is enabled.
1299   // Also, specifies if metric should start enabled
1300   Vector<int> *vstyles_e_defaults = new Vector<int>(1);
1301   Vector<int> *vstyles_i_defaults = new Vector<int>(1);
1302   Vector<bool> *registered = new Vector<bool>(1);
1303   Vector<bool> *aggregation = new Vector<bool>(1);
1304   Vector<bool> *has_value = new Vector<bool>(1);
1305   Vector<char*> *unit = new Vector<char*>(1);
1306   Vector<char*> *unit_uname = new Vector<char*>(1);
1307
1308   char *_name = NULL;
1309   char *_username = NULL;
1310   char *_description = dbe_strdup (curr->get_description ());
1311
1312   // BaseMetric fields
1313   int _flavors = 0; // SubType bitmask: (e.g. EXCLUSIVE)
1314   int _vtype = 0; // ValueTag: e.g. VT_INT, VT_FLOAT, ...
1315   int _vstyles_capable = 0; // ValueType bitmask, e.g. VAL_TIMEVAL
1316   int _vstyles_e_default_values = 0; // default visibility settings, exclusive/static
1317   int _vstyles_i_derault_values = 0; // default visibility settings, inclusive
1318   bool _registered = curr->is_registered ()
1319           || curr->get_num_registered_descendents () > 0;
1320   bool _aggregation = curr->is_composite_metric ()
1321           && curr->get_num_registered_descendents () > 0;
1322   bool _has_value = false; //not used yet; for nodes that don't have metrics
1323   char *_unit = NULL;
1324   char *_unit_uname = NULL;
1325
1326   BaseMetric *bm = curr->get_BaseMetric ();
1327   if (bm)
1328     {
1329       _name = dbe_strdup (bm->get_cmd ());
1330       _username = dbe_strdup (bm->get_username ());
1331       if (!include_unregistered && !curr->is_registered ())
1332         abort ();
1333       _flavors = bm->get_flavors ();
1334       _vtype = bm->get_vtype ();
1335       _vstyles_capable = bm->get_value_styles ();
1336       int e_visbits = bm->get_default_visbits (BaseMetric::EXCLUSIVE);
1337       int i_visbits = bm->get_default_visbits (BaseMetric::INCLUSIVE);
1338       _vstyles_e_default_values = convert_visbits_to_gui_checkbox_bits (bm, e_visbits);
1339       _vstyles_i_derault_values = convert_visbits_to_gui_checkbox_bits (bm, i_visbits);
1340       // not all metrics shown in er_print cmd line should be selected in the GUI at startup:
1341       if (has_clock_profiling_data && bm->get_hw_ctr ())
1342         {
1343           bool hide = true; // by default, hide HWCs
1344           if (dbe_strcmp (bm->get_hw_ctr ()->name, NTXT ("c_stalls")) == 0 ||
1345               dbe_strcmp (bm->get_hw_ctr ()->name, NTXT ("K_c_stalls")) == 0)
1346             {
1347               bool is_time = (bm->get_value_styles () & VAL_TIMEVAL) != 0;
1348               if (is_time)
1349                 // By default, show time variant of c_stalls
1350                 hide = false;
1351             }
1352           if (hide)
1353             {
1354               _vstyles_e_default_values |= VAL_HIDE_ALL;
1355               _vstyles_i_derault_values |= VAL_HIDE_ALL;
1356             }
1357         }
1358     }
1359   else
1360     {
1361       // not a base metric
1362       _name = dbe_strdup (curr->get_name ());
1363       _username = dbe_strdup (curr->get_user_name ());
1364      if (curr->get_unit ())
1365         { // represents a value
1366           _has_value = true;
1367           _unit = dbe_strdup (curr->get_unit ());
1368           _unit_uname = dbe_strdup (curr->get_unit_uname ());
1369         }
1370     }
1371   name->append (_name); // unique id string (dmetrics cmd)
1372   username->append (_username); // user-visible name
1373   description->append (_description);
1374   flavors->append (_flavors); // SubType bitmask: (e.g. EXCLUSIVE)
1375   vtype->append (_vtype); // ValueTag: e.g. VT_INT, VT_FLOAT, ...
1376   vstyles_capable->append (_vstyles_capable); // ValueType bitmask, e.g. VAL_TIMEVAL
1377   vstyles_e_defaults->append (_vstyles_e_default_values);
1378   vstyles_i_defaults->append (_vstyles_i_derault_values);
1379   registered->append (_registered); // is a "live" metric
1380   aggregation->append (_aggregation); // value derived from children nodes
1381   has_value->append (_has_value); // value generated from other source
1382   unit->append (_unit); // See BaseMetric.h, e.g. UNIT_SECONDS
1383   unit_uname->append (_unit_uname); //See BaseMetric.h,
1384
1385   fields->append (name);
1386   fields->append (username);
1387   fields->append (description);
1388   fields->append (flavors);
1389   fields->append (vtype);
1390   fields->append (vstyles_capable);
1391   fields->append (vstyles_e_defaults);
1392   fields->append (vstyles_i_defaults);
1393   fields->append (registered);
1394   fields->append (aggregation);
1395   fields->append (has_value);
1396   fields->append (unit);
1397   fields->append (unit_uname);
1398   data->append (fields);
1399
1400   // ----- children
1401   Vector<BaseMetricTreeNode*> *children = curr->get_children ();
1402   int num_children = children->size ();
1403   Vector<void*> *children_list = new Vector<void*>(num_children);
1404   BaseMetricTreeNode *child_node;
1405   int index;
1406
1407   Vec_loop (BaseMetricTreeNode*, children, index, child_node)
1408   {
1409     if (include_unregistered /* fetch everything */
1410         || child_node->is_registered ()
1411         || child_node->get_num_registered_descendents () > 0)
1412       {
1413         //Special case for metrics that aren't registered
1414         // but have registered children
1415         // Linux example: Total Time is unregistered, CPU Time is registered
1416         if (!include_unregistered && /* not fetching everything */
1417             !child_node->is_registered () &&
1418             (child_node->get_BaseMetric () != NULL ||
1419              child_node->is_composite_metric ()))
1420           {
1421             Vector<BaseMetricTreeNode*> *registered_descendents =
1422                     new Vector<BaseMetricTreeNode*>();
1423             child_node->get_nearest_registered_descendents (registered_descendents);
1424             int idx2;
1425             BaseMetricTreeNode*desc_node;
1426             Vec_loop (BaseMetricTreeNode*, registered_descendents, idx2, desc_node)
1427             {
1428               Vector<void*> *desc_data;
1429               desc_data = dbeGetMetricTreeNode (desc_node, mlist,
1430                                 include_unregistered, has_clock_profiling_data);
1431               children_list->append (desc_data);
1432             }
1433             delete registered_descendents;
1434             continue;
1435           }
1436         Vector<void*> *child_data;
1437         child_data = dbeGetMetricTreeNode (child_node, mlist,
1438                                 include_unregistered, has_clock_profiling_data);
1439         children_list->append (child_data);
1440       }
1441   }
1442   data->append (children_list);
1443   return data;
1444 }
1445
1446 Vector<void*> *
1447 dbeGetRefMetricTree (int dbevindex, bool include_unregistered)
1448 {
1449   DbeView *dbev = dbeSession->getView (dbevindex);
1450   MetricList *mlist = dbev->get_metric_list (MET_NORMAL);
1451   bool has_clock_profiling_data = false;
1452   for (long i = 0, sz = mlist->get_items ()->size (); i < sz; i++)
1453     {
1454       Metric *m = mlist->get_items ()->fetch (i);
1455       if (m->get_packet_type () == DATA_CLOCK)
1456         {
1457           has_clock_profiling_data = true;
1458           break;
1459         }
1460     }
1461   BaseMetricTreeNode *curr = dbeSession->get_reg_metrics_tree ();
1462   return dbeGetMetricTreeNode (curr, mlist, include_unregistered, has_clock_profiling_data);
1463 }
1464
1465 static Vector<void*> *
1466 dbeGetTableDataV2Data (DbeView *dbev, Hist_data *data);
1467
1468 static Vector<void*> *dbeGetTableDataOneColumn (Hist_data *data, int met_ind);
1469 static Vector<void*> *
1470 dbeGetTableDataOneColumn (DbeView *dbev, Vector<Hist_data::HistItem*> *data,
1471                           ValueTag vtype, int metricColumnNumber);
1472
1473 static hrtime_t
1474 dbeCalcGroupDuration (int grInd)
1475 {
1476   int thisGroupSize = 1;
1477   hrtime_t max_time = 0;
1478   Experiment *exp;
1479   if (dbeSession->expGroups->size () > 0)
1480     {
1481       ExpGroup *grp = dbeSession->expGroups->fetch (grInd);
1482       thisGroupSize = grp->exps->size ();
1483       for (int ii = 0; ii < thisGroupSize; ii++)
1484         {
1485           exp = grp->exps->fetch (ii);
1486           Vector<DataDescriptor*> *ddscr = exp->getDataDescriptors ();
1487           delete ddscr;// getDataDescriptors() forces reading of experiment data
1488           if (exp != NULL)
1489             {
1490               hrtime_t tot_time = exp->getLastEvent () - exp->getStartTime ()
1491                       + exp->getRelativeStartTime ();
1492               if (max_time < tot_time)
1493                 max_time = tot_time;
1494             }
1495         }
1496     }
1497   else
1498     {
1499       exp = dbeSession->get_exp (0);
1500       if (exp != NULL)
1501         max_time = exp->getLastEvent () - exp->getStartTime ();
1502     }
1503   return max_time; //nanoseconds
1504 }
1505
1506 static hrtime_t
1507 dbeCalcGroupGCDuration (int grInd)
1508 {
1509   int thisGroupSize = 1;
1510   hrtime_t tot_time = 0;
1511   Experiment *exp;
1512   if (dbeSession->expGroups->size () > 0)
1513     {
1514       ExpGroup *grp = dbeSession->expGroups->fetch (grInd);
1515       thisGroupSize = grp->exps->size ();
1516       for (int ii = 0; ii < thisGroupSize; ii++)
1517         {
1518           exp = grp->exps->fetch (ii);
1519           Vector<DataDescriptor*> *ddscr = exp->getDataDescriptors ();
1520           delete ddscr; // getDataDescriptors() forces reading of experiment data
1521           if (exp != NULL)
1522             tot_time += exp->getGCDuration ();
1523         }
1524     }
1525   else
1526     {
1527       exp = dbeSession->get_exp (0);
1528       if (exp != NULL)
1529         tot_time = exp->getGCDuration ();
1530     }
1531   return tot_time; //nanoseconds
1532 }
1533
1534 Vector<void*> *
1535 dbeGetRefMetricTreeValues (int dbevindex, Vector<char *> *metric_cmds,
1536                            Vector<char *> *non_metric_cmds)
1537 {
1538   DbeView *dbev = dbeSession->getView (dbevindex);
1539   // valueTable will have N "columns" of values, where N is the number of
1540   //   requested metrics and non-metrics.
1541   // Each column will be a vector with M "rows", where M is the number of
1542   //   compare groups.
1543   // highlightTable mirrors the structure of valueTable.  Each cell indicates
1544   //   if the corresponding valueTable cell is "hot" (interesting)
1545   int numMetrics = metric_cmds->size ();
1546   int numNonMetrics = non_metric_cmds->size ();
1547   int totalColumns = numMetrics + numNonMetrics; // Columns
1548   Vector<void*> *valueTable = new Vector<void*>(totalColumns);
1549   Vector<void*> *highlightTable = new Vector<void*>(totalColumns);
1550
1551   // the return value consists of the two tables discussed above.
1552   Vector<void*> *rc = new Vector<void*>(2);
1553   rc->append (valueTable);
1554   rc->append (highlightTable);
1555   if (dbeSession->nexps () == 0)
1556     { // no experiments are loaded
1557       for (int jj = 0; jj < totalColumns; jj++)
1558         {
1559           Vector<void *> *columnData = new Vector<void *>();
1560           valueTable->append (columnData);
1561           highlightTable->append (columnData);
1562         }
1563       return rc;
1564     }
1565
1566   int ngroups = dbeSession->expGroups->size (); // Rows (one per compare group)
1567   if (ngroups == 0 || !dbev->comparingExperiments ())
1568     ngroups = 1;
1569
1570   Vector<double> *groupTotalTime = new Vector<double>(ngroups);
1571   Vector<double> *groupCpuTime = new Vector<double>(ngroups);
1572   // initialize highlight table
1573   for (int ii = 0; ii < totalColumns; ii++)
1574     { // metrics
1575       Vector<bool> *columnData = new Vector<bool>(ngroups);
1576       highlightTable->append (columnData);
1577       for (int grInd = 0; grInd < ngroups; grInd++)
1578         columnData->store (grInd, false); // non-highlight
1579     }
1580
1581   if (numMetrics > 0)
1582     {
1583       MetricList *bmlist;
1584       // set bmlist to list of requested base metrics
1585       BaseMetricTreeNode *root = dbeSession->get_reg_metrics_tree ();
1586       int index;
1587       char *mcmd;
1588       Vector<BaseMetric*> *base_metrics = new Vector<BaseMetric*>();
1589       Vec_loop (char *, metric_cmds, index, mcmd)
1590       {
1591         BaseMetricTreeNode *bmt_node = root->find (mcmd);
1592         if (!bmt_node)
1593           abort (); //YXXX weird
1594         BaseMetric * baseNetric = bmt_node->get_BaseMetric ();
1595         if (!baseNetric)
1596           abort ();
1597         base_metrics->append (baseNetric);
1598       }
1599
1600       // MET_INDX will create MetricList of Exclusive metrics
1601       bmlist = new MetricList (base_metrics, MET_SRCDIS);
1602
1603       // Use the Function List to fetch <Total> values
1604       // A temporary table, v_totals, stores <total> by group
1605       Vector<Hist_data::HistItem *> *v_totals = new Vector<Hist_data::HistItem *>(ngroups);
1606       for (int grInd = 0; grInd < ngroups; grInd++)
1607         {
1608           MetricList *mlist;
1609           if (ngroups > 1)
1610             mlist = dbev->get_compare_mlist (bmlist, grInd);
1611           else
1612             mlist = bmlist;
1613           if (mlist->size () != numMetrics)
1614             abort ();
1615
1616           Hist_data *data;
1617           data = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1618                                       Hist_data::ALL);
1619           Hist_data::HistItem * totals = data->get_totals ();
1620           v_totals->append (totals);
1621         }
1622
1623       // store the Hist_data totals in valueTable
1624       {
1625         Metric *mitem;
1626         int index;
1627         Vec_loop (Metric*, bmlist->get_items (), index, mitem)
1628         {
1629           Vector<void*> * columnData = dbeGetTableDataOneColumn (dbev,
1630                                           v_totals, mitem->get_vtype (), index);
1631           valueTable->append (columnData);
1632         }
1633       }
1634
1635       // 7207285: hack for hwc profiling cycles conversion:
1636       {
1637         Metric *mitem;
1638         int index;
1639         Vec_loop (Metric*, bmlist->get_items (), index, mitem)
1640         {
1641           if (mitem->is_time_val ()
1642               && mitem->get_vtype () == VT_ULLONG)
1643             {
1644               Vector<long long> *cycleValues = (Vector<long long> *)valueTable->fetch (index);
1645               Vector<double> *timeValues = new Vector<double>(ngroups);
1646               assert (cycleValues->size () == ngroups);
1647               for (int grInd = 0; grInd < ngroups; grInd++)
1648                 {
1649                   long long cycles = cycleValues->fetch (grInd);
1650                   int expId;
1651                   if (dbeSession->expGroups->size () > 0)
1652                     {
1653                       ExpGroup *gr = dbeSession->expGroups->fetch (grInd);
1654                       Experiment *exp = gr->exps->fetch (0);
1655                       expId = exp->getExpIdx ();
1656                     }
1657                   else
1658                     expId = -1;
1659                   int clock = dbeSession->get_clock (expId);
1660                   double time;
1661                   if (clock)
1662                     time = cycles / (1.e+6 * clock);
1663                   else
1664                     time = cycles; //weird
1665                   timeValues->store (grInd, time);
1666                 }
1667               delete cycleValues;
1668               valueTable->store (index, timeValues);
1669             }
1670         }
1671       }
1672
1673       // Scan metrics for best measure of CPU time
1674       int bestCpuTimeIndx = -1;
1675       {
1676         Metric *mitem;
1677         int index;
1678         Vec_loop (Metric*, bmlist->get_items (), index, mitem)
1679         {
1680           BaseMetric::Type type = mitem->get_type ();
1681           if (type == BaseMetric::CP_KERNEL_CPU)
1682             {
1683               bestCpuTimeIndx = index;
1684               break; // CP_KERNEL_CPU trumps other measures
1685             }
1686           if (type == BaseMetric::CP_TOTAL_CPU)
1687             {
1688               // clock profiling CPU time
1689               bestCpuTimeIndx = index;
1690               // keep looking in case CP_KERNEL_CPU also exists
1691               continue;
1692             }
1693
1694           bool isTime = ((mitem->get_value_styles () & VAL_TIMEVAL) != 0);
1695           bool isHwcCycles = (type == BaseMetric::HWCNTR
1696                               && (dbe_strcmp (mitem->get_aux (), "cycles") == 0)
1697                               && isTime);
1698           if (isHwcCycles)
1699             if (bestCpuTimeIndx < 0)
1700               bestCpuTimeIndx = index;
1701         }
1702         if (bestCpuTimeIndx >= 0)
1703           {
1704             Vector<double> *timeValues = (Vector<double> *)valueTable->fetch (bestCpuTimeIndx);
1705             if (timeValues->type () == VEC_DOUBLE)
1706               for (int grInd = 0; grInd < ngroups; grInd++)
1707                 {
1708                   double time = timeValues->fetch (grInd);
1709                   groupCpuTime->append (time);
1710                 }
1711           }
1712       }
1713
1714       // Scan metrics for Total Thread time
1715       {
1716         Metric *mitem;
1717         int index;
1718         Vec_loop (Metric*, bmlist->get_items (), index, mitem)
1719         {
1720           BaseMetric::Type type = mitem->get_type ();
1721           if (type == BaseMetric::CP_TOTAL)
1722             {
1723               Vector<double> *timeValues = (Vector<double> *)valueTable->fetch (index);
1724               if (timeValues->type () != VEC_DOUBLE)
1725                 continue; // weird
1726               for (int grInd = 0; grInd < ngroups; grInd++)
1727                 {
1728                   double time = timeValues->fetch (grInd);
1729                   groupTotalTime->append (time);
1730                 }
1731               break;
1732             }
1733         }
1734       }
1735
1736       // highlight metrics based on cpu time
1737 #define CPUSEC_PERCENT_THRESHOLD            10.0
1738 #define HWC_OVERFLOWS_PER_CPUSEC_THRESHOLD  15
1739       {
1740         Metric *mitem;
1741         int index;
1742         Vec_loop (Metric*, bmlist->get_items (), index, mitem)
1743         {
1744           BaseMetric::Type type = mitem->get_type ();
1745           Vector<bool> * columnHilites = (Vector<bool> *)highlightTable->fetch (index);
1746
1747           // always highlight the following
1748           if (index == bestCpuTimeIndx)
1749             {
1750               for (int grInd = 0; grInd < ngroups; grInd++)
1751                 columnHilites->store (grInd, true);
1752               continue;
1753             }
1754
1755           // skip certain types
1756           bool typeIsCycles = (type == BaseMetric::HWCNTR
1757                        && dbe_strcmp (mitem->get_aux (), NTXT ("cycles")) == 0);
1758           bool typeIsInsts = (type == BaseMetric::HWCNTR
1759                         && dbe_strcmp (mitem->get_aux (), NTXT ("insts")) == 0);
1760           if (type == BaseMetric::CP_TOTAL
1761               || type == BaseMetric::CP_TOTAL_CPU
1762               || type == BaseMetric::CP_LMS_USER
1763               || type == BaseMetric::CP_LMS_SYSTEM
1764               || type == BaseMetric::CP_LMS_TRAP
1765               || type == BaseMetric::CP_LMS_USER_LOCK
1766               || type == BaseMetric::CP_LMS_SLEEP
1767               || type == BaseMetric::CP_KERNEL_CPU
1768               || type == BaseMetric::OMP_WORK
1769               || typeIsCycles
1770               || typeIsInsts
1771               // || type == BaseMetric::CP_TOTAL_WAIT
1772               )
1773             continue; // types we never highlight
1774
1775           // for time values, compare against CPUSEC_PERCENT_THRESHOLD
1776           bool isTime = ((mitem->get_value_styles () & VAL_TIMEVAL) != 0);
1777           if (isTime)
1778             {
1779               if (groupCpuTime->size () == 0)
1780                 continue; // no time to use as reference
1781               Vector<double> *timeValues = (Vector<double> *)valueTable->fetch (index);
1782               if (timeValues->type () != VEC_DOUBLE)
1783                 continue; // weird
1784               for (int grInd = 0; grInd < ngroups; grInd++)
1785                 {
1786                   double thistime = timeValues->fetch (grInd);
1787                   double usertime = groupCpuTime->fetch (grInd);
1788                   if (thistime / (CPUSEC_PERCENT_THRESHOLD / 100) > usertime)
1789                     columnHilites->store (grInd, true);
1790                 }
1791               continue;
1792             }
1793
1794           // for HWC event counts, look at rate of events
1795           if (type == BaseMetric::HWCNTR)
1796             {
1797               Hwcentry *hwctr = mitem->get_hw_ctr ();
1798               if (!hwctr)
1799                 continue; // weird
1800               if (!hwctr->metric)
1801                 continue; // raw counter
1802               if (groupCpuTime->size () == 0)
1803                 continue; // no time to use as reference
1804               if (mitem->get_base_metric ()->get_dependent_bm ())
1805                 continue; // has a derived time metric, only flag time version
1806               Vector<long long> *llValues = (Vector<long long> *)valueTable->fetch (index);
1807               if (llValues->type () != VEC_LLONG)
1808                 continue; // weird
1809               int overflowVal = hwctr->val; //overflow count
1810               if (!overflowVal)
1811                 continue; // weird
1812               if (overflowVal > (4000000))
1813                 // cut off events that are very frequent like loads/stores
1814                 // 4Ghz * (0.01 seconds/event) / (4000000 events/overflow) = 10 cycles
1815                 continue;
1816               // for HWCs we could base it on the overflow rate
1817               for (int grInd = 0; grInd < ngroups; grInd++)
1818                 {
1819                   double thisVal = llValues->fetch (grInd);
1820                   thisVal /= overflowVal;
1821                   double usertime = groupCpuTime->fetch (grInd);
1822                   if (thisVal > usertime * HWC_OVERFLOWS_PER_CPUSEC_THRESHOLD)
1823                     columnHilites->store (grInd, true);
1824                 }
1825               continue;
1826             }
1827
1828           // check for non-zero counts of the following
1829           if (type == BaseMetric::DEADLOCKS ||
1830               type == BaseMetric::RACCESS ||
1831               type == BaseMetric::HEAP_ALLOC_BYTES ||
1832               type == BaseMetric::HEAP_LEAK_BYTES)
1833             {
1834               Vector<long long> *llValues = (Vector<long long> *)valueTable->fetch (index);
1835               if (llValues->type () != VEC_LLONG)
1836                 continue; // weird
1837               for (int grInd = 0; grInd < ngroups; grInd++)
1838                 {
1839                   long long thisVal = llValues->fetch (grInd);
1840                   if (thisVal)
1841                     columnHilites->store (grInd, true);
1842                 }
1843               continue;
1844             }
1845           // continue adding cases as needed
1846         }
1847       }
1848     }
1849
1850   if (numNonMetrics > 0)
1851     {
1852       int index;
1853       char *mcmd;
1854       Vec_loop (char *, non_metric_cmds, index, mcmd)
1855       {
1856         if (dbe_strcmp (mcmd, NTXT ("YXXX_TOTAL_TIME_PLUS_THREADS")) == 0
1857             && groupCpuTime->size () == ngroups)
1858           {
1859             Vector<char *> *columnData = new Vector<char *>(ngroups);
1860             for (int grInd = 0; grInd < ngroups; grInd++)
1861               {
1862                 double totaltime = groupTotalTime->fetch (grInd);
1863                 columnData->append (dbe_sprintf (NTXT ("%0.3f %s"), totaltime, GTXT ("Seconds")));
1864               }
1865             valueTable->append (columnData);
1866           }
1867         else if (dbe_strcmp (mcmd, L1_DURATION) == 0)
1868           {
1869             Vector<double> *columnData = new Vector<double>(ngroups);
1870             for (int grInd = 0; grInd < ngroups; grInd++)
1871               {
1872                 hrtime_t duration = dbeCalcGroupDuration (grInd);
1873                 double seconds = duration * 1.e-9;
1874                 columnData->append (seconds);
1875               }
1876             valueTable->append (columnData);
1877           }
1878         else if (dbe_strcmp (mcmd, L1_GCDURATION) == 0)
1879           {
1880             Vector<double> *columnData = new Vector<double>(ngroups);
1881             for (int grInd = 0; grInd < ngroups; grInd++)
1882               {
1883                 hrtime_t duration = dbeCalcGroupGCDuration (grInd);
1884                 double seconds = duration * 1.e-9;
1885                 columnData->append (seconds);
1886               }
1887             valueTable->append (columnData);
1888           }
1889         else
1890           {
1891             Vector<char *> *columnData = new Vector<char *>(ngroups);
1892             char * valueString = NTXT ("<unknown>");
1893             for (int grInd = 0; grInd < ngroups; grInd++)
1894               columnData->append (dbe_strdup (valueString));
1895             valueTable->append (columnData);
1896           }
1897       }
1898     }
1899   return rc;
1900 }
1901
1902 Vector<char*> *
1903 dbeGetOverviewText (int dbevindex)
1904 {
1905   DbeView *dbev = dbeSession->getView (dbevindex);
1906   Vector<char*> *info = new Vector<char*>;
1907   char *field;
1908   int ngroups = dbeSession->expGroups->size (); // Rows (one per compare group)
1909   if (ngroups == 0 || !dbev->comparingExperiments ())
1910     ngroups = 1;
1911   for (int grInd = 0; grInd < ngroups; grInd++)
1912     {
1913       int thisGroupSize = 1;
1914       Experiment *exp;
1915       if (dbeSession->expGroups->size () > 0)
1916         {
1917           ExpGroup *gr = dbeSession->expGroups->fetch (grInd);
1918           exp = gr->exps->fetch (0);
1919           thisGroupSize = gr->exps->size ();
1920         }
1921       else
1922         {
1923           if (dbeSession->nexps () == 0)
1924             return info;
1925           exp = dbeSession->get_exp (0);
1926         }
1927       char * expHeader;
1928       if (ngroups == 1)
1929         expHeader = dbe_strdup (GTXT ("Experiment      :"));
1930       else if (grInd == 0)
1931         expHeader = dbe_strdup (GTXT ("Base Group      : "));
1932       else if (ngroups == 2)
1933         expHeader = dbe_strdup (GTXT ("Compare Group   : "));
1934       else
1935         expHeader = dbe_sprintf (GTXT ("Compare Group %d : "), grInd);
1936       if (thisGroupSize == 1)
1937         info->append (dbe_sprintf ("%s%s", expHeader, exp->get_expt_name ()));
1938       else
1939         info->append (dbe_sprintf ("%s%s (plus %d more)",
1940                           expHeader, exp->get_expt_name (), thisGroupSize - 1));
1941       free (expHeader);
1942       field = exp->uarglist;
1943       if (field && field[0])
1944         info->append (dbe_sprintf (GTXT ("  Target        : '%s'"), field));
1945       field = exp->hostname;
1946       if (field && field[0])
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
1970 dbeSetSort (int dbevindex, int sort_index, MetricType mtype, bool reverse)
1971 {
1972   DbeView *dbev;
1973
1974   dbev = dbeSession->getView (dbevindex);
1975   if (dbev == NULL)
1976     abort ();
1977   dbev->setSort (sort_index, mtype, reverse);
1978   return;
1979 }
1980
1981 //
1982 // Get annotation setting
1983 //
1984 Vector<int> *
1985 dbeGetAnoValue (int dbevindex)
1986 {
1987   DbeView *dbev = dbeSession->getView (dbevindex);
1988   if (dbev == NULL)
1989     abort ();
1990   Vector<int> *set = new Vector<int>(9);
1991   set->store (0, dbev->get_src_compcom ());
1992   set->store (1, dbev->get_dis_compcom ());
1993   set->store (2, dbev->get_thresh_src ());
1994   set->store (3, dbev->get_thresh_src ());
1995   set->store (4, dbev->get_src_visible ());
1996   set->store (5, (int) dbev->get_srcmetric_visible ());
1997   set->store (6, (int) dbev->get_hex_visible ());
1998   set->store (7, (int) dbev->get_cmpline_visible ());
1999   set->store (8, (int) dbev->get_func_scope ());
2000   return set;
2001 }
2002
2003 //
2004 // Set annotation setting
2005 //
2006 void
2007 dbeSetAnoValue (int dbevindex, Vector<int> *set)
2008 {
2009   DbeView *dbev;
2010   dbev = dbeSession->getView (dbevindex);
2011   if (dbev == NULL)
2012     abort ();
2013   if (set->size () != 10)
2014     return;
2015   dbev->set_src_compcom (set->fetch (0));
2016   dbev->set_dis_compcom (set->fetch (1));
2017   dbev->set_thresh_src (set->fetch (2));
2018   dbev->set_thresh_dis (set->fetch (3));
2019   dbev->set_src_visible (set->fetch (4));
2020   dbev->set_srcmetric_visible ((bool)set->fetch (5));
2021   dbev->set_hex_visible ((bool)set->fetch (6));
2022   dbev->set_cmpline_visible ((bool)set->fetch (7));
2023   dbev->set_func_scope (set->fetch (8));
2024   dbev->set_funcline_visible ((bool)set->fetch (9));
2025   return;
2026 }
2027
2028 //
2029 // Get name formats
2030 //
2031 int
2032 dbeGetNameFormat (int dbevindex)
2033 {
2034   DbeView *dbev;
2035   dbev = dbeSession->getView (dbevindex);
2036   if (dbev == NULL)
2037     abort ();
2038   Histable::NameFormat fmt = dbev->get_name_format ();
2039   return Histable::fname_fmt (fmt);
2040 }
2041
2042 bool
2043 dbeGetSoName (int dbevindex)
2044 {
2045   DbeView *dbev;
2046   dbev = dbeSession->getView (dbevindex);
2047   if (dbev == NULL)
2048     abort ();
2049   Histable::NameFormat fmt = dbev->get_name_format ();
2050   return Histable::soname_fmt (fmt);
2051 }
2052
2053 //
2054 // Set name formats
2055 //
2056 void
2057 dbeSetNameFormat (int dbevindex, int nformat, bool soname)
2058 {
2059   DbeView *dbev;
2060   dbev = dbeSession->getView (dbevindex);
2061   if (dbev == NULL)
2062     abort ();
2063   dbev->set_name_format (nformat, soname);
2064 }
2065
2066 //
2067 // Get View mode
2068 //
2069 int
2070 dbeGetViewMode (int dbevindex)
2071 {
2072   DbeView *dbev;
2073   dbev = dbeSession->getView (dbevindex);
2074   if (dbev == NULL)
2075     abort ();
2076   return (int) dbev->get_view_mode ();
2077 }
2078
2079 // Set View mode
2080 void
2081 dbeSetViewMode (int dbevindex, int nmode)
2082 {
2083   DbeView *dbev;
2084   dbev = dbeSession->getView (dbevindex);
2085   if (dbev == NULL)
2086     abort ();
2087   dbev->set_view_mode ((VMode) nmode);
2088   return;
2089 }
2090
2091 // Get timeline setting
2092 //
2093 Vector<void*> *
2094 dbeGetTLValue (int dbevindex)
2095 {
2096   DbeView *dbev;
2097   dbev = dbeSession->getView (dbevindex);
2098   if (dbev == NULL)
2099     abort ();
2100   Vector<char *> *strings = new Vector<char *>();
2101   char *tldata_cmd = dbev->get_tldata ();
2102   strings->store (0, tldata_cmd);
2103
2104   Vector<int> *ints = new Vector<int>(3);
2105   int val;
2106   val = dbev->get_tlmode ();
2107   ints->store (0, val);
2108   val = dbev->get_stack_align ();
2109   ints->store (1, val);
2110   val = dbev->get_stack_depth ();
2111   ints->store (2, val);
2112
2113   Vector<void*> *objs = new Vector<void*>(2);
2114   objs->store (0, strings);
2115   objs->store (1, ints);
2116   return objs;
2117 }
2118
2119 //
2120 // Set timeline setting
2121 //
2122 void
2123 dbeSetTLValue (int dbevindex, const char *tldata_cmd,
2124                int entitiy_prop_id, int stackalign, int stackdepth)
2125 {
2126   DbeView *dbev;
2127   dbev = dbeSession->getView (dbevindex);
2128   if (dbev == NULL)
2129     abort ();
2130   dbev->set_tldata (tldata_cmd);
2131   dbev->set_tlmode (entitiy_prop_id);
2132   dbev->set_stack_align (stackalign);
2133   dbev->set_stack_depth (stackdepth);
2134   return;
2135 }
2136
2137 //
2138 // Get founder experiments and their descendants
2139 //
2140 Vector<void*> *
2141 dbeGetExpFounderDescendants ()
2142 {
2143   int size = dbeSession->nexps ();
2144   if (size == 0)
2145     return NULL;
2146   Vector<void*> *table = new Vector<void*>(2);
2147   Vector<int> *founderExpIds = new Vector<int>();
2148   Vector<Vector<int> *> *subExpIds = new Vector<Vector<int>*>();
2149   for (int index = 0; index < size; index++)
2150     {
2151       Experiment *exp = dbeSession->get_exp (index);
2152       if (exp->founder_exp == NULL)
2153         {
2154           founderExpIds->append (exp->getExpIdx ());
2155           Vector<int> *subExps = new Vector<int>();
2156           for (int i = 0; i < exp->children_exps->size (); i++)
2157             {
2158               Experiment * subExp = exp->children_exps->fetch (i);
2159               subExps->append (subExp->getExpIdx ());
2160             }
2161           subExpIds->append (subExps);
2162         }
2163     }
2164   table->store (0, founderExpIds);
2165   table->store (1, subExpIds);
2166   return table;
2167 }
2168
2169 //
2170 // Get experiment selection
2171 //
2172 Vector<void*> *
2173 dbeGetExpSelection (int dbevindex)
2174 {
2175   DbeView *dbev = dbeSession->getView (dbevindex);
2176   if (dbev == NULL)
2177     abort ();
2178   int size = dbeSession->nexps ();
2179   if (size == 0)
2180     return NULL;
2181   Vector<void*> *table = new Vector<void*>(3);
2182   Vector<char*> *names = new Vector<char*>(size);
2183   Vector<bool> *enable = new Vector<bool>(size);
2184   Vector<int> *userExpIds = new Vector<int>(size);
2185
2186   // Get experiment names
2187   for (int index = 0; index < size; index++)
2188     {
2189       Experiment *exp = dbeSession->get_exp (index);
2190       char *buf = dbeGetName (dbevindex, index);
2191       names->store (index, buf);
2192       bool val;
2193       val = dbev->get_exp_enable (index);
2194       enable->store (index, val);
2195       userExpIds->store (index, exp->getUserExpId ());
2196     }
2197   table->store (0, names);
2198   table->store (1, enable);
2199   table->store (2, userExpIds);
2200   return table;
2201 }
2202
2203 int
2204 dbeValidateFilterExpression (char *str_expr)
2205 {
2206   if (str_expr == NULL)
2207     return 0;
2208   Expression *expr = dbeSession->ql_parse (str_expr);
2209   if (expr == NULL)
2210     return 0;
2211   delete expr;
2212   return 1;
2213 }
2214
2215 Vector<void*> *
2216 dbeGetFilterKeywords (int /* dbevindex */)
2217 {
2218   Vector <char*> *kwCategory = new Vector<char *>();
2219   Vector <char*> *kwCategoryI18N = new Vector<char *>();
2220   Vector <char*> *kwDataType = new Vector<char *>();
2221   Vector <char*> *kwKeyword = new Vector<char *>();
2222   Vector <char*> *kwFormula = new Vector<char *>();
2223   Vector <char*> *kwDescription = new Vector<char *>();
2224   Vector <void*> *kwEnumDescs = new Vector<void *>();
2225
2226   Vector<void*> *res = new Vector<void*>(7);
2227   res->append (kwCategory);
2228   res->append (kwCategoryI18N);
2229   res->append (kwDataType);
2230   res->append (kwKeyword);
2231   res->append (kwFormula);
2232   res->append (kwDescription);
2233   res->append (kwEnumDescs);
2234
2235   char *vtypeNames[] = VTYPE_TYPE_NAMES;
2236   // section header for global definitions
2237   kwCategory->append (dbe_strdup (NTXT ("FK_SECTION")));
2238   kwCategoryI18N->append (dbe_strdup (GTXT ("Global Definitions")));
2239   kwDataType->append (NULL);
2240   kwKeyword->append (NULL);
2241   kwFormula->append (NULL);
2242   kwDescription->append (NULL);
2243   kwEnumDescs->append (NULL);
2244   dbeSession->get_filter_keywords (res);
2245   MemorySpace::get_filter_keywords (res);
2246
2247   // loop thru all founder experiments
2248   int nexp = dbeSession->nexps ();
2249   for (int ii = 0; ii < nexp; ++ii)
2250     {
2251       Experiment* fexp = dbeSession->get_exp (ii);
2252       if (fexp->founder_exp != NULL)
2253         continue; // is a child; should be covered when we get to founder
2254
2255       // section header for each founder
2256       // section header for founder experiment
2257       kwCategory->append (dbe_strdup (NTXT ("FK_SECTION")));
2258       kwCategoryI18N->append (dbe_sprintf (NTXT ("%s [EXPGRID==%d]"),
2259                                            fexp->get_expt_name (),
2260                                            fexp->groupId));
2261       kwDataType->append (NULL);
2262       kwKeyword->append (NULL);
2263       kwFormula->append (NULL);
2264       kwDescription->append (NULL);
2265       kwEnumDescs->append (NULL);
2266
2267       int nchildren = fexp->children_exps->size ();
2268       Experiment *exp;
2269       // category header: Experiments
2270       {
2271         char *propUName = dbeSession->getPropUName (PROP_EXPID);
2272
2273         // store list of subexperiments in kwEnumDescs
2274         Vector <char*> *enumDescs = new Vector<char *>();
2275         int jj = 0;
2276         exp = fexp;
2277         while (1)
2278           {
2279             char * expBasename = get_basename (exp->get_expt_name ());
2280             char * targetName = exp->utargname ? exp->utargname
2281                     : (char *) GTXT ("(unknown)");
2282             enumDescs->append (dbe_sprintf (NTXT ("(%d) -> %s [%s, PID %d]"),
2283                                             exp->getUserExpId (), expBasename,
2284                                             targetName, exp->getPID ()));
2285             if (jj >= nchildren)
2286               break;
2287             exp = fexp->children_exps->fetch (jj);
2288             jj++;
2289           }
2290         kwCategory->append (dbe_strdup (NTXT ("FK_EXPLIST")));
2291         kwCategoryI18N->append (dbe_strdup (GTXT ("Experiments")));
2292         kwDataType->append (dbe_strdup (vtypeNames[TYPE_INT32]));
2293         kwKeyword->append (dbe_strdup (NTXT ("EXPID")));
2294         kwFormula->append (NULL);
2295         kwDescription->append (propUName);
2296         kwEnumDescs->append (enumDescs);
2297       }
2298
2299       // select representative experiment
2300       if (nchildren == 0)
2301         exp = fexp; // founder
2302       else
2303         exp = fexp->children_exps->fetch (0); // first child
2304       int expIdx = exp->getExpIdx ();
2305       Vector<void*> *data = dbeGetDataDescriptorsV2 (expIdx);
2306       if (data == NULL)
2307         continue;
2308       Vector<int> *dataId = (Vector<int>*)data->fetch (0);
2309       Vector<char*> *dataName = (Vector<char*>*)data->fetch (1);
2310       Vector<char*> *dataUName = (Vector<char*>*)data->fetch (2);
2311       if (dataId == NULL || dataName == NULL)
2312         {
2313           destroy (data);
2314           continue;
2315         }
2316       // loop thru data descriptors
2317       int ndata = dataId->size ();
2318       for (int j = 0; j < ndata; ++j)
2319         {
2320           // category: data name (e.g. Clock Profiling)
2321           char * catName = dataName->fetch (j);
2322           char * dUname = dataUName ? dataUName->fetch (j) : catName;
2323           char * catUname = dUname ? dUname : catName;
2324
2325           Vector<void*> *props = dbeGetDataPropertiesV2 (expIdx, dataId->fetch (j));
2326           if (props == NULL)
2327             continue;
2328           Vector<char*> *propUName = (Vector<char*>*)props->fetch (1);
2329           Vector<int> *propTypeId = (Vector<int> *)props->fetch (2);
2330           Vector<char*> *propType = (Vector<char*>*)props->fetch (3);
2331           Vector<char*> *propName = (Vector<char*>*)props->fetch (5);
2332           Vector<Vector<char*>*> *propStateNames =
2333                   (Vector<Vector<char*>*> *)props->fetch (6);
2334           Vector<Vector<char*>*> *propStateUNames =
2335                   (Vector<Vector<char*>*> *)props->fetch (7);
2336           if (propName == NULL || propUName == NULL || propType == NULL
2337               || propName->size () <= 0)
2338             {
2339               destroy (props);
2340               continue;
2341             }
2342           int nprop = propName->size ();
2343           for (int k = 0; k < nprop; ++k)
2344             {
2345               if (propTypeId->fetch (k) == TYPE_OBJ)
2346                 continue;
2347               if (dbe_strcmp (propName->fetch (k), NTXT ("FRINFO")) == 0)
2348                 continue;
2349
2350               // store list of states in kwEnumDescs
2351               Vector<char*> *enumDescs = new Vector<char *>();
2352               Vector<char*>* stateNames = propStateNames->fetch (k);
2353               Vector<char*>* stateUNames = propStateUNames->fetch (k);
2354               int nStates = stateNames ? stateNames->size () : 0;
2355               for (int kk = 0; kk < nStates; ++kk)
2356                 {
2357                   const char *stateName = stateNames->fetch (kk);
2358                   if (stateName == NULL || strlen (stateName) == 0)
2359                     continue;
2360                   const char *stateUName = stateUNames->fetch (kk);
2361                   if (stateUName == NULL || strlen (stateUName) == 0)
2362                     stateUName = stateName;
2363                   enumDescs->append (dbe_sprintf (NTXT ("(%d) -> %s"), kk, stateUName));
2364                 }
2365               kwCategory->append (dbe_strdup (catName));
2366               kwCategoryI18N->append (dbe_strdup (catUname));
2367               kwDataType->append (dbe_strdup (propType->fetch (k)));
2368               kwKeyword->append (dbe_strdup (propName->fetch (k)));
2369               kwFormula->append (NULL);
2370               kwDescription->append (dbe_strdup (propUName->fetch (k)));
2371               kwEnumDescs->append (enumDescs);
2372             }
2373           destroy (props);
2374         }
2375       destroy (data);
2376     }
2377   return (res);
2378 }
2379
2380 // GetFilters -- returns the list of filters for the indexed experiment
2381 //      returns false if there's a problem; true otherwise
2382 //
2383 Vector<void*> *
2384 dbeGetFilters (int dbevindex, int nexp)
2385 {
2386   FilterNumeric *filt;
2387   int index;
2388   DbeView *dbev = dbeSession->getView (dbevindex);
2389   if (dbev == NULL)
2390     abort ();
2391   Vector<FilterNumeric *>*filters = dbev->get_all_filters (nexp);
2392   if (filters == NULL)
2393     return NULL;
2394
2395   // return an array of filter data for that experiment
2396   Vector <int> *findex = new Vector<int>(); // index of the filters
2397   Vector <char*> *shortname = new Vector<char *>();
2398   // short name of filter
2399   Vector <char*> *i18n_name = new Vector<char *>();
2400   // External I18N'd name of filter
2401   Vector <char*> *pattern = new Vector<char *>();
2402   // current setting string
2403   Vector <char*> *status = new Vector<char *>();
2404   // current status of filter (%, range, etc.)
2405
2406   Vec_loop (FilterNumeric *, filters, index, filt)
2407   {
2408     findex->append (index);
2409     shortname->append (dbe_strdup (filt->get_cmd ()));
2410     i18n_name->append (dbe_strdup (filt->get_name ()));
2411     pattern->append (dbe_strdup (filt->get_pattern ()));
2412     status->append (dbe_strdup (filt->get_status ()));
2413   }
2414   Vector<void*> *res = new Vector<void*>(5);
2415   res->store (0, findex);
2416   res->store (1, shortname);
2417   res->store (2, i18n_name);
2418   res->store (3, pattern);
2419   res->store (4, status);
2420   return (res);
2421 }
2422
2423 // Set a filter string for a view
2424 //      Returns NULL if OK, error message if not
2425
2426 char *
2427 dbeSetFilterStr (int dbevindex, char *filter_str)
2428 {
2429   DbeView *dbev = dbeSession->getView (dbevindex);
2430   if (dbev == NULL)
2431     abort ();
2432   dbev->clear_error_msg ();
2433   dbev->clear_warning_msg ();
2434   char *ret = dbev->set_filter (filter_str);
2435   return ret;
2436 }
2437
2438 // Get the current filter setting for the view
2439 char *
2440 dbeGetFilterStr (int dbevindex)
2441 {
2442   DbeView *dbev = dbeSession->getView (dbevindex);
2443   if (dbev == NULL)
2444     abort ();
2445   char *ret = dbev->get_filter ();
2446   return ret;
2447 }
2448
2449 // Update a filters for a single experiment
2450 // Returns true if any filter->set_pattern() returns true,
2451 //      implying rereading the data is needed (i.e., a filter changed)
2452 //
2453 bool
2454 dbeUpdateFilters (int dbevindex, Vector<bool> *selected, Vector<char *> *pattern_str)
2455 {
2456   DbeView *dbev = dbeSession->getView (dbevindex);
2457   if (dbev == NULL)
2458     abort ();
2459   dbev->clear_error_msg ();
2460   dbev->clear_warning_msg ();
2461
2462   // Get index of first selected experiment
2463   int size = selected->size ();
2464   int nselexp = -1;
2465   for (int index = 0; index < size; index++)
2466     {
2467       if (selected->fetch (index) == true)
2468         {
2469           nselexp = index;
2470           break;
2471         }
2472     }
2473   if (nselexp == -1) // No experiment selected
2474     return false;
2475
2476   bool ret = false;
2477   for (int j = 0; j < size; j++)
2478     {
2479       if (selected->fetch (j) == false)
2480         continue;
2481       bool error;
2482       if (dbev->set_pattern (j, pattern_str, &error))
2483         ret = true;
2484     }
2485   dbev->update_advanced_filter ();
2486   return ret;
2487 }
2488
2489 char *
2490 dbeComposeFilterClause (int dbevindex, int type, int subtype, Vector<int> *selections)
2491 {
2492   DbeView *dbev = dbeSession->getView (dbevindex);
2493   if (dbev == NULL)
2494     abort ();
2495   // ask the cached data to generate the string
2496   Hist_data *data;
2497   switch (type)
2498     {
2499     case DSP_FUNCTION:
2500       data = dbev->func_data;
2501       break;
2502     case DSP_DLAYOUT:
2503       data = dbev->dlay_data;
2504       break;
2505     case DSP_DATAOBJ:
2506       data = dbev->dobj_data;
2507       break;
2508     case DSP_MEMOBJ:
2509     case DSP_INDXOBJ:
2510       data = dbev->get_indxobj_data (subtype);
2511       break;
2512     case DSP_LINE:
2513       data = dbev->line_data;
2514       break;
2515     case DSP_PC:
2516       data = dbev->pc_data;
2517       break;
2518     case DSP_SOURCE:
2519       data = dbev->src_data;
2520       break;
2521     case DSP_DISASM:
2522       data = dbev->dis_data;
2523       break;
2524     case DSP_IOACTIVITY:
2525       data = dbev->iofile_data;
2526       break;
2527     case DSP_IOVFD:
2528       data = dbev->iovfd_data;
2529       break;
2530     case DSP_IOCALLSTACK:
2531       data = dbev->iocs_data;
2532       break;
2533     case DSP_HEAPCALLSTACK:
2534       data = dbev->heapcs_data;
2535       break;
2536     default:
2537       return NULL;
2538     }
2539   if (data == NULL)
2540     return NULL;
2541
2542   // Get array of object indices, and compose filter string
2543   Vector<uint64_t> *obj_ids = data->get_object_indices (selections);
2544   if (obj_ids == NULL || obj_ids->size () == 0)
2545     return NULL;
2546
2547   uint64_t sel;
2548   int index;
2549   int found = 0;
2550   char buf[128];
2551   StringBuilder sb;
2552   sb.append ('(');
2553   switch (type)
2554     {
2555     case DSP_LINE:
2556     case DSP_PC:
2557     case DSP_SOURCE:
2558     case DSP_DISASM:
2559     case DSP_FUNCTION:
2560       sb.append (NTXT ("LEAF IN "));
2561       break;
2562     case DSP_MEMOBJ:
2563     case DSP_INDXOBJ:
2564       sb.append (dbeSession->getIndexSpaceName (subtype));
2565       sb.append (NTXT (" IN "));
2566       break;
2567     }
2568   Vec_loop (uint64_t, obj_ids, index, sel)
2569   {
2570     if (found == 0)
2571       {
2572         found = 1;
2573         sb.append ('(');
2574       }
2575     else
2576       sb.append (NTXT (", "));
2577     snprintf (buf, sizeof (buf), NTXT ("%llu"), (long long) sel);
2578     sb.append (buf);
2579   }
2580   if (found == 1)
2581     sb.append (')');
2582
2583   switch (type)
2584     {
2585     case DSP_DLAYOUT:
2586     case DSP_DATAOBJ:
2587       sb.append (NTXT (" SOME IN DOBJ"));
2588       break;
2589     }
2590   sb.append (')');
2591   return sb.toString ();
2592 }
2593
2594 //
2595 // Get load object states
2596 //
2597 Vector<void *> *
2598 dbeGetLoadObjectList (int dbevindex)
2599 {
2600   DbeView *dbev = dbeSession->getView (dbevindex);
2601   if (dbev == NULL)
2602     abort ();
2603   Vector<LoadObject*> *lobjs = dbeSession->get_text_segments ();
2604   int size = lobjs->size ();
2605
2606   // Initialize Java boolean array
2607   Vector<char *> *names = new Vector<char *>(size);
2608   Vector<int> *states = new Vector<int>(size);
2609   Vector<int> *indices = new Vector<int>(size);
2610   Vector<char *> *paths = new Vector<char *>(size);
2611   Vector<int> *isJava = new Vector<int>(size);
2612
2613   // Get load object states
2614   int index;
2615   LoadObject *lo;
2616   char *lo_name;
2617
2618   // lobjectsNoJava is a trimmed list of indices provided to front-end skipping the Java
2619   // classes. lobjectsNoJava preserves the mapping of the index into the complete lobjs
2620   // vector. What front-end sees as lobj[i] is really lobj[lobjectsNoJava[i]];
2621
2622   // This list is constructed every time GetLoadObjectList() or GetLoadObjectState() is
2623   // called. Possibility of further optimization by making it more persistent.
2624   // Only consumer of this list is dbeSetLoadObjectState
2625   int new_index = 0;
2626   if (dbev->lobjectsNoJava == NULL)
2627     dbev->lobjectsNoJava = new Vector<int>(1);
2628   else
2629     dbev->lobjectsNoJava->reset ();
2630
2631   Vec_loop (LoadObject*, lobjs, index, lo)
2632   {
2633     // Set 0, 1, or 2 for show/hide/api
2634     enum LibExpand expand = dbev->get_lo_expand (lo->seg_idx);
2635
2636     lo_name = lo->get_name ();
2637     if (lo_name != NULL)
2638       {
2639         size_t len = strlen (lo_name);
2640         if (len > 7 && streq (lo_name + len - 7, NTXT (".class>")))
2641           isJava->store (new_index, 1);
2642         else
2643           isJava->store (new_index, 0);
2644       }
2645     else
2646       isJava->store (new_index, 0);
2647     dbev->lobjectsNoJava->append (index);
2648
2649     names->store (new_index, dbe_sprintf (NTXT ("%s"), lo_name));
2650     states->store (new_index, (int) expand);
2651     indices->store (new_index, (int) lo->seg_idx);
2652     paths->store (new_index, dbe_sprintf (NTXT ("%s"), lo->get_pathname ()));
2653     new_index++;
2654   }
2655   Vector<void*> *res = new Vector<void*>(5);
2656   res->store (0, names);
2657   res->store (1, states);
2658   res->store (2, indices);
2659   res->store (3, paths);
2660   res->store (4, isJava);
2661   delete lobjs;
2662   return res;
2663 }
2664
2665 Vector<int> *
2666 dbeGetLoadObjectState (int dbevindex)
2667 {
2668   DbeView *dbev = dbeSession->getView (dbevindex);
2669   if (dbev == NULL)
2670     abort ();
2671   Vector<LoadObject*> *lobjs = dbeSession->get_text_segments ();
2672   int size = lobjs->size ();
2673
2674   // Initialize Java boolean array
2675   Vector<int> *states = new Vector<int>(size);
2676   char *lo_name;
2677
2678   // lobjectsNoJava is a trimmed list of indices provided to front-end skipping the Java
2679   // classes. lobjectsNoJava preserves the mapping of the index into the complete lobjs
2680   // vector. What front-end sees as lobj[i] is really lobj[lobjectsNoJava[i]];
2681
2682   // This list is constructed every time GetLoadObjectList() or GetLoadObjectState() is
2683   // called. Possibility of further optimization by making it more persistent.
2684   // Only consumer of this list is dbeSetLoadObjectState
2685   int new_index = 0;
2686   if (dbev->lobjectsNoJava == NULL)
2687     dbev->lobjectsNoJava = new Vector<int>(1);
2688   else
2689     dbev->lobjectsNoJava->reset ();
2690
2691   // Get load object states
2692   int index;
2693   LoadObject *lo;
2694
2695   Vec_loop (LoadObject*, lobjs, index, lo)
2696   {
2697     // Set 0, 1, or 2 for show/hide/api
2698     lo_name = lo->get_name ();
2699     if (lo_name != NULL)
2700       {
2701         size_t len = strlen (lo_name);
2702         if (len > 7 && streq (lo_name + len - 7, NTXT (".class>")))
2703           continue;
2704       }
2705     else
2706       dbev->lobjectsNoJava->append (index);
2707
2708     enum LibExpand expand = dbev->get_lo_expand (lo->seg_idx);
2709     states->store (new_index, (int) expand);
2710     new_index++;
2711   }
2712   delete lobjs;
2713   return states;
2714 }
2715
2716 // Set load object states
2717 void
2718 dbeSetLoadObjectState (int dbevindex, Vector<int> *selected)
2719 {
2720   DbeView *dbev = dbeSession->getView (dbevindex);
2721   if (dbev == NULL)
2722     abort ();
2723   Vector<LoadObject*> *lobjs = dbeSession->get_text_segments ();
2724
2725   int index;
2726   bool changed = false;
2727
2728   LoadObject *lo;
2729   int new_index = 0;
2730   dbev->setShowAll ();
2731   Vec_loop (LoadObject*, lobjs, index, lo)
2732   {
2733     if (dbev->lobjectsNoJava != NULL)
2734       {
2735         // This loadobject is a java class and was skipped
2736         if (dbev->lobjectsNoJava->fetch (new_index) != index)
2737           continue;
2738       }
2739     // Get array of settings
2740     enum LibExpand expand = (enum LibExpand) selected->fetch (new_index);
2741     if (expand == LIBEX_HIDE)
2742       {
2743         dbev->resetShowAll ();
2744         dbeSession->set_lib_visibility_used ();
2745       }
2746     changed = changed | dbev->set_libexpand (lo->get_pathname (), expand);
2747     new_index++;
2748   }
2749   delete lobjs;
2750   if (changed == true)
2751     {
2752       dbev->setShowHideChanged ();
2753       dbev->update_lo_expands ();
2754     }
2755
2756   return;
2757 }
2758
2759 // Reset load object states
2760 void
2761 dbeSetLoadObjectDefaults (int dbevindex)
2762 {
2763   DbeView *dbev = dbeSession->getView (dbevindex);
2764   if (dbev == NULL)
2765     abort ();
2766   dbev->set_libdefaults ();
2767 }
2768
2769 // Get  Machine model
2770 Vector<char*>*
2771 dbeGetCPUVerMachineModel (int dbevindex)
2772 {
2773   Vector<char*>* table = new Vector<char*>();
2774   DbeView *dbev = dbeSession->getView (dbevindex);
2775   char * mach_model = dbev->get_settings ()->get_machinemodel ();
2776   if (mach_model != NULL)
2777     {
2778       table->append (mach_model);
2779       return table;
2780     }
2781   int grsize = dbeSession->expGroups->size ();
2782   for (int j = 0; j < grsize; j++)
2783     {
2784       ExpGroup *gr = dbeSession->expGroups->fetch (j);
2785       Vector<Experiment*> *exps = gr->exps;
2786       for (int i = 0, sz = exps->size (); i < sz; i++)
2787         {
2788           Experiment *exp = exps->fetch (i);
2789           char *model = exp->machinemodel;
2790           if (model != NULL)
2791             table->append (dbe_strdup (model));
2792         }
2793     }
2794   return table;
2795 }
2796
2797 // automatically load machine model if applicable
2798 void
2799 dbeDetectLoadMachineModel (int dbevindex)
2800 {
2801   if (dbeSession->is_datamode_available ())
2802     {
2803       char *model = dbeGetMachineModel ();
2804       if (model == NULL)
2805         {
2806           Vector<char*>* models = dbeGetCPUVerMachineModel (dbevindex);
2807           char * machineModel = NTXT ("generic");
2808           if (models->size () > 0)
2809             {
2810               machineModel = models->get (0);
2811               for (int i = 1; i < models->size (); i++)
2812                 {
2813                   if (strncmp (models->get (i), machineModel, strlen (machineModel)) == 0)
2814                     {
2815                       machineModel = NTXT ("generic");
2816                       break;
2817                     }
2818                 }
2819               dbeLoadMachineModel (machineModel);
2820             }
2821           delete models;
2822         }
2823     }
2824 }
2825
2826 // Managing Memory Objects
2827 char *
2828 dbeDefineMemObj (char *name, char *index_expr, char *machinemodel,
2829                  char *sdesc, char *ldesc)
2830 {
2831   return MemorySpace::mobj_define (name, index_expr, machinemodel, sdesc, ldesc);
2832 }
2833
2834 char *
2835 dbeDeleteMemObj (char *name)
2836 {
2837   return MemorySpace::mobj_delete (name);
2838 }
2839
2840 Vector<void*> *
2841 dbeGetMemObjects (int /*dbevindex*/)
2842 {
2843   Vector<void*> *res = MemorySpace::getMemObjects ();
2844   return res;
2845 }
2846
2847 // Managing machine model
2848 char *
2849 dbeLoadMachineModel (char *name)
2850 {
2851   return dbeSession->load_mach_model (name);
2852 }
2853
2854 char *
2855 dbeGetMachineModel ()
2856 {
2857   return dbeSession->get_mach_model ();
2858 }
2859
2860 Vector <char *> *
2861 dbeListMachineModels ()
2862 {
2863   return dbeSession->list_mach_models ();
2864 }
2865
2866 // Managing Index Objects
2867 char *
2868 dbeDefineIndxObj (char *name, char *index_expr, char *sdesc, char *ldesc)
2869 {
2870   return dbeSession->indxobj_define (name, NULL, index_expr, sdesc, ldesc);
2871 }
2872
2873 Vector<void*> *
2874 dbeGetIndxObjDescriptions (int /*dbevindex*/)
2875 {
2876   Vector<void*> *res = dbeSession->getIndxObjDescriptions ();
2877   return res;
2878 }
2879
2880 Vector<void*> *
2881 dbeGetCustomIndxObjects (int /*dbevindex*/)
2882 {
2883   Vector<void*> *res = dbeSession->getCustomIndxObjects ();
2884   return res;
2885 }
2886
2887 void
2888 dbeSetSelObj (int dbevindex, Obj sel_obj_or_ind, int type, int subtype)
2889 {
2890   DbeView *dbev = dbeSession->getView (dbevindex);
2891   if (dbev == NULL)
2892     abort ();
2893   Histable *sel_obj;
2894   Hist_data *data;
2895   int sel_ind = (int) sel_obj_or_ind;
2896
2897   switch (type)
2898     {
2899     case DSP_FUNCTION:
2900       data = dbev->func_data;
2901       break;
2902     case DSP_LINE:
2903       data = dbev->line_data;
2904       break;
2905     case DSP_PC:
2906       data = dbev->pc_data;
2907       break;
2908     case DSP_CALLER:
2909       data = dbev->callers;
2910       break;
2911     case DSP_CALLEE:
2912       data = dbev->callees;
2913       break;
2914     case DSP_SOURCE:
2915       data = dbev->src_data;
2916       break;
2917     case DSP_DISASM:
2918       data = dbev->dis_data;
2919       break;
2920     case DSP_DLAYOUT:
2921       data = dbev->dlay_data;
2922       if (data == NULL)
2923         {
2924           dbev->sel_binctx = NULL;
2925           return;
2926         }
2927       if (sel_ind >= 0 && sel_ind < dbev->dlay_data->size ())
2928         dbev->sel_dobj = dbev->dlay_data->fetch (sel_ind)->obj;
2929       return;
2930     case DSP_DATAOBJ:
2931       data = dbev->dobj_data;
2932       if (data == NULL)
2933         {
2934           dbev->sel_binctx = NULL;
2935           return;
2936         }
2937       if (sel_ind >= 0 && sel_ind < dbev->dobj_data->size ())
2938         dbev->sel_dobj = dbev->dobj_data->fetch (sel_ind)->obj;
2939       return;
2940     case DSP_MEMOBJ:
2941     case DSP_INDXOBJ:
2942       dbev->set_indxobj_sel (subtype, sel_ind);
2943       sel_obj = dbev->get_indxobj_sel (subtype);
2944       if (sel_obj && sel_obj->get_type () == Histable::INDEXOBJ)
2945         dbev->set_sel_obj (((IndexObject*) sel_obj)->get_obj ());
2946       return;
2947     case DSP_SOURCE_V2:
2948     case DSP_DISASM_V2:
2949     case DSP_TIMELINE:
2950     case DSP_LEAKLIST:
2951     case DSP_RACES:
2952     case DSP_DEADLOCKS:
2953     case DSP_DUALSOURCE:
2954     case DSP_SOURCE_DISASM:
2955     case DSP_IOACTIVITY:
2956     case DSP_IOVFD:
2957     case DSP_IOCALLSTACK:
2958     case DSP_HEAPCALLSTACK:
2959     case DSP_MINICALLER:
2960       dbev->set_sel_obj ((Histable *) sel_obj_or_ind);
2961       return;
2962     default:
2963       // abort();
2964       return;
2965     }
2966   if (type != DSP_SOURCE && type != DSP_DISASM && type != DSP_SOURCE_V2
2967       && type != DSP_DISASM_V2)
2968     dbev->sel_binctx = NULL;
2969
2970   if (data == NULL || data->get_status () != Hist_data::SUCCESS
2971       || sel_ind >= data->size ())
2972     return;
2973
2974   if (sel_ind >= 0 && sel_ind < data->size ())
2975     dbev->set_sel_obj (data->fetch (sel_ind)->obj);
2976 }
2977
2978 void
2979 dbeSetSelObjV2 (int dbevindex, uint64_t id)
2980 {
2981   DbeView *dbev = dbeSession->getView (dbevindex);
2982   if (dbev == NULL)
2983     abort ();
2984   dbev->set_sel_obj (dbeSession->findObjectById (id));
2985 }
2986
2987 Obj
2988 dbeGetSelObj (int dbevindex, int type, int subtype)
2989 {
2990   DbeView *dbev = dbeSession->getView (dbevindex);
2991   Histable *sel_obj = NULL;
2992   switch (type)
2993     {
2994     case DSP_FUNCTION:
2995       sel_obj = dbev->get_sel_obj (Histable::FUNCTION);
2996       break;
2997     case DSP_LINE:
2998     case DSP_SOURCE:
2999     case DSP_SOURCE_V2:
3000       sel_obj = dbev->get_sel_obj (Histable::LINE);
3001       break;
3002     case DSP_PC:
3003     case DSP_DISASM:
3004     case DSP_DISASM_V2:
3005       sel_obj = dbev->get_sel_obj (Histable::INSTR);
3006       break;
3007     case DSP_SRC_FILE:
3008       sel_obj = dbev->get_sel_obj (Histable::SOURCEFILE);
3009       break;
3010     case DSP_DATAOBJ:
3011     case DSP_DLAYOUT:
3012       if (dbev->sel_dobj)
3013         sel_obj = dbev->sel_dobj->convertto (Histable::DOBJECT);
3014       break;
3015     case DSP_MEMOBJ:
3016     case DSP_INDXOBJ:
3017       sel_obj = dbev->get_indxobj_sel (subtype);
3018       break;
3019     default:
3020       abort ();
3021     }
3022   Dprintf (DEBUG_DBE, NTXT ("### dbeGetSelObj: Dbe.cc:%d %s (%d) returns %s\n"),
3023            __LINE__, dsp_type_to_string (type), type, sel_obj ? sel_obj->dump () : "NULL");
3024   return (Obj) sel_obj;
3025 }
3026
3027 Obj
3028 dbeConvertSelObj (Obj obj, int type)
3029 {
3030   Histable *sel_obj = (Histable *) obj;
3031   Dprintf (DEBUG_DBE, NTXT ("### dbeConvertSelObj: Dbe.cc:%d %s (%d) sel_obj=%s\n"),
3032            __LINE__, dsp_type_to_string (type), type, sel_obj ? sel_obj->dump ()
3033           : "NULL");
3034   if (sel_obj == NULL)
3035     return (Obj) NULL;
3036   switch (type)
3037     {
3038     case DSP_FUNCTION:
3039       return (Obj) sel_obj->convertto (Histable::FUNCTION);
3040     case DSP_LINE:
3041       return (Obj) sel_obj->convertto (Histable::LINE);
3042     case DSP_SOURCE:
3043     case DSP_SOURCE_V2:
3044       {
3045         SourceFile* srcCtx = NULL;
3046         if (sel_obj->get_type () == Histable::INSTR)
3047           {
3048             DbeInstr* dbei = (DbeInstr *) sel_obj;
3049             srcCtx = (SourceFile*) dbei->convertto (Histable::SOURCEFILE);
3050           }
3051         else if (sel_obj->get_type () == Histable::LINE)
3052           {
3053             DbeLine * dbel = (DbeLine *) sel_obj;
3054             srcCtx = dbel->sourceFile;
3055           }
3056         sel_obj = sel_obj->convertto (Histable::LINE, srcCtx);
3057         Dprintf (DEBUG_DBE, NTXT ("### dbeConvertSelObj: Dbe.cc:%d %s (%d) returns %s\n"),
3058                  __LINE__, dsp_type_to_string (type), type, sel_obj ? sel_obj->dump () : "NULL");
3059         if (sel_obj && sel_obj->get_type () == Histable::LINE)
3060           {
3061             DbeLine * dbel = (DbeLine *) sel_obj;
3062             return (Obj) dbel->dbeline_base;
3063           }
3064         return (Obj) sel_obj->convertto (Histable::LINE, srcCtx);
3065       }
3066     case DSP_PC:
3067     case DSP_DISASM:
3068     case DSP_DISASM_V2:
3069       return (Obj) sel_obj->convertto (Histable::INSTR);
3070     case DSP_SRC_FILE:
3071       return (Obj) sel_obj->convertto (Histable::SOURCEFILE);
3072     default:
3073       abort ();
3074     }
3075   return (Obj) NULL;
3076 }
3077
3078 uint64_t
3079 dbeGetSelObjV2 (int dbevindex, char *typeStr)
3080 {
3081   DbeView *dbev = dbeSession->getView (dbevindex);
3082   if (dbev == NULL)
3083     abort ();
3084   Histable *obj = NULL;
3085   if (typeStr != NULL)
3086     {
3087       if (streq (typeStr, NTXT ("FUNCTION")))
3088         obj = dbev->get_sel_obj (Histable::FUNCTION);
3089       else if (streq (typeStr, NTXT ("INSTRUCTION")))
3090         obj = dbev->get_sel_obj (Histable::INSTR);
3091       else if (streq (typeStr, NTXT ("SOURCELINE")))
3092         obj = dbev->get_sel_obj (Histable::LINE);
3093       else if (streq (typeStr, NTXT ("SOURCEFILE")))
3094         obj = dbev->get_sel_obj (Histable::SOURCEFILE);
3095     }
3096   Dprintf (DEBUG_DBE, NTXT ("### dbeGetSelObjV2: Dbe.cc:%d %s returns %s\n"),
3097            __LINE__, STR (typeStr), obj ? obj->dump () : "NULL");
3098   return obj != NULL ? obj->id : (uint64_t) - 1;
3099 }
3100
3101 Vector<uint64_t> *
3102 dbeGetSelObjsIO (int dbevindex, Vector<uint64_t> *ids, int type)
3103 {
3104   DbeView *dbev = dbeSession->getView (dbevindex);
3105   if (dbev == NULL)
3106     abort ();
3107   Vector<uint64_t> *res = NULL;
3108   Vector<uint64_t> *result = new Vector<uint64_t>();
3109   for (int i = 0; i < ids->size (); i++)
3110     {
3111       res = dbeGetSelObjIO (dbevindex, ids->fetch (i), type);
3112       if (res != NULL)
3113         {
3114           result->addAll (res);
3115           delete res;
3116         }
3117     }
3118   return result;
3119 }
3120
3121 Vector<uint64_t> *
3122 dbeGetSelObjIO (int dbevindex, uint64_t id, int type)
3123 {
3124   DbeView *dbev = dbeSession->getView (dbevindex);
3125   if (dbev == NULL)
3126     abort ();
3127   Histable *obj = NULL;
3128   Vector<uint64_t> *res = NULL;
3129   int size = 0;
3130   switch (type)
3131     {
3132     case DSP_IOACTIVITY:
3133       obj = dbev->get_sel_obj_io (id, Histable::IOACTFILE);
3134       size = obj != NULL ? ((FileData*) obj)->getVirtualFds ()->size () : 0;
3135       if (size)
3136         {
3137           res = new Vector<uint64_t>();
3138           Vector<int64_t> *vfds = ((FileData*) obj)->getVirtualFds ();
3139           for (int i = 0; i < size; i++)
3140             res->append (vfds->fetch (i));
3141         }
3142       break;
3143     case DSP_IOVFD:
3144       obj = dbev->get_sel_obj_io (id, Histable::IOACTVFD);
3145       if (obj)
3146         {
3147           res = new Vector<uint64_t>();
3148           res->append (obj->id);
3149         }
3150       break;
3151     case DSP_IOCALLSTACK:
3152       obj = dbev->get_sel_obj_io (id, Histable::IOCALLSTACK);
3153       if (obj)
3154         {
3155           Vector<Obj> *instrs = dbeGetStackPCs (dbevindex, obj->id);
3156           if (instrs == NULL)
3157             return NULL;
3158           int stsize = instrs->size ();
3159           res = new Vector<uint64_t>(stsize);
3160           for (int i = 0; i < stsize; i++)
3161             {
3162               Histable *objFunc = (DbeInstr*) (instrs->fetch (i));
3163               if (objFunc->get_type () != Histable::LINE)
3164                 {
3165                   objFunc = objFunc->convertto (Histable::FUNCTION);
3166                   res->insert (0, objFunc->id);
3167                 }
3168             }
3169           delete instrs;
3170         }
3171       break;
3172     default:
3173       break;
3174     }
3175   return res;
3176 }
3177
3178 uint64_t
3179 dbeGetSelObjHeapTimestamp (int dbevindex, uint64_t id)
3180 {
3181   DbeView *dbev = dbeSession->getView (dbevindex);
3182   if (dbev == NULL)
3183     abort ();
3184   Histable *obj = NULL;
3185   uint64_t res = 0;
3186   Vector<uint64_t> *peakStackIds;
3187   Vector<hrtime_t> *peakTimestamps;
3188
3189   // Find and return the timestamp for the peak
3190   bool foundPeakId = false;
3191   if (id > 0)
3192     {
3193       obj = dbev->get_sel_obj_heap (0);
3194       if (obj != NULL)
3195         {
3196           peakStackIds = ((HeapData*) obj)->getPeakStackIds ();
3197           peakTimestamps = ((HeapData*) obj)->getPeakTimestamps ();
3198           for (int i = 0; i < peakStackIds->size (); i++)
3199             {
3200               if (id == peakStackIds->fetch (i))
3201                 {
3202                   res = peakTimestamps->fetch (i);
3203                   foundPeakId = true;
3204                   break;
3205                 }
3206             }
3207         }
3208     }
3209
3210   // Return the first timestamp for the peak
3211   // if the callstack id is zero or it
3212   // doesn't match with the peak stack id
3213   if (id == 0 || !foundPeakId)
3214     {
3215       obj = dbev->get_sel_obj_heap (0);
3216       res = obj != NULL ? ((HeapData*) obj)->getPeakTimestamps ()->fetch (0) : 0;
3217     }
3218   return res;
3219 }
3220
3221 int
3222 dbeGetSelObjHeapUserExpId (int dbevindex, uint64_t id)
3223 {
3224   DbeView *dbev = dbeSession->getView (dbevindex);
3225   if (dbev == NULL)
3226     abort ();
3227   Histable *obj = NULL;
3228   int res = 0;
3229   obj = dbev->get_sel_obj_heap (id);
3230   res = obj != NULL ? ((HeapData*) obj)->getUserExpId () : 0;
3231   return res;
3232 }
3233
3234 //
3235 // Get index of selected function/object
3236 //
3237 int
3238 dbeGetSelIndex (int dbevindex, Obj sel_obj, int type, int subtype)
3239 {
3240   Hist_data *data;
3241   DbeView *dbev = dbeSession->getView (dbevindex);
3242   if (dbev == NULL)
3243     abort ();
3244   switch (type)
3245     {
3246     case DSP_FUNCTION:
3247       data = dbev->func_data;
3248       break;
3249     case DSP_LINE:
3250       data = dbev->line_data;
3251       break;
3252     case DSP_PC:
3253       data = dbev->pc_data;
3254       break;
3255     case DSP_SOURCE:
3256     case DSP_SOURCE_V2:
3257       data = dbev->src_data;
3258       break;
3259     case DSP_DISASM:
3260     case DSP_DISASM_V2:
3261       data = dbev->dis_data;
3262       break;
3263     case DSP_DLAYOUT:
3264       data = dbev->dlay_data;
3265       break;
3266     case DSP_DATAOBJ:
3267       data = dbev->dobj_data;
3268       break;
3269     case DSP_MEMOBJ:
3270     case DSP_INDXOBJ:
3271       data = dbev->get_indxobj_data (subtype);
3272       break;
3273     default:
3274       data = NULL;
3275       break;
3276     }
3277   if (data == NULL || data->get_status () != Hist_data::SUCCESS)
3278     return -1;
3279
3280   Histable *chk_obj = (Histable *) sel_obj;
3281   Vector<Hist_data::HistItem*> *histItems = data->get_hist_items ();
3282   if (histItems == NULL || chk_obj == NULL)
3283     return -1;
3284   for (int i = 0, sz = histItems->size (); i < sz; i++)
3285     {
3286       if (histItems->get (i)->obj == chk_obj)
3287         return i;
3288       if (histItems->get (i)->obj == NULL)
3289         continue;
3290       if (histItems->get (i)->obj->get_type () == Histable::LINE
3291           && chk_obj->get_type () == Histable::LINE)
3292         {
3293           if (((DbeLine*) histItems->get (i)->obj)->convertto (Histable::FUNCTION)
3294               == ((DbeLine*) chk_obj)->convertto (Histable::FUNCTION)
3295               && ((DbeLine*) histItems->get (i)->obj)->lineno
3296               == ((DbeLine*) chk_obj)->lineno)
3297             return i;
3298         }
3299       else if (histItems->get (i)->obj->get_type () == Histable::INSTR
3300          && chk_obj->get_type () == Histable::INSTR)
3301         if (((DbeInstr*) histItems->get (i)->obj)->convertto (Histable::FUNCTION)
3302             == ((DbeInstr*) chk_obj)->convertto (Histable::FUNCTION)
3303             && ((DbeInstr*) histItems->get (i)->obj)->addr
3304             == ((DbeInstr*) chk_obj)->addr)
3305           return i;
3306     }
3307
3308   Histable *chk_obj1 = NULL;
3309   switch (type)
3310     {
3311     case DSP_FUNCTION:
3312       chk_obj1 = chk_obj->convertto (Histable::FUNCTION);
3313       break;
3314     case DSP_LINE:
3315     case DSP_SOURCE:
3316     case DSP_SOURCE_V2:
3317       chk_obj1 = chk_obj->convertto (Histable::LINE);
3318       break;
3319     case DSP_PC:
3320     case DSP_DISASM:
3321     case DSP_DISASM_V2:
3322       chk_obj1 = chk_obj->convertto (Histable::INSTR);
3323       break;
3324     }
3325   if (chk_obj1 && chk_obj != chk_obj1)
3326     for (int i = 0, sz = histItems->size (); i < sz; i++)
3327       if (histItems->get (i)->obj == chk_obj1)
3328         return i;
3329
3330   if (type == DSP_LINE)
3331     {
3332       for (int i = 0, sz = histItems->size (); i < sz; i++)
3333         if (histItems->get (i)->obj != NULL
3334             && chk_obj->convertto (Histable::FUNCTION)
3335             == histItems->get (i)->obj->convertto (Histable::FUNCTION))
3336           return i;
3337     }
3338   else if (type == DSP_PC)
3339     {
3340       for (int i = 0, sz = histItems->size (); i < sz; i++)
3341         if (histItems->get (i)->obj != NULL
3342             && (histItems->get (i)->obj)->convertto (Histable::FUNCTION)
3343             == (chk_obj)->convertto (Histable::FUNCTION)
3344             && ((DbeLine*) histItems->get (i)->obj->convertto (Histable::LINE))->lineno
3345             == ((DbeLine*) chk_obj->convertto (Histable::LINE))->lineno)
3346           return i;
3347       for (int i = 0, sz = histItems->size (); i < sz; i++)
3348         if (histItems->get (i)->obj != NULL
3349             && (histItems->get (i)->obj)->convertto (Histable::FUNCTION)
3350             == (chk_obj)->convertto (Histable::FUNCTION))
3351           return i;
3352     }
3353
3354   // If we clicked on an mfunction line in the called-by call mini in user mode for omp
3355   // we might not find that function in func data
3356   if (dbev->isOmpDisMode () && type == DSP_FUNCTION)
3357     {
3358       int p = dbeGetSelIndex (dbevindex, sel_obj, DSP_DISASM, subtype);
3359       if (p != -1)
3360         return p;
3361     }
3362   return -1;
3363 }
3364
3365 // Print data
3366 //
3367 char *
3368 dbePrintData (int dbevindex, int type, int subtype, char *printer,
3369               char *fname, FILE *outfile)
3370 {
3371   Histable *current_obj;
3372   Function *func;
3373   Module *module;
3374   MetricList *mlist_orig;
3375   bool header;
3376   Print_params params;
3377   DbeView *dbev = dbeSession->getView (dbevindex);
3378   if (dbev == NULL)
3379     abort ();
3380
3381   // Set print parameters
3382   if (printer != NULL)
3383     {
3384       params.dest = DEST_PRINTER;
3385       params.name = printer;
3386     }
3387   else if (outfile != NULL)
3388     {
3389       params.dest = DEST_OPEN_FILE;
3390       params.openfile = outfile;
3391       params.name = NULL;
3392     }
3393   else
3394     {
3395       params.dest = DEST_FILE;
3396       params.name = fname;
3397       if (*(params.name) == '\0')
3398         {
3399           free (params.name);
3400           return dbe_strdup (GTXT ("Please enter the name of the file to which to print"));
3401         }
3402     }
3403   params.ncopies = 1;
3404   if (outfile != NULL)
3405     header = false;
3406   else
3407     header = !(type == DSP_SOURCE || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2);
3408
3409   params.header = header;
3410
3411   // figure out what kind of metrics to use
3412   if (type == DSP_SELF || type == DSP_CALLER || type == DSP_CALLEE
3413       || type == DSP_CALLTREE)
3414     mlist_orig = dbev->get_metric_list (MET_CALL);
3415   else if (type == DSP_DATAOBJ || type == DSP_DLAYOUT || type == DSP_MEMOBJ)
3416     mlist_orig = dbev->get_metric_list (MET_DATA);
3417   else if (type == DSP_INDXOBJ)
3418     mlist_orig = dbev->get_metric_list (MET_INDX);
3419   else if (type == DSP_IOACTIVITY || type == DSP_IOVFD
3420            || type == DSP_IOCALLSTACK)
3421     mlist_orig = dbev->get_metric_list (MET_IO);
3422   else if (type == DSP_HEAPCALLSTACK)
3423     mlist_orig = dbev->get_metric_list (MET_HEAP);
3424   else
3425     mlist_orig = dbev->get_metric_list (MET_NORMAL);
3426
3427   // make a compacted version of the input list
3428   // the list will either be moved to the generated data,
3429   //   or freed below if it wasn't needed
3430   MetricList *mlist = new MetricList (mlist_orig);
3431   Hist_data *data = NULL;
3432   er_print_common_display *cd = NULL;
3433   int ix;
3434   // Set data
3435   switch (type)
3436     {
3437     case DSP_FUNCTION:
3438     case DSP_LINE:
3439     case DSP_PC:
3440     case DSP_MEMOBJ:
3441     case DSP_INDXOBJ:
3442     case DSP_DATAOBJ:
3443       data = dbev->get_hist_data (mlist,
3444                                   ((type == DSP_FUNCTION) ? Histable::FUNCTION :
3445                                    (type == DSP_LINE) ? Histable::LINE :
3446                                    (type == DSP_PC) ? Histable::INSTR :
3447                                    (type == DSP_INDXOBJ) ? Histable::INDEXOBJ :
3448                                    (type == DSP_MEMOBJ) ? Histable::MEMOBJ
3449                                    : Histable::DOBJECT),
3450                                   subtype, Hist_data::ALL);
3451       if (data->get_status () != Hist_data::SUCCESS)
3452         return DbeView::status_str (DbeView::DBEVIEW_NO_DATA); // no strdup()
3453
3454       cd = new er_print_histogram (dbev, data, mlist, MODE_LIST,
3455                                    dbev->get_limit (),
3456                                    mlist->get_sort_name (), NULL, true, true);
3457       break;
3458     case DSP_DLAYOUT:
3459       {
3460         data = dbev->get_hist_data (mlist, Histable::DOBJECT, 0, Hist_data::LAYOUT);
3461         if (data->get_status () != Hist_data::SUCCESS)
3462           return DbeView::status_str (DbeView::DBEVIEW_NO_DATA); // no strdup()
3463         cd = new er_print_histogram (dbev, data, mlist, MODE_ANNOTATED,
3464                                      dbev->get_thresh_dis (),
3465                                      mlist->get_sort_name (), NULL, true, true);
3466         break;
3467       }
3468
3469       // source and disassembly
3470     case DSP_SOURCE:
3471     case DSP_DISASM:
3472     case DSP_SOURCE_V2:
3473     case DSP_DISASM_V2:
3474       if (dbev->sel_obj == NULL)
3475         return NULL;
3476       current_obj = dbev->sel_obj->convertto (Histable::FUNCTION);
3477       if (current_obj->get_type () != Histable::FUNCTION)
3478         return dbe_strdup (GTXT ("Not a real function; no source or disassembly available."));
3479       func = (Function*) current_obj->convertto (Histable::FUNCTION);
3480       if (func->flags & FUNC_FLAG_SIMULATED)
3481         return dbe_strdup (GTXT ("Not a real function; no source or disassembly available."));
3482       if (func->get_name () == NULL)
3483         return dbe_strdup (GTXT ("Source location not recorded in experiment"));
3484       module = func->module;
3485       if (module == NULL || module->get_name () == NULL)
3486         return dbe_strdup (GTXT ("Object name not recorded in experiment"));
3487       ix = module->loadobject->seg_idx;
3488       if (dbev->get_lo_expand (ix) == LIBEX_HIDE)
3489         return dbe_strdup (GTXT ("No source or disassembly available for hidden object"));
3490       cd = new er_print_histogram (dbev, dbev->func_data, mlist, MODE_ANNOTATED,
3491                                    type == DSP_DISASM || type == DSP_DISASM_V2,
3492                                    mlist->get_sort_name (),
3493                                    func, false, false);
3494       break;
3495
3496       // callers-callees
3497     case DSP_SELF:
3498     case DSP_CALLER:
3499     case DSP_CALLEE:
3500       if (dbev->sel_obj == NULL)
3501         return NULL;
3502       current_obj = dbev->sel_obj->convertto (Histable::FUNCTION);
3503       cd = new er_print_histogram (dbev, dbev->func_data, mlist, MODE_GPROF, 1,
3504                                    mlist->get_sort_name (), current_obj,
3505                                    false, false);
3506       break;
3507
3508       // statistics; this won't use the metric list copied above, so delete it
3509     case DSP_STATIS:
3510       cd = new er_print_experiment (dbev, 0, dbeSession->nexps () - 1,
3511                                     true, true, true, true, false);
3512       delete mlist;
3513       break;
3514     case DSP_EXP:
3515       cd = new er_print_experiment (dbev, 0, dbeSession->nexps () - 1,
3516                                     true, true, false, false, false);
3517       delete mlist;
3518       break;
3519     case DSP_LEAKLIST:
3520       cd = new er_print_leaklist (dbev, true, true, dbev->get_limit ());
3521       delete mlist;
3522       break;
3523     case DSP_HEAPCALLSTACK:
3524       cd = new er_print_heapactivity (dbev, Histable::HEAPCALLSTACK, false,
3525                                       dbev->get_limit ());
3526       delete mlist;
3527       break;
3528     case DSP_IOACTIVITY:
3529       cd = new er_print_ioactivity (dbev, Histable::IOACTFILE, false,
3530                                     dbev->get_limit ());
3531       delete mlist;
3532       break;
3533     case DSP_IOVFD:
3534       cd = new er_print_ioactivity (dbev, Histable::IOACTVFD, false,
3535                                     dbev->get_limit ());
3536       delete mlist;
3537       break;
3538
3539       // the io call stack
3540     case DSP_IOCALLSTACK:
3541       cd = new er_print_ioactivity (dbev, Histable::IOCALLSTACK, false,
3542                                     dbev->get_limit ());
3543       delete mlist;
3544       break;
3545
3546       // some unknown panel -- return an error string
3547     default:
3548       delete mlist;
3549       return dbe_strdup (GTXT ("Print not available"));
3550     }
3551
3552   // Start printing
3553   char *buf = NULL;
3554
3555   // first open the file/device/whatever
3556   if (cd->open (&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 *
3594 dbeSetPrintLimit (int dbevindex, int limit)
3595 {
3596   DbeView *dbev = dbeSession->getView (dbevindex);
3597   if (dbev == NULL)
3598     abort ();
3599   return (dbev->set_limit (limit));
3600 }
3601
3602 // get limit for print data
3603 int
3604 dbeGetPrintLimit (int dbevindex)
3605 {
3606   DbeView *dbev = dbeSession->getView (dbevindex);
3607   if (dbev == NULL)
3608     abort ();
3609   int limit = dbev->get_limit ();
3610   return limit;
3611 }
3612
3613 // set printmode for data
3614 char *
3615 dbeSetPrintMode (int dbevindex, char * pmode)
3616 {
3617   DbeView *dbev = dbeSession->getView (dbevindex);
3618   if (dbev == NULL)
3619     abort ();
3620   char *r = dbev->set_printmode (pmode);
3621   return r;
3622 }
3623
3624 // get printmode for data
3625 int
3626 dbeGetPrintMode (int dbevindex)
3627 {
3628   DbeView *dbev = dbeSession->getView (dbevindex);
3629   if (dbev == NULL)
3630     abort ();
3631   return (dbev->get_printmode ());
3632 }
3633
3634 // get printmode for data
3635 char *
3636 dbeGetPrintModeString (int dbevindex)
3637 {
3638   DbeView *dbev = dbeSession->getView (dbevindex);
3639   if (dbev == NULL)
3640     abort ();
3641   return ( dbev->get_printmode_str ());
3642 }
3643
3644 // get print delimiter for csv data
3645 char
3646 dbeGetPrintDelim (int dbevindex)
3647 {
3648   DbeView *dbev = dbeSession->getView (dbevindex);
3649   if (dbev == NULL)
3650     abort ();
3651   return (dbev->get_printdelimiter ());
3652 }
3653
3654 // Set Source/Object/Load-Object file names
3655 static void
3656 set_file_names (Function *func, char *names[3])
3657 {
3658   Module *module = func->module;
3659   LoadObject *loadobject = module->loadobject;
3660   if (loadobject == NULL)
3661     loadobject = dbeSession->get_Unknown_LoadObject ();
3662   free (names[0]);
3663   free (names[1]);
3664   free (names[2]);
3665   SourceFile *sf = func->getDefSrc ();
3666   char *src_name = sf->dbeFile->get_location_info ();
3667   DbeFile *df = module->dbeFile;
3668   if (df == NULL || (df->filetype & DbeFile::F_JAVACLASS) == 0)
3669     df = module->loadobject->dbeFile;
3670   char *lo_name = df->get_location_info ();
3671   char *dot_o_name = lo_name;
3672   if (module->dot_o_file)
3673     dot_o_name = module->dot_o_file->dbeFile->get_location_info ();
3674   names[0] = dbe_sprintf (NTXT ("%s: %s"), GTXT ("Source File"), src_name);
3675   names[1] = dbe_sprintf (NTXT ("%s: %s"), GTXT ("Object File"), dot_o_name);
3676   names[2] = dbe_sprintf (NTXT ("%s: %s"), GTXT ("Load Object"), lo_name);
3677 }
3678
3679 // dbeSetFuncData
3680 //      Master function to generate all Tab data for the analyzer
3681 //      Returns the index of the selected item in the specified list
3682 //
3683 // After calling it to set up, the Analyzer calls dbeGetFuncList
3684 //      to format the generated data and return the table
3685 //      Most of the data is destined for a JTable
3686 //
3687 int
3688 dbeSetFuncData (int dbevindex, Obj sel_obj, int type, int subtype)
3689 {
3690   MetricList *_mlist;
3691   Histable *org_obj;
3692   Hist_data *data = NULL;
3693   int index, sel_index;
3694   Function *func;
3695   char *name;
3696   int ix;
3697
3698   DbeView *dbev = dbeSession->getView (dbevindex);
3699   sel_index = -1;
3700   dbev->resetOmpDisMode ();
3701   dbev->error_msg = dbev->warning_msg = NULL;
3702
3703   // get metric list, make a compact duplicate
3704   _mlist = dbev->get_metric_list (MET_NORMAL);
3705   MetricList *mlist = new MetricList (_mlist);
3706
3707   // Remove old function/obj list data & Get new function/obj list data
3708   org_obj = (Histable *) sel_obj;
3709
3710   // Figure out which "function" data is being asked for, i.e.,
3711   //    which of the analyzer displays is asking for data
3712   switch (type)
3713     {
3714       // the various tables: functions, lines, PCs, DataObjects, IndexObjects
3715     case DSP_FUNCTION:
3716     case DSP_LINE:
3717     case DSP_PC:
3718     case DSP_DATAOBJ:
3719     case DSP_MEMOBJ:
3720     case DSP_INDXOBJ:
3721       switch (type)
3722         {
3723         case DSP_FUNCTION:
3724           if (dbev->func_data)
3725             delete dbev->func_data;
3726           dbev->func_data = data = dbev->get_hist_data (mlist,
3727                                    Histable::FUNCTION, subtype, Hist_data::ALL);
3728           break;
3729         case DSP_LINE:
3730           if (dbev->line_data)
3731             delete dbev->line_data;
3732           dbev->line_data = data = dbev->get_hist_data (mlist,
3733                                        Histable::LINE, subtype, Hist_data::ALL);
3734           break;
3735         case DSP_PC:
3736           if (dbev->pc_data)
3737             delete dbev->pc_data;
3738           dbev->pc_data = data = dbev->get_hist_data (mlist,
3739                                       Histable::INSTR, subtype, Hist_data::ALL);
3740           break;
3741         case DSP_DATAOBJ:
3742           if (dbev->dobj_data)
3743             delete dbev->dobj_data;
3744           mlist = dbev->get_metric_list (MET_DATA);
3745           dbev->dobj_data = data = dbev->get_hist_data (mlist,
3746                                     Histable::DOBJECT, subtype, Hist_data::ALL);
3747           break;
3748         case DSP_MEMOBJ:
3749           mlist = dbev->get_metric_list (MET_DATA);
3750           data = dbev->get_hist_data (mlist, Histable::MEMOBJ, subtype,
3751                                       Hist_data::ALL);
3752           dbev->indx_data->store (subtype, data);
3753           break;
3754         case DSP_INDXOBJ:
3755           mlist = dbev->get_metric_list (MET_INDX);
3756           data = dbev->get_hist_data (mlist, Histable::INDEXOBJ, subtype,
3757                                       Hist_data::ALL);
3758           dbev->indx_data->store (subtype, data);
3759           break;
3760         default:
3761           break;
3762         }
3763
3764       // Set the selection of row item
3765       if (data->get_status () == Hist_data::SUCCESS)
3766         {
3767           // otherwise, look for it
3768           sel_index = -1;
3769           if (org_obj)
3770             {
3771               Hist_data::HistItem *hi;
3772               Vec_loop (Hist_data::HistItem*, data->get_hist_items (), index, hi)
3773               {
3774                 if (hi->obj == org_obj)
3775                   {
3776                     sel_index = index;
3777                     break;
3778                   }
3779               }
3780               if (sel_index == -1 && (type == DSP_LINE || type == DSP_PC))
3781                 {
3782                   Vec_loop (Hist_data::HistItem*, data->get_hist_items (), index, hi)
3783                   {
3784                     name = hi->obj->get_name ();
3785                     if (strcmp (name, NTXT ("<Total>")) &&
3786                         strcmp (name, GTXT ("<Unknown>")))
3787                       {
3788                         int done = 0;
3789                         switch (type)
3790                           {
3791                           case DSP_LINE:
3792                             if (org_obj->convertto (Histable::FUNCTION)
3793                                      == hi->obj->convertto (Histable::FUNCTION))
3794                               {
3795                                 sel_index = index;
3796                                 done = 1;
3797                               }
3798                             break;
3799                           case DSP_PC:
3800                             if (hi->obj->convertto (Histable::FUNCTION)
3801                                 == org_obj->convertto (Histable::FUNCTION)
3802                                 && ((DbeLine*) hi->obj->convertto (Histable::LINE))->lineno
3803                                 == ((DbeLine*) org_obj->convertto (Histable::LINE))->lineno)
3804                               {
3805                                 sel_index = index;
3806                                 done = 1;
3807                               }
3808                             break;
3809                           }
3810                         if (done)
3811                           break;
3812                       }
3813                   }
3814                 }
3815               if (sel_index == -1 && type == DSP_PC)
3816                 {
3817                   Vec_loop (Hist_data::HistItem*, data->get_hist_items (), index, hi)
3818                   {
3819                     name = hi->obj->get_name ();
3820                     if (strcmp (name, NTXT ("<Total>")) &&
3821                         strcmp (name, GTXT ("<Unknown>")))
3822                       {
3823                         int done = 0;
3824                         if (hi->obj->convertto (Histable::FUNCTION) ==
3825                             org_obj->convertto (Histable::FUNCTION))
3826                           {
3827                             sel_index = index;
3828                             done = 1;
3829                           }
3830                         if (done)
3831                           break;
3832                       }
3833                   }
3834                 }
3835             }
3836           if (sel_index == -1)
3837             {
3838               Hist_data::HistItem *hi;
3839               Vec_loop (Hist_data::HistItem*, data->get_hist_items (), index, hi)
3840               {
3841                 name = hi->obj->get_name ();
3842                 if (strcmp (name, NTXT ("<Total>")) &&
3843                     strcmp (name, GTXT ("<Unknown>")))
3844                   {
3845                     sel_index = index;
3846                     break;
3847                   }
3848               }
3849             }
3850         }
3851       else
3852         dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA);
3853       return sel_index;
3854       // the end of the code for the regular tables
3855
3856       // Data Layout
3857     case DSP_DLAYOUT:
3858       if (dbev->dlay_data)
3859         delete dbev->dlay_data;
3860       dbev->marks->reset ();
3861       mlist = dbev->get_metric_list (MET_DATA);
3862
3863       // initial dobj list ...
3864       data = dbev->get_hist_data (mlist, Histable::DOBJECT, subtype,
3865                                   Hist_data::LAYOUT);
3866       // .. provides metric data for layout
3867       dbev->dlay_data = data = dbev->get_data_space ()->get_layout_data (data,
3868                                           dbev->marks, dbev->get_thresh_dis ());
3869       if (data->get_status () != Hist_data::SUCCESS)
3870         dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA);
3871       return sel_index;
3872
3873       // Source or disassembly
3874     case DSP_SOURCE_V2:
3875     case DSP_DISASM_V2:
3876     case DSP_SOURCE:
3877     case DSP_DISASM:
3878       {
3879         if (org_obj == NULL)
3880           {
3881             dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_SEL_OBJ);
3882             return sel_index;
3883           }
3884         if (org_obj->get_type () != Histable::FUNCTION)
3885           {
3886             dbev->error_msg = dbe_strdup (
3887              GTXT ("Not a real function; no source or disassembly available."));
3888             return sel_index;
3889           }
3890         func = (Function *) org_obj;
3891         if (func->flags & FUNC_FLAG_SIMULATED)
3892           {
3893             dbev->error_msg = dbe_strdup (
3894              GTXT ("Not a real function; no source or disassembly available."));
3895             return sel_index;
3896           }
3897         if (func->get_name () == NULL)
3898           {
3899             dbev->error_msg = dbe_strdup (
3900                            GTXT ("Source location not recorded in experiment"));
3901             return sel_index;
3902           }
3903         Module *module = func->module;
3904         if ((module == NULL) || (module->get_name () == NULL))
3905           {
3906             dbev->error_msg = dbe_strdup (
3907                                GTXT ("Object name not recorded in experiment"));
3908             return sel_index;
3909           }
3910         ix = module->loadobject->seg_idx;
3911         if (dbev->get_lo_expand (ix) == LIBEX_HIDE)
3912           {
3913             dbev->error_msg = dbe_strdup (
3914                  GTXT ("No source or disassembly available for hidden object"));
3915             return sel_index;
3916           }
3917
3918         if ((type == DSP_DISASM || type == DSP_DISASM_V2)
3919              && dbev->get_view_mode () == VMODE_USER
3920             && dbeSession->is_omp_available ())
3921           dbev->setOmpDisMode ();
3922
3923         dbev->marks->reset ();
3924         SourceFile *srcContext = NULL;
3925         switch (dbev->sel_obj->get_type ())
3926           {
3927           case Histable::FUNCTION:
3928             {
3929               Function *f = (Function *) dbev->sel_obj;
3930               srcContext = f->getDefSrc ();
3931               dbev->sel_binctx = f->module;
3932               break;
3933             }
3934           case Histable::LINE:
3935             {
3936               DbeLine *dl = (DbeLine *) dbev->sel_obj;
3937               srcContext = dl->sourceFile;
3938               Function *f = dl->func;
3939               if (f)
3940                 dbev->sel_binctx = f;
3941               break;
3942             }
3943           case Histable::INSTR:
3944             {
3945               Function *f = (Function *) dbev->sel_obj->convertto (Histable::FUNCTION);
3946               if (f)
3947                 {
3948                   dbev->sel_binctx = f;
3949                   srcContext = f->getDefSrc ();
3950                 }
3951               break;
3952             }
3953           default:
3954             break;
3955           }
3956         mlist = dbev->get_metric_list (MET_SRCDIS);
3957
3958         // for source and disassembly the name needs to be invisible,
3959         //      but that's handled in the module code
3960         if (type == DSP_SOURCE)
3961           {
3962             if (dbev->src_data)
3963               delete dbev->src_data;
3964
3965             // func_data computation needed for get_totals
3966             if (dbev->func_data == NULL)
3967               dbev->func_data = data = dbev->get_hist_data (mlist,
3968                                    Histable::FUNCTION, subtype, Hist_data::ALL);
3969             dbev->marks2dsrc->reset ();
3970             dbev->marks2dsrc_inc->reset ();
3971             data = dbev->src_data = module->get_data (dbev, mlist,
3972                           Histable::LINE, dbev->func_data->get_totals ()->value,
3973                           srcContext, func, dbev->marks,
3974                           dbev->get_thresh_src (), dbev->get_src_compcom (),
3975                           dbev->get_src_visible (), dbev->get_hex_visible (),
3976                           false, false, dbev->marks2dsrc, dbev->marks2dsrc_inc);
3977             set_file_names (func, dbev->names_src);
3978             if (srcContext)
3979               {
3980                 free (dbev->names_src[0]);
3981                 dbev->names_src[0] = dbe_sprintf (GTXT ("Source File: %s"),
3982                                      srcContext->dbeFile->get_location_info ());
3983               }
3984             Obj obj = (Obj) func->convertto (Histable::LINE, srcContext);
3985             sel_index = dbeGetSelIndex (dbevindex, obj, type, subtype);
3986           }
3987         else
3988           { /* type == DSP_DISASM */
3989             if (dbev->dis_data)
3990               delete dbev->dis_data;
3991
3992             // func_data computation needed for get_totals
3993             if (dbev->func_data == NULL)
3994               dbev->func_data = data = dbev->get_hist_data (mlist,
3995                                   Histable::FUNCTION, subtype, Hist_data::ALL);
3996             dbev->marks2ddis->reset ();
3997             dbev->marks2ddis_inc->reset ();
3998             data = dbev->dis_data = module->get_data (dbev, mlist,
3999                          Histable::INSTR, dbev->func_data->get_totals ()->value,
4000                          srcContext, func, dbev->marks, dbev->get_thresh_dis (),
4001                          dbev->get_dis_compcom (), dbev->get_src_visible (),
4002                          dbev->get_hex_visible (), dbev->get_func_scope (),
4003                          false, dbev->marks2ddis, dbev->marks2ddis_inc);
4004             set_file_names (func, dbev->names_dis);
4005             if (srcContext)
4006               {
4007                 free (dbev->names_dis[0]);
4008                 dbev->names_dis[0] = dbe_sprintf (GTXT ("Source File: %s"),
4009                                     srcContext->dbeFile->get_location_info ());
4010               }
4011             Obj obj = (Obj) func->convertto (Histable::INSTR);
4012             sel_index = dbeGetSelIndex (dbevindex, obj, type, subtype);
4013           }
4014         return sel_index;
4015       }
4016
4017       // the three cases for caller-callee
4018     case DSP_SELF:
4019     case DSP_CALLER:
4020     case DSP_CALLEE:
4021       if (org_obj == NULL)
4022         {
4023           dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_SEL_OBJ);
4024           return sel_index;
4025         }
4026
4027       // Caller data
4028       if (dbev->callers)
4029         delete dbev->callers;
4030       mlist = dbev->get_metric_list (MET_CALL);
4031       dbev->callers = dbev->get_hist_data (mlist, Histable::FUNCTION, subtype,
4032                                            Hist_data::CALLERS, org_obj);
4033       if (dbev->callers->get_status () != Hist_data::SUCCESS)
4034         {
4035           dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA);
4036           return sel_index;
4037         }
4038
4039       // Callee data
4040       if (dbev->callees)
4041         delete dbev->callees;
4042       dbev->callees = dbev->get_hist_data (mlist, Histable::FUNCTION, subtype,
4043                                            Hist_data::CALLEES, org_obj);
4044       if (dbev->callees->get_status () != Hist_data::SUCCESS)
4045         {
4046           dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA);
4047           return sel_index;
4048         }
4049
4050       // Center Function item
4051       if (dbev->fitem_data)
4052         delete dbev->fitem_data;
4053       dbev->fitem_data = dbev->get_hist_data (mlist, Histable::FUNCTION, subtype,
4054                                               Hist_data::SELF, org_obj);
4055       if (dbev->fitem_data->get_status () != Hist_data::SUCCESS)
4056         {
4057           dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA);
4058           return sel_index;
4059         }
4060       return sel_index;
4061     default:
4062       abort ();
4063     }
4064   return sel_index;
4065 }
4066
4067 Vector<void*>*
4068 dbeGetTotals (int dbevindex, int dsptype, int subtype)
4069 {
4070   DbeView *dbev = dbeSession->getView (dbevindex);
4071   MetricList *mlist = dbev->get_metric_list (dsptype, subtype);
4072   Hist_data *data = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
4073                                          Hist_data::ALL);
4074   Hist_data::HistItem *totals = data->get_totals ();
4075   Vector<void*> *tbl = new Vector<void*>(mlist->size ());
4076   for (long i = 0, sz = mlist->size (); i < sz; i++)
4077     {
4078       Metric *m = mlist->get (i);
4079       switch (m->get_vtype ())
4080         {
4081         case VT_DOUBLE:
4082           {
4083             Vector<double> *lst = new Vector<double>(1);
4084             lst->append (totals->value[i].d);
4085             tbl->append (lst);
4086             break;
4087           }
4088         case VT_INT:
4089           {
4090             Vector<int> *lst = new Vector<int>(1);
4091             lst->append (totals->value[i].i);
4092             tbl->append (lst);
4093             break;
4094           }
4095         case VT_LLONG:
4096         case VT_ULLONG:
4097         case VT_ADDRESS:
4098           {
4099             Vector<long long> *lst = new Vector<long long>(1);
4100             lst->append (totals->value[i].ll);
4101             tbl->append (lst);
4102             break;
4103           }
4104         case VT_LABEL:
4105           {
4106             Vector<char *> *lst = new Vector<char *>(1);
4107             Histable::NameFormat nfmt = dbev->get_name_format ();
4108             lst->append (dbe_strdup (totals->obj->get_name (nfmt)));
4109             tbl->append (lst);
4110             break;
4111           }
4112         default:
4113           abort ();
4114         }
4115     }
4116   Vector<void*> *res = new Vector<void*>(2);
4117   res->append (dbeGetMetricList (mlist));
4118   res->append (tbl);
4119   return res;
4120 }
4121
4122 Vector<void*>*
4123 dbeGetHotMarks (int dbevindex, int type)
4124 {
4125   Vector<void*>* table = new Vector<void*>(2);
4126   Vector<int>* table0 = new Vector<int> ();
4127   Vector<int>* table1 = new Vector<int> ();
4128   DbeView *dbev = dbeSession->getView (dbevindex);
4129   if (dbev == NULL)
4130     return NULL;
4131
4132   switch (type)
4133     {
4134     case DSP_SOURCE:
4135     case DSP_SOURCE_V2:
4136       for (int i = 0; i < dbev->marks2dsrc->size (); i++)
4137         {
4138           table0->append (dbev->marks2dsrc->fetch (i).index1);
4139           table1->append (dbev->marks2dsrc->fetch (i).index2);
4140         }
4141       break;
4142     case DSP_DISASM:
4143     case DSP_DISASM_V2:
4144       for (int i = 0; i < dbev->marks2ddis->size (); i++)
4145         {
4146           table0->append (dbev->marks2ddis->fetch (i).index1);
4147           table1->append (dbev->marks2ddis->fetch (i).index2);
4148         }
4149       break;
4150     default:
4151       break;
4152     }
4153   table->store (0, table0);
4154   table->store (1, table1);
4155   return table;
4156 }
4157
4158 Vector<void*>*
4159 dbeGetHotMarksInc (int dbevindex, int type)
4160 {
4161   Vector<void*>* table = new Vector<void*>(2);
4162   Vector<int>* table0 = new Vector<int> ();
4163   Vector<int>* table1 = new Vector<int> ();
4164   DbeView *dbev = dbeSession->getView (dbevindex);
4165   if (dbev == NULL)
4166     return NULL;
4167
4168   switch (type)
4169     {
4170     case DSP_SOURCE:
4171     case DSP_SOURCE_V2:
4172       for (int i = 0; i < dbev->marks2dsrc_inc->size (); i++)
4173         {
4174           table0->append (dbev->marks2dsrc_inc->fetch (i).index1);
4175           table1->append (dbev->marks2dsrc_inc->fetch (i).index2);
4176         }
4177       break;
4178     case DSP_DISASM:
4179     case DSP_DISASM_V2:
4180       for (int i = 0; i < dbev->marks2ddis_inc->size (); i++)
4181         {
4182           table0->append (dbev->marks2ddis_inc->fetch (i).index1);
4183           table1->append (dbev->marks2ddis_inc->fetch (i).index2);
4184         }
4185       break;
4186     default:
4187       break;
4188     }
4189   table->store (0, table0);
4190   table->store (1, table1);
4191   return table;
4192 }
4193
4194 Vector<void*>*
4195 dbeGetSummaryHotMarks (int dbevindex, Vector<Obj> *sel_objs, int type)
4196 {
4197   Vector<void*>* table = new Vector<void*>(2);
4198   Vector<int>* table0 = new Vector<int> ();
4199   Vector<int>* table1 = new Vector<int> ();
4200   DbeView *dbev = dbeSession->getView (dbevindex);
4201   if (dbev == NULL)
4202     return NULL;
4203   if (sel_objs == NULL || sel_objs->size () == 0)
4204     return NULL;
4205
4206   Hist_data *data;
4207   Vector<int_pair_t> *marks2d;
4208   Vector<int_pair_t>* marks2d_inc;
4209   switch (type)
4210     {
4211     case DSP_SOURCE:
4212     case DSP_SOURCE_V2:
4213       data = dbev->src_data;
4214       marks2d = dbev->marks2dsrc;
4215       marks2d_inc = dbev->marks2dsrc_inc;
4216       break;
4217     case DSP_DISASM:
4218     case DSP_DISASM_V2:
4219       data = dbev->dis_data;
4220       marks2d = dbev->marks2ddis;
4221       marks2d_inc = dbev->marks2ddis_inc;
4222       break;
4223     default:
4224       data = NULL;
4225       marks2d = NULL;
4226       marks2d_inc = NULL;
4227       break;
4228     }
4229   if (data == NULL || data->get_status () != Hist_data::SUCCESS
4230       || marks2d_inc == NULL || marks2d == NULL)
4231     return NULL;
4232
4233   MetricList *orig_mlist = data->get_metric_list ();
4234   MetricList *prop_mlist = new MetricList (dbev->get_metric_ref (MET_NORMAL));
4235   if (prop_mlist && dbev->comparingExperiments ())
4236     prop_mlist = dbev->get_compare_mlist (prop_mlist, 0);
4237   Metric *mitem;
4238   int index, index2;
4239   index2 = 0;
4240   Vec_loop (Metric*, prop_mlist->get_items (), index, mitem)
4241   {
4242     if (mitem->get_subtype () == Metric::STATIC)
4243       continue;
4244
4245     for (int i = 0; i < marks2d_inc->size (); i++)
4246       {
4247         int found = 0;
4248         for (int j = 0; j < sel_objs->size (); j++)
4249           {
4250             int sel_index = (int) sel_objs->fetch (j);
4251             int marked_index = marks2d_inc->fetch (i).index1;
4252             if (sel_index == marked_index)
4253               {
4254                 found = 1;
4255                 break;
4256               }
4257           }
4258         if (!found)
4259           continue;
4260         int mindex = marks2d_inc->fetch (i).index2;
4261         Metric *orig_metric = orig_mlist->get_items ()->fetch (mindex);
4262         if (orig_metric->get_id () == mitem->get_id ()
4263             && mitem->get_subtype () == Metric::INCLUSIVE)
4264           {
4265             table0->append (index2);
4266             table1->append (1);
4267           }
4268       }
4269
4270     for (int i = 0; i < marks2d->size (); i++)
4271       {
4272         int found = 0;
4273         for (int j = 0; j < sel_objs->size (); j++)
4274           {
4275             int sel_index = (int) sel_objs->fetch (j);
4276             int marked_index = marks2d->fetch (i).index1;
4277             if (sel_index == marked_index)
4278               {
4279                 found = 1;
4280                 break;
4281               }
4282           }
4283         if (!found)
4284           continue;
4285         int mindex = marks2d->fetch (i).index2;
4286         Metric *orig_metric = orig_mlist->get_items ()->fetch (mindex);
4287         if (orig_metric->get_id () == mitem->get_id ()
4288             && mitem->get_subtype () == Metric::EXCLUSIVE)
4289           {
4290             table0->append (index2);
4291             table1->append (0);
4292           }
4293       }
4294     if (!(mitem->get_subtype () == Metric::EXCLUSIVE
4295           || mitem->get_subtype () == Metric::DATASPACE))
4296       index2++;
4297   }
4298   table->store (0, table0);
4299   table->store (1, table1);
4300   return table;
4301 }
4302
4303 // Get a vector of function ids of data(begin, begin + length - 1)
4304 // Currently only support source/disassembly view
4305 Vector<uint64_t>*
4306 dbeGetFuncId (int dbevindex, int type, int begin, int length)
4307 {
4308   Vector<uint64_t>* table = new Vector<uint64_t > ();
4309   DbeView *dbev = dbeSession->getView (dbevindex);
4310   if (dbev == NULL)
4311     abort ();
4312
4313   Hist_data *data;
4314   Function* given_func = NULL;
4315   switch (type)
4316     {
4317     case DSP_SOURCE:
4318     case DSP_SOURCE_V2:
4319       data = dbev->src_data;
4320       break;
4321     case DSP_DISASM:
4322     case DSP_DISASM_V2:
4323       data = dbev->dis_data;
4324       break;
4325     default:
4326       data = NULL;
4327       abort ();
4328     }
4329
4330   if (data == NULL || data->get_status () != Hist_data::SUCCESS)
4331     return NULL;
4332
4333   if (begin < 0 || begin + length > data->size ())
4334     return NULL;
4335
4336   switch (type)
4337     {
4338     case DSP_SOURCE:
4339     case DSP_SOURCE_V2:
4340     case DSP_DISASM:
4341     case DSP_DISASM_V2:
4342       {
4343         for (int i = begin; i < begin + length; i++)
4344           {
4345             given_func = NULL;
4346             Histable * sel_obj = data->fetch (i)->obj;
4347             if (sel_obj != NULL)
4348               given_func = (Function*) (sel_obj)->convertto (Histable::FUNCTION, (Histable*) dbev);
4349             if (given_func == NULL)
4350               table->append (0);
4351             else
4352               table->append (given_func->id);
4353           }
4354       }
4355       break;
4356     default:
4357       abort ();
4358     }
4359   return table;
4360 }
4361
4362 Vector<void*>*
4363 dbeGetFuncCallerInfo (int dbevindex, int type, Vector<int>* idxs, int groupId)
4364 {
4365   Vector<void*>* data = new Vector<void*>();
4366   if (type == DSP_SOURCE_V2 || type == DSP_DISASM_V2)
4367     {
4368       Obj sel_func = dbeGetSelObj (dbevindex, DSP_FUNCTION, 0);
4369       if (sel_func == 0)
4370         return data;
4371       Vector<Obj> * cmpObjs = dbeGetComparableObjsV2 (dbevindex, sel_func, type);
4372       if (cmpObjs == NULL)
4373         return data;
4374       DbeView *dbev = dbeSession->getView (dbevindex);
4375       int mtype = MET_COMMON | COMPARE_BIT | ((groupId + 1) << GROUP_ID_SHIFT);
4376       MetricList *mlist = dbev->get_metric_list ((MetricType) (mtype & MTYPE_MASK),
4377                                                  (mtype & COMPARE_BIT) != 0,
4378                                                  mtype >> GROUP_ID_SHIFT);
4379       Histable *selObj = (Histable *) cmpObjs->fetch (groupId);
4380       int subtype = 0;
4381       Hist_data *hist_data = dbev->get_data (mlist, selObj, type, subtype);
4382       if (hist_data == NULL)
4383         return data;
4384     }
4385   for (int i = 0; i < idxs->size (); i++)
4386     data->append (dbeGetFuncCallerInfoById (dbevindex, type, idxs->fetch (i)));
4387   return data;
4388 }
4389
4390 //
4391 // Get Table of Caller info:
4392 // param: idx -- selected AT_FUNC row
4393 // return: callsite_id, callsite_name (function: file: line)
4394 Vector<void*>*
4395 dbeGetFuncCallerInfoById (int dbevindex, int type, int idx)
4396 {
4397   Vector<void*>* table = new Vector<void*>(3);
4398   Vector<uint64_t>* table0 = new Vector<uint64_t> ();
4399   Vector<int>* table1 = new Vector<int> ();
4400   Vector<char*>* table2 = new Vector<char*>();
4401
4402   DbeView *dbev = dbeSession->getView (dbevindex);
4403   if (dbev == NULL)
4404     abort ();
4405   Hist_data *data;
4406   Function* given_func = NULL;
4407   Vector<Histable*> *instr_info = NULL;
4408   switch (type)
4409     {
4410     case DSP_SOURCE:
4411     case DSP_SOURCE_V2:
4412       data = dbev->src_data;
4413       break;
4414     case DSP_DISASM:
4415     case DSP_DISASM_V2:
4416       data = dbev->dis_data;
4417       break;
4418     default:
4419       data = NULL;
4420       abort ();
4421     }
4422   if (data == NULL || data->get_status () != Hist_data::SUCCESS)
4423     return NULL;
4424
4425   if (idx < 0 || idx >= data->size ())
4426     return NULL;
4427   switch (type)
4428     {
4429     case DSP_SOURCE:
4430     case DSP_SOURCE_V2:
4431     case DSP_DISASM:
4432     case DSP_DISASM_V2:
4433       {
4434         Histable * sel_obj = data->fetch (idx)->obj;
4435         if (sel_obj == NULL)
4436           return NULL;
4437         given_func = (Function*) (sel_obj)->convertto (Histable::FUNCTION, (Histable*) dbev);
4438         if (given_func == NULL)
4439           return NULL;
4440         PathTree * ptree = dbev->get_path_tree ();
4441         if (ptree == NULL)
4442           return NULL;
4443         instr_info = ptree->get_clr_instr (given_func);
4444         DefaultMap<uint64_t, int> * line_seen = new DefaultMap<uint64_t, int>();
4445         for (int j = 0; j < ((Vector<Histable*>*)instr_info)->size (); j++)
4446           {
4447             Histable *instr = ((Vector<Histable*>*)instr_info)->fetch (j);
4448             Function *cur_func = NULL;
4449             if (instr->get_type () == Histable::INSTR)
4450               cur_func = ((DbeInstr*) instr)->func;
4451             else if (instr->get_type () == Histable::LINE)
4452               cur_func = ((DbeLine*) instr)->func;
4453             if (cur_func == NULL || (cur_func->flags & FUNC_FLAG_SIMULATED))
4454                 continue; // skip functions like <Total>
4455             Histable* line;
4456             switch (type)
4457               {
4458               case DSP_SOURCE:
4459               case DSP_SOURCE_V2:
4460                 if (cur_func != NULL)
4461                   {
4462                     SourceFile *sourceFile = cur_func->getDefSrc ();
4463                     if (sourceFile == NULL ||
4464                         (sourceFile->flags & SOURCE_FLAG_UNKNOWN) != 0)
4465                       continue; // skip functions like <Function: %s, instructions without line numbers>
4466                   }
4467                 line = instr->convertto (Histable::LINE, NULL);
4468                 break;
4469               case DSP_DISASM:
4470               case DSP_DISASM_V2:
4471                 line = instr->convertto (Histable::INSTR, NULL);
4472                 break;
4473               default:
4474                 abort ();
4475               }
4476             uint64_t func_id = cur_func->id;
4477             uint64_t line_id = instr->id;
4478             int is_null = 0;
4479             int line_no = -1;
4480             switch (type)
4481               {
4482               case DSP_SOURCE:
4483               case DSP_SOURCE_V2:
4484                 is_null = (((DbeLine*) line)->func == NULL) ? 1 : 0;
4485                 if (is_null)
4486                   ((DbeLine*) line)->func = cur_func;
4487                 line_no = ((DbeLine*) line)->lineno;
4488                 if (line_seen->get (line_id) == 0)
4489                   {
4490                     line_seen->put (line_id, 1);
4491                     table0->append (func_id);
4492                     table1->append (line_no);
4493                     Histable::NameFormat nfmt = dbev->get_name_format ();
4494                     table2->append (dbe_strdup (line->get_name (nfmt)));
4495                   }
4496                 if (is_null)
4497                   ((DbeLine*) line)->func = NULL;
4498                 break;
4499               case DSP_DISASM:
4500               case DSP_DISASM_V2:
4501                 is_null = (((DbeInstr*) line)->func == NULL) ? 1 : 0;
4502                 if (is_null)
4503                   ((DbeInstr*) line)->func = cur_func;
4504                 line_no = ((DbeInstr*) line)->addr;
4505                 if (line_seen->get (line_id) == 0)
4506                   {
4507                     line_seen->put (line_id, 1);
4508                     table0->append (func_id);
4509                     table1->append (line_no);
4510                     Histable::NameFormat nfmt = dbev->get_name_format ();
4511                     table2->append (dbe_strdup (line->get_name (nfmt)));
4512                   }
4513                 if (is_null)
4514                   ((DbeInstr*) line)->func = NULL;
4515                 break;
4516               default:
4517                 abort ();
4518               }
4519          }
4520         delete line_seen;
4521         delete instr_info;
4522       }
4523       break;
4524     default:
4525       abort ();
4526     }
4527   table->store (0, table0);
4528   table->store (1, table1);
4529   table->store (2, table2);
4530   return table;
4531 }
4532
4533 Vector<void*>*
4534 dbeGetFuncCalleeInfo (int dbevindex, int type, Vector<int>* idxs, int groupId)
4535 {
4536   Vector<void*>* data = new Vector<void*>();
4537   if (type == DSP_SOURCE_V2 || type == DSP_DISASM_V2)
4538     {
4539       Obj sel_func = dbeGetSelObj (dbevindex, DSP_FUNCTION, 0);
4540       if (sel_func == 0)
4541         return data;
4542       Vector<Obj> * cmpObjs = dbeGetComparableObjsV2 (dbevindex, sel_func, type);
4543       if (cmpObjs == NULL)
4544         return data;
4545       DbeView *dbev = dbeSession->getView (dbevindex);
4546       int mtype = MET_COMMON | COMPARE_BIT | ((groupId + 1) << GROUP_ID_SHIFT);
4547       MetricList *mlist = dbev->get_metric_list ((MetricType) (mtype & MTYPE_MASK),
4548                                                  (mtype & COMPARE_BIT) != 0,
4549                                                  mtype >> GROUP_ID_SHIFT);
4550       Histable *selObj = (Histable *) cmpObjs->fetch (groupId);
4551       int subtype = 0;
4552       Hist_data *hist_data = dbev->get_data (mlist, selObj, type, subtype);
4553       if (hist_data == NULL)
4554         return data;
4555     }
4556
4557   for (int i = 0; i < idxs->size (); i++)
4558     data->append (dbeGetFuncCalleeInfoById (dbevindex, type, idxs->fetch (i)));
4559   return data;
4560 }
4561
4562 //
4563 // Get Table of Callee info:
4564 // param: idx -- selected AT_FUNC row
4565 // return: callsite_row, callee_id, callee_name
4566 //
4567 Vector<void*>*
4568 dbeGetFuncCalleeInfoById (int dbevindex, int type, int idx)
4569 {
4570   Vector<void*>* table = new Vector<void*>(3);
4571   Vector<int>* table0 = new Vector<int>();
4572   Vector<uint64_t>* table1 = new Vector<uint64_t > ();
4573   Vector<char*>* table2 = new Vector<char*>();
4574   DbeView *dbev = dbeSession->getView (dbevindex);
4575   if (dbev == NULL)
4576     abort ();
4577   Hist_data *data;
4578   Function* given_func = NULL;
4579   Vector<Histable*> *instr_info = NULL;
4580   Vector<void*> *func_info = NULL;
4581
4582   switch (type)
4583     {
4584     case DSP_SOURCE:
4585     case DSP_SOURCE_V2:
4586       data = dbev->src_data;
4587       break;
4588     case DSP_DISASM:
4589     case DSP_DISASM_V2:
4590       data = dbev->dis_data;
4591       break;
4592     default:
4593       data = NULL;
4594       abort ();
4595     }
4596   if (data == NULL || data->get_status () != Hist_data::SUCCESS)
4597     return NULL;
4598   if (idx < 0 || idx >= data->size ())
4599     return NULL;
4600   switch (type)
4601     {
4602     case DSP_SOURCE:
4603     case DSP_SOURCE_V2:
4604     case DSP_DISASM:
4605     case DSP_DISASM_V2:
4606       {
4607         Histable * sel_obj = data->fetch (idx)->obj;
4608         if (sel_obj == NULL)
4609           return NULL;
4610         given_func = (Function*) (sel_obj)->convertto (Histable::FUNCTION, (Histable*) dbev);
4611         if (given_func == NULL)
4612           return NULL;
4613         PathTree * ptree = dbev->get_path_tree ();
4614         if (ptree == NULL)
4615           return NULL;
4616         Vector<Histable*> *instrs = NULL;
4617         Vector<void*> *callee_instrs = ptree->get_cle_instr (given_func, instrs);
4618         func_info = new Vector<void*>();
4619         instr_info = new Vector<Histable*>();
4620         for (long a = 0, sz_a = callee_instrs ? callee_instrs->size () : 0; a < sz_a; a++)
4621           {
4622             Vector<Histable*> *temp = ((Vector<Vector<Histable*>*>*)callee_instrs)->get (a);
4623             DefaultMap<Function*, int> * func_seen = new DefaultMap<Function*, int>();
4624             Histable* instr0 = (Histable*) instrs->fetch (a);
4625             for (long b = 0, sz_b = temp ? temp->size () : 0; b < sz_b; b++)
4626               {
4627                 Histable *instr = temp->get (b);
4628                 if (instr->get_type () == Histable::INSTR)
4629                   {
4630                     Function* func1 = ((DbeInstr *) instr)->func;
4631                     func_seen->put (func1, 1);
4632                   }
4633                 else if (instr->get_type () == Histable::LINE)
4634                   {
4635                     Function* func1 = ((DbeLine *) instr)->func;
4636                     func_seen->put (func1, 1);
4637                   }
4638               }
4639             Vector<Function*> *funcs = func_seen->keySet ();
4640             delete func_seen;
4641             if (funcs->size () > 0)
4642               {
4643                 instr_info->append (instr0);
4644                 func_info->append (funcs);
4645               }
4646           }
4647         delete instrs;
4648         destroy (callee_instrs);
4649
4650         DefaultMap<uint64_t, Vector<int>* > * instr_idxs = new DefaultMap<uint64_t, Vector<int>* >();
4651         DefaultMap<uint64_t, int> * func_idxs = new DefaultMap<uint64_t, int>();
4652         for (long j = 0, sz_j = instr_info ? instr_info->size () : 0; j < sz_j; j++)
4653           {
4654             Histable *instr = instr_info->get (j);
4655             Function *cur_func = NULL;
4656             if (instr->get_type () == Histable::INSTR)
4657               cur_func = ((DbeInstr*) instr)->func;
4658             else if (instr->get_type () == Histable::LINE)
4659               cur_func = ((DbeLine*) instr)->func;
4660             if (cur_func != NULL && (cur_func->flags & FUNC_FLAG_SIMULATED))
4661               continue; // skip functions like <Total>
4662             Histable* line;
4663             switch (type)
4664               {
4665               case DSP_SOURCE:
4666               case DSP_SOURCE_V2:
4667                 if (cur_func != NULL)
4668                   {
4669                     SourceFile *sourceFile = cur_func->getDefSrc ();
4670                     if (sourceFile == NULL ||
4671                         (sourceFile->flags & SOURCE_FLAG_UNKNOWN) != 0)
4672                       // skip functions like <Function: %s, instructions without line numbers>
4673                       continue;
4674                   }
4675                 line = instr->convertto (Histable::LINE, NULL);
4676                 if (type == DSP_SOURCE_V2)
4677                   line = dbev->get_compare_obj (line);
4678                 break;
4679               case DSP_DISASM:
4680               case DSP_DISASM_V2:
4681                 line = instr;
4682                 if (type == DSP_DISASM_V2)
4683                   line = dbev->get_compare_obj (line);
4684                 break;
4685               default:
4686                 abort ();
4687               }
4688             if (func_idxs->get (line->id) == 0)
4689               {
4690                 func_idxs->put (line->id, 1);
4691                 Vector<int> *temp_idx = new Vector<int>();
4692                 temp_idx->append (j);
4693                 instr_idxs->put (line->id, temp_idx);
4694               }
4695             else
4696               {
4697                 Vector<int> *temp_idx = instr_idxs->get (line->id);
4698                 temp_idx->append (j);
4699               }
4700           }
4701         for (long i = 0; i < data->size (); i++)
4702           {
4703             Histable* line = data->fetch (i)->obj;
4704             if (line == NULL)
4705               continue;
4706             Vector<int> * instr_idx = instr_idxs->get (line->id);
4707             if (instr_idx == NULL)
4708               continue;
4709             for (long j = 0; j < instr_idx->size (); j++)
4710               {
4711                 Vector<void*>* callee_funcs_vec = (Vector<void*>*)func_info;
4712                 if (callee_funcs_vec->size () == 0)
4713                   continue;
4714                 Vector<Function*>* callee_funcs_value = (Vector<Function*>*)callee_funcs_vec->fetch (instr_idx->fetch (j));
4715                 for (int k = 0; callee_funcs_value != NULL && k < callee_funcs_value->size (); k++)
4716                   {
4717                     uint64_t funcobj_id = ((Function*) callee_funcs_value->fetch (k))->id;
4718                     int old_size = table0->size ();
4719                     if (old_size > 0 && i == table0->fetch (old_size - 1)
4720                         && funcobj_id == table1->fetch (old_size - 1))
4721                       continue;
4722                     table0->append (i);
4723                     table1->append (funcobj_id);
4724                     table2->append (dbe_strdup (((Function*) callee_funcs_value->fetch (k))->get_name ()));
4725                   }
4726               }
4727           }
4728         delete instr_idxs;
4729         delete func_idxs;
4730         destroy (func_info);
4731         delete instr_info;
4732       }
4733       break;
4734     default:
4735       abort ();
4736     }
4737   table->store (0, table0);
4738   table->store (1, table1);
4739   table->store (2, table2);
4740   return table;
4741 }
4742
4743 //
4744 // Get Table of Function List data with only total values
4745 //
4746 Vector<void*> *
4747 dbeGetFuncListMini (int dbevindex, int type, int /*subtype*/)
4748 {
4749   Hist_data *data;
4750   DbeView *dbev = dbeSession->getView (dbevindex);
4751   switch (type)
4752     {
4753     case DSP_FUNCTION:
4754       data = dbev->func_data;
4755       break;
4756     default:
4757       data = NULL;
4758       break;
4759     }
4760   if (data == NULL || data->get_status () != Hist_data::SUCCESS)
4761     return NULL;
4762
4763   MetricList *mlist = data->get_metric_list ();
4764
4765   // Get table size: count visible metrics
4766   int nvisible = 0;
4767   for (long i = 0, sz = mlist->size (); i < sz; i++)
4768     {
4769       Metric *m = mlist->get (i);
4770       if (m->is_visible () || m->is_tvisible () || m->is_pvisible ())
4771         nvisible++;
4772     }
4773   Vector<void*> *table = new Vector<void*>(nvisible + 1);
4774
4775   // Fill function list elements
4776   Hist_data::HistItem *totals = data->get_totals ();
4777   for (long i = 0, sz = mlist->size (); i < sz; i++)
4778     {
4779       Metric *m = mlist->get (i);
4780       if (!m->is_visible () && !m->is_tvisible () && !m->is_pvisible ())
4781         continue;
4782       TValue res;
4783       TValue *v = data->get_value (&res, i, totals);
4784       if ((m->get_visbits () & VAL_RATIO) != 0)
4785         {
4786           Vector<double> *col = new Vector<double>(1);
4787           double d = (v->tag != VT_LABEL) ? v->to_double () : 100.; // NaN
4788           col->append (d);
4789           table->append (col);
4790           continue;
4791         }
4792       switch (m->get_vtype ())
4793         {
4794         case VT_INT:
4795           {
4796             Vector<int> *col = new Vector<int>(1);
4797             col->append (v->i);
4798             table->append (col);
4799             break;
4800           }
4801         case VT_ADDRESS:
4802         case VT_ULLONG:
4803         case VT_LLONG:
4804           {
4805             Vector<long long> *col = new Vector<long long>(1);
4806             col->append (v->ll);
4807             table->append (col);
4808             break;
4809           }
4810         case VT_LABEL:
4811           {
4812             Vector<char *> *col = new Vector<char *>(1);
4813             col->append (dbe_strdup (v->l));
4814             table->append (col);
4815             break;
4816           }
4817         case VT_DOUBLE:
4818         default:
4819           {
4820             Vector<double> *col = new Vector<double>(1);
4821             col->append (v->d);
4822             table->append (col);
4823             break;
4824           }
4825         }
4826     }
4827   table->append (NULL);
4828   return table;
4829 }
4830
4831 // Get Table of Function List data
4832 Vector<void*> *
4833 dbeGetFuncList (int dbevindex, int type, int subtype)
4834 {
4835   MetricList *mlist;
4836   Metric *mitem;
4837   int nitems, nvisible;
4838   int index, index2, nv;
4839   char *cell;
4840   Vector<int> *ji_list;
4841   Hist_data *data;
4842   Hist_data::HistItem *item;
4843
4844   DbeView *dbev = dbeSession->getView (dbevindex);
4845   if (dbev == NULL)
4846     abort ();
4847
4848   // fprintf(stderr, NTXT("XXX dbeGetFuncList, FuncListDisp_type = %d\n"), type);
4849   switch (type)
4850     {
4851     case DSP_FUNCTION:
4852       data = dbev->func_data;
4853       break;
4854     case DSP_LINE:
4855       data = dbev->line_data;
4856       break;
4857     case DSP_PC:
4858       data = dbev->pc_data;
4859       break;
4860     case DSP_SOURCE:
4861     case DSP_SOURCE_V2:
4862       data = dbev->src_data;
4863       break;
4864     case DSP_DISASM:
4865     case DSP_DISASM_V2:
4866       data = dbev->dis_data;
4867       break;
4868     case DSP_SELF:
4869       data = dbev->fitem_data;
4870       break;
4871     case DSP_CALLER:
4872       data = dbev->callers;
4873       break;
4874     case DSP_CALLEE:
4875       data = dbev->callees;
4876       break;
4877     case DSP_DLAYOUT:
4878       data = dbev->dlay_data;
4879       break;
4880     case DSP_DATAOBJ:
4881       data = dbev->dobj_data;
4882       break;
4883     case DSP_MEMOBJ:
4884     case DSP_INDXOBJ:
4885       data = dbev->get_indxobj_data (subtype);
4886       break;
4887     default:
4888       data = NULL;
4889       break;
4890     }
4891   if (data == NULL || data->get_status () != Hist_data::SUCCESS)
4892     return NULL;
4893   mlist = data->get_metric_list ();
4894
4895   // Get table size: count visible metrics
4896   nitems = data->size ();
4897   nvisible = 0;
4898   Vec_loop (Metric*, mlist->get_items (), index, mitem)
4899   {
4900     if (mitem->is_visible () || mitem->is_tvisible () || mitem->is_pvisible ())
4901       nvisible++;
4902   }
4903
4904   // Initialize Java String array
4905   Vector<void*> *table = new Vector<void*>(nvisible + 1);
4906
4907   // Mark Hi-value metric items for annotated src/dis/layout
4908   if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_DLAYOUT
4909       || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2)
4910     {
4911       ji_list = new Vector<int>(nitems);
4912
4913       if (dbev->marks->size () > 0)
4914         index = dbev->marks->fetch (0);
4915       else
4916         index = -1;
4917       int mindex = 0;
4918       for (index2 = 0; index2 < nitems; index2++)
4919         {
4920           item = data->fetch (index2);
4921           if (index2 == index)
4922             {
4923               ji_list->store (index2, -item->type);
4924               if (++mindex < dbev->marks->size ())
4925                 index = dbev->marks->fetch (mindex);
4926               else
4927                 index = -1;
4928             }
4929           else
4930             ji_list->store (index2, item->type);
4931         }
4932       table->store (nvisible, ji_list);
4933     }
4934   else
4935     table->store (nvisible, NULL);
4936
4937   // Fill function list elements
4938   nv = 0;
4939
4940   Vec_loop (Metric*, mlist->get_items (), index, mitem)
4941   {
4942     if (!mitem->is_visible () && !mitem->is_tvisible () &&
4943         !mitem->is_pvisible ())
4944       continue;
4945
4946     // Fill values
4947     switch (mitem->get_vtype ())
4948       {
4949       case VT_LABEL:
4950         {
4951           Vector<char*> *jobjects = new Vector<char*>(nitems);
4952           char *buf = NULL;
4953           size_t bufsz = 0;
4954           int lspace = 0;
4955           if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2
4956               || type == DSP_DISASM_V2)
4957             {
4958               // if this is source or disassembly, where we'll insert
4959               //        a preface into the output line, figure out how wide
4960               //        it needs to be
4961               // first, scan all the lines, to get the maximum line number
4962               bufsz = 1024;
4963               buf = (char *) malloc (bufsz);
4964               int max_lineno = 0;
4965               int hidx;
4966               Hist_data::HistItem *hitem;
4967               Vec_loop (Hist_data::HistItem*, data, hidx, hitem)
4968               {
4969                 if (!hitem->obj)
4970                   continue;
4971                 if (hitem->obj->get_type () == Histable::LINE &&
4972                     ((DbeLine*) hitem->obj)->lineno > max_lineno)
4973                   max_lineno = ((DbeLine*) hitem->obj)->lineno;
4974                 else if (hitem->obj->get_type () == Histable::INSTR
4975                          && ((DbeInstr*) hitem->obj)->lineno > max_lineno)
4976                   max_lineno = ((DbeInstr*) hitem->obj)->lineno;
4977               }
4978
4979               // we have the maximum integer over all linenumbers in the file
4980               //        figure out how many digits are needed
4981               lspace = snprintf (buf, bufsz, NTXT ("%d"), max_lineno);
4982             }
4983           for (index2 = 0; index2 < nitems; index2++)
4984             {
4985               item = data->fetch (index2);
4986               if (type == DSP_DLAYOUT)
4987                 cell = dbe_strdup (((DataObject*) (item->obj))->get_offset_name ());
4988               else if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2)
4989                 {
4990                   // This code is duplicated in output.cc, yet it's
4991                   // intended for presentation purpose and thus is
4992                   // potentially different for er_print and analyzer.
4993                   switch (item->type)
4994                     {
4995                     case Module::AT_SRC_ONLY:
4996                     case Module::AT_SRC:
4997                       if (item->obj == NULL)
4998                         snprintf (buf, bufsz, NTXT (" %*c. "), lspace, ' ');
4999                       else
5000                         snprintf (buf, bufsz, NTXT (" %*d. "), lspace, ((DbeLine*) item->obj)->lineno);
5001                       break;
5002                     case Module::AT_FUNC:
5003                     case Module::AT_QUOTE:
5004                       snprintf (buf, bufsz, NTXT ("%*c"), lspace + 3, ' ');
5005                       break;
5006                     case Module::AT_DIS:
5007                     case Module::AT_DIS_ONLY:
5008                       if (item->obj == NULL || ((DbeInstr*) item->obj)->lineno == -1)
5009                         snprintf (buf, bufsz, NTXT ("%*c[%*s] "), lspace + 3, ' ', lspace, NTXT ("?"));
5010                       else
5011                         snprintf (buf, bufsz, NTXT ("%*c[%*d] "), lspace + 3, ' ', lspace,
5012                                   ((DbeInstr*) item->obj)->lineno);
5013                       break;
5014                     case Module::AT_COM:
5015                     case Module::AT_EMPTY:
5016                       *buf = (char) 0;
5017                       break;
5018                     }
5019                   // get the line's text
5020                   char *s = item->value[index].l;
5021                   if (s != NULL)
5022                     {
5023                       // copy the string expanding all tabulations
5024                       // (JTable doesn't render them)
5025                       char *d = buf + strlen (buf);
5026                       char c;
5027                       size_t column = 0;
5028                       do
5029                         {
5030                           c = *s++;
5031                           if (c == '\t')
5032                             {
5033                               do
5034                                 {
5035                                   *d++ = ' ';
5036                                   column++;
5037                                 }
5038                               while (column & 07);
5039                             }
5040                           else
5041                             {
5042                               *d++ = c;
5043                               column++;
5044                             }
5045                           if (column + 32 > bufsz)
5046                             {
5047                               // Reallocate the buffer
5048                               size_t curlen = d - buf;
5049                               bufsz += 1024;
5050                               char *buf_new = (char *) malloc (bufsz);
5051                               strncpy (buf_new, buf, curlen);
5052                               buf_new[curlen] = '\0';
5053                               free (buf);
5054                               buf = buf_new;
5055                               d = buf + curlen;
5056                             }
5057                         }
5058                       while (c != (char) 0);
5059                     }
5060                   cell = dbe_strdup (buf);
5061                   free (item->value[index].l);
5062                   item->value[index].l = NULL; //YXXX missing from dbeGetFuncListV2
5063                 }
5064               else
5065                 {
5066                   // omazur: why don't we have it as metric value
5067                   Histable::NameFormat nfmt = dbev->get_name_format ();
5068                   cell = dbe_strdup (item->obj->get_name (nfmt));
5069                 }
5070               jobjects->store (index2, cell);
5071             }
5072           if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2
5073               || type == DSP_DISASM_V2)
5074             free (buf);
5075           table->store (nv++, jobjects);
5076           break;
5077         }
5078       default:
5079         table->store (nv++, dbeGetTableDataOneColumn (data, index));
5080         break;
5081       }
5082   }
5083   return table;
5084 }
5085
5086 Vector<Obj> *
5087 dbeGetComparableObjsV2 (int /* dbevindex */, Obj sel_obj, int type)
5088 {
5089   long grsize = dbeSession->expGroups->size ();
5090   Vector<Obj> *res = new Vector<Obj> (grsize + 1);
5091   for (long j = 0; j < grsize; j++)
5092     res->append ((Obj) NULL);
5093   res->append (sel_obj);
5094   Histable *obj = (Histable *) sel_obj;
5095   if (obj == NULL)
5096     return res;
5097   Function *func = (Function *) obj->convertto (Histable::FUNCTION);
5098   if (func == NULL)
5099     return res;
5100   Vector<Histable *> *cmpObjs = func->get_comparable_objs ();
5101   if (cmpObjs == NULL || cmpObjs->size () != grsize)
5102     return res;
5103
5104   Histable::Type conv_type = (type == DSP_SOURCE || type == DSP_SOURCE_V2) ?
5105           Histable::LINE : Histable::INSTR;
5106   switch (obj->get_type ())
5107     {
5108     case Histable::FUNCTION:
5109       for (long j = 0; j < grsize; j++)
5110         res->store (j, (Obj) cmpObjs->get (j));
5111       return res;
5112     case Histable::INSTR:
5113     case Histable::LINE:
5114       {
5115         SourceFile *srcContext = (SourceFile *) obj->convertto (Histable::SOURCEFILE);
5116         char *bname = get_basename (srcContext->get_name ());
5117         for (long j = 0; j < grsize; j++)
5118           {
5119             Function *func1 = (Function *) cmpObjs->get (j);
5120             if (func == func1)
5121               {
5122                 if (conv_type == Histable::LINE)
5123                   res->store (j, (Obj) obj);
5124                 else
5125                   res->store (j, (Obj) obj->convertto (conv_type, srcContext));
5126                 continue;
5127               }
5128             if (func1 == NULL)
5129               continue;
5130             Vector<SourceFile*> *sources = func1->get_sources ();
5131             SourceFile *sf = NULL;
5132             for (long j1 = 0, sz1 = sources ? sources->size () : 0; j1 < sz1; j1++)
5133               {
5134                 SourceFile *sf1 = sources->get (j1);
5135                 if (sf1 == srcContext)
5136                   { // the same file
5137                     sf = srcContext;
5138                     break;
5139                   }
5140                 else if (sf == NULL)
5141                   {
5142                     char *bname1 = get_basename (sf1->get_name ());
5143                     if (dbe_strcmp (bname, bname1) == 0)
5144                       sf = sf1;
5145                   }
5146               }
5147             res->store (j, (Obj) func1->convertto (conv_type, srcContext));
5148           }
5149         break;
5150       }
5151     default:
5152       break;
5153     }
5154   return res;
5155 }
5156
5157 // Get Table of Function List data
5158 Vector<void *> *
5159 dbeGetFuncListV2 (int dbevindex, int mtype, Obj sel_obj, int type, int subtype)
5160 {
5161   Metric *mitem;
5162   int nitems, nvisible;
5163   int index, index2, nv;
5164   char *cell;
5165   Hist_data::HistItem *item;
5166   DbeView *dbev = dbeSession->getView (dbevindex);
5167   dbev->error_msg = dbev->warning_msg = NULL;
5168   MetricList *mlist = dbev->get_metric_list ((MetricType) (mtype & MTYPE_MASK),
5169                                              (mtype & COMPARE_BIT) != 0,
5170                                              mtype >> GROUP_ID_SHIFT);
5171   Histable *selObj = (Histable *) sel_obj;
5172   int old_compare_mode = dbev->get_compare_mode ();
5173   if ((mtype & COMPARE_BIT) != 0)
5174     dbev->reset_compare_mode (CMP_DISABLE);
5175   Hist_data *data = dbev->get_data (mlist, selObj, type, subtype);
5176   dbev->reset_compare_mode (old_compare_mode);
5177   if (data == NULL || data->get_status () != Hist_data::SUCCESS)
5178     return NULL;
5179   nitems = data->size ();
5180   nvisible = mlist->get_items ()->size ();
5181
5182   // Initialize Java String array
5183   Vector<void*> *table = new Vector<void*>(nvisible + 3);
5184   // Mark Hi-value metric items for annotated src/dis/layout
5185   if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_DLAYOUT
5186       || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2)
5187     {
5188       Vector<int> *types = new Vector<int>(nitems);
5189       Vector<Obj> *ids = new Vector<Obj > (nitems);
5190       if (dbev->marks->size () > 0)
5191         index = dbev->marks->fetch (0);
5192       else
5193         index = -1;
5194       int mindex = 0;
5195       for (int i = 0; i < nitems; i++)
5196         {
5197           item = data->fetch (i);
5198           ids->store (i, (Obj) item->obj);
5199           if (i == index)
5200             {
5201               types->store (i, -item->type);
5202               if (++mindex < dbev->marks->size ())
5203                 index = dbev->marks->fetch (mindex);
5204               else
5205                 index = -1;
5206             }
5207           else
5208             types->store (i, item->type);
5209         }
5210       table->store (nvisible, types);
5211       table->store (nvisible + 1, ids);
5212     }
5213   else
5214     {
5215       table->store (nvisible, NULL);
5216       table->store (nvisible + 1, NULL);
5217     }
5218
5219   // Fill function list elements
5220   nv = 0;
5221   Vec_loop (Metric*, mlist->get_items (), index, mitem)
5222   {
5223     if (!mitem->is_visible () && !mitem->is_tvisible () &&
5224         !mitem->is_pvisible ())
5225       continue;
5226
5227     // Fill values
5228     switch (mitem->get_vtype ())
5229       {
5230       default:
5231         table->store (nv++, dbeGetTableDataOneColumn (data, index));
5232         break;
5233       case VT_LABEL:
5234         Vector<char*> *jobjects = new Vector<char*>(nitems);
5235         char *buf = NULL;
5236         size_t bufsz = 0;
5237         int lspace = 0;
5238         if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2
5239             || type == DSP_DISASM_V2)
5240           {
5241             // if this is source or disassembly, where we'll insert
5242             //  a preface into the output line, figure out how wide
5243             //  it needs to be
5244             // first, scan all the lines, to get the maximum line number
5245             bufsz = 1024;
5246             buf = (char *) malloc (bufsz);
5247             int max_lineno = 0;
5248             int hidx;
5249             Hist_data::HistItem *hitem;
5250             Vec_loop (Hist_data::HistItem*, data, hidx, hitem)
5251             {
5252               if (!hitem->obj)
5253                 continue;
5254               if (hitem->obj->get_type () == Histable::LINE &&
5255                   ((DbeLine*) hitem->obj)->lineno > max_lineno)
5256                 max_lineno = ((DbeLine*) hitem->obj)->lineno;
5257               else if (hitem->obj->get_type () == Histable::INSTR
5258                        && ((DbeInstr*) hitem->obj)->lineno > max_lineno)
5259                 max_lineno = ((DbeInstr*) hitem->obj)->lineno;
5260             }
5261
5262             // we have the maximum integer over all linenumbers in the file
5263             //  figure out how many digits are needed
5264             lspace = snprintf (buf, bufsz, NTXT ("%d"), max_lineno);
5265           }
5266
5267         for (index2 = 0; index2 < nitems; index2++)
5268           {
5269             item = data->fetch (index2);
5270             if (type == DSP_DLAYOUT)
5271               cell = dbe_strdup (((DataObject*) (item->obj))->get_offset_name ());
5272             else if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2)
5273               {
5274                 // This code is duplicated in output.cc, yet it's
5275                 // intended for presentation purpose and thus is
5276                 // potentially different for er_print and analyzer.
5277                 switch (item->type)
5278                   {
5279                   case Module::AT_SRC_ONLY:
5280                   case Module::AT_SRC:
5281                     if (item->obj == NULL)
5282                       snprintf (buf, bufsz, NTXT (" %*c. "), lspace, ' ');
5283                     else
5284                       snprintf (buf, bufsz, NTXT (" %*d. "), lspace,
5285                                 ((DbeLine*) item->obj)->lineno);
5286                     break;
5287                   case Module::AT_FUNC:
5288                   case Module::AT_QUOTE:
5289                     snprintf (buf, bufsz, NTXT ("%*c"), lspace + 3, ' ');
5290                     break;
5291                   case Module::AT_DIS:
5292                   case Module::AT_DIS_ONLY:
5293                     if (item->obj == NULL || ((DbeInstr*) item->obj)->lineno == -1)
5294                       snprintf (buf, bufsz, NTXT ("%*c[%*s] "), lspace + 3, ' ',
5295                                 lspace, NTXT ("?"));
5296                     else
5297                       snprintf (buf, bufsz, NTXT ("%*c[%*d] "), lspace + 3, ' ',
5298                                 lspace,
5299                                 ((DbeInstr*) item->obj)->lineno);
5300                     break;
5301                   case Module::AT_COM:
5302                   case Module::AT_EMPTY:
5303                     *buf = (char) 0;
5304                     break;
5305                   }
5306                 // get the line's text
5307                 char *s = item->value[index].l;
5308                 if (s != NULL)
5309                   {
5310                     // copy the string expanding all tabulations
5311                     // (JTable doesn't render them)
5312                     char *d = buf + strlen (buf);
5313                     char c;
5314                     size_t column = 0;
5315                     do
5316                       {
5317                         c = *s++;
5318                         if (c == '\t')
5319                           {
5320                             do
5321                               {
5322                                 *d++ = ' ';
5323                                 column++;
5324                               }
5325                             while (column & 07);
5326                           }
5327                         else
5328                           {
5329                             *d++ = c;
5330                             column++;
5331                           }
5332                         if (column + 32 > bufsz)
5333                           {
5334                             // Reallocate the buffer
5335                             size_t curlen = d - buf;
5336                             bufsz += 1024;
5337                             char *buf_new = (char *) malloc (bufsz);
5338                             strncpy (buf_new, buf, curlen);
5339                             buf_new[curlen] = '\0';
5340                             free (buf);
5341                             buf = buf_new;
5342                             d = buf + curlen;
5343                           }
5344                       }
5345                     while (c != (char) 0);
5346                   }
5347                 cell = dbe_strdup (buf);
5348               }
5349             else
5350               {
5351                 Histable::NameFormat nfmt = dbev->get_name_format ();
5352                 cell = dbe_strdup (item->obj->get_name (nfmt));
5353               }
5354             jobjects->store (index2, cell);
5355           }
5356
5357         if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2
5358             || type == DSP_DISASM_V2)
5359           free (buf);
5360         table->store (nv++, jobjects);
5361         break;
5362       }
5363   }
5364   table->append (dbeGetMetricList (mlist));
5365   return table;
5366 } // dbeGetFuncListV2
5367
5368 //
5369 // Get Table DataV2
5370 //
5371 Vector<void*> *
5372 dbeGetTableDataV2 (int dbevindex, char *mlistStr, char *modeStr, char *typeStr,
5373                    char *subtypeStr, Vector<uint64_t> *ids)
5374 {
5375   DbeView *dbev = dbeSession->getView (dbevindex);
5376   if (dbev == NULL)
5377     abort ();
5378
5379   // Process metric list specification
5380   if (mlistStr == NULL)
5381     return NULL;
5382   bool met_call = false;
5383   MetricList *mlist = NULL;
5384   if (streq (mlistStr, NTXT ("MET_NORMAL")))
5385     mlist = dbev->get_metric_list (MET_NORMAL);
5386   else if (streq (mlistStr, NTXT ("MET_CALL")))
5387     {
5388       met_call = true;
5389       mlist = dbev->get_metric_list (MET_CALL);
5390     }
5391   else if (streq (mlistStr, NTXT ("MET_CALL_AGR")))
5392     mlist = dbev->get_metric_list (MET_CALL_AGR);
5393   else if (streq (mlistStr, NTXT ("MET_DATA")))
5394     mlist = dbev->get_metric_list (MET_DATA);
5395   else if (streq (mlistStr, NTXT ("MET_INDX")))
5396     mlist = dbev->get_metric_list (MET_INDX);
5397   else if (streq (mlistStr, NTXT ("MET_IO")))
5398     mlist = dbev->get_metric_list (MET_IO);
5399   else if (streq (mlistStr, NTXT ("MET_HEAP")))
5400     mlist = dbev->get_metric_list (MET_HEAP);
5401   else
5402     return NULL;
5403
5404   // Process mode specification
5405   if (modeStr == NULL)
5406     return NULL;
5407   Hist_data::Mode mode = (Hist_data::Mode)0;
5408   if (streq (modeStr, NTXT ("CALLERS")))
5409     mode = Hist_data::CALLERS;
5410   else if (streq (modeStr, NTXT ("CALLEES")))
5411     mode = Hist_data::CALLEES;
5412   else if (streq (modeStr, NTXT ("SELF")))
5413     mode = Hist_data::SELF;
5414   else if (streq (modeStr, NTXT ("ALL")))
5415     mode = Hist_data::ALL;
5416   else
5417     return NULL;
5418
5419   // Process type specification
5420   if (typeStr == NULL)
5421     return NULL;
5422   Histable::Type type = Histable::OTHER;
5423   if (streq (typeStr, NTXT ("FUNCTION")))
5424     type = Histable::FUNCTION;
5425   else if (streq (typeStr, NTXT ("INDEXOBJ")))
5426     type = Histable::INDEXOBJ;
5427   else if (streq (typeStr, NTXT ("IOACTFILE")))
5428     type = Histable::IOACTFILE;
5429   else if (streq (typeStr, NTXT ("IOACTVFD")))
5430     type = Histable::IOACTVFD;
5431   else if (streq (typeStr, NTXT ("IOCALLSTACK")))
5432     type = Histable::IOCALLSTACK;
5433   else if (streq (typeStr, NTXT ("HEAPCALLSTACK")))
5434     type = Histable::HEAPCALLSTACK;
5435   else if (streq (typeStr, NTXT ("LINE")))
5436     type = Histable::LINE;
5437   else if (streq (typeStr, NTXT ("INSTR")))
5438     type = Histable::INSTR;
5439   else
5440     // XXX Accepting objects other than above may require a different
5441     // implementation of the id -> Histable mapping below
5442     return NULL;
5443
5444   // Process subtype specification
5445   int subtype = 0;
5446   if (subtypeStr != NULL)
5447     subtype = atoi (subtypeStr);
5448   Vector<Histable*> *hobjs = NULL;
5449   if (ids != NULL)
5450     {
5451       hobjs = new Vector<Histable*>();
5452       for (int i = 0; i < ids->size (); ++i)
5453         {
5454           Histable::Type obj_type = type;
5455           if ((obj_type == Histable::LINE || obj_type == Histable::INSTR)
5456               && subtype == 0)
5457             obj_type = Histable::FUNCTION;
5458           Histable *hobj = dbeSession->findObjectById (obj_type, subtype, ids->fetch (i));
5459           if ((obj_type == Histable::LINE || obj_type == Histable::INSTR)
5460               && subtype == 0 && hobj == NULL)
5461             return NULL;
5462           hobjs->append (hobj);
5463         }
5464     }
5465
5466   PathTree::PtreeComputeOption flag = PathTree::COMPUTEOPT_NONE;
5467   if (dbev->isOmpDisMode () && type == Histable::FUNCTION
5468       && mode == Hist_data::CALLEES && met_call)
5469     flag = PathTree::COMPUTEOPT_OMP_CALLEE;
5470
5471   Hist_data *data = dbev->get_hist_data (mlist, type, subtype, mode, hobjs, NULL, NULL, flag);
5472   return dbeGetTableDataV2Data (dbev, data);
5473 }
5474
5475 static Vector<void*> *
5476 dbeGetTableDataV2Data (DbeView * /*dbev*/, Hist_data *data)
5477 {
5478   if (data == NULL || data->get_status () != Hist_data::SUCCESS)
5479     return NULL;
5480   MetricList *mlist;
5481   mlist = data->get_metric_list ();
5482   int nitems = data->size ();
5483
5484   // Initialize Java String array
5485   Vector<void*> *table = new Vector<void*>(mlist->size () + 1);
5486
5487   // Fill function list elements
5488   for (long i = 0, sz = mlist->size (); i < sz; i++)
5489     {
5490       Metric *mitem = mlist->get (i);
5491       if (!mitem->is_visible () && !mitem->is_tvisible () &&
5492           !mitem->is_pvisible ())
5493         continue;
5494       table->append (dbeGetTableDataOneColumn (data, i));
5495     }
5496
5497   // Add an array of Histable IDs
5498   Vector<uint64_t> *idList = new Vector<uint64_t>(nitems);
5499   for (int i = 0; i < nitems; ++i)
5500     {
5501       Hist_data::HistItem *item = data->fetch (i);
5502       if (item->obj->get_type () == Histable::LINE
5503           || item->obj->get_type () == Histable::INSTR)
5504         idList->store (i, (uint64_t) (item->obj));
5505       else
5506         idList->store (i, item->obj->id);
5507     }
5508   table->append (idList);
5509   return table;
5510 } // dbeGetTableData
5511
5512 //YXXX try to use the following to consolidate similar cut/paste code
5513
5514 static Vector<void*> *
5515 dbeGetTableDataOneColumn (Hist_data *data, int met_ind)
5516 {
5517   // Allocates a vector and fills it with metric values for one column
5518   TValue res;
5519   Metric *m = data->get_metric_list ()->get (met_ind);
5520   if ((m->get_visbits () & VAL_RATIO) != 0)
5521     {
5522       Vector<double> *col = new Vector<double>(data->size ());
5523       for (long row = 0, sz_row = data->size (); row < sz_row; row++)
5524         {
5525           TValue *v = data->get_value (&res, met_ind, row);
5526           double d = (v->tag != VT_LABEL) ? v->to_double () : 100.; // NaN
5527           col->append (d);
5528         }
5529       return (Vector<void*> *) col;
5530     }
5531
5532   switch (m->get_vtype ())
5533     {
5534     case VT_DOUBLE:
5535       {
5536         Vector<double> *col = new Vector<double>(data->size ());
5537         for (long row = 0, sz_row = data->size (); row < sz_row; row++)
5538           {
5539             TValue *v = data->get_value (&res, met_ind, row);
5540             col->append (v->d);
5541           }
5542         return (Vector<void*> *) col;
5543       }
5544     case VT_INT:
5545       {
5546         Vector<int> *col = new Vector<int>(data->size ());
5547         for (long row = 0, sz_row = data->size (); row < sz_row; row++)
5548           {
5549             TValue *v = data->get_value (&res, met_ind, row);
5550             col->append (v->i);
5551           }
5552         return (Vector<void*> *) col;
5553       }
5554     case VT_ULLONG:
5555     case VT_LLONG:
5556       {
5557         Vector<long long> *col = new Vector<long long>(data->size ());
5558         for (long row = 0, sz_row = data->size (); row < sz_row; row++)
5559           {
5560             TValue *v = data->get_value (&res, met_ind, row);
5561             col->append (v->ll);
5562           }
5563         return (Vector<void*> *) col;
5564       }
5565     case VT_ADDRESS:
5566       {
5567         Vector<long long> *col = new Vector<long long>(data->size ());
5568         for (long row = 0, sz_row = data->size (); row < sz_row; row++)
5569           {
5570             TValue *v = data->get_value (&res, met_ind, row);
5571             // set the highest bit to mark this jlong as
5572             // a VT_ADDRESS (rather than a regular VT_LLONG)
5573             col->append (v->ll | 0x8000000000000000ULL);
5574           }
5575         return (Vector<void*> *) col;
5576       }
5577     case VT_LABEL:
5578       {
5579         Vector<char *> *col = new Vector<char *>(data->size ());
5580         for (long row = 0, sz_row = data->size (); row < sz_row; row++)
5581           {
5582             TValue *v = data->get_value (&res, met_ind, row);
5583             col->append (dbe_strdup (v->l));
5584           }
5585         return (Vector<void*> *) col;
5586       }
5587     default:
5588       return NULL;
5589     }
5590 }
5591
5592 static Vector<void*> *
5593 dbeGetTableDataOneColumn (DbeView *dbev, Vector<Hist_data::HistItem*> *data,
5594                           ValueTag vtype, int metricColumnNumber)
5595 // Allocates a vector and fills it with metric values for one column
5596 {
5597   Vector<void*> *column_data = NULL;
5598   int nitems = data->size (); // number of rows
5599   int index = metricColumnNumber;
5600   switch (vtype)
5601     {
5602     case VT_DOUBLE:
5603       {
5604         Vector<double> *jd_list = new Vector<double>(nitems);
5605         for (int index2 = 0; index2 < nitems; index2++)
5606           {
5607             Hist_data::HistItem *item = data->fetch (index2);
5608             jd_list->store (index2, item->value[index].d);
5609           }
5610         column_data = (Vector<void*> *)jd_list;
5611         break;
5612       }
5613     case VT_INT:
5614       {
5615         Vector<int> *ji_list = new Vector<int>(nitems);
5616         for (int index2 = 0; index2 < nitems; index2++)
5617           {
5618             Hist_data::HistItem *item = data->fetch (index2);
5619             ji_list->store (index2, item->value[index].i);
5620           }
5621         column_data = (Vector<void*> *)ji_list;
5622         break;
5623       }
5624     case VT_ULLONG:
5625     case VT_LLONG:
5626       {
5627         Vector<long long> *jl_list = new Vector<long long>(nitems);
5628         for (int index2 = 0; index2 < nitems; index2++)
5629           {
5630             Hist_data::HistItem *item = data->fetch (index2);
5631             jl_list->store (index2, item->value[index].ll);
5632           }
5633         column_data = (Vector<void*> *)jl_list;
5634         break;
5635       }
5636     case VT_ADDRESS:
5637       {
5638         Vector<long long> *jl_list = new Vector<long long>(nitems);
5639         for (int index2 = 0; index2 < nitems; index2++)
5640           {
5641             Hist_data::HistItem *item = data->fetch (index2);
5642
5643             // set the highest bit to mark this jlong as
5644             // a VT_ADDRESS (rather than a regular VT_LLONG)
5645             uint64_t addr = item->value[index].ll;
5646             addr |= 0x8000000000000000ULL;
5647             jl_list->store (index2, addr);
5648           }
5649         column_data = (Vector<void*> *)jl_list;
5650         break;
5651       }
5652     case VT_LABEL:
5653       {
5654         Vector<char*> *jobjects = new Vector<char*>(nitems);
5655         for (int index2 = 0; index2 < nitems; index2++)
5656           {
5657             Hist_data::HistItem *item = data->fetch (index2);
5658
5659             // omazur: why don't we have it as metric value
5660             Histable::NameFormat nfmt = dbev->get_name_format ();
5661             char *str = dbe_strdup (item->obj->get_name (nfmt));
5662             jobjects->store (index2, str);
5663           }
5664         column_data = (Vector<void*> *)jobjects;
5665         break;
5666       }
5667     default:
5668       abort ();
5669     }
5670   return column_data;
5671 }
5672
5673 int
5674 dbeGetCallTreeNumLevels (int dbevindex)
5675 {
5676   DbeView *dbev = dbeSession->getView (dbevindex);
5677   if (dbev == NULL)
5678     abort ();
5679   PathTree * ptree = dbev->get_path_tree ();
5680   if (ptree == NULL)
5681     return 0;
5682   return ptree->get_ftree_depth ();
5683 }
5684
5685 Vector<void*>*
5686 dbeGetCallTreeLevel (int dbevindex, char *mcmd, int level)
5687 {
5688   DbeView *dbev = dbeSession->getView (dbevindex);
5689   if (dbev == NULL)
5690     abort ();
5691   PathTree * ptree = dbev->get_path_tree ();
5692   if (ptree == NULL)
5693     return NULL;
5694   if (mcmd == NULL)
5695     return NULL;
5696   BaseMetric *bm = dbeSession->find_base_reg_metric (mcmd);
5697   if (bm == NULL)
5698     return NULL;
5699   return ptree->get_ftree_level (bm, level);
5700 }
5701
5702 Vector<void*>*
5703 dbeGetCallTreeLevels (int dbevindex, char *mcmd)
5704 {
5705   DbeView *dbev = dbeSession->getView (dbevindex);
5706   if (dbev == NULL)
5707     abort ();
5708   PathTree * ptree = dbev->get_path_tree ();
5709   if (ptree == NULL)
5710     return NULL;
5711   if (mcmd == NULL)
5712     return NULL;
5713   BaseMetric *bm = dbeSession->find_base_reg_metric (mcmd);
5714   if (bm == NULL)
5715     return NULL;
5716
5717   int depth = ptree->get_ftree_depth ();
5718   Vector<void*> *results = new Vector<void*>(depth);
5719   for (int ii = 0; ii < depth; ii++)
5720     results->append (ptree->get_ftree_level (bm, ii));
5721   return results;
5722 }
5723
5724 Vector<void*>*
5725 dbeGetCallTreeLevelFuncs (int dbevindex, int start_level, int end_level)
5726 { // (0,-1) -> all levels
5727   DbeView *dbev = dbeSession->getView (dbevindex);
5728   if (dbev == NULL)
5729     abort ();
5730   PathTree * ptree = dbev->get_path_tree ();
5731   if (ptree == NULL)
5732     return NULL;
5733
5734   int depth = ptree->get_ftree_depth ();
5735   if (start_level < 0)
5736     start_level = 0;
5737   if (end_level < 0 || end_level >= depth)
5738     end_level = depth - 1;
5739
5740   Histable::NameFormat nfmt = dbev->get_name_format (); //YXXX or fixed format?
5741   Vector<char*> *funcNames = new Vector<char*>();
5742   Vector<long long> *funcIds = new Vector<long long>();
5743   Vector<Obj> *funcObjs = new Vector<Obj>();
5744
5745   if (start_level == 0 && end_level == depth - 1)
5746     return dbeGetCallTreeFuncs (dbevindex);
5747   else
5748     {
5749       for (int ii = start_level; ii <= end_level; ii++)
5750         {
5751           Vector<void*> *info = ptree->get_ftree_level (NULL, ii); /*no metric*/
5752           if (!info)
5753             continue;
5754           Vector<long long> *fids = (Vector<long long> *)info->get (2);
5755           if (!fids)
5756             continue;
5757           int index;
5758           long long fid;
5759           Vec_loop (long long, fids, index, fid)
5760           {
5761             funcIds->append (fid);
5762             Histable *obj = dbeSession->findObjectById (fid);
5763             char * fname = obj ? dbe_strdup (obj->get_name (nfmt)) : NULL;
5764             funcNames->append (fname);
5765             funcObjs->append ((unsigned long) obj); // avoiding sign extension
5766           }
5767           destroy (info);
5768         }
5769     }
5770   Vector<void*> *results = new Vector<void*>(3);
5771   results->append (funcIds);
5772   results->append (funcNames);
5773   results->append (funcObjs);
5774   return results;
5775 }
5776
5777 Vector<void*> *
5778 dbeGetCallTreeFuncs (int dbevindex)
5779 { // does not require ptree->get_ftree_level() to be computed
5780   DbeView *dbev = dbeSession->getView (dbevindex);
5781   if (dbev == NULL)
5782     abort ();
5783   PathTree * ptree = dbev->get_path_tree ();
5784   if (ptree == NULL)
5785     return 0;
5786   Vector<Function*>* funcs = ptree->get_funcs (); // Unique functions in tree
5787   if (funcs == NULL)
5788     return NULL;
5789
5790   long sz = funcs->size ();
5791   Vector<void*> *results = new Vector<void*>(3);
5792   Vector<long long> *funcIds = new Vector<long long>(sz);
5793   Vector<char*> *funcNames = new Vector<char*>(sz);
5794   Vector<Obj> *funcObjs = new Vector<Obj>(sz);
5795
5796   int index;
5797   Function * func;
5798   Histable::NameFormat nfmt = dbev->get_name_format (); //YXXX or fixed format?
5799   Vec_loop (Function *, funcs, index, func)
5800   {
5801     funcIds->append (func->id); // do we need IDs?
5802     char *fname = dbe_strdup (func->get_name (nfmt));
5803     funcNames->append (fname);
5804     funcObjs->append ((unsigned long) func); // avoiding sign extension
5805   }
5806   results->put (0, funcIds);
5807   results->put (1, funcNames);
5808   results->put (2, funcObjs);
5809   destroy (funcs);
5810   return results;
5811 }
5812
5813 Vector<void*>*
5814 dbeGetCallTreeChildren (int dbevindex, char *mcmd, Vector<int /*NodeIdx*/>*node_idxs)
5815 {
5816   DbeView *dbev = dbeSession->getView (dbevindex);
5817   if (dbev == NULL)
5818     abort ();
5819   if (node_idxs == NULL || node_idxs->size () == 0)
5820     return NULL;
5821   long sz = node_idxs->size ();
5822   PathTree * ptree = dbev->get_path_tree ();
5823   if (ptree == NULL)
5824     return NULL;
5825   if (mcmd == NULL)
5826     return NULL;
5827   BaseMetric *bm = dbeSession->find_base_reg_metric (mcmd);
5828   if (bm == NULL)
5829     return NULL;
5830
5831   Vector<void*> *results = new Vector<void*>(sz);
5832   for (long ii = 0; ii < sz; ii++)
5833     {
5834       PathTree::NodeIdx nodeIdx = node_idxs->get (ii); // upcasted from int
5835       results->append (ptree->get_ftree_node_children (bm, nodeIdx));
5836     }
5837   return results;
5838 }
5839
5840 Vector<int> *
5841 dbeGetGroupIds (int /*dbevindex*/)
5842 {
5843   Vector<ExpGroup*> *groups = dbeSession->expGroups;
5844   int sz = groups->size ();
5845   Vector<int> *grIds = new Vector<int>(sz);
5846   for (int i = 0; i < sz; i++)
5847     grIds->store (i, groups->fetch (i)->groupId);
5848   return grIds;
5849 }
5850
5851 //
5852 // Get label for name column
5853 //
5854 Vector<char*> *
5855 dbeGetNames (int dbevindex, int type, Obj sel_obj)
5856 {
5857   char *s0, *s1, *s2;
5858   bool need_strdup = true;
5859   switch (type)
5860     {
5861     case DSP_SOURCE_V2:
5862     case DSP_DISASM_V2:
5863     case DSP_SOURCE:
5864     case DSP_DISASM:
5865       {
5866         if (sel_obj)
5867           {
5868             Histable *selObj = (Histable*) sel_obj;
5869             Function *func = (Function *) selObj->convertto (Histable::FUNCTION);
5870             if (func)
5871               {
5872                 char *names[3] = {NULL, NULL, NULL};
5873                 set_file_names (func, names);
5874                 s0 = names[0];
5875                 s1 = names[1];
5876                 s2 = names[2];
5877                 need_strdup = false;
5878                 break;
5879               }
5880           }
5881         DbeView *dbev = dbeSession->getView (dbevindex);
5882         char **names = type == DSP_SOURCE || type == DSP_SOURCE_V2 ? dbev->names_src : dbev->names_dis;
5883         s0 = names[0];
5884         s1 = names[1];
5885         s2 = names[2];
5886         break;
5887       }
5888     case DSP_LINE:
5889       s0 = GTXT ("Lines");
5890       s1 = GTXT ("Function, line # in \"sourcefile\"");
5891       s2 = NTXT ("");
5892       break;
5893     case DSP_PC:
5894       s0 = GTXT ("PCs");
5895       s1 = GTXT ("Function + offset");
5896       s2 = NTXT ("");
5897       break;
5898     case DSP_DLAYOUT:
5899       s0 = GTXT ("Name");
5900       s1 = GTXT ("* +offset .element");
5901       s2 = NTXT ("");
5902       break;
5903     default:
5904       s0 = GTXT ("Name");
5905       s1 = s2 = NTXT ("");
5906       break;
5907     }
5908   if (need_strdup)
5909     {
5910       s0 = dbe_strdup (s0);
5911       s1 = dbe_strdup (s1);
5912       s2 = dbe_strdup (s2);
5913     }
5914   Vector<char*> *table = new Vector<char*>(3);
5915   table->store (0, s0);
5916   table->store (1, s1);
5917   table->store (2, s2);
5918   return table;
5919 }
5920
5921 //
5922 // Get Total/Maximum element of Function List
5923 //
5924 Vector<void*> *
5925 dbeGetTotalMax (int dbevindex, int type, int subtype)
5926 {
5927   Hist_data *data;
5928   int index;
5929   Hist_data::HistItem *total_item, *maximum_item;
5930   DbeView *dbev = dbeSession->getView (dbevindex);
5931   if (dbev == NULL)
5932     abort ();
5933
5934   switch (type)
5935     {
5936     case DSP_LINE:
5937       data = dbev->line_data;
5938       break;
5939     case DSP_PC:
5940       data = dbev->pc_data;
5941       break;
5942     case DSP_CALLER:
5943       data = dbev->callers;
5944       break;
5945     case DSP_SELF:
5946     case DSP_CALLEE:
5947       data = dbev->callees;
5948       break;
5949     case DSP_DLAYOUT:
5950       data = dbev->dlay_data;
5951       break;
5952     case DSP_DATAOBJ:
5953       data = dbev->dobj_data;
5954       break;
5955     case DSP_MEMOBJ:
5956       data = dbev->get_indxobj_data (subtype);
5957       break;
5958     case DSP_INDXOBJ:
5959       data = dbev->get_indxobj_data (subtype);
5960       break;
5961     case DSP_FUNCTION: // annotated src/dis use func total/max
5962     case DSP_SOURCE:
5963     case DSP_DISASM:
5964     case DSP_SOURCE_V2:
5965     case DSP_DISASM_V2:
5966       data = dbev->func_data;
5967       break;
5968     default:
5969       abort ();
5970     }
5971   if (data == NULL || data->get_status () != Hist_data::SUCCESS)
5972     return NULL;
5973
5974   // Get list size
5975   // XXX -- the original list has all items, visible or not;
5976   // XXX -- the one from Hist_data has only visible items,
5977   // XXX --    and should be the only ones computed
5978   // XXX --    Analyzer got confused (yesterday), when we used the shorter list
5979   // XXX -- Why can we fetch total/max for metrics never
5980   // XXX --    computed without core dumping?
5981   MetricList *mlist2 = data->get_metric_list ();
5982   int size = mlist2->get_items ()->size ();
5983
5984   // Initialize Java array
5985   Vector<void*> *total_max = new Vector<void*>(2);
5986   Vector<double> *total = new Vector<double>(size);
5987   Vector<double> *maximum = new Vector<double>(size);
5988
5989   // Fill total/maximum element
5990   total_item = data->get_totals ();
5991   maximum_item = data->get_maximums ();
5992
5993   for (index = 0; index < size; index++)
5994     {
5995       total->store (index, total_item->value[index].to_double ());
5996       maximum->store (index, maximum_item->value[index].to_double ());
5997     }
5998   total_max->store (0, total);
5999   total_max->store (1, maximum);
6000   return total_max;
6001 }
6002
6003 //
6004 // Get Table of Overview List
6005 Vector<void*> *
6006 dbeGetStatisOverviewList (int dbevindex)
6007 {
6008   int size;
6009   Ovw_data **data;
6010   Ovw_data::Ovw_item labels, *totals;
6011   int nitems;
6012   int index, index2;
6013
6014   DbeView *dbev = dbeSession->getView (dbevindex);
6015   if (dbev == NULL)
6016     abort ();
6017   dbev->error_msg = dbev->warning_msg = NULL;
6018
6019   size = dbeSession->nexps ();
6020   totals = new Ovw_data::Ovw_item[size + 1];
6021   data = new Ovw_data*[size + 1];
6022   data[0] = new Ovw_data ();
6023
6024   for (index = 1; index <= size; index++)
6025     {
6026       data[index] = dbev->get_ovw_data (index - 1);
6027       if (data[index] == NULL)
6028         {
6029           Ovw_data::reset_item (&totals[index]); // set contents to zeros
6030           continue;
6031         }
6032       data[0]->sum (data[index]);
6033       totals[index] = data[index]->get_totals (); //shallow copy!
6034     }
6035   totals[0] = data[0]->get_totals ();
6036
6037   // Get table size
6038   labels = data[0]->get_labels ();
6039   nitems = labels.size + 4;
6040
6041   // Initialize Java String array
6042   Vector<void*> *table = new Vector<void*>(size + 4);
6043   Vector<char*> *jobjects = new Vector<char*>(nitems);
6044
6045   // Set the label
6046   jobjects->store (0, dbe_strdup (GTXT ("Start Time (sec.)")));
6047   jobjects->store (1, dbe_strdup (GTXT ("End Time (sec.)")));
6048   jobjects->store (2, dbe_strdup (GTXT ("Duration (sec.)")));
6049   jobjects->store (3, dbe_strdup (GTXT ("Total Thread Time (sec.)")));
6050   jobjects->store (4, dbe_strdup (GTXT ("Average number of Threads")));
6051
6052   for (index2 = 5; index2 < nitems; index2++)
6053     jobjects->store (index2, dbe_strdup (labels.values[index2 - 4].l));
6054   table->store (0, jobjects);
6055
6056   // Set the data
6057   for (index = 0; index <= size; index++)
6058     {
6059       Vector<double> *jd_list = new Vector<double>(nitems);
6060       jd_list->store (0, tstodouble (totals[index].start));
6061       jd_list->store (1, tstodouble (totals[index].end));
6062       jd_list->store (2, tstodouble (totals[index].duration));
6063       jd_list->store (3, tstodouble (totals[index].tlwp));
6064       jd_list->store (4, totals[index].nlwp);
6065       for (index2 = 5; index2 < nitems; index2++)
6066         jd_list->store (index2, tstodouble (totals[index].values[index2 - 4].t));
6067       table->store (index + 1, jd_list);
6068     }
6069   for (index = 0; index <= size; index++)
6070     delete data[index];
6071   delete[] data;
6072   delete[] totals;
6073   return table;
6074 }
6075
6076 // Get Table of Statistics List
6077 Vector<void*> *
6078 dbeGetStatisList (int dbevindex)
6079 {
6080   int size;
6081   Stats_data **data;
6082   int nitems;
6083   int index, index2;
6084   DbeView *dbev = dbeSession->getView (dbevindex);
6085   if (dbev == NULL)
6086     abort ();
6087   dbev->error_msg = dbev->warning_msg = NULL;
6088   if ((size = dbeSession->nexps ()) == 0)
6089     return NULL;
6090
6091   // Get statistics data
6092   data = (Stats_data **) malloc ((size + 1) * sizeof (Stats_data *));
6093   data[0] = new Stats_data ();
6094   for (index = 1; index <= size; index++)
6095     {
6096       data[index] = dbev->get_stats_data (index - 1);
6097       if (data[index] == NULL)
6098         continue;
6099       data[0]->sum (data[index]);
6100     }
6101
6102   // Get table size
6103   nitems = data[0]->size ();
6104
6105   // Initialize Java String array
6106   Vector<void*> *table = new Vector<void*>(size + 2);
6107   Vector<char*> *jobjects = new Vector<char*>(nitems);
6108
6109   // Set the label
6110   for (index2 = 0; index2 < nitems; index2++)
6111     jobjects->store (index2, dbe_strdup (data[0]->fetch (index2).label));
6112   table->store (0, jobjects);
6113
6114   // Set the data
6115   for (index = 0; index <= size; index++)
6116     {
6117       Vector<double> *jd_list = new Vector<double>(nitems);
6118       for (index2 = 0; index2 < nitems; index2++)
6119         {
6120           double val = 0;
6121           if (data[index])
6122             val = data[index]->fetch (index2).value.to_double ();
6123           jd_list->store (index2, val);
6124         }
6125       table->store (index + 1, jd_list);
6126     }
6127   if (data)
6128     {
6129       for (index = 0; index <= size; index++)
6130         delete data[index];
6131       free (data);
6132     }
6133   return table;
6134 }
6135
6136
6137 //
6138 // Set summary list
6139 //
6140 static void
6141 setSummary (Vector<Histable*> *objs, Vector<int> *saligns,
6142             Vector<char> *mnemonic, Vector<char*> *jlabels, Vector<char*> *jvalues)
6143 {
6144   char *sname = NULL, *oname = NULL, *lname = NULL, *alias = NULL,
6145           *mangle = NULL, *address = NULL, *size = NULL,
6146           *name_0 = NULL, *sname_0 = NULL, *oname_0 = NULL, *lname_0 = NULL,
6147           *alias_0 = NULL, *mangle_0 = NULL;
6148   Function *func, *last_func = NULL;
6149   int one_func = 1;
6150
6151   // Get the source/object/load-object files & aliases
6152   long long ll_size = 0;
6153   for (long i = 0; i < objs->size (); i++)
6154     {
6155       Histable *current_obj = objs->fetch (i);
6156       Histable::Type htype = current_obj->get_type ();
6157       if (htype == Histable::LOADOBJECT)
6158         lname = ((LoadObject *) current_obj)->dbeFile->get_location_info ();
6159       else if ((func = (Function*) current_obj->convertto (Histable::FUNCTION)) != NULL)
6160         {
6161           if (one_func && last_func != NULL && last_func != func)
6162             one_func = 0;
6163           last_func = func;
6164           sname = NULL;
6165           DbeLine *dbeline = (DbeLine*) current_obj->convertto (Histable::LINE);
6166           if (dbeline)
6167             {
6168               SourceFile *sf;
6169               if (dbeline->lineno == 0 && dbeline->include != NULL)
6170                 sf = dbeline->include;
6171               else if (dbeline->sourceFile != NULL)
6172                 sf = dbeline->sourceFile;
6173               else
6174                 sf = func->getDefSrc ();
6175               if (sf)
6176                 sname = sf->dbeFile->get_location_info ();
6177             }
6178           char *func_name = func->get_name ();
6179           mangle = func->get_mangled_name ();
6180           if (mangle && streq (func_name, mangle))
6181             mangle = NULL;
6182           Module *module = func->module;
6183           if (module != NULL)
6184             {
6185               module->read_stabs ();
6186               if (sname == NULL || strlen (sname) == 0)
6187                 {
6188                   SourceFile *sf = module->getMainSrc ();
6189                   sname = sf->dbeFile->get_location_info ();
6190                 }
6191               DbeFile *df = module->dbeFile;
6192               if (df == NULL || (df->filetype & DbeFile::F_JAVACLASS) == 0)
6193                 df = module->loadobject->dbeFile;
6194               lname = df->get_location_info ();
6195               oname = lname;
6196               if (module->dot_o_file)
6197                 oname = module->dot_o_file->dbeFile->get_location_info ();
6198             }
6199
6200           if (htype == Histable::INSTR && dbeSession->is_datamode_available ())
6201             alias = ((DbeInstr*) current_obj)->get_descriptor ();
6202         }
6203
6204       char *name = current_obj->get_name ();
6205       if (i == 0)
6206         {
6207           name_0 = name;
6208           lname_0 = lname;
6209           sname_0 = sname;
6210           oname_0 = oname;
6211           mangle_0 = mangle;
6212           alias_0 = alias;
6213           if (objs->size () == 1)
6214             {
6215               uint64_t addr = current_obj->get_addr ();
6216               address = dbe_sprintf (NTXT ("%lld:0x%08llX"),
6217                                      (long long) ADDRESS_SEG (addr),
6218                                      (long long) ADDRESS_OFF (addr));
6219             }
6220         }
6221       else
6222         {
6223           if (name_0 != name)
6224             name_0 = NULL;
6225           if (lname_0 != lname)
6226             lname_0 = NULL;
6227           if (sname_0 != sname)
6228             sname_0 = NULL;
6229           if (oname_0 != oname)
6230             oname_0 = NULL;
6231           if (mangle_0 != mangle)
6232             mangle_0 = NULL;
6233           if (alias_0 != alias)
6234             alias_0 = NULL;
6235         }
6236       if (current_obj->get_size () == -1)
6237         {
6238           if (size == NULL)
6239             size = dbe_strdup (GTXT ("(Unknown)"));
6240         }
6241       else
6242         ll_size += current_obj->get_size ();
6243     }
6244   if (size == NULL)
6245     size = dbe_sprintf (NTXT ("%lld"), ll_size);
6246   if (name_0 == NULL)
6247     {
6248       if (objs->size () > 1)
6249         {
6250           char *func_name = last_func == NULL ? NULL :
6251                   (one_func == 0 ? NULL : last_func->get_name ());
6252           name_0 = dbe_sprintf (NTXT ("%s%s%s (%lld %s)"),
6253                                 func_name == NULL ? "" : func_name,
6254                                 func_name == NULL ? "" : ": ",
6255                                 GTXT ("Multiple Selection"),
6256                                 (long long) objs->size (),
6257                                 GTXT ("objects"));
6258         }
6259     }
6260   else
6261     name_0 = dbe_strdup (name_0);
6262
6263   // Set the name area
6264   saligns->store (0, TEXT_LEFT);
6265   mnemonic->store (0, 'N');
6266   jlabels->store (0, dbe_strdup (GTXT ("Name")));
6267   jvalues->store (0, name_0);
6268
6269   saligns->store (1, TEXT_LEFT);
6270   mnemonic->store (1, 'P');
6271   jlabels->store (1, dbe_strdup (GTXT ("PC Address")));
6272   jvalues->store (1, address);
6273
6274   saligns->store (2, TEXT_LEFT);
6275   mnemonic->store (2, 'z');
6276   jlabels->store (2, dbe_strdup (GTXT ("Size")));
6277   jvalues->store (2, size);
6278
6279   saligns->store (3, TEXT_RIGHT);
6280   mnemonic->store (3, 'r');
6281   jlabels->store (3, dbe_strdup (GTXT ("Source File")));
6282   jvalues->store (3, dbe_strdup (sname_0));
6283
6284   saligns->store (4, TEXT_RIGHT);
6285   mnemonic->store (4, 'b');
6286   jlabels->store (4, dbe_strdup (GTXT ("Object File")));
6287   jvalues->store (4, dbe_strdup (oname_0));
6288
6289   saligns->store (5, TEXT_LEFT);
6290   mnemonic->store (5, 'j');
6291   jlabels->store (5, dbe_strdup (GTXT ("Load Object")));
6292   jvalues->store (5, dbe_strdup (lname_0));
6293
6294   saligns->store (6, TEXT_LEFT);
6295   mnemonic->store (6, 'm');
6296   jlabels->store (6, dbe_strdup (GTXT ("Mangled Name")));
6297   jvalues->store (6, dbe_strdup (mangle_0));
6298
6299   saligns->store (7, TEXT_LEFT);
6300   mnemonic->store (7, 'A');
6301   jlabels->store (7, dbe_strdup (GTXT ("Aliases")));
6302   jvalues->store (7, dbe_strdup (alias_0));
6303 }
6304
6305 // Set memory-object summary list
6306 //
6307 static void
6308 setMemSummary (Vector<Histable*> *objs, Vector<int> *saligns,
6309                Vector<char> *mnemonic, Vector<char*> *jlabels,
6310                Vector<char*> *jvalues)
6311 {
6312   saligns->store (0, TEXT_LEFT);
6313   mnemonic->store (0, 'M');
6314   jlabels->store (0, dbe_strdup (GTXT ("Memory Object")));
6315   if (objs->size () == 1)
6316     {
6317       Histable *current_obj = objs->fetch (0);
6318       jvalues->store (0, dbe_strdup (current_obj->get_name ()));
6319     }
6320   else
6321     {
6322       char *name = dbe_sprintf (NTXT ("%s (%lld %s)"),
6323                                 GTXT ("Multiple Selection"),
6324                                 (long long) objs->size (), GTXT ("objects"));
6325       jvalues->store (0, name);
6326     }
6327 }
6328
6329 // Set index-object summary list
6330 //
6331 static void
6332 setIndxSummary (Vector<Histable*> *objs, Vector<int> *saligns,
6333                 Vector<char> *mnemonic, Vector<char*> *jlabels,
6334                 Vector<char*> *jvalues)
6335 {
6336   saligns->store (0, TEXT_LEFT);
6337   mnemonic->store (0, 'I');
6338   jlabels->store (0, dbe_strdup (GTXT ("Index Object")));
6339
6340   if (objs->size () == 1)
6341     {
6342       Histable *current_obj = objs->fetch (0);
6343       jvalues->store (0, dbe_strdup (current_obj->get_name ()));
6344     }
6345   else
6346     {
6347       char *name = dbe_sprintf (NTXT ("%s (%lld %s)"), GTXT ("Multiple Selection"),
6348                                 (long long) objs->size (), GTXT ("objects"));
6349       jvalues->store (0, name);
6350     }
6351 }
6352
6353 // Set I/O activity summary list
6354 //
6355 static void
6356 setIOActivitySummary (Vector<Histable*> *objs, Vector<int> *saligns,
6357                       Vector<char> *mnemonic, Vector<char*> *jlabels,
6358                       Vector<char*> *jvalues)
6359 {
6360   saligns->store (0, TEXT_LEFT);
6361   mnemonic->store (0, 'O');
6362   jlabels->store (0, dbe_strdup (GTXT ("I/O Activity")));
6363   if (objs->size () == 1)
6364     {
6365       Histable *current_obj = objs->fetch (0);
6366       jvalues->store (0, dbe_strdup (current_obj->get_name ()));
6367     }
6368   else
6369     {
6370       char *name = dbe_sprintf (NTXT ("%s (%lld %s)"), GTXT ("Multiple Selection"),
6371                                 (long long) objs->size (), GTXT ("objects"));
6372       jvalues->store (0, name);
6373     }
6374 }
6375
6376 // Set heap activity summary list
6377 //
6378 static void
6379 setHeapActivitySummary (Vector<Histable*> *objs, Vector<int> *saligns,
6380                         Vector<char> *mnemonic, Vector<char*> *jlabels,
6381                         Vector<char*> *jvalues)
6382 {
6383   saligns->store (0, TEXT_LEFT);
6384   mnemonic->store (0, 'O');
6385   jlabels->store (0, dbe_strdup (GTXT ("Heap Activity")));
6386
6387   if (objs->size () == 1)
6388     {
6389       Histable *current_obj = objs->fetch (0);
6390       jvalues->store (0, dbe_strdup (current_obj->get_name ()));
6391     }
6392   else
6393     {
6394       char *name = dbe_sprintf (NTXT ("%s (%lld %s)"), GTXT ("Multiple Selection"),
6395                                 (long long) objs->size (), GTXT ("objects"));
6396       jvalues->store (0, name);
6397     }
6398 }
6399
6400 //
6401 // Set data-object summary list
6402 //
6403 static void
6404 setDataSummary (Vector<Histable*> *objs, Vector<int> *saligns,
6405                 Vector<char> *mnemonic, Vector<char*> *jlabels,
6406                 Vector<char*> *jvalues)
6407 {
6408   char *name, *type, *member, *elist;
6409   DataObject *dobj;
6410   Vector<DataObject *> *delem;
6411   Histable *scope;
6412   int index;
6413   char *size, *offset, *elements, *scopename;
6414
6415   // Get the data object elements
6416   member = elist = type = size = offset = elements = scopename = NULL;
6417
6418   if (objs->size () == 1)
6419     {
6420       Histable *current_obj = objs->fetch (0);
6421       name = dbe_strdup (current_obj->get_name ());
6422       dobj = (DataObject *) current_obj;
6423       type = dobj->get_typename ();
6424       scope = dobj->get_scope ();
6425       delem = dbeSession->get_dobj_elements (dobj);
6426       if (type == NULL)
6427         type = GTXT ("(Synthetic)");
6428       if (!scope)
6429         scopename = dbe_strdup (GTXT ("(Global)"));
6430       else
6431         {
6432           switch (scope->get_type ())
6433             {
6434             case Histable::FUNCTION:
6435               scopename = dbe_sprintf (NTXT ("%s(%s)"),
6436                                        ((Function*) scope)->module->get_name (),
6437                                        scope->get_name ());
6438               break;
6439             case Histable::LOADOBJECT:
6440             case Histable::MODULE:
6441             default:
6442               scopename = dbe_strdup (scope->get_name ());
6443               break;
6444             }
6445         }
6446
6447       if (dobj->get_offset () != -1)
6448         {
6449           if (dobj->get_parent ())
6450             member = dbe_strdup (dobj->get_parent ()->get_name ());
6451           offset = dbe_sprintf (NTXT ("%lld"), (long long) dobj->get_offset ());
6452         }
6453       size = dbe_sprintf ("%lld", (long long) dobj->get_size ());
6454
6455       if (delem->size () > 0)
6456         {
6457           elements = dbe_sprintf (NTXT ("%lld"), (long long) delem->size ());
6458           StringBuilder sb_tmp, sb;
6459           sb.append (GTXT ("Offset Size  Name\n"));
6460           for (index = 0; index < delem->size (); index++)
6461             {
6462               DataObject *ditem = delem->fetch (index);
6463               sb_tmp.sprintf (NTXT ("%6lld %5lld  %s\n"),
6464                               (long long) ditem->get_offset (),
6465                               (long long) ditem->get_size (), ditem->get_name ());
6466               sb.append (&sb_tmp);
6467             }
6468           if (sb.charAt (sb.length () - 1) == '\n')
6469             sb.setLength (sb.length () - 1);
6470           elist = sb.toString ();
6471         }
6472     }
6473   else
6474     name = dbe_sprintf (NTXT ("%s (%lld %s)"), GTXT ("Multiple Selection"),
6475                         (long long) objs->size (), GTXT ("objects"));
6476
6477   saligns->store (0, TEXT_LEFT);
6478   mnemonic->store (0, 'D');
6479   jlabels->store (0, dbe_strdup (GTXT ("Data Object")));
6480   jvalues->store (0, name);
6481
6482   saligns->store (1, TEXT_LEFT);
6483   mnemonic->store (1, 'S');
6484   jlabels->store (1, dbe_strdup (GTXT ("Scope")));
6485   jvalues->store (1, scopename);
6486
6487   saligns->store (2, TEXT_LEFT);
6488   mnemonic->store (2, 'T');
6489   jlabels->store (2, dbe_strdup (GTXT ("Type")));
6490   jvalues->store (2, dbe_strdup (type));
6491
6492   saligns->store (3, TEXT_LEFT);
6493   mnemonic->store (3, 'M');
6494   jlabels->store (3, dbe_strdup (GTXT ("Member of")));
6495   jvalues->store (3, member);
6496
6497   saligns->store (4, TEXT_LEFT);
6498   mnemonic->store (4, 'O');
6499   jlabels->store (4, dbe_strdup (GTXT ("Offset")));
6500   jvalues->store (4, offset);
6501
6502   saligns->store (5, TEXT_LEFT);
6503   mnemonic->store (5, 'z');
6504   jlabels->store (5, dbe_strdup (GTXT ("Size")));
6505   jvalues->store (5, size);
6506
6507   saligns->store (6, TEXT_LEFT);
6508   mnemonic->store (6, 'E');
6509   jlabels->store (6, dbe_strdup (GTXT ("Elements")));
6510   jvalues->store (6, elements);
6511
6512   saligns->store (7, TEXT_LEFT);
6513   mnemonic->store (7, 'L');
6514   jlabels->store (7, dbe_strdup (GTXT ("List")));
6515   jvalues->store (7, elist);
6516 }
6517
6518 #define SUMMARY_NAME 8
6519 #define DSUMMARY_NAME 8
6520 #define LSUMMARY_NAME   7
6521 #define IMSUMMARY_NAME   1
6522
6523 Vector<void*> *
6524 dbeGetSummaryV2 (int dbevindex, Vector<Obj> *sel_objs, int type, int subtype)
6525 {
6526   if (sel_objs == NULL || sel_objs->size () == 0)
6527     return NULL;
6528   DbeView *dbev = dbeSession->getView (dbevindex);
6529   Vector<Histable*>*objs = new Vector<Histable*>(sel_objs->size ());
6530   for (int i = 0; i < sel_objs->size (); i++)
6531     {
6532       Histable *obj = (Histable *) sel_objs->fetch (i);
6533       if (obj == NULL)
6534         continue;
6535       char *nm = obj->get_name ();
6536       if (streq (nm, NTXT ("<Total>")))
6537         {
6538           // Special case for 'Total'.
6539           // Multi selection which includes 'Total' is only 'Total'
6540           objs->reset ();
6541           objs->append (obj);
6542           break;
6543         }
6544       objs->append (obj);
6545     }
6546   if (objs->size () == 0)
6547     return NULL;
6548
6549   // Set name area
6550   int nname = SUMMARY_NAME;
6551   Vector<int> *saligns = new Vector<int>(nname);
6552   Vector<char>*mnemonic = new Vector<char>(nname);
6553   Vector<char*> *jlabels = new Vector<char*>(nname);
6554   Vector<char*> *jvalues = new Vector<char*>(nname);
6555   Vector<void*> *name_objs = new Vector<void*>(4);
6556   name_objs->store (0, saligns);
6557   name_objs->store (1, mnemonic);
6558   name_objs->store (2, jlabels);
6559   name_objs->store (3, jvalues);
6560   setSummary (objs, saligns, mnemonic, jlabels, jvalues);
6561
6562   MetricList *prop_mlist = new MetricList (dbev->get_metric_ref (MET_NORMAL));
6563   if (prop_mlist && dbev->comparingExperiments ())
6564     prop_mlist = dbev->get_compare_mlist (prop_mlist, 0);
6565
6566   int nitems = prop_mlist->get_items ()->size ();
6567
6568   // Set the metrics area
6569   jlabels = new Vector<char*>(nitems);
6570   Vector<double> *clock_list = new Vector<double>(nitems);
6571   Vector<double> *excl_list = new Vector<double>(nitems);
6572   Vector<double> *ep_list = new Vector<double>(nitems);
6573   Vector<double> *incl_list = new Vector<double>(nitems);
6574   Vector<double> *ip_list = new Vector<double>(nitems);
6575   Vector<int> *vtype = new Vector<int>(nitems);
6576
6577   // Initialize Java String array
6578   Vector<void*> *metric_objs = new Vector<void*>(8);
6579   metric_objs->store (0, jlabels);
6580   metric_objs->store (1, clock_list);
6581   metric_objs->store (2, excl_list);
6582   metric_objs->store (3, ep_list);
6583   metric_objs->store (4, incl_list);
6584   metric_objs->store (5, ip_list);
6585   metric_objs->store (6, vtype);
6586
6587   int last_init = -1;
6588   for (int i = 0; i < objs->size (); i++)
6589     {
6590       Histable *obj = objs->fetch (i);
6591       // Get the data to be displayed
6592       Hist_data *data = dbev->get_hist_data (prop_mlist, obj->get_type (), subtype,
6593                                              Hist_data::SELF, obj, dbev->sel_binctx, objs);
6594
6595       if (data->get_status () != Hist_data::SUCCESS)
6596         {
6597           if (type != DSP_DLAYOUT)
6598             { // For data_layout, rows with zero metrics are OK
6599               delete data;
6600               continue;
6601             }
6602         }
6603       TValue *values = NULL;
6604       if (data->get_status () == Hist_data::SUCCESS)
6605         {
6606           Hist_data::HistItem *hi = data->fetch (0);
6607           if (hi)
6608             values = hi->value;
6609         }
6610       Hist_data::HistItem *total = data->get_totals ();
6611       int index2 = 0;
6612       char *tstr = GTXT (" Time");
6613       char *estr = GTXT ("Exclusive ");
6614       size_t len = strlen (estr);
6615
6616       // get the metric list from the data
6617       MetricList *mlist = data->get_metric_list ();
6618       int index;
6619       Metric *mitem;
6620       double clock;
6621       Vec_loop (Metric*, mlist->get_items (), index, mitem)
6622       {
6623         if (mitem->get_subtype () == Metric::STATIC)
6624           continue;
6625         if (last_init < index2)
6626           {
6627             last_init = index2;
6628             jlabels->store (index2, NULL);
6629             clock_list->store (index2, 0.0);
6630             excl_list->store (index2, 0.0);
6631             ep_list->store (index2, 0.0);
6632             incl_list->store (index2, 0.0);
6633             ip_list->store (index2, 0.0);
6634             vtype->store (index2, 0);
6635           }
6636         double dvalue = (values != NULL) ? values[index].to_double () : 0.0;
6637         double dtotal = total->value[index].to_double ();
6638         if (mitem->is_time_val ())
6639           clock = 1.e+6 * dbeSession->get_clock (-1);
6640         else
6641           clock = 0.0;
6642
6643         clock_list->store (index2, clock);
6644         if ((mitem->get_subtype () == Metric::EXCLUSIVE) ||
6645             (mitem->get_subtype () == Metric::DATASPACE))
6646           {
6647             if (i == 0)
6648               {
6649                 char *sstr = mitem->get_name ();
6650                 if (!strncmp (sstr, estr, len))
6651                   sstr += len;
6652                 char *buf, *lstr = strstr (sstr, tstr);
6653                 if (lstr)
6654                   buf = dbe_strndup (sstr, lstr - sstr);
6655                 else
6656                   buf = dbe_strdup (sstr);
6657                 jlabels->store (index2, buf);
6658                 vtype->store (index2, mitem->get_vtype ());
6659               }
6660             dvalue += excl_list->fetch (index2);
6661             double percent = dtotal == 0.0 ? dtotal : (dvalue / dtotal) * 100;
6662             excl_list->store (index2, dvalue);
6663             ep_list->store (index2, percent);
6664           }
6665         else
6666           {
6667             dvalue += incl_list->fetch (index2);
6668             if (dvalue > dtotal)
6669               dvalue = dtotal; // temporary correction
6670             double percent = dtotal == 0.0 ? dtotal : (dvalue / dtotal) * 100;
6671             incl_list->store (index2, dvalue);
6672             ip_list->store (index2, percent);
6673             index2++;
6674           }
6675       }
6676       delete data;
6677     }
6678   delete prop_mlist;
6679   Vector<void*> *summary = new Vector<void*>(2);
6680   summary->store (0, name_objs);
6681   summary->store (1, metric_objs);
6682   return summary;
6683 }
6684
6685 // Get Summary List
6686 Vector<void*> *
6687 dbeGetSummary (int dbevindex, Vector<Obj> *sel_objs, int type, int subtype)
6688 {
6689   bool is_data, is_mem, is_indx, is_iodata, is_heapdata;
6690   Hist_data::HistItem *total;
6691   MetricList *prop_mlist; // as passed to get_hist_data
6692   MetricList *mlist; // as stored in the data
6693   Metric *mitem;
6694   int i, nname, nitems, index, index2;
6695   TValue *values;
6696   double dvalue, clock;
6697   Hist_data *data;
6698   Vector<double> *percent_scale;
6699
6700   DbeView *dbev = dbeSession->getView (dbevindex);
6701   if (dbev == NULL)
6702     abort ();
6703   if (sel_objs == NULL || sel_objs->size () == 0)
6704     return NULL;
6705
6706   is_mem = false;
6707   is_data = false;
6708   is_indx = false;
6709   is_iodata = false;
6710   is_heapdata = false;
6711   nname = SUMMARY_NAME;
6712   Vector<Histable*>*objs = new Vector<Histable*>(sel_objs->size ());
6713   if (type == DSP_TIMELINE)
6714     objs->append ((Histable *) sel_objs->fetch (0));
6715   else
6716     {
6717       switch (type)
6718         {
6719         case DSP_FUNCTION:
6720           data = dbev->func_data;
6721           break;
6722         case DSP_LINE:
6723           data = dbev->line_data;
6724           break;
6725         case DSP_PC:
6726           data = dbev->pc_data;
6727           break;
6728         case DSP_SELF:
6729           data = dbev->fitem_data;
6730           break;
6731         case DSP_SOURCE:
6732         case DSP_SOURCE_V2:
6733           data = dbev->src_data;
6734           break;
6735         case DSP_DISASM:
6736         case DSP_DISASM_V2:
6737           data = dbev->dis_data;
6738           break;
6739         case DSP_DLAYOUT:
6740           is_data = true;
6741           nname = LSUMMARY_NAME;
6742           data = dbev->dlay_data;
6743           break;
6744         case DSP_DATAOBJ:
6745           is_data = true;
6746           nname = DSUMMARY_NAME;
6747           data = dbev->dobj_data;
6748           break;
6749         case DSP_MEMOBJ:
6750           is_data = true;
6751           is_mem = true;
6752           nname = IMSUMMARY_NAME;
6753           data = dbev->get_indxobj_data (subtype);
6754           break;
6755         case DSP_INDXOBJ:
6756           is_indx = true;
6757           nname = IMSUMMARY_NAME;
6758           data = dbev->get_indxobj_data (subtype);
6759           break;
6760         case DSP_IOACTIVITY:
6761           is_iodata = true;
6762           nname = IMSUMMARY_NAME;
6763           data = dbev->iofile_data;
6764           break;
6765         case DSP_IOVFD:
6766           is_iodata = true;
6767           nname = IMSUMMARY_NAME;
6768           data = dbev->iovfd_data;
6769           break;
6770         case DSP_IOCALLSTACK:
6771           is_iodata = true;
6772           nname = IMSUMMARY_NAME;
6773           data = dbev->iocs_data;
6774           break;
6775         case DSP_HEAPCALLSTACK:
6776           is_heapdata = true;
6777           nname = IMSUMMARY_NAME;
6778           data = dbev->heapcs_data;
6779           break;
6780         default:
6781           data = NULL;
6782           break;
6783         }
6784       if (data == NULL || data->get_status () != Hist_data::SUCCESS)
6785         return NULL;
6786
6787       Hist_data::HistItem *current_item;
6788       for (i = 0; i < sel_objs->size (); i++)
6789         {
6790           int sel_index = (int) sel_objs->fetch (i);
6791           if (type != DSP_IOACTIVITY && type != DSP_IOVFD &&
6792               type != DSP_IOCALLSTACK && type != DSP_HEAPCALLSTACK)
6793             {
6794               if (sel_index < 0 || sel_index >= data->size ())
6795                 continue;
6796               current_item = data->fetch (sel_index);
6797               if (current_item->obj == NULL)
6798                 continue;
6799             }
6800           else
6801             {
6802               if (sel_index < 0)
6803                 continue;
6804               bool found = false;
6805               for (int j = 0; j < data->size (); j++)
6806                 {
6807                   current_item = data->fetch (j);
6808                   if ((current_item->obj != NULL) && (current_item->obj->id == sel_index))
6809                     {
6810                       found = true;
6811                       break;
6812                     }
6813                 }
6814               if (!found)
6815                 continue;
6816             }
6817           char *nm = current_item->obj->get_name ();
6818           if (streq (nm, NTXT ("<Total>")))
6819             {
6820               // Special case for 'Total'.
6821               // Multi selection which includes 'Total' is only 'Total'
6822               objs->reset ();
6823               objs->append (current_item->obj);
6824               break;
6825             }
6826           objs->append (current_item->obj);
6827         }
6828     }
6829   if (objs->size () == 0)
6830     return NULL;
6831
6832   // Set name area
6833   Vector<int> *saligns = new Vector<int>(nname);
6834   Vector<char>*mnemonic = new Vector<char>(nname);
6835   Vector<char*> *jlabels = new Vector<char*>(nname);
6836   Vector<char*> *jvalues = new Vector<char*>(nname);
6837   Vector<void*> *name_objs = new Vector<void*>(4);
6838   name_objs->store (0, saligns);
6839   name_objs->store (1, mnemonic);
6840   name_objs->store (2, jlabels);
6841   name_objs->store (3, jvalues);
6842   if (is_mem)
6843     setMemSummary (objs, saligns, mnemonic, jlabels, jvalues);
6844   else if (is_indx)
6845     setIndxSummary (objs, saligns, mnemonic, jlabels, jvalues);
6846   else if (is_data)
6847     setDataSummary (objs, saligns, mnemonic, jlabels, jvalues);
6848   else if (is_iodata)
6849     setIOActivitySummary (objs, saligns, mnemonic, jlabels, jvalues);
6850   else if (is_heapdata)
6851     setHeapActivitySummary (objs, saligns, mnemonic, jlabels, jvalues);
6852   else
6853     setSummary (objs, saligns, mnemonic, jlabels, jvalues);
6854
6855   // Get the reference metrics
6856   if (is_data)
6857     prop_mlist = new MetricList (dbev->get_metric_ref (MET_DATA));
6858   else if (is_indx)
6859     prop_mlist = new MetricList (dbev->get_metric_ref (MET_INDX));
6860   else if (is_iodata)
6861     prop_mlist = new MetricList (dbev->get_metric_ref (MET_IO));
6862   else if (is_heapdata)
6863     prop_mlist = new MetricList (dbev->get_metric_ref (MET_HEAP));
6864   else
6865     prop_mlist = new MetricList (dbev->get_metric_ref (MET_NORMAL));
6866
6867   // XXXX a workaround to avoid aggregated data for compare mode, only show base experiment data
6868   if (prop_mlist && dbev->comparingExperiments ())
6869     prop_mlist = dbev->get_compare_mlist (prop_mlist, 0);
6870   nitems = prop_mlist->get_items ()->size ();
6871
6872   // Set the metrics area
6873   jlabels = new Vector<char*>(nitems);
6874   Vector<double> *clock_list = new Vector<double>(nitems);
6875   Vector<double> *excl_list = new Vector<double>(nitems);
6876   Vector<double> *ep_list = new Vector<double>(nitems);
6877   Vector<double> *incl_list = new Vector<double>(nitems);
6878   Vector<double> *ip_list = new Vector<double>(nitems);
6879   Vector<int> *vtype = new Vector<int>(nitems);
6880
6881   // Initialize Java String array
6882   Vector<void*> *metric_objs = new Vector<void*>(8);
6883   metric_objs->store (0, jlabels);
6884   metric_objs->store (1, clock_list);
6885   metric_objs->store (2, excl_list);
6886   metric_objs->store (3, ep_list);
6887   metric_objs->store (4, incl_list);
6888   metric_objs->store (5, ip_list);
6889   metric_objs->store (6, vtype);
6890   percent_scale = new Vector<double>();
6891   int last_init = -1;
6892   for (i = 0; i < objs->size (); i++)
6893     {
6894       Histable *current_obj = objs->fetch (i);
6895       // Get the data to be displayed
6896       data = dbev->get_hist_data (prop_mlist, current_obj->get_type (), subtype,
6897                                   Hist_data::SELF, current_obj, dbev->sel_binctx, objs);
6898       if (data->get_status () != Hist_data::SUCCESS)
6899         {
6900           if (type != DSP_DLAYOUT)
6901             { // For data_layout, rows with zero metrics are OK
6902               delete data;
6903               continue;
6904             }
6905         }
6906       Hist_data::HistItem *hi = data->fetch (0);
6907       values = hi ? hi->value : NULL;
6908       total = data->get_totals ();
6909       index2 = 0;
6910
6911       // get the metric list from the data
6912       mlist = data->get_metric_list ();
6913
6914       // We loop over the metrics in mlist.
6915       // We construct index2, which tells us
6916       // the corresponding entry in the metric_objs lists.
6917       // We need this mapping multiple times.
6918       // So, if you change the looping in any way here,
6919       // do so as well in other similar loops.
6920       // All such loops are marked so:
6921       // See discussion on "mlist-to-index2 mapping".
6922
6923       Vec_loop (Metric*, mlist->get_items (), index, mitem)
6924       {
6925         if (mitem->get_subtype () == Metric::STATIC)
6926           continue;
6927         if (last_init < index2)
6928           {
6929             last_init = index2;
6930             jlabels->store (index2, NULL);
6931             clock_list->store (index2, 0.0);
6932             excl_list->store (index2, 0.0);
6933             ep_list->store (index2, 0.0);
6934             incl_list->store (index2, 0.0);
6935             ip_list->store (index2, 0.0);
6936             vtype->store (index2, 0);
6937           }
6938         dvalue = (values != NULL) ? values[index].to_double () : 0.0;
6939         double dtotal = total->value[index].to_double ();
6940         percent_scale->store (index, dtotal == 0. ? 0. : 100. / dtotal);
6941         if (mitem->is_time_val ())
6942           clock = 1.e+6 * dbeSession->get_clock (-1);
6943         else
6944           clock = 0.0;
6945
6946         clock_list->store (index2, clock);
6947         if (mitem->get_subtype () == Metric::EXCLUSIVE ||
6948             mitem->get_subtype () == Metric::DATASPACE)
6949           {
6950             if (i == 0)
6951               {
6952                 char *sstr = mitem->get_username ();
6953                 char *buf = dbe_strdup (sstr);
6954                 jlabels->store (index2, buf);
6955                 vtype->store (index2, mitem->get_vtype ());
6956               }
6957             dvalue += excl_list->fetch (index2);
6958             double percent = dvalue * percent_scale->fetch (index);
6959             excl_list->store (index2, dvalue);
6960             ep_list->store (index2, percent);
6961             if (is_data || is_indx || is_iodata || is_heapdata)
6962               // move to next row, except if there's inclusive data, too
6963               index2++;
6964           }
6965         else
6966           {
6967             dvalue += incl_list->fetch (index2);
6968             if (dvalue > dtotal && mitem->get_type () != BaseMetric::DERIVED)
6969               dvalue = dtotal; // temporary correction
6970             double percent = dvalue * percent_scale->fetch (index);
6971             incl_list->store (index2, dvalue);
6972             ip_list->store (index2, percent);
6973             index2++;
6974           }
6975       }
6976       delete data;
6977     }
6978
6979   // for multi-selection, we have to recompute the derived metrics
6980   if (objs->size () > 1 &&
6981       dbev->get_derived_metrics () != NULL &&
6982       dbev->get_derived_metrics ()->get_items () != NULL &&
6983       dbev->get_derived_metrics ()->get_items ()->size () > 0)
6984     {
6985       // See discussion on "mlist-to-index2 mapping".
6986       Vector<Metric*> *mvec = new Vector<Metric*>(nitems);
6987       index2 = 0;
6988       Vec_loop (Metric*, prop_mlist->get_items (), index, mitem)
6989       {
6990         if (mitem->get_subtype () == Metric::STATIC)
6991           continue;
6992         if (mitem->get_subtype () == Metric::EXCLUSIVE ||
6993             mitem->get_subtype () == Metric::DATASPACE)
6994           {
6995             mvec->store (index2, mitem);
6996             if (is_data || is_indx || is_iodata || is_heapdata)
6997               index2++;
6998           }
6999         else
7000           {
7001             assert (strcmp (mvec->fetch (index2)->get_cmd (), mitem->get_cmd ()) == 0);
7002             index2++;
7003           }
7004       }
7005       int *map = dbev->get_derived_metrics ()->construct_map (mvec, BaseMetric::EXCLUSIVE, mvec->fetch (0)->get_expr_spec ());
7006       if (map != NULL)
7007         {
7008           int nmetrics = mvec->size ();
7009           double *evalues = (double *) malloc (nmetrics * sizeof (double));
7010           double *ivalues = (double *) malloc (nmetrics * sizeof (double));
7011           for (index2 = 0; index2 < nmetrics; index2++)
7012             {
7013               evalues[index2] = excl_list->fetch (index2);
7014               ivalues[index2] = incl_list->fetch (index2);
7015             }
7016
7017           // evaluate derived metrics
7018           dbev->get_derived_metrics ()->eval (map, evalues);
7019           dbev->get_derived_metrics ()->eval (map, ivalues);
7020           for (index2 = 0; index2 < nmetrics; index2++)
7021             {
7022               excl_list->store (index2, evalues[index2]);
7023               incl_list->store (index2, ivalues[index2]);
7024             }
7025
7026           // recompute percentages for derived metrics    EUGENE maybe all percentage computations should be moved here
7027           // See discussion on "mlist-to-index2 mapping".
7028           index2 = 0;
7029           Vec_loop (Metric*, prop_mlist->get_items (), index, mitem)
7030           {
7031             if (mitem->get_subtype () == Metric::STATIC)
7032               continue;
7033             if (mitem->get_subtype () == Metric::EXCLUSIVE ||
7034                 mitem->get_subtype () == Metric::DATASPACE)
7035               {
7036                 if (mitem->get_type () == BaseMetric::DERIVED)
7037                   ep_list->store (index2, excl_list->fetch (index2) * percent_scale->fetch (index));
7038                 if (is_data || is_indx || is_iodata || is_heapdata)
7039                   index2++;
7040               }
7041             else
7042               {
7043                 if (mitem->get_type () == BaseMetric::DERIVED)
7044                   ip_list->store (index2, incl_list->fetch (index2) * percent_scale->fetch (index));
7045                 index2++;
7046               }
7047           }
7048           free (evalues);
7049           free (ivalues);
7050           free (map);
7051         }
7052       delete mvec;
7053     }
7054   delete prop_mlist;
7055   Vector<void*> *summary = new Vector<void*>(2);
7056   summary->store (0, name_objs);
7057   summary->store (1, metric_objs);
7058   delete objs;
7059   delete percent_scale;
7060   return summary;
7061 }
7062
7063 char *
7064 dbeGetExpName (int /*dbevindex*/, char *dir_name)
7065 {
7066   char *ret;
7067   char *warn;
7068   if (col_ctr == NULL)
7069     col_ctr = new Coll_Ctrl (1); // Potential race condition?
7070   if (dir_name != NULL)
7071     {
7072       ret = col_ctr->set_directory (dir_name, &warn);
7073       // note that the warning and error msgs are written to stderr, not returned to caller
7074       if (warn != NULL)
7075         fprintf (stderr, NTXT ("%s"), warn);
7076       if (ret != NULL)
7077         fprintf (stderr, NTXT ("%s"), ret);
7078     }
7079   return dbe_strdup (col_ctr->get_expt ());
7080 }
7081
7082 // === CollectDialog HWC info ===
7083
7084 Vector<Vector<char*>*> *
7085 dbeGetHwcSets (int /*dbevindex*/, bool forKernel)
7086 {
7087   Vector<Vector<char*>*> *list = new Vector<Vector<char*>*>(2);
7088   char * defctrs = hwc_get_default_cntrs2 (forKernel, 1);
7089   Vector<char*> *i18n = new Vector<char*>(1); // User name
7090   Vector<char*> *name = new Vector<char*>(1); // Internal name
7091   if (NULL != defctrs)
7092     {
7093       i18n->store (0, strdup (defctrs));
7094       name->store (0, strdup (NTXT ("default")));
7095     }
7096   list->store (0, i18n);
7097   list->store (1, name);
7098   return list;
7099 }
7100
7101 static Vector<void*> *
7102 dbeGetHwcs (Hwcentry **hwcs)
7103 {
7104   int sz;
7105   for (sz = 0; hwcs && hwcs[sz]; sz++)
7106     ;
7107   Vector<void*> *list = new Vector<void*>(9);
7108   Vector<char*> *i18n = new Vector<char*>(sz);
7109   Vector<char*> *name = new Vector<char*>(sz);
7110   Vector<char*> *int_name = new Vector<char*>(sz);
7111   Vector<char*> *metric = new Vector<char*>(sz);
7112   Vector<long long> *val = new Vector<long long>(sz);
7113   Vector<int> *timecvt = new Vector<int>(sz);
7114   Vector<int> *memop = new Vector<int>(sz);
7115   Vector<char*> *short_desc = new Vector<char*>(sz);
7116   Vector<Vector<int>*> *reglist_v = new Vector<Vector<int>*>(sz);
7117   Vector<bool> *supportsAttrs = new Vector<bool>(sz);
7118   Vector<bool> *supportsMemspace = new Vector<bool>(sz);
7119
7120   for (int i = 0; i < sz; i++)
7121     {
7122       Hwcentry *ctr = hwcs[i];
7123       Vector<int> *registers = new Vector<int>(MAX_PICS);
7124       regno_t *reglist = ctr->reg_list;
7125       for (int k = 0; !REG_LIST_EOL (reglist[k]) && k < MAX_PICS; k++)
7126         registers->store (k, reglist[k]);
7127
7128       i18n->store (i, dbe_strdup (hwc_i18n_metric (ctr)));
7129       name->store (i, dbe_strdup (ctr->name));
7130       int_name->store (i, dbe_strdup (ctr->int_name));
7131       metric->store (i, dbe_strdup (ctr->metric));
7132       val->store (i, ctr->val); // signed promotion from int
7133       timecvt->store (i, ctr->timecvt);
7134       memop->store (i, ctr->memop);
7135       reglist_v->store (i, registers);
7136       short_desc->store (i, dbe_strdup (ctr->short_desc));
7137       supportsAttrs->store (i, true);
7138       supportsMemspace->store (i, ABST_MEMSPACE_ENABLED (ctr->memop));
7139     }
7140   list->store (0, i18n);
7141   list->store (1, name);
7142   list->store (2, int_name);
7143   list->store (3, metric);
7144   list->store (4, val);
7145   list->store (5, timecvt);
7146   list->store (6, memop);
7147   list->store (7, short_desc);
7148   list->store (8, reglist_v);
7149   list->store (9, supportsAttrs);
7150   list->store (10, supportsMemspace);
7151   return list;
7152 }
7153
7154 Vector<void *> *
7155 dbeGetHwcsAll (int /*dbevindex*/, bool forKernel)
7156 {
7157   Vector<void*> *list = new Vector<void*>(2);
7158   list->store (0, dbeGetHwcs (hwc_get_std_ctrs (forKernel)));
7159   list->store (1, dbeGetHwcs (hwc_get_raw_ctrs (forKernel)));
7160   return list;
7161 }
7162
7163 Vector<char*> *
7164 dbeGetHwcHelp (int /*dbevindex*/, bool forKernel)
7165 {
7166   Vector<char*> *strings = new Vector<char*>(32);
7167   FILE *f = tmpfile ();
7168   hwc_usage_f (forKernel, f, "", 0, 0, 1); // writes to f
7169   fflush (f);
7170   fseek (f, 0, SEEK_SET);
7171 #define MAX_LINE_LEN 2048
7172   char buff[MAX_LINE_LEN];
7173   int ii = 0;
7174   while (fgets (buff, MAX_LINE_LEN, f))
7175     strings->store (ii++, dbe_strdup (buff));
7176   fclose (f);
7177   return strings;
7178 }
7179
7180 Vector<char*> *
7181 dbeGetHwcAttrList (int /*dbevindex*/, bool forKernel)
7182 {
7183   char ** attr_list = hwc_get_attrs (forKernel); // Get Attribute list
7184   int size;
7185   for (size = 0; attr_list && attr_list[size]; size++)
7186     ;
7187
7188   Vector<char*> *name = new Vector<char*>(size);
7189   for (int i = 0; i < size; i++)
7190     name->store (i, dbe_strdup (attr_list[i]));
7191   return name;
7192 }
7193
7194 //Get maximum number of simultaneous counters
7195 int
7196 dbeGetHwcMaxConcurrent (int /*dbevindex*/, bool forKernel)
7197 {
7198   return hwc_get_max_concurrent (forKernel);
7199 }
7200
7201 // === End CollectDialog HWC info ===
7202
7203
7204 //  Instruction-frequency data
7205 Vector<char*> *
7206 dbeGetIfreqData (int dbevindex)
7207 {
7208   DbeView *dbev = dbeSession->getView (dbevindex);
7209   if (dbev == NULL)
7210     abort ();
7211   if (!dbeSession->is_ifreq_available ())
7212     return NULL;
7213   int size = dbeSession->nexps ();
7214   if (size == 0)
7215     return NULL;
7216
7217   // Initialize Java String array
7218   Vector<char*> *list = new Vector<char*>();
7219   for (int i = 0; i < size; i++)
7220     {
7221       Experiment *exp = dbeSession->get_exp (i);
7222       if (exp->broken || !dbev->get_exp_enable (i) || !exp->ifreqavail)
7223         continue;
7224       // write a header for the experiment
7225       list->append (dbe_sprintf (GTXT ("Instruction frequency data from experiment %s\n\n"),
7226                                  exp->get_expt_name ()));
7227       // add its instruction frequency messages
7228       char *ifreq = pr_mesgs (exp->fetch_ifreq (), NTXT (""), NTXT (""));
7229       list->append (ifreq);
7230     }
7231   return list;
7232 }
7233
7234 //   LeakList related methods
7235 //
7236 Vector<void*> *
7237 dbeGetLeakListInfo (int dbevindex, bool leakflag)
7238 {
7239   DbeView *dbev = dbeSession->getView (dbevindex);
7240   if (dbev == NULL)
7241     abort ();
7242   MetricList *origmlist = dbev->get_metric_list (MET_NORMAL);
7243   MetricList *nmlist = new MetricList (origmlist);
7244   if (leakflag)
7245     nmlist->set_metrics (NTXT ("e.heapleakbytes:e.heapleakcnt:name"), true,
7246                          dbev->get_derived_metrics ());
7247   else
7248     nmlist->set_metrics (NTXT ("e.heapallocbytes:e.heapalloccnt:name"), true,
7249                          dbev->get_derived_metrics ());
7250   MetricList *mlist = new MetricList (nmlist);
7251   delete nmlist;
7252
7253   CStack_data *lam = dbev->get_cstack_data (mlist);
7254   if (lam == NULL || lam->size () == 0)
7255     {
7256       delete lam;
7257       delete mlist;
7258       return NULL;
7259     }
7260   Vector<Vector<Obj>*> *evalue = new Vector<Vector<Obj>*>(lam->size ());
7261   Vector<Vector<Obj>*> *pcstack = new Vector<Vector<Obj>*>(lam->size ());
7262   Vector<Vector<Obj>*> *offstack = new Vector<Vector<Obj>*>(lam->size ());
7263   Vector<Vector<Obj>*> *fpcstack = new Vector<Vector<Obj>*>(lam->size ());
7264   Vector<Vector<Obj>*> *sumval = new Vector<Vector<Obj>*>(lam->size ());
7265
7266   int index;
7267   CStack_data::CStack_item *lae;
7268   Vec_loop (CStack_data::CStack_item*, lam->cstack_items, index, lae)
7269   {
7270     Vector<Obj> *jivals = NULL;
7271     if (lae != NULL)
7272       {
7273         jivals = new Vector<Obj>(4);
7274         jivals->store (0, (Obj) (index + 1));
7275         jivals->store (1, (Obj) lae->value[1].ll);
7276         jivals->store (2, (Obj) lae->value[0].ll);
7277         jivals->store (3, (Obj) (leakflag ? 1 : 2));
7278       }
7279     evalue->store (index, jivals);
7280     int snum = lae->stack->size ();
7281     Vector<Obj> *jivals1 = new Vector<Obj>(snum);
7282     Vector<Obj> *jivals2 = new Vector<Obj>(snum);
7283     Vector<Obj> *jivals3 = new Vector<Obj>(snum);
7284     if (lae->stack != NULL)
7285       {
7286         for (int i = lae->stack->size () - 1; i >= 0; i--)
7287           {
7288             DbeInstr *instr = lae->stack->fetch (i);
7289             jivals1->store (i, (Obj) instr);
7290             jivals2->store (i, (Obj) instr->func);
7291             jivals3->store (i, (Obj) instr->addr);
7292           }
7293       }
7294     fpcstack->store (index, jivals1);
7295     pcstack->store (index, jivals2);
7296     offstack->store (index, jivals3);
7297     lae++;
7298   }
7299   Vector<Obj> *jivals4 = new Vector<Obj>(3);
7300   jivals4->store (0, (Obj) lam->size ());
7301   jivals4->store (1, (Obj) lam->total->value[1].ll);
7302   jivals4->store (2, (Obj) lam->total->value[0].ll);
7303   sumval->store (0, jivals4);
7304   delete lam;
7305   delete mlist;
7306   Vector<void*> *earray = new Vector<void*>(5);
7307   earray->store (0, evalue);
7308   earray->store (1, pcstack);
7309   earray->store (2, offstack);
7310   earray->store (3, fpcstack);
7311   earray->store (4, sumval);
7312   return earray;
7313 }
7314
7315 // Map timeline address to function instr
7316 //
7317 Obj
7318 dbeGetObject (int dbevindex, Obj sel_func, Obj sel_pc)
7319 {
7320   DbeView *dbev = dbeSession->getView (dbevindex);
7321   if (dbev == NULL)
7322    abort ();
7323   if (sel_pc)
7324     return sel_pc;
7325   return sel_func;
7326 }
7327
7328 char *
7329 dbeGetName (int /*dbevindex*/, int exp_id)
7330 // This function's name is not descriptive enough - it returns a string
7331 //   containing the full experiment name with path, process name, and PID.
7332 // There are various dbe functions that provide experiment name and experiment
7333 // details, and they should probably be consolidated/refactored. (TBR)
7334 // For another example of similar output formatting, see dbeGetExpName().
7335 {
7336   int id = (exp_id < 0) ? 0 : exp_id;
7337   Experiment *exp = dbeSession->get_exp (id);
7338   if (exp == NULL)
7339     return NULL;
7340   char *buf =
7341           dbe_sprintf (NTXT ("%s [%s, PID %d]"),
7342                        exp->get_expt_name (),
7343                        exp->utargname != NULL ? exp->utargname : GTXT ("(unknown)"),
7344                        exp->getPID ());
7345   return buf;
7346 }
7347
7348 Vector<char*> *
7349 dbeGetExpVerboseName (Vector<int> *exp_ids)
7350 {
7351   int len = exp_ids->size ();
7352   Vector<char*> *list = new Vector<char*>(len);
7353   for (int i = 0; i < len; i++)
7354     {
7355       char * verboseName = dbeGetName (0, exp_ids->fetch (i)); // no strdup()
7356       list->store (i, verboseName);
7357     }
7358   return list;
7359 }
7360
7361 long long
7362 dbeGetStartTime (int /*dbevindex*/, int exp_id)
7363 {
7364   int id = (exp_id < 0) ? 0 : exp_id;
7365   Experiment *exp = dbeSession->get_exp (id);
7366   return exp ? exp->getStartTime () : (long long) 0;
7367 }
7368
7369 long long
7370 dbeGetRelativeStartTime (int /*dbevindex*/, int exp_id)
7371 {
7372   int id = (exp_id < 0) ? 0 : exp_id;
7373   Experiment *exp = dbeSession->get_exp (id);
7374   return exp ? exp->getRelativeStartTime () : (long long) 0;
7375 }
7376
7377 long long
7378 dbeGetEndTime (int /*dbevindex*/, int exp_id)
7379 {
7380   int id = (exp_id < 0) ? 0 : exp_id;
7381   Experiment *exp = dbeSession->get_exp (id);
7382
7383   // Experiment::getEndTime was initially implemented as
7384   // returning exp->last_event. To preserve the semantics
7385   // new Experiment::getLastEvent() is used here.
7386   return exp ? exp->getLastEvent () : (long long) 0;
7387 }
7388
7389 int
7390 dbeGetClock (int /*dbevindex*/, int exp_id)
7391 {
7392   return dbeSession->get_clock (exp_id);
7393 }
7394
7395 long long
7396 dbeGetWallStartSec (int /*dbevindex*/, int exp_id)
7397 {
7398   int id = (exp_id < 0) ? 0 : exp_id;
7399   Experiment *exp = dbeSession->get_exp (id);
7400   return exp ? exp->getWallStartSec () : 0ll;
7401 }
7402
7403 char *
7404 dbeGetHostname (int /*dbevindex*/, int exp_id)
7405 {
7406   int id = (exp_id < 0) ? 0 : exp_id;
7407   Experiment *exp = dbeSession->get_exp (id);
7408   return exp ? dbe_strdup (exp->hostname) : NULL;
7409 }
7410
7411 static DataView *
7412 getTimelinePackets (int dbevindex, int exp_id, int data_id, int entity_prop_id)
7413 {
7414   DbeView *dbev = dbeSession->getView (dbevindex);
7415   if (dbev == NULL)
7416     abort ();
7417   const int sortprop_count = 3;
7418   const int sortprops[sortprop_count] = {
7419     PROP_HWCTAG, // aux
7420     entity_prop_id,
7421     PROP_TSTAMP
7422   };
7423   DataView *packets = dbev->get_filtered_events (exp_id, data_id,
7424                                                  sortprops, sortprop_count);
7425   return packets;
7426 }
7427
7428 static long
7429 getIdxByVals (DataView * packets, int aux, int entity_prop_val,
7430               uint64_t time, DataView::Relation rel)
7431 {
7432   const int sortprop_count = 3;
7433   Datum tval[sortprop_count];
7434   tval[0].setUINT32 (aux);
7435   tval[1].setUINT32 (entity_prop_val); //CPUID, LWPID, THRID are downsized to 32
7436   tval[2].setUINT64 (time);
7437   long idx = packets->getIdxByVals (tval, rel);
7438   return idx;
7439 }
7440
7441 static bool
7442 isValidIdx (DataView * packets, int entity_prop_id,
7443             int aux, int entity_prop_val, long idx)
7444 {
7445   if (idx < 0 || idx >= packets->getSize ())
7446     return false;
7447   int pkt_aux = packets->getIntValue (PROP_HWCTAG, idx);
7448   if (pkt_aux != aux)
7449     return false;
7450   if (entity_prop_id == PROP_EXPID)
7451     return true; // not a packet property; we know the packet is in this experiment
7452   if (entity_prop_id == PROP_NONE)
7453     return true; // not a packet property; we know the packet is in this experiment
7454   int pkt_ent = packets->getIntValue (entity_prop_id, idx);
7455   if (pkt_ent != entity_prop_val)
7456     return false;
7457   return true;
7458 }
7459
7460 static bool
7461 hasInvisbleTLEvents (Experiment *exp, VMode view_mode)
7462 {
7463   if (exp->has_java && view_mode == VMODE_USER)
7464     return true;
7465   return false;
7466 }
7467
7468 static bool
7469 isVisibleTLEvent (Experiment *exp, VMode view_mode, DataView* packets, long idx)
7470 {
7471   if (hasInvisbleTLEvents (exp, view_mode))
7472     {
7473       JThread *jthread = (JThread*) packets->getObjValue (PROP_JTHREAD, idx);
7474       if (jthread == JTHREAD_NONE || (jthread != NULL && jthread->is_system ()))
7475         return false;
7476     }
7477   return true;
7478 }
7479
7480 static long
7481 getTLVisibleIdxByStepping (Experiment *exp, VMode view_mode, int entity_prop_id,
7482                            DataView * packets, int aux, int entity_prop_val,
7483                            long idx, long move_count, int direction)
7484 {
7485   assert (move_count >= 0);
7486   assert (direction == 1 || direction == -1 || direction == 0);
7487   if (direction == 0 /* precise hit required */)
7488     move_count = 0;
7489   do
7490     {
7491       if (!isValidIdx (packets, entity_prop_id, aux, entity_prop_val, idx))
7492         return -1;
7493       if (isVisibleTLEvent (exp, view_mode, packets, idx))
7494         {
7495           if (move_count <= 0)
7496             break;
7497           move_count--;
7498         }
7499       if (direction == 0)
7500         return -1;
7501       idx += direction;
7502     }
7503   while (1);
7504   return idx;
7505 }
7506
7507 static long
7508 getTLVisibleIdxByVals (Experiment *exp, VMode view_mode, int entity_prop_id,
7509                        DataView * packets,
7510                        int aux, int entity_prop_val, uint64_t time, DataView::Relation rel)
7511 {
7512   long idx = getIdxByVals (packets, aux, entity_prop_val, time, rel);
7513   if (!hasInvisbleTLEvents (exp, view_mode))
7514     return idx;
7515   if (idx < 0)
7516     return idx;
7517   if (rel == DataView::REL_EQ)
7518     return -1; // would require bi-directional search... not supported for now
7519   int direction = (rel == DataView::REL_LT || rel == DataView::REL_LTEQ) ? -1 : 1;
7520   idx = getTLVisibleIdxByStepping (exp, view_mode, entity_prop_id, packets,
7521                                    aux, entity_prop_val,
7522                                    idx, 0 /* first match */, direction);
7523   return idx;
7524 }
7525
7526 // In thread mode, the entity name for non Java thread should be the 1st func
7527 // from the current thread's stack. See #4961315
7528 static char*
7529 getThreadRootFuncName (int, int, int, int, VMode)
7530 {
7531   return NULL; // until we figure out what we want to show... YXXX
7532 }
7533
7534 Vector<void*> *
7535 dbeGetEntityProps (int dbevindex) //YXXX TBD, should this be exp-specific?
7536 {
7537   DbeView *dbev = dbeSession->getView (dbevindex);
7538   if (dbev == NULL)
7539     abort ();
7540   Vector<int> *prop_id = new Vector<int>();
7541   Vector<char*> *prop_name = new Vector<char*>();
7542   Vector<char*> *prop_uname = new Vector<char*>();
7543   Vector<char*> *prop_cname = new Vector<char*>(); //must match TLModeCmd vals!
7544
7545   prop_id->append (PROP_NONE);
7546   prop_name->append (dbe_strdup (GTXT ("NONE")));
7547   prop_uname->append (dbe_strdup (GTXT ("Unknown")));
7548   prop_cname->append (dbe_strdup (NTXT ("unknown")));
7549
7550   prop_id->append (PROP_LWPID);
7551   prop_name->append (dbe_strdup (GTXT ("LWPID")));
7552   prop_uname->append (dbe_strdup (GTXT ("LWP")));
7553   prop_cname->append (dbe_strdup (NTXT ("lwp")));
7554
7555   prop_id->append (PROP_THRID);
7556   prop_name->append (dbe_strdup (GTXT ("THRID")));
7557   prop_uname->append (dbe_strdup (GTXT ("Thread")));
7558   prop_cname->append (dbe_strdup (NTXT ("thread")));
7559
7560   prop_id->append (PROP_CPUID);
7561   prop_name->append (dbe_strdup (GTXT ("CPUID")));
7562   prop_uname->append (dbe_strdup (GTXT ("CPU")));
7563   prop_cname->append (dbe_strdup (NTXT ("cpu")));
7564
7565   prop_id->append (PROP_EXPID);
7566   prop_name->append (dbe_strdup (GTXT ("EXPID")));
7567   prop_uname->append (dbe_strdup (GTXT ("Process"))); // placeholder...
7568   // ...until we finalize how to expose user-level Experiments, descendents
7569   prop_cname->append (dbe_strdup (NTXT ("experiment")));
7570   Vector<void*> *darray = new Vector<void*>();
7571   darray->store (0, prop_id);
7572   darray->store (1, prop_name);
7573   darray->store (2, prop_uname);
7574   darray->store (3, prop_cname);
7575   return darray;
7576 }
7577
7578 Vector<void*> *
7579 dbeGetEntities (int dbevindex, int exp_id, int entity_prop_id)
7580 {
7581   DbeView *dbev = dbeSession->getView (dbevindex);
7582   if (dbev == NULL)
7583     abort ();
7584   Experiment *exp = dbeSession->get_exp (exp_id);
7585   if (exp == NULL)
7586     return NULL;
7587
7588   // Recognize and skip faketime experiments
7589   if (exp->timelineavail == false)
7590     return NULL;
7591   Vector<Histable*> *tagObjs = exp->getTagObjs ((Prop_type) entity_prop_id);
7592   int total_nelem;
7593   if (tagObjs)
7594     total_nelem = (int) tagObjs->size ();
7595   else
7596     total_nelem = 0;
7597   const VMode view_mode = dbev->get_view_mode ();
7598   bool show_java_threadnames = (entity_prop_id == PROP_THRID &&
7599                                 view_mode != VMODE_MACHINE);
7600   // allocate the structures for the return
7601   Vector<int> *entity_prop_vals = new Vector<int>();
7602   Vector<char*> *jthr_names = new Vector<char*>();
7603   Vector<char*> *jthr_g_names = new Vector<char*>();
7604   Vector<char*> *jthr_p_names = new Vector<char*>();
7605
7606   // now walk the tagObjs from the experiment, and check for filtering
7607   for (int tagObjsIdx = 0; tagObjsIdx < total_nelem; tagObjsIdx++)
7608     {
7609       int entity_prop_val = (int) ((Other *) tagObjs->fetch (tagObjsIdx))->tag;
7610       entity_prop_vals->append (entity_prop_val);
7611       char *jname, *jgname, *jpname;
7612       JThread *jthread = NULL;
7613       bool has_java_threadnames = false;
7614       if (show_java_threadnames)
7615         {
7616           jthread = exp->get_jthread (entity_prop_val);
7617           has_java_threadnames = (jthread != JTHREAD_DEFAULT
7618                                   && jthread != JTHREAD_NONE);
7619         }
7620       if (!has_java_threadnames)
7621         {
7622           jname = jgname = jpname = NULL;
7623           if (entity_prop_id == PROP_THRID || entity_prop_id == PROP_LWPID)
7624             // if non Java thread, set thread name to the 1st func
7625             // from the current thread's stack. see #4961315
7626             jname = getThreadRootFuncName (dbevindex, exp_id, entity_prop_id,
7627                                            entity_prop_val, view_mode);
7628         }
7629       else
7630         {
7631           jname = dbe_strdup (jthread->name);
7632           jgname = dbe_strdup (jthread->group_name);
7633           jpname = dbe_strdup (jthread->parent_name);
7634         }
7635       jthr_names->append (jname);
7636       jthr_g_names->append (jgname);
7637       jthr_p_names->append (jpname);
7638     }
7639   Vector<char*> *entity_prop_name_v = new Vector<char*>();
7640   char* entity_prop_name = dbeSession->getPropName (entity_prop_id);
7641   entity_prop_name_v->append (entity_prop_name);
7642   Vector<void*> *darray = new Vector<void*>(5);
7643   darray->store (0, entity_prop_vals);
7644   darray->store (1, jthr_names);
7645   darray->store (2, jthr_g_names);
7646   darray->store (3, jthr_p_names);
7647   darray->store (4, entity_prop_name_v); // vector only has 1 element
7648   return darray;
7649 }
7650
7651 // TBR: dbeGetEntities() can be set to private now that we have dbeGetEntitiesV2()
7652 Vector<void*> *
7653 dbeGetEntitiesV2 (int dbevindex, Vector<int> *exp_ids, int entity_prop_id)
7654 {
7655   int sz = exp_ids->size ();
7656   Vector<void*> *res = new Vector<void*>(sz);
7657   for (int ii = 0; ii < sz; ii++)
7658     {
7659       int expIdx = exp_ids->fetch (ii);
7660       Vector<void*>* ents = dbeGetEntities (dbevindex, expIdx, entity_prop_id);
7661       res->store (ii, ents);
7662     }
7663   return res;
7664 }
7665
7666 //YXXX old-tl packets still used for details
7667 static Vector<void*> *
7668 getTLDetailValues (int dbevindex, Experiment * exp, int data_id,
7669                    VMode view_mode, DataView *packets, long idx)
7670 {
7671   Vector<long long> *value = new Vector<long long>(15);
7672   long i = idx;
7673   if (data_id == DATA_SAMPLE || data_id == DATA_GCEVENT)
7674     {
7675       //YXXX DATA_SAMPLE not handled but could be.
7676     }
7677   Obj stack = (unsigned long) getStack (view_mode, packets, i);
7678   Vector<Obj> *funcs = stack ? dbeGetStackFunctions (dbevindex, stack) : NULL;
7679   Function *func = (Function*)
7680           getStackPC (0, view_mode, packets, i)->convertto (Histable::FUNCTION);
7681   // Fill common data
7682   value->store (0, packets->getIntValue (PROP_LWPID, i));
7683   value->store (1, packets->getIntValue (PROP_THRID, i));
7684   value->store (2, packets->getIntValue (PROP_CPUID, i));
7685   value->store (3, packets->getLongValue (PROP_TSTAMP, i));
7686   value->store (4, (unsigned long) stack);
7687   value->store (5, (unsigned long) func);
7688
7689   // Fill specific data
7690   switch (data_id)
7691     {
7692     case DATA_CLOCK:
7693       value->store (6, packets->getIntValue (PROP_MSTATE, i));
7694       {
7695         hrtime_t interval = exp->get_params ()->ptimer_usec * 1000LL // nanoseconds
7696                 * packets->getLongValue (PROP_NTICK, i);
7697         value->store (7, interval);
7698       }
7699       value->store (8, packets->getIntValue (PROP_OMPSTATE, i));
7700       value->store (9, packets->getLongValue (PROP_EVT_TIME, i)); // visual duration
7701       break;
7702     case DATA_SYNCH:
7703       value->store (6, packets->getLongValue (PROP_EVT_TIME, i));
7704       value->store (7, packets->getLongValue (PROP_SOBJ, i));
7705       break;
7706     case DATA_HWC:
7707       value->store (6, packets->getLongValue (PROP_HWCINT, i));
7708       value->store (7, packets->getLongValue (PROP_VADDR, i)); // data vaddr
7709       value->store (8, packets->getLongValue (PROP_PADDR, i)); // data paddr
7710       value->store (9, packets->getLongValue (PROP_VIRTPC, i)); // pc paddr
7711       value->store (10, packets->getLongValue (PROP_PHYSPC, i)); // pc vaddr
7712       break;
7713     case DATA_RACE:
7714       value->store (6, packets->getIntValue (PROP_RTYPE, i));
7715       value->store (7, packets->getIntValue (PROP_RID, i));
7716       value->store (8, packets->getLongValue (PROP_RVADDR, i));
7717       break;
7718     case DATA_DLCK:
7719       value->store (6, packets->getIntValue (PROP_DTYPE, i));
7720       value->store (7, packets->getIntValue (PROP_DLTYPE, i));
7721       value->store (8, packets->getIntValue (PROP_DID, i));
7722       value->store (9, packets->getLongValue (PROP_DVADDR, i));
7723       break;
7724     case DATA_HEAP:
7725     case DATA_HEAPSZ:
7726       value->store (6, packets->getIntValue (PROP_HTYPE, i));
7727       value->store (7, packets->getLongValue (PROP_HSIZE, i));
7728       value->store (8, packets->getLongValue (PROP_HVADDR, i));
7729       value->store (9, packets->getLongValue (PROP_HOVADDR, i));
7730       value->store (10, packets->getLongValue (PROP_HLEAKED, i));
7731       value->store (11, packets->getLongValue (PROP_HFREED, i));
7732       value->store (12, packets->getLongValue (PROP_HCUR_ALLOCS, i)); // signed int64_t
7733       value->store (13, packets->getLongValue (PROP_HCUR_LEAKS, i));
7734       break;
7735     case DATA_IOTRACE:
7736       value->store (6, packets->getIntValue (PROP_IOTYPE, i));
7737       value->store (7, packets->getIntValue (PROP_IOFD, i));
7738       value->store (8, packets->getLongValue (PROP_IONBYTE, i));
7739       value->store (9, packets->getLongValue (PROP_EVT_TIME, i));
7740       value->store (10, packets->getIntValue (PROP_IOVFD, i));
7741       break;
7742     }
7743   Vector<void*> *result = new Vector<void*>(5);
7744   result->store (0, value);
7745   result->store (1, funcs); // Histable::Function*
7746   result->store (2, funcs ? dbeGetFuncNames (dbevindex, funcs) : 0); // formatted func names
7747   result->store (3, stack ? dbeGetStackPCs (dbevindex, stack) : 0); // Histable::DbeInstr*
7748   result->store (4, stack ? dbeGetStackNames (dbevindex, stack) : 0); // formatted pc names
7749   return result;
7750 }
7751
7752 Vector<void*> *
7753 dbeGetTLDetails (int dbevindex, int exp_id, int data_id,
7754                  int entity_prop_id, Obj event_id)
7755 {
7756   DbeView *dbev = dbeSession->getView (dbevindex);
7757   if (dbev == NULL)
7758     abort ();
7759   Experiment *exp = dbeSession->get_exp (exp_id < 0 ? 0 : exp_id);
7760   if (exp == NULL)
7761     return NULL;
7762   DataView *packets =
7763           getTimelinePackets (dbevindex, exp_id, data_id, entity_prop_id);
7764   if (!packets)
7765     return NULL;
7766
7767   VMode view_mode = dbev->get_view_mode ();
7768   long idx = (long) event_id;
7769   Vector<void*> *values = getTLDetailValues (dbevindex, exp, data_id, view_mode, packets, idx);
7770   return values;
7771 }
7772
7773 Vector<Obj> *
7774 dbeGetStackFunctions (int dbevindex, Obj stack)
7775 {
7776   Vector<Obj> *instrs = dbeGetStackPCs (dbevindex, stack);
7777   if (instrs == NULL)
7778     return NULL;
7779   int stsize = instrs->size ();
7780   Vector<Obj> *jivals = new Vector<Obj>(stsize);
7781   for (int i = 0; i < stsize; i++)
7782     {
7783       Histable *obj = (Histable*) instrs->fetch (i);
7784       // if ( obj->get_type() != Histable::LINE ) {//YXXX what is this?
7785       // Remove the above check: why not do this conversion for lines -
7786       // otherwise filtering in timeline by function stack in omp user mode is broken
7787       obj = obj->convertto (Histable::FUNCTION);
7788       jivals->store (i, (Obj) obj);
7789     }
7790   delete instrs;
7791   return jivals;
7792 }
7793
7794 Vector<void*> *
7795 dbeGetStacksFunctions (int dbevindex, Vector<Obj> *stacks)
7796 {
7797   long sz = stacks->size ();
7798   Vector<void*> *res = new Vector<void*>(sz);
7799   for (int ii = 0; ii < sz; ii++)
7800     {
7801       Obj stack = stacks->fetch (ii);
7802       Vector<Obj> *jivals = dbeGetStackFunctions (dbevindex, stack);
7803       res->store (ii, jivals);
7804     }
7805   return res;
7806 }
7807
7808 Vector<Obj> *
7809 dbeGetStackPCs (int dbevindex, Obj stack)
7810 {
7811   DbeView *dbev = dbeSession->getView (dbevindex);
7812   if (dbev == NULL)
7813     abort ();
7814   if (stack == 0)
7815     return NULL;
7816
7817   bool show_all = dbev->isShowAll ();
7818   Vector<Histable*> *instrs = CallStack::getStackPCs ((void *) stack, !show_all);
7819   int stsize = instrs->size ();
7820   int istart = 0;
7821   bool showAll = dbev->isShowAll ();
7822   for (int i = 0; i < stsize - 1; i++)
7823     {
7824       Function *func = (Function*) instrs->fetch (i)->convertto (Histable::FUNCTION);
7825       int ix = func->module->loadobject->seg_idx;
7826       if (showAll && dbev->get_lo_expand (ix) == LIBEX_API)
7827         // truncate stack here:  LIBRARY_VISIBILITY if we are using API only but no hide
7828         istart = i;
7829     }
7830   stsize = stsize - istart;
7831   Vector<Obj> *jlvals = new Vector<Obj>(stsize);
7832   for (int i = 0; i < stsize; i++)
7833     {
7834       Histable *instr = instrs->fetch (i + istart);
7835       jlvals->store (i, (Obj) instr);
7836     }
7837   delete instrs;
7838   return jlvals;
7839 }
7840
7841 Vector<char*> *
7842 dbeGetStackNames (int dbevindex, Obj stack)
7843 {
7844   DbeView *dbev = dbeSession->getView (dbevindex);
7845   Vector<Obj> *instrs = dbeGetStackPCs (dbevindex, stack);
7846   if (instrs == NULL)
7847     return NULL;
7848   int stsize = instrs->size ();
7849   Vector<char*> *list = new Vector<char*>(stsize);
7850   bool showAll = dbev->isShowAll ();
7851   for (int i = 0; i < stsize; i++)
7852     {
7853       Histable* instr = (Histable*) instrs->fetch (i);
7854       if (!showAll)
7855         {
7856           // LIBRARY_VISIBILITY
7857           Function *func = (Function*) instr->convertto (Histable::FUNCTION);
7858           LoadObject *lo = ((Function*) func)->module->loadobject;
7859           if (dbev->get_lo_expand (lo->seg_idx) == LIBEX_HIDE)
7860             {
7861               list->store (i, dbe_strdup (lo->get_name ()));
7862               continue;
7863             }
7864         }
7865       list->store (i, dbe_strdup (instr->get_name (dbev->get_name_format ())));
7866     }
7867   delete instrs;
7868   return list;
7869 }
7870
7871 Vector<void*> *
7872 dbeGetSamples (int dbevindex, int exp_id, int64_t lo_idx, int64_t hi_idx)
7873 {
7874   DataView * packets =
7875           getTimelinePackets (dbevindex, exp_id, DATA_SAMPLE, PROP_EXPID);
7876   if (packets == NULL || packets->getSize () == 0)
7877     return NULL;
7878   long lo;
7879   if (lo_idx < 0)
7880     lo = 0;
7881   else
7882     lo = (long) lo_idx;
7883
7884   long long max = packets->getSize () - 1;
7885   long hi;
7886   if (hi_idx < 0 || hi_idx > max)
7887     hi = (long) max;
7888   else
7889     hi = (long) hi_idx;
7890
7891   Vector<Vector<long long>*> *sarray = new Vector<Vector<long long>*>;
7892   Vector<long long>* starts = new Vector<long long>;
7893   Vector<long long>* ends = new Vector<long long>;
7894   Vector<long long>* rtimes = new Vector<long long>;
7895   Vector<char*> *startNames = new Vector<char*>;
7896   Vector<char*> *endNames = new Vector<char*>;
7897   Vector<int> *sampId = new Vector<int>;
7898
7899   for (long index = lo; index <= hi; index++)
7900     {
7901       Sample *sample = (Sample*) packets->getObjValue (PROP_SMPLOBJ, index);
7902       PrUsage *prusage = sample->get_usage ();
7903       if (prusage == NULL)
7904         prusage = new PrUsage;
7905       Vector<long long> *states = prusage->getMstateValues ();
7906       sarray->append (states);
7907       starts->append (sample->get_start_time ());
7908       ends->append (sample->get_end_time ());
7909       rtimes->append (prusage->pr_rtime);
7910       startNames->append (dbe_strdup (sample->get_start_label ()));
7911       endNames->append (dbe_strdup (sample->get_end_label ()));
7912       sampId->append (sample->get_number ());
7913     }
7914   Vector<void *> *res = new Vector<void*>(6);
7915   res->store (0, sarray);
7916   res->store (1, starts);
7917   res->store (2, ends);
7918   res->store (3, rtimes);
7919   res->store (4, startNames);
7920   res->store (5, endNames);
7921   res->store (6, sampId);
7922   return res;
7923 }
7924
7925 Vector<void*> *
7926 dbeGetGCEvents (int dbevindex, int exp_id, int64_t lo_idx, int64_t hi_idx)
7927 {
7928   DataView *packets =
7929           getTimelinePackets (dbevindex, exp_id, DATA_GCEVENT, PROP_EXPID);
7930   if (packets == NULL || packets->getSize () == 0)
7931     return NULL;
7932
7933   long lo;
7934   if (lo_idx < 0)
7935     lo = 0;
7936   else
7937     lo = (long) lo_idx;
7938   long long max = packets->getSize () - 1;
7939   long hi;
7940   if (hi_idx < 0 || hi_idx > max)
7941     hi = (long) max;
7942   else
7943     hi = (long) hi_idx;
7944
7945   Vector<long long>* starts = new Vector<long long>;
7946   Vector<long long>* ends = new Vector<long long>;
7947   Vector<int> *eventId = new Vector<int>;
7948   for (long index = lo; index <= hi; index++)
7949     {
7950       GCEvent *gcevent = (GCEvent*) packets->getObjValue (PROP_GCEVENTOBJ, index);
7951       if (gcevent)
7952         {
7953           starts->append (gcevent->start);
7954           ends->append (gcevent->end);
7955           eventId->append (gcevent->id);
7956         }
7957     }
7958   Vector<void *> *res = new Vector<void*>(3);
7959   res->store (0, starts);
7960   res->store (1, ends);
7961   res->store (2, eventId);
7962   return res;
7963 }
7964
7965 Vector<Vector<char*>*>*
7966 dbeGetIOStatistics (int dbevindex)
7967 {
7968   DbeView *dbev = dbeSession->getView (dbevindex);
7969   Hist_data *hist_data;
7970   Hist_data::HistItem *hi;
7971   FileData *fDataTotal;
7972
7973   hist_data = dbev->iofile_data;
7974   if (hist_data == NULL)
7975     return NULL;
7976   hi = hist_data->fetch (0);
7977   fDataTotal = (FileData*) hi->obj;
7978
7979   Vector<char*> *writeStat = new Vector<char*>;
7980   Vector<char*> *readStat = new Vector<char*>;
7981   Vector<char*> *otherStat = new Vector<char*>;
7982   Vector<char*> *errorStat = new Vector<char*>;
7983
7984   writeStat->append (dbe_strdup (GTXT ("Write Statistics")));
7985   readStat->append (dbe_strdup (GTXT ("Read Statistics")));
7986   otherStat->append (dbe_strdup (GTXT ("Other I/O Statistics")));
7987   errorStat->append (dbe_strdup (GTXT ("I/O Error Statistics")));
7988
7989   StringBuilder sb;
7990   if (fDataTotal->getWriteCnt () > 0)
7991     {
7992       if (fDataTotal->getW0KB1KBCnt () > 0)
7993         {
7994           sb.sprintf (GTXT ("0KB - 1KB"));
7995           writeStat->append (sb.toString ());
7996           sb.sprintf (NTXT ("%d"), fDataTotal->getW0KB1KBCnt ());
7997           writeStat->append (sb.toString ());
7998         }
7999       if (fDataTotal->getW1KB8KBCnt () > 0)
8000         {
8001           sb.sprintf (GTXT ("1KB - 8KB"));
8002           writeStat->append (sb.toString ());
8003           sb.sprintf (NTXT ("%d"), fDataTotal->getW1KB8KBCnt ());
8004           writeStat->append (sb.toString ());
8005         }
8006       if (fDataTotal->getW8KB32KBCnt () > 0)
8007         {
8008           sb.sprintf (GTXT ("8KB - 32KB"));
8009           writeStat->append (sb.toString ());
8010           sb.sprintf (NTXT ("%d"), fDataTotal->getW8KB32KBCnt ());
8011           writeStat->append (sb.toString ());
8012         }
8013       if (fDataTotal->getW32KB128KBCnt () > 0)
8014         {
8015           sb.sprintf (GTXT ("32KB - 128KB"));
8016           writeStat->append (sb.toString ());
8017           sb.sprintf (NTXT ("%d"), fDataTotal->getW32KB128KBCnt ());
8018           writeStat->append (sb.toString ());
8019         }
8020       if (fDataTotal->getW128KB256KBCnt () > 0)
8021         {
8022           sb.sprintf (GTXT ("128KB - 256KB"));
8023           writeStat->append (sb.toString ());
8024           sb.sprintf (NTXT ("%d"), fDataTotal->getW128KB256KBCnt ());
8025           writeStat->append (sb.toString ());
8026         }
8027       if (fDataTotal->getW256KB512KBCnt () > 0)
8028         {
8029           sb.sprintf (GTXT ("256KB - 512KB"));
8030           writeStat->append (sb.toString ());
8031           sb.sprintf (NTXT ("%d"), fDataTotal->getW256KB512KBCnt ());
8032           writeStat->append (sb.toString ());
8033         }
8034       if (fDataTotal->getW512KB1000KBCnt () > 0)
8035         {
8036           sb.sprintf (GTXT ("512KB - 1000KB"));
8037           writeStat->append (sb.toString ());
8038           sb.sprintf (NTXT ("%d"), fDataTotal->getW512KB1000KBCnt ());
8039           writeStat->append (sb.toString ());
8040         }
8041       if (fDataTotal->getW1000KB10MBCnt () > 0)
8042         {
8043           sb.sprintf (GTXT ("1000KB - 10MB"));
8044           writeStat->append (sb.toString ());
8045           sb.sprintf (NTXT ("%d"), fDataTotal->getW1000KB10MBCnt ());
8046           writeStat->append (sb.toString ());
8047         }
8048       if (fDataTotal->getW10MB100MBCnt () > 0)
8049         {
8050           sb.sprintf (GTXT ("10MB - 100MB"));
8051           writeStat->append (sb.toString ());
8052           sb.sprintf (NTXT ("%d"), fDataTotal->getW10MB100MBCnt ());
8053           writeStat->append (sb.toString ());
8054         }
8055       if (fDataTotal->getW100MB1GBCnt () > 0)
8056         {
8057           sb.sprintf (GTXT ("100MB - 1GB"));
8058           writeStat->append (sb.toString ());
8059           sb.sprintf (NTXT ("%d"), fDataTotal->getW100MB1GBCnt ());
8060           writeStat->append (sb.toString ());
8061         }
8062       if (fDataTotal->getW1GB10GBCnt () > 0)
8063         {
8064           sb.sprintf (GTXT ("1GB - 10GB"));
8065           writeStat->append (sb.toString ());
8066           sb.sprintf (NTXT ("%d"), fDataTotal->getW1GB10GBCnt ());
8067           writeStat->append (sb.toString ());
8068         }
8069       if (fDataTotal->getW10GB100GBCnt () > 0)
8070         {
8071           sb.sprintf (GTXT ("10GB - 100GB"));
8072           writeStat->append (sb.toString ());
8073           sb.sprintf (NTXT ("%d"), fDataTotal->getW10GB100GBCnt ());
8074           writeStat->append (sb.toString ());
8075         }
8076       if (fDataTotal->getW100GB1TBCnt () > 0)
8077         {
8078           sb.sprintf (GTXT ("100GB - 1TB"));
8079           writeStat->append (sb.toString ());
8080           sb.sprintf (NTXT ("%d"), fDataTotal->getW100GB1TBCnt ());
8081           writeStat->append (sb.toString ());
8082         }
8083       if (fDataTotal->getW1TB10TBCnt () > 0)
8084         {
8085           sb.sprintf (GTXT ("1TB - 10TB"));
8086           writeStat->append (sb.toString ());
8087           sb.sprintf (NTXT ("%d"), fDataTotal->getW1TB10TBCnt ());
8088           writeStat->append (sb.toString ());
8089         }
8090
8091       sb.sprintf (GTXT ("Longest write"));
8092       writeStat->append (sb.toString ());
8093       sb.sprintf (NTXT ("%.6f (secs.)"),
8094                   (double) (fDataTotal->getWSlowestBytes () / (double) NANOSEC));
8095       writeStat->append (sb.toString ());
8096
8097       sb.sprintf (GTXT ("Smallest write bytes"));
8098       writeStat->append (sb.toString ());
8099       sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getWSmallestBytes ()));
8100       writeStat->append (sb.toString ());
8101
8102       sb.sprintf (GTXT ("Largest write bytes"));
8103       writeStat->append (sb.toString ());
8104       sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getWLargestBytes ()));
8105       writeStat->append (sb.toString ());
8106
8107       sb.sprintf (GTXT ("Total time"));
8108       writeStat->append (sb.toString ());
8109       sb.sprintf (NTXT ("%.6f (secs.)"),
8110                   (double) (fDataTotal->getWriteTime () / (double) NANOSEC));
8111       writeStat->append (sb.toString ());
8112
8113       sb.sprintf (GTXT ("Total calls"));
8114       writeStat->append (sb.toString ());
8115       sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getWriteCnt ()));
8116       writeStat->append (sb.toString ());
8117
8118       sb.sprintf (GTXT ("Total bytes"));
8119       writeStat->append (sb.toString ());
8120       sb.sprintf (NTXT ("%lld"), (long long) (fDataTotal->getWriteBytes ()));
8121       writeStat->append (sb.toString ());
8122     }
8123
8124   if (fDataTotal->getReadCnt () > 0)
8125     {
8126       if (fDataTotal->getR0KB1KBCnt () > 0)
8127         {
8128           sb.sprintf (GTXT ("0KB - 1KB"));
8129           readStat->append (sb.toString ());
8130           sb.sprintf (NTXT ("%d"), fDataTotal->getR0KB1KBCnt ());
8131           readStat->append (sb.toString ());
8132         }
8133       if (fDataTotal->getR1KB8KBCnt () > 0)
8134         {
8135           sb.sprintf (GTXT ("1KB - 8KB"));
8136           readStat->append (sb.toString ());
8137           sb.sprintf (NTXT ("%d"), fDataTotal->getR1KB8KBCnt ());
8138           readStat->append (sb.toString ());
8139         }
8140       if (fDataTotal->getR8KB32KBCnt () > 0)
8141         {
8142           sb.sprintf (GTXT ("8KB - 32KB"));
8143           readStat->append (sb.toString ());
8144           sb.sprintf (NTXT ("%d"), fDataTotal->getR8KB32KBCnt ());
8145           readStat->append (sb.toString ());
8146         }
8147       if (fDataTotal->getR32KB128KBCnt () > 0)
8148         {
8149           sb.sprintf (GTXT ("32KB - 128KB"));
8150           readStat->append (sb.toString ());
8151           sb.sprintf (NTXT ("%d"), fDataTotal->getR32KB128KBCnt ());
8152           readStat->append (sb.toString ());
8153         }
8154       if (fDataTotal->getR128KB256KBCnt () > 0)
8155         {
8156           sb.sprintf (GTXT ("128KB - 256KB"));
8157           readStat->append (sb.toString ());
8158           sb.sprintf (NTXT ("%d"), fDataTotal->getR128KB256KBCnt ());
8159           readStat->append (sb.toString ());
8160         }
8161       if (fDataTotal->getR256KB512KBCnt () > 0)
8162         {
8163           sb.sprintf (GTXT ("256KB - 512KB"));
8164           readStat->append (sb.toString ());
8165           sb.sprintf (NTXT ("%d"), fDataTotal->getR256KB512KBCnt ());
8166           readStat->append (sb.toString ());
8167         }
8168       if (fDataTotal->getR512KB1000KBCnt () > 0)
8169         {
8170           sb.sprintf (GTXT ("512KB - 1000KB"));
8171           readStat->append (sb.toString ());
8172           sb.sprintf (NTXT ("%d"), fDataTotal->getR512KB1000KBCnt ());
8173           readStat->append (sb.toString ());
8174         }
8175       if (fDataTotal->getR1000KB10MBCnt () > 0)
8176         {
8177           sb.sprintf (GTXT ("1000KB - 10MB"));
8178           readStat->append (sb.toString ());
8179           sb.sprintf (NTXT ("%d"), fDataTotal->getR1000KB10MBCnt ());
8180           readStat->append (sb.toString ());
8181         }
8182       if (fDataTotal->getR10MB100MBCnt () > 0)
8183         {
8184           sb.sprintf (GTXT ("10MB - 100MB"));
8185           readStat->append (sb.toString ());
8186           sb.sprintf (NTXT ("%d"), fDataTotal->getR10MB100MBCnt ());
8187           readStat->append (sb.toString ());
8188         }
8189       if (fDataTotal->getR100MB1GBCnt () > 0)
8190         {
8191           sb.sprintf (GTXT ("100MB - 1GB"));
8192           readStat->append (sb.toString ());
8193           sb.sprintf (NTXT ("%d"), fDataTotal->getR100MB1GBCnt ());
8194           readStat->append (sb.toString ());
8195         }
8196       if (fDataTotal->getR1GB10GBCnt () > 0)
8197         {
8198           sb.sprintf (GTXT ("1GB - 10GB"));
8199           readStat->append (sb.toString ());
8200           sb.sprintf (NTXT ("%d"), fDataTotal->getR1GB10GBCnt ());
8201           readStat->append (sb.toString ());
8202         }
8203       if (fDataTotal->getR10GB100GBCnt () > 0)
8204         {
8205           sb.sprintf (GTXT ("10GB - 100GB"));
8206           readStat->append (sb.toString ());
8207           sb.sprintf (NTXT ("%d"), fDataTotal->getR10GB100GBCnt ());
8208           readStat->append (sb.toString ());
8209         }
8210       if (fDataTotal->getR100GB1TBCnt () > 0)
8211         {
8212           sb.sprintf (GTXT ("100GB - 1TB"));
8213           readStat->append (sb.toString ());
8214           sb.sprintf (NTXT ("%d"), fDataTotal->getR100GB1TBCnt ());
8215           readStat->append (sb.toString ());
8216         }
8217       if (fDataTotal->getR1TB10TBCnt () > 0)
8218         {
8219           sb.sprintf (GTXT ("1TB - 10TB"));
8220           readStat->append (sb.toString ());
8221           sb.sprintf (NTXT ("%d"), fDataTotal->getR1TB10TBCnt ());
8222           readStat->append (sb.toString ());
8223         }
8224
8225       sb.sprintf (GTXT ("Longest read"));
8226       readStat->append (sb.toString ());
8227       sb.sprintf (NTXT ("%.6f (secs.)"),
8228                   (double) (fDataTotal->getRSlowestBytes () / (double) NANOSEC));
8229       readStat->append (sb.toString ());
8230
8231       sb.sprintf (GTXT ("Smallest read bytes"));
8232       readStat->append (sb.toString ());
8233       sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getRSmallestBytes ()));
8234       readStat->append (sb.toString ());
8235
8236       sb.sprintf (GTXT ("Largest read bytes"));
8237       readStat->append (sb.toString ());
8238       sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getRLargestBytes ()));
8239       readStat->append (sb.toString ());
8240
8241       sb.sprintf (GTXT ("Total time"));
8242       readStat->append (sb.toString ());
8243       sb.sprintf (NTXT ("%.6f (secs.)"),
8244                   (double) (fDataTotal->getReadTime () / (double) NANOSEC));
8245       readStat->append (sb.toString ());
8246
8247       sb.sprintf (GTXT ("Total calls"));
8248       readStat->append (sb.toString ());
8249       sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getReadCnt ()));
8250       readStat->append (sb.toString ());
8251
8252       sb.sprintf (GTXT ("Total bytes"));
8253       readStat->append (sb.toString ());
8254       sb.sprintf (NTXT ("%lld"), (long long) (fDataTotal->getReadBytes ()));
8255       readStat->append (sb.toString ());
8256     }
8257
8258   if (fDataTotal->getOtherCnt () > 0)
8259     {
8260       sb.sprintf (GTXT ("Total time"));
8261       otherStat->append (sb.toString ());
8262       sb.sprintf (NTXT ("%.6f (secs.)"),
8263                   (double) (fDataTotal->getOtherTime () / (double) NANOSEC));
8264       otherStat->append (sb.toString ());
8265
8266       sb.sprintf (GTXT ("Total calls"));
8267       otherStat->append (sb.toString ());
8268       sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getOtherCnt ()));
8269       otherStat->append (sb.toString ());
8270     }
8271
8272   if (fDataTotal->getErrorCnt () > 0)
8273     {
8274       sb.sprintf (GTXT ("Total time"));
8275       errorStat->append (sb.toString ());
8276       sb.sprintf (NTXT ("%.6f (secs.)"),
8277                   (double) (fDataTotal->getErrorTime () / (double) NANOSEC));
8278       errorStat->append (sb.toString ());
8279
8280       sb.sprintf (GTXT ("Total calls"));
8281       errorStat->append (sb.toString ());
8282       sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getErrorCnt ()));
8283       errorStat->append (sb.toString ());
8284     }
8285   Vector<Vector<char*>*>* statisticsData = new Vector<Vector<char*>*>(4);
8286   statisticsData->store (0, writeStat);
8287   statisticsData->store (1, readStat);
8288   statisticsData->store (2, otherStat);
8289   statisticsData->store (3, errorStat);
8290   return statisticsData;
8291 }
8292
8293 Vector<Vector<char*>*>*
8294 dbeGetHeapStatistics (int dbevindex)
8295 {
8296   DbeView *dbev = dbeSession->getView (dbevindex);
8297   Hist_data *hist_data;
8298   Hist_data::HistItem *hi;
8299   HeapData *hDataTotal;
8300   hist_data = dbev->heapcs_data;
8301   if (hist_data == NULL)
8302     return NULL;
8303
8304   hi = hist_data->fetch (0);
8305   hDataTotal = (HeapData*) hi->obj;
8306   Vector<char*> *memoryUsage = new Vector<char*>;
8307   Vector<char*> *allocStat = new Vector<char*>;
8308   Vector<char*> *leakStat = new Vector<char*>;
8309
8310   memoryUsage->append (dbe_strdup (GTXT ("Process With Highest Peak Memory Usage")));
8311   allocStat->append (dbe_strdup (GTXT ("Memory Allocations Statistics")));
8312   leakStat->append (dbe_strdup (GTXT ("Memory Leaks Statistics")));
8313   StringBuilder sb;
8314   if (hDataTotal->getPeakMemUsage () > 0)
8315     {
8316       sb.sprintf (GTXT ("Heap size bytes"));
8317       memoryUsage->append (sb.toString ());
8318       sb.sprintf (NTXT ("%lld"), (long long) (hDataTotal->getPeakMemUsage ()));
8319       memoryUsage->append (sb.toString ());
8320
8321       sb.sprintf (GTXT ("Experiment Id"));
8322       memoryUsage->append (sb.toString ());
8323       sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getUserExpId ()));
8324       memoryUsage->append (sb.toString ());
8325
8326       sb.sprintf (GTXT ("Process Id"));
8327       memoryUsage->append (sb.toString ());
8328       sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getPid ()));
8329       memoryUsage->append (sb.toString ());
8330
8331       Vector<hrtime_t> *pTimestamps;
8332       pTimestamps = hDataTotal->getPeakTimestamps ();
8333       if (pTimestamps != NULL)
8334         {
8335           for (int i = 0; i < pTimestamps->size (); i++)
8336             {
8337               sb.sprintf (GTXT ("Time of peak"));
8338               memoryUsage->append (sb.toString ());
8339               sb.sprintf (NTXT ("%.3f (secs.)"), (double) (pTimestamps->fetch (i) / (double) NANOSEC));
8340               memoryUsage->append (sb.toString ());
8341             }
8342         }
8343     }
8344
8345   if (hDataTotal->getAllocCnt () > 0)
8346     {
8347       if (hDataTotal->getA0KB1KBCnt () > 0)
8348         {
8349           sb.sprintf (GTXT ("0KB - 1KB"));
8350           allocStat->append (sb.toString ());
8351           sb.sprintf (NTXT ("%d"), hDataTotal->getA0KB1KBCnt ());
8352           allocStat->append (sb.toString ());
8353         }
8354       if (hDataTotal->getA1KB8KBCnt () > 0)
8355         {
8356           sb.sprintf (GTXT ("1KB - 8KB"));
8357           allocStat->append (sb.toString ());
8358           sb.sprintf (NTXT ("%d"), hDataTotal->getA1KB8KBCnt ());
8359           allocStat->append (sb.toString ());
8360         }
8361       if (hDataTotal->getA8KB32KBCnt () > 0)
8362         {
8363           sb.sprintf (GTXT ("8KB - 32KB"));
8364           allocStat->append (sb.toString ());
8365           sb.sprintf (NTXT ("%d"), hDataTotal->getA8KB32KBCnt ());
8366           allocStat->append (sb.toString ());
8367         }
8368       if (hDataTotal->getA32KB128KBCnt () > 0)
8369         {
8370           sb.sprintf (GTXT ("32KB - 128KB"));
8371           allocStat->append (sb.toString ());
8372           sb.sprintf (NTXT ("%d"), hDataTotal->getA32KB128KBCnt ());
8373           allocStat->append (sb.toString ());
8374         }
8375       if (hDataTotal->getA128KB256KBCnt () > 0)
8376         {
8377           sb.sprintf (GTXT ("128KB - 256KB"));
8378           allocStat->append (sb.toString ());
8379           sb.sprintf (NTXT ("%d"), hDataTotal->getA128KB256KBCnt ());
8380           allocStat->append (sb.toString ());
8381         }
8382       if (hDataTotal->getA256KB512KBCnt () > 0)
8383         {
8384           sb.sprintf (GTXT ("256KB - 512KB"));
8385           allocStat->append (sb.toString ());
8386           sb.sprintf (NTXT ("%d"), hDataTotal->getA256KB512KBCnt ());
8387           allocStat->append (sb.toString ());
8388         }
8389       if (hDataTotal->getA512KB1000KBCnt () > 0)
8390         {
8391           sb.sprintf (GTXT ("512KB - 1000KB"));
8392           allocStat->append (sb.toString ());
8393           sb.sprintf (NTXT ("%d"), hDataTotal->getA512KB1000KBCnt ());
8394           allocStat->append (sb.toString ());
8395         }
8396       if (hDataTotal->getA1000KB10MBCnt () > 0)
8397         {
8398           sb.sprintf (GTXT ("1000KB - 10MB"));
8399           allocStat->append (sb.toString ());
8400           sb.sprintf (NTXT ("%d"), hDataTotal->getA1000KB10MBCnt ());
8401           allocStat->append (sb.toString ());
8402         }
8403       if (hDataTotal->getA10MB100MBCnt () > 0)
8404         {
8405           sb.sprintf (GTXT ("10MB - 100MB"));
8406           allocStat->append (sb.toString ());
8407           sb.sprintf (NTXT ("%d"), hDataTotal->getA10MB100MBCnt ());
8408           allocStat->append (sb.toString ());
8409         }
8410       if (hDataTotal->getA100MB1GBCnt () > 0)
8411         {
8412           sb.sprintf (GTXT ("100MB - 1GB"));
8413           allocStat->append (sb.toString ());
8414           sb.sprintf (NTXT ("%d"), hDataTotal->getA100MB1GBCnt ());
8415           allocStat->append (sb.toString ());
8416         }
8417       if (hDataTotal->getA1GB10GBCnt () > 0)
8418         {
8419           sb.sprintf (GTXT ("1GB - 10GB"));
8420           allocStat->append (sb.toString ());
8421           sb.sprintf (NTXT ("%d"), hDataTotal->getA1GB10GBCnt ());
8422           allocStat->append (sb.toString ());
8423         }
8424       if (hDataTotal->getA10GB100GBCnt () > 0)
8425         {
8426           sb.sprintf (GTXT ("10GB - 100GB"));
8427           allocStat->append (sb.toString ());
8428           sb.sprintf (NTXT ("%d"), hDataTotal->getA10GB100GBCnt ());
8429           allocStat->append (sb.toString ());
8430         }
8431       if (hDataTotal->getA100GB1TBCnt () > 0)
8432         {
8433           sb.sprintf (GTXT ("100GB - 1TB"));
8434           allocStat->append (sb.toString ());
8435           sb.sprintf (NTXT ("%d"), hDataTotal->getA100GB1TBCnt ());
8436           allocStat->append (sb.toString ());
8437         }
8438       if (hDataTotal->getA1TB10TBCnt () > 0)
8439         {
8440           sb.sprintf (GTXT ("1TB - 10TB"));
8441           allocStat->append (sb.toString ());
8442           sb.sprintf (NTXT ("%d"), hDataTotal->getA1TB10TBCnt ());
8443           allocStat->append (sb.toString ());
8444         }
8445
8446       sb.sprintf (GTXT ("Smallest allocation bytes"));
8447       allocStat->append (sb.toString ());
8448       sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getASmallestBytes ()));
8449       allocStat->append (sb.toString ());
8450
8451       sb.sprintf (GTXT ("Largest allocation bytes"));
8452       allocStat->append (sb.toString ());
8453       sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getALargestBytes ()));
8454       allocStat->append (sb.toString ());
8455
8456       sb.sprintf (GTXT ("Total allocations"));
8457       allocStat->append (sb.toString ());
8458       sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getAllocCnt ()));
8459       allocStat->append (sb.toString ());
8460
8461       sb.sprintf (GTXT ("Total bytes"));
8462       allocStat->append (sb.toString ());
8463       sb.sprintf (NTXT ("%lld"), (long long) (hDataTotal->getAllocBytes ()));
8464       allocStat->append (sb.toString ());
8465     }
8466
8467   if (hDataTotal->getLeakCnt () > 0)
8468     {
8469       if (hDataTotal->getL0KB1KBCnt () > 0)
8470         {
8471           sb.sprintf (GTXT ("0KB - 1KB"));
8472           leakStat->append (sb.toString ());
8473           sb.sprintf (NTXT ("%d"), hDataTotal->getL0KB1KBCnt ());
8474           leakStat->append (sb.toString ());
8475         }
8476       if (hDataTotal->getL1KB8KBCnt () > 0)
8477         {
8478           sb.sprintf (GTXT ("1KB - 8KB"));
8479           leakStat->append (sb.toString ());
8480           sb.sprintf (NTXT ("%d"), hDataTotal->getL1KB8KBCnt ());
8481           leakStat->append (sb.toString ());
8482         }
8483       if (hDataTotal->getL8KB32KBCnt () > 0)
8484         {
8485           sb.sprintf (GTXT ("8KB - 32KB"));
8486           leakStat->append (sb.toString ());
8487           sb.sprintf (NTXT ("%d"), hDataTotal->getL8KB32KBCnt ());
8488           leakStat->append (sb.toString ());
8489         }
8490       if (hDataTotal->getL32KB128KBCnt () > 0)
8491         {
8492           sb.sprintf (GTXT ("32KB - 128KB"));
8493           leakStat->append (sb.toString ());
8494           sb.sprintf (NTXT ("%d"), hDataTotal->getL32KB128KBCnt ());
8495           leakStat->append (sb.toString ());
8496         }
8497       if (hDataTotal->getL128KB256KBCnt () > 0)
8498         {
8499           sb.sprintf (GTXT ("128KB - 256KB"));
8500           leakStat->append (sb.toString ());
8501           sb.sprintf (NTXT ("%d"), hDataTotal->getL128KB256KBCnt ());
8502           leakStat->append (sb.toString ());
8503         }
8504       if (hDataTotal->getL256KB512KBCnt () > 0)
8505         {
8506           sb.sprintf (GTXT ("256KB - 512KB"));
8507           leakStat->append (sb.toString ());
8508           sb.sprintf (NTXT ("%d"), hDataTotal->getL256KB512KBCnt ());
8509           leakStat->append (sb.toString ());
8510         }
8511       if (hDataTotal->getL512KB1000KBCnt () > 0)
8512         {
8513           sb.sprintf (GTXT ("512KB - 1000KB"));
8514           leakStat->append (sb.toString ());
8515           sb.sprintf (NTXT ("%d"), hDataTotal->getL512KB1000KBCnt ());
8516           leakStat->append (sb.toString ());
8517         }
8518       if (hDataTotal->getL1000KB10MBCnt () > 0)
8519         {
8520           sb.sprintf (GTXT ("1000KB - 10MB"));
8521           leakStat->append (sb.toString ());
8522           sb.sprintf (NTXT ("%d"), hDataTotal->getL1000KB10MBCnt ());
8523           leakStat->append (sb.toString ());
8524         }
8525       if (hDataTotal->getL10MB100MBCnt () > 0)
8526         {
8527           sb.sprintf (GTXT ("10MB - 100MB"));
8528           leakStat->append (sb.toString ());
8529           sb.sprintf (NTXT ("%d"), hDataTotal->getL10MB100MBCnt ());
8530           leakStat->append (sb.toString ());
8531         }
8532       if (hDataTotal->getL100MB1GBCnt () > 0)
8533         {
8534           sb.sprintf (GTXT ("100MB - 1GB"));
8535           leakStat->append (sb.toString ());
8536           sb.sprintf (NTXT ("%d"), hDataTotal->getL100MB1GBCnt ());
8537           leakStat->append (sb.toString ());
8538         }
8539       if (hDataTotal->getL1GB10GBCnt () > 0)
8540         {
8541           sb.sprintf (GTXT ("1GB - 10GB"));
8542           leakStat->append (sb.toString ());
8543           sb.sprintf (NTXT ("%d"), hDataTotal->getL1GB10GBCnt ());
8544           leakStat->append (sb.toString ());
8545         }
8546       if (hDataTotal->getL10GB100GBCnt () > 0)
8547         {
8548           sb.sprintf (GTXT ("10GB - 100GB"));
8549           leakStat->append (sb.toString ());
8550           sb.sprintf (NTXT ("%d"), hDataTotal->getL10GB100GBCnt ());
8551           leakStat->append (sb.toString ());
8552         }
8553       if (hDataTotal->getL100GB1TBCnt () > 0)
8554         {
8555           sb.sprintf (GTXT ("100GB - 1TB"));
8556           leakStat->append (sb.toString ());
8557           sb.sprintf (NTXT ("%d"), hDataTotal->getL100GB1TBCnt ());
8558           leakStat->append (sb.toString ());
8559         }
8560       if (hDataTotal->getL1TB10TBCnt () > 0)
8561         {
8562           sb.sprintf (GTXT ("1TB - 10TB"));
8563           leakStat->append (sb.toString ());
8564           sb.sprintf (NTXT ("%d"), hDataTotal->getL1TB10TBCnt ());
8565           leakStat->append (sb.toString ());
8566         }
8567
8568       sb.sprintf (GTXT ("Smallest leaked bytes"));
8569       leakStat->append (sb.toString ());
8570       sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getLSmallestBytes ()));
8571       leakStat->append (sb.toString ());
8572
8573       sb.sprintf (GTXT ("Largest leaked bytes"));
8574       leakStat->append (sb.toString ());
8575       sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getLLargestBytes ()));
8576       leakStat->append (sb.toString ());
8577
8578       sb.sprintf (GTXT ("Total leaked"));
8579       leakStat->append (sb.toString ());
8580       sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getLeakCnt ()));
8581       leakStat->append (sb.toString ());
8582
8583       sb.sprintf (GTXT ("Total bytes"));
8584       leakStat->append (sb.toString ());
8585       sb.sprintf (NTXT ("%lld"), (long long) (hDataTotal->getLeakBytes ()));
8586       leakStat->append (sb.toString ());
8587     }
8588   Vector<Vector<char*>*>* statisticsData = new Vector<Vector<char*>*>(3);
8589   statisticsData->store (0, memoryUsage);
8590   statisticsData->store (1, allocStat);
8591   statisticsData->store (2, leakStat);
8592   return statisticsData;
8593 }
8594
8595 Vector<char*> *
8596 dbeGetFuncNames (int dbevindex, Vector<Obj> *funcs)
8597 {
8598   int len = funcs->size ();
8599   Vector<char*> *list = new Vector<char*>(len);
8600   for (int i = 0; i < len; i++)
8601     list->store (i, dbeGetFuncName (dbevindex, funcs->fetch (i))); // no strdup()
8602   return list;
8603 }
8604
8605 Vector<char*> *
8606 dbeGetObjNamesV2 (int dbevindex, Vector<uint64_t> *ids)
8607 {
8608   int len = ids->size ();
8609   Vector<char*> *list = new Vector<char*>(len);
8610   for (int i = 0; i < len; i++)
8611     list->store (i, dbeGetObjNameV2 (dbevindex, ids->fetch (i))); // no strdup()
8612   return list;
8613 }
8614
8615 char *
8616 dbeGetFuncName (int dbevindex, Obj func)
8617 {
8618   DbeView *dbev = dbeSession->getView (dbevindex);
8619   if (dbev == NULL)
8620     abort ();
8621   if (func == 0)
8622     return NULL;
8623   char *fname;
8624   fname = ((Histable *) func)->get_name (dbev->get_name_format ());
8625   return fname ? dbe_strdup (fname) : NULL;
8626 }
8627
8628 Vector<uint64_t> *
8629 dbeGetFuncIds (int dbevindex, Vector<Obj> *funcs)
8630 {
8631   int len = funcs->size ();
8632   Vector<uint64_t> *list = new Vector<uint64_t>(len);
8633   for (int i = 0; i < len; i++)
8634     list->store (i, dbeGetFuncId (dbevindex, funcs->fetch (i)));
8635   return list;
8636 }
8637
8638 uint64_t
8639 dbeGetFuncId (int dbevindex, Obj func)
8640 {
8641   DbeView *dbev = dbeSession->getView (dbevindex);
8642   if (dbev == NULL)
8643     abort ();
8644   if (func == 0)
8645     return 0;
8646   uint64_t id = ((Histable *) func)->id;
8647   return id;
8648 }
8649
8650 char *
8651 dbeGetObjNameV2 (int dbevindex, uint64_t id)
8652 {
8653   DbeView *dbev = dbeSession->getView (dbevindex);
8654   if (dbev == NULL)
8655     abort ();
8656   Histable *obj = dbeSession->findObjectById (id);
8657   if (obj == NULL)
8658     return NULL;
8659   char *fname = obj->get_name (dbev->get_name_format ());
8660   return fname ? dbe_strdup (fname) : NULL;
8661 }
8662
8663 char *
8664 dbeGetDataspaceTypeDesc (int /*dbevindex*/, Obj stack)
8665 {
8666   if (stack == 0)
8667     return NULL;
8668   Histable *hist = CallStack::getStackPC ((void *) stack, 0);
8669   DbeInstr *instr;
8670   Histable::Type type = hist->get_type ();
8671   if (type != Histable::INSTR)
8672     return NULL;
8673   else
8674     instr = (DbeInstr *) hist;
8675   char *descriptor = instr->get_descriptor ();
8676   return descriptor ? dbe_strdup (descriptor) : NULL;
8677 }
8678
8679 Vector<void*> *
8680 dbeGetDataDescriptorsV2 (int exp_id)
8681 {
8682   Experiment *exp = dbeSession->get_exp (exp_id);
8683   if (exp == NULL)
8684     return NULL;
8685   Vector<int> *dataId = new Vector<int>;
8686   Vector<char*> *dataName = new Vector<char*>;
8687   Vector<char*> *dataUName = new Vector<char*>;
8688   Vector<int> *auxProp = new Vector<int>;
8689   Vector<DataDescriptor*> *ddscr = exp->getDataDescriptors ();
8690   for (int i = 0; i < ddscr->size (); i++)
8691     {
8692       DataDescriptor *dataDscr = ddscr->fetch (i);
8693       if (dataDscr->getFlags () & DDFLAG_NOSHOW)
8694         continue;
8695       int data_id = dataDscr->getId ();
8696       int aux_prop_id = (data_id == DATA_HWC) ? PROP_HWCTAG : PROP_NONE;
8697       dataId->append (data_id);
8698       dataName->append (strdup (dataDscr->getName ()));
8699       dataUName->append (strdup (dataDscr->getUName ()));
8700       auxProp->append (aux_prop_id);
8701     }
8702   delete ddscr;
8703   Vector<void*> *res = new Vector<void*>(3);
8704   res->store (0, dataId);
8705   res->store (1, dataName);
8706   res->store (2, dataUName);
8707   res->store (3, auxProp);
8708   return res;
8709 }
8710
8711 Vector<void*> *
8712 dbeGetDataPropertiesV2 (int exp_id, int data_id)
8713 {
8714   Experiment *exp = dbeSession->get_exp (exp_id);
8715   if (exp == NULL)
8716     return NULL;
8717   DataDescriptor *dataDscr = exp->get_raw_events (data_id);
8718   if (dataDscr == NULL)
8719     return NULL;
8720   Vector<PropDescr*> *props = dataDscr->getProps ();
8721   Vector<int> *propId = new Vector<int>(props->size ());
8722   Vector<char*> *propUName = new Vector<char*>(props->size ());
8723   Vector<int> *propTypeId = new Vector<int>(props->size ());
8724   Vector<char*> *propTypeName = new Vector<char*>(props->size ());
8725   Vector<int> *propFlags = new Vector<int>(props->size ());
8726   Vector<char*> *propName = new Vector<char*>(props->size ());
8727   Vector<void*> *propStateNames = new Vector<void*>(props->size ());
8728   Vector<void*> *propStateUNames = new Vector<void*>(props->size ());
8729
8730   for (int i = 0; i < props->size (); i++)
8731     {
8732       PropDescr *prop = props->fetch (i);
8733       char *pname = prop->name;
8734       if (pname == NULL)
8735         pname = NTXT ("");
8736       char *uname = prop->uname;
8737       if (uname == NULL)
8738         uname = pname;
8739       int vtypeNum = prop->vtype;
8740       if (vtypeNum < 0 || vtypeNum >= TYPE_LAST)
8741         vtypeNum = TYPE_NONE;
8742       const char * vtypeNames[] = VTYPE_TYPE_NAMES;
8743       const char *vtype = vtypeNames[prop->vtype];
8744       Vector<char*> *stateNames = NULL;
8745       Vector<char*> *stateUNames = NULL;
8746       int nStates = prop->getMaxState ();
8747       if (nStates > 0)
8748         {
8749           stateNames = new Vector<char*>(nStates);
8750           stateUNames = new Vector<char*>(nStates);
8751           for (int kk = 0; kk < nStates; kk++)
8752             {
8753               const char * stateName = prop->getStateName (kk);
8754               stateNames->store (kk, dbe_strdup (stateName));
8755               const char * Uname = prop->getStateUName (kk);
8756               stateUNames->store (kk, dbe_strdup (Uname));
8757             }
8758         }
8759       propId->store (i, prop->propID);
8760       propUName->store (i, dbe_strdup (uname));
8761       propTypeId->store (i, prop->vtype);
8762       propTypeName->store (i, dbe_strdup (vtype));
8763       propFlags->store (i, prop->flags);
8764       propName->store (i, dbe_strdup (pname));
8765       propStateNames->store (i, stateNames);
8766       propStateUNames->store (i, stateUNames);
8767     }
8768   Vector<void*> *res = new Vector<void*>(7);
8769   res->store (0, propId);
8770   res->store (1, propUName);
8771   res->store (2, propTypeId);
8772   res->store (3, propTypeName);
8773   res->store (4, propFlags);
8774   res->store (5, propName);
8775   res->store (6, propStateNames);
8776   res->store (7, propStateUNames);
8777   return res;
8778 }
8779
8780 Vector<void *> *
8781 dbeGetExperimentTimeInfo (Vector<int> *exp_ids)
8782 {
8783   int sz = exp_ids->size ();
8784   Vector<long long> *offset_time = new Vector<long long> (sz);
8785   Vector<long long> *start_time = new Vector<long long> (sz);
8786   Vector<long long> *end_time = new Vector<long long> (sz);
8787   Vector<long long> *start_wall_sec = new Vector<long long> (sz);
8788   Vector<char* > *hostname = new Vector<char*> (sz);
8789   Vector<int> *cpu_freq = new Vector<int> (sz);
8790   for (int ii = 0; ii < sz; ii++)
8791     {
8792       int expIdx = exp_ids->fetch (ii);
8793       { // update end_time by forcing fetch of experiment data
8794         // workaround until dbeGetEndTime() is more robust
8795         int id = (expIdx < 0) ? 0 : expIdx;
8796         Experiment *exp = dbeSession->get_exp (id);
8797         if (exp)
8798           {
8799             Vector<DataDescriptor*> *ddscr = exp->getDataDescriptors ();
8800             delete ddscr;
8801           }
8802       }
8803       offset_time->store (ii, dbeGetRelativeStartTime (0, expIdx));
8804       start_time->store (ii, dbeGetStartTime (0, expIdx));
8805       end_time->store (ii, dbeGetEndTime (0, expIdx));
8806       start_wall_sec->store (ii, dbeGetWallStartSec (0, expIdx));
8807       hostname->store (ii, dbeGetHostname (0, expIdx));
8808       cpu_freq->store (ii, dbeGetClock (0, expIdx));
8809     }
8810   Vector<void*> *res = new Vector<void*>(4);
8811   res->store (0, offset_time);
8812   res->store (1, start_time);
8813   res->store (2, end_time);
8814   res->store (3, start_wall_sec);
8815   res->store (4, hostname);
8816   res->store (5, cpu_freq);
8817   return res;
8818 }
8819
8820 Vector<void *> *
8821 dbeGetExperimentDataDescriptors (Vector<int> *exp_ids)
8822 {
8823   int sz = exp_ids->size ();
8824   Vector<void*> *exp_dscr_info = new Vector<void*> (sz);
8825   Vector<void*> *exp_dscr_props = new Vector<void*> (sz);
8826
8827   for (int ii = 0; ii < sz; ii++)
8828     {
8829       int expIdx = exp_ids->fetch (ii);
8830       Vector<void*> *ddscrInfo = dbeGetDataDescriptorsV2 (expIdx);
8831       Vector<void*> *ddscrProps = new Vector<void*> (); // one entry per ddscrInfo
8832       if (ddscrInfo)
8833         {
8834           Vector<int> *dataId = (Vector<int>*)ddscrInfo->fetch (0);
8835           if (dataId)
8836             {
8837               // loop thru data descriptors
8838               int ndata = dataId->size ();
8839               for (int j = 0; j < ndata; ++j)
8840                 {
8841                   Vector<void*> *props = dbeGetDataPropertiesV2 (expIdx, dataId->fetch (j));
8842                   ddscrProps->store (j, props);
8843                 }
8844             }
8845         }
8846       exp_dscr_info->store (ii, ddscrInfo);
8847       exp_dscr_props->store (ii, ddscrProps);
8848     }
8849   Vector<void*> *res = new Vector<void*>(2);
8850   res->store (0, exp_dscr_info);
8851   res->store (1, exp_dscr_props);
8852   return res;
8853 }
8854
8855 static Vector<void *> *
8856 dbeGetTLDataRepVals (VMode view_mode, hrtime_t start_ts, hrtime_t delta,
8857                      int numDeltas, DataView*packets,
8858                      Vector<long> *representativeEvents, bool showDuration);
8859
8860 static bool
8861 dbeHasTLData (int dbevindex, int exp_id, int data_id, int entity_prop_id,
8862               int entity_prop_value, int aux)
8863 {
8864   DataView *packets =
8865           getTimelinePackets (dbevindex, exp_id, data_id, entity_prop_id);
8866   if (!packets || packets->getSize () == 0)
8867     return false;
8868   long start_ind = getIdxByVals (packets, aux, entity_prop_value,
8869                                  0, DataView::REL_GTEQ); // time >= 0
8870   if (start_ind < 0)
8871     return false;
8872
8873   DbeView *dbev = dbeSession->getView (dbevindex);
8874   VMode view_mode = dbev->get_view_mode ();
8875   Experiment *exp = dbeSession->get_exp (exp_id);
8876   if (!hasInvisbleTLEvents (exp, view_mode))
8877     return true; // all events are visible, no further checking required
8878   long end_ind = getIdxByVals (packets, aux, entity_prop_value,
8879                                MAX_TIME, DataView::REL_LTEQ);
8880   for (long ii = start_ind; ii <= end_ind; ii++)
8881     {
8882       if (!isVisibleTLEvent (exp, view_mode, packets, ii))
8883         continue;
8884       return true; // first visible packet => has data
8885     }
8886   return false;
8887 }
8888
8889 Vector<bool> *
8890 dbeHasTLData (int dbev_index, Vector<int> *exp_ids, Vector<int> *data_ids,
8891               Vector<int> *entity_prop_ids, // LWP,CPU,THR, etc
8892               Vector<int> *entity_prop_values, Vector<int> *auxs)
8893 {
8894   DbeView *dbev = dbeSession->getView (dbev_index);
8895   if (!dbev->isShowAll () && (dbev->isShowHideChanged ()
8896                               || dbev->isNewViewMode ()))
8897     {
8898       // LIBRARY_VISIBILITY
8899       dbev->resetAndConstructShowHideStacks ();
8900       if (dbev->isNewViewMode ())
8901         dbev->resetNewViewMode ();
8902       if (dbev->isShowHideChanged ())
8903         dbev->resetShowHideChanged ();
8904     }
8905
8906   int sz = exp_ids->size ();
8907   Vector<bool> *hasVec = new Vector<bool>(sz);
8908   for (int ii = 0; ii < sz; ii++)
8909     {
8910       bool hasData = dbeHasTLData (dbev_index, exp_ids->fetch (ii),
8911                                    data_ids->fetch (ii),
8912                                    entity_prop_ids->fetch (ii),
8913                                    entity_prop_values->fetch (ii),
8914                                    auxs->fetch (ii));
8915       hasVec->store (ii, hasData);
8916     }
8917   return hasVec;
8918 }
8919
8920 /*
8921  *   dbeGetTLData implements:
8922  *   FROM data_id
8923  *     DURATION >= delta AND ( start_ts <= TSTAMP < start_ts+num*delta OR
8924  *                             start_ts <= TSTAMP-DURATION < start_ts+num*delta )
8925  *     OR
8926  *     FAIR( DURATION < delta AND ( start_ts <= TSTAMP < start_ts+num*delta ) )
8927  *     WHERE lfilter
8928  */
8929
8930 Vector<void *> *
8931 dbeGetTLData (
8932               int dbevindex,
8933               int exp_id,
8934               int data_id, // DATA_*
8935               int entity_prop_id, // Show PROP_LWPID, PROP_CPUID, PROP_THRID, PROP_EXPID, or N/A
8936               int entity_prop_value, // which LWPID, CPUID, THRID, EXPID for this request
8937               int aux,
8938               hrtime_t param_start_ts,
8939               hrtime_t param_delta,
8940               int param_numDeltas,
8941               bool getRepresentatives, // fetch TL representatives
8942               Vector<char *> *chartProps) // calculate sums for these property vals
8943 {
8944   const hrtime_t start_ts = param_start_ts;
8945   const hrtime_t delta = param_delta;
8946   const int numDeltas = param_numDeltas;
8947   DbeView *dbev = dbeSession->getView (dbevindex);
8948   if (dbev == NULL)
8949     abort ();
8950   Experiment *exp = dbeSession->get_exp (exp_id);
8951   if (exp == NULL)
8952     return NULL;
8953   if (getRepresentatives == false && chartProps == NULL)
8954     return NULL;
8955   if (delta <= 0)
8956     return NULL;
8957
8958   hrtime_t tmp_ts = start_ts + delta * numDeltas;
8959   if (tmp_ts < start_ts)
8960     tmp_ts = MAX_TIME;
8961   const hrtime_t end_ts = tmp_ts;
8962   if (exp->get_status () == Experiment::INCOMPLETE &&
8963       exp->getLastEvent () < end_ts)
8964     exp->update ();
8965   DataView *packets =
8966           getTimelinePackets (dbevindex, exp_id, data_id, entity_prop_id);
8967   if (packets == NULL)
8968     return NULL; // strange, no data view?
8969
8970   VMode view_mode = dbev->get_view_mode (); // user, expert, machine //YXXX yuck
8971
8972   // storage for calculating timeline representative events
8973   Vector<long> *representativeEvents = NULL;
8974   // list of representative events to be displayed on TL
8975   Vector<int> *binRepIdx = NULL;
8976   // for each bin, index    of current "best" representativeEvent
8977   Vector<void*> *representativeVals = NULL;
8978   // TL representative packets' values
8979
8980   // storage for calculating charts
8981   Vector<int> *propIds = NULL; // [propIdx], which prop to measure
8982   Vector<void*> *propVals = NULL; // [propIdx][bin], prop vals
8983   Vector<int> *propNumStates = NULL; // [propIdx], how many states for prop?
8984   Vector<bool> *propCumulativeChart = NULL; // [propIdx], data represents cumulative totals
8985   Vector<long long> *propCumulativeRecentBinLastVal = NULL; // [propIdx], most recent value
8986   Vector<long long> *propCumulativeRecentBinHighVal = NULL; // [propIdx], highest value for propCumulativeRecentBin
8987   Vector<int> *propCumulativeRecentBin = NULL; // [propIdx], most recent bin
8988
8989   // determine when to show duration of events
8990   bool tmp_repsShowDuration = false;
8991   bool tmp_statesUseDuration = false;
8992   bool tmp_extendMicrostates = false;
8993   const hrtime_t ptimerTickDuration = exp->get_params ()->ptimer_usec * 1000LL; // nanoseconds per tick
8994   const bool hasDuration = packets->getProp (PROP_EVT_TIME) ? true : false;
8995   if (hasDuration)
8996     {
8997       switch (entity_prop_id)
8998         {
8999         case PROP_CPUID:
9000           tmp_repsShowDuration = false;
9001           tmp_statesUseDuration = false;
9002           break;
9003         case PROP_THRID:
9004         case PROP_LWPID:
9005           tmp_repsShowDuration = true;
9006           tmp_statesUseDuration = true;
9007           tmp_extendMicrostates = (DATA_CLOCK == data_id) && (ptimerTickDuration < param_delta);
9008           break;
9009         case PROP_EXPID:
9010         case PROP_NONE: // experiment summary row uses this
9011         default:
9012           if (DATA_SAMPLE == data_id)
9013             {
9014               tmp_repsShowDuration = true;
9015               tmp_statesUseDuration = true;
9016             }
9017           else if (DATA_GCEVENT == data_id)
9018             {
9019               tmp_repsShowDuration = true;
9020               tmp_statesUseDuration = true;
9021             }
9022           else if (DATA_CLOCK == data_id)
9023             {
9024               tmp_repsShowDuration = false;
9025               tmp_statesUseDuration = true;
9026               tmp_extendMicrostates = true;
9027             }
9028           else
9029             {
9030               tmp_repsShowDuration = false;
9031               tmp_statesUseDuration = true;
9032             }
9033           break;
9034         }
9035     }
9036   const bool repsShowDuration = tmp_repsShowDuration; // show stretched callstacks
9037   const bool statesUseDuration = tmp_statesUseDuration; // use duration to calculate state charts
9038   const bool extendMicrostates = tmp_extendMicrostates; // we show discrete profiling microstates with
9039   // width=(tick-1), but for computing
9040   // zoomed-out graphs we need to extend to
9041   // account for all ticks, width=(ntick)
9042   const bool reverseScan = repsShowDuration || extendMicrostates; // scan packets in reverse
9043
9044   // determine range of packet indices (lo_pkt_idx, hi_pkt_idx)
9045   long lo_pkt_idx, hi_pkt_idx;
9046   if (extendMicrostates && !(entity_prop_id == PROP_THRID || entity_prop_id == PROP_LWPID))
9047     {
9048       // merging data from multiple threads, need to scan all packets with timestamp [start_ts, exp end]
9049       hrtime_t exp_end_time = exp->getLastEvent () + 1;
9050       hi_pkt_idx = getIdxByVals (packets, aux, entity_prop_value,
9051                                  exp_end_time, DataView::REL_LT); // last item
9052     }
9053   else
9054     hi_pkt_idx = getIdxByVals (packets, aux, entity_prop_value,
9055                                end_ts, DataView::REL_LT);
9056   if (repsShowDuration)
9057     {
9058       // There are two issues to deal with
9059       // 1. events that end "off screen" to the right
9060       // 2. overlapping events
9061
9062       // 1. events that end "off screen" to the right
9063       // For now, we only consistently handle the case where events don't overlap.
9064       // Note that packet timestamps mark end of duration, not start.
9065       // This means that the rightmost event won't be within hi_pkt_idx.
9066       // Solution: Check if end+1 packet _started_ in-range
9067       // Caveat: because we only look ahead by one packet, if there are
9068       // overlapping duration events (e.g. EXPID aggregation)), zoom level
9069       // and panning combo may cause events with TSTAMP>end_ts
9070       // to appear/disappear.  A complete solution would involve
9071       // a solution to 2.
9072
9073       // 2. overlapping events
9074       // For now, we have a simplistic solution that makes "wide" events win.  However,
9075       // a future solution for deterministically dealing with overlap might look like this:
9076       // - find all packets that touch the visible time range
9077       //   - possibly use two DataViews: one with TSTAMP_HI sort and one with TSTAMP_LO
9078       //     sort to allow efficient determination of packets with HI and LO endpoints in-range
9079       // - create buckets to  capture "winning" event for each bin (each pixel, that is)
9080       // - sort the new list of packets by TSTAMP_HI (for example)
9081       // - looping thru the packets that are in-range, update every bin it touches with it's id
9082       // - if there is overlap, earlier packets will be kicked out of bins
9083       // - On the GUI side, paint one event at a time, as normal.
9084       // - However, for selections, recognize that duration of event may span many bins
9085       //
9086       long idx;
9087       if (hi_pkt_idx >= 0)
9088         // a packet was found to the left of the end time
9089         idx = hi_pkt_idx + 1; // attempt to go one packet right
9090       else
9091         idx = getIdxByVals (packets, aux, entity_prop_value,
9092                             end_ts, DataView::REL_GTEQ);
9093       if (isValidIdx (packets, entity_prop_id, aux, entity_prop_value, idx))
9094         {
9095           int64_t pkt_ts = packets->getLongValue (PROP_TSTAMP, idx);
9096           int64_t duration = packets->getLongValue (PROP_EVT_TIME, idx);
9097           pkt_ts -= duration;
9098           if (pkt_ts < end_ts)
9099             hi_pkt_idx = idx;
9100         }
9101     }
9102   lo_pkt_idx = getIdxByVals (packets, aux, entity_prop_value,
9103                              start_ts, DataView::REL_GTEQ);
9104
9105   // allocate structs that return chart data
9106   bool hasCumulativeCharts = false;
9107   if (chartProps && chartProps->size () > 0)
9108     {
9109       int nprops = chartProps->size ();
9110       // pre-allocate storage
9111       propIds = new Vector<int> (nprops);
9112       propVals = new Vector<void*>(nprops);
9113       propNumStates = new Vector<int> (nprops);
9114       propCumulativeChart = new Vector<bool>(nprops);
9115       propCumulativeRecentBinLastVal = new Vector<long long>(nprops);
9116       propCumulativeRecentBinHighVal = new Vector<long long>(nprops);
9117       propCumulativeRecentBin = new Vector<int>(nprops);
9118       for (int propNum = 0; propNum < nprops; propNum++)
9119         {
9120           const char* propStr = chartProps->fetch (propNum);
9121           int items_per_prop = 0;
9122           int prop_id = PROP_NONE;
9123           if (!strcmp (propStr, "EVT_COUNT"))
9124             items_per_prop = 1; // use PROP_NONE for counting packets
9125           else
9126             {
9127               int lookup_prop_id = dbeSession->getPropIdByName (propStr);
9128               PropDescr *propDscr = packets->getProp (lookup_prop_id);
9129               if (propDscr != NULL)
9130                 {
9131                   switch (propDscr->vtype)
9132                     {
9133                     case TYPE_INT32:
9134                     case TYPE_UINT32:
9135                     case TYPE_INT64:
9136                     case TYPE_UINT64:
9137                       items_per_prop = propDscr->getMaxState () + 1;
9138                       // add extra slot to store values with out-of-range idx
9139                       prop_id = lookup_prop_id;
9140                       break;
9141                     case TYPE_DOUBLE:
9142                       break; // not implemented yet
9143                     case TYPE_STRING:
9144                     case TYPE_OBJ:
9145                     case TYPE_DATE:
9146                     default:
9147                       break;
9148                     }
9149                 }
9150             }
9151           void *vals;
9152           if (!items_per_prop)
9153             vals = NULL;
9154           else if (items_per_prop == 1)
9155             {
9156               Vector<long long> *longVals = new Vector<long long> ();
9157               longVals->store (numDeltas - 1, 0); // initialize all elements
9158               vals = longVals;
9159             }
9160           else
9161             {
9162               Vector<Vector<long long>*> *stateVals =
9163                       new Vector<Vector<long long>*> ();
9164               vals = stateVals;
9165               // initialize only on-demand, some may not be needed
9166             }
9167
9168           bool isCumulativeChart;
9169 #define YXXX_HEAP_VS_TIME 1 // YXXX add data meaning to properties?
9170 #if YXXX_HEAP_VS_TIME
9171           isCumulativeChart = (prop_id == PROP_HCUR_LEAKS || prop_id == PROP_HCUR_ALLOCS);
9172 #endif
9173           if (isCumulativeChart)
9174             hasCumulativeCharts = true;
9175           propIds->store (propNum, prop_id);
9176           propVals->store (propNum, vals);
9177           propNumStates->store (propNum, items_per_prop);
9178           propCumulativeRecentBinLastVal->store (propNum, 0);
9179           propCumulativeRecentBinHighVal->store (propNum, 0);
9180           propCumulativeRecentBin->store (propNum, 0);
9181           propCumulativeChart->store (propNum, isCumulativeChart);
9182         }
9183     }
9184
9185   // Adjust idx range for calculating 'cumulative charts' e.g. heap size
9186   if (hasCumulativeCharts)
9187     {
9188       // set initial values if earlier packet exists
9189       long lo_idx;
9190       if (lo_pkt_idx >= 0)
9191         // packet was found to the right of start
9192         lo_idx = lo_pkt_idx - 1; // attempt to go left by one event
9193       else
9194         // no packet was to the right of start, look left of start
9195         lo_idx = getIdxByVals (packets, aux, entity_prop_value,
9196                                start_ts, DataView::REL_LT);
9197       if (isValidIdx (packets, entity_prop_id, aux, entity_prop_value, lo_idx))
9198         {
9199           // preceding packet found
9200           // update initial values
9201           int nprops = propCumulativeChart->size ();
9202           for (int propNum = 0; propNum < nprops; propNum++)
9203             {
9204               if (!propCumulativeChart->fetch (propNum))
9205                 continue;
9206               int propId = propIds->fetch (propNum);
9207               long long value = packets->getLongValue (propId, lo_idx);
9208               propCumulativeRecentBinLastVal->store (propNum, value);
9209               propCumulativeRecentBinHighVal->store (propNum, value);
9210             }
9211           // update indices used for iterating
9212           lo_pkt_idx = lo_idx;
9213           if (hi_pkt_idx < lo_pkt_idx)
9214             hi_pkt_idx = lo_pkt_idx;
9215         }
9216     }
9217   if (lo_pkt_idx < 0 || hi_pkt_idx < 0)
9218     goto dbeGetTLData_done; // no data; return empty vectors, not null
9219
9220   // representative events (subset of callstacks to represent on TL)
9221   if (getRepresentatives)
9222     {
9223       representativeEvents = new Vector<long>(numDeltas);
9224       // per-bin, longest event's index
9225       binRepIdx = new Vector<int>(numDeltas);
9226       for (int ii = 0; ii < numDeltas; ++ii)
9227         binRepIdx->append (-1);
9228     }
9229   // While packets are sorted by _end_ timestamp (TSTAMP),
9230   // after calculating start times for non-zero durations,
9231   // start times are not guaranteed be monotonically increasing.
9232   // For packets with duration, we'll scan them in reverse order to
9233   // take advantage of the monotonically decreasing _end_ timestamps.
9234   long start_idx, idx_inc;
9235   if (!reverseScan)
9236     {
9237       start_idx = lo_pkt_idx;
9238       idx_inc = 1;
9239     }
9240   else
9241     {
9242       start_idx = hi_pkt_idx;
9243       idx_inc = -1;
9244     }
9245   for (long ii = start_idx; ii >= lo_pkt_idx && ii <= hi_pkt_idx; ii += idx_inc)
9246     {
9247       if (!isVisibleTLEvent (exp, view_mode, packets, ii) && !hasCumulativeCharts)
9248         continue;
9249
9250       // determine packet time duration and start bin
9251       int tmp_start_bin; // packet start bin
9252       int tmp_end_bin; // packet end bin (inclusive)
9253       const hrtime_t pkt_end_ts = packets->getLongValue (PROP_TSTAMP, ii);
9254       const hrtime_t pkt_dur = packets->getLongValue (PROP_EVT_TIME, ii);
9255       const hrtime_t pkt_start_ts = pkt_end_ts - pkt_dur;
9256       if (pkt_end_ts < start_ts && !hasCumulativeCharts)
9257         continue; // weird, should not happen
9258       if (pkt_start_ts >= end_ts)
9259         continue; // could happen
9260       hrtime_t bin_end_ts = pkt_end_ts;
9261       if (bin_end_ts >= end_ts)
9262         bin_end_ts = end_ts - 1;
9263       tmp_end_bin = (int) ((bin_end_ts - start_ts) / delta);
9264       hrtime_t bin_start_ts = pkt_start_ts;
9265       if (bin_start_ts < start_ts)
9266         bin_start_ts = start_ts; // event truncated to left.
9267       tmp_start_bin = (int) ((bin_start_ts - start_ts) / delta);
9268       // By definition
9269       //   (end_ts - start_ts) == delta * numDeltas
9270       // and we know
9271       //   pkt_start < end_ts
9272       // therefore
9273       //   (pkt_start - start_ts) < delta * numDeltas
9274       //   (pkt_start - start_ts) / delta < numDeltas
9275       //   bin < numDeltas
9276       assert (tmp_end_bin < numDeltas);
9277       assert (tmp_start_bin < numDeltas);
9278       const bool is_offscreen = tmp_end_bin < 0 ? true : false;
9279       if (tmp_end_bin < 0)
9280         tmp_end_bin = 0;
9281       const int pkt_end_bin = tmp_end_bin; // packet end bin (inclusive)
9282       const int pkt_start_bin = tmp_start_bin;
9283       if (getRepresentatives && !is_offscreen)
9284         { // find best representative
9285           // Note: for events with duration, we're scanning packets in order
9286           // of decreasing end-timestamp.  This means that the first packet
9287           // that hits a particular _start_ bin will have the longest duration
9288           // of any later packet that might hit that start bin.  The
9289           // the first packet will be the best (longest) packet.
9290           const int bin = reverseScan ? pkt_start_bin : pkt_end_bin;
9291           int eventIdx = binRepIdx->fetch (bin);
9292           if (eventIdx == -1)
9293             {
9294               eventIdx = representativeEvents->size (); // append to end
9295               representativeEvents->append (ii);
9296               binRepIdx->store (bin, eventIdx);
9297             }
9298         }
9299       if (propIds)
9300         { // per-bin chart: sum across filtered packets
9301           for (int propNum = 0; propNum < propIds->size (); propNum++)
9302             {
9303               void *thisProp = propVals->fetch (propNum);
9304               if (thisProp == NULL)
9305                 continue; // no valid data
9306               if (is_offscreen && !propCumulativeChart->fetch (propNum))
9307                 continue; // offscreen events are only processed for cumulative charts
9308               int propId = propIds->fetch (propNum);
9309               long long val;
9310               if (propId == PROP_NONE)
9311                 val = 1; // count
9312               else
9313                 val = packets->getLongValue (propId, ii);
9314               long nitems = propNumStates->fetch (propNum);
9315               if (nitems < 1)
9316                 continue;
9317               else if (nitems == 1)
9318                 {
9319                   // chart is not based on not multiple states
9320                   Vector<long long>* thisPropVals =
9321                           (Vector<long long>*)thisProp;
9322                   if (thisPropVals->size () == 0)
9323                     thisPropVals->store (numDeltas - 1, 0);
9324                   const int bin = statesUseDuration ? pkt_start_bin : pkt_end_bin;
9325                   if (!propCumulativeChart->fetch (propNum))
9326                     {
9327                       val += thisPropVals->fetch (bin);
9328                       thisPropVals->store (bin, val);
9329                     }
9330                   else
9331                     {
9332                       // propCumulativeChart
9333                       long long high_value = propCumulativeRecentBinHighVal->fetch (propNum);
9334                       int last_bin = propCumulativeRecentBin->fetch (propNum);
9335                       if (last_bin < bin)
9336                         {
9337                           // backfill from previous event
9338                           // last_bin: store largest value (in case of multiple events)
9339                           thisPropVals->store (last_bin, high_value);
9340                           // propagate forward the bin's last value
9341                           long long last_value = propCumulativeRecentBinLastVal->fetch (propNum);
9342                           for (int kk = last_bin + 1; kk < bin; kk++)
9343                             thisPropVals->store (kk, last_value);
9344                           // prepare new bin for current event
9345                           high_value = 0; // high value of next bin is 0.
9346                           propCumulativeRecentBinHighVal->store (propNum, high_value);
9347                           propCumulativeRecentBin->store (propNum, bin);
9348                         }
9349                       long long this_value = packets->getLongValue (propId, ii);
9350                       propCumulativeRecentBinLastVal->store (propNum, this_value);
9351                       if (high_value < this_value)
9352                         {
9353                           // record the max
9354                           high_value = this_value;
9355                           propCumulativeRecentBinHighVal->store (propNum, high_value);
9356                         }
9357                       if (ii == hi_pkt_idx)
9358                         {
9359                           // bin: show largest value (in case of multiple events
9360                           thisPropVals->store (bin, high_value);
9361                           //forward fill remaining bins
9362                           for (int kk = bin + 1; kk < numDeltas; kk++)
9363                             thisPropVals->store (kk, this_value);
9364                         }
9365                     }
9366                 }
9367               else
9368                 {
9369                   // means val is actually a state #
9370                   Vector<Vector<long long>*>* thisPropStateVals =
9371                           (Vector<Vector<long long>*>*)thisProp;
9372                   if (thisPropStateVals->size () == 0)
9373                     thisPropStateVals->store (numDeltas - 1, 0);
9374                   long stateNum;
9375                   if (val >= 0 && val < nitems)
9376                     stateNum = (long) val;
9377                   else
9378                     stateNum = nitems - 1; // out of range, use last slot
9379                   hrtime_t graph_pkt_dur = pkt_dur;
9380                   hrtime_t graph_pkt_start_ts = pkt_start_ts;
9381                   int tmp2_start_bin = pkt_start_bin;
9382                   if (propId == PROP_MSTATE)
9383                     {
9384                       if (statesUseDuration && extendMicrostates)
9385                         {
9386                           // microstate stacks are shown and filtered with width=NTICK-1
9387                           // but for microstate graph calcs use width=NTICK.
9388                           graph_pkt_dur += ptimerTickDuration;
9389                           graph_pkt_start_ts -= ptimerTickDuration;
9390                           hrtime_t bin_start_ts = graph_pkt_start_ts;
9391                           if (bin_start_ts < start_ts)
9392                             bin_start_ts = start_ts; // event truncated to left.
9393                           tmp2_start_bin = (int) ((bin_start_ts - start_ts) / delta);
9394                         }
9395                     }
9396                   const int graph_pkt_start_bin = statesUseDuration ? tmp2_start_bin : pkt_end_bin;
9397
9398                   // We will distribute the state's presence evenly over duration of the event.
9399                   // When only a 'partial bin' is touched by an event, adjust accordingly.
9400                   long long value_per_bin; // weight to be applied to each bin
9401                   {
9402                     long long weight;
9403                     if (propId == PROP_MSTATE)  // ticks to nanoseconds
9404                       weight = packets->getLongValue (PROP_NTICK, ii) * ptimerTickDuration;
9405                     else if (graph_pkt_dur)
9406                       weight = graph_pkt_dur; // nanoseconds
9407                     else
9408                       weight = 1; // no duration; indicate presence
9409                     if (graph_pkt_start_bin != pkt_end_bin)
9410                       {
9411                         // spans multiple bins
9412                         double nbins = (double) graph_pkt_dur / delta;
9413                         value_per_bin = weight / nbins;
9414                       }
9415                     else
9416                       value_per_bin = weight;
9417                   }
9418                   for (int evtbin = graph_pkt_start_bin; evtbin <= pkt_end_bin; evtbin++)
9419                     {
9420                       Vector<long long>* stateValues =
9421                               (Vector<long long>*) thisPropStateVals->fetch (evtbin);
9422                       if (stateValues == NULL)
9423                         {
9424                           // on-demand storage
9425                           stateValues = new Vector<long long>(nitems);
9426                           stateValues->store (nitems - 1, 0); // force memset of full vector
9427                           thisPropStateVals->store (evtbin, stateValues);
9428                         }
9429                       long long new_val = stateValues->fetch (stateNum);
9430                       if (graph_pkt_start_bin == pkt_end_bin ||
9431                           (evtbin > graph_pkt_start_bin && evtbin < pkt_end_bin))
9432                         {
9433                           new_val += value_per_bin;
9434                         }
9435                       else
9436                         {
9437                           // partial bin
9438                           const hrtime_t bin_start = start_ts + evtbin * delta;
9439                           const hrtime_t bin_end = start_ts + (evtbin + 1) * delta - 1;
9440                           if (evtbin == graph_pkt_start_bin)
9441                             {
9442                               // leftmost bin
9443                               if (graph_pkt_start_ts < bin_start)
9444                                 new_val += value_per_bin;
9445                               else
9446                                 {
9447                                   double percent = (double) (bin_end - graph_pkt_start_ts) / delta;
9448                                   new_val += value_per_bin*percent;
9449                                 }
9450                             }
9451                           else
9452                             {
9453                               // rightmost bin
9454                               if (pkt_end_ts > bin_end)
9455                                 new_val += value_per_bin;
9456                               else
9457                                 {
9458                                   double percent = (double) (pkt_end_ts - bin_start) / delta;
9459                                   new_val += value_per_bin*percent;
9460                                 }
9461                             }
9462                         }
9463                       stateValues->store (stateNum, new_val);
9464                     }
9465                 }
9466             }
9467         }
9468     }
9469   delete binRepIdx;
9470   delete propIds;
9471   delete propCumulativeChart;
9472   delete propCumulativeRecentBinLastVal;
9473   delete propCumulativeRecentBinHighVal;
9474   delete propCumulativeRecentBin;
9475   if (representativeEvents != NULL && reverseScan)
9476     {
9477       if (repsShowDuration)
9478         {
9479           //YXXX for now prune here, but in the future, let gui decide what to show
9480           // Prune events that are completely obscured long duration events.
9481           // Note: representativeEvents is sorted by decreasing _end_ timestamps.
9482           Vector<long> *prunedEvents = new Vector<long>(numDeltas);
9483           hrtime_t prev_start_ts = MAX_TIME;
9484           long repCnt = representativeEvents->size ();
9485           for (long kk = 0; kk < repCnt; kk++)
9486             {
9487               long ii = representativeEvents->fetch (kk);
9488               hrtime_t tmp_end_ts = packets->getLongValue (PROP_TSTAMP, ii);
9489               hrtime_t tmp_dur = packets->getLongValue (PROP_EVT_TIME, ii);
9490               hrtime_t tmp_start_ts = tmp_end_ts - tmp_dur;
9491               if (tmp_start_ts >= prev_start_ts)
9492                 // this event would be completely hidden
9493                 // (because of sorting, we know tmp_end_ts <= prev_end_ts)
9494                 continue;
9495               prev_start_ts = tmp_start_ts;
9496               prunedEvents->append (ii);
9497             }
9498           // invert order to to get increasing _end_ timestamps
9499           representativeEvents->reset ();
9500           for (long kk = prunedEvents->size () - 1; kk >= 0; kk--)
9501             {
9502               long packet_idx = prunedEvents->fetch (kk);
9503               representativeEvents->append (packet_idx);
9504             }
9505           delete prunedEvents;
9506         }
9507       else
9508         { // !repsShowDuration
9509           // Note: representativeEvents is sorted by decreasing _end_ timestamps.
9510           // Reverse the order:
9511           long hi_idx = representativeEvents->size () - 1;
9512           long lo_idx = 0;
9513           while (hi_idx > lo_idx)
9514             {
9515               // swap
9516               long lo = representativeEvents->fetch (lo_idx);
9517               long hi = representativeEvents->fetch (hi_idx);
9518               representativeEvents->store (lo_idx, hi);
9519               representativeEvents->store (hi_idx, lo);
9520               hi_idx--;
9521               lo_idx++;
9522             }
9523         }
9524     }
9525
9526 dbeGetTLData_done:
9527   if (getRepresentatives)
9528     {
9529       representativeVals = dbeGetTLDataRepVals (view_mode, start_ts, delta,
9530                     numDeltas, packets, representativeEvents, repsShowDuration);
9531       delete representativeEvents;
9532     }
9533   Vector<void*> *results = new Vector<void*> (2);
9534   results->store (0, representativeVals);
9535   results->store (1, propVals);
9536   return results;
9537 }
9538
9539 // add representative events to return buffer
9540
9541 static Vector<void *> *
9542 dbeGetTLDataRepVals (VMode view_mode, hrtime_t start_ts, hrtime_t delta,
9543                      int numDeltas, DataView*packets,
9544                      Vector<long> *representativeEvents, bool showDuration)
9545 {
9546   int numrecs = representativeEvents ? representativeEvents->size () : 0;
9547   // allocate storage for results
9548   Vector<int> *startBins = new Vector<int>(numrecs);
9549   Vector<int> *numBins = new Vector<int>(numrecs);
9550   Vector<Obj> *eventIdxs = new Vector<Obj>(numrecs);
9551   Vector<Obj> *stackIds = NULL;
9552   if (packets->getProp (PROP_FRINFO))
9553     stackIds = new Vector<Obj>(numrecs);
9554   Vector<int> *mstates = NULL;
9555   if (packets->getProp (PROP_MSTATE))
9556     mstates = new Vector<int>(numrecs);
9557   Vector<Vector<long long>*> *sampleVals = NULL;
9558   if (packets->getProp (PROP_SMPLOBJ))
9559     sampleVals = new Vector<Vector<long long>*>(numrecs);
9560   Vector<long long> *timeStart = new Vector<long long>(numrecs);
9561   Vector<long long> *timeEnd = new Vector<long long>(numrecs);
9562   int prevEndBin = -1; // make sure we don't overlap bins
9563   for (int eventIdx = 0; eventIdx < numrecs; eventIdx++)
9564     {
9565       long packetIdx = representativeEvents->fetch (eventIdx);
9566       // long eventId = packets->getIdByIdx( packetIdx );
9567       const hrtime_t pkt_tstamp = packets->getLongValue (PROP_TSTAMP, packetIdx);
9568       const hrtime_t pkt_dur = showDuration ? packets->getLongValue (PROP_EVT_TIME, packetIdx) : 0;
9569       timeStart->store (eventIdx, pkt_tstamp - pkt_dur);
9570       timeEnd->store (eventIdx, pkt_tstamp);
9571
9572       // calc startBin
9573       int startBin = (int) ((pkt_tstamp - pkt_dur - start_ts) / delta);
9574       if (startBin <= prevEndBin)
9575         startBin = prevEndBin + 1;
9576       // calc binCnt
9577       int endBin = (int) ((pkt_tstamp - start_ts) / delta);
9578       if (endBin >= numDeltas)
9579         endBin = numDeltas - 1;
9580       int binCnt = endBin - startBin + 1;
9581       prevEndBin = endBin;
9582       startBins->store (eventIdx, startBin);
9583       numBins->store (eventIdx, binCnt);
9584       eventIdxs->store (eventIdx, packetIdx); // store packet's idx
9585       if (stackIds != NULL)
9586         {
9587           void* stackId = getStack (view_mode, packets, packetIdx);
9588           stackIds->store (eventIdx, (Obj) (unsigned long) stackId);
9589         }
9590       if (mstates != NULL)
9591         {
9592           int mstate = packets->getIntValue (PROP_MSTATE, packetIdx);
9593           mstates->store (eventIdx, mstate);
9594         }
9595       if (sampleVals != NULL)
9596         {
9597           Sample* sample = (Sample*) packets->getObjValue (PROP_SMPLOBJ, packetIdx);
9598           if (!sample || !sample->get_usage ())
9599             sample = sample;
9600           else
9601             {
9602               PrUsage* prusage = sample->get_usage ();
9603               Vector<long long> *mstateVals = prusage->getMstateValues ();
9604               sampleVals->store (eventIdx, mstateVals);
9605             }
9606         }
9607     }
9608   // caller responsible for: delete representativeEvents;
9609   Vector<void*> *results = new Vector<void*> (8);
9610   results->store (0, startBins);
9611   results->store (1, numBins);
9612   results->store (2, eventIdxs);
9613   results->store (3, stackIds);
9614   results->store (4, mstates);
9615   results->store (5, sampleVals);
9616   results->store (6, timeStart);
9617   results->store (7, timeEnd);
9618   return results;
9619 }
9620
9621 // starting from <event_id> packet idx, step <move_count> visible events
9622 // return the resulting idx and that packet's center time, or null if no event.
9623 Vector<long long> *
9624 dbeGetTLEventCenterTime (int dbevindex, int exp_id, int data_id,
9625                          int entity_prop_id, int entity_prop_val, int aux,
9626                          long long event_id, long long move_count)
9627 {
9628   DataView *packets = getTimelinePackets (dbevindex, exp_id, data_id,
9629                                           entity_prop_id);
9630   if (packets == NULL)
9631     return NULL;
9632   long idx = (long) event_id;
9633
9634   DbeView *dbev = dbeSession->getView (dbevindex);
9635   VMode view_mode = dbev->get_view_mode ();
9636   Experiment *exp = dbeSession->get_exp (exp_id);
9637   int direction;
9638   if (move_count == 0)
9639     direction = 0;
9640   else if (move_count < 0)
9641     {
9642       move_count = -move_count;
9643       direction = -1;
9644     }
9645   else
9646     direction = 1;
9647   idx = getTLVisibleIdxByStepping (exp, view_mode, entity_prop_id, packets, aux,
9648                                    entity_prop_val, idx, move_count, direction);
9649   if (idx >= 0)
9650     {
9651       long long ts = packets->getLongValue (PROP_TSTAMP, idx);
9652       long long dur = packets->getLongValue (PROP_EVT_TIME, idx);
9653       long long center = ts - dur / 2;
9654       Vector<long long> *results = new Vector<long long> (2);
9655       results->store (0, idx); // result idx
9656       results->store (1, center); // result timestamp
9657       return results;
9658     }
9659   return NULL;
9660 }
9661
9662 long long
9663 dbeGetTLEventIdxNearTime (int dbevindex, int exp_id, int data_id,
9664                           int entity_prop_id, int entity_prop_val, int aux,
9665                           int searchDirection, long long tstamp)
9666 {
9667   DataView *packets = getTimelinePackets (dbevindex, exp_id, data_id,
9668                                           entity_prop_id);
9669   if (packets == NULL)
9670     return -1;
9671   DbeView *dbev = dbeSession->getView (dbevindex);
9672   VMode view_mode = dbev->get_view_mode ();
9673   Experiment *exp = dbeSession->get_exp (exp_id);
9674   if (searchDirection < 0)
9675     {
9676       int idx = getTLVisibleIdxByVals (exp, view_mode, entity_prop_id,
9677                                        packets, aux, entity_prop_val, tstamp,
9678                                        DataView::REL_LTEQ);
9679       if (idx != -1)
9680         return idx;
9681       searchDirection = 1; // couldn't find to left, try to right
9682     }
9683   if (searchDirection > 0)
9684     {
9685       int idx = getTLVisibleIdxByVals (exp, view_mode, entity_prop_id,
9686                                        packets, aux, entity_prop_val, tstamp,
9687                                        DataView::REL_GTEQ);
9688       if (idx != -1)
9689         return idx;
9690       // couldn't find to right, fall through to generic
9691     }
9692   // search left and right of timestamp
9693   long idx1, idx2;
9694   idx1 = getTLVisibleIdxByVals (exp, view_mode, entity_prop_id,
9695                                 packets, aux, entity_prop_val, tstamp,
9696                                 DataView::REL_LT);
9697   idx2 = getTLVisibleIdxByVals (exp, view_mode, entity_prop_id,
9698                                 packets, aux, entity_prop_val, tstamp,
9699                                 DataView::REL_GTEQ);
9700   if (idx1 == -1)
9701     return idx2;
9702   else if (idx2 == -1)
9703     return idx1;
9704
9705   // both valid, so need to compare to see which is closer
9706   long long t1 = packets->getLongValue (PROP_TSTAMP, idx1);
9707   long long t2 = packets->getLongValue (PROP_TSTAMP, idx2);
9708   long long t2dur = packets->getLongValue (PROP_EVT_TIME, idx2);
9709   long long delta1 = tstamp - t1; // should always be positive
9710   long long delta2 = (t2 - t2dur) - tstamp; // if negative, overlaps idx1
9711   if (delta1 > delta2)
9712     return idx2;
9713   else
9714     return idx1;
9715 }
9716
9717 enum Aggr_type
9718 {
9719   AGGR_NONE,
9720   AGGR_FAIR,
9721   AGGR_MAX,
9722   AGGR_MIN,
9723   AGGR_CNT,
9724   AGGR_SUM,
9725   AGGR_AVG
9726 };
9727
9728 static Aggr_type
9729 getAggrFunc (char *aname)
9730 {
9731   Aggr_type agrfn = AGGR_NONE;
9732   if (aname == NULL)
9733     return agrfn;
9734   if (strcmp (aname, NTXT ("FAIR")) == 0)
9735     agrfn = AGGR_FAIR;
9736   else if (strcmp (aname, NTXT ("MAX")) == 0)
9737     agrfn = AGGR_MAX;
9738   else if (strcmp (aname, NTXT ("MIN")) == 0)
9739     agrfn = AGGR_MIN;
9740   else if (strcmp (aname, NTXT ("CNT")) == 0)
9741     agrfn = AGGR_CNT;
9742   else if (strcmp (aname, NTXT ("SUM")) == 0)
9743     agrfn = AGGR_SUM;
9744   else if (strcmp (aname, NTXT ("AVG")) == 0)
9745     agrfn = AGGR_AVG;
9746   return agrfn;
9747 }
9748
9749 static long long
9750 computeAggrVal (DefaultMap<long long, long long> *fval_map, Aggr_type agrfn)
9751 {
9752   long long aval = 0;
9753   long cnt = 0;
9754   Vector<long long> *fvals = fval_map->values ();
9755   long nvals = fvals->size ();
9756   for (int i = 0; i < nvals; ++i)
9757     {
9758       long long val = fvals->fetch (i);
9759       switch (agrfn)
9760         {
9761         case AGGR_FAIR:
9762           aval = val;
9763           break;
9764         case AGGR_MAX:
9765           if (aval < val || cnt == 0)
9766             aval = val;
9767           break;
9768         case AGGR_MIN:
9769           if (aval > val || cnt == 0)
9770             aval = val;
9771           break;
9772         case AGGR_CNT:
9773           aval = cnt + 1;
9774           break;
9775         case AGGR_SUM:
9776         case AGGR_AVG:
9777           aval += val;
9778           break;
9779         case AGGR_NONE:
9780           break;
9781         }
9782       if (agrfn == AGGR_FAIR)
9783         break;
9784       cnt += 1;
9785     }
9786
9787   // Finalize aggregation
9788   if (agrfn == AGGR_AVG)
9789     if (cnt > 0)
9790       aval = (aval + cnt / 2) / cnt;
9791   delete fvals;
9792   return aval;
9793 }
9794
9795 Vector<long long> *
9796 dbeGetAggregatedValue (int data_id, // data table id
9797                        char *lfilter, // local filter
9798                        char *fexpr, // function expression
9799                        char *pname_ts, // property name for timestamp
9800                        hrtime_t start_ts, // start of the first time interval
9801                        hrtime_t delta, // time interval length
9802                        int num, // number of time intervals
9803                        char *pname_key, // property name for aggregation key
9804                        char *aggr_func) // aggregation function
9805 {
9806   Vector<long long> *res = new Vector<long long>;
9807   Experiment *exp = dbeSession->get_exp (0);
9808   if (exp == NULL)
9809     return res;
9810   hrtime_t end_ts = start_ts + delta * num;
9811   if (end_ts < start_ts)    // check overflow
9812     end_ts = MAX_TIME;
9813
9814   if (exp->get_status () == Experiment::INCOMPLETE
9815       && exp->getLastEvent () < end_ts)
9816     exp->update ();
9817
9818   DataDescriptor *dataDscr = exp->get_raw_events (data_id);
9819   if (dataDscr == NULL)
9820     return res;
9821
9822   // Process timestamp argument
9823   int prop_ts = dbeSession->getPropIdByName (pname_ts);
9824   if (prop_ts == PROP_NONE)
9825     return res;
9826   assert (prop_ts == -1);
9827
9828   // Parse all expressions
9829   Expression *flt_expr = NULL;
9830   if (lfilter != NULL)
9831     flt_expr = dbeSession->ql_parse (lfilter);
9832   Expression *func_expr = NULL;
9833   if (fexpr != NULL)
9834     func_expr = dbeSession->ql_parse (fexpr);
9835   if (func_expr == NULL)   // Not specified or malformed
9836     return res;
9837
9838   // Process aggregation key argument
9839   int prop_key = PROP_NONE;
9840   Data *data_key = NULL;
9841   if (pname_key != NULL)
9842     {
9843       prop_key = dbeSession->getPropIdByName (pname_key);
9844       data_key = dataDscr->getData (prop_key);
9845       if (data_key == NULL)   // Specified but not found
9846         return res;
9847     }
9848
9849   // Process aggregation function argument
9850   Aggr_type agrfn = AGGR_FAIR;
9851   if (aggr_func != NULL)
9852     {
9853       agrfn = getAggrFunc (aggr_func);
9854       if (agrfn == AGGR_NONE) // Specified but not recognized
9855         return res;
9856     }
9857   DefaultMap<long long, long long> *
9858         fval_map = new DefaultMap<long long, long long>; // key_val -> func_val
9859   Vector<long long> *key_set = NULL;
9860   assert (key_set != NULL);
9861   if (key_set == NULL)
9862     {
9863       key_set = new Vector<long long>;
9864       key_set->append (0L);
9865     }
9866   DefaultMap<long long, int> *key_seen = new DefaultMap<long long, int>;
9867   long idx_prev = -1;
9868   for (int tidx = 0; tidx < num; ++tidx)
9869     {
9870       long idx_cur = -1;
9871       assert (idx_cur != -1);
9872       int left = key_set->size ();
9873       key_seen->clear ();
9874       for (long idx = idx_cur; idx > idx_prev; --idx)
9875         {
9876           long id = 0;
9877           assert (id != 0);
9878
9879           // Pre-create expression context
9880           Expression::Context ctx (dbeSession->getView (0), exp, NULL, id);
9881           // First use the filter
9882           if (flt_expr != NULL)
9883             if (flt_expr->eval (&ctx) == 0)
9884               continue;
9885
9886           // Calculate the key
9887           // keys are limited to integral values
9888           long long key = 0;
9889           if (data_key != NULL)
9890             key = data_key->fetchLong (id);
9891
9892           // Check if already seen
9893           if (key_seen->get (key) == 1)
9894             continue;
9895           key_seen->put (key, 1);
9896           left -= 1;
9897
9898           // Calculate function value
9899           // function values are limited to integral values
9900           long long fval = func_expr->eval (&ctx);
9901           fval_map->put (key, fval);
9902           if (left == 0)
9903             break;
9904         }
9905       idx_prev = idx_cur;
9906       long long aval = computeAggrVal (fval_map, agrfn);
9907       res->store (tidx, aval);
9908     }
9909   delete key_seen;
9910   delete fval_map;
9911   delete flt_expr;
9912   delete func_expr;
9913   return res;
9914 }
9915
9916 Vector<char*> *
9917 dbeGetLineInfo (Obj pc)
9918 {
9919   DbeInstr *instr = (DbeInstr*) pc;
9920   if (instr == NULL || instr->get_type () != Histable::INSTR)
9921     return NULL;
9922   DbeLine *dbeline = (DbeLine*) instr->convertto (Histable::LINE);
9923   const char *fname = dbeline ? dbeline->sourceFile->get_name () : NTXT ("");
9924   char lineno[16];
9925   *lineno = '\0';
9926   if (dbeline != NULL)
9927     snprintf (lineno, sizeof (lineno), NTXT ("%d"), dbeline->lineno);
9928   Vector<char*> *res = new Vector<char*>(2);
9929   res->store (0, strdup (fname));
9930   res->store (1, strdup (lineno));
9931   return res;
9932 }
9933
9934 int
9935 dbeSetAlias (char *name, char *uname, char *expr)
9936 {
9937   char *res = dbeSession->indxobj_define (name, uname, expr, NULL, NULL);
9938   return res == NULL ? 0 : 1;
9939 }
9940
9941 Vector<char*> *
9942 dbeGetAlias (char *name)
9943 {
9944   Vector<char*> *res = new Vector<char*>;
9945   int idx = dbeSession->findIndexSpaceByName (name);
9946   if (idx >= 0)
9947     {
9948       char *str = dbeSession->getIndexSpaceDescr (idx);
9949       res->append (dbe_strdup (str));
9950       str = dbeSession->getIndexSpaceExprStr (idx);
9951       res->append (dbe_strdup (str));
9952     }
9953   return res;
9954 }
9955
9956 static int
9957 key_cmp (const void *p1, const void *p2)
9958 {
9959   long long ll1 = *(long long*) p1;
9960   long long ll2 = *(long long*) p2;
9961   return ll1 < ll2 ? -1 : ll1 > ll2 ? 1 : 0;
9962 }
9963
9964 Vector<Vector<long long>*> *
9965 dbeGetXYPlotData (
9966                   int data_id, // data table id
9967                   char *lfilter, // local filter expression
9968                   char *arg, // name for the argument
9969                   char *func1, // expression for the first axis (x)
9970                   char *aggr1, // aggregation function for func1: "SUM","CNT",...
9971                   char *func2, // expression for the second axis (y)
9972                   char *aggr2, // aggregation function for func2
9973                   char *func3, // expression for the third axis (color)
9974                   char *aggr3) // aggregation function for func3
9975 {
9976   Vector<Vector<long long>*> *res = new Vector<Vector<long long>*>;
9977   Experiment *exp = dbeSession->get_exp (0);
9978   if (exp == NULL)
9979     return res;
9980   if (exp->get_status () == Experiment::INCOMPLETE)
9981     exp->update ();
9982
9983   DataDescriptor *dataDscr = exp->get_raw_events (data_id);
9984   if (dataDscr == NULL)
9985     return res;
9986
9987   // Parse all expressions
9988   Vector<Expression*> *funcs = new Vector<Expression*>;
9989   Vector<Aggr_type> *aggrs = new Vector<Aggr_type>;
9990   Vector<DefaultMap<long long, long long>*> *fval_maps =
9991           new Vector<DefaultMap<long long, long long>*>;
9992   Vector<DefaultMap<long long, long>*> *cnt_maps =
9993           new Vector<DefaultMap<long long, long>*>;
9994   if (func1 != NULL)
9995     {
9996       Expression *expr = dbeSession->ql_parse (func1);
9997       funcs->append (expr);
9998       aggrs->append (getAggrFunc (aggr1));
9999       fval_maps->append (new DefaultMap<long long, long long>);
10000       cnt_maps->append (new DefaultMap<long long, long>);
10001       res->append (new Vector<long long>);
10002       if (func2 != NULL)
10003         {
10004           expr = dbeSession->ql_parse (func2);
10005           funcs->append (expr);
10006           aggrs->append (getAggrFunc (aggr2));
10007           fval_maps->append (new DefaultMap<long long, long long>);
10008           cnt_maps->append (new DefaultMap<long long, long>);
10009           res->append (new Vector<long long>);
10010           if (func3 != NULL)
10011             {
10012               expr = dbeSession->ql_parse (func3);
10013               funcs->append (expr);
10014               aggrs->append (getAggrFunc (aggr3));
10015               fval_maps->append (new DefaultMap<long long, long long>);
10016               cnt_maps->append (new DefaultMap<long long, long>);
10017               res->append (new Vector<long long>);
10018             }
10019         }
10020     }
10021   if (funcs->size () == 0)
10022     {
10023       funcs->destroy ();
10024       delete funcs;
10025       fval_maps->destroy ();
10026       delete fval_maps;
10027       cnt_maps->destroy ();
10028       delete cnt_maps;
10029       delete aggrs;
10030       return res;
10031     }
10032   Expression *arg_expr = NULL;
10033   if (arg != NULL)
10034     arg_expr = dbeSession->ql_parse (arg);
10035   if (arg_expr == NULL)
10036     {
10037       funcs->destroy ();
10038       delete funcs;
10039       fval_maps->destroy ();
10040       delete fval_maps;
10041       cnt_maps->destroy ();
10042       delete cnt_maps;
10043       delete aggrs;
10044       return res;
10045     }
10046   Expression *flt_expr = NULL;
10047   if (lfilter != NULL)
10048     flt_expr = dbeSession->ql_parse (lfilter);
10049   Vector<long long> *kidx_map = new Vector<long long>(); // key_idx -> key_val
10050   for (long i = 0; i < dataDscr->getSize (); i++)
10051     {
10052       Expression::Context ctx (dbeSession->getView (0), exp, NULL, i);
10053       // First use the filter
10054       if (flt_expr != NULL)
10055         if (flt_expr->eval (&ctx) == 0)
10056           continue;
10057
10058       // Compute the argument
10059       long long key = arg_expr->eval (&ctx);
10060       if (kidx_map->find (key) == -1)
10061         kidx_map->append (key);
10062       for (long j = 0; j < funcs->size (); ++j)
10063         {
10064           Expression *func = funcs->fetch (j);
10065           Aggr_type aggr = aggrs->fetch (j);
10066           DefaultMap<long long, long long> *fval_map = fval_maps->fetch (j);
10067           DefaultMap<long long, long> *cnt_map = cnt_maps->fetch (j);
10068           long long fval = func->eval (&ctx);
10069           long long aval = fval_map->get (key);
10070           long cnt = cnt_map->get (key);
10071           switch (aggr)
10072             {
10073             case AGGR_NONE:
10074             case AGGR_FAIR:
10075               if (cnt == 0)
10076                 aval = fval;
10077               break;
10078             case AGGR_MAX:
10079               if (aval < fval || cnt == 0)
10080                 aval = fval;
10081               break;
10082             case AGGR_MIN:
10083               if (aval > fval || cnt == 0)
10084                 aval = fval;
10085               break;
10086             case AGGR_CNT:
10087               aval = cnt + 1;
10088               break;
10089             case AGGR_SUM:
10090             case AGGR_AVG:
10091               aval += fval;
10092               break;
10093             }
10094           cnt_map->put (key, cnt + 1);
10095           fval_map->put (key, aval);
10096         }
10097     }
10098   kidx_map->sort (key_cmp);
10099
10100   // Finalize aggregation, prepare result
10101   for (long j = 0; j < funcs->size (); ++j)
10102     {
10103       Aggr_type aggr = aggrs->fetch (j);
10104       Vector<long long> *resj = res->fetch (j);
10105       DefaultMap<long long, long long> *
10106               fval_map = fval_maps->fetch (j);
10107       DefaultMap<long long, long> *
10108               cnt_map = cnt_maps->fetch (j);
10109       for (int kidx = 0; kidx < kidx_map->size (); ++kidx)
10110         {
10111           long long key = kidx_map->fetch (kidx);
10112           long long aval = fval_map->get (key);
10113           if (aggr == AGGR_AVG)
10114             {
10115               long cnt = cnt_map->get (key);
10116               if (cnt > 0)
10117                 aval = (aval + cnt / 2) / cnt;
10118             }
10119           resj->append (aval);
10120         }
10121     }
10122   delete flt_expr;
10123   funcs->destroy ();
10124   delete funcs;
10125   delete aggrs;
10126   delete arg_expr;
10127   delete kidx_map;
10128   fval_maps->destroy ();
10129   delete fval_maps;
10130   cnt_maps->destroy ();
10131   delete cnt_maps;
10132   return res;
10133 }
10134
10135 /* ********************************************************************* */
10136 /*  Routines for use by Collector GUI */
10137 /**
10138  * Returns signal value for provided name. Example of name: "SIGUSR1"
10139  * @param signal
10140  * @return value
10141  */
10142 int
10143 dbeGetSignalValue (char *signal)
10144 {
10145   int ret = -1;
10146   if (signal == NULL)
10147     return ret;
10148   if (strcmp (signal, "SIGUSR1") == 0)
10149     return (SIGUSR1);
10150   if (strcmp (signal, "SIGUSR2") == 0)
10151     return (SIGUSR2);
10152   if (strcmp (signal, "SIGPROF") == 0)
10153     return (SIGPROF);
10154   return ret;
10155 }
10156
10157 char *
10158 dbeSendSignal (pid_t p, int signum)
10159 {
10160   int ret = kill (p, signum);
10161   if (p == 0 || p == -1)
10162     return (dbe_sprintf (GTXT ("kill of process %d not supported\n"), p));
10163   if (ret == 0)
10164     return NULL;
10165   char *msg = dbe_sprintf (GTXT ("kill(%d, %d) failed: %s\n"), p, signum,
10166                            strerror (errno));
10167   return msg;
10168 }
10169
10170 char *
10171 dbeGetCollectorControlValue (char *control)
10172 {
10173   if (control == NULL)
10174     return NULL;
10175   if (col_ctr == NULL)
10176     col_ctr = new Coll_Ctrl (1);
10177   char *msg = col_ctr->get (control);
10178   return msg;
10179 }
10180
10181 char *
10182 dbeSetCollectorControlValue (char *control, char * value)
10183 {
10184   if (control == NULL)
10185     return NULL;
10186   if (col_ctr == NULL)
10187     col_ctr = new Coll_Ctrl (1);
10188   char *msg = col_ctr->set (control, value);
10189   return msg;
10190 }
10191
10192 char *
10193 dbeUnsetCollectorControlValue (char *control)
10194 {
10195   if (control == NULL)
10196     return NULL;
10197   if (col_ctr == NULL)
10198     col_ctr = new Coll_Ctrl (1);
10199   char *msg = col_ctr->unset (control);
10200   return msg;
10201 }
10202
10203 void
10204 dbeSetLocation (const char *fname, const char *location)
10205 {
10206   Vector<SourceFile*> *sources = dbeSession->get_sources ();
10207   for (long i = 0, sz = sources ? sources->size () : 0; i < sz; i++)
10208     {
10209       SourceFile *src = sources->get (i);
10210       DbeFile *df = src->dbeFile;
10211       if (df && (strcmp (fname, df->get_name ()) == 0))
10212         {
10213           df->find_file ((char *) location);
10214           break;
10215         }
10216     }
10217 }
10218
10219 void
10220 dbeSetLocations (Vector<const char *> *fnames, Vector<const char *> *locations)
10221 {
10222   if (fnames == NULL || locations == NULL
10223       || fnames->size () != locations->size ())
10224     return;
10225   for (long i = 0, sz = fnames->size (); i < sz; i++)
10226     dbeSetLocation (fnames->get (i), locations->get (i));
10227 }
10228
10229 Vector<void*> *
10230 dbeResolvedWith_setpath (const char *path)
10231 {
10232   Vector<char*> *names = new Vector<char*>();
10233   Vector<char*> *pathes = new Vector<char*>();
10234   Vector<long long> *ids = new Vector<long long>();
10235   Vector<SourceFile*> *sources = dbeSession->get_sources ();
10236   for (long i = 0, sz = sources ? sources->size () : 0; i < sz; i++)
10237     {
10238       SourceFile *src = sources->get (i);
10239       DbeFile *df = src->dbeFile;
10240       if (df == NULL || (df->filetype & DbeFile::F_FICTION) != 0)
10241         continue;
10242       char *fnm = df->get_name ();
10243       if ((df->filetype & (DbeFile::F_JAVACLASS | DbeFile::F_JAVA_SOURCE)) != 0)
10244         {
10245           char *jnm = dbe_sprintf (NTXT ("%s/%s"), path, fnm);
10246           if (df->check_access (jnm) == DbeFile::F_FILE)
10247             {
10248               names->append (dbe_strdup (fnm));
10249               pathes->append (jnm);
10250               ids->append (src->id);
10251               continue;
10252             }
10253           free (jnm);
10254         }
10255       char *nm = dbe_sprintf (NTXT ("%s/%s"), path, get_basename (fnm));
10256       if (df->check_access (nm) == DbeFile::F_FILE)
10257         {
10258           names->append (dbe_strdup (fnm));
10259           pathes->append (nm);
10260           ids->append (src->id);
10261           continue;
10262         }
10263       free (nm);
10264     }
10265   if (names->size () != 0)
10266     {
10267       Vector<void*> *data = new Vector<void*>(3);
10268       data->append (names);
10269       data->append (pathes);
10270       data->append (ids);
10271       return data;
10272     }
10273   return NULL;
10274 }
10275
10276 Vector<void*> *
10277 dbeResolvedWith_pathmap (const char *old_prefix, const char *new_prefix)
10278 {
10279   size_t len = strlen (old_prefix);
10280   Vector<char*> *names = new Vector<char*>();
10281   Vector<char*> *pathes = new Vector<char*>();
10282   Vector<long long> *ids = new Vector<long long>();
10283   Vector<SourceFile*> *sources = dbeSession->get_sources ();
10284   for (long i = 0, sz = sources ? sources->size () : 0; i < sz; i++)
10285     {
10286       SourceFile *src = sources->get (i);
10287       DbeFile *df = src->dbeFile;
10288       if (df == NULL || (df->filetype & DbeFile::F_FICTION) != 0)
10289         continue;
10290       char *fnm = df->get_name ();
10291       if (strncmp (old_prefix, fnm, len) == 0
10292           && (fnm[len] == '/' || fnm[len] == '\0'))
10293         {
10294           char *nm = dbe_sprintf (NTXT ("%s/%s"), new_prefix, fnm + len);
10295           if (df->check_access (nm) == DbeFile::F_FILE)
10296             {
10297               names->append (dbe_strdup (fnm));
10298               pathes->append (nm);
10299               ids->append (src->id);
10300               continue;
10301             }
10302           if ((df->filetype & DbeFile::F_JAVA_SOURCE) != 0)
10303             {
10304               free (nm);
10305               nm = dbe_sprintf (NTXT ("%s/%s"), new_prefix, fnm);
10306               if (df->check_access (nm) == DbeFile::F_FILE)
10307                 {
10308                   names->append (dbe_strdup (fnm));
10309                   pathes->append (nm);
10310                   ids->append (src->id);
10311                   continue;
10312                 }
10313             }
10314           free (nm);
10315         }
10316     }
10317   if (names->size () != 0)
10318     {
10319       Vector<void*> *data = new Vector<void*>(3);
10320       data->append (names);
10321       data->append (pathes);
10322       data->append (ids);
10323       return data;
10324     }
10325   return NULL;
10326 }
10327
10328 void
10329 dbe_archive (Vector<long long> *ids, Vector<const char *> *locations)
10330 {
10331   if (ids == NULL || locations == NULL || ids->size () != locations->size ())
10332     return;
10333   Experiment *exp = dbeSession->get_exp (0);
10334   if (exp == NULL)
10335     return;
10336   Vector<SourceFile*> *sources = dbeSession->get_sources ();
10337   for (long i1 = 0, sz1 = ids->size (); i1 < sz1; i1++)
10338     {
10339       long long id = ids->get (i1);
10340       for (long i = 0, sz = sources ? sources->size () : 0; i < sz; i++)
10341         {
10342           SourceFile *src = sources->get (i);
10343           if (src->id == id)
10344             {
10345               DbeFile *df = src->dbeFile;
10346               if (df)
10347                 {
10348                   char *fnm = df->find_file ((char *) locations->get (i1));
10349                   if (fnm)
10350                     {
10351                       char *nm = df->get_name ();
10352                       char *anm = exp->getNameInArchive (nm, false);
10353                       exp->copy_file (fnm, anm, true);
10354                       free (anm);
10355                     }
10356                 }
10357             }
10358         }
10359     }
10360 }
10361
10362 /* ************************************************************************ */
10363
10364 /* Routines to check connection between Remote Analyzer Client and er_print */
10365 char *
10366 dbeCheckConnection (char *str)
10367 {
10368   return dbe_strdup (str);
10369 }
This page took 0.610343 seconds and 4 git commands to generate.