blob: 09b7f94eaa8e3fbf10a8fd38764bc23e13df76a4 [file] [log] [blame]
/* Copyright (C) 2021-2024 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 *) malloc (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 ();