|  | /* Copyright (C) 2021-2025 Free Software Foundation, Inc. | 
|  | Contributed by Oracle. | 
|  |  | 
|  | This file is part of GNU Binutils. | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 3, or (at your option) | 
|  | any later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program; if not, write to the Free Software | 
|  | Foundation, 51 Franklin Street - Fifth Floor, Boston, | 
|  | MA 02110-1301, USA.  */ | 
|  |  | 
|  | #include "config.h" | 
|  | #include <errno.h> | 
|  | #include <sys/types.h> // open, chmod | 
|  | #include <signal.h> | 
|  | #include <fcntl.h>     // open | 
|  | #include <strings.h> | 
|  | #include <unistd.h> | 
|  |  | 
|  | #include "util.h" | 
|  | #include "Histable.h" | 
|  | #include "DbeSession.h" | 
|  | #include "DbeView.h" | 
|  | #include "BaseMetric.h" | 
|  | #include "CallStack.h" | 
|  | #include "collctrl.h" | 
|  | #include "Command.h" | 
|  | #include "Dbe.h" | 
|  | #include "DbeApplication.h" | 
|  | #include "DefaultMap.h" | 
|  | #include "LoadObject.h" | 
|  | #include "Experiment.h" | 
|  | #include "IndexObject.h" | 
|  | #include "IOActivity.h" | 
|  | #include "PreviewExp.h" | 
|  | #include "Function.h" | 
|  | #include "Hist_data.h" | 
|  | #include "MetricList.h" | 
|  | #include "Module.h" | 
|  | #include "DataSpace.h" | 
|  | #include "MemorySpace.h" | 
|  | #include "DataObject.h" | 
|  | #include "MemObject.h" | 
|  | #include "Filter.h" | 
|  | #include "FilterSet.h" | 
|  | #include "FilterExp.h" | 
|  | #include "Sample.h" | 
|  | #include "Print.h" | 
|  | #include "StringBuilder.h" | 
|  | #include "dbe_types.h" | 
|  | #include "ExpGroup.h" | 
|  | #include "vec.h" | 
|  | #include "UserLabel.h" | 
|  | #include "DbeFile.h" | 
|  | #include "PathTree.h" | 
|  |  | 
|  | // Data structures for managing the collector control info for Collection GUI | 
|  | static Coll_Ctrl *col_ctr = NULL; | 
|  |  | 
|  | template<> VecType Vector<int>::type () | 
|  | { | 
|  | return VEC_INTEGER; | 
|  | } | 
|  |  | 
|  | template<> VecType Vector<unsigned>::type () | 
|  | { | 
|  | return VEC_INTEGER; | 
|  | } | 
|  |  | 
|  | template<> VecType Vector<char>::type () | 
|  | { | 
|  | return VEC_CHAR; | 
|  | } | 
|  |  | 
|  | template<> VecType Vector<bool>::type () | 
|  | { | 
|  | return VEC_BOOL; | 
|  | } | 
|  |  | 
|  | template<> VecType Vector<double>::type () | 
|  | { | 
|  | return VEC_DOUBLE; | 
|  | } | 
|  |  | 
|  | template<> VecType Vector<long long>::type () | 
|  | { | 
|  | return VEC_LLONG; | 
|  | } | 
|  |  | 
|  | template<> VecType Vector<uint64_t>::type () | 
|  | { | 
|  | return VEC_LLONG; | 
|  | } | 
|  |  | 
|  | template<> VecType Vector<void*>::type () | 
|  | { | 
|  | return VEC_VOIDARR; | 
|  | } | 
|  |  | 
|  | template<> VecType Vector<char*>::type () | 
|  | { | 
|  | return VEC_STRING; | 
|  | } | 
|  |  | 
|  | template<> VecType Vector<Vector<int>*>::type () | 
|  | { | 
|  | return VEC_INTARR; | 
|  | } | 
|  |  | 
|  | template<> VecType Vector<Vector<char*>*>::type () | 
|  | { | 
|  | return VEC_STRINGARR; | 
|  | } | 
|  |  | 
|  | template<> VecType Vector<Vector<long long>*>::type () | 
|  | { | 
|  | return VEC_LLONGARR; | 
|  | } | 
|  |  | 
|  | // gcc won't instantiate Vector<unsigned>::type() without it | 
|  | Vector<unsigned> __dummy_unsigned_vector; | 
|  |  | 
|  | #define CASE_S(x)   case x: return #x | 
|  | static const char * | 
|  | dsp_type_to_string (int t) | 
|  | { | 
|  | switch (t) | 
|  | { | 
|  | CASE_S (DSP_FUNCTION); | 
|  | CASE_S (DSP_LINE); | 
|  | CASE_S (DSP_PC); | 
|  | CASE_S (DSP_SOURCE); | 
|  | CASE_S (DSP_DISASM); | 
|  | CASE_S (DSP_SELF); | 
|  | CASE_S (DSP_CALLER); | 
|  | CASE_S (DSP_CALLEE); | 
|  | CASE_S (DSP_CALLTREE); | 
|  | CASE_S (DSP_TIMELINE); | 
|  | CASE_S (DSP_STATIS); | 
|  | CASE_S (DSP_EXP); | 
|  | CASE_S (DSP_LEAKLIST); | 
|  | CASE_S (DSP_MEMOBJ); | 
|  | CASE_S (DSP_DATAOBJ); | 
|  | CASE_S (DSP_DLAYOUT); | 
|  | CASE_S (DSP_SRC_FILE); | 
|  | CASE_S (DSP_IFREQ); | 
|  | CASE_S (DSP_RACES); | 
|  | CASE_S (DSP_INDXOBJ); | 
|  | CASE_S (DSP_DUALSOURCE); | 
|  | CASE_S (DSP_SOURCE_DISASM); | 
|  | CASE_S (DSP_DEADLOCKS); | 
|  | CASE_S (DSP_SOURCE_V2); | 
|  | CASE_S (DSP_DISASM_V2); | 
|  | CASE_S (DSP_IOACTIVITY); | 
|  | CASE_S (DSP_OVERVIEW); | 
|  | CASE_S (DSP_IOCALLSTACK); | 
|  | CASE_S (DSP_HEAPCALLSTACK); | 
|  | CASE_S (DSP_SAMPLE); | 
|  | default: | 
|  | break; | 
|  | } | 
|  | return NTXT ("ERROR"); | 
|  | } | 
|  |  | 
|  | enum | 
|  | { | 
|  | COMPARE_BIT       = 1 << 8, | 
|  | MTYPE_MASK        = (1 << 8) - 1, | 
|  | GROUP_ID_SHIFT    = 16 | 
|  | }; | 
|  |  | 
|  | static DbeView * | 
|  | getDbeView (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | return dbev; | 
|  | } | 
|  |  | 
|  |  | 
|  | Vector<char*> * | 
|  | dbeGetInitMessages () | 
|  | { | 
|  | // If any comments from the .rc files, send them to the GUI | 
|  | Emsg *msg = theDbeApplication->fetch_comments (); | 
|  | int size = 0; | 
|  | while (msg != NULL) | 
|  | { | 
|  | size++; | 
|  | msg = msg->next; | 
|  | } | 
|  |  | 
|  | // Initialize Java String array | 
|  | Vector<char*> *list = new Vector<char*>(size); | 
|  | msg = theDbeApplication->fetch_comments (); | 
|  | size = 0; | 
|  | int i = 0; | 
|  | while (msg != NULL) | 
|  | { | 
|  | char *str = msg->get_msg (); | 
|  | list->store (i, dbe_strdup (str)); | 
|  | i++; | 
|  | msg = msg->next; | 
|  | } | 
|  |  | 
|  | // now delete the comments | 
|  | theDbeApplication->delete_comments (); | 
|  | return list; | 
|  | } | 
|  |  | 
|  | Vector<char*> * | 
|  | dbeGetExpPreview (int /*dbevindex*/, char *exp_name) | 
|  | { | 
|  | PreviewExp *preview = new PreviewExp (); | 
|  | preview->experiment_open (exp_name); | 
|  | preview->open_epilogue (); | 
|  |  | 
|  | // Initialize Java String array | 
|  | Vector<char*> *info = preview->preview_info (); | 
|  | int size = info->size (); | 
|  | Vector<char*> *list = new Vector<char*>(size); | 
|  |  | 
|  | // Get experiment names | 
|  | for (int i = 0; i < size; i++) | 
|  | { | 
|  | char *str = info->fetch (i); | 
|  | if (str == NULL) | 
|  | str = GTXT ("N/A"); | 
|  | list->store (i, dbe_strdup (str)); | 
|  | } | 
|  | delete info; | 
|  | delete preview; | 
|  | return list; | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeGetExpParams (int /*dbevindex*/, char *exp_name) | 
|  | { | 
|  | PreviewExp *preview = new PreviewExp (); | 
|  | preview->experiment_open (exp_name); | 
|  |  | 
|  | // Initialize Java String array | 
|  | char *arg_list = dbe_strdup (preview->getArgList ()); | 
|  | delete preview; | 
|  | return arg_list; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Gets File Attributes according to the specified format | 
|  | * Supported formats: | 
|  | * "/bin/ls -dl " - see 'man ls' for details | 
|  | * @param filename | 
|  | * @param format | 
|  | * @return char * attributes | 
|  | */ | 
|  | char * | 
|  | dbeGetFileAttributes (const char *filename, const char *format) | 
|  | { | 
|  | if (format != NULL) | 
|  | { | 
|  | if (!strcmp (format, NTXT ("/bin/ls -dl "))) | 
|  | { | 
|  | // A kind of "/bin/ls -dl " simulation | 
|  | dbe_stat_t sbuf; | 
|  | sbuf.st_mode = 0; | 
|  | dbe_stat (filename, &sbuf); | 
|  | if (S_IREAD & sbuf.st_mode) | 
|  | { // Readable | 
|  | if (S_ISDIR (sbuf.st_mode) != 0) | 
|  | return dbe_sprintf (NTXT ("%s %s\n"), NTXT ("drwxrwxr-x"), filename); | 
|  | else if (S_ISREG (sbuf.st_mode) != 0) | 
|  | return dbe_sprintf (NTXT ("%s %s\n"), NTXT ("-rwxrwxr-x"), filename); | 
|  | } | 
|  | } | 
|  | } | 
|  | return dbe_strdup (NTXT ("")); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Gets list of files for specified directory according to the specified format | 
|  | * Supported formats: | 
|  | * "/bin/ls -a" - see 'man ls' for details | 
|  | * "/bin/ls -aF" - see 'man ls' for details | 
|  | * @param dirname | 
|  | * @param format | 
|  | * @return char * files | 
|  | */ | 
|  | char * | 
|  | dbeGetFiles (const char *dirname, const char *format) | 
|  | { | 
|  | if (format != NULL) | 
|  | return dbe_read_dir (dirname, format); | 
|  | return dbe_strdup (NTXT ("")); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Creates the directory named by this full path name, including any | 
|  | * necessary but nonexistent parent directories. | 
|  | * @param dirname | 
|  | * @return result | 
|  | */ | 
|  | char * | 
|  | dbeCreateDirectories (const char *dirname) | 
|  | { | 
|  | if (dirname != NULL) | 
|  | { | 
|  | char *res = dbe_create_directories (dirname); | 
|  | if (res != NULL) | 
|  | return res; | 
|  | } | 
|  | return dbe_strdup (NTXT ("")); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Deletes the file or the directory named by the specified path name. | 
|  | * If this pathname denotes a directory, then the directory must be empty in order to be deleted. | 
|  | * @param const char *pathname | 
|  | * @return int result | 
|  | */ | 
|  | char * | 
|  | dbeDeleteFile (const char *pathname) | 
|  | { | 
|  | // return unlink(pathname); | 
|  | if (pathname != NULL) | 
|  | { | 
|  | char *res = dbe_delete_file (pathname); | 
|  | if (res != NULL) | 
|  | return res; | 
|  | } | 
|  | return dbe_strdup (NTXT ("")); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Reads the file named by the specified path name. | 
|  | * Temporary limitation: file should be "text only" and its size should be less than the 1 MB limit. | 
|  | * If the operation was successful, the contents is in the first element, and second element is NULL. | 
|  | * If the operation failed, then first element is NULL, and second element contains the error message. | 
|  | * @param const char *pathname | 
|  | * @return Vector<char*> *result | 
|  | */ | 
|  | Vector<char*> * | 
|  | dbeReadFile (const char *pathname) | 
|  | { | 
|  | Vector<char*> *result = new Vector<char*>(2); | 
|  | int limit = 1024 * 1024; // Temporary limit: 1 MB | 
|  | char * contents = (char *) xmalloc (limit); | 
|  | StringBuilder sb; | 
|  | if (NULL == contents) | 
|  | { | 
|  | sb.sprintf (NTXT ("\nError: Cannot allocate %d bytes\n"), limit); | 
|  | result->store (0, NULL); | 
|  | result->store (1, sb.toString ()); // failure | 
|  | return result; | 
|  | } | 
|  | int fd = open (pathname, O_RDONLY); | 
|  | if (fd >= 0) | 
|  | { | 
|  | int64_t bytes = read_from_file (fd, contents, limit); | 
|  | close (fd); | 
|  | if (bytes >= limit) | 
|  | { | 
|  | sb.sprintf (NTXT ("\nError: file size is greater than the limit (%d bytes)\n"), limit); | 
|  | result->store (0, NULL); | 
|  | result->store (1, sb.toString ()); // failure | 
|  | } | 
|  | else | 
|  | { | 
|  | contents[bytes] = '\0'; // add string terminator | 
|  | result->store (0, contents); | 
|  | result->store (1, NULL); // success | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | sb.sprintf (NTXT ("\nError: Cannot open file %s\n"), pathname); | 
|  | result->store (0, NULL); | 
|  | result->store (1, sb.toString ()); // failure | 
|  | free (contents); | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Writes the file named by the specified path name. | 
|  | * Temporary limitation: file should be "text only" and its size should be less than the 1 MB limit. | 
|  | * If the operation failed, then -1 is returned. | 
|  | * @param const char *pathname | 
|  | * @return int result  (written bytes) | 
|  | */ | 
|  | int | 
|  | dbeWriteFile (const char *pathname, const char *contents) | 
|  | { | 
|  | int result = -1; // error | 
|  | size_t len = 0; | 
|  | if (NULL != contents) | 
|  | len = strlen (contents); | 
|  | size_t limit = 1024 * 1024; // Temporary limit: 1 MB | 
|  | if (len > limit) return result; | 
|  | unlink (pathname); | 
|  | mode_t mode = S_IRUSR | S_IWUSR; | 
|  | int fd = open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode); | 
|  | if (fd >= 0) | 
|  | {  // replace file contents | 
|  | chmod (pathname, /*S_IRUSR || S_IWUSR*/ 0600); // rw for owner only | 
|  | ssize_t bytes = 0; | 
|  | if (len > 0) | 
|  | bytes = write (fd, contents, len); | 
|  | close (fd); | 
|  | result = (int) bytes; | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Gets list of running processes according to the specified format | 
|  | * Supported formats: | 
|  | * "/bin/ps -ef" - see 'man ps' for details | 
|  | * @param format | 
|  | * @return char * processes | 
|  | */ | 
|  | char * | 
|  | dbeGetRunningProcesses (const char *format) | 
|  | { | 
|  | if (format != NULL) | 
|  | return dbe_get_processes (format); | 
|  | return dbe_strdup (NTXT ("")); | 
|  | } | 
|  |  | 
|  | // | 
|  | // Open experiment | 
|  | // | 
|  | char * | 
|  | dbeOpenExperimentList (int /* dbevindex */, Vector<Vector<char*>*> *groups, | 
|  | bool sessionRestart) | 
|  | { | 
|  | if (sessionRestart) | 
|  | dbeSession->reset (); | 
|  | char *errstr; | 
|  | // Open experiments | 
|  | try | 
|  | { | 
|  | errstr = dbeSession->setExperimentsGroups (groups); | 
|  | } | 
|  | catch (ExperimentLoadCancelException *) | 
|  | { | 
|  | errstr = dbe_strdup (NTXT ("Experiment Load Cancelled")); | 
|  | } | 
|  | return errstr; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Drop experiments | 
|  | // | 
|  | char * | 
|  | dbeDropExperiment (int /* dbevindex */, Vector<int> *drop_index) | 
|  | { | 
|  | for (int i = drop_index->size () - 1; i >= 0; i--) | 
|  | { | 
|  | char *ret = dbeSession->drop_experiment (drop_index->fetch (i)); | 
|  | if (ret != NULL) | 
|  | return ret; | 
|  | } | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Read .er.rc file from the specified location | 
|  | * @param path | 
|  | * @return | 
|  | */ | 
|  | char * | 
|  | dbeReadRCFile (int dbevindex, char* path) | 
|  | { | 
|  | DbeView *dbev = getDbeView (dbevindex); | 
|  | char *err_msg = dbev->get_settings ()->read_rc (path); | 
|  | return err_msg; | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeSetExperimentsGroups (Vector<Vector<char*>*> *groups) | 
|  | { | 
|  | int cmp_mode = dbeSession->get_settings ()->get_compare_mode (); | 
|  | if (groups->size () < 2) | 
|  | cmp_mode = CMP_DISABLE; | 
|  | else if (cmp_mode == CMP_DISABLE) | 
|  | cmp_mode = CMP_ENABLE; | 
|  | for (int i = 0;; i++) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (i); | 
|  | if (dbev == NULL) | 
|  | break; | 
|  | dbev->get_settings ()->set_compare_mode (cmp_mode); | 
|  | } | 
|  | char *err_msg = dbeSession->setExperimentsGroups (groups); | 
|  |  | 
|  | // automatically load machine model if applicable | 
|  | dbeDetectLoadMachineModel (0); | 
|  | return err_msg; | 
|  | } | 
|  |  | 
|  | Vector<Vector<char*>*> * | 
|  | dbeGetExperimensGroups () | 
|  | { | 
|  | Vector<Vector<char*>*> *grops = dbeSession->getExperimensGroups (); | 
|  | return grops; | 
|  | } | 
|  |  | 
|  | Vector<int> * | 
|  | dbeGetFounderExpId (Vector<int> *expIds) | 
|  | { | 
|  | Vector<int> *ret = new Vector<int>(expIds->size ()); | 
|  | for (int i = 0; i < expIds->size (); i++) | 
|  | { | 
|  | int expId = expIds->fetch (i); | 
|  | Experiment *exp = dbeSession->get_exp (expId); | 
|  | if (exp != NULL) | 
|  | { | 
|  | int founderExpId = exp->getBaseFounder ()->getExpIdx (); | 
|  | ret->store (i, founderExpId); | 
|  | } | 
|  | else | 
|  | ret->store (i, -1); | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | Vector<int> * | 
|  | dbeGetUserExpId (Vector<int> *expIds) | 
|  | { | 
|  | // returns "User Visible" ids used for EXPID filters and timeline processes | 
|  | Vector<int> *ret = new Vector<int>(expIds->size ()); | 
|  | for (int i = 0; i < expIds->size (); i++) | 
|  | { | 
|  | int expId = expIds->fetch (i); | 
|  | Experiment *exp = dbeSession->get_exp (expId); | 
|  | if (exp != NULL) | 
|  | { | 
|  | int userExpId = exp->getUserExpId (); | 
|  | ret->store (i, userExpId); | 
|  | } | 
|  | else | 
|  | ret->store (i, -1); | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get experiment groupid | 
|  | // | 
|  | Vector<int> * | 
|  | dbeGetExpGroupId (Vector<int> *expIds) | 
|  | { | 
|  | Vector<int> *ret = new Vector<int>(expIds->size ()); | 
|  | for (int i = 0; i < expIds->size (); i++) | 
|  | { | 
|  | int expId = expIds->fetch (i); | 
|  | Experiment *exp = dbeSession->get_exp (expId); | 
|  | if (exp != NULL) | 
|  | { | 
|  | int gId = exp->groupId; | 
|  | ret->store (i, gId); | 
|  | } | 
|  | else | 
|  | ret->store (i, -1); | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | Vector<char*> * | 
|  | dbeGetExpsProperty (const char *prop_name) | 
|  | { | 
|  | long nexps = dbeSession->nexps (); | 
|  | if (prop_name == NULL || nexps == 0) | 
|  | return NULL; | 
|  | Vector<char*> *list = new Vector<char*>(nexps); | 
|  | StringBuilder sb; | 
|  | int empty = 1; | 
|  | int prop = 99; | 
|  | if (strcasecmp (prop_name, NTXT ("ERRORS")) == 0) | 
|  | prop = 1; | 
|  | else if (strcasecmp (prop_name, NTXT ("WARNINGS")) == 0) | 
|  | prop = 2; | 
|  | if (prop < 3) | 
|  | { | 
|  | for (long i = 0; i < nexps; i++) | 
|  | { | 
|  | Experiment *exp = dbeSession->get_exp (i); | 
|  | char *nm = exp->get_expt_name (); | 
|  | sb.setLength (0); | 
|  | for (Emsg *emsg = (prop == 1) ? exp->fetch_errors () : exp->fetch_warnings (); | 
|  | emsg; emsg = emsg->next) | 
|  | sb.appendf (NTXT ("%s: %s\n"), STR (nm), STR (emsg->get_msg ())); | 
|  | char *s = NULL; | 
|  | if (sb.length () > 0) | 
|  | { | 
|  | s = sb.toString (); | 
|  | empty = 0; | 
|  | } | 
|  | list->append (s); | 
|  | } | 
|  | } | 
|  | if (empty) | 
|  | { | 
|  | delete list; | 
|  | list = NULL; | 
|  | } | 
|  | return list; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get experiment names | 
|  | // | 
|  | Vector<char*> * | 
|  | dbeGetExpName (int /*dbevindex*/) | 
|  | { | 
|  | int size = dbeSession->nexps (); | 
|  | if (size == 0) | 
|  | return NULL; | 
|  | // Initialize Java String array | 
|  | Vector<char*> *list = new Vector<char*>(size); | 
|  |  | 
|  | // Get experiment names | 
|  | for (int i = 0; i < size; i++) | 
|  | { | 
|  | Experiment *texp = dbeSession->get_exp (i); | 
|  | char *buf = dbe_sprintf (NTXT ("%s [%s]"), texp->get_expt_name (), | 
|  | texp->utargname != NULL ? texp->utargname : GTXT ("(unknown)")); | 
|  | list->store (i, buf); | 
|  | } | 
|  | return list; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get experiment state | 
|  | // | 
|  | Vector<int> * | 
|  | dbeGetExpState (int /* dbevindex */) | 
|  | { | 
|  | int size = dbeSession->nexps (); | 
|  | if (size == 0) | 
|  | return NULL; | 
|  | // Initialize Java array | 
|  | Vector<int> *state = new Vector<int>(size); | 
|  |  | 
|  | // Get experiment state | 
|  | for (int i = 0; i < size; i++) | 
|  | { | 
|  | Experiment *exp = dbeSession->get_exp (i); | 
|  | int set = EXP_SUCCESS; | 
|  | if (exp->get_status () == Experiment::FAILURE) | 
|  | set |= EXP_FAILURE; | 
|  | if (exp->get_status () == Experiment::INCOMPLETE) | 
|  | set |= EXP_INCOMPLETE; | 
|  | if (exp->broken) | 
|  | set |= EXP_BROKEN; | 
|  | if (exp->obsolete) | 
|  | set |= EXP_OBSOLETE; | 
|  | state->store (i, set); | 
|  | } | 
|  | return state; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get enabled experiment indices | 
|  | // | 
|  | Vector<bool> * | 
|  | dbeGetExpEnable (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = getDbeView (dbevindex); | 
|  | int size = dbeSession->nexps (); | 
|  | if (dbev == NULL || size == 0) | 
|  | return NULL; | 
|  |  | 
|  | // Get enabled experiment | 
|  | Vector<bool> *enable = new Vector<bool>(size); | 
|  | for (int i = 0; i < size; i++) | 
|  | { | 
|  | bool val = dbev->get_exp_enable (i) && !dbeSession->get_exp (i)->broken; | 
|  | enable->store (i, val); | 
|  | } | 
|  | return enable; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get enabled experiment indices | 
|  | // | 
|  | bool | 
|  | dbeSetExpEnable (int dbevindex, Vector<bool> *enable) | 
|  | { | 
|  | DbeView *dbev = getDbeView (dbevindex); | 
|  | bool ret = false; | 
|  | int size = dbeSession->nexps (); | 
|  | if (dbev == NULL || size == 0) | 
|  | return false; | 
|  |  | 
|  | // set enable, as per input vector | 
|  | for (int i = 0; i < size; i++) | 
|  | if (!dbeSession->get_exp (i)->broken | 
|  | && dbev->get_exp_enable (i) != enable->fetch (i)) | 
|  | { | 
|  | dbev->set_exp_enable (i, enable->fetch (i)); | 
|  | ret = true; | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get experiment info | 
|  | // | 
|  | Vector<char*> * | 
|  | dbeGetExpInfo (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | int size = dbeSession->nexps (); | 
|  | if (size == 0) | 
|  | return NULL; | 
|  |  | 
|  | // Initialize Java String array | 
|  | Vector<char*> *list = new Vector<char*>(size * 2 + 1); | 
|  |  | 
|  | // Get experiment names | 
|  | Vector<LoadObject*> *text_segments = dbeSession->get_text_segments (); | 
|  | char *msg = pr_load_objects (text_segments, NTXT ("")); | 
|  | delete text_segments; | 
|  | list->store (0, msg); | 
|  | int k = 1; | 
|  | for (int i = 0; i < size; i++) | 
|  | { | 
|  | Experiment *exp = dbeSession->get_exp (i); | 
|  | char *msg0 = pr_mesgs (exp->fetch_notes (), NTXT (""), NTXT ("")); | 
|  | char *msg1 = pr_mesgs (exp->fetch_errors (), GTXT ("No errors\n"), NTXT ("")); | 
|  | char *msg2 = pr_mesgs (exp->fetch_warnings (), GTXT ("No warnings\n"), NTXT ("")); | 
|  | char *msg3 = pr_mesgs (exp->fetch_comments (), NTXT (""), NTXT ("")); | 
|  | char *msg4 = pr_mesgs (exp->fetch_pprocq (), NTXT (""), NTXT ("")); | 
|  | msg = dbe_sprintf (NTXT ("%s%s%s%s"), msg1, msg2, msg3, msg4); | 
|  | list->store (k++, msg0); | 
|  | list->store (k++, msg); | 
|  | free (msg1); | 
|  | free (msg2); | 
|  | free (msg3); | 
|  | free (msg4); | 
|  | } | 
|  | return list; | 
|  | } | 
|  |  | 
|  | bool | 
|  | dbeGetViewModeEnable () | 
|  | { | 
|  | return dbeSession->has_ompavail () || dbeSession->has_java (); | 
|  | } | 
|  |  | 
|  | bool | 
|  | dbeGetJavaEnable () | 
|  | { | 
|  | return dbeSession->has_java (); | 
|  | } | 
|  |  | 
|  | int | 
|  | dbeUpdateNotes (int dbevindex, int exp_id, int type, char* text, bool handle_file) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | int size = dbeSession->nexps (); | 
|  | if (size == 0) | 
|  | return -1; | 
|  | Experiment *exp = dbeSession->get_exp (exp_id); | 
|  | return (type == 0) ? exp->save_notes (text, handle_file) : exp->delete_notes (handle_file); | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get load object names | 
|  | // | 
|  | Vector<char*> * | 
|  | dbeGetLoadObjectName (int /* dbevindex */) | 
|  | { | 
|  | Vector<LoadObject*> *lobjs = dbeSession->get_text_segments (); | 
|  | int size = lobjs->size (); | 
|  |  | 
|  | // Initialize Java String array | 
|  | Vector<char*> *list = new Vector<char*>(size); | 
|  |  | 
|  | // Get load object names | 
|  | LoadObject *lo; | 
|  | int index; | 
|  | Vec_loop (LoadObject*, lobjs, index, lo) | 
|  | { | 
|  | list->store (index, dbe_strdup (lo->get_name ())); | 
|  | } | 
|  | delete lobjs; | 
|  | return list; | 
|  | } | 
|  |  | 
|  | // XXX Will use later when order has to be passed too, | 
|  | // Get complete List of tabs | 
|  | // | 
|  | Vector<void*> * | 
|  | dbeGetTabList (int /* dbevindex */) | 
|  | { | 
|  | //DbeView *dbev = getDbeView (dbevindex); | 
|  | //Vector<void*> *tabs = dbeSession->get_TabList(); | 
|  | //return tabs; | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Returns list of available tabs | 
|  | // | 
|  | Vector<void*> * | 
|  | dbeGetTabListInfo (int dbevindex) | 
|  | { | 
|  | int index; | 
|  | DispTab *dsptab; | 
|  | DbeView *dbev = getDbeView (dbevindex); | 
|  |  | 
|  | // make sure the tabs are initialized properly | 
|  | dbev->get_settings ()->proc_tabs (theDbeApplication->rdtMode); | 
|  | Vector<DispTab*> *tabs = dbev->get_TabList (); | 
|  |  | 
|  | // Get number of available tabs | 
|  | int size = 0; | 
|  | Vec_loop (DispTab*, tabs, index, dsptab) | 
|  | { | 
|  | if (!dsptab->available) | 
|  | continue; | 
|  | size++; | 
|  | } | 
|  | Vector<void*> *data = new Vector<void*>(2); | 
|  | Vector<int> *typelist = new Vector<int>(size); | 
|  | Vector<char*> *cmdlist = new Vector<char*>(size); | 
|  | Vector<int> *ordlist = new Vector<int>(size); | 
|  |  | 
|  | // Build list of avaliable tabs | 
|  | int i = 0; | 
|  |  | 
|  | Vec_loop (DispTab*, tabs, index, dsptab) | 
|  | { | 
|  | if (!dsptab->available) | 
|  | continue; | 
|  | typelist->store (i, dsptab->type); | 
|  | cmdlist->store (i, dbe_strdup (Command::get_cmd_str (dsptab->cmdtoken))); | 
|  | ordlist->store (i, dsptab->order); | 
|  | i++; | 
|  | } | 
|  | data->store (0, typelist); | 
|  | data->store (1, cmdlist); | 
|  | data->store (2, ordlist); | 
|  | return data; | 
|  | } | 
|  |  | 
|  | // Return visibility state for all available tabs | 
|  | // | 
|  | Vector<bool> * | 
|  | dbeGetTabSelectionState (int dbevindex) | 
|  | { | 
|  | int index; | 
|  | DispTab *dsptab; | 
|  | DbeView *dbev = getDbeView (dbevindex); | 
|  | Vector<DispTab*> *tabs = dbev->get_TabList (); | 
|  |  | 
|  | // Get number of available tabs | 
|  | int size = 0; | 
|  | Vec_loop (DispTab*, tabs, index, dsptab) | 
|  | { | 
|  | if (!dsptab->available) | 
|  | continue; | 
|  | size++; | 
|  | } | 
|  | Vector<bool> *states = new Vector<bool>(size); | 
|  |  | 
|  | // Get visibility bit for all available tabs | 
|  | int i = 0; | 
|  | Vec_loop (DispTab*, tabs, index, dsptab) | 
|  | { | 
|  | if (!dsptab->available) | 
|  | continue; | 
|  | states->store (i++, dsptab->visible); | 
|  | } | 
|  | return states; | 
|  | } | 
|  |  | 
|  | // Set visibility bit for a tab | 
|  | void | 
|  | dbeSetTabSelectionState (int dbevindex, Vector<bool> *selected) | 
|  | { | 
|  | int index; | 
|  | DispTab *dsptab; | 
|  | DbeView *dbev = getDbeView (dbevindex); | 
|  | Vector<DispTab*> *tabs = dbev->get_TabList (); | 
|  | int i = 0; | 
|  | Vec_loop (DispTab*, tabs, index, dsptab) | 
|  | { | 
|  | if (!dsptab->available) | 
|  | continue; | 
|  | dsptab->visible = selected->fetch (i++); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Return visibility state for all available MemObj tabs | 
|  | Vector<bool> * | 
|  | dbeGetMemTabSelectionState (int dbevindex) | 
|  | { | 
|  | int index; | 
|  | bool dsptab; | 
|  | DbeView *dbev = getDbeView (dbevindex); | 
|  | Vector<bool> *memtabs = dbev->get_MemTabState (); | 
|  |  | 
|  | // set the output vector | 
|  | int size = memtabs->size (); | 
|  | Vector<bool> *states = new Vector<bool>(size); | 
|  |  | 
|  | // Get visibility bit for all available tabs | 
|  | int i = 0; | 
|  | Vec_loop (bool, memtabs, index, dsptab) | 
|  | { | 
|  | states->store (i++, dsptab); | 
|  | } | 
|  | return states; | 
|  | } | 
|  |  | 
|  | // Set visibility bit for a memory tab | 
|  | // | 
|  | void | 
|  | dbeSetMemTabSelectionState (int dbevindex, Vector<bool> *selected) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | dbev->set_MemTabState (selected); | 
|  | } | 
|  |  | 
|  | // Return visibility state for all available index tabs | 
|  | Vector<bool> * | 
|  | dbeGetIndxTabSelectionState (int dbevindex) | 
|  | { | 
|  | int index; | 
|  | bool dsptab; | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Vector<bool> *indxtabs = dbev->get_IndxTabState (); | 
|  |  | 
|  | // set the output vector | 
|  | int size = indxtabs->size (); | 
|  | Vector<bool> *states = new Vector<bool>(size); | 
|  |  | 
|  | // Get visibility bit for all available tabs | 
|  | int i = 0; | 
|  | Vec_loop (bool, indxtabs, index, dsptab) | 
|  | { | 
|  | states->store (i++, dsptab); | 
|  | } | 
|  | return states; | 
|  | } | 
|  |  | 
|  | // Set visibility bit for a index tab | 
|  | void | 
|  | dbeSetIndxTabSelectionState (int dbevindex, Vector<bool> *selected) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | dbev->set_IndxTabState (selected); | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get search path | 
|  | // | 
|  | Vector<char*> * | 
|  | dbeGetSearchPath (int /*dbevindex*/) | 
|  | { | 
|  | Vector<char*> *path = dbeSession->get_search_path (); | 
|  | int size = path->size (); | 
|  | Vector<char*> *list = new Vector<char*>(size); | 
|  | int index; | 
|  | char *name; | 
|  | Vec_loop (char*, path, index, name) | 
|  | { | 
|  | list->store (index, dbe_strdup (name)); | 
|  | } | 
|  | return list; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Set search path | 
|  | // | 
|  | void | 
|  | dbeSetSearchPath (int /*dbevindex*/, Vector<char*> *path) | 
|  | { | 
|  | dbeSession->set_search_path (path, true); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get pathmaps | 
|  | // | 
|  | Vector<void*> * | 
|  | dbeGetPathmaps (int /*dbevindex*/) | 
|  | { | 
|  | int index; | 
|  | pathmap_t *pthmap; | 
|  | Vector<pathmap_t*> *path = dbeSession->get_pathmaps (); | 
|  | int size = path->size (); | 
|  | Vector<void*> *data = new Vector<void*>(2); | 
|  | Vector<char*> *oldlist = new Vector<char*>(size); | 
|  | Vector<char*> *newlist = new Vector<char*>(size); | 
|  |  | 
|  | int i = 0; | 
|  | Vec_loop (pathmap_t*, path, index, pthmap) | 
|  | { | 
|  | oldlist->store (i, dbe_strdup (pthmap->old_prefix)); | 
|  | newlist->store (i, dbe_strdup (pthmap->new_prefix)); | 
|  | i++; | 
|  | } | 
|  | data->store (0, oldlist); | 
|  | data->store (1, newlist); | 
|  | return data; | 
|  | } // dbeGetPathmaps | 
|  |  | 
|  | char * | 
|  | dbeSetPathmaps (Vector<char*> *from, Vector<char*> *to) | 
|  | { | 
|  | if (from == NULL || to == NULL || from->size () != to->size ()) | 
|  | return dbe_strdup ("dbeSetPathmaps: size of 'from' does not match for size of 'to'\n"); | 
|  | Vector<pathmap_t*> *newPath = new Vector<pathmap_t*>(from->size ()); | 
|  | for (int i = 0, sz = from->size (); i < sz; i++) | 
|  | { | 
|  | char *err = Settings::add_pathmap (newPath, from->get (i), to->get (i)); | 
|  | if (err) | 
|  | { | 
|  | newPath->destroy (); | 
|  | delete newPath; | 
|  | return err; | 
|  | } | 
|  | } | 
|  | dbeSession->set_pathmaps (newPath); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Add pathmap | 
|  | char * | 
|  | dbeAddPathmap (int /* dbevindex */, char *from, char *to) | 
|  | { | 
|  | Vector<pathmap_t*> *pmp = dbeSession->get_pathmaps (); | 
|  | char *err = Settings::add_pathmap (pmp, from, to); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get error/warning string of data | 
|  | char * | 
|  | dbeGetMsg (int dbevindex, int type) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | char *msgstr = NULL; | 
|  | if (type == ERROR_MSG) | 
|  | msgstr = dbev->get_error_msg (); | 
|  | else if (type == WARNING_MSG) | 
|  | msgstr = dbev->get_warning_msg (); | 
|  | else if (type == PSTAT_MSG) | 
|  | msgstr = dbev->get_processor_msg (PSTAT_MSG); | 
|  | else if (type == PWARN_MSG) | 
|  | msgstr = dbev->get_processor_msg (PWARN_MSG); | 
|  | return msgstr ? dbe_strdup (msgstr) : NULL; | 
|  | } | 
|  |  | 
|  | // Create a DbeView, given new index, and index of view to clone | 
|  | int | 
|  | dbeInitView (int id, int cloneid) | 
|  | { | 
|  | return dbeSession->createView (id, cloneid); | 
|  | } | 
|  |  | 
|  |  | 
|  | // Delete a DbeView | 
|  | void | 
|  | dbeDeleteView (int dbevindex) | 
|  | { | 
|  | dbeSession->dropView (dbevindex); | 
|  | return; | 
|  | } // dbeDeleteView | 
|  |  | 
|  | MetricList * | 
|  | dbeGetMetricListV2 (int dbevindex, MetricType mtype, | 
|  | Vector<int> *type, Vector<int> *subtype, Vector<bool> *sort, | 
|  | Vector<int> *vis, Vector<char*> *cmd, | 
|  | Vector<char*> *expr_spec, Vector<char*> *legends) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | MetricList *mlist = new MetricList (mtype); | 
|  | for (int i = 0, msize = type->size (); i < msize; i++) | 
|  | { | 
|  | BaseMetric *bm = dbev->register_metric_expr ((BaseMetric::Type) type->fetch (i), | 
|  | cmd->fetch (i), | 
|  | expr_spec->fetch (i)); | 
|  | Metric *m = new Metric (bm, (Metric::SubType) subtype->fetch (i)); | 
|  | m->set_raw_visbits (vis->fetch (i)); | 
|  | if (m->legend == NULL) | 
|  | m->legend = dbe_strdup (legends->fetch (i)); | 
|  | mlist->append (m); | 
|  | if (sort->fetch (i)) | 
|  | { | 
|  | mlist->set_sort_ref_index (i); | 
|  | } | 
|  | } | 
|  | return mlist; | 
|  | } | 
|  |  | 
|  | static Vector<void*> * | 
|  | dbeGetMetricList (MetricList *mlist) | 
|  | { | 
|  | int clock_val = dbeSession->get_clock (-1); | 
|  | Vector<Metric*> *items = mlist->get_items (); | 
|  | int size = items->size (); | 
|  |  | 
|  | Vector<int> *type = new Vector<int>(size); | 
|  | Vector<int> *subtype = new Vector<int>(size); | 
|  | Vector<int> *clock = new Vector<int>(size); | 
|  | Vector<int> *flavors = new Vector<int>(size); | 
|  | Vector<int> *vis = new Vector<int>(size); | 
|  | Vector<bool> *sorted = new Vector<bool>(size); | 
|  | Vector<int> *value_styles = new Vector<int>(size); | 
|  | Vector<char*> *aux = new Vector<char*>(size); | 
|  | Vector<char*> *name = new Vector<char*>(size); | 
|  | Vector<char*> *abbr = new Vector<char*>(size); | 
|  | Vector<char*> *comd = new Vector<char*>(size); | 
|  | Vector<char*> *unit = new Vector<char*>(size); | 
|  | Vector<char*> *user_name = new Vector<char*>(size); | 
|  | Vector<char*> *expr_spec = new Vector<char*>(size); | 
|  | Vector<char*> *legend = new Vector<char*>(size); | 
|  | Vector<int> *valtype = new Vector<int>(size); | 
|  | Vector<char*> *data_type_name = new Vector<char*>(size); | 
|  | Vector<char*> *data_type_uname = new Vector<char*>(size); | 
|  | Vector<char*> *short_desc = new Vector<char*>(size); | 
|  |  | 
|  | int sort_index = mlist->get_sort_ref_index (); | 
|  | // Fill metric elements | 
|  | for (int i = 0; i < size; i++) | 
|  | { | 
|  | Metric *m = items->fetch (i); | 
|  | type->append (m->get_type ()); | 
|  | subtype->append (m->get_subtype ()); | 
|  | flavors->append (m->get_flavors ()); | 
|  | abbr->append (dbe_strdup (m->get_abbr ())); | 
|  | char *s = m->get_abbr_unit (); | 
|  | if ((m->get_visbits () & VAL_RATIO) != 0) | 
|  | s = NULL; | 
|  | unit->append (dbe_strdup (s ? s : NTXT (""))); | 
|  | value_styles->append (m->get_value_styles ()); | 
|  | vis->append (m->get_visbits ()); | 
|  | sorted->append (i == sort_index); | 
|  | clock->append (m->get_type () == Metric::HWCNTR ? clock_val | 
|  | : m->get_clock_unit ()); | 
|  | aux->append (dbe_strdup (m->get_aux ())); | 
|  | name->append (dbe_strdup (m->get_name ())); | 
|  | comd->append (dbe_strdup (m->get_cmd ())); | 
|  | user_name->append (dbe_strdup (m->get_username ())); | 
|  | expr_spec->append (dbe_strdup (m->get_expr_spec ())); | 
|  | legend->append (dbe_strdup (m->legend)); | 
|  | valtype->append (m->get_vtype2 ()); | 
|  |  | 
|  | char* _data_type_name = NULL; | 
|  | char* _data_type_uname = NULL; | 
|  | int data_type = m->get_packet_type (); | 
|  | if (data_type >= 0 && data_type < DATA_LAST) | 
|  | { | 
|  | _data_type_name = dbe_strdup (get_prof_data_type_name (data_type)); | 
|  | _data_type_uname = dbe_strdup (get_prof_data_type_uname (data_type)); | 
|  | } | 
|  | data_type_name->append (_data_type_name); | 
|  | data_type_uname->append (_data_type_uname); | 
|  |  | 
|  | char* _short_desc = NULL; | 
|  | if (m->get_type () == Metric::HWCNTR) | 
|  | { | 
|  | Hwcentry * hwctr = m->get_hw_ctr (); | 
|  | if (hwctr) | 
|  | _short_desc = dbe_strdup (hwctr->short_desc); | 
|  | } | 
|  | short_desc->append (_short_desc); | 
|  | } | 
|  |  | 
|  | // Set Java array | 
|  | Vector<void*> *data = new Vector<void*>(16); | 
|  | data->append (type); | 
|  | data->append (subtype); | 
|  | data->append (clock); | 
|  | data->append (flavors); | 
|  | data->append (value_styles); | 
|  | data->append (user_name); | 
|  | data->append (expr_spec); | 
|  | data->append (aux); | 
|  | data->append (name); | 
|  | data->append (abbr); | 
|  | data->append (comd); | 
|  | data->append (unit); | 
|  | data->append (vis); | 
|  | data->append (sorted); | 
|  | data->append (legend); | 
|  | data->append (valtype); | 
|  | data->append (data_type_name); | 
|  | data->append (data_type_uname); | 
|  | data->append (short_desc); | 
|  | return data; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetRefMetricsV2 () | 
|  | { | 
|  | MetricList *mlist = new MetricList (MET_NORMAL); | 
|  | Vector<BaseMetric*> *base_metrics = dbeSession->get_base_reg_metrics (); | 
|  | for (long i = 0, sz = base_metrics->size (); i < sz; i++) | 
|  | { | 
|  | BaseMetric *bm = base_metrics->fetch (i); | 
|  | Metric *m; | 
|  | if (bm->get_flavors () & Metric::EXCLUSIVE) | 
|  | { | 
|  | m = new Metric (bm, Metric::EXCLUSIVE); | 
|  | m->enable_all_visbits (); | 
|  | mlist->append (m); | 
|  | } | 
|  | else if (bm->get_flavors () & BaseMetric::STATIC) | 
|  | { | 
|  | m = new Metric (bm, BaseMetric::STATIC); | 
|  | m->enable_all_visbits (); | 
|  | mlist->append (m); | 
|  | } | 
|  | } | 
|  | Vector<void*> *data = dbeGetMetricList (mlist); | 
|  | delete mlist; | 
|  | return data; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetCurMetricsV2 (int dbevindex, MetricType mtype) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | MetricList *mlist = dbev->get_metric_list (mtype); | 
|  | Vector<void*> *data = dbeGetMetricList (mlist); | 
|  | return data; | 
|  | } | 
|  |  | 
|  | // YXXX we should refactor Metrics/BaseMetrics so that it no longer uses VAL_VALUE to enable time. | 
|  | static int | 
|  | convert_visbits_to_gui_checkbox_bits (BaseMetric *bm, const int visbits) | 
|  | { | 
|  | // The purpose of this function is to handle the following case: | 
|  | //    When bm->get_value_styles() supports VAL_TIMEVAL but not VAL_VALUE | 
|  | //        Metric and BaseMetric use (visbits&VAL_VALUE) to enable time. | 
|  | //    However, the Overview expects the VAL_TIMEVAL bit to enable time. | 
|  | // Inputs: visbits as returned by BaseMetric->get_default_visbits(); | 
|  | // Returns: valuebits, as used for checks in GUI checkboxes | 
|  | int valuebits = visbits; | 
|  | const int value_styles = bm->get_value_styles (); | 
|  | if ((value_styles & VAL_TIMEVAL) && // supports time | 
|  | !(value_styles & VAL_VALUE)) | 
|  | { // but not value | 
|  | unsigned mask = ~(VAL_VALUE | VAL_TIMEVAL); | 
|  | valuebits = (unsigned) valuebits & mask; // clear bits | 
|  | if (visbits & VAL_VALUE) | 
|  | valuebits |= VAL_TIMEVAL; // set VAL_TIMEVAL | 
|  | if (visbits & VAL_TIMEVAL) | 
|  | valuebits |= VAL_TIMEVAL; // weird, this should never happen. | 
|  | } | 
|  | return valuebits; | 
|  | } | 
|  |  | 
|  | static Vector<void*> * | 
|  | dbeGetMetricTreeNode (BaseMetricTreeNode* curr, MetricList *mlist, | 
|  | bool include_unregistered, bool has_clock_profiling_data) | 
|  | { | 
|  | Vector<void*> *data = new Vector<void*>(2); | 
|  |  | 
|  | // ----- fields | 
|  | Vector<void*> *fields = new Vector<void*>(); | 
|  | Vector<char*> *name = new Vector<char*>(1); | 
|  | Vector<char*> *username = new Vector<char*>(1); | 
|  | Vector<char*> *description = new Vector<char*>(1); | 
|  | Vector<int> * flavors = new Vector<int>(1); | 
|  | Vector<int> * vtype = new Vector<int>(1); | 
|  | Vector<int> * vstyles_capable = new Vector<int>(1); | 
|  |  | 
|  | // Specifies which default styles should be enabled when a metric is enabled. | 
|  | // Also, specifies if metric should start enabled | 
|  | Vector<int> *vstyles_e_defaults = new Vector<int>(1); | 
|  | Vector<int> *vstyles_i_defaults = new Vector<int>(1); | 
|  | Vector<bool> *registered = new Vector<bool>(1); | 
|  | Vector<bool> *aggregation = new Vector<bool>(1); | 
|  | Vector<bool> *has_value = new Vector<bool>(1); | 
|  | Vector<char*> *unit = new Vector<char*>(1); | 
|  | Vector<char*> *unit_uname = new Vector<char*>(1); | 
|  |  | 
|  | char *_name = NULL; | 
|  | char *_username = NULL; | 
|  | char *_description = dbe_strdup (curr->get_description ()); | 
|  |  | 
|  | // BaseMetric fields | 
|  | int _flavors = 0; // SubType bitmask: (e.g. EXCLUSIVE) | 
|  | int _vtype = 0; // ValueTag: e.g. VT_INT, VT_FLOAT, ... | 
|  | int _vstyles_capable = 0; // ValueType bitmask, e.g. VAL_TIMEVAL | 
|  | int _vstyles_e_default_values = 0; // default visibility settings, exclusive/static | 
|  | int _vstyles_i_derault_values = 0; // default visibility settings, inclusive | 
|  | bool _registered = curr->is_registered () | 
|  | || curr->get_num_registered_descendents () > 0; | 
|  | bool _aggregation = curr->is_composite_metric () | 
|  | && curr->get_num_registered_descendents () > 0; | 
|  | bool _has_value = false; //not used yet; for nodes that don't have metrics | 
|  | char *_unit = NULL; | 
|  | char *_unit_uname = NULL; | 
|  |  | 
|  | BaseMetric *bm = curr->get_BaseMetric (); | 
|  | if (bm) | 
|  | { | 
|  | _name = dbe_strdup (bm->get_cmd ()); | 
|  | _username = dbe_strdup (bm->get_username ()); | 
|  | if (!include_unregistered && !curr->is_registered ()) | 
|  | abort (); | 
|  | _flavors = bm->get_flavors (); | 
|  | _vtype = bm->get_vtype (); | 
|  | _vstyles_capable = bm->get_value_styles (); | 
|  | int e_visbits = bm->get_default_visbits (BaseMetric::EXCLUSIVE); | 
|  | int i_visbits = bm->get_default_visbits (BaseMetric::INCLUSIVE); | 
|  | _vstyles_e_default_values = convert_visbits_to_gui_checkbox_bits (bm, e_visbits); | 
|  | _vstyles_i_derault_values = convert_visbits_to_gui_checkbox_bits (bm, i_visbits); | 
|  | // not all metrics shown in er_print cmd line should be selected in the GUI at startup: | 
|  | if (has_clock_profiling_data && bm->get_hw_ctr ()) | 
|  | { | 
|  | bool hide = true; // by default, hide HWCs | 
|  | if (dbe_strcmp (bm->get_hw_ctr ()->name, NTXT ("c_stalls")) == 0 || | 
|  | dbe_strcmp (bm->get_hw_ctr ()->name, NTXT ("K_c_stalls")) == 0) | 
|  | { | 
|  | bool is_time = (bm->get_value_styles () & VAL_TIMEVAL) != 0; | 
|  | if (is_time) | 
|  | // By default, show time variant of c_stalls | 
|  | hide = false; | 
|  | } | 
|  | if (hide) | 
|  | { | 
|  | _vstyles_e_default_values |= VAL_HIDE_ALL; | 
|  | _vstyles_i_derault_values |= VAL_HIDE_ALL; | 
|  | } | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | // not a base metric | 
|  | _name = dbe_strdup (curr->get_name ()); | 
|  | _username = dbe_strdup (curr->get_user_name ()); | 
|  | if (curr->get_unit ()) | 
|  | { // represents a value | 
|  | _has_value = true; | 
|  | _unit = dbe_strdup (curr->get_unit ()); | 
|  | _unit_uname = dbe_strdup (curr->get_unit_uname ()); | 
|  | } | 
|  | } | 
|  | name->append (_name); // unique id string (dmetrics cmd) | 
|  | username->append (_username); // user-visible name | 
|  | description->append (_description); | 
|  | flavors->append (_flavors); // SubType bitmask: (e.g. EXCLUSIVE) | 
|  | vtype->append (_vtype); // ValueTag: e.g. VT_INT, VT_FLOAT, ... | 
|  | vstyles_capable->append (_vstyles_capable); // ValueType bitmask, e.g. VAL_TIMEVAL | 
|  | vstyles_e_defaults->append (_vstyles_e_default_values); | 
|  | vstyles_i_defaults->append (_vstyles_i_derault_values); | 
|  | registered->append (_registered); // is a "live" metric | 
|  | aggregation->append (_aggregation); // value derived from children nodes | 
|  | has_value->append (_has_value); // value generated from other source | 
|  | unit->append (_unit); // See BaseMetric.h, e.g. UNIT_SECONDS | 
|  | unit_uname->append (_unit_uname); //See BaseMetric.h, | 
|  |  | 
|  | fields->append (name); | 
|  | fields->append (username); | 
|  | fields->append (description); | 
|  | fields->append (flavors); | 
|  | fields->append (vtype); | 
|  | fields->append (vstyles_capable); | 
|  | fields->append (vstyles_e_defaults); | 
|  | fields->append (vstyles_i_defaults); | 
|  | fields->append (registered); | 
|  | fields->append (aggregation); | 
|  | fields->append (has_value); | 
|  | fields->append (unit); | 
|  | fields->append (unit_uname); | 
|  | data->append (fields); | 
|  |  | 
|  | // ----- children | 
|  | Vector<BaseMetricTreeNode*> *children = curr->get_children (); | 
|  | int num_children = children->size (); | 
|  | Vector<void*> *children_list = new Vector<void*>(num_children); | 
|  | BaseMetricTreeNode *child_node; | 
|  | int index; | 
|  |  | 
|  | Vec_loop (BaseMetricTreeNode*, children, index, child_node) | 
|  | { | 
|  | if (include_unregistered /* fetch everything */ | 
|  | || child_node->is_registered () | 
|  | || child_node->get_num_registered_descendents () > 0) | 
|  | { | 
|  | //Special case for metrics that aren't registered | 
|  | // but have registered children | 
|  | // Linux example: Total Time is unregistered, CPU Time is registered | 
|  | if (!include_unregistered && /* not fetching everything */ | 
|  | !child_node->is_registered () && | 
|  | (child_node->get_BaseMetric () != NULL || | 
|  | child_node->is_composite_metric ())) | 
|  | { | 
|  | Vector<BaseMetricTreeNode*> *registered_descendents = | 
|  | new Vector<BaseMetricTreeNode*>(); | 
|  | child_node->get_nearest_registered_descendents (registered_descendents); | 
|  | int idx2; | 
|  | BaseMetricTreeNode*desc_node; | 
|  | Vec_loop (BaseMetricTreeNode*, registered_descendents, idx2, desc_node) | 
|  | { | 
|  | Vector<void*> *desc_data; | 
|  | desc_data = dbeGetMetricTreeNode (desc_node, mlist, | 
|  | include_unregistered, has_clock_profiling_data); | 
|  | children_list->append (desc_data); | 
|  | } | 
|  | delete registered_descendents; | 
|  | continue; | 
|  | } | 
|  | Vector<void*> *child_data; | 
|  | child_data = dbeGetMetricTreeNode (child_node, mlist, | 
|  | include_unregistered, has_clock_profiling_data); | 
|  | children_list->append (child_data); | 
|  | } | 
|  | } | 
|  | data->append (children_list); | 
|  | return data; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetRefMetricTree (int dbevindex, bool include_unregistered) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | MetricList *mlist = dbev->get_metric_list (MET_NORMAL); | 
|  | bool has_clock_profiling_data = false; | 
|  | for (long i = 0, sz = mlist->get_items ()->size (); i < sz; i++) | 
|  | { | 
|  | Metric *m = mlist->get_items ()->fetch (i); | 
|  | if (m->get_packet_type () == DATA_CLOCK) | 
|  | { | 
|  | has_clock_profiling_data = true; | 
|  | break; | 
|  | } | 
|  | } | 
|  | BaseMetricTreeNode *curr = dbeSession->get_reg_metrics_tree (); | 
|  | return dbeGetMetricTreeNode (curr, mlist, include_unregistered, has_clock_profiling_data); | 
|  | } | 
|  |  | 
|  | static Vector<void*> * | 
|  | dbeGetTableDataV2Data (DbeView *dbev, Hist_data *data); | 
|  |  | 
|  | static Vector<void*> *dbeGetTableDataOneColumn (Hist_data *data, int met_ind); | 
|  | static Vector<void*> * | 
|  | dbeGetTableDataOneColumn (DbeView *dbev, Vector<Hist_data::HistItem*> *data, | 
|  | ValueTag vtype, int metricColumnNumber); | 
|  |  | 
|  | static hrtime_t | 
|  | dbeCalcGroupDuration (int grInd) | 
|  | { | 
|  | int thisGroupSize = 1; | 
|  | hrtime_t max_time = 0; | 
|  | Experiment *exp; | 
|  | if (dbeSession->expGroups->size () > 0) | 
|  | { | 
|  | ExpGroup *grp = dbeSession->expGroups->fetch (grInd); | 
|  | thisGroupSize = grp->exps->size (); | 
|  | for (int ii = 0; ii < thisGroupSize; ii++) | 
|  | { | 
|  | exp = grp->exps->fetch (ii); | 
|  | Vector<DataDescriptor*> *ddscr = exp->getDataDescriptors (); | 
|  | delete ddscr;// getDataDescriptors() forces reading of experiment data | 
|  | if (exp != NULL) | 
|  | { | 
|  | hrtime_t tot_time = exp->getLastEvent () - exp->getStartTime () | 
|  | + exp->getRelativeStartTime (); | 
|  | if (max_time < tot_time) | 
|  | max_time = tot_time; | 
|  | } | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | exp = dbeSession->get_exp (0); | 
|  | if (exp != NULL) | 
|  | max_time = exp->getLastEvent () - exp->getStartTime (); | 
|  | } | 
|  | return max_time; //nanoseconds | 
|  | } | 
|  |  | 
|  | static hrtime_t | 
|  | dbeCalcGroupGCDuration (int grInd) | 
|  | { | 
|  | int thisGroupSize = 1; | 
|  | hrtime_t tot_time = 0; | 
|  | Experiment *exp; | 
|  | if (dbeSession->expGroups->size () > 0) | 
|  | { | 
|  | ExpGroup *grp = dbeSession->expGroups->fetch (grInd); | 
|  | thisGroupSize = grp->exps->size (); | 
|  | for (int ii = 0; ii < thisGroupSize; ii++) | 
|  | { | 
|  | exp = grp->exps->fetch (ii); | 
|  | Vector<DataDescriptor*> *ddscr = exp->getDataDescriptors (); | 
|  | delete ddscr; // getDataDescriptors() forces reading of experiment data | 
|  | if (exp != NULL) | 
|  | tot_time += exp->getGCDuration (); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | exp = dbeSession->get_exp (0); | 
|  | if (exp != NULL) | 
|  | tot_time = exp->getGCDuration (); | 
|  | } | 
|  | return tot_time; //nanoseconds | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetRefMetricTreeValues (int dbevindex, Vector<char *> *metric_cmds, | 
|  | Vector<char *> *non_metric_cmds) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | // valueTable will have N "columns" of values, where N is the number of | 
|  | //   requested metrics and non-metrics. | 
|  | // Each column will be a vector with M "rows", where M is the number of | 
|  | //   compare groups. | 
|  | // highlightTable mirrors the structure of valueTable.  Each cell indicates | 
|  | //   if the corresponding valueTable cell is "hot" (interesting) | 
|  | int numMetrics = metric_cmds->size (); | 
|  | int numNonMetrics = non_metric_cmds->size (); | 
|  | int totalColumns = numMetrics + numNonMetrics; // Columns | 
|  | Vector<void*> *valueTable = new Vector<void*>(totalColumns); | 
|  | Vector<void*> *highlightTable = new Vector<void*>(totalColumns); | 
|  |  | 
|  | // the return value consists of the two tables discussed above. | 
|  | Vector<void*> *rc = new Vector<void*>(2); | 
|  | rc->append (valueTable); | 
|  | rc->append (highlightTable); | 
|  | if (dbeSession->nexps () == 0) | 
|  | { // no experiments are loaded | 
|  | for (int jj = 0; jj < totalColumns; jj++) | 
|  | { | 
|  | Vector<void *> *columnData = new Vector<void *>(); | 
|  | valueTable->append (columnData); | 
|  | highlightTable->append (columnData); | 
|  | } | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | int ngroups = dbeSession->expGroups->size (); // Rows (one per compare group) | 
|  | if (ngroups == 0 || !dbev->comparingExperiments ()) | 
|  | ngroups = 1; | 
|  |  | 
|  | Vector<double> *groupTotalTime = new Vector<double>(ngroups); | 
|  | Vector<double> *groupCpuTime = new Vector<double>(ngroups); | 
|  | // initialize highlight table | 
|  | for (int ii = 0; ii < totalColumns; ii++) | 
|  | { // metrics | 
|  | Vector<bool> *columnData = new Vector<bool>(ngroups); | 
|  | highlightTable->append (columnData); | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | columnData->store (grInd, false); // non-highlight | 
|  | } | 
|  |  | 
|  | if (numMetrics > 0) | 
|  | { | 
|  | MetricList *bmlist; | 
|  | // set bmlist to list of requested base metrics | 
|  | BaseMetricTreeNode *root = dbeSession->get_reg_metrics_tree (); | 
|  | int index; | 
|  | char *mcmd; | 
|  | Vector<BaseMetric*> *base_metrics = new Vector<BaseMetric*>(); | 
|  | Vec_loop (char *, metric_cmds, index, mcmd) | 
|  | { | 
|  | BaseMetricTreeNode *bmt_node = root->find (mcmd); | 
|  | if (!bmt_node) | 
|  | abort (); //YXXX weird | 
|  | BaseMetric * baseNetric = bmt_node->get_BaseMetric (); | 
|  | if (!baseNetric) | 
|  | abort (); | 
|  | base_metrics->append (baseNetric); | 
|  | } | 
|  |  | 
|  | // MET_INDX will create MetricList of Exclusive metrics | 
|  | bmlist = new MetricList (base_metrics, MET_SRCDIS); | 
|  |  | 
|  | // Use the Function List to fetch <Total> values | 
|  | // A temporary table, v_totals, stores <total> by group | 
|  | Vector<Hist_data::HistItem *> *v_totals = new Vector<Hist_data::HistItem *>(ngroups); | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | { | 
|  | MetricList *mlist; | 
|  | if (ngroups > 1) | 
|  | mlist = dbev->get_compare_mlist (bmlist, grInd); | 
|  | else | 
|  | mlist = bmlist; | 
|  | if (mlist->size () != numMetrics) | 
|  | abort (); | 
|  |  | 
|  | Hist_data *data; | 
|  | data = dbev->get_hist_data (mlist, Histable::FUNCTION, 0, | 
|  | Hist_data::ALL); | 
|  | Hist_data::HistItem * totals = data->get_totals (); | 
|  | v_totals->append (totals); | 
|  | } | 
|  |  | 
|  | // store the Hist_data totals in valueTable | 
|  | { | 
|  | Metric *mitem; | 
|  | int index; | 
|  | Vec_loop (Metric*, bmlist->get_items (), index, mitem) | 
|  | { | 
|  | Vector<void*> * columnData = dbeGetTableDataOneColumn (dbev, | 
|  | v_totals, mitem->get_vtype (), index); | 
|  | valueTable->append (columnData); | 
|  | } | 
|  | } | 
|  |  | 
|  | // 7207285: hack for hwc profiling cycles conversion: | 
|  | { | 
|  | Metric *mitem; | 
|  | int index; | 
|  | Vec_loop (Metric*, bmlist->get_items (), index, mitem) | 
|  | { | 
|  | if (mitem->is_time_val () | 
|  | && mitem->get_vtype () == VT_ULLONG) | 
|  | { | 
|  | Vector<long long> *cycleValues = (Vector<long long> *)valueTable->fetch (index); | 
|  | Vector<double> *timeValues = new Vector<double>(ngroups); | 
|  | assert (cycleValues->size () == ngroups); | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | { | 
|  | long long cycles = cycleValues->fetch (grInd); | 
|  | int expId; | 
|  | if (dbeSession->expGroups->size () > 0) | 
|  | { | 
|  | ExpGroup *gr = dbeSession->expGroups->fetch (grInd); | 
|  | Experiment *exp = gr->exps->fetch (0); | 
|  | expId = exp->getExpIdx (); | 
|  | } | 
|  | else | 
|  | expId = -1; | 
|  | int clock = dbeSession->get_clock (expId); | 
|  | double time; | 
|  | if (clock) | 
|  | time = cycles / (1.e+6 * clock); | 
|  | else | 
|  | time = cycles; //weird | 
|  | timeValues->store (grInd, time); | 
|  | } | 
|  | delete cycleValues; | 
|  | valueTable->store (index, timeValues); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // Scan metrics for best measure of CPU time | 
|  | int bestCpuTimeIndx = -1; | 
|  | { | 
|  | Metric *mitem; | 
|  | int index; | 
|  | Vec_loop (Metric*, bmlist->get_items (), index, mitem) | 
|  | { | 
|  | BaseMetric::Type type = mitem->get_type (); | 
|  | if (type == BaseMetric::CP_KERNEL_CPU) | 
|  | { | 
|  | bestCpuTimeIndx = index; | 
|  | break; // CP_KERNEL_CPU trumps other measures | 
|  | } | 
|  | if (type == BaseMetric::CP_TOTAL_CPU) | 
|  | { | 
|  | // clock profiling CPU time | 
|  | bestCpuTimeIndx = index; | 
|  | // keep looking in case CP_KERNEL_CPU also exists | 
|  | continue; | 
|  | } | 
|  |  | 
|  | bool isTime = ((mitem->get_value_styles () & VAL_TIMEVAL) != 0); | 
|  | bool isHwcCycles = (type == BaseMetric::HWCNTR | 
|  | && (dbe_strcmp (mitem->get_aux (), "cycles") == 0) | 
|  | && isTime); | 
|  | if (isHwcCycles) | 
|  | if (bestCpuTimeIndx < 0) | 
|  | bestCpuTimeIndx = index; | 
|  | } | 
|  | if (bestCpuTimeIndx >= 0) | 
|  | { | 
|  | Vector<double> *timeValues = (Vector<double> *)valueTable->fetch (bestCpuTimeIndx); | 
|  | if (timeValues->type () == VEC_DOUBLE) | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | { | 
|  | double time = timeValues->fetch (grInd); | 
|  | groupCpuTime->append (time); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // Scan metrics for Total Thread time | 
|  | { | 
|  | Metric *mitem; | 
|  | int index; | 
|  | Vec_loop (Metric*, bmlist->get_items (), index, mitem) | 
|  | { | 
|  | BaseMetric::Type type = mitem->get_type (); | 
|  | if (type == BaseMetric::CP_TOTAL) | 
|  | { | 
|  | Vector<double> *timeValues = (Vector<double> *)valueTable->fetch (index); | 
|  | if (timeValues->type () != VEC_DOUBLE) | 
|  | continue; // weird | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | { | 
|  | double time = timeValues->fetch (grInd); | 
|  | groupTotalTime->append (time); | 
|  | } | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // highlight metrics based on cpu time | 
|  | #define CPUSEC_PERCENT_THRESHOLD            10.0 | 
|  | #define HWC_OVERFLOWS_PER_CPUSEC_THRESHOLD  15 | 
|  | { | 
|  | Metric *mitem; | 
|  | int index; | 
|  | Vec_loop (Metric*, bmlist->get_items (), index, mitem) | 
|  | { | 
|  | BaseMetric::Type type = mitem->get_type (); | 
|  | Vector<bool> * columnHilites = (Vector<bool> *)highlightTable->fetch (index); | 
|  |  | 
|  | // always highlight the following | 
|  | if (index == bestCpuTimeIndx) | 
|  | { | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | columnHilites->store (grInd, true); | 
|  | continue; | 
|  | } | 
|  |  | 
|  | // skip certain types | 
|  | bool typeIsCycles = (type == BaseMetric::HWCNTR | 
|  | && dbe_strcmp (mitem->get_aux (), NTXT ("cycles")) == 0); | 
|  | bool typeIsInsts = (type == BaseMetric::HWCNTR | 
|  | && dbe_strcmp (mitem->get_aux (), NTXT ("insts")) == 0); | 
|  | if (type == BaseMetric::CP_TOTAL | 
|  | || type == BaseMetric::CP_TOTAL_CPU | 
|  | || type == BaseMetric::CP_LMS_USER | 
|  | || type == BaseMetric::CP_LMS_SYSTEM | 
|  | || type == BaseMetric::CP_LMS_TRAP | 
|  | || type == BaseMetric::CP_LMS_USER_LOCK | 
|  | || type == BaseMetric::CP_LMS_SLEEP | 
|  | || type == BaseMetric::CP_KERNEL_CPU | 
|  | || type == BaseMetric::OMP_WORK | 
|  | || typeIsCycles | 
|  | || typeIsInsts | 
|  | // || type == BaseMetric::CP_TOTAL_WAIT | 
|  | ) | 
|  | continue; // types we never highlight | 
|  |  | 
|  | // for time values, compare against CPUSEC_PERCENT_THRESHOLD | 
|  | bool isTime = ((mitem->get_value_styles () & VAL_TIMEVAL) != 0); | 
|  | if (isTime) | 
|  | { | 
|  | if (groupCpuTime->size () == 0) | 
|  | continue; // no time to use as reference | 
|  | Vector<double> *timeValues = (Vector<double> *)valueTable->fetch (index); | 
|  | if (timeValues->type () != VEC_DOUBLE) | 
|  | continue; // weird | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | { | 
|  | double thistime = timeValues->fetch (grInd); | 
|  | double usertime = groupCpuTime->fetch (grInd); | 
|  | if (thistime / (CPUSEC_PERCENT_THRESHOLD / 100) > usertime) | 
|  | columnHilites->store (grInd, true); | 
|  | } | 
|  | continue; | 
|  | } | 
|  |  | 
|  | // for HWC event counts, look at rate of events | 
|  | if (type == BaseMetric::HWCNTR) | 
|  | { | 
|  | Hwcentry *hwctr = mitem->get_hw_ctr (); | 
|  | if (!hwctr) | 
|  | continue; // weird | 
|  | if (!hwctr->metric) | 
|  | continue; // raw counter | 
|  | if (groupCpuTime->size () == 0) | 
|  | continue; // no time to use as reference | 
|  | if (mitem->get_base_metric ()->get_dependent_bm ()) | 
|  | continue; // has a derived time metric, only flag time version | 
|  | Vector<long long> *llValues = (Vector<long long> *)valueTable->fetch (index); | 
|  | if (llValues->type () != VEC_LLONG) | 
|  | continue; // weird | 
|  | int overflowVal = hwctr->val; //overflow count | 
|  | if (!overflowVal) | 
|  | continue; // weird | 
|  | if (overflowVal > (4000000)) | 
|  | // cut off events that are very frequent like loads/stores | 
|  | // 4Ghz * (0.01 seconds/event) / (4000000 events/overflow) = 10 cycles | 
|  | continue; | 
|  | // for HWCs we could base it on the overflow rate | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | { | 
|  | double thisVal = llValues->fetch (grInd); | 
|  | thisVal /= overflowVal; | 
|  | double usertime = groupCpuTime->fetch (grInd); | 
|  | if (thisVal > usertime * HWC_OVERFLOWS_PER_CPUSEC_THRESHOLD) | 
|  | columnHilites->store (grInd, true); | 
|  | } | 
|  | continue; | 
|  | } | 
|  |  | 
|  | // check for non-zero counts of the following | 
|  | if (type == BaseMetric::DEADLOCKS || | 
|  | type == BaseMetric::RACCESS || | 
|  | type == BaseMetric::HEAP_ALLOC_BYTES || | 
|  | type == BaseMetric::HEAP_LEAK_BYTES) | 
|  | { | 
|  | Vector<long long> *llValues = (Vector<long long> *)valueTable->fetch (index); | 
|  | if (llValues->type () != VEC_LLONG) | 
|  | continue; // weird | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | { | 
|  | long long thisVal = llValues->fetch (grInd); | 
|  | if (thisVal) | 
|  | columnHilites->store (grInd, true); | 
|  | } | 
|  | continue; | 
|  | } | 
|  | // continue adding cases as needed | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | if (numNonMetrics > 0) | 
|  | { | 
|  | int index; | 
|  | char *mcmd; | 
|  | Vec_loop (char *, non_metric_cmds, index, mcmd) | 
|  | { | 
|  | if (dbe_strcmp (mcmd, NTXT ("YXXX_TOTAL_TIME_PLUS_THREADS")) == 0 | 
|  | && groupCpuTime->size () == ngroups) | 
|  | { | 
|  | Vector<char *> *columnData = new Vector<char *>(ngroups); | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | { | 
|  | double totaltime = groupTotalTime->fetch (grInd); | 
|  | columnData->append (dbe_sprintf (NTXT ("%0.3f %s"), totaltime, GTXT ("Seconds"))); | 
|  | } | 
|  | valueTable->append (columnData); | 
|  | } | 
|  | else if (dbe_strcmp (mcmd, L1_DURATION) == 0) | 
|  | { | 
|  | Vector<double> *columnData = new Vector<double>(ngroups); | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | { | 
|  | hrtime_t duration = dbeCalcGroupDuration (grInd); | 
|  | double seconds = duration * 1.e-9; | 
|  | columnData->append (seconds); | 
|  | } | 
|  | valueTable->append (columnData); | 
|  | } | 
|  | else if (dbe_strcmp (mcmd, L1_GCDURATION) == 0) | 
|  | { | 
|  | Vector<double> *columnData = new Vector<double>(ngroups); | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | { | 
|  | hrtime_t duration = dbeCalcGroupGCDuration (grInd); | 
|  | double seconds = duration * 1.e-9; | 
|  | columnData->append (seconds); | 
|  | } | 
|  | valueTable->append (columnData); | 
|  | } | 
|  | else | 
|  | { | 
|  | Vector<char *> *columnData = new Vector<char *>(ngroups); | 
|  | char * valueString = NTXT ("<unknown>"); | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | columnData->append (dbe_strdup (valueString)); | 
|  | valueTable->append (columnData); | 
|  | } | 
|  | } | 
|  | } | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | Vector<char*> * | 
|  | dbeGetOverviewText (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | Vector<char*> *info = new Vector<char*>; | 
|  | char *field; | 
|  | int ngroups = dbeSession->expGroups->size (); // Rows (one per compare group) | 
|  | if (ngroups == 0 || !dbev->comparingExperiments ()) | 
|  | ngroups = 1; | 
|  | for (int grInd = 0; grInd < ngroups; grInd++) | 
|  | { | 
|  | int thisGroupSize = 1; | 
|  | Experiment *exp; | 
|  | if (dbeSession->expGroups->size () > 0) | 
|  | { | 
|  | ExpGroup *gr = dbeSession->expGroups->fetch (grInd); | 
|  | exp = gr->exps->fetch (0); | 
|  | thisGroupSize = gr->exps->size (); | 
|  | } | 
|  | else | 
|  | { | 
|  | if (dbeSession->nexps () == 0) | 
|  | return info; | 
|  | exp = dbeSession->get_exp (0); | 
|  | } | 
|  | char * expHeader; | 
|  | if (ngroups == 1) | 
|  | expHeader = dbe_strdup (GTXT ("Experiment      :")); | 
|  | else if (grInd == 0) | 
|  | expHeader = dbe_strdup (GTXT ("Base Group      : ")); | 
|  | else if (ngroups == 2) | 
|  | expHeader = dbe_strdup (GTXT ("Compare Group   : ")); | 
|  | else | 
|  | expHeader = dbe_sprintf (GTXT ("Compare Group %d : "), grInd); | 
|  | if (thisGroupSize == 1) | 
|  | info->append (dbe_sprintf ("%s%s", expHeader, exp->get_expt_name ())); | 
|  | else | 
|  | info->append (dbe_sprintf ("%s%s (plus %d more)", | 
|  | expHeader, exp->get_expt_name (), thisGroupSize - 1)); | 
|  | free (expHeader); | 
|  | field = exp->uarglist; | 
|  | if (field && field[0]) | 
|  | info->append (dbe_sprintf (GTXT ("  Target        : '%s'"), field)); | 
|  | field = exp->hostname; | 
|  | if (field && field[0]) | 
|  | info->append (dbe_sprintf (GTXT ("  Host          : %s (%s, %s)"), | 
|  | field, | 
|  | exp->architecture ? exp->architecture | 
|  | : GTXT ("<CPU architecture not recorded>"), | 
|  | exp->os_version ? exp->os_version | 
|  | : GTXT ("<OS version not recorded>"))); | 
|  | time_t start_sec = (time_t) exp->start_sec; | 
|  | char *p = ctime (&start_sec); | 
|  | hrtime_t tot_time = dbeCalcGroupDuration (grInd); | 
|  | double seconds = tot_time * 1.e-9; | 
|  | info->append (dbe_sprintf ( | 
|  | GTXT ("  Start Time    : %s  Duration      : %0.3f Seconds"), | 
|  | p, seconds)); | 
|  | // Number of descendants/processes would be nice | 
|  | info->append (dbe_strdup (NTXT (""))); | 
|  | } | 
|  | return info; | 
|  | } | 
|  |  | 
|  | //-------------------------------------------------------------------------- | 
|  | // Set Sort by index | 
|  | // | 
|  | void | 
|  | dbeSetSort (int dbevindex, int sort_index, MetricType mtype, bool reverse) | 
|  | { | 
|  | DbeView *dbev; | 
|  |  | 
|  | dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | dbev->setSort (sort_index, mtype, reverse); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get annotation setting | 
|  | // | 
|  | Vector<int> * | 
|  | dbeGetAnoValue (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Vector<int> *set = new Vector<int>(9); | 
|  | set->store (0, dbev->get_src_compcom ()); | 
|  | set->store (1, dbev->get_dis_compcom ()); | 
|  | set->store (2, dbev->get_thresh_src ()); | 
|  | set->store (3, dbev->get_thresh_src ()); | 
|  | set->store (4, dbev->get_src_visible ()); | 
|  | set->store (5, (int) dbev->get_srcmetric_visible ()); | 
|  | set->store (6, (int) dbev->get_hex_visible ()); | 
|  | set->store (7, (int) dbev->get_cmpline_visible ()); | 
|  | set->store (8, (int) dbev->get_func_scope ()); | 
|  | return set; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Set annotation setting | 
|  | // | 
|  | void | 
|  | dbeSetAnoValue (int dbevindex, Vector<int> *set) | 
|  | { | 
|  | DbeView *dbev; | 
|  | dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | if (set->size () != 10) | 
|  | return; | 
|  | dbev->set_src_compcom (set->fetch (0)); | 
|  | dbev->set_dis_compcom (set->fetch (1)); | 
|  | dbev->set_thresh_src (set->fetch (2)); | 
|  | dbev->set_thresh_dis (set->fetch (3)); | 
|  | dbev->set_src_visible (set->fetch (4)); | 
|  | dbev->set_srcmetric_visible ((bool)set->fetch (5)); | 
|  | dbev->set_hex_visible ((bool)set->fetch (6)); | 
|  | dbev->set_cmpline_visible ((bool)set->fetch (7)); | 
|  | dbev->set_func_scope (set->fetch (8)); | 
|  | dbev->set_funcline_visible ((bool)set->fetch (9)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get name formats | 
|  | // | 
|  | int | 
|  | dbeGetNameFormat (int dbevindex) | 
|  | { | 
|  | DbeView *dbev; | 
|  | dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Histable::NameFormat fmt = dbev->get_name_format (); | 
|  | return Histable::fname_fmt (fmt); | 
|  | } | 
|  |  | 
|  | bool | 
|  | dbeGetSoName (int dbevindex) | 
|  | { | 
|  | DbeView *dbev; | 
|  | dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Histable::NameFormat fmt = dbev->get_name_format (); | 
|  | return Histable::soname_fmt (fmt); | 
|  | } | 
|  |  | 
|  | // | 
|  | // Set name formats | 
|  | // | 
|  | void | 
|  | dbeSetNameFormat (int dbevindex, int nformat, bool soname) | 
|  | { | 
|  | DbeView *dbev; | 
|  | dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | dbev->set_name_format (nformat, soname); | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get View mode | 
|  | // | 
|  | int | 
|  | dbeGetViewMode (int dbevindex) | 
|  | { | 
|  | DbeView *dbev; | 
|  | dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | return (int) dbev->get_view_mode (); | 
|  | } | 
|  |  | 
|  | // Set View mode | 
|  | void | 
|  | dbeSetViewMode (int dbevindex, int nmode) | 
|  | { | 
|  | DbeView *dbev; | 
|  | dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | dbev->set_view_mode ((VMode) nmode); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Get timeline setting | 
|  | // | 
|  | Vector<void*> * | 
|  | dbeGetTLValue (int dbevindex) | 
|  | { | 
|  | DbeView *dbev; | 
|  | dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Vector<char *> *strings = new Vector<char *>(); | 
|  | char *tldata_cmd = dbev->get_tldata (); | 
|  | strings->store (0, tldata_cmd); | 
|  |  | 
|  | Vector<int> *ints = new Vector<int>(3); | 
|  | int val; | 
|  | val = dbev->get_tlmode (); | 
|  | ints->store (0, val); | 
|  | val = dbev->get_stack_align (); | 
|  | ints->store (1, val); | 
|  | val = dbev->get_stack_depth (); | 
|  | ints->store (2, val); | 
|  |  | 
|  | Vector<void*> *objs = new Vector<void*>(2); | 
|  | objs->store (0, strings); | 
|  | objs->store (1, ints); | 
|  | return objs; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Set timeline setting | 
|  | // | 
|  | void | 
|  | dbeSetTLValue (int dbevindex, const char *tldata_cmd, | 
|  | int entitiy_prop_id, int stackalign, int stackdepth) | 
|  | { | 
|  | DbeView *dbev; | 
|  | dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | dbev->set_tldata (tldata_cmd); | 
|  | dbev->set_tlmode (entitiy_prop_id); | 
|  | dbev->set_stack_align (stackalign); | 
|  | dbev->set_stack_depth (stackdepth); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get founder experiments and their descendants | 
|  | // | 
|  | Vector<void*> * | 
|  | dbeGetExpFounderDescendants () | 
|  | { | 
|  | int size = dbeSession->nexps (); | 
|  | if (size == 0) | 
|  | return NULL; | 
|  | Vector<void*> *table = new Vector<void*>(2); | 
|  | Vector<int> *founderExpIds = new Vector<int>(); | 
|  | Vector<Vector<int> *> *subExpIds = new Vector<Vector<int>*>(); | 
|  | for (int index = 0; index < size; index++) | 
|  | { | 
|  | Experiment *exp = dbeSession->get_exp (index); | 
|  | if (exp->founder_exp == NULL) | 
|  | { | 
|  | founderExpIds->append (exp->getExpIdx ()); | 
|  | Vector<int> *subExps = new Vector<int>(); | 
|  | for (int i = 0; i < exp->children_exps->size (); i++) | 
|  | { | 
|  | Experiment * subExp = exp->children_exps->fetch (i); | 
|  | subExps->append (subExp->getExpIdx ()); | 
|  | } | 
|  | subExpIds->append (subExps); | 
|  | } | 
|  | } | 
|  | table->store (0, founderExpIds); | 
|  | table->store (1, subExpIds); | 
|  | return table; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get experiment selection | 
|  | // | 
|  | Vector<void*> * | 
|  | dbeGetExpSelection (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | int size = dbeSession->nexps (); | 
|  | if (size == 0) | 
|  | return NULL; | 
|  | Vector<void*> *table = new Vector<void*>(3); | 
|  | Vector<char*> *names = new Vector<char*>(size); | 
|  | Vector<bool> *enable = new Vector<bool>(size); | 
|  | Vector<int> *userExpIds = new Vector<int>(size); | 
|  |  | 
|  | // Get experiment names | 
|  | for (int index = 0; index < size; index++) | 
|  | { | 
|  | Experiment *exp = dbeSession->get_exp (index); | 
|  | char *buf = dbeGetName (dbevindex, index); | 
|  | names->store (index, buf); | 
|  | bool val; | 
|  | val = dbev->get_exp_enable (index); | 
|  | enable->store (index, val); | 
|  | userExpIds->store (index, exp->getUserExpId ()); | 
|  | } | 
|  | table->store (0, names); | 
|  | table->store (1, enable); | 
|  | table->store (2, userExpIds); | 
|  | return table; | 
|  | } | 
|  |  | 
|  | int | 
|  | dbeValidateFilterExpression (char *str_expr) | 
|  | { | 
|  | if (str_expr == NULL) | 
|  | return 0; | 
|  | Expression *expr = dbeSession->ql_parse (str_expr); | 
|  | if (expr == NULL) | 
|  | return 0; | 
|  | delete expr; | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetFilterKeywords (int /* dbevindex */) | 
|  | { | 
|  | Vector <char*> *kwCategory = new Vector<char *>(); | 
|  | Vector <char*> *kwCategoryI18N = new Vector<char *>(); | 
|  | Vector <char*> *kwDataType = new Vector<char *>(); | 
|  | Vector <char*> *kwKeyword = new Vector<char *>(); | 
|  | Vector <char*> *kwFormula = new Vector<char *>(); | 
|  | Vector <char*> *kwDescription = new Vector<char *>(); | 
|  | Vector <void*> *kwEnumDescs = new Vector<void *>(); | 
|  |  | 
|  | Vector<void*> *res = new Vector<void*>(7); | 
|  | res->append (kwCategory); | 
|  | res->append (kwCategoryI18N); | 
|  | res->append (kwDataType); | 
|  | res->append (kwKeyword); | 
|  | res->append (kwFormula); | 
|  | res->append (kwDescription); | 
|  | res->append (kwEnumDescs); | 
|  |  | 
|  | char *vtypeNames[] = VTYPE_TYPE_NAMES; | 
|  | // section header for global definitions | 
|  | kwCategory->append (dbe_strdup (NTXT ("FK_SECTION"))); | 
|  | kwCategoryI18N->append (dbe_strdup (GTXT ("Global Definitions"))); | 
|  | kwDataType->append (NULL); | 
|  | kwKeyword->append (NULL); | 
|  | kwFormula->append (NULL); | 
|  | kwDescription->append (NULL); | 
|  | kwEnumDescs->append (NULL); | 
|  | dbeSession->get_filter_keywords (res); | 
|  | MemorySpace::get_filter_keywords (res); | 
|  |  | 
|  | // loop thru all founder experiments | 
|  | int nexp = dbeSession->nexps (); | 
|  | for (int ii = 0; ii < nexp; ++ii) | 
|  | { | 
|  | Experiment* fexp = dbeSession->get_exp (ii); | 
|  | if (fexp->founder_exp != NULL) | 
|  | continue; // is a child; should be covered when we get to founder | 
|  |  | 
|  | // section header for each founder | 
|  | // section header for founder experiment | 
|  | kwCategory->append (dbe_strdup (NTXT ("FK_SECTION"))); | 
|  | kwCategoryI18N->append (dbe_sprintf (NTXT ("%s [EXPGRID==%d]"), | 
|  | fexp->get_expt_name (), | 
|  | fexp->groupId)); | 
|  | kwDataType->append (NULL); | 
|  | kwKeyword->append (NULL); | 
|  | kwFormula->append (NULL); | 
|  | kwDescription->append (NULL); | 
|  | kwEnumDescs->append (NULL); | 
|  |  | 
|  | int nchildren = fexp->children_exps->size (); | 
|  | Experiment *exp; | 
|  | // category header: Experiments | 
|  | { | 
|  | char *propUName = dbeSession->getPropUName (PROP_EXPID); | 
|  |  | 
|  | // store list of subexperiments in kwEnumDescs | 
|  | Vector <char*> *enumDescs = new Vector<char *>(); | 
|  | int jj = 0; | 
|  | exp = fexp; | 
|  | while (1) | 
|  | { | 
|  | char * expBasename = get_basename (exp->get_expt_name ()); | 
|  | char * targetName = exp->utargname ? exp->utargname | 
|  | : (char *) GTXT ("(unknown)"); | 
|  | enumDescs->append (dbe_sprintf (NTXT ("(%d) -> %s [%s, PID %d]"), | 
|  | exp->getUserExpId (), expBasename, | 
|  | targetName, exp->getPID ())); | 
|  | if (jj >= nchildren) | 
|  | break; | 
|  | exp = fexp->children_exps->fetch (jj); | 
|  | jj++; | 
|  | } | 
|  | kwCategory->append (dbe_strdup (NTXT ("FK_EXPLIST"))); | 
|  | kwCategoryI18N->append (dbe_strdup (GTXT ("Experiments"))); | 
|  | kwDataType->append (dbe_strdup (vtypeNames[TYPE_INT32])); | 
|  | kwKeyword->append (dbe_strdup (NTXT ("EXPID"))); | 
|  | kwFormula->append (NULL); | 
|  | kwDescription->append (propUName); | 
|  | kwEnumDescs->append (enumDescs); | 
|  | } | 
|  |  | 
|  | // select representative experiment | 
|  | if (nchildren == 0) | 
|  | exp = fexp; // founder | 
|  | else | 
|  | exp = fexp->children_exps->fetch (0); // first child | 
|  | int expIdx = exp->getExpIdx (); | 
|  | Vector<void*> *data = dbeGetDataDescriptorsV2 (expIdx); | 
|  | if (data == NULL) | 
|  | continue; | 
|  | Vector<int> *dataId = (Vector<int>*)data->fetch (0); | 
|  | Vector<char*> *dataName = (Vector<char*>*)data->fetch (1); | 
|  | Vector<char*> *dataUName = (Vector<char*>*)data->fetch (2); | 
|  | if (dataId == NULL || dataName == NULL) | 
|  | { | 
|  | destroy (data); | 
|  | continue; | 
|  | } | 
|  | // loop thru data descriptors | 
|  | int ndata = dataId->size (); | 
|  | for (int j = 0; j < ndata; ++j) | 
|  | { | 
|  | // category: data name (e.g. Clock Profiling) | 
|  | char * catName = dataName->fetch (j); | 
|  | char * dUname = dataUName ? dataUName->fetch (j) : catName; | 
|  | char * catUname = dUname ? dUname : catName; | 
|  |  | 
|  | Vector<void*> *props = dbeGetDataPropertiesV2 (expIdx, dataId->fetch (j)); | 
|  | if (props == NULL) | 
|  | continue; | 
|  | Vector<char*> *propUName = (Vector<char*>*)props->fetch (1); | 
|  | Vector<int> *propTypeId = (Vector<int> *)props->fetch (2); | 
|  | Vector<char*> *propType = (Vector<char*>*)props->fetch (3); | 
|  | Vector<char*> *propName = (Vector<char*>*)props->fetch (5); | 
|  | Vector<Vector<char*>*> *propStateNames = | 
|  | (Vector<Vector<char*>*> *)props->fetch (6); | 
|  | Vector<Vector<char*>*> *propStateUNames = | 
|  | (Vector<Vector<char*>*> *)props->fetch (7); | 
|  | if (propName == NULL || propUName == NULL || propType == NULL | 
|  | || propName->size () <= 0) | 
|  | { | 
|  | destroy (props); | 
|  | continue; | 
|  | } | 
|  | int nprop = propName->size (); | 
|  | for (int k = 0; k < nprop; ++k) | 
|  | { | 
|  | if (propTypeId->fetch (k) == TYPE_OBJ) | 
|  | continue; | 
|  | if (dbe_strcmp (propName->fetch (k), NTXT ("FRINFO")) == 0) | 
|  | continue; | 
|  |  | 
|  | // store list of states in kwEnumDescs | 
|  | Vector<char*> *enumDescs = new Vector<char *>(); | 
|  | Vector<char*>* stateNames = propStateNames->fetch (k); | 
|  | Vector<char*>* stateUNames = propStateUNames->fetch (k); | 
|  | int nStates = stateNames ? stateNames->size () : 0; | 
|  | for (int kk = 0; kk < nStates; ++kk) | 
|  | { | 
|  | const char *stateName = stateNames->fetch (kk); | 
|  | if (stateName == NULL || strlen (stateName) == 0) | 
|  | continue; | 
|  | const char *stateUName = stateUNames->fetch (kk); | 
|  | if (stateUName == NULL || strlen (stateUName) == 0) | 
|  | stateUName = stateName; | 
|  | enumDescs->append (dbe_sprintf (NTXT ("(%d) -> %s"), kk, stateUName)); | 
|  | } | 
|  | kwCategory->append (dbe_strdup (catName)); | 
|  | kwCategoryI18N->append (dbe_strdup (catUname)); | 
|  | kwDataType->append (dbe_strdup (propType->fetch (k))); | 
|  | kwKeyword->append (dbe_strdup (propName->fetch (k))); | 
|  | kwFormula->append (NULL); | 
|  | kwDescription->append (dbe_strdup (propUName->fetch (k))); | 
|  | kwEnumDescs->append (enumDescs); | 
|  | } | 
|  | destroy (props); | 
|  | } | 
|  | destroy (data); | 
|  | } | 
|  | return (res); | 
|  | } | 
|  |  | 
|  | // GetFilters -- returns the list of filters for the indexed experiment | 
|  | //	returns false if there's a problem; true otherwise | 
|  | // | 
|  | Vector<void*> * | 
|  | dbeGetFilters (int dbevindex, int nexp) | 
|  | { | 
|  | FilterNumeric *filt; | 
|  | int index; | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Vector<FilterNumeric *>*filters = dbev->get_all_filters (nexp); | 
|  | if (filters == NULL) | 
|  | return NULL; | 
|  |  | 
|  | // return an array of filter data for that experiment | 
|  | Vector <int> *findex = new Vector<int>(); // index of the filters | 
|  | Vector <char*> *shortname = new Vector<char *>(); | 
|  | // short name of filter | 
|  | Vector <char*> *i18n_name = new Vector<char *>(); | 
|  | // External I18N'd name of filter | 
|  | Vector <char*> *pattern = new Vector<char *>(); | 
|  | // current setting string | 
|  | Vector <char*> *status = new Vector<char *>(); | 
|  | // current status of filter (%, range, etc.) | 
|  |  | 
|  | Vec_loop (FilterNumeric *, filters, index, filt) | 
|  | { | 
|  | findex->append (index); | 
|  | shortname->append (dbe_strdup (filt->get_cmd ())); | 
|  | i18n_name->append (dbe_strdup (filt->get_name ())); | 
|  | pattern->append (dbe_strdup (filt->get_pattern ())); | 
|  | status->append (dbe_strdup (filt->get_status ())); | 
|  | } | 
|  | Vector<void*> *res = new Vector<void*>(5); | 
|  | res->store (0, findex); | 
|  | res->store (1, shortname); | 
|  | res->store (2, i18n_name); | 
|  | res->store (3, pattern); | 
|  | res->store (4, status); | 
|  | return (res); | 
|  | } | 
|  |  | 
|  | // Set a filter string for a view | 
|  | //	Returns NULL if OK, error message if not | 
|  |  | 
|  | char * | 
|  | dbeSetFilterStr (int dbevindex, char *filter_str) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | dbev->clear_error_msg (); | 
|  | dbev->clear_warning_msg (); | 
|  | char *ret = dbev->set_filter (filter_str); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | // Get the current filter setting for the view | 
|  | char * | 
|  | dbeGetFilterStr (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | char *ret = dbev->get_filter (); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | // Update a filters for a single experiment | 
|  | // Returns true if any filter->set_pattern() returns true, | 
|  | //	implying rereading the data is needed (i.e., a filter changed) | 
|  | // | 
|  | bool | 
|  | dbeUpdateFilters (int dbevindex, Vector<bool> *selected, Vector<char *> *pattern_str) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | dbev->clear_error_msg (); | 
|  | dbev->clear_warning_msg (); | 
|  |  | 
|  | // Get index of first selected experiment | 
|  | int size = selected->size (); | 
|  | int nselexp = -1; | 
|  | for (int index = 0; index < size; index++) | 
|  | { | 
|  | if (selected->fetch (index) == true) | 
|  | { | 
|  | nselexp = index; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (nselexp == -1) // No experiment selected | 
|  | return false; | 
|  |  | 
|  | bool ret = false; | 
|  | for (int j = 0; j < size; j++) | 
|  | { | 
|  | if (selected->fetch (j) == false) | 
|  | continue; | 
|  | bool error; | 
|  | if (dbev->set_pattern (j, pattern_str, &error)) | 
|  | ret = true; | 
|  | } | 
|  | dbev->update_advanced_filter (); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeComposeFilterClause (int dbevindex, int type, int subtype, Vector<int> *selections) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | // ask the cached data to generate the string | 
|  | Hist_data *data; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_FUNCTION: | 
|  | data = dbev->func_data; | 
|  | break; | 
|  | case DSP_DLAYOUT: | 
|  | data = dbev->dlay_data; | 
|  | break; | 
|  | case DSP_DATAOBJ: | 
|  | data = dbev->dobj_data; | 
|  | break; | 
|  | case DSP_MEMOBJ: | 
|  | case DSP_INDXOBJ: | 
|  | data = dbev->get_indxobj_data (subtype); | 
|  | break; | 
|  | case DSP_LINE: | 
|  | data = dbev->line_data; | 
|  | break; | 
|  | case DSP_PC: | 
|  | data = dbev->pc_data; | 
|  | break; | 
|  | case DSP_SOURCE: | 
|  | data = dbev->src_data; | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | data = dbev->dis_data; | 
|  | break; | 
|  | case DSP_IOACTIVITY: | 
|  | data = dbev->iofile_data; | 
|  | break; | 
|  | case DSP_IOVFD: | 
|  | data = dbev->iovfd_data; | 
|  | break; | 
|  | case DSP_IOCALLSTACK: | 
|  | data = dbev->iocs_data; | 
|  | break; | 
|  | case DSP_HEAPCALLSTACK: | 
|  | data = dbev->heapcs_data; | 
|  | break; | 
|  | default: | 
|  | return NULL; | 
|  | } | 
|  | if (data == NULL) | 
|  | return NULL; | 
|  |  | 
|  | // Get array of object indices, and compose filter string | 
|  | Vector<uint64_t> *obj_ids = data->get_object_indices (selections); | 
|  | if (obj_ids == NULL || obj_ids->size () == 0) | 
|  | return NULL; | 
|  |  | 
|  | uint64_t sel; | 
|  | int index; | 
|  | int found = 0; | 
|  | char buf[128]; | 
|  | StringBuilder sb; | 
|  | sb.append ('('); | 
|  | switch (type) | 
|  | { | 
|  | case DSP_LINE: | 
|  | case DSP_PC: | 
|  | case DSP_SOURCE: | 
|  | case DSP_DISASM: | 
|  | case DSP_FUNCTION: | 
|  | sb.append (NTXT ("LEAF IN ")); | 
|  | break; | 
|  | case DSP_MEMOBJ: | 
|  | case DSP_INDXOBJ: | 
|  | sb.append (dbeSession->getIndexSpaceName (subtype)); | 
|  | sb.append (NTXT (" IN ")); | 
|  | break; | 
|  | } | 
|  | Vec_loop (uint64_t, obj_ids, index, sel) | 
|  | { | 
|  | if (found == 0) | 
|  | { | 
|  | found = 1; | 
|  | sb.append ('('); | 
|  | } | 
|  | else | 
|  | sb.append (NTXT (", ")); | 
|  | snprintf (buf, sizeof (buf), NTXT ("%llu"), (long long) sel); | 
|  | sb.append (buf); | 
|  | } | 
|  | if (found == 1) | 
|  | sb.append (')'); | 
|  |  | 
|  | switch (type) | 
|  | { | 
|  | case DSP_DLAYOUT: | 
|  | case DSP_DATAOBJ: | 
|  | sb.append (NTXT (" SOME IN DOBJ")); | 
|  | break; | 
|  | } | 
|  | sb.append (')'); | 
|  | return sb.toString (); | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get load object states | 
|  | // | 
|  | Vector<void *> * | 
|  | dbeGetLoadObjectList (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Vector<LoadObject*> *lobjs = dbeSession->get_text_segments (); | 
|  | int size = lobjs->size (); | 
|  |  | 
|  | // Initialize Java boolean array | 
|  | Vector<char *> *names = new Vector<char *>(size); | 
|  | Vector<int> *states = new Vector<int>(size); | 
|  | Vector<int> *indices = new Vector<int>(size); | 
|  | Vector<char *> *paths = new Vector<char *>(size); | 
|  | Vector<int> *isJava = new Vector<int>(size); | 
|  |  | 
|  | // Get load object states | 
|  | int index; | 
|  | LoadObject *lo; | 
|  | char *lo_name; | 
|  |  | 
|  | // lobjectsNoJava is a trimmed list of indices provided to front-end skipping the Java | 
|  | // classes. lobjectsNoJava preserves the mapping of the index into the complete lobjs | 
|  | // vector. What front-end sees as lobj[i] is really lobj[lobjectsNoJava[i]]; | 
|  |  | 
|  | // This list is constructed every time GetLoadObjectList() or GetLoadObjectState() is | 
|  | // called. Possibility of further optimization by making it more persistent. | 
|  | // Only consumer of this list is dbeSetLoadObjectState | 
|  | int new_index = 0; | 
|  | if (dbev->lobjectsNoJava == NULL) | 
|  | dbev->lobjectsNoJava = new Vector<int>(1); | 
|  | else | 
|  | dbev->lobjectsNoJava->reset (); | 
|  |  | 
|  | Vec_loop (LoadObject*, lobjs, index, lo) | 
|  | { | 
|  | // Set 0, 1, or 2 for show/hide/api | 
|  | enum LibExpand expand = dbev->get_lo_expand (lo->seg_idx); | 
|  |  | 
|  | lo_name = lo->get_name (); | 
|  | if (lo_name != NULL) | 
|  | { | 
|  | size_t len = strlen (lo_name); | 
|  | if (len > 7 && streq (lo_name + len - 7, NTXT (".class>"))) | 
|  | isJava->store (new_index, 1); | 
|  | else | 
|  | isJava->store (new_index, 0); | 
|  | } | 
|  | else | 
|  | isJava->store (new_index, 0); | 
|  | dbev->lobjectsNoJava->append (index); | 
|  |  | 
|  | names->store (new_index, dbe_sprintf (NTXT ("%s"), lo_name)); | 
|  | states->store (new_index, (int) expand); | 
|  | indices->store (new_index, (int) lo->seg_idx); | 
|  | paths->store (new_index, dbe_sprintf (NTXT ("%s"), lo->get_pathname ())); | 
|  | new_index++; | 
|  | } | 
|  | Vector<void*> *res = new Vector<void*>(5); | 
|  | res->store (0, names); | 
|  | res->store (1, states); | 
|  | res->store (2, indices); | 
|  | res->store (3, paths); | 
|  | res->store (4, isJava); | 
|  | delete lobjs; | 
|  | return res; | 
|  | } | 
|  |  | 
|  | Vector<int> * | 
|  | dbeGetLoadObjectState (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Vector<LoadObject*> *lobjs = dbeSession->get_text_segments (); | 
|  | int size = lobjs->size (); | 
|  |  | 
|  | // Initialize Java boolean array | 
|  | Vector<int> *states = new Vector<int>(size); | 
|  | char *lo_name; | 
|  |  | 
|  | // lobjectsNoJava is a trimmed list of indices provided to front-end skipping the Java | 
|  | // classes. lobjectsNoJava preserves the mapping of the index into the complete lobjs | 
|  | // vector. What front-end sees as lobj[i] is really lobj[lobjectsNoJava[i]]; | 
|  |  | 
|  | // This list is constructed every time GetLoadObjectList() or GetLoadObjectState() is | 
|  | // called. Possibility of further optimization by making it more persistent. | 
|  | // Only consumer of this list is dbeSetLoadObjectState | 
|  | int new_index = 0; | 
|  | if (dbev->lobjectsNoJava == NULL) | 
|  | dbev->lobjectsNoJava = new Vector<int>(1); | 
|  | else | 
|  | dbev->lobjectsNoJava->reset (); | 
|  |  | 
|  | // Get load object states | 
|  | int index; | 
|  | LoadObject *lo; | 
|  |  | 
|  | Vec_loop (LoadObject*, lobjs, index, lo) | 
|  | { | 
|  | // Set 0, 1, or 2 for show/hide/api | 
|  | lo_name = lo->get_name (); | 
|  | if (lo_name != NULL) | 
|  | { | 
|  | size_t len = strlen (lo_name); | 
|  | if (len > 7 && streq (lo_name + len - 7, NTXT (".class>"))) | 
|  | continue; | 
|  | } | 
|  | else | 
|  | dbev->lobjectsNoJava->append (index); | 
|  |  | 
|  | enum LibExpand expand = dbev->get_lo_expand (lo->seg_idx); | 
|  | states->store (new_index, (int) expand); | 
|  | new_index++; | 
|  | } | 
|  | delete lobjs; | 
|  | return states; | 
|  | } | 
|  |  | 
|  | // Set load object states | 
|  | void | 
|  | dbeSetLoadObjectState (int dbevindex, Vector<int> *selected) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Vector<LoadObject*> *lobjs = dbeSession->get_text_segments (); | 
|  |  | 
|  | int index; | 
|  | bool changed = false; | 
|  |  | 
|  | LoadObject *lo; | 
|  | int new_index = 0; | 
|  | dbev->setShowAll (); | 
|  | Vec_loop (LoadObject*, lobjs, index, lo) | 
|  | { | 
|  | if (dbev->lobjectsNoJava != NULL) | 
|  | { | 
|  | // This loadobject is a java class and was skipped | 
|  | if (dbev->lobjectsNoJava->fetch (new_index) != index) | 
|  | continue; | 
|  | } | 
|  | // Get array of settings | 
|  | enum LibExpand expand = (enum LibExpand) selected->fetch (new_index); | 
|  | if (expand == LIBEX_HIDE) | 
|  | { | 
|  | dbev->resetShowAll (); | 
|  | dbeSession->set_lib_visibility_used (); | 
|  | } | 
|  | changed = changed | dbev->set_libexpand (lo->get_pathname (), expand); | 
|  | new_index++; | 
|  | } | 
|  | delete lobjs; | 
|  | if (changed == true) | 
|  | { | 
|  | dbev->setShowHideChanged (); | 
|  | dbev->update_lo_expands (); | 
|  | } | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Reset load object states | 
|  | void | 
|  | dbeSetLoadObjectDefaults (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | dbev->set_libdefaults (); | 
|  | } | 
|  |  | 
|  | // Get  Machine model | 
|  | Vector<char*>* | 
|  | dbeGetCPUVerMachineModel (int dbevindex) | 
|  | { | 
|  | Vector<char*>* table = new Vector<char*>(); | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | char * mach_model = dbev->get_settings ()->get_machinemodel (); | 
|  | if (mach_model != NULL) | 
|  | { | 
|  | table->append (mach_model); | 
|  | return table; | 
|  | } | 
|  | int grsize = dbeSession->expGroups->size (); | 
|  | for (int j = 0; j < grsize; j++) | 
|  | { | 
|  | ExpGroup *gr = dbeSession->expGroups->fetch (j); | 
|  | Vector<Experiment*> *exps = gr->exps; | 
|  | for (int i = 0, sz = exps->size (); i < sz; i++) | 
|  | { | 
|  | Experiment *exp = exps->fetch (i); | 
|  | char *model = exp->machinemodel; | 
|  | if (model != NULL) | 
|  | table->append (dbe_strdup (model)); | 
|  | } | 
|  | } | 
|  | return table; | 
|  | } | 
|  |  | 
|  | // automatically load machine model if applicable | 
|  | void | 
|  | dbeDetectLoadMachineModel (int dbevindex) | 
|  | { | 
|  | if (dbeSession->is_datamode_available ()) | 
|  | { | 
|  | char *model = dbeGetMachineModel (); | 
|  | if (model == NULL) | 
|  | { | 
|  | Vector<char*>* models = dbeGetCPUVerMachineModel (dbevindex); | 
|  | char * machineModel = NTXT ("generic"); | 
|  | if (models->size () > 0) | 
|  | { | 
|  | machineModel = models->get (0); | 
|  | for (int i = 1; i < models->size (); i++) | 
|  | { | 
|  | if (strncmp (models->get (i), machineModel, strlen (machineModel)) == 0) | 
|  | { | 
|  | machineModel = NTXT ("generic"); | 
|  | break; | 
|  | } | 
|  | } | 
|  | dbeLoadMachineModel (machineModel); | 
|  | } | 
|  | delete models; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // Managing Memory Objects | 
|  | char * | 
|  | dbeDefineMemObj (char *name, char *index_expr, char *machinemodel, | 
|  | char *sdesc, char *ldesc) | 
|  | { | 
|  | return MemorySpace::mobj_define (name, index_expr, machinemodel, sdesc, ldesc); | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeDeleteMemObj (char *name) | 
|  | { | 
|  | return MemorySpace::mobj_delete (name); | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetMemObjects (int /*dbevindex*/) | 
|  | { | 
|  | Vector<void*> *res = MemorySpace::getMemObjects (); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | // Managing machine model | 
|  | char * | 
|  | dbeLoadMachineModel (char *name) | 
|  | { | 
|  | return dbeSession->load_mach_model (name); | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeGetMachineModel () | 
|  | { | 
|  | return dbeSession->get_mach_model (); | 
|  | } | 
|  |  | 
|  | Vector <char *> * | 
|  | dbeListMachineModels () | 
|  | { | 
|  | return dbeSession->list_mach_models (); | 
|  | } | 
|  |  | 
|  | // Managing Index Objects | 
|  | char * | 
|  | dbeDefineIndxObj (char *name, char *index_expr, char *sdesc, char *ldesc) | 
|  | { | 
|  | return dbeSession->indxobj_define (name, NULL, index_expr, sdesc, ldesc); | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetIndxObjDescriptions (int /*dbevindex*/) | 
|  | { | 
|  | Vector<void*> *res = dbeSession->getIndxObjDescriptions (); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetCustomIndxObjects (int /*dbevindex*/) | 
|  | { | 
|  | Vector<void*> *res = dbeSession->getCustomIndxObjects (); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | void | 
|  | dbeSetSelObj (int dbevindex, Obj sel_obj_or_ind, int type, int subtype) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Histable *sel_obj; | 
|  | Hist_data *data; | 
|  | int sel_ind = (int) sel_obj_or_ind; | 
|  |  | 
|  | switch (type) | 
|  | { | 
|  | case DSP_FUNCTION: | 
|  | data = dbev->func_data; | 
|  | break; | 
|  | case DSP_LINE: | 
|  | data = dbev->line_data; | 
|  | break; | 
|  | case DSP_PC: | 
|  | data = dbev->pc_data; | 
|  | break; | 
|  | case DSP_CALLER: | 
|  | data = dbev->callers; | 
|  | break; | 
|  | case DSP_CALLEE: | 
|  | data = dbev->callees; | 
|  | break; | 
|  | case DSP_SOURCE: | 
|  | data = dbev->src_data; | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | data = dbev->dis_data; | 
|  | break; | 
|  | case DSP_DLAYOUT: | 
|  | data = dbev->dlay_data; | 
|  | if (data == NULL) | 
|  | { | 
|  | dbev->sel_binctx = NULL; | 
|  | return; | 
|  | } | 
|  | if (sel_ind >= 0 && sel_ind < dbev->dlay_data->size ()) | 
|  | dbev->sel_dobj = dbev->dlay_data->fetch (sel_ind)->obj; | 
|  | return; | 
|  | case DSP_DATAOBJ: | 
|  | data = dbev->dobj_data; | 
|  | if (data == NULL) | 
|  | { | 
|  | dbev->sel_binctx = NULL; | 
|  | return; | 
|  | } | 
|  | if (sel_ind >= 0 && sel_ind < dbev->dobj_data->size ()) | 
|  | dbev->sel_dobj = dbev->dobj_data->fetch (sel_ind)->obj; | 
|  | return; | 
|  | case DSP_MEMOBJ: | 
|  | case DSP_INDXOBJ: | 
|  | dbev->set_indxobj_sel (subtype, sel_ind); | 
|  | sel_obj = dbev->get_indxobj_sel (subtype); | 
|  | if (sel_obj && sel_obj->get_type () == Histable::INDEXOBJ) | 
|  | dbev->set_sel_obj (((IndexObject*) sel_obj)->get_obj ()); | 
|  | return; | 
|  | case DSP_SOURCE_V2: | 
|  | case DSP_DISASM_V2: | 
|  | case DSP_TIMELINE: | 
|  | case DSP_LEAKLIST: | 
|  | case DSP_RACES: | 
|  | case DSP_DEADLOCKS: | 
|  | case DSP_DUALSOURCE: | 
|  | case DSP_SOURCE_DISASM: | 
|  | case DSP_IOACTIVITY: | 
|  | case DSP_IOVFD: | 
|  | case DSP_IOCALLSTACK: | 
|  | case DSP_HEAPCALLSTACK: | 
|  | case DSP_MINICALLER: | 
|  | dbev->set_sel_obj ((Histable *) sel_obj_or_ind); | 
|  | return; | 
|  | default: | 
|  | // abort(); | 
|  | return; | 
|  | } | 
|  | if (type != DSP_SOURCE && type != DSP_DISASM && type != DSP_SOURCE_V2 | 
|  | && type != DSP_DISASM_V2) | 
|  | dbev->sel_binctx = NULL; | 
|  |  | 
|  | if (data == NULL || data->get_status () != Hist_data::SUCCESS | 
|  | || sel_ind >= data->size ()) | 
|  | return; | 
|  |  | 
|  | if (sel_ind >= 0 && sel_ind < data->size ()) | 
|  | dbev->set_sel_obj (data->fetch (sel_ind)->obj); | 
|  | } | 
|  |  | 
|  | void | 
|  | dbeSetSelObjV2 (int dbevindex, uint64_t id) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | dbev->set_sel_obj (dbeSession->findObjectById (id)); | 
|  | } | 
|  |  | 
|  | Obj | 
|  | dbeGetSelObj (int dbevindex, int type, int subtype) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | Histable *sel_obj = NULL; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_FUNCTION: | 
|  | sel_obj = dbev->get_sel_obj (Histable::FUNCTION); | 
|  | break; | 
|  | case DSP_LINE: | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | sel_obj = dbev->get_sel_obj (Histable::LINE); | 
|  | break; | 
|  | case DSP_PC: | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | sel_obj = dbev->get_sel_obj (Histable::INSTR); | 
|  | break; | 
|  | case DSP_SRC_FILE: | 
|  | sel_obj = dbev->get_sel_obj (Histable::SOURCEFILE); | 
|  | break; | 
|  | case DSP_DATAOBJ: | 
|  | case DSP_DLAYOUT: | 
|  | if (dbev->sel_dobj) | 
|  | sel_obj = dbev->sel_dobj->convertto (Histable::DOBJECT); | 
|  | break; | 
|  | case DSP_MEMOBJ: | 
|  | case DSP_INDXOBJ: | 
|  | sel_obj = dbev->get_indxobj_sel (subtype); | 
|  | break; | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | Dprintf (DEBUG_DBE, NTXT ("### dbeGetSelObj: Dbe.cc:%d %s (%d) returns %s\n"), | 
|  | __LINE__, dsp_type_to_string (type), type, sel_obj ? sel_obj->dump () : "NULL"); | 
|  | return (Obj) sel_obj; | 
|  | } | 
|  |  | 
|  | Obj | 
|  | dbeConvertSelObj (Obj obj, int type) | 
|  | { | 
|  | Histable *sel_obj = (Histable *) obj; | 
|  | Dprintf (DEBUG_DBE, NTXT ("### dbeConvertSelObj: Dbe.cc:%d %s (%d) sel_obj=%s\n"), | 
|  | __LINE__, dsp_type_to_string (type), type, sel_obj ? sel_obj->dump () | 
|  | : "NULL"); | 
|  | if (sel_obj == NULL) | 
|  | return (Obj) NULL; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_FUNCTION: | 
|  | return (Obj) sel_obj->convertto (Histable::FUNCTION); | 
|  | case DSP_LINE: | 
|  | return (Obj) sel_obj->convertto (Histable::LINE); | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | { | 
|  | SourceFile* srcCtx = NULL; | 
|  | if (sel_obj->get_type () == Histable::INSTR) | 
|  | { | 
|  | DbeInstr* dbei = (DbeInstr *) sel_obj; | 
|  | srcCtx = (SourceFile*) dbei->convertto (Histable::SOURCEFILE); | 
|  | } | 
|  | else if (sel_obj->get_type () == Histable::LINE) | 
|  | { | 
|  | DbeLine * dbel = (DbeLine *) sel_obj; | 
|  | srcCtx = dbel->sourceFile; | 
|  | } | 
|  | sel_obj = sel_obj->convertto (Histable::LINE, srcCtx); | 
|  | Dprintf (DEBUG_DBE, NTXT ("### dbeConvertSelObj: Dbe.cc:%d %s (%d) returns %s\n"), | 
|  | __LINE__, dsp_type_to_string (type), type, sel_obj ? sel_obj->dump () : "NULL"); | 
|  | if (sel_obj && sel_obj->get_type () == Histable::LINE) | 
|  | { | 
|  | DbeLine * dbel = (DbeLine *) sel_obj; | 
|  | return (Obj) dbel->dbeline_base; | 
|  | } | 
|  | return (Obj) sel_obj->convertto (Histable::LINE, srcCtx); | 
|  | } | 
|  | case DSP_PC: | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | return (Obj) sel_obj->convertto (Histable::INSTR); | 
|  | case DSP_SRC_FILE: | 
|  | return (Obj) sel_obj->convertto (Histable::SOURCEFILE); | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | return (Obj) NULL; | 
|  | } | 
|  |  | 
|  | uint64_t | 
|  | dbeGetSelObjV2 (int dbevindex, char *typeStr) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Histable *obj = NULL; | 
|  | if (typeStr != NULL) | 
|  | { | 
|  | if (streq (typeStr, NTXT ("FUNCTION"))) | 
|  | obj = dbev->get_sel_obj (Histable::FUNCTION); | 
|  | else if (streq (typeStr, NTXT ("INSTRUCTION"))) | 
|  | obj = dbev->get_sel_obj (Histable::INSTR); | 
|  | else if (streq (typeStr, NTXT ("SOURCELINE"))) | 
|  | obj = dbev->get_sel_obj (Histable::LINE); | 
|  | else if (streq (typeStr, NTXT ("SOURCEFILE"))) | 
|  | obj = dbev->get_sel_obj (Histable::SOURCEFILE); | 
|  | } | 
|  | Dprintf (DEBUG_DBE, NTXT ("### dbeGetSelObjV2: Dbe.cc:%d %s returns %s\n"), | 
|  | __LINE__, STR (typeStr), obj ? obj->dump () : "NULL"); | 
|  | return obj != NULL ? obj->id : (uint64_t) - 1; | 
|  | } | 
|  |  | 
|  | Vector<uint64_t> * | 
|  | dbeGetSelObjsIO (int dbevindex, Vector<uint64_t> *ids, int type) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Vector<uint64_t> *res = NULL; | 
|  | Vector<uint64_t> *result = new Vector<uint64_t>(); | 
|  | for (int i = 0; i < ids->size (); i++) | 
|  | { | 
|  | res = dbeGetSelObjIO (dbevindex, ids->fetch (i), type); | 
|  | if (res != NULL) | 
|  | { | 
|  | result->addAll (res); | 
|  | delete res; | 
|  | } | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | Vector<uint64_t> * | 
|  | dbeGetSelObjIO (int dbevindex, uint64_t id, int type) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Histable *obj = NULL; | 
|  | Vector<uint64_t> *res = NULL; | 
|  | int size = 0; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_IOACTIVITY: | 
|  | obj = dbev->get_sel_obj_io (id, Histable::IOACTFILE); | 
|  | size = obj != NULL ? ((FileData*) obj)->getVirtualFds ()->size () : 0; | 
|  | if (size) | 
|  | { | 
|  | res = new Vector<uint64_t>(); | 
|  | Vector<int64_t> *vfds = ((FileData*) obj)->getVirtualFds (); | 
|  | for (int i = 0; i < size; i++) | 
|  | res->append (vfds->fetch (i)); | 
|  | } | 
|  | break; | 
|  | case DSP_IOVFD: | 
|  | obj = dbev->get_sel_obj_io (id, Histable::IOACTVFD); | 
|  | if (obj) | 
|  | { | 
|  | res = new Vector<uint64_t>(); | 
|  | res->append (obj->id); | 
|  | } | 
|  | break; | 
|  | case DSP_IOCALLSTACK: | 
|  | obj = dbev->get_sel_obj_io (id, Histable::IOCALLSTACK); | 
|  | if (obj) | 
|  | { | 
|  | Vector<Obj> *instrs = dbeGetStackPCs (dbevindex, obj->id); | 
|  | if (instrs == NULL) | 
|  | return NULL; | 
|  | int stsize = instrs->size (); | 
|  | res = new Vector<uint64_t>(stsize); | 
|  | for (int i = 0; i < stsize; i++) | 
|  | { | 
|  | Histable *objFunc = (DbeInstr*) (instrs->fetch (i)); | 
|  | if (objFunc->get_type () != Histable::LINE) | 
|  | { | 
|  | objFunc = objFunc->convertto (Histable::FUNCTION); | 
|  | res->insert (0, objFunc->id); | 
|  | } | 
|  | } | 
|  | delete instrs; | 
|  | } | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | uint64_t | 
|  | dbeGetSelObjHeapTimestamp (int dbevindex, uint64_t id) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Histable *obj = NULL; | 
|  | uint64_t res = 0; | 
|  | Vector<uint64_t> *peakStackIds; | 
|  | Vector<hrtime_t> *peakTimestamps; | 
|  |  | 
|  | // Find and return the timestamp for the peak | 
|  | bool foundPeakId = false; | 
|  | if (id > 0) | 
|  | { | 
|  | obj = dbev->get_sel_obj_heap (0); | 
|  | if (obj != NULL) | 
|  | { | 
|  | peakStackIds = ((HeapData*) obj)->getPeakStackIds (); | 
|  | peakTimestamps = ((HeapData*) obj)->getPeakTimestamps (); | 
|  | for (int i = 0; i < peakStackIds->size (); i++) | 
|  | { | 
|  | if (id == peakStackIds->fetch (i)) | 
|  | { | 
|  | res = peakTimestamps->fetch (i); | 
|  | foundPeakId = true; | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // Return the first timestamp for the peak | 
|  | // if the callstack id is zero or it | 
|  | // doesn't match with the peak stack id | 
|  | if (id == 0 || !foundPeakId) | 
|  | { | 
|  | obj = dbev->get_sel_obj_heap (0); | 
|  | res = obj != NULL ? ((HeapData*) obj)->getPeakTimestamps ()->fetch (0) : 0; | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | int | 
|  | dbeGetSelObjHeapUserExpId (int dbevindex, uint64_t id) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Histable *obj = NULL; | 
|  | int res = 0; | 
|  | obj = dbev->get_sel_obj_heap (id); | 
|  | res = obj != NULL ? ((HeapData*) obj)->getUserExpId () : 0; | 
|  | return res; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get index of selected function/object | 
|  | // | 
|  | int | 
|  | dbeGetSelIndex (int dbevindex, Obj sel_obj, int type, int subtype) | 
|  | { | 
|  | Hist_data *data; | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | switch (type) | 
|  | { | 
|  | case DSP_FUNCTION: | 
|  | data = dbev->func_data; | 
|  | break; | 
|  | case DSP_LINE: | 
|  | data = dbev->line_data; | 
|  | break; | 
|  | case DSP_PC: | 
|  | data = dbev->pc_data; | 
|  | break; | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | data = dbev->src_data; | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | data = dbev->dis_data; | 
|  | break; | 
|  | case DSP_DLAYOUT: | 
|  | data = dbev->dlay_data; | 
|  | break; | 
|  | case DSP_DATAOBJ: | 
|  | data = dbev->dobj_data; | 
|  | break; | 
|  | case DSP_MEMOBJ: | 
|  | case DSP_INDXOBJ: | 
|  | data = dbev->get_indxobj_data (subtype); | 
|  | break; | 
|  | default: | 
|  | data = NULL; | 
|  | break; | 
|  | } | 
|  | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | 
|  | return -1; | 
|  |  | 
|  | Histable *chk_obj = (Histable *) sel_obj; | 
|  | Vector<Hist_data::HistItem*> *histItems = data->get_hist_items (); | 
|  | if (histItems == NULL || chk_obj == NULL) | 
|  | return -1; | 
|  | for (int i = 0, sz = histItems->size (); i < sz; i++) | 
|  | { | 
|  | if (histItems->get (i)->obj == chk_obj) | 
|  | return i; | 
|  | if (histItems->get (i)->obj == NULL) | 
|  | continue; | 
|  | if (histItems->get (i)->obj->get_type () == Histable::LINE | 
|  | && chk_obj->get_type () == Histable::LINE) | 
|  | { | 
|  | if (((DbeLine*) histItems->get (i)->obj)->convertto (Histable::FUNCTION) | 
|  | == ((DbeLine*) chk_obj)->convertto (Histable::FUNCTION) | 
|  | && ((DbeLine*) histItems->get (i)->obj)->lineno | 
|  | == ((DbeLine*) chk_obj)->lineno) | 
|  | return i; | 
|  | } | 
|  | else if (histItems->get (i)->obj->get_type () == Histable::INSTR | 
|  | && chk_obj->get_type () == Histable::INSTR) | 
|  | if (((DbeInstr*) histItems->get (i)->obj)->convertto (Histable::FUNCTION) | 
|  | == ((DbeInstr*) chk_obj)->convertto (Histable::FUNCTION) | 
|  | && ((DbeInstr*) histItems->get (i)->obj)->addr | 
|  | == ((DbeInstr*) chk_obj)->addr) | 
|  | return i; | 
|  | } | 
|  |  | 
|  | Histable *chk_obj1 = NULL; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_FUNCTION: | 
|  | chk_obj1 = chk_obj->convertto (Histable::FUNCTION); | 
|  | break; | 
|  | case DSP_LINE: | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | chk_obj1 = chk_obj->convertto (Histable::LINE); | 
|  | break; | 
|  | case DSP_PC: | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | chk_obj1 = chk_obj->convertto (Histable::INSTR); | 
|  | break; | 
|  | } | 
|  | if (chk_obj1 && chk_obj != chk_obj1) | 
|  | for (int i = 0, sz = histItems->size (); i < sz; i++) | 
|  | if (histItems->get (i)->obj == chk_obj1) | 
|  | return i; | 
|  |  | 
|  | if (type == DSP_LINE) | 
|  | { | 
|  | for (int i = 0, sz = histItems->size (); i < sz; i++) | 
|  | if (histItems->get (i)->obj != NULL | 
|  | && chk_obj->convertto (Histable::FUNCTION) | 
|  | == histItems->get (i)->obj->convertto (Histable::FUNCTION)) | 
|  | return i; | 
|  | } | 
|  | else if (type == DSP_PC) | 
|  | { | 
|  | for (int i = 0, sz = histItems->size (); i < sz; i++) | 
|  | if (histItems->get (i)->obj != NULL | 
|  | && (histItems->get (i)->obj)->convertto (Histable::FUNCTION) | 
|  | == (chk_obj)->convertto (Histable::FUNCTION) | 
|  | && ((DbeLine*) histItems->get (i)->obj->convertto (Histable::LINE))->lineno | 
|  | == ((DbeLine*) chk_obj->convertto (Histable::LINE))->lineno) | 
|  | return i; | 
|  | for (int i = 0, sz = histItems->size (); i < sz; i++) | 
|  | if (histItems->get (i)->obj != NULL | 
|  | && (histItems->get (i)->obj)->convertto (Histable::FUNCTION) | 
|  | == (chk_obj)->convertto (Histable::FUNCTION)) | 
|  | return i; | 
|  | } | 
|  |  | 
|  | // If we clicked on an mfunction line in the called-by call mini in user mode for omp | 
|  | // we might not find that function in func data | 
|  | if (dbev->isOmpDisMode () && type == DSP_FUNCTION) | 
|  | { | 
|  | int p = dbeGetSelIndex (dbevindex, sel_obj, DSP_DISASM, subtype); | 
|  | if (p != -1) | 
|  | return p; | 
|  | } | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | // Print data | 
|  | // | 
|  | char * | 
|  | dbePrintData (int dbevindex, int type, int subtype, char *printer, | 
|  | char *fname, FILE *outfile) | 
|  | { | 
|  | Histable *current_obj; | 
|  | Function *func; | 
|  | Module *module; | 
|  | MetricList *mlist_orig; | 
|  | bool header; | 
|  | Print_params params; | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  |  | 
|  | // Set print parameters | 
|  | if (printer != NULL) | 
|  | { | 
|  | params.dest = DEST_PRINTER; | 
|  | params.name = printer; | 
|  | } | 
|  | else if (outfile != NULL) | 
|  | { | 
|  | params.dest = DEST_OPEN_FILE; | 
|  | params.openfile = outfile; | 
|  | params.name = NULL; | 
|  | } | 
|  | else | 
|  | { | 
|  | params.dest = DEST_FILE; | 
|  | params.name = fname; | 
|  | if (*(params.name) == '\0') | 
|  | { | 
|  | free (params.name); | 
|  | return dbe_strdup (GTXT ("Please enter the name of the file to which to print")); | 
|  | } | 
|  | } | 
|  | params.ncopies = 1; | 
|  | if (outfile != NULL) | 
|  | header = false; | 
|  | else | 
|  | header = !(type == DSP_SOURCE || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2); | 
|  |  | 
|  | params.header = header; | 
|  |  | 
|  | // figure out what kind of metrics to use | 
|  | if (type == DSP_SELF || type == DSP_CALLER || type == DSP_CALLEE | 
|  | || type == DSP_CALLTREE) | 
|  | mlist_orig = dbev->get_metric_list (MET_CALL); | 
|  | else if (type == DSP_DATAOBJ || type == DSP_DLAYOUT || type == DSP_MEMOBJ) | 
|  | mlist_orig = dbev->get_metric_list (MET_DATA); | 
|  | else if (type == DSP_INDXOBJ) | 
|  | mlist_orig = dbev->get_metric_list (MET_INDX); | 
|  | else if (type == DSP_IOACTIVITY || type == DSP_IOVFD | 
|  | || type == DSP_IOCALLSTACK) | 
|  | mlist_orig = dbev->get_metric_list (MET_IO); | 
|  | else if (type == DSP_HEAPCALLSTACK) | 
|  | mlist_orig = dbev->get_metric_list (MET_HEAP); | 
|  | else | 
|  | mlist_orig = dbev->get_metric_list (MET_NORMAL); | 
|  |  | 
|  | // make a compacted version of the input list | 
|  | // the list will either be moved to the generated data, | 
|  | //   or freed below if it wasn't needed | 
|  | MetricList *mlist = new MetricList (mlist_orig); | 
|  | Hist_data *data = NULL; | 
|  | er_print_common_display *cd = NULL; | 
|  | int ix; | 
|  | // Set data | 
|  | switch (type) | 
|  | { | 
|  | case DSP_FUNCTION: | 
|  | case DSP_LINE: | 
|  | case DSP_PC: | 
|  | case DSP_MEMOBJ: | 
|  | case DSP_INDXOBJ: | 
|  | case DSP_DATAOBJ: | 
|  | data = dbev->get_hist_data (mlist, | 
|  | ((type == DSP_FUNCTION) ? Histable::FUNCTION : | 
|  | (type == DSP_LINE) ? Histable::LINE : | 
|  | (type == DSP_PC) ? Histable::INSTR : | 
|  | (type == DSP_INDXOBJ) ? Histable::INDEXOBJ : | 
|  | (type == DSP_MEMOBJ) ? Histable::MEMOBJ | 
|  | : Histable::DOBJECT), | 
|  | subtype, Hist_data::ALL); | 
|  | if (data->get_status () != Hist_data::SUCCESS) | 
|  | return DbeView::status_str (DbeView::DBEVIEW_NO_DATA); // no strdup() | 
|  |  | 
|  | cd = new er_print_histogram (dbev, data, mlist, MODE_LIST, | 
|  | dbev->get_limit (), | 
|  | mlist->get_sort_name (), NULL, true, true); | 
|  | break; | 
|  | case DSP_DLAYOUT: | 
|  | { | 
|  | data = dbev->get_hist_data (mlist, Histable::DOBJECT, 0, Hist_data::LAYOUT); | 
|  | if (data->get_status () != Hist_data::SUCCESS) | 
|  | return DbeView::status_str (DbeView::DBEVIEW_NO_DATA); // no strdup() | 
|  | cd = new er_print_histogram (dbev, data, mlist, MODE_ANNOTATED, | 
|  | dbev->get_thresh_dis (), | 
|  | mlist->get_sort_name (), NULL, true, true); | 
|  | break; | 
|  | } | 
|  |  | 
|  | // source and disassembly | 
|  | case DSP_SOURCE: | 
|  | case DSP_DISASM: | 
|  | case DSP_SOURCE_V2: | 
|  | case DSP_DISASM_V2: | 
|  | if (dbev->sel_obj == NULL) | 
|  | return NULL; | 
|  | current_obj = dbev->sel_obj->convertto (Histable::FUNCTION); | 
|  | if (current_obj->get_type () != Histable::FUNCTION) | 
|  | return dbe_strdup (GTXT ("Not a real function; no source or disassembly available.")); | 
|  | func = (Function*) current_obj->convertto (Histable::FUNCTION); | 
|  | if (func->flags & FUNC_FLAG_SIMULATED) | 
|  | return dbe_strdup (GTXT ("Not a real function; no source or disassembly available.")); | 
|  | if (func->get_name () == NULL) | 
|  | return dbe_strdup (GTXT ("Source location not recorded in experiment")); | 
|  | module = func->module; | 
|  | if (module == NULL || module->get_name () == NULL) | 
|  | return dbe_strdup (GTXT ("Object name not recorded in experiment")); | 
|  | ix = module->loadobject->seg_idx; | 
|  | if (dbev->get_lo_expand (ix) == LIBEX_HIDE) | 
|  | return dbe_strdup (GTXT ("No source or disassembly available for hidden object")); | 
|  | cd = new er_print_histogram (dbev, dbev->func_data, mlist, MODE_ANNOTATED, | 
|  | type == DSP_DISASM || type == DSP_DISASM_V2, | 
|  | mlist->get_sort_name (), | 
|  | func, false, false); | 
|  | break; | 
|  |  | 
|  | // callers-callees | 
|  | case DSP_SELF: | 
|  | case DSP_CALLER: | 
|  | case DSP_CALLEE: | 
|  | if (dbev->sel_obj == NULL) | 
|  | return NULL; | 
|  | current_obj = dbev->sel_obj->convertto (Histable::FUNCTION); | 
|  | cd = new er_print_histogram (dbev, dbev->func_data, mlist, MODE_GPROF, 1, | 
|  | mlist->get_sort_name (), current_obj, | 
|  | false, false); | 
|  | break; | 
|  |  | 
|  | // statistics; this won't use the metric list copied above, so delete it | 
|  | case DSP_STATIS: | 
|  | cd = new er_print_experiment (dbev, 0, dbeSession->nexps () - 1, | 
|  | true, true, true, true, false); | 
|  | delete mlist; | 
|  | break; | 
|  | case DSP_EXP: | 
|  | cd = new er_print_experiment (dbev, 0, dbeSession->nexps () - 1, | 
|  | true, true, false, false, false); | 
|  | delete mlist; | 
|  | break; | 
|  | case DSP_LEAKLIST: | 
|  | cd = new er_print_leaklist (dbev, true, true, dbev->get_limit ()); | 
|  | delete mlist; | 
|  | break; | 
|  | case DSP_HEAPCALLSTACK: | 
|  | cd = new er_print_heapactivity (dbev, Histable::HEAPCALLSTACK, false, | 
|  | dbev->get_limit ()); | 
|  | delete mlist; | 
|  | break; | 
|  | case DSP_IOACTIVITY: | 
|  | cd = new er_print_ioactivity (dbev, Histable::IOACTFILE, false, | 
|  | dbev->get_limit ()); | 
|  | delete mlist; | 
|  | break; | 
|  | case DSP_IOVFD: | 
|  | cd = new er_print_ioactivity (dbev, Histable::IOACTVFD, false, | 
|  | dbev->get_limit ()); | 
|  | delete mlist; | 
|  | break; | 
|  |  | 
|  | // the io call stack | 
|  | case DSP_IOCALLSTACK: | 
|  | cd = new er_print_ioactivity (dbev, Histable::IOCALLSTACK, false, | 
|  | dbev->get_limit ()); | 
|  | delete mlist; | 
|  | break; | 
|  |  | 
|  | // some unknown panel -- return an error string | 
|  | default: | 
|  | delete mlist; | 
|  | return dbe_strdup (GTXT ("Print not available")); | 
|  | } | 
|  |  | 
|  | // Start printing | 
|  | char *buf = NULL; | 
|  |  | 
|  | // first open the file/device/whatever | 
|  | if (cd->open (¶ms) == 0) | 
|  | { | 
|  | // now call the actual print routine | 
|  | cd->data_dump (); | 
|  | if (params.dest == DEST_PRINTER) | 
|  | { | 
|  | if (streq ((char *) params.name, NTXT ("-"))) | 
|  | { | 
|  | // Special case - return report to the GUI | 
|  | int maxbytes = 2 * 1024 * 1024; // IPC large buffer limit | 
|  | char *report = cd->get_output (maxbytes); | 
|  | delete data; | 
|  | delete cd; | 
|  | return report; // TEMPORARY | 
|  | } | 
|  | } | 
|  | if (cd->print_output () == false) | 
|  | buf = dbe_sprintf (NTXT ("%s: %s"), | 
|  | GTXT ("Unable to submit print request to"), | 
|  | params.name); | 
|  | } | 
|  | else | 
|  | // if unable to set up the print, return an error | 
|  | buf = dbe_sprintf (NTXT ("%s: %s"), | 
|  | GTXT ("Unable to open file"), | 
|  | params.name); | 
|  |  | 
|  | // dbe_free((void *) params.name); XXX when should this happen? | 
|  | if (data) | 
|  | if (data->isViewOwned () == false) | 
|  | delete data; | 
|  | delete cd; | 
|  | return buf; | 
|  | } | 
|  |  | 
|  | // Set limit for print data | 
|  | // | 
|  | char * | 
|  | dbeSetPrintLimit (int dbevindex, int limit) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | return (dbev->set_limit (limit)); | 
|  | } | 
|  |  | 
|  | // get limit for print data | 
|  | int | 
|  | dbeGetPrintLimit (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | int limit = dbev->get_limit (); | 
|  | return limit; | 
|  | } | 
|  |  | 
|  | // set printmode for data | 
|  | char * | 
|  | dbeSetPrintMode (int dbevindex, char * pmode) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | char *r = dbev->set_printmode (pmode); | 
|  | return r; | 
|  | } | 
|  |  | 
|  | // get printmode for data | 
|  | int | 
|  | dbeGetPrintMode (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | return (dbev->get_printmode ()); | 
|  | } | 
|  |  | 
|  | // get printmode for data | 
|  | char * | 
|  | dbeGetPrintModeString (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | return ( dbev->get_printmode_str ()); | 
|  | } | 
|  |  | 
|  | // get print delimiter for csv data | 
|  | char | 
|  | dbeGetPrintDelim (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | return (dbev->get_printdelimiter ()); | 
|  | } | 
|  |  | 
|  | // Set Source/Object/Load-Object file names | 
|  | static void | 
|  | set_file_names (Function *func, char *names[3]) | 
|  | { | 
|  | Module *module = func->module; | 
|  | LoadObject *loadobject = module->loadobject; | 
|  | if (loadobject == NULL) | 
|  | loadobject = dbeSession->get_Unknown_LoadObject (); | 
|  | free (names[0]); | 
|  | free (names[1]); | 
|  | free (names[2]); | 
|  | SourceFile *sf = func->getDefSrc (); | 
|  | char *src_name = sf->dbeFile->get_location_info (); | 
|  | DbeFile *df = module->dbeFile; | 
|  | if (df == NULL || (df->filetype & DbeFile::F_JAVACLASS) == 0) | 
|  | df = module->loadobject->dbeFile; | 
|  | char *lo_name = df->get_location_info (); | 
|  | char *dot_o_name = lo_name; | 
|  | if (module->dot_o_file) | 
|  | dot_o_name = module->dot_o_file->dbeFile->get_location_info (); | 
|  | names[0] = dbe_sprintf (NTXT ("%s: %s"), GTXT ("Source File"), src_name); | 
|  | names[1] = dbe_sprintf (NTXT ("%s: %s"), GTXT ("Object File"), dot_o_name); | 
|  | names[2] = dbe_sprintf (NTXT ("%s: %s"), GTXT ("Load Object"), lo_name); | 
|  | } | 
|  |  | 
|  | // dbeSetFuncData | 
|  | //	Master function to generate all Tab data for the analyzer | 
|  | //	Returns the index of the selected item in the specified list | 
|  | // | 
|  | // After calling it to set up, the Analyzer calls dbeGetFuncList | 
|  | //	to format the generated data and return the table | 
|  | //	Most of the data is destined for a JTable | 
|  | // | 
|  | int | 
|  | dbeSetFuncData (int dbevindex, Obj sel_obj, int type, int subtype) | 
|  | { | 
|  | MetricList *_mlist; | 
|  | Histable *org_obj; | 
|  | Hist_data *data = NULL; | 
|  | int index, sel_index; | 
|  | Function *func; | 
|  | char *name; | 
|  | int ix; | 
|  |  | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | sel_index = -1; | 
|  | dbev->resetOmpDisMode (); | 
|  | dbev->error_msg = dbev->warning_msg = NULL; | 
|  |  | 
|  | // get metric list, make a compact duplicate | 
|  | _mlist = dbev->get_metric_list (MET_NORMAL); | 
|  | MetricList *mlist = new MetricList (_mlist); | 
|  |  | 
|  | // Remove old function/obj list data & Get new function/obj list data | 
|  | org_obj = (Histable *) sel_obj; | 
|  |  | 
|  | // Figure out which "function" data is being asked for, i.e., | 
|  | //	which of the analyzer displays is asking for data | 
|  | switch (type) | 
|  | { | 
|  | // the various tables: functions, lines, PCs, DataObjects, IndexObjects | 
|  | case DSP_FUNCTION: | 
|  | case DSP_LINE: | 
|  | case DSP_PC: | 
|  | case DSP_DATAOBJ: | 
|  | case DSP_MEMOBJ: | 
|  | case DSP_INDXOBJ: | 
|  | switch (type) | 
|  | { | 
|  | case DSP_FUNCTION: | 
|  | if (dbev->func_data) | 
|  | delete dbev->func_data; | 
|  | dbev->func_data = data = dbev->get_hist_data (mlist, | 
|  | Histable::FUNCTION, subtype, Hist_data::ALL); | 
|  | break; | 
|  | case DSP_LINE: | 
|  | if (dbev->line_data) | 
|  | delete dbev->line_data; | 
|  | dbev->line_data = data = dbev->get_hist_data (mlist, | 
|  | Histable::LINE, subtype, Hist_data::ALL); | 
|  | break; | 
|  | case DSP_PC: | 
|  | if (dbev->pc_data) | 
|  | delete dbev->pc_data; | 
|  | dbev->pc_data = data = dbev->get_hist_data (mlist, | 
|  | Histable::INSTR, subtype, Hist_data::ALL); | 
|  | break; | 
|  | case DSP_DATAOBJ: | 
|  | if (dbev->dobj_data) | 
|  | delete dbev->dobj_data; | 
|  | mlist = dbev->get_metric_list (MET_DATA); | 
|  | dbev->dobj_data = data = dbev->get_hist_data (mlist, | 
|  | Histable::DOBJECT, subtype, Hist_data::ALL); | 
|  | break; | 
|  | case DSP_MEMOBJ: | 
|  | mlist = dbev->get_metric_list (MET_DATA); | 
|  | data = dbev->get_hist_data (mlist, Histable::MEMOBJ, subtype, | 
|  | Hist_data::ALL); | 
|  | dbev->indx_data->store (subtype, data); | 
|  | break; | 
|  | case DSP_INDXOBJ: | 
|  | mlist = dbev->get_metric_list (MET_INDX); | 
|  | data = dbev->get_hist_data (mlist, Histable::INDEXOBJ, subtype, | 
|  | Hist_data::ALL); | 
|  | dbev->indx_data->store (subtype, data); | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  |  | 
|  | // Set the selection of row item | 
|  | if (data->get_status () == Hist_data::SUCCESS) | 
|  | { | 
|  | // otherwise, look for it | 
|  | sel_index = -1; | 
|  | if (org_obj) | 
|  | { | 
|  | Hist_data::HistItem *hi; | 
|  | Vec_loop (Hist_data::HistItem*, data->get_hist_items (), index, hi) | 
|  | { | 
|  | if (hi->obj == org_obj) | 
|  | { | 
|  | sel_index = index; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (sel_index == -1 && (type == DSP_LINE || type == DSP_PC)) | 
|  | { | 
|  | Vec_loop (Hist_data::HistItem*, data->get_hist_items (), index, hi) | 
|  | { | 
|  | name = hi->obj->get_name (); | 
|  | if (strcmp (name, NTXT ("<Total>")) && | 
|  | strcmp (name, GTXT ("<Unknown>"))) | 
|  | { | 
|  | int done = 0; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_LINE: | 
|  | if (org_obj->convertto (Histable::FUNCTION) | 
|  | == hi->obj->convertto (Histable::FUNCTION)) | 
|  | { | 
|  | sel_index = index; | 
|  | done = 1; | 
|  | } | 
|  | break; | 
|  | case DSP_PC: | 
|  | if (hi->obj->convertto (Histable::FUNCTION) | 
|  | == org_obj->convertto (Histable::FUNCTION) | 
|  | && ((DbeLine*) hi->obj->convertto (Histable::LINE))->lineno | 
|  | == ((DbeLine*) org_obj->convertto (Histable::LINE))->lineno) | 
|  | { | 
|  | sel_index = index; | 
|  | done = 1; | 
|  | } | 
|  | break; | 
|  | } | 
|  | if (done) | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | if (sel_index == -1 && type == DSP_PC) | 
|  | { | 
|  | Vec_loop (Hist_data::HistItem*, data->get_hist_items (), index, hi) | 
|  | { | 
|  | name = hi->obj->get_name (); | 
|  | if (strcmp (name, NTXT ("<Total>")) && | 
|  | strcmp (name, GTXT ("<Unknown>"))) | 
|  | { | 
|  | int done = 0; | 
|  | if (hi->obj->convertto (Histable::FUNCTION) == | 
|  | org_obj->convertto (Histable::FUNCTION)) | 
|  | { | 
|  | sel_index = index; | 
|  | done = 1; | 
|  | } | 
|  | if (done) | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | if (sel_index == -1) | 
|  | { | 
|  | Hist_data::HistItem *hi; | 
|  | Vec_loop (Hist_data::HistItem*, data->get_hist_items (), index, hi) | 
|  | { | 
|  | name = hi->obj->get_name (); | 
|  | if (strcmp (name, NTXT ("<Total>")) && | 
|  | strcmp (name, GTXT ("<Unknown>"))) | 
|  | { | 
|  | sel_index = index; | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | else | 
|  | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA); | 
|  | return sel_index; | 
|  | // the end of the code for the regular tables | 
|  |  | 
|  | // Data Layout | 
|  | case DSP_DLAYOUT: | 
|  | if (dbev->dlay_data) | 
|  | delete dbev->dlay_data; | 
|  | dbev->marks->reset (); | 
|  | mlist = dbev->get_metric_list (MET_DATA); | 
|  |  | 
|  | // initial dobj list ... | 
|  | data = dbev->get_hist_data (mlist, Histable::DOBJECT, subtype, | 
|  | Hist_data::LAYOUT); | 
|  | // .. provides metric data for layout | 
|  | dbev->dlay_data = data = dbev->get_data_space ()->get_layout_data (data, | 
|  | dbev->marks, dbev->get_thresh_dis ()); | 
|  | if (data->get_status () != Hist_data::SUCCESS) | 
|  | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA); | 
|  | return sel_index; | 
|  |  | 
|  | // Source or disassembly | 
|  | case DSP_SOURCE_V2: | 
|  | case DSP_DISASM_V2: | 
|  | case DSP_SOURCE: | 
|  | case DSP_DISASM: | 
|  | { | 
|  | if (org_obj == NULL) | 
|  | { | 
|  | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_SEL_OBJ); | 
|  | return sel_index; | 
|  | } | 
|  | if (org_obj->get_type () != Histable::FUNCTION) | 
|  | { | 
|  | dbev->error_msg = dbe_strdup ( | 
|  | GTXT ("Not a real function; no source or disassembly available.")); | 
|  | return sel_index; | 
|  | } | 
|  | func = (Function *) org_obj; | 
|  | if (func->flags & FUNC_FLAG_SIMULATED) | 
|  | { | 
|  | dbev->error_msg = dbe_strdup ( | 
|  | GTXT ("Not a real function; no source or disassembly available.")); | 
|  | return sel_index; | 
|  | } | 
|  | if (func->get_name () == NULL) | 
|  | { | 
|  | dbev->error_msg = dbe_strdup ( | 
|  | GTXT ("Source location not recorded in experiment")); | 
|  | return sel_index; | 
|  | } | 
|  | Module *module = func->module; | 
|  | if ((module == NULL) || (module->get_name () == NULL)) | 
|  | { | 
|  | dbev->error_msg = dbe_strdup ( | 
|  | GTXT ("Object name not recorded in experiment")); | 
|  | return sel_index; | 
|  | } | 
|  | ix = module->loadobject->seg_idx; | 
|  | if (dbev->get_lo_expand (ix) == LIBEX_HIDE) | 
|  | { | 
|  | dbev->error_msg = dbe_strdup ( | 
|  | GTXT ("No source or disassembly available for hidden object")); | 
|  | return sel_index; | 
|  | } | 
|  |  | 
|  | if ((type == DSP_DISASM || type == DSP_DISASM_V2) | 
|  | && dbev->get_view_mode () == VMODE_USER | 
|  | && dbeSession->is_omp_available ()) | 
|  | dbev->setOmpDisMode (); | 
|  |  | 
|  | dbev->marks->reset (); | 
|  | SourceFile *srcContext = NULL; | 
|  | switch (dbev->sel_obj->get_type ()) | 
|  | { | 
|  | case Histable::FUNCTION: | 
|  | { | 
|  | Function *f = (Function *) dbev->sel_obj; | 
|  | srcContext = f->getDefSrc (); | 
|  | dbev->sel_binctx = f->module; | 
|  | break; | 
|  | } | 
|  | case Histable::LINE: | 
|  | { | 
|  | DbeLine *dl = (DbeLine *) dbev->sel_obj; | 
|  | srcContext = dl->sourceFile; | 
|  | Function *f = dl->func; | 
|  | if (f) | 
|  | dbev->sel_binctx = f; | 
|  | break; | 
|  | } | 
|  | case Histable::INSTR: | 
|  | { | 
|  | Function *f = (Function *) dbev->sel_obj->convertto (Histable::FUNCTION); | 
|  | if (f) | 
|  | { | 
|  | dbev->sel_binctx = f; | 
|  | srcContext = f->getDefSrc (); | 
|  | } | 
|  | break; | 
|  | } | 
|  | default: | 
|  | break; | 
|  | } | 
|  | mlist = dbev->get_metric_list (MET_SRCDIS); | 
|  |  | 
|  | // for source and disassembly the name needs to be invisible, | 
|  | //	but that's handled in the module code | 
|  | if (type == DSP_SOURCE) | 
|  | { | 
|  | if (dbev->src_data) | 
|  | delete dbev->src_data; | 
|  |  | 
|  | // func_data computation needed for get_totals | 
|  | if (dbev->func_data == NULL) | 
|  | dbev->func_data = data = dbev->get_hist_data (mlist, | 
|  | Histable::FUNCTION, subtype, Hist_data::ALL); | 
|  | dbev->marks2dsrc->reset (); | 
|  | dbev->marks2dsrc_inc->reset (); | 
|  | data = dbev->src_data = module->get_data (dbev, mlist, | 
|  | Histable::LINE, dbev->func_data->get_totals ()->value, | 
|  | srcContext, func, dbev->marks, | 
|  | dbev->get_thresh_src (), dbev->get_src_compcom (), | 
|  | dbev->get_src_visible (), dbev->get_hex_visible (), | 
|  | false, false, dbev->marks2dsrc, dbev->marks2dsrc_inc); | 
|  | set_file_names (func, dbev->names_src); | 
|  | if (srcContext) | 
|  | { | 
|  | free (dbev->names_src[0]); | 
|  | dbev->names_src[0] = dbe_sprintf (GTXT ("Source File: %s"), | 
|  | srcContext->dbeFile->get_location_info ()); | 
|  | } | 
|  | Obj obj = (Obj) func->convertto (Histable::LINE, srcContext); | 
|  | sel_index = dbeGetSelIndex (dbevindex, obj, type, subtype); | 
|  | } | 
|  | else | 
|  | { /* type == DSP_DISASM */ | 
|  | if (dbev->dis_data) | 
|  | delete dbev->dis_data; | 
|  |  | 
|  | // func_data computation needed for get_totals | 
|  | if (dbev->func_data == NULL) | 
|  | dbev->func_data = data = dbev->get_hist_data (mlist, | 
|  | Histable::FUNCTION, subtype, Hist_data::ALL); | 
|  | dbev->marks2ddis->reset (); | 
|  | dbev->marks2ddis_inc->reset (); | 
|  | data = dbev->dis_data = module->get_data (dbev, mlist, | 
|  | Histable::INSTR, dbev->func_data->get_totals ()->value, | 
|  | srcContext, func, dbev->marks, dbev->get_thresh_dis (), | 
|  | dbev->get_dis_compcom (), dbev->get_src_visible (), | 
|  | dbev->get_hex_visible (), dbev->get_func_scope (), | 
|  | false, dbev->marks2ddis, dbev->marks2ddis_inc); | 
|  | set_file_names (func, dbev->names_dis); | 
|  | if (srcContext) | 
|  | { | 
|  | free (dbev->names_dis[0]); | 
|  | dbev->names_dis[0] = dbe_sprintf (GTXT ("Source File: %s"), | 
|  | srcContext->dbeFile->get_location_info ()); | 
|  | } | 
|  | Obj obj = (Obj) func->convertto (Histable::INSTR); | 
|  | sel_index = dbeGetSelIndex (dbevindex, obj, type, subtype); | 
|  | } | 
|  | return sel_index; | 
|  | } | 
|  |  | 
|  | // the three cases for caller-callee | 
|  | case DSP_SELF: | 
|  | case DSP_CALLER: | 
|  | case DSP_CALLEE: | 
|  | if (org_obj == NULL) | 
|  | { | 
|  | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_SEL_OBJ); | 
|  | return sel_index; | 
|  | } | 
|  |  | 
|  | // Caller data | 
|  | if (dbev->callers) | 
|  | delete dbev->callers; | 
|  | mlist = dbev->get_metric_list (MET_CALL); | 
|  | dbev->callers = dbev->get_hist_data (mlist, Histable::FUNCTION, subtype, | 
|  | Hist_data::CALLERS, org_obj); | 
|  | if (dbev->callers->get_status () != Hist_data::SUCCESS) | 
|  | { | 
|  | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA); | 
|  | return sel_index; | 
|  | } | 
|  |  | 
|  | // Callee data | 
|  | if (dbev->callees) | 
|  | delete dbev->callees; | 
|  | dbev->callees = dbev->get_hist_data (mlist, Histable::FUNCTION, subtype, | 
|  | Hist_data::CALLEES, org_obj); | 
|  | if (dbev->callees->get_status () != Hist_data::SUCCESS) | 
|  | { | 
|  | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA); | 
|  | return sel_index; | 
|  | } | 
|  |  | 
|  | // Center Function item | 
|  | if (dbev->fitem_data) | 
|  | delete dbev->fitem_data; | 
|  | dbev->fitem_data = dbev->get_hist_data (mlist, Histable::FUNCTION, subtype, | 
|  | Hist_data::SELF, org_obj); | 
|  | if (dbev->fitem_data->get_status () != Hist_data::SUCCESS) | 
|  | { | 
|  | dbev->error_msg = DbeView::status_str (DbeView::DBEVIEW_NO_DATA); | 
|  | return sel_index; | 
|  | } | 
|  | return sel_index; | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | return sel_index; | 
|  | } | 
|  |  | 
|  | Vector<void*>* | 
|  | dbeGetTotals (int dbevindex, int dsptype, int subtype) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | MetricList *mlist = dbev->get_metric_list (dsptype, subtype); | 
|  | Hist_data *data = dbev->get_hist_data (mlist, Histable::FUNCTION, 0, | 
|  | Hist_data::ALL); | 
|  | Hist_data::HistItem *totals = data->get_totals (); | 
|  | Vector<void*> *tbl = new Vector<void*>(mlist->size ()); | 
|  | for (long i = 0, sz = mlist->size (); i < sz; i++) | 
|  | { | 
|  | Metric *m = mlist->get (i); | 
|  | switch (m->get_vtype ()) | 
|  | { | 
|  | case VT_DOUBLE: | 
|  | { | 
|  | Vector<double> *lst = new Vector<double>(1); | 
|  | lst->append (totals->value[i].d); | 
|  | tbl->append (lst); | 
|  | break; | 
|  | } | 
|  | case VT_INT: | 
|  | { | 
|  | Vector<int> *lst = new Vector<int>(1); | 
|  | lst->append (totals->value[i].i); | 
|  | tbl->append (lst); | 
|  | break; | 
|  | } | 
|  | case VT_LLONG: | 
|  | case VT_ULLONG: | 
|  | case VT_ADDRESS: | 
|  | { | 
|  | Vector<long long> *lst = new Vector<long long>(1); | 
|  | lst->append (totals->value[i].ll); | 
|  | tbl->append (lst); | 
|  | break; | 
|  | } | 
|  | case VT_LABEL: | 
|  | { | 
|  | Vector<char *> *lst = new Vector<char *>(1); | 
|  | Histable::NameFormat nfmt = dbev->get_name_format (); | 
|  | lst->append (dbe_strdup (totals->obj->get_name (nfmt))); | 
|  | tbl->append (lst); | 
|  | break; | 
|  | } | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | } | 
|  | Vector<void*> *res = new Vector<void*>(2); | 
|  | res->append (dbeGetMetricList (mlist)); | 
|  | res->append (tbl); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | Vector<void*>* | 
|  | dbeGetHotMarks (int dbevindex, int type) | 
|  | { | 
|  | Vector<void*>* table = new Vector<void*>(2); | 
|  | Vector<int>* table0 = new Vector<int> (); | 
|  | Vector<int>* table1 = new Vector<int> (); | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | return NULL; | 
|  |  | 
|  | switch (type) | 
|  | { | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | for (int i = 0; i < dbev->marks2dsrc->size (); i++) | 
|  | { | 
|  | table0->append (dbev->marks2dsrc->fetch (i).index1); | 
|  | table1->append (dbev->marks2dsrc->fetch (i).index2); | 
|  | } | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | for (int i = 0; i < dbev->marks2ddis->size (); i++) | 
|  | { | 
|  | table0->append (dbev->marks2ddis->fetch (i).index1); | 
|  | table1->append (dbev->marks2ddis->fetch (i).index2); | 
|  | } | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | table->store (0, table0); | 
|  | table->store (1, table1); | 
|  | return table; | 
|  | } | 
|  |  | 
|  | Vector<void*>* | 
|  | dbeGetHotMarksInc (int dbevindex, int type) | 
|  | { | 
|  | Vector<void*>* table = new Vector<void*>(2); | 
|  | Vector<int>* table0 = new Vector<int> (); | 
|  | Vector<int>* table1 = new Vector<int> (); | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | return NULL; | 
|  |  | 
|  | switch (type) | 
|  | { | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | for (int i = 0; i < dbev->marks2dsrc_inc->size (); i++) | 
|  | { | 
|  | table0->append (dbev->marks2dsrc_inc->fetch (i).index1); | 
|  | table1->append (dbev->marks2dsrc_inc->fetch (i).index2); | 
|  | } | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | for (int i = 0; i < dbev->marks2ddis_inc->size (); i++) | 
|  | { | 
|  | table0->append (dbev->marks2ddis_inc->fetch (i).index1); | 
|  | table1->append (dbev->marks2ddis_inc->fetch (i).index2); | 
|  | } | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | table->store (0, table0); | 
|  | table->store (1, table1); | 
|  | return table; | 
|  | } | 
|  |  | 
|  | Vector<void*>* | 
|  | dbeGetSummaryHotMarks (int dbevindex, Vector<Obj> *sel_objs, int type) | 
|  | { | 
|  | Vector<void*>* table = new Vector<void*>(2); | 
|  | Vector<int>* table0 = new Vector<int> (); | 
|  | Vector<int>* table1 = new Vector<int> (); | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | return NULL; | 
|  | if (sel_objs == NULL || sel_objs->size () == 0) | 
|  | return NULL; | 
|  |  | 
|  | Hist_data *data; | 
|  | Vector<int_pair_t> *marks2d; | 
|  | Vector<int_pair_t>* marks2d_inc; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | data = dbev->src_data; | 
|  | marks2d = dbev->marks2dsrc; | 
|  | marks2d_inc = dbev->marks2dsrc_inc; | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | data = dbev->dis_data; | 
|  | marks2d = dbev->marks2ddis; | 
|  | marks2d_inc = dbev->marks2ddis_inc; | 
|  | break; | 
|  | default: | 
|  | data = NULL; | 
|  | marks2d = NULL; | 
|  | marks2d_inc = NULL; | 
|  | break; | 
|  | } | 
|  | if (data == NULL || data->get_status () != Hist_data::SUCCESS | 
|  | || marks2d_inc == NULL || marks2d == NULL) | 
|  | return NULL; | 
|  |  | 
|  | MetricList *orig_mlist = data->get_metric_list (); | 
|  | MetricList *prop_mlist = new MetricList (dbev->get_metric_ref (MET_NORMAL)); | 
|  | if (prop_mlist && dbev->comparingExperiments ()) | 
|  | prop_mlist = dbev->get_compare_mlist (prop_mlist, 0); | 
|  | Metric *mitem; | 
|  | int index, index2; | 
|  | index2 = 0; | 
|  | Vec_loop (Metric*, prop_mlist->get_items (), index, mitem) | 
|  | { | 
|  | if (mitem->get_subtype () == Metric::STATIC) | 
|  | continue; | 
|  |  | 
|  | for (int i = 0; i < marks2d_inc->size (); i++) | 
|  | { | 
|  | int found = 0; | 
|  | for (int j = 0; j < sel_objs->size (); j++) | 
|  | { | 
|  | int sel_index = (int) sel_objs->fetch (j); | 
|  | int marked_index = marks2d_inc->fetch (i).index1; | 
|  | if (sel_index == marked_index) | 
|  | { | 
|  | found = 1; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (!found) | 
|  | continue; | 
|  | int mindex = marks2d_inc->fetch (i).index2; | 
|  | Metric *orig_metric = orig_mlist->get_items ()->fetch (mindex); | 
|  | if (orig_metric->get_id () == mitem->get_id () | 
|  | && mitem->get_subtype () == Metric::INCLUSIVE) | 
|  | { | 
|  | table0->append (index2); | 
|  | table1->append (1); | 
|  | } | 
|  | } | 
|  |  | 
|  | for (int i = 0; i < marks2d->size (); i++) | 
|  | { | 
|  | int found = 0; | 
|  | for (int j = 0; j < sel_objs->size (); j++) | 
|  | { | 
|  | int sel_index = (int) sel_objs->fetch (j); | 
|  | int marked_index = marks2d->fetch (i).index1; | 
|  | if (sel_index == marked_index) | 
|  | { | 
|  | found = 1; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (!found) | 
|  | continue; | 
|  | int mindex = marks2d->fetch (i).index2; | 
|  | Metric *orig_metric = orig_mlist->get_items ()->fetch (mindex); | 
|  | if (orig_metric->get_id () == mitem->get_id () | 
|  | && mitem->get_subtype () == Metric::EXCLUSIVE) | 
|  | { | 
|  | table0->append (index2); | 
|  | table1->append (0); | 
|  | } | 
|  | } | 
|  | if (!(mitem->get_subtype () == Metric::EXCLUSIVE | 
|  | || mitem->get_subtype () == Metric::DATASPACE)) | 
|  | index2++; | 
|  | } | 
|  | table->store (0, table0); | 
|  | table->store (1, table1); | 
|  | return table; | 
|  | } | 
|  |  | 
|  | // Get a vector of function ids of data(begin, begin + length - 1) | 
|  | // Currently only support source/disassembly view | 
|  | Vector<uint64_t>* | 
|  | dbeGetFuncId (int dbevindex, int type, int begin, int length) | 
|  | { | 
|  | Vector<uint64_t>* table = new Vector<uint64_t > (); | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  |  | 
|  | Hist_data *data; | 
|  | Function* given_func = NULL; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | data = dbev->src_data; | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | data = dbev->dis_data; | 
|  | break; | 
|  | default: | 
|  | data = NULL; | 
|  | abort (); | 
|  | } | 
|  |  | 
|  | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | 
|  | return NULL; | 
|  |  | 
|  | if (begin < 0 || begin + length > data->size ()) | 
|  | return NULL; | 
|  |  | 
|  | switch (type) | 
|  | { | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | { | 
|  | for (int i = begin; i < begin + length; i++) | 
|  | { | 
|  | given_func = NULL; | 
|  | Histable * sel_obj = data->fetch (i)->obj; | 
|  | if (sel_obj != NULL) | 
|  | given_func = (Function*) (sel_obj)->convertto (Histable::FUNCTION, (Histable*) dbev); | 
|  | if (given_func == NULL) | 
|  | table->append (0); | 
|  | else | 
|  | table->append (given_func->id); | 
|  | } | 
|  | } | 
|  | break; | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | return table; | 
|  | } | 
|  |  | 
|  | Vector<void*>* | 
|  | dbeGetFuncCallerInfo (int dbevindex, int type, Vector<int>* idxs, int groupId) | 
|  | { | 
|  | Vector<void*>* data = new Vector<void*>(); | 
|  | if (type == DSP_SOURCE_V2 || type == DSP_DISASM_V2) | 
|  | { | 
|  | Obj sel_func = dbeGetSelObj (dbevindex, DSP_FUNCTION, 0); | 
|  | if (sel_func == 0) | 
|  | return data; | 
|  | Vector<Obj> * cmpObjs = dbeGetComparableObjsV2 (dbevindex, sel_func, type); | 
|  | if (cmpObjs == NULL) | 
|  | return data; | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | int mtype = MET_COMMON | COMPARE_BIT | ((groupId + 1) << GROUP_ID_SHIFT); | 
|  | MetricList *mlist = dbev->get_metric_list ((MetricType) (mtype & MTYPE_MASK), | 
|  | (mtype & COMPARE_BIT) != 0, | 
|  | mtype >> GROUP_ID_SHIFT); | 
|  | Histable *selObj = (Histable *) cmpObjs->fetch (groupId); | 
|  | int subtype = 0; | 
|  | Hist_data *hist_data = dbev->get_data (mlist, selObj, type, subtype); | 
|  | if (hist_data == NULL) | 
|  | return data; | 
|  | } | 
|  | for (int i = 0; i < idxs->size (); i++) | 
|  | data->append (dbeGetFuncCallerInfoById (dbevindex, type, idxs->fetch (i))); | 
|  | return data; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get Table of Caller info: | 
|  | // param: idx -- selected AT_FUNC row | 
|  | // return: callsite_id, callsite_name (function: file: line) | 
|  | Vector<void*>* | 
|  | dbeGetFuncCallerInfoById (int dbevindex, int type, int idx) | 
|  | { | 
|  | Vector<void*>* table = new Vector<void*>(3); | 
|  | Vector<uint64_t>* table0 = new Vector<uint64_t> (); | 
|  | Vector<int>* table1 = new Vector<int> (); | 
|  | Vector<char*>* table2 = new Vector<char*>(); | 
|  |  | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Hist_data *data; | 
|  | Function* given_func = NULL; | 
|  | Vector<Histable*> *instr_info = NULL; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | data = dbev->src_data; | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | data = dbev->dis_data; | 
|  | break; | 
|  | default: | 
|  | data = NULL; | 
|  | abort (); | 
|  | } | 
|  | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | 
|  | return NULL; | 
|  |  | 
|  | if (idx < 0 || idx >= data->size ()) | 
|  | return NULL; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | { | 
|  | Histable * sel_obj = data->fetch (idx)->obj; | 
|  | if (sel_obj == NULL) | 
|  | return NULL; | 
|  | given_func = (Function*) (sel_obj)->convertto (Histable::FUNCTION, (Histable*) dbev); | 
|  | if (given_func == NULL) | 
|  | return NULL; | 
|  | PathTree * ptree = dbev->get_path_tree (); | 
|  | if (ptree == NULL) | 
|  | return NULL; | 
|  | instr_info = ptree->get_clr_instr (given_func); | 
|  | DefaultMap<uint64_t, int> * line_seen = new DefaultMap<uint64_t, int>(); | 
|  | for (int j = 0; j < ((Vector<Histable*>*)instr_info)->size (); j++) | 
|  | { | 
|  | Histable *instr = ((Vector<Histable*>*)instr_info)->fetch (j); | 
|  | Function *cur_func = NULL; | 
|  | if (instr->get_type () == Histable::INSTR) | 
|  | cur_func = ((DbeInstr*) instr)->func; | 
|  | else if (instr->get_type () == Histable::LINE) | 
|  | cur_func = ((DbeLine*) instr)->func; | 
|  | if (cur_func == NULL || (cur_func->flags & FUNC_FLAG_SIMULATED)) | 
|  | continue; // skip functions like <Total> | 
|  | Histable* line; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | if (cur_func != NULL) | 
|  | { | 
|  | SourceFile *sourceFile = cur_func->getDefSrc (); | 
|  | if (sourceFile == NULL || | 
|  | (sourceFile->flags & SOURCE_FLAG_UNKNOWN) != 0) | 
|  | continue; // skip functions like <Function: %s, instructions without line numbers> | 
|  | } | 
|  | line = instr->convertto (Histable::LINE, NULL); | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | line = instr->convertto (Histable::INSTR, NULL); | 
|  | break; | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | uint64_t func_id = cur_func->id; | 
|  | uint64_t line_id = instr->id; | 
|  | int is_null = 0; | 
|  | int line_no = -1; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | is_null = (((DbeLine*) line)->func == NULL) ? 1 : 0; | 
|  | if (is_null) | 
|  | ((DbeLine*) line)->func = cur_func; | 
|  | line_no = ((DbeLine*) line)->lineno; | 
|  | if (line_seen->get (line_id) == 0) | 
|  | { | 
|  | line_seen->put (line_id, 1); | 
|  | table0->append (func_id); | 
|  | table1->append (line_no); | 
|  | Histable::NameFormat nfmt = dbev->get_name_format (); | 
|  | table2->append (dbe_strdup (line->get_name (nfmt))); | 
|  | } | 
|  | if (is_null) | 
|  | ((DbeLine*) line)->func = NULL; | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | is_null = (((DbeInstr*) line)->func == NULL) ? 1 : 0; | 
|  | if (is_null) | 
|  | ((DbeInstr*) line)->func = cur_func; | 
|  | line_no = ((DbeInstr*) line)->addr; | 
|  | if (line_seen->get (line_id) == 0) | 
|  | { | 
|  | line_seen->put (line_id, 1); | 
|  | table0->append (func_id); | 
|  | table1->append (line_no); | 
|  | Histable::NameFormat nfmt = dbev->get_name_format (); | 
|  | table2->append (dbe_strdup (line->get_name (nfmt))); | 
|  | } | 
|  | if (is_null) | 
|  | ((DbeInstr*) line)->func = NULL; | 
|  | break; | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | } | 
|  | delete line_seen; | 
|  | delete instr_info; | 
|  | } | 
|  | break; | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | table->store (0, table0); | 
|  | table->store (1, table1); | 
|  | table->store (2, table2); | 
|  | return table; | 
|  | } | 
|  |  | 
|  | Vector<void*>* | 
|  | dbeGetFuncCalleeInfo (int dbevindex, int type, Vector<int>* idxs, int groupId) | 
|  | { | 
|  | Vector<void*>* data = new Vector<void*>(); | 
|  | if (type == DSP_SOURCE_V2 || type == DSP_DISASM_V2) | 
|  | { | 
|  | Obj sel_func = dbeGetSelObj (dbevindex, DSP_FUNCTION, 0); | 
|  | if (sel_func == 0) | 
|  | return data; | 
|  | Vector<Obj> * cmpObjs = dbeGetComparableObjsV2 (dbevindex, sel_func, type); | 
|  | if (cmpObjs == NULL) | 
|  | return data; | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | int mtype = MET_COMMON | COMPARE_BIT | ((groupId + 1) << GROUP_ID_SHIFT); | 
|  | MetricList *mlist = dbev->get_metric_list ((MetricType) (mtype & MTYPE_MASK), | 
|  | (mtype & COMPARE_BIT) != 0, | 
|  | mtype >> GROUP_ID_SHIFT); | 
|  | Histable *selObj = (Histable *) cmpObjs->fetch (groupId); | 
|  | int subtype = 0; | 
|  | Hist_data *hist_data = dbev->get_data (mlist, selObj, type, subtype); | 
|  | if (hist_data == NULL) | 
|  | return data; | 
|  | } | 
|  |  | 
|  | for (int i = 0; i < idxs->size (); i++) | 
|  | data->append (dbeGetFuncCalleeInfoById (dbevindex, type, idxs->fetch (i))); | 
|  | return data; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get Table of Callee info: | 
|  | // param: idx -- selected AT_FUNC row | 
|  | // return: callsite_row, callee_id, callee_name | 
|  | // | 
|  | Vector<void*>* | 
|  | dbeGetFuncCalleeInfoById (int dbevindex, int type, int idx) | 
|  | { | 
|  | Vector<void*>* table = new Vector<void*>(3); | 
|  | Vector<int>* table0 = new Vector<int>(); | 
|  | Vector<uint64_t>* table1 = new Vector<uint64_t > (); | 
|  | Vector<char*>* table2 = new Vector<char*>(); | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Hist_data *data; | 
|  | Function* given_func = NULL; | 
|  | Vector<Histable*> *instr_info = NULL; | 
|  | Vector<void*> *func_info = NULL; | 
|  |  | 
|  | switch (type) | 
|  | { | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | data = dbev->src_data; | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | data = dbev->dis_data; | 
|  | break; | 
|  | default: | 
|  | data = NULL; | 
|  | abort (); | 
|  | } | 
|  | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | 
|  | return NULL; | 
|  | if (idx < 0 || idx >= data->size ()) | 
|  | return NULL; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | { | 
|  | Histable * sel_obj = data->fetch (idx)->obj; | 
|  | if (sel_obj == NULL) | 
|  | return NULL; | 
|  | given_func = (Function*) (sel_obj)->convertto (Histable::FUNCTION, (Histable*) dbev); | 
|  | if (given_func == NULL) | 
|  | return NULL; | 
|  | PathTree * ptree = dbev->get_path_tree (); | 
|  | if (ptree == NULL) | 
|  | return NULL; | 
|  | Vector<Histable*> *instrs = NULL; | 
|  | Vector<void*> *callee_instrs = ptree->get_cle_instr (given_func, instrs); | 
|  | func_info = new Vector<void*>(); | 
|  | instr_info = new Vector<Histable*>(); | 
|  | for (long a = 0, sz_a = callee_instrs ? callee_instrs->size () : 0; a < sz_a; a++) | 
|  | { | 
|  | Vector<Histable*> *temp = ((Vector<Vector<Histable*>*>*)callee_instrs)->get (a); | 
|  | DefaultMap<Function*, int> * func_seen = new DefaultMap<Function*, int>(); | 
|  | Histable* instr0 = (Histable*) instrs->fetch (a); | 
|  | for (long b = 0, sz_b = temp ? temp->size () : 0; b < sz_b; b++) | 
|  | { | 
|  | Histable *instr = temp->get (b); | 
|  | if (instr->get_type () == Histable::INSTR) | 
|  | { | 
|  | Function* func1 = ((DbeInstr *) instr)->func; | 
|  | func_seen->put (func1, 1); | 
|  | } | 
|  | else if (instr->get_type () == Histable::LINE) | 
|  | { | 
|  | Function* func1 = ((DbeLine *) instr)->func; | 
|  | func_seen->put (func1, 1); | 
|  | } | 
|  | } | 
|  | Vector<Function*> *funcs = func_seen->keySet (); | 
|  | delete func_seen; | 
|  | if (funcs->size () > 0) | 
|  | { | 
|  | instr_info->append (instr0); | 
|  | func_info->append (funcs); | 
|  | } | 
|  | } | 
|  | delete instrs; | 
|  | destroy (callee_instrs); | 
|  |  | 
|  | DefaultMap<uint64_t, Vector<int>* > * instr_idxs = new DefaultMap<uint64_t, Vector<int>* >(); | 
|  | DefaultMap<uint64_t, int> * func_idxs = new DefaultMap<uint64_t, int>(); | 
|  | for (long j = 0, sz_j = instr_info ? instr_info->size () : 0; j < sz_j; j++) | 
|  | { | 
|  | Histable *instr = instr_info->get (j); | 
|  | Function *cur_func = NULL; | 
|  | if (instr->get_type () == Histable::INSTR) | 
|  | cur_func = ((DbeInstr*) instr)->func; | 
|  | else if (instr->get_type () == Histable::LINE) | 
|  | cur_func = ((DbeLine*) instr)->func; | 
|  | if (cur_func != NULL && (cur_func->flags & FUNC_FLAG_SIMULATED)) | 
|  | continue; // skip functions like <Total> | 
|  | Histable* line; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | if (cur_func != NULL) | 
|  | { | 
|  | SourceFile *sourceFile = cur_func->getDefSrc (); | 
|  | if (sourceFile == NULL || | 
|  | (sourceFile->flags & SOURCE_FLAG_UNKNOWN) != 0) | 
|  | // skip functions like <Function: %s, instructions without line numbers> | 
|  | continue; | 
|  | } | 
|  | line = instr->convertto (Histable::LINE, NULL); | 
|  | if (type == DSP_SOURCE_V2) | 
|  | line = dbev->get_compare_obj (line); | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | line = instr; | 
|  | if (type == DSP_DISASM_V2) | 
|  | line = dbev->get_compare_obj (line); | 
|  | break; | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | if (func_idxs->get (line->id) == 0) | 
|  | { | 
|  | func_idxs->put (line->id, 1); | 
|  | Vector<int> *temp_idx = new Vector<int>(); | 
|  | temp_idx->append (j); | 
|  | instr_idxs->put (line->id, temp_idx); | 
|  | } | 
|  | else | 
|  | { | 
|  | Vector<int> *temp_idx = instr_idxs->get (line->id); | 
|  | temp_idx->append (j); | 
|  | } | 
|  | } | 
|  | for (long i = 0; i < data->size (); i++) | 
|  | { | 
|  | Histable* line = data->fetch (i)->obj; | 
|  | if (line == NULL) | 
|  | continue; | 
|  | Vector<int> * instr_idx = instr_idxs->get (line->id); | 
|  | if (instr_idx == NULL) | 
|  | continue; | 
|  | for (long j = 0; j < instr_idx->size (); j++) | 
|  | { | 
|  | Vector<void*>* callee_funcs_vec = (Vector<void*>*)func_info; | 
|  | if (callee_funcs_vec->size () == 0) | 
|  | continue; | 
|  | Vector<Function*>* callee_funcs_value = (Vector<Function*>*)callee_funcs_vec->fetch (instr_idx->fetch (j)); | 
|  | for (int k = 0; callee_funcs_value != NULL && k < callee_funcs_value->size (); k++) | 
|  | { | 
|  | uint64_t funcobj_id = ((Function*) callee_funcs_value->fetch (k))->id; | 
|  | int old_size = table0->size (); | 
|  | if (old_size > 0 && i == table0->fetch (old_size - 1) | 
|  | && funcobj_id == table1->fetch (old_size - 1)) | 
|  | continue; | 
|  | table0->append (i); | 
|  | table1->append (funcobj_id); | 
|  | table2->append (dbe_strdup (((Function*) callee_funcs_value->fetch (k))->get_name ())); | 
|  | } | 
|  | } | 
|  | } | 
|  | delete instr_idxs; | 
|  | delete func_idxs; | 
|  | destroy (func_info); | 
|  | delete instr_info; | 
|  | } | 
|  | break; | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | table->store (0, table0); | 
|  | table->store (1, table1); | 
|  | table->store (2, table2); | 
|  | return table; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get Table of Function List data with only total values | 
|  | // | 
|  | Vector<void*> * | 
|  | dbeGetFuncListMini (int dbevindex, int type, int /*subtype*/) | 
|  | { | 
|  | Hist_data *data; | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | switch (type) | 
|  | { | 
|  | case DSP_FUNCTION: | 
|  | data = dbev->func_data; | 
|  | break; | 
|  | default: | 
|  | data = NULL; | 
|  | break; | 
|  | } | 
|  | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | 
|  | return NULL; | 
|  |  | 
|  | MetricList *mlist = data->get_metric_list (); | 
|  |  | 
|  | // Get table size: count visible metrics | 
|  | int nvisible = 0; | 
|  | for (long i = 0, sz = mlist->size (); i < sz; i++) | 
|  | { | 
|  | Metric *m = mlist->get (i); | 
|  | if (m->is_visible () || m->is_tvisible () || m->is_pvisible ()) | 
|  | nvisible++; | 
|  | } | 
|  | Vector<void*> *table = new Vector<void*>(nvisible + 1); | 
|  |  | 
|  | // Fill function list elements | 
|  | Hist_data::HistItem *totals = data->get_totals (); | 
|  | for (long i = 0, sz = mlist->size (); i < sz; i++) | 
|  | { | 
|  | Metric *m = mlist->get (i); | 
|  | if (!m->is_visible () && !m->is_tvisible () && !m->is_pvisible ()) | 
|  | continue; | 
|  | TValue res; | 
|  | TValue *v = data->get_value (&res, i, totals); | 
|  | if ((m->get_visbits () & VAL_RATIO) != 0) | 
|  | { | 
|  | Vector<double> *col = new Vector<double>(1); | 
|  | double d = (v->tag != VT_LABEL) ? v->to_double () : 100.; // NaN | 
|  | col->append (d); | 
|  | table->append (col); | 
|  | continue; | 
|  | } | 
|  | switch (m->get_vtype ()) | 
|  | { | 
|  | case VT_INT: | 
|  | { | 
|  | Vector<int> *col = new Vector<int>(1); | 
|  | col->append (v->i); | 
|  | table->append (col); | 
|  | break; | 
|  | } | 
|  | case VT_ADDRESS: | 
|  | case VT_ULLONG: | 
|  | case VT_LLONG: | 
|  | { | 
|  | Vector<long long> *col = new Vector<long long>(1); | 
|  | col->append (v->ll); | 
|  | table->append (col); | 
|  | break; | 
|  | } | 
|  | case VT_LABEL: | 
|  | { | 
|  | Vector<char *> *col = new Vector<char *>(1); | 
|  | col->append (dbe_strdup (v->l)); | 
|  | table->append (col); | 
|  | break; | 
|  | } | 
|  | case VT_DOUBLE: | 
|  | default: | 
|  | { | 
|  | Vector<double> *col = new Vector<double>(1); | 
|  | col->append (v->d); | 
|  | table->append (col); | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | table->append (NULL); | 
|  | return table; | 
|  | } | 
|  |  | 
|  | // Get Table of Function List data | 
|  | Vector<void*> * | 
|  | dbeGetFuncList (int dbevindex, int type, int subtype) | 
|  | { | 
|  | MetricList *mlist; | 
|  | Metric *mitem; | 
|  | int nitems, nvisible; | 
|  | int index, index2, nv; | 
|  | char *cell; | 
|  | Vector<int> *ji_list; | 
|  | Hist_data *data; | 
|  | Hist_data::HistItem *item; | 
|  |  | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  |  | 
|  | // fprintf(stderr, NTXT("XXX dbeGetFuncList, FuncListDisp_type = %d\n"), type); | 
|  | switch (type) | 
|  | { | 
|  | case DSP_FUNCTION: | 
|  | data = dbev->func_data; | 
|  | break; | 
|  | case DSP_LINE: | 
|  | data = dbev->line_data; | 
|  | break; | 
|  | case DSP_PC: | 
|  | data = dbev->pc_data; | 
|  | break; | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | data = dbev->src_data; | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | data = dbev->dis_data; | 
|  | break; | 
|  | case DSP_SELF: | 
|  | data = dbev->fitem_data; | 
|  | break; | 
|  | case DSP_CALLER: | 
|  | data = dbev->callers; | 
|  | break; | 
|  | case DSP_CALLEE: | 
|  | data = dbev->callees; | 
|  | break; | 
|  | case DSP_DLAYOUT: | 
|  | data = dbev->dlay_data; | 
|  | break; | 
|  | case DSP_DATAOBJ: | 
|  | data = dbev->dobj_data; | 
|  | break; | 
|  | case DSP_MEMOBJ: | 
|  | case DSP_INDXOBJ: | 
|  | data = dbev->get_indxobj_data (subtype); | 
|  | break; | 
|  | default: | 
|  | data = NULL; | 
|  | break; | 
|  | } | 
|  | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | 
|  | return NULL; | 
|  | mlist = data->get_metric_list (); | 
|  |  | 
|  | // Get table size: count visible metrics | 
|  | nitems = data->size (); | 
|  | nvisible = 0; | 
|  | Vec_loop (Metric*, mlist->get_items (), index, mitem) | 
|  | { | 
|  | if (mitem->is_visible () || mitem->is_tvisible () || mitem->is_pvisible ()) | 
|  | nvisible++; | 
|  | } | 
|  |  | 
|  | // Initialize Java String array | 
|  | Vector<void*> *table = new Vector<void*>(nvisible + 1); | 
|  |  | 
|  | // Mark Hi-value metric items for annotated src/dis/layout | 
|  | if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_DLAYOUT | 
|  | || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2) | 
|  | { | 
|  | ji_list = new Vector<int>(nitems); | 
|  |  | 
|  | if (dbev->marks->size () > 0) | 
|  | index = dbev->marks->fetch (0); | 
|  | else | 
|  | index = -1; | 
|  | int mindex = 0; | 
|  | for (index2 = 0; index2 < nitems; index2++) | 
|  | { | 
|  | item = data->fetch (index2); | 
|  | if (index2 == index) | 
|  | { | 
|  | ji_list->store (index2, -item->type); | 
|  | if (++mindex < dbev->marks->size ()) | 
|  | index = dbev->marks->fetch (mindex); | 
|  | else | 
|  | index = -1; | 
|  | } | 
|  | else | 
|  | ji_list->store (index2, item->type); | 
|  | } | 
|  | table->store (nvisible, ji_list); | 
|  | } | 
|  | else | 
|  | table->store (nvisible, NULL); | 
|  |  | 
|  | // Fill function list elements | 
|  | nv = 0; | 
|  |  | 
|  | Vec_loop (Metric*, mlist->get_items (), index, mitem) | 
|  | { | 
|  | if (!mitem->is_visible () && !mitem->is_tvisible () && | 
|  | !mitem->is_pvisible ()) | 
|  | continue; | 
|  |  | 
|  | // Fill values | 
|  | switch (mitem->get_vtype ()) | 
|  | { | 
|  | case VT_LABEL: | 
|  | { | 
|  | Vector<char*> *jobjects = new Vector<char*>(nitems); | 
|  | char *buf = NULL; | 
|  | size_t bufsz = 0; | 
|  | int lspace = 0; | 
|  | if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 | 
|  | || type == DSP_DISASM_V2) | 
|  | { | 
|  | // if this is source or disassembly, where we'll insert | 
|  | //	a preface into the output line, figure out how wide | 
|  | //	it needs to be | 
|  | // first, scan all the lines, to get the maximum line number | 
|  | bufsz = 1024; | 
|  | buf = (char *) xmalloc (bufsz); | 
|  | int max_lineno = 0; | 
|  | int hidx; | 
|  | Hist_data::HistItem *hitem; | 
|  | Vec_loop (Hist_data::HistItem*, data, hidx, hitem) | 
|  | { | 
|  | if (!hitem->obj) | 
|  | continue; | 
|  | if (hitem->obj->get_type () == Histable::LINE && | 
|  | ((DbeLine*) hitem->obj)->lineno > max_lineno) | 
|  | max_lineno = ((DbeLine*) hitem->obj)->lineno; | 
|  | else if (hitem->obj->get_type () == Histable::INSTR | 
|  | && ((DbeInstr*) hitem->obj)->lineno > max_lineno) | 
|  | max_lineno = ((DbeInstr*) hitem->obj)->lineno; | 
|  | } | 
|  |  | 
|  | // we have the maximum integer over all linenumbers in the file | 
|  | // 	figure out how many digits are needed | 
|  | lspace = snprintf (buf, bufsz, NTXT ("%d"), max_lineno); | 
|  | } | 
|  | for (index2 = 0; index2 < nitems; index2++) | 
|  | { | 
|  | item = data->fetch (index2); | 
|  | if (type == DSP_DLAYOUT) | 
|  | cell = dbe_strdup (((DataObject*) (item->obj))->get_offset_name ()); | 
|  | else if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2) | 
|  | { | 
|  | // This code is duplicated in output.cc, yet it's | 
|  | // intended for presentation purpose and thus is | 
|  | // potentially different for er_print and analyzer. | 
|  | switch (item->type) | 
|  | { | 
|  | case Module::AT_SRC_ONLY: | 
|  | case Module::AT_SRC: | 
|  | if (item->obj == NULL) | 
|  | snprintf (buf, bufsz, NTXT (" %*c. "), lspace, ' '); | 
|  | else | 
|  | snprintf (buf, bufsz, NTXT (" %*d. "), lspace, ((DbeLine*) item->obj)->lineno); | 
|  | break; | 
|  | case Module::AT_FUNC: | 
|  | case Module::AT_QUOTE: | 
|  | snprintf (buf, bufsz, NTXT ("%*c"), lspace + 3, ' '); | 
|  | break; | 
|  | case Module::AT_DIS: | 
|  | case Module::AT_DIS_ONLY: | 
|  | if (item->obj == NULL || ((DbeInstr*) item->obj)->lineno == -1) | 
|  | snprintf (buf, bufsz, NTXT ("%*c[%*s] "), lspace + 3, ' ', lspace, NTXT ("?")); | 
|  | else | 
|  | snprintf (buf, bufsz, NTXT ("%*c[%*d] "), lspace + 3, ' ', lspace, | 
|  | ((DbeInstr*) item->obj)->lineno); | 
|  | break; | 
|  | case Module::AT_COM: | 
|  | case Module::AT_EMPTY: | 
|  | *buf = (char) 0; | 
|  | break; | 
|  | } | 
|  | // get the line's text | 
|  | char *s = item->value[index].l; | 
|  | if (s != NULL) | 
|  | { | 
|  | // copy the string expanding all tabulations | 
|  | // (JTable doesn't render them) | 
|  | char *d = buf + strlen (buf); | 
|  | char c; | 
|  | size_t column = 0; | 
|  | do | 
|  | { | 
|  | c = *s++; | 
|  | if (c == '\t') | 
|  | { | 
|  | do | 
|  | { | 
|  | *d++ = ' '; | 
|  | column++; | 
|  | } | 
|  | while (column & 07); | 
|  | } | 
|  | else | 
|  | { | 
|  | *d++ = c; | 
|  | column++; | 
|  | } | 
|  | if (column + 32 > bufsz) | 
|  | { | 
|  | // Reallocate the buffer | 
|  | size_t curlen = d - buf; | 
|  | bufsz += 1024; | 
|  | char *buf_new = (char *) xmalloc (bufsz); | 
|  | strncpy (buf_new, buf, curlen); | 
|  | buf_new[curlen] = '\0'; | 
|  | free (buf); | 
|  | buf = buf_new; | 
|  | d = buf + curlen; | 
|  | } | 
|  | } | 
|  | while (c != (char) 0); | 
|  | } | 
|  | cell = dbe_strdup (buf); | 
|  | free (item->value[index].l); | 
|  | item->value[index].l = NULL; //YXXX missing from dbeGetFuncListV2 | 
|  | } | 
|  | else | 
|  | { | 
|  | // omazur: why don't we have it as metric value | 
|  | Histable::NameFormat nfmt = dbev->get_name_format (); | 
|  | cell = dbe_strdup (item->obj->get_name (nfmt)); | 
|  | } | 
|  | jobjects->store (index2, cell); | 
|  | } | 
|  | if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 | 
|  | || type == DSP_DISASM_V2) | 
|  | free (buf); | 
|  | table->store (nv++, jobjects); | 
|  | break; | 
|  | } | 
|  | default: | 
|  | table->store (nv++, dbeGetTableDataOneColumn (data, index)); | 
|  | break; | 
|  | } | 
|  | } | 
|  | return table; | 
|  | } | 
|  |  | 
|  | Vector<Obj> * | 
|  | dbeGetComparableObjsV2 (int /* dbevindex */, Obj sel_obj, int type) | 
|  | { | 
|  | long grsize = dbeSession->expGroups->size (); | 
|  | Vector<Obj> *res = new Vector<Obj> (grsize + 1); | 
|  | for (long j = 0; j < grsize; j++) | 
|  | res->append ((Obj) NULL); | 
|  | res->append (sel_obj); | 
|  | Histable *obj = (Histable *) sel_obj; | 
|  | if (obj == NULL) | 
|  | return res; | 
|  | Function *func = (Function *) obj->convertto (Histable::FUNCTION); | 
|  | if (func == NULL) | 
|  | return res; | 
|  | Vector<Histable *> *cmpObjs = func->get_comparable_objs (); | 
|  | if (cmpObjs == NULL || cmpObjs->size () != grsize) | 
|  | return res; | 
|  |  | 
|  | Histable::Type conv_type = (type == DSP_SOURCE || type == DSP_SOURCE_V2) ? | 
|  | Histable::LINE : Histable::INSTR; | 
|  | switch (obj->get_type ()) | 
|  | { | 
|  | case Histable::FUNCTION: | 
|  | for (long j = 0; j < grsize; j++) | 
|  | res->store (j, (Obj) cmpObjs->get (j)); | 
|  | return res; | 
|  | case Histable::INSTR: | 
|  | case Histable::LINE: | 
|  | { | 
|  | SourceFile *srcContext = (SourceFile *) obj->convertto (Histable::SOURCEFILE); | 
|  | char *bname = get_basename (srcContext->get_name ()); | 
|  | for (long j = 0; j < grsize; j++) | 
|  | { | 
|  | Function *func1 = (Function *) cmpObjs->get (j); | 
|  | if (func == func1) | 
|  | { | 
|  | if (conv_type == Histable::LINE) | 
|  | res->store (j, (Obj) obj); | 
|  | else | 
|  | res->store (j, (Obj) obj->convertto (conv_type, srcContext)); | 
|  | continue; | 
|  | } | 
|  | if (func1 == NULL) | 
|  | continue; | 
|  | Vector<SourceFile*> *sources = func1->get_sources (); | 
|  | SourceFile *sf = NULL; | 
|  | for (long j1 = 0, sz1 = sources ? sources->size () : 0; j1 < sz1; j1++) | 
|  | { | 
|  | SourceFile *sf1 = sources->get (j1); | 
|  | if (sf1 == srcContext) | 
|  | { // the same file | 
|  | sf = srcContext; | 
|  | break; | 
|  | } | 
|  | else if (sf == NULL) | 
|  | { | 
|  | char *bname1 = get_basename (sf1->get_name ()); | 
|  | if (dbe_strcmp (bname, bname1) == 0) | 
|  | sf = sf1; | 
|  | } | 
|  | } | 
|  | res->store (j, (Obj) func1->convertto (conv_type, srcContext)); | 
|  | } | 
|  | break; | 
|  | } | 
|  | default: | 
|  | break; | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | // Get Table of Function List data | 
|  | Vector<void *> * | 
|  | dbeGetFuncListV2 (int dbevindex, int mtype, Obj sel_obj, int type, int subtype) | 
|  | { | 
|  | Metric *mitem; | 
|  | int nitems, nvisible; | 
|  | int index, index2, nv; | 
|  | char *cell; | 
|  | Hist_data::HistItem *item; | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | dbev->error_msg = dbev->warning_msg = NULL; | 
|  | MetricList *mlist = dbev->get_metric_list ((MetricType) (mtype & MTYPE_MASK), | 
|  | (mtype & COMPARE_BIT) != 0, | 
|  | mtype >> GROUP_ID_SHIFT); | 
|  | Histable *selObj = (Histable *) sel_obj; | 
|  | int old_compare_mode = dbev->get_compare_mode (); | 
|  | if ((mtype & COMPARE_BIT) != 0) | 
|  | dbev->reset_compare_mode (CMP_DISABLE); | 
|  | Hist_data *data = dbev->get_data (mlist, selObj, type, subtype); | 
|  | dbev->reset_compare_mode (old_compare_mode); | 
|  | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | 
|  | return NULL; | 
|  | nitems = data->size (); | 
|  | nvisible = mlist->get_items ()->size (); | 
|  |  | 
|  | // Initialize Java String array | 
|  | Vector<void*> *table = new Vector<void*>(nvisible + 3); | 
|  | // Mark Hi-value metric items for annotated src/dis/layout | 
|  | if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_DLAYOUT | 
|  | || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2) | 
|  | { | 
|  | Vector<int> *types = new Vector<int>(nitems); | 
|  | Vector<Obj> *ids = new Vector<Obj > (nitems); | 
|  | if (dbev->marks->size () > 0) | 
|  | index = dbev->marks->fetch (0); | 
|  | else | 
|  | index = -1; | 
|  | int mindex = 0; | 
|  | for (int i = 0; i < nitems; i++) | 
|  | { | 
|  | item = data->fetch (i); | 
|  | ids->store (i, (Obj) item->obj); | 
|  | if (i == index) | 
|  | { | 
|  | types->store (i, -item->type); | 
|  | if (++mindex < dbev->marks->size ()) | 
|  | index = dbev->marks->fetch (mindex); | 
|  | else | 
|  | index = -1; | 
|  | } | 
|  | else | 
|  | types->store (i, item->type); | 
|  | } | 
|  | table->store (nvisible, types); | 
|  | table->store (nvisible + 1, ids); | 
|  | } | 
|  | else | 
|  | { | 
|  | table->store (nvisible, NULL); | 
|  | table->store (nvisible + 1, NULL); | 
|  | } | 
|  |  | 
|  | // Fill function list elements | 
|  | nv = 0; | 
|  | Vec_loop (Metric*, mlist->get_items (), index, mitem) | 
|  | { | 
|  | if (!mitem->is_visible () && !mitem->is_tvisible () && | 
|  | !mitem->is_pvisible ()) | 
|  | continue; | 
|  |  | 
|  | // Fill values | 
|  | switch (mitem->get_vtype ()) | 
|  | { | 
|  | default: | 
|  | table->store (nv++, dbeGetTableDataOneColumn (data, index)); | 
|  | break; | 
|  | case VT_LABEL: | 
|  | Vector<char*> *jobjects = new Vector<char*>(nitems); | 
|  | char *buf = NULL; | 
|  | size_t bufsz = 0; | 
|  | int lspace = 0; | 
|  | if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 | 
|  | || type == DSP_DISASM_V2) | 
|  | { | 
|  | // if this is source or disassembly, where we'll insert | 
|  | //	a preface into the output line, figure out how wide | 
|  | //	it needs to be | 
|  | // first, scan all the lines, to get the maximum line number | 
|  | bufsz = 1024; | 
|  | buf = (char *) xmalloc (bufsz); | 
|  | int max_lineno = 0; | 
|  | int hidx; | 
|  | Hist_data::HistItem *hitem; | 
|  | Vec_loop (Hist_data::HistItem*, data, hidx, hitem) | 
|  | { | 
|  | if (!hitem->obj) | 
|  | continue; | 
|  | if (hitem->obj->get_type () == Histable::LINE && | 
|  | ((DbeLine*) hitem->obj)->lineno > max_lineno) | 
|  | max_lineno = ((DbeLine*) hitem->obj)->lineno; | 
|  | else if (hitem->obj->get_type () == Histable::INSTR | 
|  | && ((DbeInstr*) hitem->obj)->lineno > max_lineno) | 
|  | max_lineno = ((DbeInstr*) hitem->obj)->lineno; | 
|  | } | 
|  |  | 
|  | // we have the maximum integer over all linenumbers in the file | 
|  | // 	figure out how many digits are needed | 
|  | lspace = snprintf (buf, bufsz, NTXT ("%d"), max_lineno); | 
|  | } | 
|  |  | 
|  | for (index2 = 0; index2 < nitems; index2++) | 
|  | { | 
|  | item = data->fetch (index2); | 
|  | if (type == DSP_DLAYOUT) | 
|  | cell = dbe_strdup (((DataObject*) (item->obj))->get_offset_name ()); | 
|  | else if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 || type == DSP_DISASM_V2) | 
|  | { | 
|  | // This code is duplicated in output.cc, yet it's | 
|  | // intended for presentation purpose and thus is | 
|  | // potentially different for er_print and analyzer. | 
|  | switch (item->type) | 
|  | { | 
|  | case Module::AT_SRC_ONLY: | 
|  | case Module::AT_SRC: | 
|  | if (item->obj == NULL) | 
|  | snprintf (buf, bufsz, NTXT (" %*c. "), lspace, ' '); | 
|  | else | 
|  | snprintf (buf, bufsz, NTXT (" %*d. "), lspace, | 
|  | ((DbeLine*) item->obj)->lineno); | 
|  | break; | 
|  | case Module::AT_FUNC: | 
|  | case Module::AT_QUOTE: | 
|  | snprintf (buf, bufsz, NTXT ("%*c"), lspace + 3, ' '); | 
|  | break; | 
|  | case Module::AT_DIS: | 
|  | case Module::AT_DIS_ONLY: | 
|  | if (item->obj == NULL || ((DbeInstr*) item->obj)->lineno == -1) | 
|  | snprintf (buf, bufsz, NTXT ("%*c[%*s] "), lspace + 3, ' ', | 
|  | lspace, NTXT ("?")); | 
|  | else | 
|  | snprintf (buf, bufsz, NTXT ("%*c[%*d] "), lspace + 3, ' ', | 
|  | lspace, | 
|  | ((DbeInstr*) item->obj)->lineno); | 
|  | break; | 
|  | case Module::AT_COM: | 
|  | case Module::AT_EMPTY: | 
|  | *buf = (char) 0; | 
|  | break; | 
|  | } | 
|  | // get the line's text | 
|  | char *s = item->value[index].l; | 
|  | if (s != NULL) | 
|  | { | 
|  | // copy the string expanding all tabulations | 
|  | // (JTable doesn't render them) | 
|  | char *d = buf + strlen (buf); | 
|  | char c; | 
|  | size_t column = 0; | 
|  | do | 
|  | { | 
|  | c = *s++; | 
|  | if (c == '\t') | 
|  | { | 
|  | do | 
|  | { | 
|  | *d++ = ' '; | 
|  | column++; | 
|  | } | 
|  | while (column & 07); | 
|  | } | 
|  | else | 
|  | { | 
|  | *d++ = c; | 
|  | column++; | 
|  | } | 
|  | if (column + 32 > bufsz) | 
|  | { | 
|  | // Reallocate the buffer | 
|  | size_t curlen = d - buf; | 
|  | bufsz += 1024; | 
|  | char *buf_new = (char *) xmalloc (bufsz); | 
|  | strncpy (buf_new, buf, curlen); | 
|  | buf_new[curlen] = '\0'; | 
|  | free (buf); | 
|  | buf = buf_new; | 
|  | d = buf + curlen; | 
|  | } | 
|  | } | 
|  | while (c != (char) 0); | 
|  | } | 
|  | cell = dbe_strdup (buf); | 
|  | } | 
|  | else | 
|  | { | 
|  | Histable::NameFormat nfmt = dbev->get_name_format (); | 
|  | cell = dbe_strdup (item->obj->get_name (nfmt)); | 
|  | } | 
|  | jobjects->store (index2, cell); | 
|  | } | 
|  |  | 
|  | if (type == DSP_SOURCE || type == DSP_DISASM || type == DSP_SOURCE_V2 | 
|  | || type == DSP_DISASM_V2) | 
|  | free (buf); | 
|  | table->store (nv++, jobjects); | 
|  | break; | 
|  | } | 
|  | } | 
|  | table->append (dbeGetMetricList (mlist)); | 
|  | return table; | 
|  | } // dbeGetFuncListV2 | 
|  |  | 
|  | // | 
|  | // Get Table DataV2 | 
|  | // | 
|  | Vector<void*> * | 
|  | dbeGetTableDataV2 (int dbevindex, char *mlistStr, char *modeStr, char *typeStr, | 
|  | char *subtypeStr, Vector<uint64_t> *ids) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  |  | 
|  | // Process metric list specification | 
|  | if (mlistStr == NULL) | 
|  | return NULL; | 
|  | bool met_call = false; | 
|  | MetricList *mlist = NULL; | 
|  | if (streq (mlistStr, NTXT ("MET_NORMAL"))) | 
|  | mlist = dbev->get_metric_list (MET_NORMAL); | 
|  | else if (streq (mlistStr, NTXT ("MET_CALL"))) | 
|  | { | 
|  | met_call = true; | 
|  | mlist = dbev->get_metric_list (MET_CALL); | 
|  | } | 
|  | else if (streq (mlistStr, NTXT ("MET_CALL_AGR"))) | 
|  | mlist = dbev->get_metric_list (MET_CALL_AGR); | 
|  | else if (streq (mlistStr, NTXT ("MET_DATA"))) | 
|  | mlist = dbev->get_metric_list (MET_DATA); | 
|  | else if (streq (mlistStr, NTXT ("MET_INDX"))) | 
|  | mlist = dbev->get_metric_list (MET_INDX); | 
|  | else if (streq (mlistStr, NTXT ("MET_IO"))) | 
|  | mlist = dbev->get_metric_list (MET_IO); | 
|  | else if (streq (mlistStr, NTXT ("MET_HEAP"))) | 
|  | mlist = dbev->get_metric_list (MET_HEAP); | 
|  | else | 
|  | return NULL; | 
|  |  | 
|  | // Process mode specification | 
|  | if (modeStr == NULL) | 
|  | return NULL; | 
|  | Hist_data::Mode mode = (Hist_data::Mode)0; | 
|  | if (streq (modeStr, NTXT ("CALLERS"))) | 
|  | mode = Hist_data::CALLERS; | 
|  | else if (streq (modeStr, NTXT ("CALLEES"))) | 
|  | mode = Hist_data::CALLEES; | 
|  | else if (streq (modeStr, NTXT ("SELF"))) | 
|  | mode = Hist_data::SELF; | 
|  | else if (streq (modeStr, NTXT ("ALL"))) | 
|  | mode = Hist_data::ALL; | 
|  | else | 
|  | return NULL; | 
|  |  | 
|  | // Process type specification | 
|  | if (typeStr == NULL) | 
|  | return NULL; | 
|  | Histable::Type type = Histable::OTHER; | 
|  | if (streq (typeStr, NTXT ("FUNCTION"))) | 
|  | type = Histable::FUNCTION; | 
|  | else if (streq (typeStr, NTXT ("INDEXOBJ"))) | 
|  | type = Histable::INDEXOBJ; | 
|  | else if (streq (typeStr, NTXT ("IOACTFILE"))) | 
|  | type = Histable::IOACTFILE; | 
|  | else if (streq (typeStr, NTXT ("IOACTVFD"))) | 
|  | type = Histable::IOACTVFD; | 
|  | else if (streq (typeStr, NTXT ("IOCALLSTACK"))) | 
|  | type = Histable::IOCALLSTACK; | 
|  | else if (streq (typeStr, NTXT ("HEAPCALLSTACK"))) | 
|  | type = Histable::HEAPCALLSTACK; | 
|  | else if (streq (typeStr, NTXT ("LINE"))) | 
|  | type = Histable::LINE; | 
|  | else if (streq (typeStr, NTXT ("INSTR"))) | 
|  | type = Histable::INSTR; | 
|  | else | 
|  | // XXX Accepting objects other than above may require a different | 
|  | // implementation of the id -> Histable mapping below | 
|  | return NULL; | 
|  |  | 
|  | // Process subtype specification | 
|  | int subtype = 0; | 
|  | if (subtypeStr != NULL) | 
|  | subtype = atoi (subtypeStr); | 
|  | Vector<Histable*> *hobjs = NULL; | 
|  | if (ids != NULL) | 
|  | { | 
|  | hobjs = new Vector<Histable*>(); | 
|  | for (int i = 0; i < ids->size (); ++i) | 
|  | { | 
|  | Histable::Type obj_type = type; | 
|  | if ((obj_type == Histable::LINE || obj_type == Histable::INSTR) | 
|  | && subtype == 0) | 
|  | obj_type = Histable::FUNCTION; | 
|  | Histable *hobj = dbeSession->findObjectById (obj_type, subtype, ids->fetch (i)); | 
|  | if ((obj_type == Histable::LINE || obj_type == Histable::INSTR) | 
|  | && subtype == 0 && hobj == NULL) | 
|  | return NULL; | 
|  | hobjs->append (hobj); | 
|  | } | 
|  | } | 
|  |  | 
|  | PathTree::PtreeComputeOption flag = PathTree::COMPUTEOPT_NONE; | 
|  | if (dbev->isOmpDisMode () && type == Histable::FUNCTION | 
|  | && mode == Hist_data::CALLEES && met_call) | 
|  | flag = PathTree::COMPUTEOPT_OMP_CALLEE; | 
|  |  | 
|  | Hist_data *data = dbev->get_hist_data (mlist, type, subtype, mode, hobjs, NULL, NULL, flag); | 
|  | return dbeGetTableDataV2Data (dbev, data); | 
|  | } | 
|  |  | 
|  | static Vector<void*> * | 
|  | dbeGetTableDataV2Data (DbeView * /*dbev*/, Hist_data *data) | 
|  | { | 
|  | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | 
|  | return NULL; | 
|  | MetricList *mlist; | 
|  | mlist = data->get_metric_list (); | 
|  | int nitems = data->size (); | 
|  |  | 
|  | // Initialize Java String array | 
|  | Vector<void*> *table = new Vector<void*>(mlist->size () + 1); | 
|  |  | 
|  | // Fill function list elements | 
|  | for (long i = 0, sz = mlist->size (); i < sz; i++) | 
|  | { | 
|  | Metric *mitem = mlist->get (i); | 
|  | if (!mitem->is_visible () && !mitem->is_tvisible () && | 
|  | !mitem->is_pvisible ()) | 
|  | continue; | 
|  | table->append (dbeGetTableDataOneColumn (data, i)); | 
|  | } | 
|  |  | 
|  | // Add an array of Histable IDs | 
|  | Vector<uint64_t> *idList = new Vector<uint64_t>(nitems); | 
|  | for (int i = 0; i < nitems; ++i) | 
|  | { | 
|  | Hist_data::HistItem *item = data->fetch (i); | 
|  | if (item->obj->get_type () == Histable::LINE | 
|  | || item->obj->get_type () == Histable::INSTR) | 
|  | idList->store (i, (uint64_t) (item->obj)); | 
|  | else | 
|  | idList->store (i, item->obj->id); | 
|  | } | 
|  | table->append (idList); | 
|  | return table; | 
|  | } // dbeGetTableData | 
|  |  | 
|  | //YXXX try to use the following to consolidate similar cut/paste code | 
|  |  | 
|  | static Vector<void*> * | 
|  | dbeGetTableDataOneColumn (Hist_data *data, int met_ind) | 
|  | { | 
|  | // Allocates a vector and fills it with metric values for one column | 
|  | TValue res; | 
|  | Metric *m = data->get_metric_list ()->get (met_ind); | 
|  | if ((m->get_visbits () & VAL_RATIO) != 0) | 
|  | { | 
|  | Vector<double> *col = new Vector<double>(data->size ()); | 
|  | for (long row = 0, sz_row = data->size (); row < sz_row; row++) | 
|  | { | 
|  | TValue *v = data->get_value (&res, met_ind, row); | 
|  | double d = (v->tag != VT_LABEL) ? v->to_double () : 100.; // NaN | 
|  | col->append (d); | 
|  | } | 
|  | return (Vector<void*> *) col; | 
|  | } | 
|  |  | 
|  | switch (m->get_vtype ()) | 
|  | { | 
|  | case VT_DOUBLE: | 
|  | { | 
|  | Vector<double> *col = new Vector<double>(data->size ()); | 
|  | for (long row = 0, sz_row = data->size (); row < sz_row; row++) | 
|  | { | 
|  | TValue *v = data->get_value (&res, met_ind, row); | 
|  | col->append (v->d); | 
|  | } | 
|  | return (Vector<void*> *) col; | 
|  | } | 
|  | case VT_INT: | 
|  | { | 
|  | Vector<int> *col = new Vector<int>(data->size ()); | 
|  | for (long row = 0, sz_row = data->size (); row < sz_row; row++) | 
|  | { | 
|  | TValue *v = data->get_value (&res, met_ind, row); | 
|  | col->append (v->i); | 
|  | } | 
|  | return (Vector<void*> *) col; | 
|  | } | 
|  | case VT_ULLONG: | 
|  | case VT_LLONG: | 
|  | { | 
|  | Vector<long long> *col = new Vector<long long>(data->size ()); | 
|  | for (long row = 0, sz_row = data->size (); row < sz_row; row++) | 
|  | { | 
|  | TValue *v = data->get_value (&res, met_ind, row); | 
|  | col->append (v->ll); | 
|  | } | 
|  | return (Vector<void*> *) col; | 
|  | } | 
|  | case VT_ADDRESS: | 
|  | { | 
|  | Vector<long long> *col = new Vector<long long>(data->size ()); | 
|  | for (long row = 0, sz_row = data->size (); row < sz_row; row++) | 
|  | { | 
|  | TValue *v = data->get_value (&res, met_ind, row); | 
|  | // set the highest bit to mark this jlong as | 
|  | // a VT_ADDRESS (rather than a regular VT_LLONG) | 
|  | col->append (v->ll | 0x8000000000000000ULL); | 
|  | } | 
|  | return (Vector<void*> *) col; | 
|  | } | 
|  | case VT_LABEL: | 
|  | { | 
|  | Vector<char *> *col = new Vector<char *>(data->size ()); | 
|  | for (long row = 0, sz_row = data->size (); row < sz_row; row++) | 
|  | { | 
|  | TValue *v = data->get_value (&res, met_ind, row); | 
|  | col->append (dbe_strdup (v->l)); | 
|  | } | 
|  | return (Vector<void*> *) col; | 
|  | } | 
|  | default: | 
|  | return NULL; | 
|  | } | 
|  | } | 
|  |  | 
|  | static Vector<void*> * | 
|  | dbeGetTableDataOneColumn (DbeView *dbev, Vector<Hist_data::HistItem*> *data, | 
|  | ValueTag vtype, int metricColumnNumber) | 
|  | // Allocates a vector and fills it with metric values for one column | 
|  | { | 
|  | Vector<void*> *column_data = NULL; | 
|  | int nitems = data->size (); // number of rows | 
|  | int index = metricColumnNumber; | 
|  | switch (vtype) | 
|  | { | 
|  | case VT_DOUBLE: | 
|  | { | 
|  | Vector<double> *jd_list = new Vector<double>(nitems); | 
|  | for (int index2 = 0; index2 < nitems; index2++) | 
|  | { | 
|  | Hist_data::HistItem *item = data->fetch (index2); | 
|  | jd_list->store (index2, item->value[index].d); | 
|  | } | 
|  | column_data = (Vector<void*> *)jd_list; | 
|  | break; | 
|  | } | 
|  | case VT_INT: | 
|  | { | 
|  | Vector<int> *ji_list = new Vector<int>(nitems); | 
|  | for (int index2 = 0; index2 < nitems; index2++) | 
|  | { | 
|  | Hist_data::HistItem *item = data->fetch (index2); | 
|  | ji_list->store (index2, item->value[index].i); | 
|  | } | 
|  | column_data = (Vector<void*> *)ji_list; | 
|  | break; | 
|  | } | 
|  | case VT_ULLONG: | 
|  | case VT_LLONG: | 
|  | { | 
|  | Vector<long long> *jl_list = new Vector<long long>(nitems); | 
|  | for (int index2 = 0; index2 < nitems; index2++) | 
|  | { | 
|  | Hist_data::HistItem *item = data->fetch (index2); | 
|  | jl_list->store (index2, item->value[index].ll); | 
|  | } | 
|  | column_data = (Vector<void*> *)jl_list; | 
|  | break; | 
|  | } | 
|  | case VT_ADDRESS: | 
|  | { | 
|  | Vector<long long> *jl_list = new Vector<long long>(nitems); | 
|  | for (int index2 = 0; index2 < nitems; index2++) | 
|  | { | 
|  | Hist_data::HistItem *item = data->fetch (index2); | 
|  |  | 
|  | // set the highest bit to mark this jlong as | 
|  | // a VT_ADDRESS (rather than a regular VT_LLONG) | 
|  | uint64_t addr = item->value[index].ll; | 
|  | addr |= 0x8000000000000000ULL; | 
|  | jl_list->store (index2, addr); | 
|  | } | 
|  | column_data = (Vector<void*> *)jl_list; | 
|  | break; | 
|  | } | 
|  | case VT_LABEL: | 
|  | { | 
|  | Vector<char*> *jobjects = new Vector<char*>(nitems); | 
|  | for (int index2 = 0; index2 < nitems; index2++) | 
|  | { | 
|  | Hist_data::HistItem *item = data->fetch (index2); | 
|  |  | 
|  | // omazur: why don't we have it as metric value | 
|  | Histable::NameFormat nfmt = dbev->get_name_format (); | 
|  | char *str = dbe_strdup (item->obj->get_name (nfmt)); | 
|  | jobjects->store (index2, str); | 
|  | } | 
|  | column_data = (Vector<void*> *)jobjects; | 
|  | break; | 
|  | } | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | return column_data; | 
|  | } | 
|  |  | 
|  | int | 
|  | dbeGetCallTreeNumLevels (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | PathTree * ptree = dbev->get_path_tree (); | 
|  | if (ptree == NULL) | 
|  | return 0; | 
|  | return ptree->get_ftree_depth (); | 
|  | } | 
|  |  | 
|  | Vector<void*>* | 
|  | dbeGetCallTreeLevel (int dbevindex, char *mcmd, int level) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | PathTree * ptree = dbev->get_path_tree (); | 
|  | if (ptree == NULL) | 
|  | return NULL; | 
|  | if (mcmd == NULL) | 
|  | return NULL; | 
|  | BaseMetric *bm = dbeSession->find_base_reg_metric (mcmd); | 
|  | if (bm == NULL) | 
|  | return NULL; | 
|  | return ptree->get_ftree_level (bm, level); | 
|  | } | 
|  |  | 
|  | Vector<void*>* | 
|  | dbeGetCallTreeLevels (int dbevindex, char *mcmd) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | PathTree * ptree = dbev->get_path_tree (); | 
|  | if (ptree == NULL) | 
|  | return NULL; | 
|  | if (mcmd == NULL) | 
|  | return NULL; | 
|  | BaseMetric *bm = dbeSession->find_base_reg_metric (mcmd); | 
|  | if (bm == NULL) | 
|  | return NULL; | 
|  |  | 
|  | int depth = ptree->get_ftree_depth (); | 
|  | Vector<void*> *results = new Vector<void*>(depth); | 
|  | for (int ii = 0; ii < depth; ii++) | 
|  | results->append (ptree->get_ftree_level (bm, ii)); | 
|  | return results; | 
|  | } | 
|  |  | 
|  | Vector<void*>* | 
|  | dbeGetCallTreeLevelFuncs (int dbevindex, int start_level, int end_level) | 
|  | { // (0,-1) -> all levels | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | PathTree * ptree = dbev->get_path_tree (); | 
|  | if (ptree == NULL) | 
|  | return NULL; | 
|  |  | 
|  | int depth = ptree->get_ftree_depth (); | 
|  | if (start_level < 0) | 
|  | start_level = 0; | 
|  | if (end_level < 0 || end_level >= depth) | 
|  | end_level = depth - 1; | 
|  |  | 
|  | Histable::NameFormat nfmt = dbev->get_name_format (); //YXXX or fixed format? | 
|  | Vector<char*> *funcNames = new Vector<char*>(); | 
|  | Vector<long long> *funcIds = new Vector<long long>(); | 
|  | Vector<Obj> *funcObjs = new Vector<Obj>(); | 
|  |  | 
|  | if (start_level == 0 && end_level == depth - 1) | 
|  | return dbeGetCallTreeFuncs (dbevindex); | 
|  | else | 
|  | { | 
|  | for (int ii = start_level; ii <= end_level; ii++) | 
|  | { | 
|  | Vector<void*> *info = ptree->get_ftree_level (NULL, ii); /*no metric*/ | 
|  | if (!info) | 
|  | continue; | 
|  | Vector<long long> *fids = (Vector<long long> *)info->get (2); | 
|  | if (!fids) | 
|  | continue; | 
|  | int index; | 
|  | long long fid; | 
|  | Vec_loop (long long, fids, index, fid) | 
|  | { | 
|  | funcIds->append (fid); | 
|  | Histable *obj = dbeSession->findObjectById (fid); | 
|  | char * fname = obj ? dbe_strdup (obj->get_name (nfmt)) : NULL; | 
|  | funcNames->append (fname); | 
|  | funcObjs->append ((unsigned long) obj); // avoiding sign extension | 
|  | } | 
|  | destroy (info); | 
|  | } | 
|  | } | 
|  | Vector<void*> *results = new Vector<void*>(3); | 
|  | results->append (funcIds); | 
|  | results->append (funcNames); | 
|  | results->append (funcObjs); | 
|  | return results; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetCallTreeFuncs (int dbevindex) | 
|  | { // does not require ptree->get_ftree_level() to be computed | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | PathTree * ptree = dbev->get_path_tree (); | 
|  | if (ptree == NULL) | 
|  | return 0; | 
|  | Vector<Function*>* funcs = ptree->get_funcs (); // Unique functions in tree | 
|  | if (funcs == NULL) | 
|  | return NULL; | 
|  |  | 
|  | long sz = funcs->size (); | 
|  | Vector<void*> *results = new Vector<void*>(3); | 
|  | Vector<long long> *funcIds = new Vector<long long>(sz); | 
|  | Vector<char*> *funcNames = new Vector<char*>(sz); | 
|  | Vector<Obj> *funcObjs = new Vector<Obj>(sz); | 
|  |  | 
|  | int index; | 
|  | Function * func; | 
|  | Histable::NameFormat nfmt = dbev->get_name_format (); //YXXX or fixed format? | 
|  | Vec_loop (Function *, funcs, index, func) | 
|  | { | 
|  | funcIds->append (func->id); // do we need IDs? | 
|  | char *fname = dbe_strdup (func->get_name (nfmt)); | 
|  | funcNames->append (fname); | 
|  | funcObjs->append ((unsigned long) func); // avoiding sign extension | 
|  | } | 
|  | results->put (0, funcIds); | 
|  | results->put (1, funcNames); | 
|  | results->put (2, funcObjs); | 
|  | destroy (funcs); | 
|  | return results; | 
|  | } | 
|  |  | 
|  | Vector<void*>* | 
|  | dbeGetCallTreeChildren (int dbevindex, char *mcmd, Vector<int /*NodeIdx*/>*node_idxs) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | if (node_idxs == NULL || node_idxs->size () == 0) | 
|  | return NULL; | 
|  | long sz = node_idxs->size (); | 
|  | PathTree * ptree = dbev->get_path_tree (); | 
|  | if (ptree == NULL) | 
|  | return NULL; | 
|  | if (mcmd == NULL) | 
|  | return NULL; | 
|  | BaseMetric *bm = dbeSession->find_base_reg_metric (mcmd); | 
|  | if (bm == NULL) | 
|  | return NULL; | 
|  |  | 
|  | Vector<void*> *results = new Vector<void*>(sz); | 
|  | for (long ii = 0; ii < sz; ii++) | 
|  | { | 
|  | PathTree::NodeIdx nodeIdx = node_idxs->get (ii); // upcasted from int | 
|  | results->append (ptree->get_ftree_node_children (bm, nodeIdx)); | 
|  | } | 
|  | return results; | 
|  | } | 
|  |  | 
|  | Vector<int> * | 
|  | dbeGetGroupIds (int /*dbevindex*/) | 
|  | { | 
|  | Vector<ExpGroup*> *groups = dbeSession->expGroups; | 
|  | int sz = groups->size (); | 
|  | Vector<int> *grIds = new Vector<int>(sz); | 
|  | for (int i = 0; i < sz; i++) | 
|  | grIds->store (i, groups->fetch (i)->groupId); | 
|  | return grIds; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get label for name column | 
|  | // | 
|  | Vector<char*> * | 
|  | dbeGetNames (int dbevindex, int type, Obj sel_obj) | 
|  | { | 
|  | char *s0, *s1, *s2; | 
|  | bool need_strdup = true; | 
|  | switch (type) | 
|  | { | 
|  | case DSP_SOURCE_V2: | 
|  | case DSP_DISASM_V2: | 
|  | case DSP_SOURCE: | 
|  | case DSP_DISASM: | 
|  | { | 
|  | if (sel_obj) | 
|  | { | 
|  | Histable *selObj = (Histable*) sel_obj; | 
|  | Function *func = (Function *) selObj->convertto (Histable::FUNCTION); | 
|  | if (func) | 
|  | { | 
|  | char *names[3] = {NULL, NULL, NULL}; | 
|  | set_file_names (func, names); | 
|  | s0 = names[0]; | 
|  | s1 = names[1]; | 
|  | s2 = names[2]; | 
|  | need_strdup = false; | 
|  | break; | 
|  | } | 
|  | } | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | char **names = type == DSP_SOURCE || type == DSP_SOURCE_V2 ? dbev->names_src : dbev->names_dis; | 
|  | s0 = names[0]; | 
|  | s1 = names[1]; | 
|  | s2 = names[2]; | 
|  | break; | 
|  | } | 
|  | case DSP_LINE: | 
|  | s0 = GTXT ("Lines"); | 
|  | s1 = GTXT ("Function, line # in \"sourcefile\""); | 
|  | s2 = NTXT (""); | 
|  | break; | 
|  | case DSP_PC: | 
|  | s0 = GTXT ("PCs"); | 
|  | s1 = GTXT ("Function + offset"); | 
|  | s2 = NTXT (""); | 
|  | break; | 
|  | case DSP_DLAYOUT: | 
|  | s0 = GTXT ("Name"); | 
|  | s1 = GTXT ("* +offset .element"); | 
|  | s2 = NTXT (""); | 
|  | break; | 
|  | default: | 
|  | s0 = GTXT ("Name"); | 
|  | s1 = s2 = NTXT (""); | 
|  | break; | 
|  | } | 
|  | if (need_strdup) | 
|  | { | 
|  | s0 = dbe_strdup (s0); | 
|  | s1 = dbe_strdup (s1); | 
|  | s2 = dbe_strdup (s2); | 
|  | } | 
|  | Vector<char*> *table = new Vector<char*>(3); | 
|  | table->store (0, s0); | 
|  | table->store (1, s1); | 
|  | table->store (2, s2); | 
|  | return table; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get Total/Maximum element of Function List | 
|  | // | 
|  | Vector<void*> * | 
|  | dbeGetTotalMax (int dbevindex, int type, int subtype) | 
|  | { | 
|  | Hist_data *data; | 
|  | int index; | 
|  | Hist_data::HistItem *total_item, *maximum_item; | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  |  | 
|  | switch (type) | 
|  | { | 
|  | case DSP_LINE: | 
|  | data = dbev->line_data; | 
|  | break; | 
|  | case DSP_PC: | 
|  | data = dbev->pc_data; | 
|  | break; | 
|  | case DSP_CALLER: | 
|  | data = dbev->callers; | 
|  | break; | 
|  | case DSP_SELF: | 
|  | case DSP_CALLEE: | 
|  | data = dbev->callees; | 
|  | break; | 
|  | case DSP_DLAYOUT: | 
|  | data = dbev->dlay_data; | 
|  | break; | 
|  | case DSP_DATAOBJ: | 
|  | data = dbev->dobj_data; | 
|  | break; | 
|  | case DSP_MEMOBJ: | 
|  | data = dbev->get_indxobj_data (subtype); | 
|  | break; | 
|  | case DSP_INDXOBJ: | 
|  | data = dbev->get_indxobj_data (subtype); | 
|  | break; | 
|  | case DSP_FUNCTION: // annotated src/dis use func total/max | 
|  | case DSP_SOURCE: | 
|  | case DSP_DISASM: | 
|  | case DSP_SOURCE_V2: | 
|  | case DSP_DISASM_V2: | 
|  | data = dbev->func_data; | 
|  | break; | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | 
|  | return NULL; | 
|  |  | 
|  | // Get list size | 
|  | // XXX -- the original list has all items, visible or not; | 
|  | // XXX -- the one from Hist_data has only visible items, | 
|  | // XXX --    and should be the only ones computed | 
|  | // XXX --    Analyzer got confused (yesterday), when we used the shorter list | 
|  | // XXX -- Why can we fetch total/max for metrics never | 
|  | // XXX --    computed without core dumping? | 
|  | MetricList *mlist2 = data->get_metric_list (); | 
|  | int size = mlist2->get_items ()->size (); | 
|  |  | 
|  | // Initialize Java array | 
|  | Vector<void*> *total_max = new Vector<void*>(2); | 
|  | Vector<double> *total = new Vector<double>(size); | 
|  | Vector<double> *maximum = new Vector<double>(size); | 
|  |  | 
|  | // Fill total/maximum element | 
|  | total_item = data->get_totals (); | 
|  | maximum_item = data->get_maximums (); | 
|  |  | 
|  | for (index = 0; index < size; index++) | 
|  | { | 
|  | total->store (index, total_item->value[index].to_double ()); | 
|  | maximum->store (index, maximum_item->value[index].to_double ()); | 
|  | } | 
|  | total_max->store (0, total); | 
|  | total_max->store (1, maximum); | 
|  | return total_max; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Get Table of Overview List | 
|  | Vector<void*> * | 
|  | dbeGetStatisOverviewList (int dbevindex) | 
|  | { | 
|  | int size; | 
|  | Ovw_data **data; | 
|  | Ovw_data::Ovw_item labels, *totals; | 
|  | int nitems; | 
|  | int index, index2; | 
|  |  | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | dbev->error_msg = dbev->warning_msg = NULL; | 
|  |  | 
|  | size = dbeSession->nexps (); | 
|  | totals = new Ovw_data::Ovw_item[size + 1]; | 
|  | data = new Ovw_data*[size + 1]; | 
|  | data[0] = new Ovw_data (); | 
|  |  | 
|  | for (index = 1; index <= size; index++) | 
|  | { | 
|  | data[index] = dbev->get_ovw_data (index - 1); | 
|  | if (data[index] == NULL) | 
|  | { | 
|  | Ovw_data::reset_item (&totals[index]); // set contents to zeros | 
|  | continue; | 
|  | } | 
|  | data[0]->sum (data[index]); | 
|  | totals[index] = data[index]->get_totals (); //shallow copy! | 
|  | } | 
|  | totals[0] = data[0]->get_totals (); | 
|  |  | 
|  | // Get table size | 
|  | labels = data[0]->get_labels (); | 
|  | nitems = labels.size + 4; | 
|  |  | 
|  | // Initialize Java String array | 
|  | Vector<void*> *table = new Vector<void*>(size + 4); | 
|  | Vector<char*> *jobjects = new Vector<char*>(nitems); | 
|  |  | 
|  | // Set the label | 
|  | jobjects->store (0, dbe_strdup (GTXT ("Start Time (sec.)"))); | 
|  | jobjects->store (1, dbe_strdup (GTXT ("End Time (sec.)"))); | 
|  | jobjects->store (2, dbe_strdup (GTXT ("Duration (sec.)"))); | 
|  | jobjects->store (3, dbe_strdup (GTXT ("Total Thread Time (sec.)"))); | 
|  | jobjects->store (4, dbe_strdup (GTXT ("Average number of Threads"))); | 
|  |  | 
|  | for (index2 = 5; index2 < nitems; index2++) | 
|  | jobjects->store (index2, dbe_strdup (labels.values[index2 - 4].l)); | 
|  | table->store (0, jobjects); | 
|  |  | 
|  | // Set the data | 
|  | for (index = 0; index <= size; index++) | 
|  | { | 
|  | Vector<double> *jd_list = new Vector<double>(nitems); | 
|  | jd_list->store (0, tstodouble (totals[index].start)); | 
|  | jd_list->store (1, tstodouble (totals[index].end)); | 
|  | jd_list->store (2, tstodouble (totals[index].duration)); | 
|  | jd_list->store (3, tstodouble (totals[index].tlwp)); | 
|  | jd_list->store (4, totals[index].nlwp); | 
|  | for (index2 = 5; index2 < nitems; index2++) | 
|  | jd_list->store (index2, tstodouble (totals[index].values[index2 - 4].t)); | 
|  | table->store (index + 1, jd_list); | 
|  | } | 
|  | for (index = 0; index <= size; index++) | 
|  | delete data[index]; | 
|  | delete[] data; | 
|  | delete[] totals; | 
|  | return table; | 
|  | } | 
|  |  | 
|  | // Get Table of Statistics List | 
|  | Vector<void*> * | 
|  | dbeGetStatisList (int dbevindex) | 
|  | { | 
|  | int size; | 
|  | Stats_data **data; | 
|  | int nitems; | 
|  | int index, index2; | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | dbev->error_msg = dbev->warning_msg = NULL; | 
|  | if ((size = dbeSession->nexps ()) == 0) | 
|  | return NULL; | 
|  |  | 
|  | // Get statistics data | 
|  | data = (Stats_data **) xmalloc ((size + 1) * sizeof (Stats_data *)); | 
|  | data[0] = new Stats_data (); | 
|  | for (index = 1; index <= size; index++) | 
|  | { | 
|  | data[index] = dbev->get_stats_data (index - 1); | 
|  | if (data[index] == NULL) | 
|  | continue; | 
|  | data[0]->sum (data[index]); | 
|  | } | 
|  |  | 
|  | // Get table size | 
|  | nitems = data[0]->size (); | 
|  |  | 
|  | // Initialize Java String array | 
|  | Vector<void*> *table = new Vector<void*>(size + 2); | 
|  | Vector<char*> *jobjects = new Vector<char*>(nitems); | 
|  |  | 
|  | // Set the label | 
|  | for (index2 = 0; index2 < nitems; index2++) | 
|  | jobjects->store (index2, dbe_strdup (data[0]->fetch (index2).label)); | 
|  | table->store (0, jobjects); | 
|  |  | 
|  | // Set the data | 
|  | for (index = 0; index <= size; index++) | 
|  | { | 
|  | Vector<double> *jd_list = new Vector<double>(nitems); | 
|  | for (index2 = 0; index2 < nitems; index2++) | 
|  | { | 
|  | double val = 0; | 
|  | if (data[index]) | 
|  | val = data[index]->fetch (index2).value.to_double (); | 
|  | jd_list->store (index2, val); | 
|  | } | 
|  | table->store (index + 1, jd_list); | 
|  | } | 
|  | if (data) | 
|  | { | 
|  | for (index = 0; index <= size; index++) | 
|  | delete data[index]; | 
|  | free (data); | 
|  | } | 
|  | return table; | 
|  | } | 
|  |  | 
|  |  | 
|  | // | 
|  | // Set summary list | 
|  | // | 
|  | static void | 
|  | setSummary (Vector<Histable*> *objs, Vector<int> *saligns, | 
|  | Vector<char> *mnemonic, Vector<char*> *jlabels, Vector<char*> *jvalues) | 
|  | { | 
|  | char *sname = NULL, *oname = NULL, *lname = NULL, *alias = NULL, | 
|  | *mangle = NULL, *address = NULL, *size = NULL, | 
|  | *name_0 = NULL, *sname_0 = NULL, *oname_0 = NULL, *lname_0 = NULL, | 
|  | *alias_0 = NULL, *mangle_0 = NULL; | 
|  | Function *func, *last_func = NULL; | 
|  | int one_func = 1; | 
|  |  | 
|  | // Get the source/object/load-object files & aliases | 
|  | long long ll_size = 0; | 
|  | for (long i = 0; i < objs->size (); i++) | 
|  | { | 
|  | Histable *current_obj = objs->fetch (i); | 
|  | Histable::Type htype = current_obj->get_type (); | 
|  | if (htype == Histable::LOADOBJECT) | 
|  | lname = ((LoadObject *) current_obj)->dbeFile->get_location_info (); | 
|  | else if ((func = (Function*) current_obj->convertto (Histable::FUNCTION)) != NULL) | 
|  | { | 
|  | if (one_func && last_func != NULL && last_func != func) | 
|  | one_func = 0; | 
|  | last_func = func; | 
|  | sname = NULL; | 
|  | DbeLine *dbeline = (DbeLine*) current_obj->convertto (Histable::LINE); | 
|  | if (dbeline) | 
|  | { | 
|  | SourceFile *sf; | 
|  | if (dbeline->lineno == 0 && dbeline->include != NULL) | 
|  | sf = dbeline->include; | 
|  | else if (dbeline->sourceFile != NULL) | 
|  | sf = dbeline->sourceFile; | 
|  | else | 
|  | sf = func->getDefSrc (); | 
|  | if (sf) | 
|  | sname = sf->dbeFile->get_location_info (); | 
|  | } | 
|  | char *func_name = func->get_name (); | 
|  | mangle = func->get_mangled_name (); | 
|  | if (mangle && streq (func_name, mangle)) | 
|  | mangle = NULL; | 
|  | Module *module = func->module; | 
|  | if (module != NULL) | 
|  | { | 
|  | module->read_stabs (); | 
|  | if (sname == NULL || strlen (sname) == 0) | 
|  | { | 
|  | SourceFile *sf = module->getMainSrc (); | 
|  | sname = sf->dbeFile->get_location_info (); | 
|  | } | 
|  | DbeFile *df = module->dbeFile; | 
|  | if (df == NULL || (df->filetype & DbeFile::F_JAVACLASS) == 0) | 
|  | df = module->loadobject->dbeFile; | 
|  | lname = df->get_location_info (); | 
|  | oname = lname; | 
|  | if (module->dot_o_file) | 
|  | oname = module->dot_o_file->dbeFile->get_location_info (); | 
|  | } | 
|  |  | 
|  | if (htype == Histable::INSTR && dbeSession->is_datamode_available ()) | 
|  | alias = ((DbeInstr*) current_obj)->get_descriptor (); | 
|  | } | 
|  |  | 
|  | char *name = current_obj->get_name (); | 
|  | if (i == 0) | 
|  | { | 
|  | name_0 = name; | 
|  | lname_0 = lname; | 
|  | sname_0 = sname; | 
|  | oname_0 = oname; | 
|  | mangle_0 = mangle; | 
|  | alias_0 = alias; | 
|  | if (objs->size () == 1) | 
|  | { | 
|  | uint64_t addr = current_obj->get_addr (); | 
|  | address = dbe_sprintf (NTXT ("%lld:0x%08llX"), | 
|  | (long long) ADDRESS_SEG (addr), | 
|  | (long long) ADDRESS_OFF (addr)); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | if (name_0 != name) | 
|  | name_0 = NULL; | 
|  | if (lname_0 != lname) | 
|  | lname_0 = NULL; | 
|  | if (sname_0 != sname) | 
|  | sname_0 = NULL; | 
|  | if (oname_0 != oname) | 
|  | oname_0 = NULL; | 
|  | if (mangle_0 != mangle) | 
|  | mangle_0 = NULL; | 
|  | if (alias_0 != alias) | 
|  | alias_0 = NULL; | 
|  | } | 
|  | if (current_obj->get_size () == -1) | 
|  | { | 
|  | if (size == NULL) | 
|  | size = dbe_strdup (GTXT ("(Unknown)")); | 
|  | } | 
|  | else | 
|  | ll_size += current_obj->get_size (); | 
|  | } | 
|  | if (size == NULL) | 
|  | size = dbe_sprintf (NTXT ("%lld"), ll_size); | 
|  | if (name_0 == NULL) | 
|  | { | 
|  | if (objs->size () > 1) | 
|  | { | 
|  | char *func_name = last_func == NULL ? NULL : | 
|  | (one_func == 0 ? NULL : last_func->get_name ()); | 
|  | name_0 = dbe_sprintf (NTXT ("%s%s%s (%lld %s)"), | 
|  | func_name == NULL ? "" : func_name, | 
|  | func_name == NULL ? "" : ": ", | 
|  | GTXT ("Multiple Selection"), | 
|  | (long long) objs->size (), | 
|  | GTXT ("objects")); | 
|  | } | 
|  | } | 
|  | else | 
|  | name_0 = dbe_strdup (name_0); | 
|  |  | 
|  | // Set the name area | 
|  | saligns->store (0, TEXT_LEFT); | 
|  | mnemonic->store (0, 'N'); | 
|  | jlabels->store (0, dbe_strdup (GTXT ("Name"))); | 
|  | jvalues->store (0, name_0); | 
|  |  | 
|  | saligns->store (1, TEXT_LEFT); | 
|  | mnemonic->store (1, 'P'); | 
|  | jlabels->store (1, dbe_strdup (GTXT ("PC Address"))); | 
|  | jvalues->store (1, address); | 
|  |  | 
|  | saligns->store (2, TEXT_LEFT); | 
|  | mnemonic->store (2, 'z'); | 
|  | jlabels->store (2, dbe_strdup (GTXT ("Size"))); | 
|  | jvalues->store (2, size); | 
|  |  | 
|  | saligns->store (3, TEXT_RIGHT); | 
|  | mnemonic->store (3, 'r'); | 
|  | jlabels->store (3, dbe_strdup (GTXT ("Source File"))); | 
|  | jvalues->store (3, dbe_strdup (sname_0)); | 
|  |  | 
|  | saligns->store (4, TEXT_RIGHT); | 
|  | mnemonic->store (4, 'b'); | 
|  | jlabels->store (4, dbe_strdup (GTXT ("Object File"))); | 
|  | jvalues->store (4, dbe_strdup (oname_0)); | 
|  |  | 
|  | saligns->store (5, TEXT_LEFT); | 
|  | mnemonic->store (5, 'j'); | 
|  | jlabels->store (5, dbe_strdup (GTXT ("Load Object"))); | 
|  | jvalues->store (5, dbe_strdup (lname_0)); | 
|  |  | 
|  | saligns->store (6, TEXT_LEFT); | 
|  | mnemonic->store (6, 'm'); | 
|  | jlabels->store (6, dbe_strdup (GTXT ("Mangled Name"))); | 
|  | jvalues->store (6, dbe_strdup (mangle_0)); | 
|  |  | 
|  | saligns->store (7, TEXT_LEFT); | 
|  | mnemonic->store (7, 'A'); | 
|  | jlabels->store (7, dbe_strdup (GTXT ("Aliases"))); | 
|  | jvalues->store (7, dbe_strdup (alias_0)); | 
|  | } | 
|  |  | 
|  | // Set memory-object summary list | 
|  | // | 
|  | static void | 
|  | setMemSummary (Vector<Histable*> *objs, Vector<int> *saligns, | 
|  | Vector<char> *mnemonic, Vector<char*> *jlabels, | 
|  | Vector<char*> *jvalues) | 
|  | { | 
|  | saligns->store (0, TEXT_LEFT); | 
|  | mnemonic->store (0, 'M'); | 
|  | jlabels->store (0, dbe_strdup (GTXT ("Memory Object"))); | 
|  | if (objs->size () == 1) | 
|  | { | 
|  | Histable *current_obj = objs->fetch (0); | 
|  | jvalues->store (0, dbe_strdup (current_obj->get_name ())); | 
|  | } | 
|  | else | 
|  | { | 
|  | char *name = dbe_sprintf (NTXT ("%s (%lld %s)"), | 
|  | GTXT ("Multiple Selection"), | 
|  | (long long) objs->size (), GTXT ("objects")); | 
|  | jvalues->store (0, name); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Set index-object summary list | 
|  | // | 
|  | static void | 
|  | setIndxSummary (Vector<Histable*> *objs, Vector<int> *saligns, | 
|  | Vector<char> *mnemonic, Vector<char*> *jlabels, | 
|  | Vector<char*> *jvalues) | 
|  | { | 
|  | saligns->store (0, TEXT_LEFT); | 
|  | mnemonic->store (0, 'I'); | 
|  | jlabels->store (0, dbe_strdup (GTXT ("Index Object"))); | 
|  |  | 
|  | if (objs->size () == 1) | 
|  | { | 
|  | Histable *current_obj = objs->fetch (0); | 
|  | jvalues->store (0, dbe_strdup (current_obj->get_name ())); | 
|  | } | 
|  | else | 
|  | { | 
|  | char *name = dbe_sprintf (NTXT ("%s (%lld %s)"), GTXT ("Multiple Selection"), | 
|  | (long long) objs->size (), GTXT ("objects")); | 
|  | jvalues->store (0, name); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Set I/O activity summary list | 
|  | // | 
|  | static void | 
|  | setIOActivitySummary (Vector<Histable*> *objs, Vector<int> *saligns, | 
|  | Vector<char> *mnemonic, Vector<char*> *jlabels, | 
|  | Vector<char*> *jvalues) | 
|  | { | 
|  | saligns->store (0, TEXT_LEFT); | 
|  | mnemonic->store (0, 'O'); | 
|  | jlabels->store (0, dbe_strdup (GTXT ("I/O Activity"))); | 
|  | if (objs->size () == 1) | 
|  | { | 
|  | Histable *current_obj = objs->fetch (0); | 
|  | jvalues->store (0, dbe_strdup (current_obj->get_name ())); | 
|  | } | 
|  | else | 
|  | { | 
|  | char *name = dbe_sprintf (NTXT ("%s (%lld %s)"), GTXT ("Multiple Selection"), | 
|  | (long long) objs->size (), GTXT ("objects")); | 
|  | jvalues->store (0, name); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Set heap activity summary list | 
|  | // | 
|  | static void | 
|  | setHeapActivitySummary (Vector<Histable*> *objs, Vector<int> *saligns, | 
|  | Vector<char> *mnemonic, Vector<char*> *jlabels, | 
|  | Vector<char*> *jvalues) | 
|  | { | 
|  | saligns->store (0, TEXT_LEFT); | 
|  | mnemonic->store (0, 'O'); | 
|  | jlabels->store (0, dbe_strdup (GTXT ("Heap Activity"))); | 
|  |  | 
|  | if (objs->size () == 1) | 
|  | { | 
|  | Histable *current_obj = objs->fetch (0); | 
|  | jvalues->store (0, dbe_strdup (current_obj->get_name ())); | 
|  | } | 
|  | else | 
|  | { | 
|  | char *name = dbe_sprintf (NTXT ("%s (%lld %s)"), GTXT ("Multiple Selection"), | 
|  | (long long) objs->size (), GTXT ("objects")); | 
|  | jvalues->store (0, name); | 
|  | } | 
|  | } | 
|  |  | 
|  | // | 
|  | // Set data-object summary list | 
|  | // | 
|  | static void | 
|  | setDataSummary (Vector<Histable*> *objs, Vector<int> *saligns, | 
|  | Vector<char> *mnemonic, Vector<char*> *jlabels, | 
|  | Vector<char*> *jvalues) | 
|  | { | 
|  | char *name, *type, *member, *elist; | 
|  | DataObject *dobj; | 
|  | Vector<DataObject *> *delem; | 
|  | Histable *scope; | 
|  | int index; | 
|  | char *size, *offset, *elements, *scopename; | 
|  |  | 
|  | // Get the data object elements | 
|  | member = elist = type = size = offset = elements = scopename = NULL; | 
|  |  | 
|  | if (objs->size () == 1) | 
|  | { | 
|  | Histable *current_obj = objs->fetch (0); | 
|  | name = dbe_strdup (current_obj->get_name ()); | 
|  | dobj = (DataObject *) current_obj; | 
|  | type = dobj->get_typename (); | 
|  | scope = dobj->get_scope (); | 
|  | delem = dbeSession->get_dobj_elements (dobj); | 
|  | if (type == NULL) | 
|  | type = GTXT ("(Synthetic)"); | 
|  | if (!scope) | 
|  | scopename = dbe_strdup (GTXT ("(Global)")); | 
|  | else | 
|  | { | 
|  | switch (scope->get_type ()) | 
|  | { | 
|  | case Histable::FUNCTION: | 
|  | scopename = dbe_sprintf (NTXT ("%s(%s)"), | 
|  | ((Function*) scope)->module->get_name (), | 
|  | scope->get_name ()); | 
|  | break; | 
|  | case Histable::LOADOBJECT: | 
|  | case Histable::MODULE: | 
|  | default: | 
|  | scopename = dbe_strdup (scope->get_name ()); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (dobj->get_offset () != -1) | 
|  | { | 
|  | if (dobj->get_parent ()) | 
|  | member = dbe_strdup (dobj->get_parent ()->get_name ()); | 
|  | offset = dbe_sprintf (NTXT ("%lld"), (long long) dobj->get_offset ()); | 
|  | } | 
|  | size = dbe_sprintf ("%lld", (long long) dobj->get_size ()); | 
|  |  | 
|  | if (delem->size () > 0) | 
|  | { | 
|  | elements = dbe_sprintf (NTXT ("%lld"), (long long) delem->size ()); | 
|  | StringBuilder sb_tmp, sb; | 
|  | sb.append (GTXT ("Offset Size  Name\n")); | 
|  | for (index = 0; index < delem->size (); index++) | 
|  | { | 
|  | DataObject *ditem = delem->fetch (index); | 
|  | sb_tmp.sprintf (NTXT ("%6lld %5lld  %s\n"), | 
|  | (long long) ditem->get_offset (), | 
|  | (long long) ditem->get_size (), ditem->get_name ()); | 
|  | sb.append (&sb_tmp); | 
|  | } | 
|  | if (sb.charAt (sb.length () - 1) == '\n') | 
|  | sb.setLength (sb.length () - 1); | 
|  | elist = sb.toString (); | 
|  | } | 
|  | } | 
|  | else | 
|  | name = dbe_sprintf (NTXT ("%s (%lld %s)"), GTXT ("Multiple Selection"), | 
|  | (long long) objs->size (), GTXT ("objects")); | 
|  |  | 
|  | saligns->store (0, TEXT_LEFT); | 
|  | mnemonic->store (0, 'D'); | 
|  | jlabels->store (0, dbe_strdup (GTXT ("Data Object"))); | 
|  | jvalues->store (0, name); | 
|  |  | 
|  | saligns->store (1, TEXT_LEFT); | 
|  | mnemonic->store (1, 'S'); | 
|  | jlabels->store (1, dbe_strdup (GTXT ("Scope"))); | 
|  | jvalues->store (1, scopename); | 
|  |  | 
|  | saligns->store (2, TEXT_LEFT); | 
|  | mnemonic->store (2, 'T'); | 
|  | jlabels->store (2, dbe_strdup (GTXT ("Type"))); | 
|  | jvalues->store (2, dbe_strdup (type)); | 
|  |  | 
|  | saligns->store (3, TEXT_LEFT); | 
|  | mnemonic->store (3, 'M'); | 
|  | jlabels->store (3, dbe_strdup (GTXT ("Member of"))); | 
|  | jvalues->store (3, member); | 
|  |  | 
|  | saligns->store (4, TEXT_LEFT); | 
|  | mnemonic->store (4, 'O'); | 
|  | jlabels->store (4, dbe_strdup (GTXT ("Offset"))); | 
|  | jvalues->store (4, offset); | 
|  |  | 
|  | saligns->store (5, TEXT_LEFT); | 
|  | mnemonic->store (5, 'z'); | 
|  | jlabels->store (5, dbe_strdup (GTXT ("Size"))); | 
|  | jvalues->store (5, size); | 
|  |  | 
|  | saligns->store (6, TEXT_LEFT); | 
|  | mnemonic->store (6, 'E'); | 
|  | jlabels->store (6, dbe_strdup (GTXT ("Elements"))); | 
|  | jvalues->store (6, elements); | 
|  |  | 
|  | saligns->store (7, TEXT_LEFT); | 
|  | mnemonic->store (7, 'L'); | 
|  | jlabels->store (7, dbe_strdup (GTXT ("List"))); | 
|  | jvalues->store (7, elist); | 
|  | } | 
|  |  | 
|  | #define SUMMARY_NAME 8 | 
|  | #define DSUMMARY_NAME 8 | 
|  | #define LSUMMARY_NAME   7 | 
|  | #define IMSUMMARY_NAME   1 | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetSummaryV2 (int dbevindex, Vector<Obj> *sel_objs, int type, int subtype) | 
|  | { | 
|  | if (sel_objs == NULL || sel_objs->size () == 0) | 
|  | return NULL; | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | Vector<Histable*>*objs = new Vector<Histable*>(sel_objs->size ()); | 
|  | for (int i = 0; i < sel_objs->size (); i++) | 
|  | { | 
|  | Histable *obj = (Histable *) sel_objs->fetch (i); | 
|  | if (obj == NULL) | 
|  | continue; | 
|  | char *nm = obj->get_name (); | 
|  | if (streq (nm, NTXT ("<Total>"))) | 
|  | { | 
|  | // Special case for 'Total'. | 
|  | // Multi selection which includes 'Total' is only 'Total' | 
|  | objs->reset (); | 
|  | objs->append (obj); | 
|  | break; | 
|  | } | 
|  | objs->append (obj); | 
|  | } | 
|  | if (objs->size () == 0) | 
|  | return NULL; | 
|  |  | 
|  | // Set name area | 
|  | int nname = SUMMARY_NAME; | 
|  | Vector<int> *saligns = new Vector<int>(nname); | 
|  | Vector<char>*mnemonic = new Vector<char>(nname); | 
|  | Vector<char*> *jlabels = new Vector<char*>(nname); | 
|  | Vector<char*> *jvalues = new Vector<char*>(nname); | 
|  | Vector<void*> *name_objs = new Vector<void*>(4); | 
|  | name_objs->store (0, saligns); | 
|  | name_objs->store (1, mnemonic); | 
|  | name_objs->store (2, jlabels); | 
|  | name_objs->store (3, jvalues); | 
|  | setSummary (objs, saligns, mnemonic, jlabels, jvalues); | 
|  |  | 
|  | MetricList *prop_mlist = new MetricList (dbev->get_metric_ref (MET_NORMAL)); | 
|  | if (prop_mlist && dbev->comparingExperiments ()) | 
|  | prop_mlist = dbev->get_compare_mlist (prop_mlist, 0); | 
|  |  | 
|  | int nitems = prop_mlist->get_items ()->size (); | 
|  |  | 
|  | // Set the metrics area | 
|  | jlabels = new Vector<char*>(nitems); | 
|  | Vector<double> *clock_list = new Vector<double>(nitems); | 
|  | Vector<double> *excl_list = new Vector<double>(nitems); | 
|  | Vector<double> *ep_list = new Vector<double>(nitems); | 
|  | Vector<double> *incl_list = new Vector<double>(nitems); | 
|  | Vector<double> *ip_list = new Vector<double>(nitems); | 
|  | Vector<int> *vtype = new Vector<int>(nitems); | 
|  |  | 
|  | // Initialize Java String array | 
|  | Vector<void*> *metric_objs = new Vector<void*>(8); | 
|  | metric_objs->store (0, jlabels); | 
|  | metric_objs->store (1, clock_list); | 
|  | metric_objs->store (2, excl_list); | 
|  | metric_objs->store (3, ep_list); | 
|  | metric_objs->store (4, incl_list); | 
|  | metric_objs->store (5, ip_list); | 
|  | metric_objs->store (6, vtype); | 
|  |  | 
|  | int last_init = -1; | 
|  | for (int i = 0; i < objs->size (); i++) | 
|  | { | 
|  | Histable *obj = objs->fetch (i); | 
|  | // Get the data to be displayed | 
|  | Hist_data *data = dbev->get_hist_data (prop_mlist, obj->get_type (), subtype, | 
|  | Hist_data::SELF, obj, dbev->sel_binctx, objs); | 
|  |  | 
|  | if (data->get_status () != Hist_data::SUCCESS) | 
|  | { | 
|  | if (type != DSP_DLAYOUT) | 
|  | { // For data_layout, rows with zero metrics are OK | 
|  | delete data; | 
|  | continue; | 
|  | } | 
|  | } | 
|  | TValue *values = NULL; | 
|  | if (data->get_status () == Hist_data::SUCCESS) | 
|  | { | 
|  | Hist_data::HistItem *hi = data->fetch (0); | 
|  | if (hi) | 
|  | values = hi->value; | 
|  | } | 
|  | Hist_data::HistItem *total = data->get_totals (); | 
|  | int index2 = 0; | 
|  | char *tstr = GTXT (" Time"); | 
|  | char *estr = GTXT ("Exclusive "); | 
|  | size_t len = strlen (estr); | 
|  |  | 
|  | // get the metric list from the data | 
|  | MetricList *mlist = data->get_metric_list (); | 
|  | int index; | 
|  | Metric *mitem; | 
|  | double clock; | 
|  | Vec_loop (Metric*, mlist->get_items (), index, mitem) | 
|  | { | 
|  | if (mitem->get_subtype () == Metric::STATIC) | 
|  | continue; | 
|  | if (last_init < index2) | 
|  | { | 
|  | last_init = index2; | 
|  | jlabels->store (index2, NULL); | 
|  | clock_list->store (index2, 0.0); | 
|  | excl_list->store (index2, 0.0); | 
|  | ep_list->store (index2, 0.0); | 
|  | incl_list->store (index2, 0.0); | 
|  | ip_list->store (index2, 0.0); | 
|  | vtype->store (index2, 0); | 
|  | } | 
|  | double dvalue = (values != NULL) ? values[index].to_double () : 0.0; | 
|  | double dtotal = total->value[index].to_double (); | 
|  | if (mitem->is_time_val ()) | 
|  | clock = 1.e+6 * dbeSession->get_clock (-1); | 
|  | else | 
|  | clock = 0.0; | 
|  |  | 
|  | clock_list->store (index2, clock); | 
|  | if ((mitem->get_subtype () == Metric::EXCLUSIVE) || | 
|  | (mitem->get_subtype () == Metric::DATASPACE)) | 
|  | { | 
|  | if (i == 0) | 
|  | { | 
|  | char *sstr = mitem->get_name (); | 
|  | if (!strncmp (sstr, estr, len)) | 
|  | sstr += len; | 
|  | char *buf, *lstr = strstr (sstr, tstr); | 
|  | if (lstr) | 
|  | buf = dbe_strndup (sstr, lstr - sstr); | 
|  | else | 
|  | buf = dbe_strdup (sstr); | 
|  | jlabels->store (index2, buf); | 
|  | vtype->store (index2, mitem->get_vtype ()); | 
|  | } | 
|  | dvalue += excl_list->fetch (index2); | 
|  | double percent = dtotal == 0.0 ? dtotal : (dvalue / dtotal) * 100; | 
|  | excl_list->store (index2, dvalue); | 
|  | ep_list->store (index2, percent); | 
|  | } | 
|  | else | 
|  | { | 
|  | dvalue += incl_list->fetch (index2); | 
|  | if (dvalue > dtotal) | 
|  | dvalue = dtotal; // temporary correction | 
|  | double percent = dtotal == 0.0 ? dtotal : (dvalue / dtotal) * 100; | 
|  | incl_list->store (index2, dvalue); | 
|  | ip_list->store (index2, percent); | 
|  | index2++; | 
|  | } | 
|  | } | 
|  | delete data; | 
|  | } | 
|  | delete prop_mlist; | 
|  | Vector<void*> *summary = new Vector<void*>(2); | 
|  | summary->store (0, name_objs); | 
|  | summary->store (1, metric_objs); | 
|  | return summary; | 
|  | } | 
|  |  | 
|  | // Get Summary List | 
|  | Vector<void*> * | 
|  | dbeGetSummary (int dbevindex, Vector<Obj> *sel_objs, int type, int subtype) | 
|  | { | 
|  | bool is_data, is_mem, is_indx, is_iodata, is_heapdata; | 
|  | Hist_data::HistItem *total; | 
|  | MetricList *prop_mlist; // as passed to get_hist_data | 
|  | MetricList *mlist; // as stored in the data | 
|  | Metric *mitem; | 
|  | int i, nname, nitems, index, index2; | 
|  | TValue *values; | 
|  | double dvalue, clock; | 
|  | Hist_data *data; | 
|  | Vector<double> *percent_scale; | 
|  |  | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | if (sel_objs == NULL || sel_objs->size () == 0) | 
|  | return NULL; | 
|  |  | 
|  | is_mem = false; | 
|  | is_data = false; | 
|  | is_indx = false; | 
|  | is_iodata = false; | 
|  | is_heapdata = false; | 
|  | nname = SUMMARY_NAME; | 
|  | Vector<Histable*>*objs = new Vector<Histable*>(sel_objs->size ()); | 
|  | if (type == DSP_TIMELINE) | 
|  | objs->append ((Histable *) sel_objs->fetch (0)); | 
|  | else | 
|  | { | 
|  | switch (type) | 
|  | { | 
|  | case DSP_FUNCTION: | 
|  | data = dbev->func_data; | 
|  | break; | 
|  | case DSP_LINE: | 
|  | data = dbev->line_data; | 
|  | break; | 
|  | case DSP_PC: | 
|  | data = dbev->pc_data; | 
|  | break; | 
|  | case DSP_SELF: | 
|  | data = dbev->fitem_data; | 
|  | break; | 
|  | case DSP_SOURCE: | 
|  | case DSP_SOURCE_V2: | 
|  | data = dbev->src_data; | 
|  | break; | 
|  | case DSP_DISASM: | 
|  | case DSP_DISASM_V2: | 
|  | data = dbev->dis_data; | 
|  | break; | 
|  | case DSP_DLAYOUT: | 
|  | is_data = true; | 
|  | nname = LSUMMARY_NAME; | 
|  | data = dbev->dlay_data; | 
|  | break; | 
|  | case DSP_DATAOBJ: | 
|  | is_data = true; | 
|  | nname = DSUMMARY_NAME; | 
|  | data = dbev->dobj_data; | 
|  | break; | 
|  | case DSP_MEMOBJ: | 
|  | is_data = true; | 
|  | is_mem = true; | 
|  | nname = IMSUMMARY_NAME; | 
|  | data = dbev->get_indxobj_data (subtype); | 
|  | break; | 
|  | case DSP_INDXOBJ: | 
|  | is_indx = true; | 
|  | nname = IMSUMMARY_NAME; | 
|  | data = dbev->get_indxobj_data (subtype); | 
|  | break; | 
|  | case DSP_IOACTIVITY: | 
|  | is_iodata = true; | 
|  | nname = IMSUMMARY_NAME; | 
|  | data = dbev->iofile_data; | 
|  | break; | 
|  | case DSP_IOVFD: | 
|  | is_iodata = true; | 
|  | nname = IMSUMMARY_NAME; | 
|  | data = dbev->iovfd_data; | 
|  | break; | 
|  | case DSP_IOCALLSTACK: | 
|  | is_iodata = true; | 
|  | nname = IMSUMMARY_NAME; | 
|  | data = dbev->iocs_data; | 
|  | break; | 
|  | case DSP_HEAPCALLSTACK: | 
|  | is_heapdata = true; | 
|  | nname = IMSUMMARY_NAME; | 
|  | data = dbev->heapcs_data; | 
|  | break; | 
|  | default: | 
|  | data = NULL; | 
|  | break; | 
|  | } | 
|  | if (data == NULL || data->get_status () != Hist_data::SUCCESS) | 
|  | return NULL; | 
|  |  | 
|  | Hist_data::HistItem *current_item; | 
|  | for (i = 0; i < sel_objs->size (); i++) | 
|  | { | 
|  | int sel_index = (int) sel_objs->fetch (i); | 
|  | if (type != DSP_IOACTIVITY && type != DSP_IOVFD && | 
|  | type != DSP_IOCALLSTACK && type != DSP_HEAPCALLSTACK) | 
|  | { | 
|  | if (sel_index < 0 || sel_index >= data->size ()) | 
|  | continue; | 
|  | current_item = data->fetch (sel_index); | 
|  | if (current_item->obj == NULL) | 
|  | continue; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (sel_index < 0) | 
|  | continue; | 
|  | bool found = false; | 
|  | for (int j = 0; j < data->size (); j++) | 
|  | { | 
|  | current_item = data->fetch (j); | 
|  | if ((current_item->obj != NULL) && (current_item->obj->id == sel_index)) | 
|  | { | 
|  | found = true; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (!found) | 
|  | continue; | 
|  | } | 
|  | char *nm = current_item->obj->get_name (); | 
|  | if (streq (nm, NTXT ("<Total>"))) | 
|  | { | 
|  | // Special case for 'Total'. | 
|  | // Multi selection which includes 'Total' is only 'Total' | 
|  | objs->reset (); | 
|  | objs->append (current_item->obj); | 
|  | break; | 
|  | } | 
|  | objs->append (current_item->obj); | 
|  | } | 
|  | } | 
|  | if (objs->size () == 0) | 
|  | return NULL; | 
|  |  | 
|  | // Set name area | 
|  | Vector<int> *saligns = new Vector<int>(nname); | 
|  | Vector<char>*mnemonic = new Vector<char>(nname); | 
|  | Vector<char*> *jlabels = new Vector<char*>(nname); | 
|  | Vector<char*> *jvalues = new Vector<char*>(nname); | 
|  | Vector<void*> *name_objs = new Vector<void*>(4); | 
|  | name_objs->store (0, saligns); | 
|  | name_objs->store (1, mnemonic); | 
|  | name_objs->store (2, jlabels); | 
|  | name_objs->store (3, jvalues); | 
|  | if (is_mem) | 
|  | setMemSummary (objs, saligns, mnemonic, jlabels, jvalues); | 
|  | else if (is_indx) | 
|  | setIndxSummary (objs, saligns, mnemonic, jlabels, jvalues); | 
|  | else if (is_data) | 
|  | setDataSummary (objs, saligns, mnemonic, jlabels, jvalues); | 
|  | else if (is_iodata) | 
|  | setIOActivitySummary (objs, saligns, mnemonic, jlabels, jvalues); | 
|  | else if (is_heapdata) | 
|  | setHeapActivitySummary (objs, saligns, mnemonic, jlabels, jvalues); | 
|  | else | 
|  | setSummary (objs, saligns, mnemonic, jlabels, jvalues); | 
|  |  | 
|  | // Get the reference metrics | 
|  | if (is_data) | 
|  | prop_mlist = new MetricList (dbev->get_metric_ref (MET_DATA)); | 
|  | else if (is_indx) | 
|  | prop_mlist = new MetricList (dbev->get_metric_ref (MET_INDX)); | 
|  | else if (is_iodata) | 
|  | prop_mlist = new MetricList (dbev->get_metric_ref (MET_IO)); | 
|  | else if (is_heapdata) | 
|  | prop_mlist = new MetricList (dbev->get_metric_ref (MET_HEAP)); | 
|  | else | 
|  | prop_mlist = new MetricList (dbev->get_metric_ref (MET_NORMAL)); | 
|  |  | 
|  | // XXXX a workaround to avoid aggregated data for compare mode, only show base experiment data | 
|  | if (prop_mlist && dbev->comparingExperiments ()) | 
|  | prop_mlist = dbev->get_compare_mlist (prop_mlist, 0); | 
|  | nitems = prop_mlist->get_items ()->size (); | 
|  |  | 
|  | // Set the metrics area | 
|  | jlabels = new Vector<char*>(nitems); | 
|  | Vector<double> *clock_list = new Vector<double>(nitems); | 
|  | Vector<double> *excl_list = new Vector<double>(nitems); | 
|  | Vector<double> *ep_list = new Vector<double>(nitems); | 
|  | Vector<double> *incl_list = new Vector<double>(nitems); | 
|  | Vector<double> *ip_list = new Vector<double>(nitems); | 
|  | Vector<int> *vtype = new Vector<int>(nitems); | 
|  |  | 
|  | // Initialize Java String array | 
|  | Vector<void*> *metric_objs = new Vector<void*>(8); | 
|  | metric_objs->store (0, jlabels); | 
|  | metric_objs->store (1, clock_list); | 
|  | metric_objs->store (2, excl_list); | 
|  | metric_objs->store (3, ep_list); | 
|  | metric_objs->store (4, incl_list); | 
|  | metric_objs->store (5, ip_list); | 
|  | metric_objs->store (6, vtype); | 
|  | percent_scale = new Vector<double>(); | 
|  | int last_init = -1; | 
|  | for (i = 0; i < objs->size (); i++) | 
|  | { | 
|  | Histable *current_obj = objs->fetch (i); | 
|  | // Get the data to be displayed | 
|  | data = dbev->get_hist_data (prop_mlist, current_obj->get_type (), subtype, | 
|  | Hist_data::SELF, current_obj, dbev->sel_binctx, objs); | 
|  | if (data->get_status () != Hist_data::SUCCESS) | 
|  | { | 
|  | if (type != DSP_DLAYOUT) | 
|  | { // For data_layout, rows with zero metrics are OK | 
|  | delete data; | 
|  | continue; | 
|  | } | 
|  | } | 
|  | Hist_data::HistItem *hi = data->fetch (0); | 
|  | values = hi ? hi->value : NULL; | 
|  | total = data->get_totals (); | 
|  | index2 = 0; | 
|  |  | 
|  | // get the metric list from the data | 
|  | mlist = data->get_metric_list (); | 
|  |  | 
|  | // We loop over the metrics in mlist. | 
|  | // We construct index2, which tells us | 
|  | // the corresponding entry in the metric_objs lists. | 
|  | // We need this mapping multiple times. | 
|  | // So, if you change the looping in any way here, | 
|  | // do so as well in other similar loops. | 
|  | // All such loops are marked so: | 
|  | // See discussion on "mlist-to-index2 mapping". | 
|  |  | 
|  | Vec_loop (Metric*, mlist->get_items (), index, mitem) | 
|  | { | 
|  | if (mitem->get_subtype () == Metric::STATIC) | 
|  | continue; | 
|  | if (last_init < index2) | 
|  | { | 
|  | last_init = index2; | 
|  | jlabels->store (index2, NULL); | 
|  | clock_list->store (index2, 0.0); | 
|  | excl_list->store (index2, 0.0); | 
|  | ep_list->store (index2, 0.0); | 
|  | incl_list->store (index2, 0.0); | 
|  | ip_list->store (index2, 0.0); | 
|  | vtype->store (index2, 0); | 
|  | } | 
|  | dvalue = (values != NULL) ? values[index].to_double () : 0.0; | 
|  | double dtotal = total->value[index].to_double (); | 
|  | percent_scale->store (index, dtotal == 0. ? 0. : 100. / dtotal); | 
|  | if (mitem->is_time_val ()) | 
|  | clock = 1.e+6 * dbeSession->get_clock (-1); | 
|  | else | 
|  | clock = 0.0; | 
|  |  | 
|  | clock_list->store (index2, clock); | 
|  | if (mitem->get_subtype () == Metric::EXCLUSIVE || | 
|  | mitem->get_subtype () == Metric::DATASPACE) | 
|  | { | 
|  | if (i == 0) | 
|  | { | 
|  | char *sstr = mitem->get_username (); | 
|  | char *buf = dbe_strdup (sstr); | 
|  | jlabels->store (index2, buf); | 
|  | vtype->store (index2, mitem->get_vtype ()); | 
|  | } | 
|  | dvalue += excl_list->fetch (index2); | 
|  | double percent = dvalue * percent_scale->fetch (index); | 
|  | excl_list->store (index2, dvalue); | 
|  | ep_list->store (index2, percent); | 
|  | if (is_data || is_indx || is_iodata || is_heapdata) | 
|  | // move to next row, except if there's inclusive data, too | 
|  | index2++; | 
|  | } | 
|  | else | 
|  | { | 
|  | dvalue += incl_list->fetch (index2); | 
|  | if (dvalue > dtotal && mitem->get_type () != BaseMetric::DERIVED) | 
|  | dvalue = dtotal; // temporary correction | 
|  | double percent = dvalue * percent_scale->fetch (index); | 
|  | incl_list->store (index2, dvalue); | 
|  | ip_list->store (index2, percent); | 
|  | index2++; | 
|  | } | 
|  | } | 
|  | delete data; | 
|  | } | 
|  |  | 
|  | // for multi-selection, we have to recompute the derived metrics | 
|  | if (objs->size () > 1 && | 
|  | dbev->get_derived_metrics () != NULL && | 
|  | dbev->get_derived_metrics ()->get_items () != NULL && | 
|  | dbev->get_derived_metrics ()->get_items ()->size () > 0) | 
|  | { | 
|  | // See discussion on "mlist-to-index2 mapping". | 
|  | Vector<Metric*> *mvec = new Vector<Metric*>(nitems); | 
|  | index2 = 0; | 
|  | Vec_loop (Metric*, prop_mlist->get_items (), index, mitem) | 
|  | { | 
|  | if (mitem->get_subtype () == Metric::STATIC) | 
|  | continue; | 
|  | if (mitem->get_subtype () == Metric::EXCLUSIVE || | 
|  | mitem->get_subtype () == Metric::DATASPACE) | 
|  | { | 
|  | mvec->store (index2, mitem); | 
|  | if (is_data || is_indx || is_iodata || is_heapdata) | 
|  | index2++; | 
|  | } | 
|  | else | 
|  | { | 
|  | assert (strcmp (mvec->fetch (index2)->get_cmd (), mitem->get_cmd ()) == 0); | 
|  | index2++; | 
|  | } | 
|  | } | 
|  | int *map = dbev->get_derived_metrics ()->construct_map (mvec, BaseMetric::EXCLUSIVE, mvec->fetch (0)->get_expr_spec ()); | 
|  | if (map != NULL) | 
|  | { | 
|  | int nmetrics = mvec->size (); | 
|  | double *evalues = (double *) xmalloc (nmetrics * sizeof (double)); | 
|  | double *ivalues = (double *) xmalloc (nmetrics * sizeof (double)); | 
|  | for (index2 = 0; index2 < nmetrics; index2++) | 
|  | { | 
|  | evalues[index2] = excl_list->fetch (index2); | 
|  | ivalues[index2] = incl_list->fetch (index2); | 
|  | } | 
|  |  | 
|  | // evaluate derived metrics | 
|  | dbev->get_derived_metrics ()->eval (map, evalues); | 
|  | dbev->get_derived_metrics ()->eval (map, ivalues); | 
|  | for (index2 = 0; index2 < nmetrics; index2++) | 
|  | { | 
|  | excl_list->store (index2, evalues[index2]); | 
|  | incl_list->store (index2, ivalues[index2]); | 
|  | } | 
|  |  | 
|  | // recompute percentages for derived metrics    EUGENE maybe all percentage computations should be moved here | 
|  | // See discussion on "mlist-to-index2 mapping". | 
|  | index2 = 0; | 
|  | Vec_loop (Metric*, prop_mlist->get_items (), index, mitem) | 
|  | { | 
|  | if (mitem->get_subtype () == Metric::STATIC) | 
|  | continue; | 
|  | if (mitem->get_subtype () == Metric::EXCLUSIVE || | 
|  | mitem->get_subtype () == Metric::DATASPACE) | 
|  | { | 
|  | if (mitem->get_type () == BaseMetric::DERIVED) | 
|  | ep_list->store (index2, excl_list->fetch (index2) * percent_scale->fetch (index)); | 
|  | if (is_data || is_indx || is_iodata || is_heapdata) | 
|  | index2++; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (mitem->get_type () == BaseMetric::DERIVED) | 
|  | ip_list->store (index2, incl_list->fetch (index2) * percent_scale->fetch (index)); | 
|  | index2++; | 
|  | } | 
|  | } | 
|  | free (evalues); | 
|  | free (ivalues); | 
|  | free (map); | 
|  | } | 
|  | delete mvec; | 
|  | } | 
|  | delete prop_mlist; | 
|  | Vector<void*> *summary = new Vector<void*>(2); | 
|  | summary->store (0, name_objs); | 
|  | summary->store (1, metric_objs); | 
|  | delete objs; | 
|  | delete percent_scale; | 
|  | return summary; | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeGetExpName (int /*dbevindex*/, char *dir_name) | 
|  | { | 
|  | char *ret; | 
|  | char *warn; | 
|  | if (col_ctr == NULL) | 
|  | col_ctr = new Coll_Ctrl (1); // Potential race condition? | 
|  | if (dir_name != NULL) | 
|  | { | 
|  | ret = col_ctr->set_directory (dir_name, &warn); | 
|  | // note that the warning and error msgs are written to stderr, not returned to caller | 
|  | if (warn != NULL) | 
|  | fprintf (stderr, NTXT ("%s"), warn); | 
|  | if (ret != NULL) | 
|  | fprintf (stderr, NTXT ("%s"), ret); | 
|  | } | 
|  | return dbe_strdup (col_ctr->get_expt ()); | 
|  | } | 
|  |  | 
|  | // === CollectDialog HWC info === | 
|  |  | 
|  | Vector<Vector<char*>*> * | 
|  | dbeGetHwcSets (int /*dbevindex*/, bool forKernel) | 
|  | { | 
|  | Vector<Vector<char*>*> *list = new Vector<Vector<char*>*>(2); | 
|  | char * defctrs = hwc_get_default_cntrs2 (forKernel, 1); | 
|  | Vector<char*> *i18n = new Vector<char*>(1); // User name | 
|  | Vector<char*> *name = new Vector<char*>(1); // Internal name | 
|  | if (NULL != defctrs) | 
|  | { | 
|  | i18n->store (0, xstrdup (defctrs)); | 
|  | name->store (0, xstrdup (NTXT ("default"))); | 
|  | } | 
|  | list->store (0, i18n); | 
|  | list->store (1, name); | 
|  | return list; | 
|  | } | 
|  |  | 
|  | static Vector<void*> * | 
|  | dbeGetHwcs (Hwcentry **hwcs) | 
|  | { | 
|  | int sz; | 
|  | for (sz = 0; hwcs && hwcs[sz]; sz++) | 
|  | ; | 
|  | Vector<void*> *list = new Vector<void*>(9); | 
|  | Vector<char*> *i18n = new Vector<char*>(sz); | 
|  | Vector<char*> *name = new Vector<char*>(sz); | 
|  | Vector<char*> *int_name = new Vector<char*>(sz); | 
|  | Vector<char*> *metric = new Vector<char*>(sz); | 
|  | Vector<long long> *val = new Vector<long long>(sz); | 
|  | Vector<int> *timecvt = new Vector<int>(sz); | 
|  | Vector<int> *memop = new Vector<int>(sz); | 
|  | Vector<char*> *short_desc = new Vector<char*>(sz); | 
|  | Vector<Vector<int>*> *reglist_v = new Vector<Vector<int>*>(sz); | 
|  | Vector<bool> *supportsAttrs = new Vector<bool>(sz); | 
|  | Vector<bool> *supportsMemspace = new Vector<bool>(sz); | 
|  |  | 
|  | for (int i = 0; i < sz; i++) | 
|  | { | 
|  | Hwcentry *ctr = hwcs[i]; | 
|  | Vector<int> *registers = new Vector<int>(MAX_PICS); | 
|  | registers->store (0, REGNO_ANY); | 
|  | i18n->store (i, dbe_strdup (hwc_i18n_metric (ctr))); | 
|  | name->store (i, dbe_strdup (ctr->name)); | 
|  | int_name->store (i, dbe_strdup (ctr->int_name)); | 
|  | metric->store (i, dbe_strdup (ctr->metric)); | 
|  | val->store (i, ctr->val); // signed promotion from int | 
|  | timecvt->store (i, ctr->timecvt); | 
|  | memop->store (i, ctr->memop); | 
|  | reglist_v->store (i, registers); | 
|  | short_desc->store (i, dbe_strdup (ctr->short_desc)); | 
|  | supportsAttrs->store (i, true); | 
|  | supportsMemspace->store (i, ABST_MEMSPACE_ENABLED (ctr->memop)); | 
|  | } | 
|  | list->store (0, i18n); | 
|  | list->store (1, name); | 
|  | list->store (2, int_name); | 
|  | list->store (3, metric); | 
|  | list->store (4, val); | 
|  | list->store (5, timecvt); | 
|  | list->store (6, memop); | 
|  | list->store (7, short_desc); | 
|  | list->store (8, reglist_v); | 
|  | list->store (9, supportsAttrs); | 
|  | list->store (10, supportsMemspace); | 
|  | return list; | 
|  | } | 
|  |  | 
|  | Vector<void *> * | 
|  | dbeGetHwcsAll (int /*dbevindex*/, bool forKernel) | 
|  | { | 
|  | Vector<void*> *list = new Vector<void*>(2); | 
|  | list->store (0, dbeGetHwcs (hwc_get_std_ctrs (forKernel))); | 
|  | list->store (1, dbeGetHwcs (hwc_get_raw_ctrs (forKernel))); | 
|  | return list; | 
|  | } | 
|  |  | 
|  | Vector<char*> * | 
|  | dbeGetHwcHelp (int /*dbevindex*/, bool forKernel) | 
|  | { | 
|  | Vector<char*> *strings = new Vector<char*>(32); | 
|  | FILE *f = tmpfile (); | 
|  | hwc_usage_f (forKernel, f, "", 0, 0, 1); // writes to f | 
|  | fflush (f); | 
|  | fseek (f, 0, SEEK_SET); | 
|  | #define MAX_LINE_LEN 2048 | 
|  | char buff[MAX_LINE_LEN]; | 
|  | int ii = 0; | 
|  | while (fgets (buff, MAX_LINE_LEN, f)) | 
|  | strings->store (ii++, dbe_strdup (buff)); | 
|  | fclose (f); | 
|  | return strings; | 
|  | } | 
|  |  | 
|  | Vector<char*> * | 
|  | dbeGetHwcAttrList (int /*dbevindex*/, bool forKernel) | 
|  | { | 
|  | char ** attr_list = hwc_get_attrs (forKernel); // Get Attribute list | 
|  | int size; | 
|  | for (size = 0; attr_list && attr_list[size]; size++) | 
|  | ; | 
|  |  | 
|  | Vector<char*> *name = new Vector<char*>(size); | 
|  | for (int i = 0; i < size; i++) | 
|  | name->store (i, dbe_strdup (attr_list[i])); | 
|  | return name; | 
|  | } | 
|  |  | 
|  | //Get maximum number of simultaneous counters | 
|  | int | 
|  | dbeGetHwcMaxConcurrent (int /*dbevindex*/, bool forKernel) | 
|  | { | 
|  | return hwc_get_max_concurrent (forKernel); | 
|  | } | 
|  |  | 
|  | // === End CollectDialog HWC info === | 
|  |  | 
|  |  | 
|  | //  Instruction-frequency data | 
|  | Vector<char*> * | 
|  | dbeGetIfreqData (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | if (!dbeSession->is_ifreq_available ()) | 
|  | return NULL; | 
|  | int size = dbeSession->nexps (); | 
|  | if (size == 0) | 
|  | return NULL; | 
|  |  | 
|  | // Initialize Java String array | 
|  | Vector<char*> *list = new Vector<char*>(); | 
|  | for (int i = 0; i < size; i++) | 
|  | { | 
|  | Experiment *exp = dbeSession->get_exp (i); | 
|  | if (exp->broken || !dbev->get_exp_enable (i) || !exp->ifreqavail) | 
|  | continue; | 
|  | // write a header for the experiment | 
|  | list->append (dbe_sprintf (GTXT ("Instruction frequency data from experiment %s\n\n"), | 
|  | exp->get_expt_name ())); | 
|  | // add its instruction frequency messages | 
|  | char *ifreq = pr_mesgs (exp->fetch_ifreq (), NTXT (""), NTXT ("")); | 
|  | list->append (ifreq); | 
|  | } | 
|  | return list; | 
|  | } | 
|  |  | 
|  | //   LeakList related methods | 
|  | // | 
|  | Vector<void*> * | 
|  | dbeGetLeakListInfo (int dbevindex, bool leakflag) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | MetricList *origmlist = dbev->get_metric_list (MET_NORMAL); | 
|  | MetricList *nmlist = new MetricList (origmlist); | 
|  | if (leakflag) | 
|  | nmlist->set_metrics (NTXT ("e.heapleakbytes:e.heapleakcnt:name"), true, | 
|  | dbev->get_derived_metrics ()); | 
|  | else | 
|  | nmlist->set_metrics (NTXT ("e.heapallocbytes:e.heapalloccnt:name"), true, | 
|  | dbev->get_derived_metrics ()); | 
|  | MetricList *mlist = new MetricList (nmlist); | 
|  | delete nmlist; | 
|  |  | 
|  | CStack_data *lam = dbev->get_cstack_data (mlist); | 
|  | if (lam == NULL || lam->size () == 0) | 
|  | { | 
|  | delete lam; | 
|  | delete mlist; | 
|  | return NULL; | 
|  | } | 
|  | Vector<Vector<Obj>*> *evalue = new Vector<Vector<Obj>*>(lam->size ()); | 
|  | Vector<Vector<Obj>*> *pcstack = new Vector<Vector<Obj>*>(lam->size ()); | 
|  | Vector<Vector<Obj>*> *offstack = new Vector<Vector<Obj>*>(lam->size ()); | 
|  | Vector<Vector<Obj>*> *fpcstack = new Vector<Vector<Obj>*>(lam->size ()); | 
|  | Vector<Vector<Obj>*> *sumval = new Vector<Vector<Obj>*>(lam->size ()); | 
|  |  | 
|  | int index; | 
|  | CStack_data::CStack_item *lae; | 
|  | Vec_loop (CStack_data::CStack_item*, lam->cstack_items, index, lae) | 
|  | { | 
|  | Vector<Obj> *jivals = NULL; | 
|  | if (lae != NULL) | 
|  | { | 
|  | jivals = new Vector<Obj>(4); | 
|  | jivals->store (0, (Obj) (index + 1)); | 
|  | jivals->store (1, (Obj) lae->value[1].ll); | 
|  | jivals->store (2, (Obj) lae->value[0].ll); | 
|  | jivals->store (3, (Obj) (leakflag ? 1 : 2)); | 
|  | } | 
|  | evalue->store (index, jivals); | 
|  | int snum = lae->stack->size (); | 
|  | Vector<Obj> *jivals1 = new Vector<Obj>(snum); | 
|  | Vector<Obj> *jivals2 = new Vector<Obj>(snum); | 
|  | Vector<Obj> *jivals3 = new Vector<Obj>(snum); | 
|  | if (lae->stack != NULL) | 
|  | { | 
|  | for (int i = lae->stack->size () - 1; i >= 0; i--) | 
|  | { | 
|  | DbeInstr *instr = lae->stack->fetch (i); | 
|  | jivals1->store (i, (Obj) instr); | 
|  | jivals2->store (i, (Obj) instr->func); | 
|  | jivals3->store (i, (Obj) instr->addr); | 
|  | } | 
|  | } | 
|  | fpcstack->store (index, jivals1); | 
|  | pcstack->store (index, jivals2); | 
|  | offstack->store (index, jivals3); | 
|  | lae++; | 
|  | } | 
|  | Vector<Obj> *jivals4 = new Vector<Obj>(3); | 
|  | jivals4->store (0, (Obj) lam->size ()); | 
|  | jivals4->store (1, (Obj) lam->total->value[1].ll); | 
|  | jivals4->store (2, (Obj) lam->total->value[0].ll); | 
|  | sumval->store (0, jivals4); | 
|  | delete lam; | 
|  | delete mlist; | 
|  | Vector<void*> *earray = new Vector<void*>(5); | 
|  | earray->store (0, evalue); | 
|  | earray->store (1, pcstack); | 
|  | earray->store (2, offstack); | 
|  | earray->store (3, fpcstack); | 
|  | earray->store (4, sumval); | 
|  | return earray; | 
|  | } | 
|  |  | 
|  | // Map timeline address to function instr | 
|  | // | 
|  | Obj | 
|  | dbeGetObject (int dbevindex, Obj sel_func, Obj sel_pc) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | if (sel_pc) | 
|  | return sel_pc; | 
|  | return sel_func; | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeGetName (int /*dbevindex*/, int exp_id) | 
|  | // This function's name is not descriptive enough - it returns a string | 
|  | //   containing the full experiment name with path, process name, and PID. | 
|  | // There are various dbe functions that provide experiment name and experiment | 
|  | // details, and they should probably be consolidated/refactored. (TBR) | 
|  | // For another example of similar output formatting, see dbeGetExpName(). | 
|  | { | 
|  | int id = (exp_id < 0) ? 0 : exp_id; | 
|  | Experiment *exp = dbeSession->get_exp (id); | 
|  | if (exp == NULL) | 
|  | return NULL; | 
|  | char *buf = | 
|  | dbe_sprintf (NTXT ("%s [%s, PID %d]"), | 
|  | exp->get_expt_name (), | 
|  | exp->utargname != NULL ? exp->utargname : GTXT ("(unknown)"), | 
|  | exp->getPID ()); | 
|  | return buf; | 
|  | } | 
|  |  | 
|  | Vector<char*> * | 
|  | dbeGetExpVerboseName (Vector<int> *exp_ids) | 
|  | { | 
|  | int len = exp_ids->size (); | 
|  | Vector<char*> *list = new Vector<char*>(len); | 
|  | for (int i = 0; i < len; i++) | 
|  | { | 
|  | char * verboseName = dbeGetName (0, exp_ids->fetch (i)); // no strdup() | 
|  | list->store (i, verboseName); | 
|  | } | 
|  | return list; | 
|  | } | 
|  |  | 
|  | long long | 
|  | dbeGetStartTime (int /*dbevindex*/, int exp_id) | 
|  | { | 
|  | int id = (exp_id < 0) ? 0 : exp_id; | 
|  | Experiment *exp = dbeSession->get_exp (id); | 
|  | return exp ? exp->getStartTime () : (long long) 0; | 
|  | } | 
|  |  | 
|  | long long | 
|  | dbeGetRelativeStartTime (int /*dbevindex*/, int exp_id) | 
|  | { | 
|  | int id = (exp_id < 0) ? 0 : exp_id; | 
|  | Experiment *exp = dbeSession->get_exp (id); | 
|  | return exp ? exp->getRelativeStartTime () : (long long) 0; | 
|  | } | 
|  |  | 
|  | long long | 
|  | dbeGetEndTime (int /*dbevindex*/, int exp_id) | 
|  | { | 
|  | int id = (exp_id < 0) ? 0 : exp_id; | 
|  | Experiment *exp = dbeSession->get_exp (id); | 
|  |  | 
|  | // Experiment::getEndTime was initially implemented as | 
|  | // returning exp->last_event. To preserve the semantics | 
|  | // new Experiment::getLastEvent() is used here. | 
|  | return exp ? exp->getLastEvent () : (long long) 0; | 
|  | } | 
|  |  | 
|  | int | 
|  | dbeGetClock (int /*dbevindex*/, int exp_id) | 
|  | { | 
|  | return dbeSession->get_clock (exp_id); | 
|  | } | 
|  |  | 
|  | long long | 
|  | dbeGetWallStartSec (int /*dbevindex*/, int exp_id) | 
|  | { | 
|  | int id = (exp_id < 0) ? 0 : exp_id; | 
|  | Experiment *exp = dbeSession->get_exp (id); | 
|  | return exp ? exp->getWallStartSec () : 0ll; | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeGetHostname (int /*dbevindex*/, int exp_id) | 
|  | { | 
|  | int id = (exp_id < 0) ? 0 : exp_id; | 
|  | Experiment *exp = dbeSession->get_exp (id); | 
|  | return exp ? dbe_strdup (exp->hostname) : NULL; | 
|  | } | 
|  |  | 
|  | static DataView * | 
|  | getTimelinePackets (int dbevindex, int exp_id, int data_id, int entity_prop_id) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | const int sortprop_count = 3; | 
|  | const int sortprops[sortprop_count] = { | 
|  | PROP_HWCTAG, // aux | 
|  | entity_prop_id, | 
|  | PROP_TSTAMP | 
|  | }; | 
|  | DataView *packets = dbev->get_filtered_events (exp_id, data_id, | 
|  | sortprops, sortprop_count); | 
|  | return packets; | 
|  | } | 
|  |  | 
|  | static long | 
|  | getIdxByVals (DataView * packets, int aux, int entity_prop_val, | 
|  | uint64_t time, DataView::Relation rel) | 
|  | { | 
|  | const int sortprop_count = 3; | 
|  | Datum tval[sortprop_count]; | 
|  | tval[0].setUINT32 (aux); | 
|  | tval[1].setUINT32 (entity_prop_val); //CPUID, LWPID, THRID are downsized to 32 | 
|  | tval[2].setUINT64 (time); | 
|  | long idx = packets->getIdxByVals (tval, rel); | 
|  | return idx; | 
|  | } | 
|  |  | 
|  | static bool | 
|  | isValidIdx (DataView * packets, int entity_prop_id, | 
|  | int aux, int entity_prop_val, long idx) | 
|  | { | 
|  | if (idx < 0 || idx >= packets->getSize ()) | 
|  | return false; | 
|  | int pkt_aux = packets->getIntValue (PROP_HWCTAG, idx); | 
|  | if (pkt_aux != aux) | 
|  | return false; | 
|  | if (entity_prop_id == PROP_EXPID) | 
|  | return true; // not a packet property; we know the packet is in this experiment | 
|  | if (entity_prop_id == PROP_NONE) | 
|  | return true; // not a packet property; we know the packet is in this experiment | 
|  | int pkt_ent = packets->getIntValue (entity_prop_id, idx); | 
|  | if (pkt_ent != entity_prop_val) | 
|  | return false; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool | 
|  | hasInvisbleTLEvents (Experiment *exp, VMode view_mode) | 
|  | { | 
|  | if (exp->has_java && view_mode == VMODE_USER) | 
|  | return true; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | static bool | 
|  | isVisibleTLEvent (Experiment *exp, VMode view_mode, DataView* packets, long idx) | 
|  | { | 
|  | if (hasInvisbleTLEvents (exp, view_mode)) | 
|  | { | 
|  | JThread *jthread = (JThread*) packets->getObjValue (PROP_JTHREAD, idx); | 
|  | if (jthread == JTHREAD_NONE || (jthread != NULL && jthread->is_system ())) | 
|  | return false; | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static long | 
|  | getTLVisibleIdxByStepping (Experiment *exp, VMode view_mode, int entity_prop_id, | 
|  | DataView * packets, int aux, int entity_prop_val, | 
|  | long idx, long move_count, int direction) | 
|  | { | 
|  | assert (move_count >= 0); | 
|  | assert (direction == 1 || direction == -1 || direction == 0); | 
|  | if (direction == 0 /* precise hit required */) | 
|  | move_count = 0; | 
|  | do | 
|  | { | 
|  | if (!isValidIdx (packets, entity_prop_id, aux, entity_prop_val, idx)) | 
|  | return -1; | 
|  | if (isVisibleTLEvent (exp, view_mode, packets, idx)) | 
|  | { | 
|  | if (move_count <= 0) | 
|  | break; | 
|  | move_count--; | 
|  | } | 
|  | if (direction == 0) | 
|  | return -1; | 
|  | idx += direction; | 
|  | } | 
|  | while (1); | 
|  | return idx; | 
|  | } | 
|  |  | 
|  | static long | 
|  | getTLVisibleIdxByVals (Experiment *exp, VMode view_mode, int entity_prop_id, | 
|  | DataView * packets, | 
|  | int aux, int entity_prop_val, uint64_t time, DataView::Relation rel) | 
|  | { | 
|  | long idx = getIdxByVals (packets, aux, entity_prop_val, time, rel); | 
|  | if (!hasInvisbleTLEvents (exp, view_mode)) | 
|  | return idx; | 
|  | if (idx < 0) | 
|  | return idx; | 
|  | if (rel == DataView::REL_EQ) | 
|  | return -1; // would require bi-directional search... not supported for now | 
|  | int direction = (rel == DataView::REL_LT || rel == DataView::REL_LTEQ) ? -1 : 1; | 
|  | idx = getTLVisibleIdxByStepping (exp, view_mode, entity_prop_id, packets, | 
|  | aux, entity_prop_val, | 
|  | idx, 0 /* first match */, direction); | 
|  | return idx; | 
|  | } | 
|  |  | 
|  | // In thread mode, the entity name for non Java thread should be the 1st func | 
|  | // from the current thread's stack. See #4961315 | 
|  | static char* | 
|  | getThreadRootFuncName (int, int, int, int, VMode) | 
|  | { | 
|  | return NULL; // until we figure out what we want to show... YXXX | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetEntityProps (int dbevindex) //YXXX TBD, should this be exp-specific? | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Vector<int> *prop_id = new Vector<int>(); | 
|  | Vector<char*> *prop_name = new Vector<char*>(); | 
|  | Vector<char*> *prop_uname = new Vector<char*>(); | 
|  | Vector<char*> *prop_cname = new Vector<char*>(); //must match TLModeCmd vals! | 
|  |  | 
|  | prop_id->append (PROP_NONE); | 
|  | prop_name->append (dbe_strdup (GTXT ("NONE"))); | 
|  | prop_uname->append (dbe_strdup (GTXT ("Unknown"))); | 
|  | prop_cname->append (dbe_strdup (NTXT ("unknown"))); | 
|  |  | 
|  | prop_id->append (PROP_LWPID); | 
|  | prop_name->append (dbe_strdup (GTXT ("LWPID"))); | 
|  | prop_uname->append (dbe_strdup (GTXT ("LWP"))); | 
|  | prop_cname->append (dbe_strdup (NTXT ("lwp"))); | 
|  |  | 
|  | prop_id->append (PROP_THRID); | 
|  | prop_name->append (dbe_strdup (GTXT ("THRID"))); | 
|  | prop_uname->append (dbe_strdup (GTXT ("Thread"))); | 
|  | prop_cname->append (dbe_strdup (NTXT ("thread"))); | 
|  |  | 
|  | prop_id->append (PROP_CPUID); | 
|  | prop_name->append (dbe_strdup (GTXT ("CPUID"))); | 
|  | prop_uname->append (dbe_strdup (GTXT ("CPU"))); | 
|  | prop_cname->append (dbe_strdup (NTXT ("cpu"))); | 
|  |  | 
|  | prop_id->append (PROP_EXPID); | 
|  | prop_name->append (dbe_strdup (GTXT ("EXPID"))); | 
|  | prop_uname->append (dbe_strdup (GTXT ("Process"))); // placeholder... | 
|  | // ...until we finalize how to expose user-level Experiments, descendents | 
|  | prop_cname->append (dbe_strdup (NTXT ("experiment"))); | 
|  | Vector<void*> *darray = new Vector<void*>(); | 
|  | darray->store (0, prop_id); | 
|  | darray->store (1, prop_name); | 
|  | darray->store (2, prop_uname); | 
|  | darray->store (3, prop_cname); | 
|  | return darray; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetEntities (int dbevindex, int exp_id, int entity_prop_id) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Experiment *exp = dbeSession->get_exp (exp_id); | 
|  | if (exp == NULL) | 
|  | return NULL; | 
|  |  | 
|  | // Recognize and skip faketime experiments | 
|  | if (exp->timelineavail == false) | 
|  | return NULL; | 
|  | Vector<Histable*> *tagObjs = exp->getTagObjs ((Prop_type) entity_prop_id); | 
|  | int total_nelem; | 
|  | if (tagObjs) | 
|  | total_nelem = (int) tagObjs->size (); | 
|  | else | 
|  | total_nelem = 0; | 
|  | const VMode view_mode = dbev->get_view_mode (); | 
|  | bool show_java_threadnames = (entity_prop_id == PROP_THRID && | 
|  | view_mode != VMODE_MACHINE); | 
|  | // allocate the structures for the return | 
|  | Vector<int> *entity_prop_vals = new Vector<int>(); | 
|  | Vector<char*> *jthr_names = new Vector<char*>(); | 
|  | Vector<char*> *jthr_g_names = new Vector<char*>(); | 
|  | Vector<char*> *jthr_p_names = new Vector<char*>(); | 
|  |  | 
|  | // now walk the tagObjs from the experiment, and check for filtering | 
|  | for (int tagObjsIdx = 0; tagObjsIdx < total_nelem; tagObjsIdx++) | 
|  | { | 
|  | int entity_prop_val = (int) ((Other *) tagObjs->fetch (tagObjsIdx))->tag; | 
|  | entity_prop_vals->append (entity_prop_val); | 
|  | char *jname, *jgname, *jpname; | 
|  | JThread *jthread = NULL; | 
|  | bool has_java_threadnames = false; | 
|  | if (show_java_threadnames) | 
|  | { | 
|  | jthread = exp->get_jthread (entity_prop_val); | 
|  | has_java_threadnames = (jthread != JTHREAD_DEFAULT | 
|  | && jthread != JTHREAD_NONE); | 
|  | } | 
|  | if (!has_java_threadnames) | 
|  | { | 
|  | jname = jgname = jpname = NULL; | 
|  | if (entity_prop_id == PROP_THRID || entity_prop_id == PROP_LWPID) | 
|  | // if non Java thread, set thread name to the 1st func | 
|  | // from the current thread's stack. see #4961315 | 
|  | jname = getThreadRootFuncName (dbevindex, exp_id, entity_prop_id, | 
|  | entity_prop_val, view_mode); | 
|  | } | 
|  | else | 
|  | { | 
|  | jname = dbe_strdup (jthread->name); | 
|  | jgname = dbe_strdup (jthread->group_name); | 
|  | jpname = dbe_strdup (jthread->parent_name); | 
|  | } | 
|  | jthr_names->append (jname); | 
|  | jthr_g_names->append (jgname); | 
|  | jthr_p_names->append (jpname); | 
|  | } | 
|  | Vector<char*> *entity_prop_name_v = new Vector<char*>(); | 
|  | char* entity_prop_name = dbeSession->getPropName (entity_prop_id); | 
|  | entity_prop_name_v->append (entity_prop_name); | 
|  | Vector<void*> *darray = new Vector<void*>(5); | 
|  | darray->store (0, entity_prop_vals); | 
|  | darray->store (1, jthr_names); | 
|  | darray->store (2, jthr_g_names); | 
|  | darray->store (3, jthr_p_names); | 
|  | darray->store (4, entity_prop_name_v); // vector only has 1 element | 
|  | return darray; | 
|  | } | 
|  |  | 
|  | // TBR: dbeGetEntities() can be set to private now that we have dbeGetEntitiesV2() | 
|  | Vector<void*> * | 
|  | dbeGetEntitiesV2 (int dbevindex, Vector<int> *exp_ids, int entity_prop_id) | 
|  | { | 
|  | int sz = exp_ids->size (); | 
|  | Vector<void*> *res = new Vector<void*>(sz); | 
|  | for (int ii = 0; ii < sz; ii++) | 
|  | { | 
|  | int expIdx = exp_ids->fetch (ii); | 
|  | Vector<void*>* ents = dbeGetEntities (dbevindex, expIdx, entity_prop_id); | 
|  | res->store (ii, ents); | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | //YXXX old-tl packets still used for details | 
|  | static Vector<void*> * | 
|  | getTLDetailValues (int dbevindex, Experiment * exp, int data_id, | 
|  | VMode view_mode, DataView *packets, long idx) | 
|  | { | 
|  | Vector<long long> *value = new Vector<long long>(15); | 
|  | long i = idx; | 
|  | if (data_id == DATA_SAMPLE || data_id == DATA_GCEVENT) | 
|  | { | 
|  | //YXXX DATA_SAMPLE not handled but could be. | 
|  | } | 
|  | Obj stack = (unsigned long) getStack (view_mode, packets, i); | 
|  | Vector<Obj> *funcs = stack ? dbeGetStackFunctions (dbevindex, stack) : NULL; | 
|  | Function *func = (Function*) | 
|  | getStackPC (0, view_mode, packets, i)->convertto (Histable::FUNCTION); | 
|  | // Fill common data | 
|  | value->store (0, packets->getIntValue (PROP_LWPID, i)); | 
|  | value->store (1, packets->getIntValue (PROP_THRID, i)); | 
|  | value->store (2, packets->getIntValue (PROP_CPUID, i)); | 
|  | value->store (3, packets->getLongValue (PROP_TSTAMP, i)); | 
|  | value->store (4, (unsigned long) stack); | 
|  | value->store (5, (unsigned long) func); | 
|  |  | 
|  | // Fill specific data | 
|  | switch (data_id) | 
|  | { | 
|  | case DATA_CLOCK: | 
|  | value->store (6, packets->getIntValue (PROP_MSTATE, i)); | 
|  | { | 
|  | hrtime_t interval = exp->get_params ()->ptimer_usec * 1000LL // nanoseconds | 
|  | * packets->getLongValue (PROP_NTICK, i); | 
|  | value->store (7, interval); | 
|  | } | 
|  | value->store (8, packets->getIntValue (PROP_OMPSTATE, i)); | 
|  | value->store (9, packets->getLongValue (PROP_EVT_TIME, i)); // visual duration | 
|  | break; | 
|  | case DATA_SYNCH: | 
|  | value->store (6, packets->getLongValue (PROP_EVT_TIME, i)); | 
|  | value->store (7, packets->getLongValue (PROP_SOBJ, i)); | 
|  | break; | 
|  | case DATA_HWC: | 
|  | value->store (6, packets->getLongValue (PROP_HWCINT, i)); | 
|  | value->store (7, packets->getLongValue (PROP_VADDR, i)); // data vaddr | 
|  | value->store (8, packets->getLongValue (PROP_PADDR, i)); // data paddr | 
|  | value->store (9, packets->getLongValue (PROP_VIRTPC, i)); // pc paddr | 
|  | value->store (10, packets->getLongValue (PROP_PHYSPC, i)); // pc vaddr | 
|  | break; | 
|  | case DATA_RACE: | 
|  | value->store (6, packets->getIntValue (PROP_RTYPE, i)); | 
|  | value->store (7, packets->getIntValue (PROP_RID, i)); | 
|  | value->store (8, packets->getLongValue (PROP_RVADDR, i)); | 
|  | break; | 
|  | case DATA_DLCK: | 
|  | value->store (6, packets->getIntValue (PROP_DTYPE, i)); | 
|  | value->store (7, packets->getIntValue (PROP_DLTYPE, i)); | 
|  | value->store (8, packets->getIntValue (PROP_DID, i)); | 
|  | value->store (9, packets->getLongValue (PROP_DVADDR, i)); | 
|  | break; | 
|  | case DATA_HEAP: | 
|  | case DATA_HEAPSZ: | 
|  | value->store (6, packets->getIntValue (PROP_HTYPE, i)); | 
|  | value->store (7, packets->getLongValue (PROP_HSIZE, i)); | 
|  | value->store (8, packets->getLongValue (PROP_HVADDR, i)); | 
|  | value->store (9, packets->getLongValue (PROP_HOVADDR, i)); | 
|  | value->store (10, packets->getLongValue (PROP_HLEAKED, i)); | 
|  | value->store (11, packets->getLongValue (PROP_HFREED, i)); | 
|  | value->store (12, packets->getLongValue (PROP_HCUR_ALLOCS, i)); // signed int64_t | 
|  | value->store (13, packets->getLongValue (PROP_HCUR_LEAKS, i)); | 
|  | break; | 
|  | case DATA_IOTRACE: | 
|  | value->store (6, packets->getIntValue (PROP_IOTYPE, i)); | 
|  | value->store (7, packets->getIntValue (PROP_IOFD, i)); | 
|  | value->store (8, packets->getLongValue (PROP_IONBYTE, i)); | 
|  | value->store (9, packets->getLongValue (PROP_EVT_TIME, i)); | 
|  | value->store (10, packets->getIntValue (PROP_IOVFD, i)); | 
|  | break; | 
|  | } | 
|  | Vector<void*> *result = new Vector<void*>(5); | 
|  | result->store (0, value); | 
|  | result->store (1, funcs); // Histable::Function* | 
|  | result->store (2, funcs ? dbeGetFuncNames (dbevindex, funcs) : 0); // formatted func names | 
|  | result->store (3, stack ? dbeGetStackPCs (dbevindex, stack) : 0); // Histable::DbeInstr* | 
|  | result->store (4, stack ? dbeGetStackNames (dbevindex, stack) : 0); // formatted pc names | 
|  | return result; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetTLDetails (int dbevindex, int exp_id, int data_id, | 
|  | int entity_prop_id, Obj event_id) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Experiment *exp = dbeSession->get_exp (exp_id < 0 ? 0 : exp_id); | 
|  | if (exp == NULL) | 
|  | return NULL; | 
|  | DataView *packets = | 
|  | getTimelinePackets (dbevindex, exp_id, data_id, entity_prop_id); | 
|  | if (!packets) | 
|  | return NULL; | 
|  |  | 
|  | VMode view_mode = dbev->get_view_mode (); | 
|  | long idx = (long) event_id; | 
|  | Vector<void*> *values = getTLDetailValues (dbevindex, exp, data_id, view_mode, packets, idx); | 
|  | return values; | 
|  | } | 
|  |  | 
|  | Vector<Obj> * | 
|  | dbeGetStackFunctions (int dbevindex, Obj stack) | 
|  | { | 
|  | Vector<Obj> *instrs = dbeGetStackPCs (dbevindex, stack); | 
|  | if (instrs == NULL) | 
|  | return NULL; | 
|  | int stsize = instrs->size (); | 
|  | Vector<Obj> *jivals = new Vector<Obj>(stsize); | 
|  | for (int i = 0; i < stsize; i++) | 
|  | { | 
|  | Histable *obj = (Histable*) instrs->fetch (i); | 
|  | // if ( obj->get_type() != Histable::LINE ) {//YXXX what is this? | 
|  | // Remove the above check: why not do this conversion for lines - | 
|  | // otherwise filtering in timeline by function stack in omp user mode is broken | 
|  | obj = obj->convertto (Histable::FUNCTION); | 
|  | jivals->store (i, (Obj) obj); | 
|  | } | 
|  | delete instrs; | 
|  | return jivals; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetStacksFunctions (int dbevindex, Vector<Obj> *stacks) | 
|  | { | 
|  | long sz = stacks->size (); | 
|  | Vector<void*> *res = new Vector<void*>(sz); | 
|  | for (int ii = 0; ii < sz; ii++) | 
|  | { | 
|  | Obj stack = stacks->fetch (ii); | 
|  | Vector<Obj> *jivals = dbeGetStackFunctions (dbevindex, stack); | 
|  | res->store (ii, jivals); | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | Vector<Obj> * | 
|  | dbeGetStackPCs (int dbevindex, Obj stack) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | if (stack == 0) | 
|  | return NULL; | 
|  |  | 
|  | bool show_all = dbev->isShowAll (); | 
|  | Vector<Histable*> *instrs = CallStack::getStackPCs ((void *) stack, !show_all); | 
|  | int stsize = instrs->size (); | 
|  | int istart = 0; | 
|  | bool showAll = dbev->isShowAll (); | 
|  | for (int i = 0; i < stsize - 1; i++) | 
|  | { | 
|  | Function *func = (Function*) instrs->fetch (i)->convertto (Histable::FUNCTION); | 
|  | int ix = func->module->loadobject->seg_idx; | 
|  | if (showAll && dbev->get_lo_expand (ix) == LIBEX_API) | 
|  | // truncate stack here:  LIBRARY_VISIBILITY if we are using API only but no hide | 
|  | istart = i; | 
|  | } | 
|  | stsize = stsize - istart; | 
|  | Vector<Obj> *jlvals = new Vector<Obj>(stsize); | 
|  | for (int i = 0; i < stsize; i++) | 
|  | { | 
|  | Histable *instr = instrs->fetch (i + istart); | 
|  | jlvals->store (i, (Obj) instr); | 
|  | } | 
|  | delete instrs; | 
|  | return jlvals; | 
|  | } | 
|  |  | 
|  | Vector<char*> * | 
|  | dbeGetStackNames (int dbevindex, Obj stack) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | Vector<Obj> *instrs = dbeGetStackPCs (dbevindex, stack); | 
|  | if (instrs == NULL) | 
|  | return NULL; | 
|  | int stsize = instrs->size (); | 
|  | Vector<char*> *list = new Vector<char*>(stsize); | 
|  | bool showAll = dbev->isShowAll (); | 
|  | for (int i = 0; i < stsize; i++) | 
|  | { | 
|  | Histable* instr = (Histable*) instrs->fetch (i); | 
|  | if (!showAll) | 
|  | { | 
|  | // LIBRARY_VISIBILITY | 
|  | Function *func = (Function*) instr->convertto (Histable::FUNCTION); | 
|  | LoadObject *lo = ((Function*) func)->module->loadobject; | 
|  | if (dbev->get_lo_expand (lo->seg_idx) == LIBEX_HIDE) | 
|  | { | 
|  | list->store (i, dbe_strdup (lo->get_name ())); | 
|  | continue; | 
|  | } | 
|  | } | 
|  | list->store (i, dbe_strdup (instr->get_name (dbev->get_name_format ()))); | 
|  | } | 
|  | delete instrs; | 
|  | return list; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetSamples (int dbevindex, int exp_id, int64_t lo_idx, int64_t hi_idx) | 
|  | { | 
|  | DataView * packets = | 
|  | getTimelinePackets (dbevindex, exp_id, DATA_SAMPLE, PROP_EXPID); | 
|  | if (packets == NULL || packets->getSize () == 0) | 
|  | return NULL; | 
|  | long lo; | 
|  | if (lo_idx < 0) | 
|  | lo = 0; | 
|  | else | 
|  | lo = (long) lo_idx; | 
|  |  | 
|  | long long max = packets->getSize () - 1; | 
|  | long hi; | 
|  | if (hi_idx < 0 || hi_idx > max) | 
|  | hi = (long) max; | 
|  | else | 
|  | hi = (long) hi_idx; | 
|  |  | 
|  | Vector<Vector<long long>*> *sarray = new Vector<Vector<long long>*>; | 
|  | Vector<long long>* starts = new Vector<long long>; | 
|  | Vector<long long>* ends = new Vector<long long>; | 
|  | Vector<long long>* rtimes = new Vector<long long>; | 
|  | Vector<char*> *startNames = new Vector<char*>; | 
|  | Vector<char*> *endNames = new Vector<char*>; | 
|  | Vector<int> *sampId = new Vector<int>; | 
|  |  | 
|  | for (long index = lo; index <= hi; index++) | 
|  | { | 
|  | Sample *sample = (Sample*) packets->getObjValue (PROP_SMPLOBJ, index); | 
|  | PrUsage *prusage = sample->get_usage (); | 
|  | if (prusage == NULL) | 
|  | prusage = new PrUsage; | 
|  | Vector<long long> *states = prusage->getMstateValues (); | 
|  | sarray->append (states); | 
|  | starts->append (sample->get_start_time ()); | 
|  | ends->append (sample->get_end_time ()); | 
|  | rtimes->append (prusage->pr_rtime); | 
|  | startNames->append (dbe_strdup (sample->get_start_label ())); | 
|  | endNames->append (dbe_strdup (sample->get_end_label ())); | 
|  | sampId->append (sample->get_number ()); | 
|  | } | 
|  | Vector<void *> *res = new Vector<void*>(6); | 
|  | res->store (0, sarray); | 
|  | res->store (1, starts); | 
|  | res->store (2, ends); | 
|  | res->store (3, rtimes); | 
|  | res->store (4, startNames); | 
|  | res->store (5, endNames); | 
|  | res->store (6, sampId); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetGCEvents (int dbevindex, int exp_id, int64_t lo_idx, int64_t hi_idx) | 
|  | { | 
|  | DataView *packets = | 
|  | getTimelinePackets (dbevindex, exp_id, DATA_GCEVENT, PROP_EXPID); | 
|  | if (packets == NULL || packets->getSize () == 0) | 
|  | return NULL; | 
|  |  | 
|  | long lo; | 
|  | if (lo_idx < 0) | 
|  | lo = 0; | 
|  | else | 
|  | lo = (long) lo_idx; | 
|  | long long max = packets->getSize () - 1; | 
|  | long hi; | 
|  | if (hi_idx < 0 || hi_idx > max) | 
|  | hi = (long) max; | 
|  | else | 
|  | hi = (long) hi_idx; | 
|  |  | 
|  | Vector<long long>* starts = new Vector<long long>; | 
|  | Vector<long long>* ends = new Vector<long long>; | 
|  | Vector<int> *eventId = new Vector<int>; | 
|  | for (long index = lo; index <= hi; index++) | 
|  | { | 
|  | GCEvent *gcevent = (GCEvent*) packets->getObjValue (PROP_GCEVENTOBJ, index); | 
|  | if (gcevent) | 
|  | { | 
|  | starts->append (gcevent->start); | 
|  | ends->append (gcevent->end); | 
|  | eventId->append (gcevent->id); | 
|  | } | 
|  | } | 
|  | Vector<void *> *res = new Vector<void*>(3); | 
|  | res->store (0, starts); | 
|  | res->store (1, ends); | 
|  | res->store (2, eventId); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | Vector<Vector<char*>*>* | 
|  | dbeGetIOStatistics (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | Hist_data *hist_data; | 
|  | Hist_data::HistItem *hi; | 
|  | FileData *fDataTotal; | 
|  |  | 
|  | hist_data = dbev->iofile_data; | 
|  | if (hist_data == NULL) | 
|  | return NULL; | 
|  | hi = hist_data->fetch (0); | 
|  | fDataTotal = (FileData*) hi->obj; | 
|  |  | 
|  | Vector<char*> *writeStat = new Vector<char*>; | 
|  | Vector<char*> *readStat = new Vector<char*>; | 
|  | Vector<char*> *otherStat = new Vector<char*>; | 
|  | Vector<char*> *errorStat = new Vector<char*>; | 
|  |  | 
|  | writeStat->append (dbe_strdup (GTXT ("Write Statistics"))); | 
|  | readStat->append (dbe_strdup (GTXT ("Read Statistics"))); | 
|  | otherStat->append (dbe_strdup (GTXT ("Other I/O Statistics"))); | 
|  | errorStat->append (dbe_strdup (GTXT ("I/O Error Statistics"))); | 
|  |  | 
|  | StringBuilder sb; | 
|  | if (fDataTotal->getWriteCnt () > 0) | 
|  | { | 
|  | if (fDataTotal->getW0KB1KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("0KB - 1KB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW0KB1KBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getW1KB8KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1KB - 8KB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW1KB8KBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getW8KB32KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("8KB - 32KB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW8KB32KBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getW32KB128KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("32KB - 128KB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW32KB128KBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getW128KB256KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("128KB - 256KB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW128KB256KBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getW256KB512KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("256KB - 512KB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW256KB512KBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getW512KB1000KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("512KB - 1000KB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW512KB1000KBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getW1000KB10MBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1000KB - 10MB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW1000KB10MBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getW10MB100MBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("10MB - 100MB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW10MB100MBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getW100MB1GBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("100MB - 1GB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW100MB1GBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getW1GB10GBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1GB - 10GB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW1GB10GBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getW10GB100GBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("10GB - 100GB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW10GB100GBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getW100GB1TBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("100GB - 1TB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW100GB1TBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getW1TB10TBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1TB - 10TB")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getW1TB10TBCnt ()); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  |  | 
|  | sb.sprintf (GTXT ("Longest write")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%.6f (secs.)"), | 
|  | (double) (fDataTotal->getWSlowestBytes () / (double) NANOSEC)); | 
|  | writeStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Smallest write bytes")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getWSmallestBytes ())); | 
|  | writeStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Largest write bytes")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getWLargestBytes ())); | 
|  | writeStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Total time")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%.6f (secs.)"), | 
|  | (double) (fDataTotal->getWriteTime () / (double) NANOSEC)); | 
|  | writeStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Total calls")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getWriteCnt ())); | 
|  | writeStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Total bytes")); | 
|  | writeStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%lld"), (long long) (fDataTotal->getWriteBytes ())); | 
|  | writeStat->append (sb.toString ()); | 
|  | } | 
|  |  | 
|  | if (fDataTotal->getReadCnt () > 0) | 
|  | { | 
|  | if (fDataTotal->getR0KB1KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("0KB - 1KB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR0KB1KBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getR1KB8KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1KB - 8KB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR1KB8KBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getR8KB32KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("8KB - 32KB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR8KB32KBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getR32KB128KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("32KB - 128KB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR32KB128KBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getR128KB256KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("128KB - 256KB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR128KB256KBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getR256KB512KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("256KB - 512KB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR256KB512KBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getR512KB1000KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("512KB - 1000KB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR512KB1000KBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getR1000KB10MBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1000KB - 10MB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR1000KB10MBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getR10MB100MBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("10MB - 100MB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR10MB100MBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getR100MB1GBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("100MB - 1GB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR100MB1GBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getR1GB10GBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1GB - 10GB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR1GB10GBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getR10GB100GBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("10GB - 100GB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR10GB100GBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getR100GB1TBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("100GB - 1TB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR100GB1TBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  | if (fDataTotal->getR1TB10TBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1TB - 10TB")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), fDataTotal->getR1TB10TBCnt ()); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  |  | 
|  | sb.sprintf (GTXT ("Longest read")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%.6f (secs.)"), | 
|  | (double) (fDataTotal->getRSlowestBytes () / (double) NANOSEC)); | 
|  | readStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Smallest read bytes")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getRSmallestBytes ())); | 
|  | readStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Largest read bytes")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getRLargestBytes ())); | 
|  | readStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Total time")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%.6f (secs.)"), | 
|  | (double) (fDataTotal->getReadTime () / (double) NANOSEC)); | 
|  | readStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Total calls")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getReadCnt ())); | 
|  | readStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Total bytes")); | 
|  | readStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%lld"), (long long) (fDataTotal->getReadBytes ())); | 
|  | readStat->append (sb.toString ()); | 
|  | } | 
|  |  | 
|  | if (fDataTotal->getOtherCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("Total time")); | 
|  | otherStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%.6f (secs.)"), | 
|  | (double) (fDataTotal->getOtherTime () / (double) NANOSEC)); | 
|  | otherStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Total calls")); | 
|  | otherStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getOtherCnt ())); | 
|  | otherStat->append (sb.toString ()); | 
|  | } | 
|  |  | 
|  | if (fDataTotal->getErrorCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("Total time")); | 
|  | errorStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%.6f (secs.)"), | 
|  | (double) (fDataTotal->getErrorTime () / (double) NANOSEC)); | 
|  | errorStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Total calls")); | 
|  | errorStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (fDataTotal->getErrorCnt ())); | 
|  | errorStat->append (sb.toString ()); | 
|  | } | 
|  | Vector<Vector<char*>*>* statisticsData = new Vector<Vector<char*>*>(4); | 
|  | statisticsData->store (0, writeStat); | 
|  | statisticsData->store (1, readStat); | 
|  | statisticsData->store (2, otherStat); | 
|  | statisticsData->store (3, errorStat); | 
|  | return statisticsData; | 
|  | } | 
|  |  | 
|  | Vector<Vector<char*>*>* | 
|  | dbeGetHeapStatistics (int dbevindex) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | Hist_data *hist_data; | 
|  | Hist_data::HistItem *hi; | 
|  | HeapData *hDataTotal; | 
|  | hist_data = dbev->heapcs_data; | 
|  | if (hist_data == NULL) | 
|  | return NULL; | 
|  |  | 
|  | hi = hist_data->fetch (0); | 
|  | hDataTotal = (HeapData*) hi->obj; | 
|  | Vector<char*> *memoryUsage = new Vector<char*>; | 
|  | Vector<char*> *allocStat = new Vector<char*>; | 
|  | Vector<char*> *leakStat = new Vector<char*>; | 
|  |  | 
|  | memoryUsage->append (dbe_strdup (GTXT ("Process With Highest Peak Memory Usage"))); | 
|  | allocStat->append (dbe_strdup (GTXT ("Memory Allocations Statistics"))); | 
|  | leakStat->append (dbe_strdup (GTXT ("Memory Leaks Statistics"))); | 
|  | StringBuilder sb; | 
|  | if (hDataTotal->getPeakMemUsage () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("Heap size bytes")); | 
|  | memoryUsage->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%lld"), (long long) (hDataTotal->getPeakMemUsage ())); | 
|  | memoryUsage->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Experiment Id")); | 
|  | memoryUsage->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getUserExpId ())); | 
|  | memoryUsage->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Process Id")); | 
|  | memoryUsage->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getPid ())); | 
|  | memoryUsage->append (sb.toString ()); | 
|  |  | 
|  | Vector<hrtime_t> *pTimestamps; | 
|  | pTimestamps = hDataTotal->getPeakTimestamps (); | 
|  | if (pTimestamps != NULL) | 
|  | { | 
|  | for (int i = 0; i < pTimestamps->size (); i++) | 
|  | { | 
|  | sb.sprintf (GTXT ("Time of peak")); | 
|  | memoryUsage->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%.3f (secs.)"), (double) (pTimestamps->fetch (i) / (double) NANOSEC)); | 
|  | memoryUsage->append (sb.toString ()); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | if (hDataTotal->getAllocCnt () > 0) | 
|  | { | 
|  | if (hDataTotal->getA0KB1KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("0KB - 1KB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA0KB1KBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getA1KB8KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1KB - 8KB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA1KB8KBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getA8KB32KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("8KB - 32KB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA8KB32KBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getA32KB128KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("32KB - 128KB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA32KB128KBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getA128KB256KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("128KB - 256KB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA128KB256KBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getA256KB512KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("256KB - 512KB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA256KB512KBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getA512KB1000KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("512KB - 1000KB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA512KB1000KBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getA1000KB10MBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1000KB - 10MB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA1000KB10MBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getA10MB100MBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("10MB - 100MB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA10MB100MBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getA100MB1GBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("100MB - 1GB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA100MB1GBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getA1GB10GBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1GB - 10GB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA1GB10GBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getA10GB100GBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("10GB - 100GB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA10GB100GBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getA100GB1TBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("100GB - 1TB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA100GB1TBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getA1TB10TBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1TB - 10TB")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getA1TB10TBCnt ()); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  |  | 
|  | sb.sprintf (GTXT ("Smallest allocation bytes")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getASmallestBytes ())); | 
|  | allocStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Largest allocation bytes")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getALargestBytes ())); | 
|  | allocStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Total allocations")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getAllocCnt ())); | 
|  | allocStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Total bytes")); | 
|  | allocStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%lld"), (long long) (hDataTotal->getAllocBytes ())); | 
|  | allocStat->append (sb.toString ()); | 
|  | } | 
|  |  | 
|  | if (hDataTotal->getLeakCnt () > 0) | 
|  | { | 
|  | if (hDataTotal->getL0KB1KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("0KB - 1KB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL0KB1KBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getL1KB8KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1KB - 8KB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL1KB8KBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getL8KB32KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("8KB - 32KB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL8KB32KBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getL32KB128KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("32KB - 128KB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL32KB128KBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getL128KB256KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("128KB - 256KB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL128KB256KBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getL256KB512KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("256KB - 512KB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL256KB512KBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getL512KB1000KBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("512KB - 1000KB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL512KB1000KBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getL1000KB10MBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1000KB - 10MB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL1000KB10MBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getL10MB100MBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("10MB - 100MB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL10MB100MBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getL100MB1GBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("100MB - 1GB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL100MB1GBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getL1GB10GBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1GB - 10GB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL1GB10GBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getL10GB100GBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("10GB - 100GB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL10GB100GBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getL100GB1TBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("100GB - 1TB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL100GB1TBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | if (hDataTotal->getL1TB10TBCnt () > 0) | 
|  | { | 
|  | sb.sprintf (GTXT ("1TB - 10TB")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), hDataTotal->getL1TB10TBCnt ()); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  |  | 
|  | sb.sprintf (GTXT ("Smallest leaked bytes")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getLSmallestBytes ())); | 
|  | leakStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Largest leaked bytes")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getLLargestBytes ())); | 
|  | leakStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Total leaked")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%d"), (int) (hDataTotal->getLeakCnt ())); | 
|  | leakStat->append (sb.toString ()); | 
|  |  | 
|  | sb.sprintf (GTXT ("Total bytes")); | 
|  | leakStat->append (sb.toString ()); | 
|  | sb.sprintf (NTXT ("%lld"), (long long) (hDataTotal->getLeakBytes ())); | 
|  | leakStat->append (sb.toString ()); | 
|  | } | 
|  | Vector<Vector<char*>*>* statisticsData = new Vector<Vector<char*>*>(3); | 
|  | statisticsData->store (0, memoryUsage); | 
|  | statisticsData->store (1, allocStat); | 
|  | statisticsData->store (2, leakStat); | 
|  | return statisticsData; | 
|  | } | 
|  |  | 
|  | Vector<char*> * | 
|  | dbeGetFuncNames (int dbevindex, Vector<Obj> *funcs) | 
|  | { | 
|  | int len = funcs->size (); | 
|  | Vector<char*> *list = new Vector<char*>(len); | 
|  | for (int i = 0; i < len; i++) | 
|  | list->store (i, dbeGetFuncName (dbevindex, funcs->fetch (i))); // no strdup() | 
|  | return list; | 
|  | } | 
|  |  | 
|  | Vector<char*> * | 
|  | dbeGetObjNamesV2 (int dbevindex, Vector<uint64_t> *ids) | 
|  | { | 
|  | int len = ids->size (); | 
|  | Vector<char*> *list = new Vector<char*>(len); | 
|  | for (int i = 0; i < len; i++) | 
|  | list->store (i, dbeGetObjNameV2 (dbevindex, ids->fetch (i))); // no strdup() | 
|  | return list; | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeGetFuncName (int dbevindex, Obj func) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | if (func == 0) | 
|  | return NULL; | 
|  | char *fname; | 
|  | fname = ((Histable *) func)->get_name (dbev->get_name_format ()); | 
|  | return fname ? dbe_strdup (fname) : NULL; | 
|  | } | 
|  |  | 
|  | Vector<uint64_t> * | 
|  | dbeGetFuncIds (int dbevindex, Vector<Obj> *funcs) | 
|  | { | 
|  | int len = funcs->size (); | 
|  | Vector<uint64_t> *list = new Vector<uint64_t>(len); | 
|  | for (int i = 0; i < len; i++) | 
|  | list->store (i, dbeGetFuncId (dbevindex, funcs->fetch (i))); | 
|  | return list; | 
|  | } | 
|  |  | 
|  | uint64_t | 
|  | dbeGetFuncId (int dbevindex, Obj func) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | if (func == 0) | 
|  | return 0; | 
|  | uint64_t id = ((Histable *) func)->id; | 
|  | return id; | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeGetObjNameV2 (int dbevindex, uint64_t id) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Histable *obj = dbeSession->findObjectById (id); | 
|  | if (obj == NULL) | 
|  | return NULL; | 
|  | char *fname = obj->get_name (dbev->get_name_format ()); | 
|  | return fname ? dbe_strdup (fname) : NULL; | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeGetDataspaceTypeDesc (int /*dbevindex*/, Obj stack) | 
|  | { | 
|  | if (stack == 0) | 
|  | return NULL; | 
|  | Histable *hist = CallStack::getStackPC ((void *) stack, 0); | 
|  | DbeInstr *instr; | 
|  | Histable::Type type = hist->get_type (); | 
|  | if (type != Histable::INSTR) | 
|  | return NULL; | 
|  | else | 
|  | instr = (DbeInstr *) hist; | 
|  | char *descriptor = instr->get_descriptor (); | 
|  | return descriptor ? dbe_strdup (descriptor) : NULL; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetDataDescriptorsV2 (int exp_id) | 
|  | { | 
|  | Experiment *exp = dbeSession->get_exp (exp_id); | 
|  | if (exp == NULL) | 
|  | return NULL; | 
|  | Vector<int> *dataId = new Vector<int>; | 
|  | Vector<char*> *dataName = new Vector<char*>; | 
|  | Vector<char*> *dataUName = new Vector<char*>; | 
|  | Vector<int> *auxProp = new Vector<int>; | 
|  | Vector<DataDescriptor*> *ddscr = exp->getDataDescriptors (); | 
|  | for (int i = 0; i < ddscr->size (); i++) | 
|  | { | 
|  | DataDescriptor *dataDscr = ddscr->fetch (i); | 
|  | if (dataDscr->getFlags () & DDFLAG_NOSHOW) | 
|  | continue; | 
|  | int data_id = dataDscr->getId (); | 
|  | int aux_prop_id = (data_id == DATA_HWC) ? PROP_HWCTAG : PROP_NONE; | 
|  | dataId->append (data_id); | 
|  | dataName->append (xstrdup (dataDscr->getName ())); | 
|  | dataUName->append (xstrdup (dataDscr->getUName ())); | 
|  | auxProp->append (aux_prop_id); | 
|  | } | 
|  | delete ddscr; | 
|  | Vector<void*> *res = new Vector<void*>(3); | 
|  | res->store (0, dataId); | 
|  | res->store (1, dataName); | 
|  | res->store (2, dataUName); | 
|  | res->store (3, auxProp); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeGetDataPropertiesV2 (int exp_id, int data_id) | 
|  | { | 
|  | Experiment *exp = dbeSession->get_exp (exp_id); | 
|  | if (exp == NULL) | 
|  | return NULL; | 
|  | DataDescriptor *dataDscr = exp->get_raw_events (data_id); | 
|  | if (dataDscr == NULL) | 
|  | return NULL; | 
|  | Vector<PropDescr*> *props = dataDscr->getProps (); | 
|  | Vector<int> *propId = new Vector<int>(props->size ()); | 
|  | Vector<char*> *propUName = new Vector<char*>(props->size ()); | 
|  | Vector<int> *propTypeId = new Vector<int>(props->size ()); | 
|  | Vector<char*> *propTypeName = new Vector<char*>(props->size ()); | 
|  | Vector<int> *propFlags = new Vector<int>(props->size ()); | 
|  | Vector<char*> *propName = new Vector<char*>(props->size ()); | 
|  | Vector<void*> *propStateNames = new Vector<void*>(props->size ()); | 
|  | Vector<void*> *propStateUNames = new Vector<void*>(props->size ()); | 
|  |  | 
|  | for (int i = 0; i < props->size (); i++) | 
|  | { | 
|  | PropDescr *prop = props->fetch (i); | 
|  | char *pname = prop->name; | 
|  | if (pname == NULL) | 
|  | pname = NTXT (""); | 
|  | char *uname = prop->uname; | 
|  | if (uname == NULL) | 
|  | uname = pname; | 
|  | int vtypeNum = prop->vtype; | 
|  | if (vtypeNum < 0 || vtypeNum >= TYPE_LAST) | 
|  | vtypeNum = TYPE_NONE; | 
|  | const char * vtypeNames[] = VTYPE_TYPE_NAMES; | 
|  | const char *vtype = vtypeNames[prop->vtype]; | 
|  | Vector<char*> *stateNames = NULL; | 
|  | Vector<char*> *stateUNames = NULL; | 
|  | int nStates = prop->getMaxState (); | 
|  | if (nStates > 0) | 
|  | { | 
|  | stateNames = new Vector<char*>(nStates); | 
|  | stateUNames = new Vector<char*>(nStates); | 
|  | for (int kk = 0; kk < nStates; kk++) | 
|  | { | 
|  | const char * stateName = prop->getStateName (kk); | 
|  | stateNames->store (kk, dbe_strdup (stateName)); | 
|  | const char * Uname = prop->getStateUName (kk); | 
|  | stateUNames->store (kk, dbe_strdup (Uname)); | 
|  | } | 
|  | } | 
|  | propId->store (i, prop->propID); | 
|  | propUName->store (i, dbe_strdup (uname)); | 
|  | propTypeId->store (i, prop->vtype); | 
|  | propTypeName->store (i, dbe_strdup (vtype)); | 
|  | propFlags->store (i, prop->flags); | 
|  | propName->store (i, dbe_strdup (pname)); | 
|  | propStateNames->store (i, stateNames); | 
|  | propStateUNames->store (i, stateUNames); | 
|  | } | 
|  | Vector<void*> *res = new Vector<void*>(7); | 
|  | res->store (0, propId); | 
|  | res->store (1, propUName); | 
|  | res->store (2, propTypeId); | 
|  | res->store (3, propTypeName); | 
|  | res->store (4, propFlags); | 
|  | res->store (5, propName); | 
|  | res->store (6, propStateNames); | 
|  | res->store (7, propStateUNames); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | Vector<void *> * | 
|  | dbeGetExperimentTimeInfo (Vector<int> *exp_ids) | 
|  | { | 
|  | int sz = exp_ids->size (); | 
|  | Vector<long long> *offset_time = new Vector<long long> (sz); | 
|  | Vector<long long> *start_time = new Vector<long long> (sz); | 
|  | Vector<long long> *end_time = new Vector<long long> (sz); | 
|  | Vector<long long> *start_wall_sec = new Vector<long long> (sz); | 
|  | Vector<char* > *hostname = new Vector<char*> (sz); | 
|  | Vector<int> *cpu_freq = new Vector<int> (sz); | 
|  | for (int ii = 0; ii < sz; ii++) | 
|  | { | 
|  | int expIdx = exp_ids->fetch (ii); | 
|  | { // update end_time by forcing fetch of experiment data | 
|  | // workaround until dbeGetEndTime() is more robust | 
|  | int id = (expIdx < 0) ? 0 : expIdx; | 
|  | Experiment *exp = dbeSession->get_exp (id); | 
|  | if (exp) | 
|  | { | 
|  | Vector<DataDescriptor*> *ddscr = exp->getDataDescriptors (); | 
|  | delete ddscr; | 
|  | } | 
|  | } | 
|  | offset_time->store (ii, dbeGetRelativeStartTime (0, expIdx)); | 
|  | start_time->store (ii, dbeGetStartTime (0, expIdx)); | 
|  | end_time->store (ii, dbeGetEndTime (0, expIdx)); | 
|  | start_wall_sec->store (ii, dbeGetWallStartSec (0, expIdx)); | 
|  | hostname->store (ii, dbeGetHostname (0, expIdx)); | 
|  | cpu_freq->store (ii, dbeGetClock (0, expIdx)); | 
|  | } | 
|  | Vector<void*> *res = new Vector<void*>(4); | 
|  | res->store (0, offset_time); | 
|  | res->store (1, start_time); | 
|  | res->store (2, end_time); | 
|  | res->store (3, start_wall_sec); | 
|  | res->store (4, hostname); | 
|  | res->store (5, cpu_freq); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | Vector<void *> * | 
|  | dbeGetExperimentDataDescriptors (Vector<int> *exp_ids) | 
|  | { | 
|  | int sz = exp_ids->size (); | 
|  | Vector<void*> *exp_dscr_info = new Vector<void*> (sz); | 
|  | Vector<void*> *exp_dscr_props = new Vector<void*> (sz); | 
|  |  | 
|  | for (int ii = 0; ii < sz; ii++) | 
|  | { | 
|  | int expIdx = exp_ids->fetch (ii); | 
|  | Vector<void*> *ddscrInfo = dbeGetDataDescriptorsV2 (expIdx); | 
|  | Vector<void*> *ddscrProps = new Vector<void*> (); // one entry per ddscrInfo | 
|  | if (ddscrInfo) | 
|  | { | 
|  | Vector<int> *dataId = (Vector<int>*)ddscrInfo->fetch (0); | 
|  | if (dataId) | 
|  | { | 
|  | // loop thru data descriptors | 
|  | int ndata = dataId->size (); | 
|  | for (int j = 0; j < ndata; ++j) | 
|  | { | 
|  | Vector<void*> *props = dbeGetDataPropertiesV2 (expIdx, dataId->fetch (j)); | 
|  | ddscrProps->store (j, props); | 
|  | } | 
|  | } | 
|  | } | 
|  | exp_dscr_info->store (ii, ddscrInfo); | 
|  | exp_dscr_props->store (ii, ddscrProps); | 
|  | } | 
|  | Vector<void*> *res = new Vector<void*>(2); | 
|  | res->store (0, exp_dscr_info); | 
|  | res->store (1, exp_dscr_props); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | static Vector<void *> * | 
|  | dbeGetTLDataRepVals (VMode view_mode, hrtime_t start_ts, hrtime_t delta, | 
|  | int numDeltas, DataView*packets, | 
|  | Vector<long> *representativeEvents, bool showDuration); | 
|  |  | 
|  | static bool | 
|  | dbeHasTLData (int dbevindex, int exp_id, int data_id, int entity_prop_id, | 
|  | int entity_prop_value, int aux) | 
|  | { | 
|  | DataView *packets = | 
|  | getTimelinePackets (dbevindex, exp_id, data_id, entity_prop_id); | 
|  | if (!packets || packets->getSize () == 0) | 
|  | return false; | 
|  | long start_ind = getIdxByVals (packets, aux, entity_prop_value, | 
|  | 0, DataView::REL_GTEQ); // time >= 0 | 
|  | if (start_ind < 0) | 
|  | return false; | 
|  |  | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | VMode view_mode = dbev->get_view_mode (); | 
|  | Experiment *exp = dbeSession->get_exp (exp_id); | 
|  | if (!hasInvisbleTLEvents (exp, view_mode)) | 
|  | return true; // all events are visible, no further checking required | 
|  | long end_ind = getIdxByVals (packets, aux, entity_prop_value, | 
|  | MAX_TIME, DataView::REL_LTEQ); | 
|  | for (long ii = start_ind; ii <= end_ind; ii++) | 
|  | { | 
|  | if (!isVisibleTLEvent (exp, view_mode, packets, ii)) | 
|  | continue; | 
|  | return true; // first visible packet => has data | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | Vector<bool> * | 
|  | dbeHasTLData (int dbev_index, Vector<int> *exp_ids, Vector<int> *data_ids, | 
|  | Vector<int> *entity_prop_ids, // LWP,CPU,THR, etc | 
|  | Vector<int> *entity_prop_values, Vector<int> *auxs) | 
|  | { | 
|  | DbeView *dbev = dbeSession->getView (dbev_index); | 
|  | if (!dbev->isShowAll () && (dbev->isShowHideChanged () | 
|  | || dbev->isNewViewMode ())) | 
|  | { | 
|  | // LIBRARY_VISIBILITY | 
|  | dbev->resetAndConstructShowHideStacks (); | 
|  | if (dbev->isNewViewMode ()) | 
|  | dbev->resetNewViewMode (); | 
|  | if (dbev->isShowHideChanged ()) | 
|  | dbev->resetShowHideChanged (); | 
|  | } | 
|  |  | 
|  | int sz = exp_ids->size (); | 
|  | Vector<bool> *hasVec = new Vector<bool>(sz); | 
|  | for (int ii = 0; ii < sz; ii++) | 
|  | { | 
|  | bool hasData = dbeHasTLData (dbev_index, exp_ids->fetch (ii), | 
|  | data_ids->fetch (ii), | 
|  | entity_prop_ids->fetch (ii), | 
|  | entity_prop_values->fetch (ii), | 
|  | auxs->fetch (ii)); | 
|  | hasVec->store (ii, hasData); | 
|  | } | 
|  | return hasVec; | 
|  | } | 
|  |  | 
|  | /* | 
|  | *   dbeGetTLData implements: | 
|  | *   FROM data_id | 
|  | *     DURATION >= delta AND ( start_ts <= TSTAMP < start_ts+num*delta OR | 
|  | *                             start_ts <= TSTAMP-DURATION < start_ts+num*delta ) | 
|  | *     OR | 
|  | *     FAIR( DURATION < delta AND ( start_ts <= TSTAMP < start_ts+num*delta ) ) | 
|  | *     WHERE lfilter | 
|  | */ | 
|  |  | 
|  | Vector<void *> * | 
|  | dbeGetTLData ( | 
|  | int dbevindex, | 
|  | int exp_id, | 
|  | int data_id, // DATA_* | 
|  | int entity_prop_id, // Show PROP_LWPID, PROP_CPUID, PROP_THRID, PROP_EXPID, or N/A | 
|  | int entity_prop_value, // which LWPID, CPUID, THRID, EXPID for this request | 
|  | int aux, | 
|  | hrtime_t param_start_ts, | 
|  | hrtime_t param_delta, | 
|  | int param_numDeltas, | 
|  | bool getRepresentatives, // fetch TL representatives | 
|  | Vector<char *> *chartProps) // calculate sums for these property vals | 
|  | { | 
|  | const hrtime_t start_ts = param_start_ts; | 
|  | const hrtime_t delta = param_delta; | 
|  | const int numDeltas = param_numDeltas; | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | if (dbev == NULL) | 
|  | abort (); | 
|  | Experiment *exp = dbeSession->get_exp (exp_id); | 
|  | if (exp == NULL) | 
|  | return NULL; | 
|  | if (getRepresentatives == false && chartProps == NULL) | 
|  | return NULL; | 
|  | if (delta <= 0) | 
|  | return NULL; | 
|  |  | 
|  | hrtime_t tmp_ts = start_ts + delta * numDeltas; | 
|  | if (tmp_ts < start_ts) | 
|  | tmp_ts = MAX_TIME; | 
|  | const hrtime_t end_ts = tmp_ts; | 
|  | if (exp->get_status () == Experiment::INCOMPLETE && | 
|  | exp->getLastEvent () < end_ts) | 
|  | exp->update (); | 
|  | DataView *packets = | 
|  | getTimelinePackets (dbevindex, exp_id, data_id, entity_prop_id); | 
|  | if (packets == NULL) | 
|  | return NULL; // strange, no data view? | 
|  |  | 
|  | VMode view_mode = dbev->get_view_mode (); // user, expert, machine //YXXX yuck | 
|  |  | 
|  | // storage for calculating timeline representative events | 
|  | Vector<long> *representativeEvents = NULL; | 
|  | // list of representative events to be displayed on TL | 
|  | Vector<int> *binRepIdx = NULL; | 
|  | // for each bin, index    of current "best" representativeEvent | 
|  | Vector<void*> *representativeVals = NULL; | 
|  | // TL representative packets' values | 
|  |  | 
|  | // storage for calculating charts | 
|  | Vector<int> *propIds = NULL; // [propIdx], which prop to measure | 
|  | Vector<void*> *propVals = NULL; // [propIdx][bin], prop vals | 
|  | Vector<int> *propNumStates = NULL; // [propIdx], how many states for prop? | 
|  | Vector<bool> *propCumulativeChart = NULL; // [propIdx], data represents cumulative totals | 
|  | Vector<long long> *propCumulativeRecentBinLastVal = NULL; // [propIdx], most recent value | 
|  | Vector<long long> *propCumulativeRecentBinHighVal = NULL; // [propIdx], highest value for propCumulativeRecentBin | 
|  | Vector<int> *propCumulativeRecentBin = NULL; // [propIdx], most recent bin | 
|  |  | 
|  | // determine when to show duration of events | 
|  | bool tmp_repsShowDuration = false; | 
|  | bool tmp_statesUseDuration = false; | 
|  | bool tmp_extendMicrostates = false; | 
|  | const hrtime_t ptimerTickDuration = exp->get_params ()->ptimer_usec * 1000LL; // nanoseconds per tick | 
|  | const bool hasDuration = packets->getProp (PROP_EVT_TIME) ? true : false; | 
|  | if (hasDuration) | 
|  | { | 
|  | switch (entity_prop_id) | 
|  | { | 
|  | case PROP_CPUID: | 
|  | tmp_repsShowDuration = false; | 
|  | tmp_statesUseDuration = false; | 
|  | break; | 
|  | case PROP_THRID: | 
|  | case PROP_LWPID: | 
|  | tmp_repsShowDuration = true; | 
|  | tmp_statesUseDuration = true; | 
|  | tmp_extendMicrostates = (DATA_CLOCK == data_id) && (ptimerTickDuration < param_delta); | 
|  | break; | 
|  | case PROP_EXPID: | 
|  | case PROP_NONE: // experiment summary row uses this | 
|  | default: | 
|  | if (DATA_SAMPLE == data_id) | 
|  | { | 
|  | tmp_repsShowDuration = true; | 
|  | tmp_statesUseDuration = true; | 
|  | } | 
|  | else if (DATA_GCEVENT == data_id) | 
|  | { | 
|  | tmp_repsShowDuration = true; | 
|  | tmp_statesUseDuration = true; | 
|  | } | 
|  | else if (DATA_CLOCK == data_id) | 
|  | { | 
|  | tmp_repsShowDuration = false; | 
|  | tmp_statesUseDuration = true; | 
|  | tmp_extendMicrostates = true; | 
|  | } | 
|  | else | 
|  | { | 
|  | tmp_repsShowDuration = false; | 
|  | tmp_statesUseDuration = true; | 
|  | } | 
|  | break; | 
|  | } | 
|  | } | 
|  | const bool repsShowDuration = tmp_repsShowDuration; // show stretched callstacks | 
|  | const bool statesUseDuration = tmp_statesUseDuration; // use duration to calculate state charts | 
|  | const bool extendMicrostates = tmp_extendMicrostates; // we show discrete profiling microstates with | 
|  | // width=(tick-1), but for computing | 
|  | // zoomed-out graphs we need to extend to | 
|  | // account for all ticks, width=(ntick) | 
|  | const bool reverseScan = repsShowDuration || extendMicrostates; // scan packets in reverse | 
|  |  | 
|  | // determine range of packet indices (lo_pkt_idx, hi_pkt_idx) | 
|  | long lo_pkt_idx, hi_pkt_idx; | 
|  | if (extendMicrostates && !(entity_prop_id == PROP_THRID || entity_prop_id == PROP_LWPID)) | 
|  | { | 
|  | // merging data from multiple threads, need to scan all packets with timestamp [start_ts, exp end] | 
|  | hrtime_t exp_end_time = exp->getLastEvent () + 1; | 
|  | hi_pkt_idx = getIdxByVals (packets, aux, entity_prop_value, | 
|  | exp_end_time, DataView::REL_LT); // last item | 
|  | } | 
|  | else | 
|  | hi_pkt_idx = getIdxByVals (packets, aux, entity_prop_value, | 
|  | end_ts, DataView::REL_LT); | 
|  | if (repsShowDuration) | 
|  | { | 
|  | // There are two issues to deal with | 
|  | // 1. events that end "off screen" to the right | 
|  | // 2. overlapping events | 
|  |  | 
|  | // 1. events that end "off screen" to the right | 
|  | // For now, we only consistently handle the case where events don't overlap. | 
|  | // Note that packet timestamps mark end of duration, not start. | 
|  | // This means that the rightmost event won't be within hi_pkt_idx. | 
|  | // Solution: Check if end+1 packet _started_ in-range | 
|  | // Caveat: because we only look ahead by one packet, if there are | 
|  | // overlapping duration events (e.g. EXPID aggregation)), zoom level | 
|  | // and panning combo may cause events with TSTAMP>end_ts | 
|  | // to appear/disappear.  A complete solution would involve | 
|  | // a solution to 2. | 
|  |  | 
|  | // 2. overlapping events | 
|  | // For now, we have a simplistic solution that makes "wide" events win.  However, | 
|  | // a future solution for deterministically dealing with overlap might look like this: | 
|  | // - find all packets that touch the visible time range | 
|  | //   - possibly use two DataViews: one with TSTAMP_HI sort and one with TSTAMP_LO | 
|  | //     sort to allow efficient determination of packets with HI and LO endpoints in-range | 
|  | // - create buckets to  capture "winning" event for each bin (each pixel, that is) | 
|  | // - sort the new list of packets by TSTAMP_HI (for example) | 
|  | // - looping thru the packets that are in-range, update every bin it touches with it's id | 
|  | // - if there is overlap, earlier packets will be kicked out of bins | 
|  | // - On the GUI side, paint one event at a time, as normal. | 
|  | // - However, for selections, recognize that duration of event may span many bins | 
|  | // | 
|  | long idx; | 
|  | if (hi_pkt_idx >= 0) | 
|  | // a packet was found to the left of the end time | 
|  | idx = hi_pkt_idx + 1; // attempt to go one packet right | 
|  | else | 
|  | idx = getIdxByVals (packets, aux, entity_prop_value, | 
|  | end_ts, DataView::REL_GTEQ); | 
|  | if (isValidIdx (packets, entity_prop_id, aux, entity_prop_value, idx)) | 
|  | { | 
|  | int64_t pkt_ts = packets->getLongValue (PROP_TSTAMP, idx); | 
|  | int64_t duration = packets->getLongValue (PROP_EVT_TIME, idx); | 
|  | pkt_ts -= duration; | 
|  | if (pkt_ts < end_ts) | 
|  | hi_pkt_idx = idx; | 
|  | } | 
|  | } | 
|  | lo_pkt_idx = getIdxByVals (packets, aux, entity_prop_value, | 
|  | start_ts, DataView::REL_GTEQ); | 
|  |  | 
|  | // allocate structs that return chart data | 
|  | bool hasCumulativeCharts = false; | 
|  | if (chartProps && chartProps->size () > 0) | 
|  | { | 
|  | int nprops = chartProps->size (); | 
|  | // pre-allocate storage | 
|  | propIds = new Vector<int> (nprops); | 
|  | propVals = new Vector<void*>(nprops); | 
|  | propNumStates = new Vector<int> (nprops); | 
|  | propCumulativeChart = new Vector<bool>(nprops); | 
|  | propCumulativeRecentBinLastVal = new Vector<long long>(nprops); | 
|  | propCumulativeRecentBinHighVal = new Vector<long long>(nprops); | 
|  | propCumulativeRecentBin = new Vector<int>(nprops); | 
|  | for (int propNum = 0; propNum < nprops; propNum++) | 
|  | { | 
|  | const char* propStr = chartProps->fetch (propNum); | 
|  | int items_per_prop = 0; | 
|  | int prop_id = PROP_NONE; | 
|  | if (!strcmp (propStr, "EVT_COUNT")) | 
|  | items_per_prop = 1; // use PROP_NONE for counting packets | 
|  | else | 
|  | { | 
|  | int lookup_prop_id = dbeSession->getPropIdByName (propStr); | 
|  | PropDescr *propDscr = packets->getProp (lookup_prop_id); | 
|  | if (propDscr != NULL) | 
|  | { | 
|  | switch (propDscr->vtype) | 
|  | { | 
|  | case TYPE_INT32: | 
|  | case TYPE_UINT32: | 
|  | case TYPE_INT64: | 
|  | case TYPE_UINT64: | 
|  | items_per_prop = propDscr->getMaxState () + 1; | 
|  | // add extra slot to store values with out-of-range idx | 
|  | prop_id = lookup_prop_id; | 
|  | break; | 
|  | case TYPE_DOUBLE: | 
|  | break; // not implemented yet | 
|  | case TYPE_STRING: | 
|  | case TYPE_OBJ: | 
|  | case TYPE_DATE: | 
|  | default: | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | void *vals; | 
|  | if (!items_per_prop) | 
|  | vals = NULL; | 
|  | else if (items_per_prop == 1) | 
|  | { | 
|  | Vector<long long> *longVals = new Vector<long long> (); | 
|  | longVals->store (numDeltas - 1, 0); // initialize all elements | 
|  | vals = longVals; | 
|  | } | 
|  | else | 
|  | { | 
|  | Vector<Vector<long long>*> *stateVals = | 
|  | new Vector<Vector<long long>*> (); | 
|  | vals = stateVals; | 
|  | // initialize only on-demand, some may not be needed | 
|  | } | 
|  |  | 
|  | bool isCumulativeChart; | 
|  | #define YXXX_HEAP_VS_TIME 1 // YXXX add data meaning to properties? | 
|  | #if YXXX_HEAP_VS_TIME | 
|  | isCumulativeChart = (prop_id == PROP_HCUR_LEAKS || prop_id == PROP_HCUR_ALLOCS); | 
|  | #endif | 
|  | if (isCumulativeChart) | 
|  | hasCumulativeCharts = true; | 
|  | propIds->store (propNum, prop_id); | 
|  | propVals->store (propNum, vals); | 
|  | propNumStates->store (propNum, items_per_prop); | 
|  | propCumulativeRecentBinLastVal->store (propNum, 0); | 
|  | propCumulativeRecentBinHighVal->store (propNum, 0); | 
|  | propCumulativeRecentBin->store (propNum, 0); | 
|  | propCumulativeChart->store (propNum, isCumulativeChart); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Adjust idx range for calculating 'cumulative charts' e.g. heap size | 
|  | if (hasCumulativeCharts) | 
|  | { | 
|  | // set initial values if earlier packet exists | 
|  | long lo_idx; | 
|  | if (lo_pkt_idx >= 0) | 
|  | // packet was found to the right of start | 
|  | lo_idx = lo_pkt_idx - 1; // attempt to go left by one event | 
|  | else | 
|  | // no packet was to the right of start, look left of start | 
|  | lo_idx = getIdxByVals (packets, aux, entity_prop_value, | 
|  | start_ts, DataView::REL_LT); | 
|  | if (isValidIdx (packets, entity_prop_id, aux, entity_prop_value, lo_idx)) | 
|  | { | 
|  | // preceding packet found | 
|  | // update initial values | 
|  | int nprops = propCumulativeChart->size (); | 
|  | for (int propNum = 0; propNum < nprops; propNum++) | 
|  | { | 
|  | if (!propCumulativeChart->fetch (propNum)) | 
|  | continue; | 
|  | int propId = propIds->fetch (propNum); | 
|  | long long value = packets->getLongValue (propId, lo_idx); | 
|  | propCumulativeRecentBinLastVal->store (propNum, value); | 
|  | propCumulativeRecentBinHighVal->store (propNum, value); | 
|  | } | 
|  | // update indices used for iterating | 
|  | lo_pkt_idx = lo_idx; | 
|  | if (hi_pkt_idx < lo_pkt_idx) | 
|  | hi_pkt_idx = lo_pkt_idx; | 
|  | } | 
|  | } | 
|  | if (lo_pkt_idx < 0 || hi_pkt_idx < 0) | 
|  | goto dbeGetTLData_done; // no data; return empty vectors, not null | 
|  |  | 
|  | // representative events (subset of callstacks to represent on TL) | 
|  | if (getRepresentatives) | 
|  | { | 
|  | representativeEvents = new Vector<long>(numDeltas); | 
|  | // per-bin, longest event's index | 
|  | binRepIdx = new Vector<int>(numDeltas); | 
|  | for (int ii = 0; ii < numDeltas; ++ii) | 
|  | binRepIdx->append (-1); | 
|  | } | 
|  | // While packets are sorted by _end_ timestamp (TSTAMP), | 
|  | // after calculating start times for non-zero durations, | 
|  | // start times are not guaranteed be monotonically increasing. | 
|  | // For packets with duration, we'll scan them in reverse order to | 
|  | // take advantage of the monotonically decreasing _end_ timestamps. | 
|  | long start_idx, idx_inc; | 
|  | if (!reverseScan) | 
|  | { | 
|  | start_idx = lo_pkt_idx; | 
|  | idx_inc = 1; | 
|  | } | 
|  | else | 
|  | { | 
|  | start_idx = hi_pkt_idx; | 
|  | idx_inc = -1; | 
|  | } | 
|  | for (long ii = start_idx; ii >= lo_pkt_idx && ii <= hi_pkt_idx; ii += idx_inc) | 
|  | { | 
|  | if (!isVisibleTLEvent (exp, view_mode, packets, ii) && !hasCumulativeCharts) | 
|  | continue; | 
|  |  | 
|  | // determine packet time duration and start bin | 
|  | int tmp_start_bin; // packet start bin | 
|  | int tmp_end_bin; // packet end bin (inclusive) | 
|  | const hrtime_t pkt_end_ts = packets->getLongValue (PROP_TSTAMP, ii); | 
|  | const hrtime_t pkt_dur = packets->getLongValue (PROP_EVT_TIME, ii); | 
|  | const hrtime_t pkt_start_ts = pkt_end_ts - pkt_dur; | 
|  | if (pkt_end_ts < start_ts && !hasCumulativeCharts) | 
|  | continue; // weird, should not happen | 
|  | if (pkt_start_ts >= end_ts) | 
|  | continue; // could happen | 
|  | hrtime_t bin_end_ts = pkt_end_ts; | 
|  | if (bin_end_ts >= end_ts) | 
|  | bin_end_ts = end_ts - 1; | 
|  | tmp_end_bin = (int) ((bin_end_ts - start_ts) / delta); | 
|  | hrtime_t bin_start_ts = pkt_start_ts; | 
|  | if (bin_start_ts < start_ts) | 
|  | bin_start_ts = start_ts; // event truncated to left. | 
|  | tmp_start_bin = (int) ((bin_start_ts - start_ts) / delta); | 
|  | // By definition | 
|  | //   (end_ts - start_ts) == delta * numDeltas | 
|  | // and we know | 
|  | //   pkt_start < end_ts | 
|  | // therefore | 
|  | //   (pkt_start - start_ts) < delta * numDeltas | 
|  | //   (pkt_start - start_ts) / delta < numDeltas | 
|  | //   bin < numDeltas | 
|  | assert (tmp_end_bin < numDeltas); | 
|  | assert (tmp_start_bin < numDeltas); | 
|  | const bool is_offscreen = tmp_end_bin < 0 ? true : false; | 
|  | if (tmp_end_bin < 0) | 
|  | tmp_end_bin = 0; | 
|  | const int pkt_end_bin = tmp_end_bin; // packet end bin (inclusive) | 
|  | const int pkt_start_bin = tmp_start_bin; | 
|  | if (getRepresentatives && !is_offscreen) | 
|  | { // find best representative | 
|  | // Note: for events with duration, we're scanning packets in order | 
|  | // of decreasing end-timestamp.  This means that the first packet | 
|  | // that hits a particular _start_ bin will have the longest duration | 
|  | // of any later packet that might hit that start bin.  The | 
|  | // the first packet will be the best (longest) packet. | 
|  | const int bin = reverseScan ? pkt_start_bin : pkt_end_bin; | 
|  | int eventIdx = binRepIdx->fetch (bin); | 
|  | if (eventIdx == -1) | 
|  | { | 
|  | eventIdx = representativeEvents->size (); // append to end | 
|  | representativeEvents->append (ii); | 
|  | binRepIdx->store (bin, eventIdx); | 
|  | } | 
|  | } | 
|  | if (propIds) | 
|  | { // per-bin chart: sum across filtered packets | 
|  | for (int propNum = 0; propNum < propIds->size (); propNum++) | 
|  | { | 
|  | void *thisProp = propVals->fetch (propNum); | 
|  | if (thisProp == NULL) | 
|  | continue; // no valid data | 
|  | if (is_offscreen && !propCumulativeChart->fetch (propNum)) | 
|  | continue; // offscreen events are only processed for cumulative charts | 
|  | int propId = propIds->fetch (propNum); | 
|  | long long val; | 
|  | if (propId == PROP_NONE) | 
|  | val = 1; // count | 
|  | else | 
|  | val = packets->getLongValue (propId, ii); | 
|  | long nitems = propNumStates->fetch (propNum); | 
|  | if (nitems < 1) | 
|  | continue; | 
|  | else if (nitems == 1) | 
|  | { | 
|  | // chart is not based on not multiple states | 
|  | Vector<long long>* thisPropVals = | 
|  | (Vector<long long>*)thisProp; | 
|  | if (thisPropVals->size () == 0) | 
|  | thisPropVals->store (numDeltas - 1, 0); | 
|  | const int bin = statesUseDuration ? pkt_start_bin : pkt_end_bin; | 
|  | if (!propCumulativeChart->fetch (propNum)) | 
|  | { | 
|  | val += thisPropVals->fetch (bin); | 
|  | thisPropVals->store (bin, val); | 
|  | } | 
|  | else | 
|  | { | 
|  | // propCumulativeChart | 
|  | long long high_value = propCumulativeRecentBinHighVal->fetch (propNum); | 
|  | int last_bin = propCumulativeRecentBin->fetch (propNum); | 
|  | if (last_bin < bin) | 
|  | { | 
|  | // backfill from previous event | 
|  | // last_bin: store largest value (in case of multiple events) | 
|  | thisPropVals->store (last_bin, high_value); | 
|  | // propagate forward the bin's last value | 
|  | long long last_value = propCumulativeRecentBinLastVal->fetch (propNum); | 
|  | for (int kk = last_bin + 1; kk < bin; kk++) | 
|  | thisPropVals->store (kk, last_value); | 
|  | // prepare new bin for current event | 
|  | high_value = 0; // high value of next bin is 0. | 
|  | propCumulativeRecentBinHighVal->store (propNum, high_value); | 
|  | propCumulativeRecentBin->store (propNum, bin); | 
|  | } | 
|  | long long this_value = packets->getLongValue (propId, ii); | 
|  | propCumulativeRecentBinLastVal->store (propNum, this_value); | 
|  | if (high_value < this_value) | 
|  | { | 
|  | // record the max | 
|  | high_value = this_value; | 
|  | propCumulativeRecentBinHighVal->store (propNum, high_value); | 
|  | } | 
|  | if (ii == hi_pkt_idx) | 
|  | { | 
|  | // bin: show largest value (in case of multiple events | 
|  | thisPropVals->store (bin, high_value); | 
|  | //forward fill remaining bins | 
|  | for (int kk = bin + 1; kk < numDeltas; kk++) | 
|  | thisPropVals->store (kk, this_value); | 
|  | } | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | // means val is actually a state # | 
|  | Vector<Vector<long long>*>* thisPropStateVals = | 
|  | (Vector<Vector<long long>*>*)thisProp; | 
|  | if (thisPropStateVals->size () == 0) | 
|  | thisPropStateVals->store (numDeltas - 1, 0); | 
|  | long stateNum; | 
|  | if (val >= 0 && val < nitems) | 
|  | stateNum = (long) val; | 
|  | else | 
|  | stateNum = nitems - 1; // out of range, use last slot | 
|  | hrtime_t graph_pkt_dur = pkt_dur; | 
|  | hrtime_t graph_pkt_start_ts = pkt_start_ts; | 
|  | int tmp2_start_bin = pkt_start_bin; | 
|  | if (propId == PROP_MSTATE) | 
|  | { | 
|  | if (statesUseDuration && extendMicrostates) | 
|  | { | 
|  | // microstate stacks are shown and filtered with width=NTICK-1 | 
|  | // but for microstate graph calcs use width=NTICK. | 
|  | graph_pkt_dur += ptimerTickDuration; | 
|  | graph_pkt_start_ts -= ptimerTickDuration; | 
|  | hrtime_t bin_start_ts = graph_pkt_start_ts; | 
|  | if (bin_start_ts < start_ts) | 
|  | bin_start_ts = start_ts; // event truncated to left. | 
|  | tmp2_start_bin = (int) ((bin_start_ts - start_ts) / delta); | 
|  | } | 
|  | } | 
|  | const int graph_pkt_start_bin = statesUseDuration ? tmp2_start_bin : pkt_end_bin; | 
|  |  | 
|  | // We will distribute the state's presence evenly over duration of the event. | 
|  | // When only a 'partial bin' is touched by an event, adjust accordingly. | 
|  | long long value_per_bin; // weight to be applied to each bin | 
|  | { | 
|  | long long weight; | 
|  | if (propId == PROP_MSTATE)  // ticks to nanoseconds | 
|  | weight = packets->getLongValue (PROP_NTICK, ii) * ptimerTickDuration; | 
|  | else if (graph_pkt_dur) | 
|  | weight = graph_pkt_dur; // nanoseconds | 
|  | else | 
|  | weight = 1; // no duration; indicate presence | 
|  | if (graph_pkt_start_bin != pkt_end_bin) | 
|  | { | 
|  | // spans multiple bins | 
|  | double nbins = (double) graph_pkt_dur / delta; | 
|  | value_per_bin = weight / nbins; | 
|  | } | 
|  | else | 
|  | value_per_bin = weight; | 
|  | } | 
|  | for (int evtbin = graph_pkt_start_bin; evtbin <= pkt_end_bin; evtbin++) | 
|  | { | 
|  | Vector<long long>* stateValues = | 
|  | (Vector<long long>*) thisPropStateVals->fetch (evtbin); | 
|  | if (stateValues == NULL) | 
|  | { | 
|  | // on-demand storage | 
|  | stateValues = new Vector<long long>(nitems); | 
|  | stateValues->store (nitems - 1, 0); // force memset of full vector | 
|  | thisPropStateVals->store (evtbin, stateValues); | 
|  | } | 
|  | long long new_val = stateValues->fetch (stateNum); | 
|  | if (graph_pkt_start_bin == pkt_end_bin || | 
|  | (evtbin > graph_pkt_start_bin && evtbin < pkt_end_bin)) | 
|  | { | 
|  | new_val += value_per_bin; | 
|  | } | 
|  | else | 
|  | { | 
|  | // partial bin | 
|  | const hrtime_t bin_start = start_ts + evtbin * delta; | 
|  | const hrtime_t bin_end = start_ts + (evtbin + 1) * delta - 1; | 
|  | if (evtbin == graph_pkt_start_bin) | 
|  | { | 
|  | // leftmost bin | 
|  | if (graph_pkt_start_ts < bin_start) | 
|  | new_val += value_per_bin; | 
|  | else | 
|  | { | 
|  | double percent = (double) (bin_end - graph_pkt_start_ts) / delta; | 
|  | new_val += value_per_bin*percent; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | // rightmost bin | 
|  | if (pkt_end_ts > bin_end) | 
|  | new_val += value_per_bin; | 
|  | else | 
|  | { | 
|  | double percent = (double) (pkt_end_ts - bin_start) / delta; | 
|  | new_val += value_per_bin*percent; | 
|  | } | 
|  | } | 
|  | } | 
|  | stateValues->store (stateNum, new_val); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | delete binRepIdx; | 
|  | delete propIds; | 
|  | delete propCumulativeChart; | 
|  | delete propCumulativeRecentBinLastVal; | 
|  | delete propCumulativeRecentBinHighVal; | 
|  | delete propCumulativeRecentBin; | 
|  | if (representativeEvents != NULL && reverseScan) | 
|  | { | 
|  | if (repsShowDuration) | 
|  | { | 
|  | //YXXX for now prune here, but in the future, let gui decide what to show | 
|  | // Prune events that are completely obscured long duration events. | 
|  | // Note: representativeEvents is sorted by decreasing _end_ timestamps. | 
|  | Vector<long> *prunedEvents = new Vector<long>(numDeltas); | 
|  | hrtime_t prev_start_ts = MAX_TIME; | 
|  | long repCnt = representativeEvents->size (); | 
|  | for (long kk = 0; kk < repCnt; kk++) | 
|  | { | 
|  | long ii = representativeEvents->fetch (kk); | 
|  | hrtime_t tmp_end_ts = packets->getLongValue (PROP_TSTAMP, ii); | 
|  | hrtime_t tmp_dur = packets->getLongValue (PROP_EVT_TIME, ii); | 
|  | hrtime_t tmp_start_ts = tmp_end_ts - tmp_dur; | 
|  | if (tmp_start_ts >= prev_start_ts) | 
|  | // this event would be completely hidden | 
|  | // (because of sorting, we know tmp_end_ts <= prev_end_ts) | 
|  | continue; | 
|  | prev_start_ts = tmp_start_ts; | 
|  | prunedEvents->append (ii); | 
|  | } | 
|  | // invert order to to get increasing _end_ timestamps | 
|  | representativeEvents->reset (); | 
|  | for (long kk = prunedEvents->size () - 1; kk >= 0; kk--) | 
|  | { | 
|  | long packet_idx = prunedEvents->fetch (kk); | 
|  | representativeEvents->append (packet_idx); | 
|  | } | 
|  | delete prunedEvents; | 
|  | } | 
|  | else | 
|  | { // !repsShowDuration | 
|  | // Note: representativeEvents is sorted by decreasing _end_ timestamps. | 
|  | // Reverse the order: | 
|  | long hi_idx = representativeEvents->size () - 1; | 
|  | long lo_idx = 0; | 
|  | while (hi_idx > lo_idx) | 
|  | { | 
|  | // swap | 
|  | long lo = representativeEvents->fetch (lo_idx); | 
|  | long hi = representativeEvents->fetch (hi_idx); | 
|  | representativeEvents->store (lo_idx, hi); | 
|  | representativeEvents->store (hi_idx, lo); | 
|  | hi_idx--; | 
|  | lo_idx++; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | dbeGetTLData_done: | 
|  | if (getRepresentatives) | 
|  | { | 
|  | representativeVals = dbeGetTLDataRepVals (view_mode, start_ts, delta, | 
|  | numDeltas, packets, representativeEvents, repsShowDuration); | 
|  | delete representativeEvents; | 
|  | } | 
|  | Vector<void*> *results = new Vector<void*> (2); | 
|  | results->store (0, representativeVals); | 
|  | results->store (1, propVals); | 
|  | return results; | 
|  | } | 
|  |  | 
|  | // add representative events to return buffer | 
|  |  | 
|  | static Vector<void *> * | 
|  | dbeGetTLDataRepVals (VMode view_mode, hrtime_t start_ts, hrtime_t delta, | 
|  | int numDeltas, DataView*packets, | 
|  | Vector<long> *representativeEvents, bool showDuration) | 
|  | { | 
|  | int numrecs = representativeEvents ? representativeEvents->size () : 0; | 
|  | // allocate storage for results | 
|  | Vector<int> *startBins = new Vector<int>(numrecs); | 
|  | Vector<int> *numBins = new Vector<int>(numrecs); | 
|  | Vector<Obj> *eventIdxs = new Vector<Obj>(numrecs); | 
|  | Vector<Obj> *stackIds = NULL; | 
|  | if (packets->getProp (PROP_FRINFO)) | 
|  | stackIds = new Vector<Obj>(numrecs); | 
|  | Vector<int> *mstates = NULL; | 
|  | if (packets->getProp (PROP_MSTATE)) | 
|  | mstates = new Vector<int>(numrecs); | 
|  | Vector<Vector<long long>*> *sampleVals = NULL; | 
|  | if (packets->getProp (PROP_SMPLOBJ)) | 
|  | sampleVals = new Vector<Vector<long long>*>(numrecs); | 
|  | Vector<long long> *timeStart = new Vector<long long>(numrecs); | 
|  | Vector<long long> *timeEnd = new Vector<long long>(numrecs); | 
|  | int prevEndBin = -1; // make sure we don't overlap bins | 
|  | for (int eventIdx = 0; eventIdx < numrecs; eventIdx++) | 
|  | { | 
|  | long packetIdx = representativeEvents->fetch (eventIdx); | 
|  | // long eventId = packets->getIdByIdx( packetIdx ); | 
|  | const hrtime_t pkt_tstamp = packets->getLongValue (PROP_TSTAMP, packetIdx); | 
|  | const hrtime_t pkt_dur = showDuration ? packets->getLongValue (PROP_EVT_TIME, packetIdx) : 0; | 
|  | timeStart->store (eventIdx, pkt_tstamp - pkt_dur); | 
|  | timeEnd->store (eventIdx, pkt_tstamp); | 
|  |  | 
|  | // calc startBin | 
|  | int startBin = (int) ((pkt_tstamp - pkt_dur - start_ts) / delta); | 
|  | if (startBin <= prevEndBin) | 
|  | startBin = prevEndBin + 1; | 
|  | // calc binCnt | 
|  | int endBin = (int) ((pkt_tstamp - start_ts) / delta); | 
|  | if (endBin >= numDeltas) | 
|  | endBin = numDeltas - 1; | 
|  | int binCnt = endBin - startBin + 1; | 
|  | prevEndBin = endBin; | 
|  | startBins->store (eventIdx, startBin); | 
|  | numBins->store (eventIdx, binCnt); | 
|  | eventIdxs->store (eventIdx, packetIdx); // store packet's idx | 
|  | if (stackIds != NULL) | 
|  | { | 
|  | void* stackId = getStack (view_mode, packets, packetIdx); | 
|  | stackIds->store (eventIdx, (Obj) (unsigned long) stackId); | 
|  | } | 
|  | if (mstates != NULL) | 
|  | { | 
|  | int mstate = packets->getIntValue (PROP_MSTATE, packetIdx); | 
|  | mstates->store (eventIdx, mstate); | 
|  | } | 
|  | if (sampleVals != NULL) | 
|  | { | 
|  | Sample *sample = (Sample*) packets->getObjValue (PROP_SMPLOBJ, packetIdx); | 
|  | if (sample != NULL) | 
|  | { | 
|  | PrUsage *prusage = sample->get_usage (); | 
|  | if (prusage != NULL) | 
|  | sampleVals->store (eventIdx, prusage->getMstateValues ()); | 
|  | } | 
|  | } | 
|  | } | 
|  | // caller responsible for: delete representativeEvents; | 
|  | Vector<void*> *results = new Vector<void*> (8); | 
|  | results->store (0, startBins); | 
|  | results->store (1, numBins); | 
|  | results->store (2, eventIdxs); | 
|  | results->store (3, stackIds); | 
|  | results->store (4, mstates); | 
|  | results->store (5, sampleVals); | 
|  | results->store (6, timeStart); | 
|  | results->store (7, timeEnd); | 
|  | return results; | 
|  | } | 
|  |  | 
|  | // starting from <event_id> packet idx, step <move_count> visible events | 
|  | // return the resulting idx and that packet's center time, or null if no event. | 
|  | Vector<long long> * | 
|  | dbeGetTLEventCenterTime (int dbevindex, int exp_id, int data_id, | 
|  | int entity_prop_id, int entity_prop_val, int aux, | 
|  | long long event_id, long long move_count) | 
|  | { | 
|  | DataView *packets = getTimelinePackets (dbevindex, exp_id, data_id, | 
|  | entity_prop_id); | 
|  | if (packets == NULL) | 
|  | return NULL; | 
|  | long idx = (long) event_id; | 
|  |  | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | VMode view_mode = dbev->get_view_mode (); | 
|  | Experiment *exp = dbeSession->get_exp (exp_id); | 
|  | int direction; | 
|  | if (move_count == 0) | 
|  | direction = 0; | 
|  | else if (move_count < 0) | 
|  | { | 
|  | move_count = -move_count; | 
|  | direction = -1; | 
|  | } | 
|  | else | 
|  | direction = 1; | 
|  | idx = getTLVisibleIdxByStepping (exp, view_mode, entity_prop_id, packets, aux, | 
|  | entity_prop_val, idx, move_count, direction); | 
|  | if (idx >= 0) | 
|  | { | 
|  | long long ts = packets->getLongValue (PROP_TSTAMP, idx); | 
|  | long long dur = packets->getLongValue (PROP_EVT_TIME, idx); | 
|  | long long center = ts - dur / 2; | 
|  | Vector<long long> *results = new Vector<long long> (2); | 
|  | results->store (0, idx); // result idx | 
|  | results->store (1, center); // result timestamp | 
|  | return results; | 
|  | } | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | long long | 
|  | dbeGetTLEventIdxNearTime (int dbevindex, int exp_id, int data_id, | 
|  | int entity_prop_id, int entity_prop_val, int aux, | 
|  | int searchDirection, long long tstamp) | 
|  | { | 
|  | DataView *packets = getTimelinePackets (dbevindex, exp_id, data_id, | 
|  | entity_prop_id); | 
|  | if (packets == NULL) | 
|  | return -1; | 
|  | DbeView *dbev = dbeSession->getView (dbevindex); | 
|  | VMode view_mode = dbev->get_view_mode (); | 
|  | Experiment *exp = dbeSession->get_exp (exp_id); | 
|  | if (searchDirection < 0) | 
|  | { | 
|  | int idx = getTLVisibleIdxByVals (exp, view_mode, entity_prop_id, | 
|  | packets, aux, entity_prop_val, tstamp, | 
|  | DataView::REL_LTEQ); | 
|  | if (idx != -1) | 
|  | return idx; | 
|  | searchDirection = 1; // couldn't find to left, try to right | 
|  | } | 
|  | if (searchDirection > 0) | 
|  | { | 
|  | int idx = getTLVisibleIdxByVals (exp, view_mode, entity_prop_id, | 
|  | packets, aux, entity_prop_val, tstamp, | 
|  | DataView::REL_GTEQ); | 
|  | if (idx != -1) | 
|  | return idx; | 
|  | // couldn't find to right, fall through to generic | 
|  | } | 
|  | // search left and right of timestamp | 
|  | long idx1, idx2; | 
|  | idx1 = getTLVisibleIdxByVals (exp, view_mode, entity_prop_id, | 
|  | packets, aux, entity_prop_val, tstamp, | 
|  | DataView::REL_LT); | 
|  | idx2 = getTLVisibleIdxByVals (exp, view_mode, entity_prop_id, | 
|  | packets, aux, entity_prop_val, tstamp, | 
|  | DataView::REL_GTEQ); | 
|  | if (idx1 == -1) | 
|  | return idx2; | 
|  | else if (idx2 == -1) | 
|  | return idx1; | 
|  |  | 
|  | // both valid, so need to compare to see which is closer | 
|  | long long t1 = packets->getLongValue (PROP_TSTAMP, idx1); | 
|  | long long t2 = packets->getLongValue (PROP_TSTAMP, idx2); | 
|  | long long t2dur = packets->getLongValue (PROP_EVT_TIME, idx2); | 
|  | long long delta1 = tstamp - t1; // should always be positive | 
|  | long long delta2 = (t2 - t2dur) - tstamp; // if negative, overlaps idx1 | 
|  | if (delta1 > delta2) | 
|  | return idx2; | 
|  | else | 
|  | return idx1; | 
|  | } | 
|  |  | 
|  | enum Aggr_type | 
|  | { | 
|  | AGGR_NONE, | 
|  | AGGR_FAIR, | 
|  | AGGR_MAX, | 
|  | AGGR_MIN, | 
|  | AGGR_CNT, | 
|  | AGGR_SUM, | 
|  | AGGR_AVG | 
|  | }; | 
|  |  | 
|  | static Aggr_type | 
|  | getAggrFunc (char *aname) | 
|  | { | 
|  | Aggr_type agrfn = AGGR_NONE; | 
|  | if (aname == NULL) | 
|  | return agrfn; | 
|  | if (strcmp (aname, NTXT ("FAIR")) == 0) | 
|  | agrfn = AGGR_FAIR; | 
|  | else if (strcmp (aname, NTXT ("MAX")) == 0) | 
|  | agrfn = AGGR_MAX; | 
|  | else if (strcmp (aname, NTXT ("MIN")) == 0) | 
|  | agrfn = AGGR_MIN; | 
|  | else if (strcmp (aname, NTXT ("CNT")) == 0) | 
|  | agrfn = AGGR_CNT; | 
|  | else if (strcmp (aname, NTXT ("SUM")) == 0) | 
|  | agrfn = AGGR_SUM; | 
|  | else if (strcmp (aname, NTXT ("AVG")) == 0) | 
|  | agrfn = AGGR_AVG; | 
|  | return agrfn; | 
|  | } | 
|  |  | 
|  | static long long | 
|  | computeAggrVal (DefaultMap<long long, long long> *fval_map, Aggr_type agrfn) | 
|  | { | 
|  | long long aval = 0; | 
|  | long cnt = 0; | 
|  | Vector<long long> *fvals = fval_map->values (); | 
|  | long nvals = fvals->size (); | 
|  | for (int i = 0; i < nvals; ++i) | 
|  | { | 
|  | long long val = fvals->fetch (i); | 
|  | switch (agrfn) | 
|  | { | 
|  | case AGGR_FAIR: | 
|  | aval = val; | 
|  | break; | 
|  | case AGGR_MAX: | 
|  | if (aval < val || cnt == 0) | 
|  | aval = val; | 
|  | break; | 
|  | case AGGR_MIN: | 
|  | if (aval > val || cnt == 0) | 
|  | aval = val; | 
|  | break; | 
|  | case AGGR_CNT: | 
|  | aval = cnt + 1; | 
|  | break; | 
|  | case AGGR_SUM: | 
|  | case AGGR_AVG: | 
|  | aval += val; | 
|  | break; | 
|  | case AGGR_NONE: | 
|  | break; | 
|  | } | 
|  | if (agrfn == AGGR_FAIR) | 
|  | break; | 
|  | cnt += 1; | 
|  | } | 
|  |  | 
|  | // Finalize aggregation | 
|  | if (agrfn == AGGR_AVG) | 
|  | if (cnt > 0) | 
|  | aval = (aval + cnt / 2) / cnt; | 
|  | delete fvals; | 
|  | return aval; | 
|  | } | 
|  |  | 
|  | Vector<long long> * | 
|  | dbeGetAggregatedValue (int data_id, // data table id | 
|  | char *lfilter, // local filter | 
|  | char *fexpr, // function expression | 
|  | char *pname_ts, // property name for timestamp | 
|  | hrtime_t start_ts, // start of the first time interval | 
|  | hrtime_t delta, // time interval length | 
|  | int num, // number of time intervals | 
|  | char *pname_key, // property name for aggregation key | 
|  | char *aggr_func) // aggregation function | 
|  | { | 
|  | Vector<long long> *res = new Vector<long long>; | 
|  | Experiment *exp = dbeSession->get_exp (0); | 
|  | if (exp == NULL) | 
|  | return res; | 
|  | hrtime_t end_ts = start_ts + delta * num; | 
|  | if (end_ts < start_ts)    // check overflow | 
|  | end_ts = MAX_TIME; | 
|  |  | 
|  | if (exp->get_status () == Experiment::INCOMPLETE | 
|  | && exp->getLastEvent () < end_ts) | 
|  | exp->update (); | 
|  |  | 
|  | DataDescriptor *dataDscr = exp->get_raw_events (data_id); | 
|  | if (dataDscr == NULL) | 
|  | return res; | 
|  |  | 
|  | // Process timestamp argument | 
|  | int prop_ts = dbeSession->getPropIdByName (pname_ts); | 
|  | if (prop_ts == PROP_NONE) | 
|  | return res; | 
|  | assert (prop_ts == -1); | 
|  |  | 
|  | // Parse all expressions | 
|  | Expression *flt_expr = NULL; | 
|  | if (lfilter != NULL) | 
|  | flt_expr = dbeSession->ql_parse (lfilter); | 
|  | Expression *func_expr = NULL; | 
|  | if (fexpr != NULL) | 
|  | func_expr = dbeSession->ql_parse (fexpr); | 
|  | if (func_expr == NULL)   // Not specified or malformed | 
|  | return res; | 
|  |  | 
|  | // Process aggregation key argument | 
|  | int prop_key = PROP_NONE; | 
|  | Data *data_key = NULL; | 
|  | if (pname_key != NULL) | 
|  | { | 
|  | prop_key = dbeSession->getPropIdByName (pname_key); | 
|  | data_key = dataDscr->getData (prop_key); | 
|  | if (data_key == NULL)   // Specified but not found | 
|  | return res; | 
|  | } | 
|  |  | 
|  | // Process aggregation function argument | 
|  | Aggr_type agrfn = AGGR_FAIR; | 
|  | if (aggr_func != NULL) | 
|  | { | 
|  | agrfn = getAggrFunc (aggr_func); | 
|  | if (agrfn == AGGR_NONE) // Specified but not recognized | 
|  | return res; | 
|  | } | 
|  | DefaultMap<long long, long long> * | 
|  | fval_map = new DefaultMap<long long, long long>; // key_val -> func_val | 
|  | Vector<long long> *key_set = NULL; | 
|  | assert (key_set != NULL); | 
|  | if (key_set == NULL) | 
|  | { | 
|  | key_set = new Vector<long long>; | 
|  | key_set->append (0L); | 
|  | } | 
|  | DefaultMap<long long, int> *key_seen = new DefaultMap<long long, int>; | 
|  | long idx_prev = -1; | 
|  | for (int tidx = 0; tidx < num; ++tidx) | 
|  | { | 
|  | long idx_cur = -1; | 
|  | assert (idx_cur != -1); | 
|  | int left = key_set->size (); | 
|  | key_seen->clear (); | 
|  | for (long idx = idx_cur; idx > idx_prev; --idx) | 
|  | { | 
|  | long id = 0; | 
|  | assert (id != 0); | 
|  |  | 
|  | // Pre-create expression context | 
|  | Expression::Context ctx (dbeSession->getView (0), exp, NULL, id); | 
|  | // First use the filter | 
|  | if (flt_expr != NULL) | 
|  | if (flt_expr->eval (&ctx) == 0) | 
|  | continue; | 
|  |  | 
|  | // Calculate the key | 
|  | // keys are limited to integral values | 
|  | long long key = 0; | 
|  | if (data_key != NULL) | 
|  | key = data_key->fetchLong (id); | 
|  |  | 
|  | // Check if already seen | 
|  | if (key_seen->get (key) == 1) | 
|  | continue; | 
|  | key_seen->put (key, 1); | 
|  | left -= 1; | 
|  |  | 
|  | // Calculate function value | 
|  | // function values are limited to integral values | 
|  | long long fval = func_expr->eval (&ctx); | 
|  | fval_map->put (key, fval); | 
|  | if (left == 0) | 
|  | break; | 
|  | } | 
|  | idx_prev = idx_cur; | 
|  | long long aval = computeAggrVal (fval_map, agrfn); | 
|  | res->store (tidx, aval); | 
|  | } | 
|  | delete key_seen; | 
|  | delete fval_map; | 
|  | delete flt_expr; | 
|  | delete func_expr; | 
|  | return res; | 
|  | } | 
|  |  | 
|  | Vector<char*> * | 
|  | dbeGetLineInfo (Obj pc) | 
|  | { | 
|  | DbeInstr *instr = (DbeInstr*) pc; | 
|  | if (instr == NULL || instr->get_type () != Histable::INSTR) | 
|  | return NULL; | 
|  | DbeLine *dbeline = (DbeLine*) instr->convertto (Histable::LINE); | 
|  | const char *fname = dbeline ? dbeline->sourceFile->get_name () : NTXT (""); | 
|  | char lineno[16]; | 
|  | *lineno = '\0'; | 
|  | if (dbeline != NULL) | 
|  | snprintf (lineno, sizeof (lineno), NTXT ("%d"), dbeline->lineno); | 
|  | Vector<char*> *res = new Vector<char*>(2); | 
|  | res->store (0, xstrdup (fname)); | 
|  | res->store (1, xstrdup (lineno)); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | int | 
|  | dbeSetAlias (char *name, char *uname, char *expr) | 
|  | { | 
|  | char *res = dbeSession->indxobj_define (name, uname, expr, NULL, NULL); | 
|  | return res == NULL ? 0 : 1; | 
|  | } | 
|  |  | 
|  | Vector<char*> * | 
|  | dbeGetAlias (char *name) | 
|  | { | 
|  | Vector<char*> *res = new Vector<char*>; | 
|  | int idx = dbeSession->findIndexSpaceByName (name); | 
|  | if (idx >= 0) | 
|  | { | 
|  | char *str = dbeSession->getIndexSpaceDescr (idx); | 
|  | res->append (dbe_strdup (str)); | 
|  | str = dbeSession->getIndexSpaceExprStr (idx); | 
|  | res->append (dbe_strdup (str)); | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | static int | 
|  | key_cmp (const void *p1, const void *p2) | 
|  | { | 
|  | long long ll1 = *(long long*) p1; | 
|  | long long ll2 = *(long long*) p2; | 
|  | return ll1 < ll2 ? -1 : ll1 > ll2 ? 1 : 0; | 
|  | } | 
|  |  | 
|  | Vector<Vector<long long>*> * | 
|  | dbeGetXYPlotData ( | 
|  | int data_id, // data table id | 
|  | char *lfilter, // local filter expression | 
|  | char *arg, // name for the argument | 
|  | char *func1, // expression for the first axis (x) | 
|  | char *aggr1, // aggregation function for func1: "SUM","CNT",... | 
|  | char *func2, // expression for the second axis (y) | 
|  | char *aggr2, // aggregation function for func2 | 
|  | char *func3, // expression for the third axis (color) | 
|  | char *aggr3) // aggregation function for func3 | 
|  | { | 
|  | Vector<Vector<long long>*> *res = new Vector<Vector<long long>*>; | 
|  | Experiment *exp = dbeSession->get_exp (0); | 
|  | if (exp == NULL) | 
|  | return res; | 
|  | if (exp->get_status () == Experiment::INCOMPLETE) | 
|  | exp->update (); | 
|  |  | 
|  | DataDescriptor *dataDscr = exp->get_raw_events (data_id); | 
|  | if (dataDscr == NULL) | 
|  | return res; | 
|  |  | 
|  | // Parse all expressions | 
|  | Vector<Expression*> *funcs = new Vector<Expression*>; | 
|  | Vector<Aggr_type> *aggrs = new Vector<Aggr_type>; | 
|  | Vector<DefaultMap<long long, long long>*> *fval_maps = | 
|  | new Vector<DefaultMap<long long, long long>*>; | 
|  | Vector<DefaultMap<long long, long>*> *cnt_maps = | 
|  | new Vector<DefaultMap<long long, long>*>; | 
|  | if (func1 != NULL) | 
|  | { | 
|  | Expression *expr = dbeSession->ql_parse (func1); | 
|  | funcs->append (expr); | 
|  | aggrs->append (getAggrFunc (aggr1)); | 
|  | fval_maps->append (new DefaultMap<long long, long long>); | 
|  | cnt_maps->append (new DefaultMap<long long, long>); | 
|  | res->append (new Vector<long long>); | 
|  | if (func2 != NULL) | 
|  | { | 
|  | expr = dbeSession->ql_parse (func2); | 
|  | funcs->append (expr); | 
|  | aggrs->append (getAggrFunc (aggr2)); | 
|  | fval_maps->append (new DefaultMap<long long, long long>); | 
|  | cnt_maps->append (new DefaultMap<long long, long>); | 
|  | res->append (new Vector<long long>); | 
|  | if (func3 != NULL) | 
|  | { | 
|  | expr = dbeSession->ql_parse (func3); | 
|  | funcs->append (expr); | 
|  | aggrs->append (getAggrFunc (aggr3)); | 
|  | fval_maps->append (new DefaultMap<long long, long long>); | 
|  | cnt_maps->append (new DefaultMap<long long, long>); | 
|  | res->append (new Vector<long long>); | 
|  | } | 
|  | } | 
|  | } | 
|  | if (funcs->size () == 0) | 
|  | { | 
|  | funcs->destroy (); | 
|  | delete funcs; | 
|  | fval_maps->destroy (); | 
|  | delete fval_maps; | 
|  | cnt_maps->destroy (); | 
|  | delete cnt_maps; | 
|  | delete aggrs; | 
|  | return res; | 
|  | } | 
|  | Expression *arg_expr = NULL; | 
|  | if (arg != NULL) | 
|  | arg_expr = dbeSession->ql_parse (arg); | 
|  | if (arg_expr == NULL) | 
|  | { | 
|  | funcs->destroy (); | 
|  | delete funcs; | 
|  | fval_maps->destroy (); | 
|  | delete fval_maps; | 
|  | cnt_maps->destroy (); | 
|  | delete cnt_maps; | 
|  | delete aggrs; | 
|  | return res; | 
|  | } | 
|  | Expression *flt_expr = NULL; | 
|  | if (lfilter != NULL) | 
|  | flt_expr = dbeSession->ql_parse (lfilter); | 
|  | Vector<long long> *kidx_map = new Vector<long long>(); // key_idx -> key_val | 
|  | for (long i = 0; i < dataDscr->getSize (); i++) | 
|  | { | 
|  | Expression::Context ctx (dbeSession->getView (0), exp, NULL, i); | 
|  | // First use the filter | 
|  | if (flt_expr != NULL) | 
|  | if (flt_expr->eval (&ctx) == 0) | 
|  | continue; | 
|  |  | 
|  | // Compute the argument | 
|  | long long key = arg_expr->eval (&ctx); | 
|  | if (kidx_map->find (key) == -1) | 
|  | kidx_map->append (key); | 
|  | for (long j = 0; j < funcs->size (); ++j) | 
|  | { | 
|  | Expression *func = funcs->fetch (j); | 
|  | Aggr_type aggr = aggrs->fetch (j); | 
|  | DefaultMap<long long, long long> *fval_map = fval_maps->fetch (j); | 
|  | DefaultMap<long long, long> *cnt_map = cnt_maps->fetch (j); | 
|  | long long fval = func->eval (&ctx); | 
|  | long long aval = fval_map->get (key); | 
|  | long cnt = cnt_map->get (key); | 
|  | switch (aggr) | 
|  | { | 
|  | case AGGR_NONE: | 
|  | case AGGR_FAIR: | 
|  | if (cnt == 0) | 
|  | aval = fval; | 
|  | break; | 
|  | case AGGR_MAX: | 
|  | if (aval < fval || cnt == 0) | 
|  | aval = fval; | 
|  | break; | 
|  | case AGGR_MIN: | 
|  | if (aval > fval || cnt == 0) | 
|  | aval = fval; | 
|  | break; | 
|  | case AGGR_CNT: | 
|  | aval = cnt + 1; | 
|  | break; | 
|  | case AGGR_SUM: | 
|  | case AGGR_AVG: | 
|  | aval += fval; | 
|  | break; | 
|  | } | 
|  | cnt_map->put (key, cnt + 1); | 
|  | fval_map->put (key, aval); | 
|  | } | 
|  | } | 
|  | kidx_map->sort (key_cmp); | 
|  |  | 
|  | // Finalize aggregation, prepare result | 
|  | for (long j = 0; j < funcs->size (); ++j) | 
|  | { | 
|  | Aggr_type aggr = aggrs->fetch (j); | 
|  | Vector<long long> *resj = res->fetch (j); | 
|  | DefaultMap<long long, long long> * | 
|  | fval_map = fval_maps->fetch (j); | 
|  | DefaultMap<long long, long> * | 
|  | cnt_map = cnt_maps->fetch (j); | 
|  | for (int kidx = 0; kidx < kidx_map->size (); ++kidx) | 
|  | { | 
|  | long long key = kidx_map->fetch (kidx); | 
|  | long long aval = fval_map->get (key); | 
|  | if (aggr == AGGR_AVG) | 
|  | { | 
|  | long cnt = cnt_map->get (key); | 
|  | if (cnt > 0) | 
|  | aval = (aval + cnt / 2) / cnt; | 
|  | } | 
|  | resj->append (aval); | 
|  | } | 
|  | } | 
|  | delete flt_expr; | 
|  | funcs->destroy (); | 
|  | delete funcs; | 
|  | delete aggrs; | 
|  | delete arg_expr; | 
|  | delete kidx_map; | 
|  | fval_maps->destroy (); | 
|  | delete fval_maps; | 
|  | cnt_maps->destroy (); | 
|  | delete cnt_maps; | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* ********************************************************************* */ | 
|  | /*  Routines for use by Collector GUI */ | 
|  | /** | 
|  | * Returns signal value for provided name. Example of name: "SIGUSR1" | 
|  | * @param signal | 
|  | * @return value | 
|  | */ | 
|  | int | 
|  | dbeGetSignalValue (char *signal) | 
|  | { | 
|  | int ret = -1; | 
|  | if (signal == NULL) | 
|  | return ret; | 
|  | if (strcmp (signal, "SIGUSR1") == 0) | 
|  | return (SIGUSR1); | 
|  | if (strcmp (signal, "SIGUSR2") == 0) | 
|  | return (SIGUSR2); | 
|  | if (strcmp (signal, "SIGPROF") == 0) | 
|  | return (SIGPROF); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeSendSignal (pid_t p, int signum) | 
|  | { | 
|  | int ret = kill (p, signum); | 
|  | if (p == 0 || p == -1) | 
|  | return (dbe_sprintf (GTXT ("kill of process %d not supported\n"), p)); | 
|  | if (ret == 0) | 
|  | return NULL; | 
|  | char *msg = dbe_sprintf (GTXT ("kill(%d, %d) failed: %s\n"), p, signum, | 
|  | strerror (errno)); | 
|  | return msg; | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeGetCollectorControlValue (char *control) | 
|  | { | 
|  | if (control == NULL) | 
|  | return NULL; | 
|  | if (col_ctr == NULL) | 
|  | col_ctr = new Coll_Ctrl (1); | 
|  | char *msg = col_ctr->get (control); | 
|  | return msg; | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeSetCollectorControlValue (char *control, char * value) | 
|  | { | 
|  | if (control == NULL) | 
|  | return NULL; | 
|  | if (col_ctr == NULL) | 
|  | col_ctr = new Coll_Ctrl (1); | 
|  | char *msg = col_ctr->set (control, value); | 
|  | return msg; | 
|  | } | 
|  |  | 
|  | char * | 
|  | dbeUnsetCollectorControlValue (char *control) | 
|  | { | 
|  | if (control == NULL) | 
|  | return NULL; | 
|  | if (col_ctr == NULL) | 
|  | col_ctr = new Coll_Ctrl (1); | 
|  | char *msg = col_ctr->unset (control); | 
|  | return msg; | 
|  | } | 
|  |  | 
|  | void | 
|  | dbeSetLocation (const char *fname, const char *location) | 
|  | { | 
|  | Vector<SourceFile*> *sources = dbeSession->get_sources (); | 
|  | for (long i = 0, sz = sources ? sources->size () : 0; i < sz; i++) | 
|  | { | 
|  | SourceFile *src = sources->get (i); | 
|  | DbeFile *df = src->dbeFile; | 
|  | if (df && (strcmp (fname, df->get_name ()) == 0)) | 
|  | { | 
|  | df->find_file ((char *) location); | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void | 
|  | dbeSetLocations (Vector<const char *> *fnames, Vector<const char *> *locations) | 
|  | { | 
|  | if (fnames == NULL || locations == NULL | 
|  | || fnames->size () != locations->size ()) | 
|  | return; | 
|  | for (long i = 0, sz = fnames->size (); i < sz; i++) | 
|  | dbeSetLocation (fnames->get (i), locations->get (i)); | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeResolvedWith_setpath (const char *path) | 
|  | { | 
|  | Vector<char*> *names = new Vector<char*>(); | 
|  | Vector<char*> *pathes = new Vector<char*>(); | 
|  | Vector<long long> *ids = new Vector<long long>(); | 
|  | Vector<SourceFile*> *sources = dbeSession->get_sources (); | 
|  | for (long i = 0, sz = sources ? sources->size () : 0; i < sz; i++) | 
|  | { | 
|  | SourceFile *src = sources->get (i); | 
|  | DbeFile *df = src->dbeFile; | 
|  | if (df == NULL || (df->filetype & DbeFile::F_FICTION) != 0) | 
|  | continue; | 
|  | char *fnm = df->get_name (); | 
|  | if ((df->filetype & (DbeFile::F_JAVACLASS | DbeFile::F_JAVA_SOURCE)) != 0) | 
|  | { | 
|  | char *jnm = dbe_sprintf (NTXT ("%s/%s"), path, fnm); | 
|  | if (df->check_access (jnm) == DbeFile::F_FILE) | 
|  | { | 
|  | names->append (dbe_strdup (fnm)); | 
|  | pathes->append (jnm); | 
|  | ids->append (src->id); | 
|  | continue; | 
|  | } | 
|  | free (jnm); | 
|  | } | 
|  | char *nm = dbe_sprintf (NTXT ("%s/%s"), path, get_basename (fnm)); | 
|  | if (df->check_access (nm) == DbeFile::F_FILE) | 
|  | { | 
|  | names->append (dbe_strdup (fnm)); | 
|  | pathes->append (nm); | 
|  | ids->append (src->id); | 
|  | continue; | 
|  | } | 
|  | free (nm); | 
|  | } | 
|  | if (names->size () != 0) | 
|  | { | 
|  | Vector<void*> *data = new Vector<void*>(3); | 
|  | data->append (names); | 
|  | data->append (pathes); | 
|  | data->append (ids); | 
|  | return data; | 
|  | } | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | Vector<void*> * | 
|  | dbeResolvedWith_pathmap (const char *old_prefix, const char *new_prefix) | 
|  | { | 
|  | size_t len = strlen (old_prefix); | 
|  | Vector<char*> *names = new Vector<char*>(); | 
|  | Vector<char*> *pathes = new Vector<char*>(); | 
|  | Vector<long long> *ids = new Vector<long long>(); | 
|  | Vector<SourceFile*> *sources = dbeSession->get_sources (); | 
|  | for (long i = 0, sz = sources ? sources->size () : 0; i < sz; i++) | 
|  | { | 
|  | SourceFile *src = sources->get (i); | 
|  | DbeFile *df = src->dbeFile; | 
|  | if (df == NULL || (df->filetype & DbeFile::F_FICTION) != 0) | 
|  | continue; | 
|  | char *fnm = df->get_name (); | 
|  | if (strncmp (old_prefix, fnm, len) == 0 | 
|  | && (fnm[len] == '/' || fnm[len] == '\0')) | 
|  | { | 
|  | char *nm = dbe_sprintf (NTXT ("%s/%s"), new_prefix, fnm + len); | 
|  | if (df->check_access (nm) == DbeFile::F_FILE) | 
|  | { | 
|  | names->append (dbe_strdup (fnm)); | 
|  | pathes->append (nm); | 
|  | ids->append (src->id); | 
|  | continue; | 
|  | } | 
|  | if ((df->filetype & DbeFile::F_JAVA_SOURCE) != 0) | 
|  | { | 
|  | free (nm); | 
|  | nm = dbe_sprintf (NTXT ("%s/%s"), new_prefix, fnm); | 
|  | if (df->check_access (nm) == DbeFile::F_FILE) | 
|  | { | 
|  | names->append (dbe_strdup (fnm)); | 
|  | pathes->append (nm); | 
|  | ids->append (src->id); | 
|  | continue; | 
|  | } | 
|  | } | 
|  | free (nm); | 
|  | } | 
|  | } | 
|  | if (names->size () != 0) | 
|  | { | 
|  | Vector<void*> *data = new Vector<void*>(3); | 
|  | data->append (names); | 
|  | data->append (pathes); | 
|  | data->append (ids); | 
|  | return data; | 
|  | } | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | void | 
|  | dbe_archive (Vector<long long> *ids, Vector<const char *> *locations) | 
|  | { | 
|  | if (ids == NULL || locations == NULL || ids->size () != locations->size ()) | 
|  | return; | 
|  | Experiment *exp = dbeSession->get_exp (0); | 
|  | if (exp == NULL) | 
|  | return; | 
|  | Vector<SourceFile*> *sources = dbeSession->get_sources (); | 
|  | for (long i1 = 0, sz1 = ids->size (); i1 < sz1; i1++) | 
|  | { | 
|  | long long id = ids->get (i1); | 
|  | for (long i = 0, sz = sources ? sources->size () : 0; i < sz; i++) | 
|  | { | 
|  | SourceFile *src = sources->get (i); | 
|  | if (src->id == id) | 
|  | { | 
|  | DbeFile *df = src->dbeFile; | 
|  | if (df) | 
|  | { | 
|  | char *fnm = df->find_file ((char *) locations->get (i1)); | 
|  | if (fnm) | 
|  | { | 
|  | char *nm = df->get_name (); | 
|  | char *anm = exp->getNameInArchive (nm, false); | 
|  | exp->copy_file (fnm, anm, true); | 
|  | free (anm); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* ************************************************************************ */ | 
|  |  | 
|  | /* Routines to check connection between Remote Analyzer Client and er_print */ | 
|  | char * | 
|  | dbeCheckConnection (char *str) | 
|  | { | 
|  | return dbe_strdup (str); | 
|  | } |