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
67static Coll_Ctrl *col_ctr = NULL;
68
69template<> VecType Vector<int>::type ()
70{
71  return VEC_INTEGER;
72}
73
74template<> VecType Vector<unsigned>::type ()
75{
76  return VEC_INTEGER;
77}
78
79template<> VecType Vector<char>::type ()
80{
81  return VEC_CHAR;
82}
83
84template<> VecType Vector<bool>::type ()
85{
86  return VEC_BOOL;
87}
88
89template<> VecType Vector<double>::type ()
90{
91  return VEC_DOUBLE;
92}
93
94template<> VecType Vector<long long>::type ()
95{
96  return VEC_LLONG;
97}
98
99template<> VecType Vector<uint64_t>::type ()
100{
101  return VEC_LLONG;
102}
103
104template<> VecType Vector<void*>::type ()
105{
106  return VEC_VOIDARR;
107}
108
109template<> VecType Vector<char*>::type ()
110{
111  return VEC_STRING;
112}
113
114template<> VecType Vector<Vector<int>*>::type ()
115{
116  return VEC_INTARR;
117}
118
119template<> VecType Vector<Vector<char*>*>::type ()
120{
121  return VEC_STRINGARR;
122}
123
124template<> VecType Vector<Vector<long long>*>::type ()
125{
126  return VEC_LLONGARR;
127}
128
129// gcc won't instantiate Vector<unsigned>::type() without it
130Vector<unsigned> __dummy_unsigned_vector;
131
132#define CASE_S(x)   case x: return #x
133static const char *
134dsp_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
174enum
175{
176  COMPARE_BIT       = 1 << 8,
177  MTYPE_MASK        = (1 << 8) - 1,
178  GROUP_ID_SHIFT    = 16
179};
180
181static DbeView *
182getDbeView (int dbevindex)
183{
184  DbeView *dbev = dbeSession->getView (dbevindex);
185  if (dbev == NULL)
186    abort ();
187  return dbev;
188}
189
190
191Vector<char*> *
192dbeGetInitMessages ()
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
221Vector<char*> *
222dbeGetExpPreview (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
246char *
247dbeGetExpParams (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 */
266char *
267dbeGetFileAttributes (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 */
298char *
299dbeGetFiles (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 */
312char *
313dbeCreateDirectories (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 */
330char *
331dbeDeleteFile (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 */
351Vector<char*> *
352dbeReadFile (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 */
400int
401dbeWriteFile (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 */
431char *
432dbeGetRunningProcesses (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//
442char *
443dbeOpenExperimentList (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//
464char *
465dbeDropExperiment (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 */
481char *
482dbeReadRCFile (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
489char *
490dbeSetExperimentsGroups (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
511Vector<Vector<char*>*> *
512dbeGetExperimensGroups ()
513{
514  Vector<Vector<char*>*> *grops = dbeSession->getExperimensGroups ();
515  return grops;
516}
517
518Vector<int> *
519dbeGetFounderExpId (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
537Vector<int> *
538dbeGetUserExpId (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//
560Vector<int> *
561dbeGetExpGroupId (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
579Vector<char*> *
580dbeGetExpsProperty (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//
623Vector<char*> *
624dbeGetExpName (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//
646Vector<int> *
647dbeGetExpState (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//
676Vector<bool> *
677dbeGetExpEnable (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//
697bool
698dbeSetExpEnable (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//
720Vector<char*> *
721dbeGetExpInfo (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
758bool
759dbeGetViewModeEnable ()
760{
761  return dbeSession->has_ompavail () || dbeSession->has_java ();
762}
763
764bool
765dbeGetJavaEnable ()
766{
767  return dbeSession->has_java ();
768}
769
770int
771dbeUpdateNotes (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//
786Vector<char*> *
787dbeGetLoadObjectName (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//
809Vector<void*> *
810dbeGetTabList (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//
821Vector<void*> *
822dbeGetTabListInfo (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//
865Vector<bool> *
866dbeGetTabSelectionState (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
895void
896dbeSetTabSelectionState (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
912Vector<bool> *
913dbeGetMemTabSelectionState (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//
935void
936dbeSetMemTabSelectionState (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
945Vector<bool> *
946dbeGetIndxTabSelectionState (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
969void
970dbeSetIndxTabSelectionState (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//
981Vector<char*> *
982dbeGetSearchPath (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//
999void
1000dbeSetSearchPath (int /*dbevindex*/, Vector<char*> *path)
1001{
1002  dbeSession->set_search_path (path, true);
1003  return;
1004}
1005
1006//
1007// Get pathmaps
1008//
1009Vector<void*> *
1010dbeGetPathmaps (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
1032char *
1033dbeSetPathmaps (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
1054char *
1055dbeAddPathmap (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
1064char *
1065dbeGetMsg (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
1083int
1084dbeInitView (int id, int cloneid)
1085{
1086  return dbeSession->createView (id, cloneid);
1087}
1088
1089
1090// Delete a DbeView
1091void
1092dbeDeleteView (int dbevindex)
1093{
1094  dbeSession->dropView (dbevindex);
1095  return;
1096} // dbeDeleteView
1097
1098MetricList *
1099dbeGetMetricListV2 (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
1124static Vector<void*> *
1125dbeGetMetricList (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
1222Vector<void*> *
1223dbeGetRefMetricsV2 ()
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
1249Vector<void*> *
1250dbeGetCurMetricsV2 (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.
1259static int
1260convert_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
1283static Vector<void*> *
1284dbeGetMetricTreeNode (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
1446Vector<void*> *
1447dbeGetRefMetricTree (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
1465static Vector<void*> *
1466dbeGetTableDataV2Data (DbeView *dbev, Hist_data *data);
1467
1468static Vector<void*> *dbeGetTableDataOneColumn (Hist_data *data, int met_ind);
1469static Vector<void*> *
1470dbeGetTableDataOneColumn (DbeView *dbev, Vector<Hist_data::HistItem*> *data,
1471			  ValueTag vtype, int metricColumnNumber);
1472
1473static hrtime_t
1474dbeCalcGroupDuration (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
1506static hrtime_t
1507dbeCalcGroupGCDuration (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
1534Vector<void*> *
1535dbeGetRefMetricTreeValues (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
1902Vector<char*> *
1903dbeGetOverviewText (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//
1969void
1970dbeSetSort (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//
1984Vector<int> *
1985dbeGetAnoValue (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//
2006void
2007dbeSetAnoValue (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//
2031int
2032dbeGetNameFormat (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
2042bool
2043dbeGetSoName (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//
2056void
2057dbeSetNameFormat (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//
2069int
2070dbeGetViewMode (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
2080void
2081dbeSetViewMode (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//
2093Vector<void*> *
2094dbeGetTLValue (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//
2122void
2123dbeSetTLValue (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//
2140Vector<void*> *
2141dbeGetExpFounderDescendants ()
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//
2172Vector<void*> *
2173dbeGetExpSelection (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
2203int
2204dbeValidateFilterExpression (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
2215Vector<void*> *
2216dbeGetFilterKeywords (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//
2383Vector<void*> *
2384dbeGetFilters (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
2426char *
2427dbeSetFilterStr (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
2439char *
2440dbeGetFilterStr (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//
2453bool
2454dbeUpdateFilters (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
2489char *
2490dbeComposeFilterClause (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//
2597Vector<void *> *
2598dbeGetLoadObjectList (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
2665Vector<int> *
2666dbeGetLoadObjectState (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
2717void
2718dbeSetLoadObjectState (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
2760void
2761dbeSetLoadObjectDefaults (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
2770Vector<char*>*
2771dbeGetCPUVerMachineModel (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
2798void
2799dbeDetectLoadMachineModel (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
2827char *
2828dbeDefineMemObj (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
2834char *
2835dbeDeleteMemObj (char *name)
2836{
2837  return MemorySpace::mobj_delete (name);
2838}
2839
2840Vector<void*> *
2841dbeGetMemObjects (int /*dbevindex*/)
2842{
2843  Vector<void*> *res = MemorySpace::getMemObjects ();
2844  return res;
2845}
2846
2847// Managing machine model
2848char *
2849dbeLoadMachineModel (char *name)
2850{
2851  return dbeSession->load_mach_model (name);
2852}
2853
2854char *
2855dbeGetMachineModel ()
2856{
2857  return dbeSession->get_mach_model ();
2858}
2859
2860Vector <char *> *
2861dbeListMachineModels ()
2862{
2863  return dbeSession->list_mach_models ();
2864}
2865
2866// Managing Index Objects
2867char *
2868dbeDefineIndxObj (char *name, char *index_expr, char *sdesc, char *ldesc)
2869{
2870  return dbeSession->indxobj_define (name, NULL, index_expr, sdesc, ldesc);
2871}
2872
2873Vector<void*> *
2874dbeGetIndxObjDescriptions (int /*dbevindex*/)
2875{
2876  Vector<void*> *res = dbeSession->getIndxObjDescriptions ();
2877  return res;
2878}
2879
2880Vector<void*> *
2881dbeGetCustomIndxObjects (int /*dbevindex*/)
2882{
2883  Vector<void*> *res = dbeSession->getCustomIndxObjects ();
2884  return res;
2885}
2886
2887void
2888dbeSetSelObj (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
2978void
2979dbeSetSelObjV2 (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
2987Obj
2988dbeGetSelObj (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
3027Obj
3028dbeConvertSelObj (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
3078uint64_t
3079dbeGetSelObjV2 (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
3101Vector<uint64_t> *
3102dbeGetSelObjsIO (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
3121Vector<uint64_t> *
3122dbeGetSelObjIO (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
3178uint64_t
3179dbeGetSelObjHeapTimestamp (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
3221int
3222dbeGetSelObjHeapUserExpId (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//
3237int
3238dbeGetSelIndex (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//
3367char *
3368dbePrintData (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//
3593char *
3594dbeSetPrintLimit (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
3603int
3604dbeGetPrintLimit (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
3614char *
3615dbeSetPrintMode (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
3625int
3626dbeGetPrintMode (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
3635char *
3636dbeGetPrintModeString (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
3645char
3646dbeGetPrintDelim (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
3655static void
3656set_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//
3687int
3688dbeSetFuncData (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
4067Vector<void*>*
4068dbeGetTotals (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
4122Vector<void*>*
4123dbeGetHotMarks (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
4158Vector<void*>*
4159dbeGetHotMarksInc (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
4194Vector<void*>*
4195dbeGetSummaryHotMarks (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
4305Vector<uint64_t>*
4306dbeGetFuncId (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
4362Vector<void*>*
4363dbeGetFuncCallerInfo (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)
4394Vector<void*>*
4395dbeGetFuncCallerInfoById (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
4533Vector<void*>*
4534dbeGetFuncCalleeInfo (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//
4567Vector<void*>*
4568dbeGetFuncCalleeInfoById (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//
4746Vector<void*> *
4747dbeGetFuncListMini (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
4832Vector<void*> *
4833dbeGetFuncList (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
5086Vector<Obj> *
5087dbeGetComparableObjsV2 (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
5158Vector<void *> *
5159dbeGetFuncListV2 (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//
5371Vector<void*> *
5372dbeGetTableDataV2 (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
5475static Vector<void*> *
5476dbeGetTableDataV2Data (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
5514static Vector<void*> *
5515dbeGetTableDataOneColumn (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
5592static Vector<void*> *
5593dbeGetTableDataOneColumn (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
5673int
5674dbeGetCallTreeNumLevels (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
5685Vector<void*>*
5686dbeGetCallTreeLevel (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
5702Vector<void*>*
5703dbeGetCallTreeLevels (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
5724Vector<void*>*
5725dbeGetCallTreeLevelFuncs (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
5777Vector<void*> *
5778dbeGetCallTreeFuncs (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
5813Vector<void*>*
5814dbeGetCallTreeChildren (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
5840Vector<int> *
5841dbeGetGroupIds (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//
5854Vector<char*> *
5855dbeGetNames (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//
5924Vector<void*> *
5925dbeGetTotalMax (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
6005Vector<void*> *
6006dbeGetStatisOverviewList (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
6077Vector<void*> *
6078dbeGetStatisList (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//
6140static void
6141setSummary (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//
6307static void
6308setMemSummary (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//
6331static void
6332setIndxSummary (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//
6355static void
6356setIOActivitySummary (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//
6378static void
6379setHeapActivitySummary (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//
6403static void
6404setDataSummary (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
6523Vector<void*> *
6524dbeGetSummaryV2 (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
6686Vector<void*> *
6687dbeGetSummary (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
7063char *
7064dbeGetExpName (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
7084Vector<Vector<char*>*> *
7085dbeGetHwcSets (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
7101static Vector<void*> *
7102dbeGetHwcs (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
7154Vector<void *> *
7155dbeGetHwcsAll (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
7163Vector<char*> *
7164dbeGetHwcHelp (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
7180Vector<char*> *
7181dbeGetHwcAttrList (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
7195int
7196dbeGetHwcMaxConcurrent (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
7205Vector<char*> *
7206dbeGetIfreqData (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//
7236Vector<void*> *
7237dbeGetLeakListInfo (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//
7317Obj
7318dbeGetObject (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
7328char *
7329dbeGetName (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
7348Vector<char*> *
7349dbeGetExpVerboseName (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
7361long long
7362dbeGetStartTime (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
7369long long
7370dbeGetRelativeStartTime (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
7377long long
7378dbeGetEndTime (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
7389int
7390dbeGetClock (int /*dbevindex*/, int exp_id)
7391{
7392  return dbeSession->get_clock (exp_id);
7393}
7394
7395long long
7396dbeGetWallStartSec (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
7403char *
7404dbeGetHostname (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
7411static DataView *
7412getTimelinePackets (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
7428static long
7429getIdxByVals (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
7441static bool
7442isValidIdx (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
7460static bool
7461hasInvisbleTLEvents (Experiment *exp, VMode view_mode)
7462{
7463  if (exp->has_java && view_mode == VMODE_USER)
7464    return true;
7465  return false;
7466}
7467
7468static bool
7469isVisibleTLEvent (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
7480static long
7481getTLVisibleIdxByStepping (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
7507static long
7508getTLVisibleIdxByVals (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
7528static char*
7529getThreadRootFuncName (int, int, int, int, VMode)
7530{
7531  return NULL; // until we figure out what we want to show... YXXX
7532}
7533
7534Vector<void*> *
7535dbeGetEntityProps (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
7578Vector<void*> *
7579dbeGetEntities (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()
7652Vector<void*> *
7653dbeGetEntitiesV2 (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
7667static Vector<void*> *
7668getTLDetailValues (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
7752Vector<void*> *
7753dbeGetTLDetails (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
7773Vector<Obj> *
7774dbeGetStackFunctions (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
7794Vector<void*> *
7795dbeGetStacksFunctions (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
7808Vector<Obj> *
7809dbeGetStackPCs (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
7841Vector<char*> *
7842dbeGetStackNames (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
7871Vector<void*> *
7872dbeGetSamples (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
7925Vector<void*> *
7926dbeGetGCEvents (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
7965Vector<Vector<char*>*>*
7966dbeGetIOStatistics (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
8293Vector<Vector<char*>*>*
8294dbeGetHeapStatistics (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
8595Vector<char*> *
8596dbeGetFuncNames (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
8605Vector<char*> *
8606dbeGetObjNamesV2 (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
8615char *
8616dbeGetFuncName (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
8628Vector<uint64_t> *
8629dbeGetFuncIds (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
8638uint64_t
8639dbeGetFuncId (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
8650char *
8651dbeGetObjNameV2 (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
8663char *
8664dbeGetDataspaceTypeDesc (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
8679Vector<void*> *
8680dbeGetDataDescriptorsV2 (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
8711Vector<void*> *
8712dbeGetDataPropertiesV2 (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
8780Vector<void *> *
8781dbeGetExperimentTimeInfo (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
8820Vector<void *> *
8821dbeGetExperimentDataDescriptors (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
8855static Vector<void *> *
8856dbeGetTLDataRepVals (VMode view_mode, hrtime_t start_ts, hrtime_t delta,
8857		     int numDeltas, DataView*packets,
8858		     Vector<long> *representativeEvents, bool showDuration);
8859
8860static bool
8861dbeHasTLData (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
8889Vector<bool> *
8890dbeHasTLData (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
8930Vector<void *> *
8931dbeGetTLData (
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
9526dbeGetTLData_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
9541static Vector<void *> *
9542dbeGetTLDataRepVals (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.
9623Vector<long long> *
9624dbeGetTLEventCenterTime (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
9662long long
9663dbeGetTLEventIdxNearTime (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
9717enum 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
9728static Aggr_type
9729getAggrFunc (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
9749static long long
9750computeAggrVal (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
9795Vector<long long> *
9796dbeGetAggregatedValue (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
9916Vector<char*> *
9917dbeGetLineInfo (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
9934int
9935dbeSetAlias (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
9941Vector<char*> *
9942dbeGetAlias (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
9956static int
9957key_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
9964Vector<Vector<long long>*> *
9965dbeGetXYPlotData (
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 */
10142int
10143dbeGetSignalValue (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
10157char *
10158dbeSendSignal (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
10170char *
10171dbeGetCollectorControlValue (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
10181char *
10182dbeSetCollectorControlValue (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
10192char *
10193dbeUnsetCollectorControlValue (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
10203void
10204dbeSetLocation (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
10219void
10220dbeSetLocations (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
10229Vector<void*> *
10230dbeResolvedWith_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
10276Vector<void*> *
10277dbeResolvedWith_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
10328void
10329dbe_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 */
10365char *
10366dbeCheckConnection (char *str)
10367{
10368  return dbe_strdup (str);
10369}
10370