| /* Copyright (C) 2021 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 <ctype.h> | |
| #include <stdio.h> | |
| #include <dirent.h> | |
| #include <unistd.h> | |
| #include <sys/types.h> | |
| #include <errno.h> | |
| #include <sys/param.h> | |
| #include "util.h" | |
| #include "Application.h" | |
| #include "Experiment.h" | |
| #include "ExpGroup.h" | |
| #include "Expression.h" | |
| #include "DataObject.h" | |
| #include "Elf.h" | |
| #include "Function.h" | |
| #include "DbeSession.h" | |
| #include "LoadObject.h" | |
| #include "DbeSyncMap.h" | |
| #include "DbeThread.h" | |
| #include "ClassFile.h" | |
| #include "IndexObject.h" | |
| #include "PathTree.h" | |
| #include "Print.h" | |
| #include "QLParser.tab.hh" | |
| #include "DbeView.h" | |
| #include "MemorySpace.h" | |
| #include "Module.h" | |
| #include "SourceFile.h" | |
| #include "StringBuilder.h" | |
| #include "BaseMetric.h" | |
| #include "BaseMetricTreeNode.h" | |
| #include "Command.h" | |
| #include "UserLabel.h" | |
| #include "StringMap.h" | |
| #include "DbeFile.h" | |
| #include "DbeJarFile.h" | |
| #include "IOActivity.h" | |
| #include "HeapActivity.h" | |
| // This is a universal List structure to organize objects | |
| // of various types, even if different. | |
| struct List | |
| { | |
| List *next; | |
| void *val; | |
| }; | |
| struct Countable | |
| { | |
| Countable (void *_item) | |
| { | |
| item = _item; | |
| ref_count = 0; | |
| } | |
| void *item; | |
| int ref_count; | |
| }; | |
| Platform_t DbeSession::platform = | |
| #if ARCH(SPARC) | |
| Sparc; | |
| #elif ARCH(Aarch64) | |
| Aarch64; | |
| #else // ARCH(Intel) | |
| Intel; | |
| #endif | |
| // This constant determines the size of the data object name hash table. | |
| static const int HTableSize = 8192; | |
| static int DEFAULT_TINY_THRESHOLD = -1; | |
| unsigned int mpmt_debug_opt = 0; | |
| DbeSession *dbeSession = NULL; | |
| DbeSession::DbeSession (Settings *_settings, bool _ipc_mode, bool _rdt_mode) | |
| { | |
| dbeSession = this; | |
| ipc_mode = _ipc_mode; | |
| rdt_mode = _rdt_mode; | |
| settings = new Settings (_settings); | |
| views = new Vector<DbeView*>; | |
| exps = new Vector<Experiment*>; | |
| lobjs = new Vector<LoadObject*>; | |
| objs = new Vector<Histable*>; | |
| dobjs = new Vector<DataObject*>; | |
| metrics = new Vector<Countable*>; | |
| reg_metrics = new Vector<BaseMetric*>; | |
| hwcentries = NULL; | |
| reg_metrics_tree = NULL; // BaseMetric() requires DbeSession::ql_parse | |
| idxobjs = new Vector<HashMap<uint64_t, Histable*>*>; | |
| tmp_files = new Vector<char*>; | |
| search_path = new Vector<char*>; | |
| classpath = new Vector<char*>; | |
| classpath_df = NULL; | |
| expGroups = new Vector<ExpGroup*>; | |
| sourcesMap = new HashMap<char*, SourceFile*>; | |
| sources = new Vector<SourceFile*>; | |
| comp_lobjs = new HashMap<char*, LoadObject*>; | |
| comp_dbelines = new HashMap<char*, DbeLine*>; | |
| comp_sources = new HashMap<char*, SourceFile*>; | |
| loadObjMap = new DbeSyncMap<LoadObject>; | |
| f_special = new Vector<Function*>(LastSpecialFunction); | |
| omp_functions = new Vector<Function*>(OMP_LAST_STATE); | |
| interactive = false; | |
| lib_visibility_used = false; | |
| // Define all known property names | |
| propNames = new Vector<PropDescr*>; | |
| propNames_name_store (PROP_NONE, NTXT ("")); | |
| propNames_name_store (PROP_ATSTAMP, NTXT ("ATSTAMP")); | |
| propNames_name_store (PROP_ETSTAMP, NTXT ("ETSTAMP")); | |
| propNames_name_store (PROP_TSTAMP, NTXT ("TSTAMP")); | |
| propNames_name_store (PROP_THRID, NTXT ("THRID")); | |
| propNames_name_store (PROP_LWPID, NTXT ("LWPID")); | |
| propNames_name_store (PROP_CPUID, NTXT ("CPUID")); | |
| propNames_name_store (PROP_FRINFO, NTXT ("FRINFO")); | |
| propNames_name_store (PROP_EVT_TIME, NTXT ("EVT_TIME")); | |
| // Samples | |
| propNames_name_store (PROP_SMPLOBJ, NTXT ("SMPLOBJ")); | |
| propNames_name_store (PROP_SAMPLE, NTXT ("SAMPLE")); | |
| // GCEvents | |
| propNames_name_store (PROP_GCEVENTOBJ, NTXT ("GCEVENTOBJ")); | |
| propNames_name_store (PROP_GCEVENT, NTXT ("GCEVENT")); | |
| // Metadata used by some packet types | |
| propNames_name_store (PROP_VOIDP_OBJ, NTXT ("VOIDP_OBJ"), | |
| NULL, TYPE_UINT64, DDFLAG_NOSHOW); | |
| // Clock profiling properties | |
| propNames_name_store (PROP_UCPU, NTXT ("UCPU")); | |
| propNames_name_store (PROP_SCPU, NTXT ("SCPU")); | |
| propNames_name_store (PROP_TRAP, NTXT ("TRAP")); | |
| propNames_name_store (PROP_TFLT, NTXT ("TFLT")); | |
| propNames_name_store (PROP_DFLT, NTXT ("DFLT")); | |
| propNames_name_store (PROP_KFLT, NTXT ("KFLT")); | |
| propNames_name_store (PROP_ULCK, NTXT ("ULCK")); | |
| propNames_name_store (PROP_TSLP, NTXT ("TSLP")); | |
| propNames_name_store (PROP_WCPU, NTXT ("WCPU")); | |
| propNames_name_store (PROP_TSTP, NTXT ("TSTP")); | |
| propNames_name_store (PROP_MSTATE, NTXT ("MSTATE")); | |
| propNames_name_store (PROP_NTICK, NTXT ("NTICK")); | |
| propNames_name_store (PROP_OMPSTATE, NTXT ("OMPSTATE")); | |
| // Synchronization tracing properties | |
| propNames_name_store (PROP_SRQST, NTXT ("SRQST")); | |
| propNames_name_store (PROP_SOBJ, NTXT ("SOBJ")); | |
| // Hardware counter profiling properties | |
| propNames_name_store (PROP_HWCTAG, NTXT ("HWCTAG")); | |
| propNames_name_store (PROP_HWCINT, NTXT ("HWCINT")); | |
| propNames_name_store (PROP_VADDR, NTXT ("VADDR")); | |
| propNames_name_store (PROP_PADDR, NTXT ("PADDR")); | |
| propNames_name_store (PROP_VIRTPC, NTXT ("VIRTPC")); | |
| propNames_name_store (PROP_PHYSPC, NTXT ("PHYSPC")); | |
| propNames_name_store (PROP_LWP_LGRP_HOME, NTXT ("LWP_LGRP_HOME")); | |
| propNames_name_store (PROP_PS_LGRP_HOME, NTXT ("PS_LGRP_HOME")); | |
| propNames_name_store (PROP_EA_PAGESIZE, NTXT ("EA_PAGESIZE")); | |
| propNames_name_store (PROP_EA_LGRP, NTXT ("EA_LGRP")); | |
| propNames_name_store (PROP_PC_PAGESIZE, NTXT ("PC_PAGESIZE")); | |
| propNames_name_store (PROP_PC_LGRP, NTXT ("PC_LGRP")); | |
| propNames_name_store (PROP_HWCDOBJ, NTXT ("HWCDOBJ")); | |
| propNames_name_store (PROP_MEM_LAT, NTXT ("MEM_LAT")); | |
| propNames_name_store (PROP_MEM_SRC, NTXT ("MEM_SRC")); | |
| // Heap tracing properties | |
| propNames_name_store (PROP_HTYPE, NTXT ("HTYPE")); | |
| propNames_name_store (PROP_HSIZE, NTXT ("HSIZE")); | |
| propNames_name_store (PROP_HVADDR, NTXT ("HVADDR")); | |
| propNames_name_store (PROP_HOVADDR, NTXT ("HOVADDR")); | |
| propNames_name_store (PROP_HLEAKED, NTXT ("HLEAKED"), | |
| GTXT ("Leaked bytes"), TYPE_UINT64, 0); | |
| propNames_name_store (PROP_HMEM_USAGE, NTXT ("HMEM_USAGE")); | |
| propNames_name_store (PROP_HFREED, NTXT ("HFREED"), | |
| GTXT ("Freed bytes"), TYPE_UINT64, 0); | |
| propNames_name_store (PROP_HCUR_ALLOCS, NTXT ("HCUR_ALLOCS"), | |
| GTXT ("Current allocations"), TYPE_INT64, 0); | |
| propNames_name_store (PROP_HCUR_NET_ALLOC, NTXT ("HCUR_NET_ALLOC"), | |
| NULL, TYPE_INT64, DDFLAG_NOSHOW); | |
| propNames_name_store (PROP_HCUR_LEAKS, NTXT ("HCUR_LEAKS"), | |
| GTXT ("Current leaks"), TYPE_UINT64, 0); | |
| propNames_name_store (PROP_DDSCR_LNK, NTXT ("DDSCR_LNK"), | |
| NULL, TYPE_UINT64, DDFLAG_NOSHOW); | |
| // IO tracing properties | |
| propNames_name_store (PROP_IOTYPE, NTXT ("IOTYPE")); | |
| propNames_name_store (PROP_IOFD, NTXT ("IOFD")); | |
| propNames_name_store (PROP_IONBYTE, NTXT ("IONBYTE")); | |
| propNames_name_store (PROP_IORQST, NTXT ("IORQST")); | |
| propNames_name_store (PROP_IOOFD, NTXT ("IOOFD")); | |
| propNames_name_store (PROP_IOFNAME, NTXT ("IOFNAME")); | |
| propNames_name_store (PROP_IOVFD, NTXT ("IOVFD")); | |
| propNames_name_store (PROP_IOFSTYPE, NTXT ("IOFSTYPE")); | |
| // omptrace raw properties | |
| propNames_name_store (PROP_CPRID, NTXT ("CPRID")); | |
| propNames_name_store (PROP_PPRID, NTXT ("PPRID")); | |
| propNames_name_store (PROP_TSKID, NTXT ("TSKID")); | |
| propNames_name_store (PROP_PTSKID, NTXT ("PTSKID")); | |
| propNames_name_store (PROP_PRPC, NTXT ("PRPC")); | |
| // Data race detection properties | |
| propNames_name_store (PROP_RID, NTXT ("RID")); | |
| propNames_name_store (PROP_RTYPE, NTXT ("RTYPE")); | |
| propNames_name_store (PROP_LEAFPC, NTXT ("LEAFPC")); | |
| propNames_name_store (PROP_RVADDR, NTXT ("RVADDR")); | |
| propNames_name_store (PROP_RCNT, NTXT ("RCNT")); | |
| // Deadlock detection properties | |
| propNames_name_store (PROP_DID, NTXT ("DID")); | |
| propNames_name_store (PROP_DLTYPE, NTXT ("DLTYPE")); | |
| propNames_name_store (PROP_DTYPE, NTXT ("DTYPE")); | |
| propNames_name_store (PROP_DVADDR, NTXT ("DVADDR")); | |
| // Synthetic properties (queries only) | |
| propNames_name_store (PROP_STACK, NTXT ("STACK")); | |
| propNames_name_store (PROP_MSTACK, NTXT ("MSTACK")); | |
| propNames_name_store (PROP_USTACK, NTXT ("USTACK")); | |
| propNames_name_store (PROP_XSTACK, NTXT ("XSTACK")); | |
| propNames_name_store (PROP_HSTACK, NTXT ("HSTACK")); | |
| propNames_name_store (PROP_STACKID, NTXT ("STACKID")); | |
| //propNames_name_store( PROP_CPRID, NTXT("CPRID") ); | |
| //propNames_name_store( PROP_TSKID, NTXT("TSKID") ); | |
| propNames_name_store (PROP_JTHREAD, NTXT ("JTHREAD"), | |
| GTXT ("Java thread number"), TYPE_UINT64, 0); | |
| propNames_name_store (PROP_LEAF, NTXT ("LEAF")); | |
| propNames_name_store (PROP_DOBJ, NTXT ("DOBJ")); | |
| propNames_name_store (PROP_SAMPLE_MAP, NTXT ("SAMPLE_MAP")); | |
| propNames_name_store (PROP_GCEVENT_MAP, NTXT ("GCEVENT_MAP")); | |
| propNames_name_store (PROP_PID, NTXT ("PID"), | |
| GTXT ("Process id"), TYPE_UINT64, 0); | |
| propNames_name_store (PROP_EXPID, NTXT ("EXPID"), | |
| GTXT ("Experiment id"), TYPE_UINT64, DDFLAG_NOSHOW); | |
| propNames_name_store (PROP_EXPID_CMP, NTXT ("EXPID_CMP"), | |
| GTXT ("Comparable Experiment Id"), TYPE_UINT64, | |
| DDFLAG_NOSHOW); //YXXX find better description | |
| propNames_name_store (PROP_EXPGRID, NTXT ("EXPGRID"), | |
| GTXT ("Comparison Group id"), TYPE_UINT64, 0); | |
| propNames_name_store (PROP_PARREG, NTXT ("PARREG")); | |
| propNames_name_store (PROP_TSTAMP_LO, NTXT ("TSTAMP_LO"), | |
| GTXT ("Start Timestamp (nanoseconds)"), TYPE_UINT64, 0); | |
| propNames_name_store (PROP_TSTAMP_HI, NTXT ("TSTAMP_HI"), | |
| GTXT ("End Timestamp (nanoseconds)"), TYPE_UINT64, 0); | |
| propNames_name_store (PROP_TSTAMP2, NTXT ("TSTAMP2"), | |
| GTXT ("End Timestamp (nanoseconds)"), TYPE_UINT64, | |
| DDFLAG_NOSHOW); | |
| propNames_name_store (PROP_FREQ_MHZ, NTXT ("FREQ_MHZ"), | |
| GTXT ("CPU Frequency, MHz"), TYPE_UINT32, 0); | |
| propNames_name_store (PROP_NTICK_USEC, NTXT ("NTICK_USEC"), | |
| GTXT ("Clock Profiling Interval, Microseconds"), | |
| TYPE_UINT64, 0); | |
| propNames_name_store (PROP_IOHEAPBYTES, NTXT ("IOHEAPBYTES")); | |
| propNames_name_store (PROP_STACKL, NTXT ("STACKL")); | |
| propNames_name_store (PROP_MSTACKL, NTXT ("MSTACKL")); | |
| propNames_name_store (PROP_USTACKL, NTXT ("USTACKL")); | |
| propNames_name_store (PROP_XSTACKL, NTXT ("XSTACKL")); | |
| propNames_name_store (PROP_STACKI, NTXT ("STACKI")); | |
| propNames_name_store (PROP_MSTACKI, NTXT ("MSTACKI")); | |
| propNames_name_store (PROP_USTACKI, NTXT ("USTACKI")); | |
| propNames_name_store (PROP_XSTACKI, NTXT ("XSTACKI")); | |
| // Make sure predefined names are not used for dynamic properties | |
| propNames_name_store (PROP_LAST, NTXT ("")); | |
| localized_SP_UNKNOWN_NAME = GTXT ("(unknown)"); | |
| // define Index objects | |
| dyn_indxobj = new Vector<IndexObjType_t*>(); | |
| dyn_indxobj_indx = 0; | |
| char *s = dbe_sprintf (NTXT ("((EXPID_CMP<<%llu) | THRID)"), | |
| (unsigned long long) IndexObject::INDXOBJ_EXPID_SHIFT); | |
| indxobj_define (NTXT ("Threads"), GTXT ("Threads"), s, NULL, NULL); | |
| free (s); | |
| indxobj_define (NTXT ("CPUs"), GTXT ("CPUs"), NTXT ("(CPUID)"), NULL, NULL); | |
| indxobj_define (NTXT ("Samples"), GTXT ("Samples"), NTXT ("(SAMPLE_MAP)"), | |
| NULL, NULL); | |
| indxobj_define (NTXT ("GCEvents"), GTXT ("GCEvents"), NTXT ("(GCEVENT_MAP)"), | |
| NULL, NULL); | |
| indxobj_define (NTXT ("Seconds"), GTXT ("Seconds"), | |
| NTXT ("(TSTAMP/1000000000)"), NULL, NULL); | |
| indxobj_define (NTXT ("Processes"), GTXT ("Processes"), NTXT ("(EXPID_CMP)"), | |
| NULL, NULL); | |
| s = dbe_sprintf (NTXT ("((EXPGRID<<%llu) | (EXPID<<%llu))"), | |
| (unsigned long long) IndexObject::INDXOBJ_EXPGRID_SHIFT, | |
| (unsigned long long) IndexObject::INDXOBJ_EXPID_SHIFT); | |
| indxobj_define (NTXT ("Experiment_IDs"), GTXT ("Experiment_IDs"), s, NULL, NULL); | |
| free (s); | |
| indxobj_define (NTXT ("Datasize"), GTXT ("Datasize"), | |
| "(IOHEAPBYTES==0?0:" | |
| "((IOHEAPBYTES<=(1<<0)?(1<<0):" | |
| "((IOHEAPBYTES<=(1<<2)?(1<<2):" | |
| "((IOHEAPBYTES<=(1<<4)?(1<<4):" | |
| "((IOHEAPBYTES<=(1<<6)?(1<<6):" | |
| "((IOHEAPBYTES<=(1<<8)?(1<<8):" | |
| "((IOHEAPBYTES<=(1<<10)?(1<<10):" | |
| "((IOHEAPBYTES<=(1<<12)?(1<<12):" | |
| "((IOHEAPBYTES<=(1<<14)?(1<<14):" | |
| "((IOHEAPBYTES<=(1<<16)?(1<<16):" | |
| "((IOHEAPBYTES<=(1<<18)?(1<<18):" | |
| "((IOHEAPBYTES<=(1<<20)?(1<<20):" | |
| "((IOHEAPBYTES<=(1<<22)?(1<<22):" | |
| "((IOHEAPBYTES<=(1<<24)?(1<<24):" | |
| "((IOHEAPBYTES<=(1<<26)?(1<<26):" | |
| "((IOHEAPBYTES<=(1<<28)?(1<<28):" | |
| "((IOHEAPBYTES<=(1<<30)?(1<<30):" | |
| "((IOHEAPBYTES<=(1<<32)?(1<<32):" | |
| "((IOHEAPBYTES<=(1<<34)?(1<<34):" | |
| "((IOHEAPBYTES<=(1<<36)?(1<<36):" | |
| "((IOHEAPBYTES<=(1<<38)?(1<<38):" | |
| "((IOHEAPBYTES<=(1<<40)?(1<<40):" | |
| "((IOHEAPBYTES<=(1<<42)?(1<<42):" | |
| "((IOHEAPBYTES<=(1<<44)?(1<<44):" | |
| "((IOHEAPBYTES<=(1<<46)?(1<<46):" | |
| "((IOHEAPBYTES<=(1<<48)?(1<<48):" | |
| "((IOHEAPBYTES<=(1<<50)?(1<<50):" | |
| "(IOHEAPBYTES==-1?-1:(1<<50|1)" | |
| "))))))))))))))))))))))))))))))))))))))))))))))))))))))", | |
| NULL, NULL); | |
| indxobj_define (NTXT ("Duration"), GTXT ("Duration"), | |
| "((TSTAMP_HI-TSTAMP_LO)==0?0:" | |
| "(((TSTAMP_HI-TSTAMP_LO)<=1000?1000:" | |
| "(((TSTAMP_HI-TSTAMP_LO)<=10000?10000:" | |
| "(((TSTAMP_HI-TSTAMP_LO)<=100000?100000:" | |
| "(((TSTAMP_HI-TSTAMP_LO)<=1000000?1000000:" | |
| "(((TSTAMP_HI-TSTAMP_LO)<=10000000?10000000:" | |
| "(((TSTAMP_HI-TSTAMP_LO)<=100000000?100000000:" | |
| "(((TSTAMP_HI-TSTAMP_LO)<=1000000000?1000000000:" | |
| "(((TSTAMP_HI-TSTAMP_LO)<=10000000000?10000000000:" | |
| "(((TSTAMP_HI-TSTAMP_LO)<=100000000000?100000000000:" | |
| "(((TSTAMP_HI-TSTAMP_LO)<=1000000000000?1000000000000:" | |
| "(((TSTAMP_HI-TSTAMP_LO)<=10000000000000?10000000000000:" | |
| "(10000000000001))))))))))))))))))))))))", NULL, NULL); | |
| dyn_indxobj_indx_fixed = dyn_indxobj_indx; | |
| Elf::elf_init (); | |
| defExpName = NULL; | |
| mach_model_loaded = NULL; | |
| tmp_dir_name = NULL; | |
| settings->read_rc (ipc_mode || rdt_mode); | |
| init (); | |
| } | |
| DbeSession::~DbeSession () | |
| { | |
| Destroy (views); | |
| Destroy (exps); | |
| Destroy (dobjs); | |
| Destroy (metrics); | |
| Destroy (search_path); | |
| Destroy (classpath); | |
| Destroy (propNames); | |
| Destroy (expGroups); | |
| Destroy (userLabels); | |
| if (hwcentries) | |
| { | |
| for (long i = 0, sz = hwcentries->size (); i < sz; i++) | |
| { | |
| Hwcentry *h = hwcentries->get (i); | |
| free (h->int_name); | |
| free (h->name); | |
| delete h; | |
| } | |
| delete hwcentries; | |
| } | |
| if (idxobjs) | |
| { | |
| for (int i = 0; i < idxobjs->size (); ++i) | |
| { | |
| HashMap<uint64_t, Histable*> *hMap = idxobjs->get (i); | |
| if (hMap) | |
| { | |
| hMap->values ()->destroy (); | |
| delete hMap; | |
| } | |
| } | |
| delete idxobjs; | |
| } | |
| for (int i = 0; i < HTableSize; i++) | |
| { | |
| List *list = dnameHTable[i]; | |
| while (list) | |
| { | |
| List *tmp = list; | |
| list = list->next; | |
| delete tmp; | |
| } | |
| } | |
| delete[] dnameHTable; | |
| delete classpath_df; | |
| Destroy (objs); | |
| Destroy (reg_metrics); | |
| Destroy (dyn_indxobj); | |
| delete lobjs; | |
| delete f_special; | |
| destroy_map (DbeFile *, dbeFiles); | |
| destroy_map (DbeJarFile *, dbeJarFiles); | |
| delete loadObjMap; | |
| delete omp_functions; | |
| delete sourcesMap; | |
| delete sources; | |
| delete comp_lobjs; | |
| delete comp_dbelines; | |
| delete comp_sources; | |
| delete reg_metrics_tree; | |
| delete settings; | |
| free (mach_model_loaded); | |
| if (defExpName != NULL) | |
| { | |
| StringBuilder *sb = new StringBuilder (); | |
| sb->append (NTXT ("/bin/rm -rf ")); | |
| sb->append (defExpName); | |
| char *cmd = sb->toString (); | |
| system (cmd); | |
| free (cmd); | |
| delete sb; | |
| free (defExpName); | |
| } | |
| unlink_tmp_files (); | |
| delete tmp_files; | |
| dbeSession = NULL; | |
| } | |
| void | |
| DbeSession::unlink_tmp_files () | |
| { | |
| if (tmp_files) | |
| { | |
| for (int i = 0, sz = tmp_files->size (); i < sz; i++) | |
| unlink (tmp_files->fetch (i)); | |
| tmp_files->destroy (); | |
| delete tmp_files; | |
| tmp_files = NULL; | |
| } | |
| if (tmp_dir_name) | |
| { | |
| char *cmd = dbe_sprintf (NTXT ("/bin/rm -rf %s"), tmp_dir_name); | |
| system (cmd); | |
| free (cmd); | |
| free (tmp_dir_name); | |
| tmp_dir_name = NULL; | |
| } | |
| } | |
| char * | |
| DbeSession::get_tmp_file_name (const char *nm, bool for_java) | |
| { | |
| if (tmp_dir_name == NULL) | |
| { | |
| tmp_dir_name = dbe_sprintf (NTXT ("/tmp/analyzer.%llu.%lld"), | |
| (unsigned long long) getuid (), (long long) getpid ()); | |
| mkdir (tmp_dir_name, S_IRWXU); | |
| } | |
| char *fnm = dbe_sprintf (NTXT ("%s/%s"), tmp_dir_name, nm); | |
| if (for_java) | |
| for (char *s = fnm + strlen (tmp_dir_name) + 1; *s; s++) | |
| if (*s == '/') | |
| *s = '.'; | |
| return fnm; | |
| } | |
| void | |
| DbeSession::init () | |
| { | |
| user_exp_id_counter = 0; | |
| status_ompavail = 0; | |
| archive_mode = 0; | |
| #if DEBUG | |
| char *s = getenv (NTXT ("MPMT_DEBUG")); | |
| if (s) | |
| mpmt_debug_opt = atoi (s); | |
| #endif /* DEBUG */ | |
| dbeFiles = new StringMap<DbeFile*>(); | |
| dbeJarFiles = new StringMap<DbeJarFile*>(128, 128); | |
| // set up the initial (after .rc file reading) search path | |
| set_search_path (settings->str_search_path, true); | |
| userLabels = NULL; | |
| // Preset all objects as they may reuse each other | |
| lo_unknown = NULL; | |
| f_unknown = NULL; | |
| j_unknown = NULL; | |
| lo_total = NULL; | |
| sf_unknown = NULL; | |
| f_total = NULL; | |
| f_jvm = NULL; | |
| d_total = NULL; | |
| d_scalars = NULL; | |
| d_unknown = NULL; | |
| expGroups->destroy (); | |
| f_special->reset (); | |
| for (int i = 0; i < LastSpecialFunction; i++) | |
| f_special->append (NULL); | |
| lo_omp = NULL; | |
| omp_functions->reset (); | |
| for (int i = 0; i < OMP_LAST_STATE; i++) | |
| omp_functions->append (NULL); | |
| // make sure the metric list is initialized | |
| register_metric (Metric::SIZES); | |
| register_metric (Metric::ADDRESS); | |
| register_metric (Metric::ONAME); | |
| // This is needed only to maintain loadobject id's | |
| // for <Total> and <Unknown> in tests | |
| (void) get_Unknown_LoadObject (); | |
| (void) get_Total_LoadObject (); | |
| // Create the data object name hash table. | |
| dnameHTable = new List*[HTableSize]; | |
| for (int i = 0; i < HTableSize; i++) | |
| dnameHTable[i] = NULL; | |
| d_total = createDataObject (); | |
| d_total->set_name (NTXT ("<Total>")); | |
| // XXXX <Scalars> only appropriate for Program/Data-oriented analyses | |
| d_scalars = createDataObject (); | |
| d_scalars->set_name (GTXT ("<Scalars>")); | |
| d_unknown = createDataObject (); | |
| d_unknown->set_name (GTXT ("<Unknown>")); | |
| // assign d_unknown's children so data_olayout has consistent sorting | |
| for (unsigned pp_code = 1; pp_code < NUM_ABS_PP_CODES + 2; pp_code++) | |
| { | |
| char *errcode; | |
| DataObject* dobj = createDataObject (); | |
| switch (pp_code) | |
| { | |
| case NUM_ABS_PP_CODES + 1: | |
| errcode = PTXT (DOBJ_UNDETERMINED); | |
| break; | |
| case NUM_ABS_PP_CODES: | |
| errcode = PTXT (DOBJ_UNSPECIFIED); | |
| break; | |
| case NUM_ABS_PP_CODES - 1: | |
| errcode = PTXT (DOBJ_UNIDENTIFIED); | |
| break; | |
| default: | |
| errcode = PTXT (ABS_PP_CODES[pp_code]); | |
| } | |
| dobj->parent = d_unknown; | |
| dobj->set_dobjname (errcode, NULL); // dobj->parent must already be set | |
| } | |
| for (unsigned rt_code = 1; rt_code < NUM_ABS_RT_CODES - 1; rt_code++) | |
| { | |
| DataObject* dobj = createDataObject (); | |
| dobj->parent = d_unknown; | |
| dobj->set_dobjname (PTXT (ABS_RT_CODES[rt_code]), NULL); // dobj->parent must already be set | |
| } | |
| } | |
| void | |
| DbeSession::reset_data () | |
| { | |
| for (long i = 0, sz = VecSize (idxobjs); i < sz; ++i) | |
| if (idxobjs->get (i)) | |
| idxobjs->get (i)->reset (); | |
| } | |
| void | |
| DbeSession::reset () | |
| { | |
| loadObjMap->reset (); | |
| DbeView *dbev; | |
| int index; | |
| Vec_loop (DbeView*, views, index, dbev) | |
| { | |
| dbev->reset (); | |
| } | |
| destroy_map (DbeFile *, dbeFiles); | |
| destroy_map (DbeJarFile *, dbeJarFiles); | |
| exps->destroy (); | |
| lobjs->reset (); // all LoadObjects belong to objs | |
| dobjs->destroy (); // deletes d_unknown and d_total as well | |
| objs->destroy (); | |
| comp_lobjs->clear (); | |
| comp_dbelines->clear (); | |
| comp_sources->clear (); | |
| sourcesMap->clear (); | |
| sources->reset (); | |
| // Delete the data object name hash table. | |
| for (int i = 0; i < HTableSize; i++) | |
| { | |
| List *list = dnameHTable[i]; | |
| while (list) | |
| { | |
| List *tmp = list; | |
| list = list->next; | |
| delete tmp; | |
| } | |
| } | |
| delete[] dnameHTable; | |
| // IndexObect definitions remain, objects themselves may go | |
| for (int i = 0; i < idxobjs->size (); ++i) | |
| { | |
| HashMap<uint64_t, Histable*> *v = idxobjs->fetch (i); | |
| if (v != NULL) | |
| { | |
| v->values ()->destroy (); | |
| v->clear (); | |
| } | |
| } | |
| init (); | |
| } | |
| Vector<SourceFile*> * | |
| DbeSession::get_sources () | |
| { | |
| return sources; | |
| } | |
| DbeFile * | |
| DbeSession::getDbeFile (char *filename, int filetype) | |
| { | |
| Dprintf (DEBUG_DBE_FILE, NTXT ("DbeSession::getDbeFile filetype=0x%x %s\n"), filetype, filename); | |
| if (strncmp (filename, NTXT ("./"), 2) == 0) | |
| filename += 2; | |
| DbeFile *dbeFile = dbeFiles->get (filename); | |
| if (dbeFile == NULL) | |
| { | |
| dbeFile = new DbeFile (filename); | |
| dbeFiles->put (filename, dbeFile); | |
| } | |
| dbeFile->filetype |= filetype; | |
| return dbeFile; | |
| } | |
| LoadObject * | |
| DbeSession::get_Total_LoadObject () | |
| { | |
| if (lo_total == NULL) | |
| { | |
| lo_total = createLoadObject (NTXT ("<Total>")); | |
| lo_total->dbeFile->filetype |= DbeFile::F_FICTION; | |
| } | |
| return lo_total; | |
| } | |
| Function * | |
| DbeSession::get_Total_Function () | |
| { | |
| if (f_total == NULL) | |
| { | |
| f_total = createFunction (); | |
| f_total->flags |= FUNC_FLAG_SIMULATED | FUNC_FLAG_NO_OFFSET; | |
| f_total->set_name (NTXT ("<Total>")); | |
| Module *mod = get_Total_LoadObject ()->noname; | |
| f_total->module = mod; | |
| mod->functions->append (f_total); | |
| } | |
| return f_total; | |
| } | |
| LoadObject * | |
| DbeSession::get_Unknown_LoadObject () | |
| { | |
| if (lo_unknown == NULL) | |
| { | |
| lo_unknown = createLoadObject (GTXT ("<Unknown>")); | |
| lo_unknown->type = LoadObject::SEG_TEXT; // makes it expandable | |
| lo_unknown->dbeFile->filetype |= DbeFile::F_FICTION; | |
| // force creation of the <Unknown> function | |
| (void) get_Unknown_Function (); | |
| } | |
| return lo_unknown; | |
| } | |
| SourceFile * | |
| DbeSession::get_Unknown_Source () | |
| { | |
| if (sf_unknown == NULL) | |
| { | |
| sf_unknown = createSourceFile (localized_SP_UNKNOWN_NAME); | |
| sf_unknown->dbeFile->filetype |= DbeFile::F_FICTION; | |
| sf_unknown->flags |= SOURCE_FLAG_UNKNOWN; | |
| } | |
| return sf_unknown; | |
| } | |
| Function * | |
| DbeSession::get_Unknown_Function () | |
| { | |
| if (f_unknown == NULL) | |
| { | |
| f_unknown = createFunction (); | |
| f_unknown->flags |= FUNC_FLAG_SIMULATED; | |
| f_unknown->set_name (GTXT ("<Unknown>")); | |
| Module *mod = get_Unknown_LoadObject ()->noname; | |
| f_unknown->module = mod; | |
| mod->functions->append (f_unknown); | |
| } | |
| return f_unknown; | |
| } | |
| // LIBRARY_VISIBILITY | |
| Function * | |
| DbeSession::create_hide_function (LoadObject *lo) | |
| { | |
| Function *h_function = createFunction (); | |
| h_function->set_name (lo->get_name ()); | |
| h_function->module = lo->noname; | |
| h_function->isHideFunc = true; | |
| lo->noname->functions->append (h_function); | |
| return h_function; | |
| } | |
| Function * | |
| DbeSession::get_JUnknown_Function () | |
| { | |
| if (j_unknown == NULL) | |
| { | |
| j_unknown = createFunction (); | |
| j_unknown->flags |= FUNC_FLAG_SIMULATED; | |
| j_unknown->set_name (GTXT ("<no Java callstack recorded>")); | |
| Module *mod = get_Unknown_LoadObject ()->noname; | |
| j_unknown->module = mod; | |
| mod->functions->append (j_unknown); | |
| } | |
| return j_unknown; | |
| } | |
| Function * | |
| DbeSession::get_jvm_Function () | |
| { | |
| if (f_jvm == NULL) | |
| { | |
| f_jvm = createFunction (); | |
| f_jvm->flags |= FUNC_FLAG_SIMULATED | FUNC_FLAG_NO_OFFSET; | |
| f_jvm->set_name (GTXT ("<JVM-System>")); | |
| // Find the JVM LoadObject | |
| LoadObject *jvm = get_Unknown_LoadObject (); | |
| for (int i = 0; i < lobjs->size (); ++i) | |
| { | |
| LoadObject *lo = lobjs->fetch (i); | |
| if (lo->flags & SEG_FLAG_JVM) | |
| { | |
| jvm = lo; | |
| break; | |
| } | |
| } | |
| Module *mod = jvm->noname; | |
| f_jvm->module = mod; | |
| mod->functions->append (f_jvm); | |
| // XXXX is it required? no consistency among all special functions | |
| // jvm->functions->append( f_jvm ); | |
| } | |
| return f_jvm; | |
| } | |
| Function * | |
| DbeSession::getSpecialFunction (SpecialFunction kind) | |
| { | |
| if (kind < 0 || kind >= LastSpecialFunction) | |
| return NULL; | |
| Function *func = f_special->fetch (kind); | |
| if (func == NULL) | |
| { | |
| char *fname; | |
| switch (kind) | |
| { | |
| case TruncatedStackFunc: | |
| fname = GTXT ("<Truncated-stack>"); | |
| break; | |
| case FailedUnwindFunc: | |
| fname = GTXT ("<Stack-unwind-failed>"); | |
| break; | |
| default: | |
| return NULL; | |
| } | |
| func = createFunction (); | |
| func->flags |= FUNC_FLAG_SIMULATED | FUNC_FLAG_NO_OFFSET; | |
| Module *mod = get_Total_LoadObject ()->noname; | |
| func->module = mod; | |
| mod->functions->append (func); | |
| func->set_name (fname); | |
| f_special->store (kind, func); | |
| } | |
| return func; | |
| } | |
| LoadObject * | |
| DbeSession::get_OMP_LoadObject () | |
| { | |
| if (lo_omp == NULL) | |
| { | |
| for (int i = 0, sz = lobjs->size (); i < sz; i++) | |
| { | |
| LoadObject *lo = lobjs->fetch (i); | |
| if (lo->flags & SEG_FLAG_OMP) | |
| { | |
| lo_omp = lo; | |
| return lo_omp; | |
| } | |
| } | |
| lo_omp = createLoadObject (GTXT ("<OMP>")); | |
| lo_omp->type = LoadObject::SEG_TEXT; | |
| lo_omp->dbeFile->filetype |= DbeFile::F_FICTION; | |
| } | |
| return lo_omp; | |
| } | |
| Function * | |
| DbeSession::get_OMP_Function (int n) | |
| { | |
| if (n < 0 || n >= OMP_LAST_STATE) | |
| return NULL; | |
| Function *func = omp_functions->fetch (n); | |
| if (func == NULL) | |
| { | |
| char *fname; | |
| switch (n) | |
| { | |
| case OMP_OVHD_STATE: | |
| fname = GTXT ("<OMP-overhead>"); | |
| break; | |
| case OMP_IDLE_STATE: | |
| fname = GTXT ("<OMP-idle>"); | |
| break; | |
| case OMP_RDUC_STATE: | |
| fname = GTXT ("<OMP-reduction>"); | |
| break; | |
| case OMP_IBAR_STATE: | |
| fname = GTXT ("<OMP-implicit_barrier>"); | |
| break; | |
| case OMP_EBAR_STATE: | |
| fname = GTXT ("<OMP-explicit_barrier>"); | |
| break; | |
| case OMP_LKWT_STATE: | |
| fname = GTXT ("<OMP-lock_wait>"); | |
| break; | |
| case OMP_CTWT_STATE: | |
| fname = GTXT ("<OMP-critical_section_wait>"); | |
| break; | |
| case OMP_ODWT_STATE: | |
| fname = GTXT ("<OMP-ordered_section_wait>"); | |
| break; | |
| case OMP_ATWT_STATE: | |
| fname = GTXT ("<OMP-atomic_wait>"); | |
| break; | |
| default: | |
| return NULL; | |
| } | |
| func = createFunction (); | |
| func->flags |= FUNC_FLAG_SIMULATED | FUNC_FLAG_NO_OFFSET; | |
| func->set_name (fname); | |
| LoadObject *omp = get_OMP_LoadObject (); | |
| func->module = omp->noname; | |
| omp->noname->functions->append (func); | |
| omp->functions->append (func); | |
| omp_functions->store (n, func); | |
| } | |
| return func; | |
| } | |
| // Divide the original createExperiment() into two steps | |
| // In part1, we just create the data structure, in part2, if | |
| // we decide to keep the experiment around, add it to various | |
| // lists in DbeSession | |
| Experiment * | |
| DbeSession::createExperimentPart1 () | |
| { | |
| Experiment *exp = new Experiment (); | |
| return exp; | |
| } | |
| void | |
| DbeSession::createExperimentPart2 (Experiment *exp) | |
| { | |
| int ind = expGroups->size (); | |
| if (ind > 0) | |
| { | |
| ExpGroup *gr = expGroups->fetch (ind - 1); | |
| exp->groupId = gr->groupId; | |
| gr->append (exp); | |
| } | |
| exp->setExpIdx (exps->size ()); | |
| exp->setUserExpId (++user_exp_id_counter); | |
| exps->append (exp); | |
| } | |
| Experiment * | |
| DbeSession::createExperiment () | |
| { | |
| Experiment *exp = new Experiment (); | |
| append (exp); | |
| return exp; | |
| } | |
| void | |
| DbeSession::append (Experiment *exp) | |
| { | |
| exp->setExpIdx (exps->size ()); | |
| exp->setUserExpId (++user_exp_id_counter); | |
| exps->append (exp); | |
| if (exp->founder_exp) | |
| { | |
| if (exp->founder_exp->children_exps == NULL) | |
| exp->founder_exp->children_exps = new Vector<Experiment *>; | |
| exp->founder_exp->children_exps->append (exp); | |
| if (exp->founder_exp->groupId > 0) | |
| { | |
| exp->groupId = exp->founder_exp->groupId; | |
| expGroups->get (exp->groupId - 1)->append (exp); | |
| } | |
| } | |
| if (exp->groupId == 0) | |
| { | |
| long ind = VecSize (expGroups); | |
| if (ind > 0) | |
| { | |
| ExpGroup *gr = expGroups->get (ind - 1); | |
| exp->groupId = gr->groupId; | |
| gr->append (exp); | |
| } | |
| } | |
| } | |
| void | |
| DbeSession::append (Hwcentry *h) | |
| { | |
| if (hwcentries == NULL) | |
| hwcentries = new Vector<Hwcentry*>; | |
| hwcentries->append (h); | |
| } | |
| int | |
| DbeSession::ngoodexps () | |
| { | |
| int cnt = 0; | |
| for (long i = 0, sz = VecSize (exps); i < sz; i++) | |
| if (exps->get (i)->get_status () == Experiment::SUCCESS) | |
| cnt++; | |
| return cnt; | |
| } | |
| int | |
| DbeSession::createView (int index, int cloneindex) | |
| { | |
| // ensure that there is no view with that index | |
| DbeView *dbev = getView (index); | |
| if (dbev != NULL) | |
| abort (); | |
| // find the view to be cloned | |
| dbev = getView (cloneindex); | |
| DbeView *newview; | |
| if (dbev == NULL) | |
| newview = new DbeView (theApplication, settings, index); | |
| else | |
| newview = new DbeView (dbev, index); | |
| views->append (newview); | |
| return index; | |
| } | |
| DbeView * | |
| DbeSession::getView (int index) | |
| { | |
| int i; | |
| DbeView *dbev; | |
| Vec_loop (DbeView*, views, i, dbev) | |
| { | |
| if (dbev->vindex == index) | |
| return dbev; | |
| } | |
| return NULL; | |
| } | |
| void | |
| DbeSession::dropView (int index) | |
| { | |
| int i; | |
| DbeView *dbev; | |
| Vec_loop (DbeView*, views, i, dbev) | |
| { | |
| if (dbev->vindex == index) | |
| { | |
| views->remove (i); | |
| delete dbev; | |
| return; | |
| } | |
| } | |
| // view not found; ignore for now | |
| } | |
| Vector<char*> * | |
| DbeSession::get_group_or_expt (char *path) | |
| { | |
| Vector<char*> *exp_list = new Vector<char*>; | |
| FILE *fptr; | |
| char *new_path, buf[MAXPATHLEN], name[MAXPATHLEN]; | |
| fptr = fopen (path, NTXT ("r")); | |
| if (!fptr || !fgets (buf, (int) sizeof (buf), fptr) | |
| || strncmp (buf, SP_GROUP_HEADER, strlen (SP_GROUP_HEADER))) | |
| { | |
| // it's not an experiment group | |
| new_path = dbe_strdup (path); | |
| new_path = canonical_path (new_path); | |
| exp_list->append (new_path); | |
| } | |
| else | |
| { | |
| // it is an experiment group, read the list to get them all | |
| while (fgets (buf, (int) sizeof (buf), fptr)) | |
| { | |
| if ((*buf != '#') && (sscanf (buf, NTXT ("%s"), name) == 1)) | |
| { | |
| new_path = dbe_strdup (name); | |
| new_path = canonical_path (new_path); | |
| exp_list->append (new_path); | |
| } | |
| } | |
| } | |
| if (fptr) | |
| fclose (fptr); | |
| return exp_list; | |
| } | |
| #define GET_INT_VAL(v, s, len) \ | |
| for (v = len = 0; isdigit(*s); s++, len++) { v = v * 10 + (*s -'0'); } | |
| static int | |
| dir_name_cmp (const void *a, const void *b) | |
| { | |
| char *s1 = *((char **) a); | |
| char *s2 = *((char **) b); | |
| while (*s1) | |
| { | |
| if (isdigit (*s1) && isdigit (*s2)) | |
| { | |
| int v1, v2, len1, len2; | |
| GET_INT_VAL (v1, s1, len1); | |
| GET_INT_VAL (v2, s2, len2); | |
| if (v1 != v2) | |
| return v1 - v2; | |
| if (len1 != len2) | |
| return len2 - len1; | |
| continue; | |
| } | |
| if (*s1 != *s2) | |
| break; | |
| s1++; | |
| s2++; | |
| } | |
| return *s1 - *s2; | |
| } | |
| static int | |
| read_experiment_data_in_parallel (void *arg) | |
| { | |
| exp_ctx *ctx = (exp_ctx *) arg; | |
| Experiment *dexp = ctx->exp; | |
| bool read_ahead = ctx->read_ahead; | |
| dexp->read_experiment_data (read_ahead); | |
| free (ctx); | |
| return 0; | |
| } | |
| void | |
| DbeSession::open_experiment (Experiment *exp, char *path) | |
| { | |
| exp->open (path); | |
| if (exp->get_status () != Experiment::FAILURE) | |
| exp->read_experiment_data (false); | |
| exp->open_epilogue (); | |
| // Update all DbeViews | |
| for (int i = 0, sz = views->size (); i < sz; i++) | |
| { | |
| DbeView *dbev = views->fetch (i); | |
| dbev->add_experiment (exp->getExpIdx (), true); | |
| } | |
| if (exp->get_status () == Experiment::FAILURE) | |
| { | |
| check_tab_avail (); | |
| return; | |
| } | |
| char *discard_tiny = getenv (NTXT ("SP_ANALYZER_DISCARD_TINY_EXPERIMENTS")); | |
| int user_specified_tiny_threshold = DEFAULT_TINY_THRESHOLD; // in milliseconds | |
| if (discard_tiny != NULL) | |
| { | |
| user_specified_tiny_threshold = (atoi (discard_tiny)); | |
| if (user_specified_tiny_threshold < 0) | |
| user_specified_tiny_threshold = DEFAULT_TINY_THRESHOLD; | |
| } | |
| // Open descendant experiments | |
| DIR *exp_dir = opendir (path); | |
| if (exp_dir == NULL) | |
| { | |
| check_tab_avail (); | |
| return; | |
| } | |
| Vector<char*> *exp_names = new Vector<char*>(); | |
| struct dirent *entry = NULL; | |
| while ((entry = readdir (exp_dir)) != NULL) | |
| { | |
| if (entry->d_name[0] != '_') | |
| continue; | |
| size_t len = strlen (entry->d_name); | |
| if (len < 3 || strcmp (entry->d_name + len - 3, NTXT (".er")) != 0) | |
| continue; | |
| exp_names->append (dbe_strdup (entry->d_name)); | |
| } | |
| closedir (exp_dir); | |
| exp_names->sort (dir_name_cmp); | |
| Experiment **t_exp_list = new Experiment *[exp_names->size ()]; | |
| int nsubexps = 0; | |
| for (int j = 0, jsz = exp_names->size (); j < jsz; j++) | |
| { | |
| t_exp_list[j] = NULL; | |
| char *lineage_name = exp_names->fetch (j); | |
| struct stat64 sbuf; | |
| char *dpath = dbe_sprintf (NTXT ("%s/%s"), path, lineage_name); | |
| // look for experiments with no profile collected | |
| if (user_specified_tiny_threshold == DEFAULT_TINY_THRESHOLD) | |
| { | |
| char *frinfoname = dbe_sprintf (NTXT ("%s/%s"), dpath, "data." SP_FRINFO_FILE); | |
| int st = dbe_stat (frinfoname, &sbuf); | |
| free (frinfoname); | |
| if (st == 0) | |
| { | |
| // if no profile/trace data do not process this experiment any further | |
| if (sbuf.st_size == 0) | |
| { | |
| free (dpath); | |
| continue; | |
| } | |
| } | |
| } | |
| else | |
| { // check if dpath is a directory | |
| if (dbe_stat (dpath, &sbuf) != 0) | |
| { | |
| free (dpath); | |
| continue; | |
| } | |
| else if (!S_ISDIR (sbuf.st_mode)) | |
| { | |
| free (dpath); | |
| continue; | |
| } | |
| } | |
| size_t lineage_name_len = strlen (lineage_name); | |
| lineage_name[lineage_name_len - 3] = 0; /* remove .er */ | |
| Experiment *dexp = new Experiment (); | |
| dexp->founder_exp = exp; | |
| if (user_specified_tiny_threshold > DEFAULT_TINY_THRESHOLD) | |
| { | |
| dexp->setTinyThreshold (user_specified_tiny_threshold); | |
| dexp->open (dpath); | |
| if (dexp->isDiscardedTinyExperiment ()) | |
| { | |
| delete dexp; | |
| free (dpath); | |
| continue; | |
| } | |
| } | |
| else | |
| dexp->open (dpath); | |
| append (dexp); | |
| t_exp_list[j] = dexp; | |
| nsubexps++; | |
| dexp->set_clock (exp->clock); | |
| // DbeView add_experiment() is split into two parts | |
| // add_subexperiment() is called repeeatedly for | |
| // all sub_experiments, later add_experiment_epilogue() finishes up the task | |
| for (int i = 0, sz = views->size (); i < sz; i++) | |
| { | |
| DbeView *dbev = views->fetch (i); | |
| bool enabled = settings->check_en_desc (lineage_name, dexp->utargname); | |
| dbev->add_subexperiment (dexp->getExpIdx (), enabled); | |
| } | |
| free (dpath); | |
| } | |
| for (int i = 0, sz = views->size (); i < sz; i++) | |
| { | |
| DbeView *dbev = views->fetch (i); | |
| dbev->add_experiment_epilogue (); | |
| } | |
| DbeThreadPool * threadPool = new DbeThreadPool (-1); | |
| for (int j = 0, jsz = exp_names->size (); j < jsz; j++) | |
| { | |
| if (t_exp_list[j] == NULL) continue; | |
| Experiment *dexp = t_exp_list[j]; | |
| exp_ctx *new_ctx = (exp_ctx*) malloc (sizeof (exp_ctx)); | |
| new_ctx->path = NULL; | |
| new_ctx->exp = dexp; | |
| new_ctx->ds = this; | |
| new_ctx->read_ahead = true; | |
| DbeQueue *q = new DbeQueue (read_experiment_data_in_parallel, new_ctx); | |
| threadPool->put_queue (q); | |
| } | |
| threadPool->wait_queues (); | |
| delete threadPool; | |
| for (long j = 0, jsz = exp_names->size (); j < jsz; j++) | |
| { | |
| if (t_exp_list[j] == NULL) continue; | |
| Experiment *dexp = t_exp_list[j]; | |
| dexp->open_epilogue (); | |
| } | |
| exp_names->destroy (); | |
| delete[] t_exp_list; | |
| delete exp_names; | |
| // update setting for leaklist and dataspace | |
| check_tab_avail (); | |
| } | |
| void | |
| DbeSession::append_mesgs (StringBuilder *sb, char *path, Experiment *exp) | |
| { | |
| if (exp->fetch_errors () != NULL) | |
| { | |
| // yes, there were errors | |
| char *ststr = pr_mesgs (exp->fetch_errors (), NTXT (""), NTXT ("")); | |
| sb->append (path); | |
| sb->append (NTXT (": ")); | |
| sb->append (ststr); | |
| free (ststr); | |
| } | |
| Emsg *m = exp->fetch_warnings (); | |
| if (m != NULL) | |
| { | |
| sb->append (path); | |
| sb->append (NTXT (": ")); | |
| if (!is_interactive ()) | |
| sb->append (GTXT ("Experiment has warnings, see header for details\n")); | |
| else | |
| sb->append (GTXT ("Experiment has warnings, see experiment panel for details\n")); | |
| } | |
| // Check for descendant experiments that are not loaded | |
| int num_desc = VecSize (exp->children_exps); | |
| if ((num_desc > 0) && !settings->check_en_desc (NULL, NULL)) | |
| { | |
| char *s; | |
| if (!is_interactive ()) | |
| s = dbe_sprintf (GTXT ("Has %d descendant(s), use commands controlling selection to load descendant data\n"), num_desc); | |
| else | |
| s = dbe_sprintf (GTXT ("Has %d descendant(s), use filter panel to load descendant data\n"), num_desc); | |
| sb->append (path); | |
| sb->append (NTXT (": ")); | |
| sb->append (s); | |
| free (s); | |
| } | |
| } | |
| Experiment * | |
| DbeSession::get_exp (int exp_ind) | |
| { | |
| if (exp_ind < 0 || exp_ind >= exps->size ()) | |
| return NULL; | |
| Experiment *exp = exps->fetch (exp_ind); | |
| exp->setExpIdx (exp_ind); | |
| return exp; | |
| } | |
| Vector<Vector<char*>*> * | |
| DbeSession::getExperimensGroups () | |
| { | |
| if (dbeSession->expGroups == NULL || dbeSession->expGroups->size () == 0) | |
| return NULL; | |
| bool compare_mode = expGroups->size () > 1; | |
| Vector<Vector<char*>*> *groups = new Vector<Vector<char*>*> ( | |
| compare_mode ? expGroups->size () : 1); | |
| for (int i = 0; i < expGroups->size (); i++) | |
| { | |
| ExpGroup *grp = expGroups->fetch (i); | |
| Vector<Experiment*> *founders = grp->get_founders (); | |
| if (founders && founders->size () != 0) | |
| { | |
| Vector<char *> *names = new Vector<char*> (founders->size ()); | |
| for (int j = 0; j < founders->size (); j++) | |
| { | |
| Experiment *exp = founders->fetch (j); | |
| names->append (dbe_strdup (exp->get_expt_name ())); | |
| } | |
| if (compare_mode || groups->size () == 0) | |
| groups->append (names); | |
| else | |
| groups->fetch (0)->addAll (names); | |
| } | |
| delete founders; | |
| } | |
| return groups; | |
| } | |
| char * | |
| DbeSession::setExperimentsGroups (Vector<Vector<char*>*> *groups) | |
| { | |
| StringBuilder sb; | |
| for (int i = 0; i < groups->size (); i++) | |
| { | |
| Vector<char *> *names = groups->fetch (i); | |
| ExpGroup *grp; | |
| if (names->size () == 1) | |
| grp = new ExpGroup (names->fetch (0)); | |
| else | |
| { | |
| char *nm = dbe_sprintf (GTXT ("Group %d"), i + 1); | |
| grp = new ExpGroup (nm); | |
| free (nm); | |
| } | |
| expGroups->append (grp); | |
| grp->groupId = expGroups->size (); | |
| for (int j = 0; j < names->size (); j++) | |
| { | |
| char *path = names->fetch (j); | |
| size_t len = strlen (path); | |
| if ((len > 4) && !strcmp (path + len - 4, NTXT (".erg"))) | |
| { | |
| Vector<char*> *lst = get_group_or_expt (path); | |
| for (int j1 = 0; j1 < lst->size (); j1++) | |
| { | |
| Experiment *exp = new Experiment (); | |
| append (exp); | |
| open_experiment (exp, lst->get (j1)); | |
| if (exp->get_status () == Experiment::FAILURE) | |
| append_mesgs (&sb, path, exp); | |
| } | |
| lst->destroy (); | |
| delete lst; | |
| } | |
| else | |
| { | |
| Experiment *exp = new Experiment (); | |
| append (exp); | |
| open_experiment (exp, path); | |
| if (exp->get_status () == Experiment::FAILURE) | |
| append_mesgs (&sb, path, exp); | |
| } | |
| } | |
| } | |
| for (int i = 0, sz = views->size (); i < sz; i++) | |
| { | |
| DbeView *dbev = views->fetch (i); | |
| dbev->update_advanced_filter (); | |
| int cmp = dbev->get_settings ()->get_compare_mode (); | |
| dbev->set_compare_mode (CMP_DISABLE); | |
| dbev->set_compare_mode (cmp); | |
| } | |
| return sb.length () == 0 ? NULL : sb.toString (); | |
| } | |
| char * | |
| DbeSession::drop_experiment (int exp_ind) | |
| { | |
| DbeView *dbev; | |
| int index; | |
| Experiment *exp2; | |
| status_ompavail = -1; | |
| Experiment *exp = exps->fetch (exp_ind); | |
| // If this is a sub experiment, don't do it | |
| if (exp->founder_exp != NULL) // this is a sub experiment; don't do it | |
| return (dbe_strdup (GTXT ("Can not drop subexperiments"))); | |
| if (VecSize (exp->children_exps) > 0) | |
| for (;;) | |
| { | |
| // search the list of experiments to find all that have this one as founder | |
| bool found = false; | |
| Vec_loop (Experiment*, exps, index, exp2) | |
| { | |
| if (exp2->founder_exp == exp) | |
| { | |
| exp2->founder_exp = NULL; | |
| drop_experiment (index); | |
| found = true; | |
| break; | |
| } | |
| } | |
| if (found == false) | |
| break; | |
| } | |
| // then proceed to finish the drop | |
| Vec_loop (DbeView*, views, index, dbev) | |
| { | |
| dbev->drop_experiment (exp_ind); | |
| } | |
| int old_cnt = expGroups->size (); | |
| for (int i = 0; i < old_cnt; i++) | |
| { | |
| ExpGroup *gr = expGroups->fetch (i); | |
| if (gr->groupId == exp->groupId) | |
| { | |
| gr->drop_experiment (exp); | |
| if ((gr->founder == NULL) && (gr->exps->size () == 0)) | |
| { | |
| delete gr; | |
| expGroups->remove (i); | |
| } | |
| break; | |
| } | |
| } | |
| delete exps->remove (exp_ind); | |
| if (old_cnt != expGroups->size ()) | |
| { | |
| for (int i = 0, sz = expGroups->size (); i < sz; i++) | |
| { | |
| ExpGroup *gr = expGroups->fetch (i); | |
| gr->groupId = i + 1; | |
| Vector<Experiment*> *expList = gr->exps; | |
| for (int i1 = 0, sz1 = expList->size (); i1 < sz1; i1++) | |
| expList->fetch (i1)->groupId = gr->groupId; | |
| } | |
| for (int i = 0, sz = views->size (); i < sz; i++) | |
| { | |
| dbev = views->fetch (i); | |
| int cmp = dbev->get_compare_mode (); | |
| dbev->set_compare_mode (CMP_DISABLE); | |
| dbev->set_compare_mode (cmp); | |
| } | |
| } | |
| check_tab_avail (); // update tab availability | |
| return NULL; | |
| } | |
| int | |
| DbeSession::find_experiment (char *path) | |
| { | |
| Experiment *exp; | |
| int index; | |
| Vec_loop (Experiment*, exps, index, exp) | |
| { | |
| if (strcmp (exp->get_expt_name (), path) == 0) | |
| return exp->getExpIdx (); | |
| } | |
| return -1; | |
| } | |
| LoadObject * | |
| DbeSession::createLoadObject (const char *nm, int64_t cksum) | |
| { | |
| return loadObjMap->sync_create_item (nm, cksum); | |
| } | |
| LoadObject * | |
| DbeSession::createLoadObject (const char *nm, const char *runTimePath, DbeFile *df) | |
| { | |
| return loadObjMap->sync_create_item (nm, runTimePath, df); | |
| } | |
| void | |
| DbeSession::append (LoadObject *lobj) | |
| { | |
| Histable *obj = lobj; // workaround for a C++ problem | |
| objs->append (obj); | |
| lobj->id = objs->size () - 1; | |
| lobjs->append (lobj); | |
| lobj->seg_idx = lobjs->size () - 1; | |
| char *loname = lobj->get_pathname (); | |
| dbeFiles->put (loname, lobj->dbeFile); | |
| } | |
| DbeJarFile * | |
| DbeSession::get_JarFile (const char *name) | |
| { | |
| DbeJarFile *jf = dbeJarFiles->get (name); | |
| if (jf == NULL) | |
| { | |
| jf = new DbeJarFile (name); | |
| dbeJarFiles->put (name, jf); | |
| } | |
| return jf; | |
| } | |
| Module * | |
| DbeSession::createModule (LoadObject *lo, const char *nm) | |
| { | |
| Module *mod = new Module (); | |
| Histable *obj = mod; // workaround for a C++ problem | |
| objs->append (obj); | |
| mod->id = objs->size () - 1; | |
| mod->loadobject = lo; | |
| mod->set_name (dbe_strdup (nm ? nm : localized_SP_UNKNOWN_NAME)); | |
| lo->seg_modules->append (mod); | |
| return mod; | |
| } | |
| Module * | |
| DbeSession::createUnknownModule (LoadObject *lo) | |
| { | |
| Module *mod = createModule (lo, localized_SP_UNKNOWN_NAME); | |
| mod->flags |= MOD_FLAG_UNKNOWN; | |
| mod->set_file_name (dbe_strdup (localized_SP_UNKNOWN_NAME)); | |
| return mod; | |
| } | |
| SourceFile * | |
| DbeSession::createSourceFile (const char *_path) | |
| { | |
| char *path = (char *) _path; | |
| if (strncmp (path, NTXT ("./"), 2) == 0) | |
| path += 2; | |
| SourceFile *source = sourcesMap->get (path); | |
| if (source == NULL) | |
| { | |
| source = new SourceFile (path); | |
| (void) sourcesMap->put (path, source); | |
| append (source); | |
| } | |
| return source; | |
| } | |
| Function * | |
| DbeSession::createFunction () | |
| { | |
| Function *func = new Function (objs->size ()); | |
| Histable *obj = func; // workaround for a C++ problem | |
| objs->append (obj); | |
| return func; | |
| } | |
| JMethod * | |
| DbeSession::createJMethod () | |
| { | |
| JMethod *jmthd = new JMethod (objs->size ()); | |
| Histable *obj = jmthd; // workaround for a C++ problem | |
| objs->append (obj); | |
| return jmthd; | |
| } | |
| Module * | |
| DbeSession::createClassFile (char *className) | |
| { | |
| ClassFile *cls = new ClassFile (); | |
| cls->set_name (className); | |
| char *clpath = cls->get_java_file_name (className, true); | |
| cls->dbeFile = getDbeFile (clpath, DbeFile::F_JAVACLASS); | |
| free (clpath); | |
| Histable *obj = cls; // workaround for a C++ problem | |
| objs->append (obj); | |
| cls->id = objs->size () - 1; | |
| return cls; | |
| } | |
| Histable * | |
| DbeSession::createHistObject (Histable::Type type) | |
| { | |
| switch (type) | |
| { | |
| case Histable::DOBJECT: | |
| { | |
| DataObject *dataobj = new DataObject (); | |
| dobjs->append (dataobj); | |
| dataobj->id = dobjs->size () - 1; | |
| return dataobj; | |
| } | |
| default: | |
| assert (0); | |
| } | |
| return NULL; | |
| } | |
| DataObject * | |
| DbeSession::createDataObject () | |
| { | |
| DataObject *dataobj = new DataObject (); | |
| dobjs->append (dataobj); | |
| dataobj->id = dobjs->size () - 1; | |
| return dataobj; | |
| } | |
| DataObject * | |
| DbeSession::createDataObject (DataObject *dobj, DataObject *parent) | |
| { | |
| DataObject *dataobj = new DataObject (); | |
| dataobj->size = dobj->size; | |
| dataobj->offset = dobj->offset; | |
| dataobj->parent = parent; | |
| dataobj->set_dobjname (dobj->get_typename (), dobj->get_instname ()); | |
| dobjs->append (dataobj); | |
| dataobj->id = dobjs->size () - 1; | |
| return dataobj; | |
| } | |
| DataObject * | |
| DbeSession::createMasterDataObject (DataObject *dobj) | |
| { | |
| DataObject *parent = NULL; | |
| if (dobj->parent) | |
| { // define master parent first | |
| parent = find_dobj_master (dobj->parent); | |
| if (!parent) | |
| { // clone master from this dataobject parent | |
| parent = createDataObject (dobj->parent); | |
| parent->scope = NULL; // master is scope-less | |
| Dprintf (DEBUG_DATAOBJ, | |
| "Master DataObject(%llu) cloned from (%llu) %s\n", | |
| (ull_t) parent->id, (ull_t) dobj->parent->id, | |
| dobj->parent->get_name ()); | |
| // clone master DataObject elements | |
| Vector<DataObject*> *delem = get_dobj_elements (dobj->parent); | |
| int element_index = 0; | |
| DataObject *element = NULL; | |
| Vec_loop (DataObject*, delem, element_index, element) | |
| { | |
| DataObject *master_element = createDataObject (element, parent); | |
| master_element->scope = NULL; // master is scope-less | |
| Dprintf (DEBUG_DATAOBJ, | |
| "Member DataObject(%llu) cloned from (%llu) %s\n", | |
| (ull_t) master_element->id, (ull_t) element->id, | |
| element->get_name ()); | |
| } | |
| } | |
| else | |
| Dprintf (DEBUG_DATAOBJ, "Master DataObject(%llu) clone found (%llu) %s\n", | |
| (ull_t) parent->id, (ull_t) dobj->parent->id, | |
| dobj->parent->get_name ()); | |
| } | |
| DataObject *master = find_dobj_master (dobj); | |
| if (!master) | |
| { // clone master from this dataobject | |
| master = createDataObject (dobj, parent); | |
| master->scope = NULL; // master is scope-less | |
| Dprintf (DEBUG_DATAOBJ, "Master DataObject(%llu) cloned from (%llu) %s\n", | |
| (ull_t) master->id, (ull_t) dobj->id, dobj->get_name ()); | |
| } | |
| else | |
| Dprintf (DEBUG_DATAOBJ, "Master DataObject(%llu) clone found (%llu) %s\n", | |
| (ull_t) master->id, (ull_t) dobj->id, dobj->get_name ()); | |
| return master; | |
| } | |
| void | |
| DbeSession::insert_metric (BaseMetric *mtr, Vector<BaseMetric*> *mlist) | |
| { | |
| if ((mtr->get_flavors () & Metric::STATIC) == 0) | |
| { | |
| // insert in front of the first STATIC | |
| for (int i = 0, mlist_sz = mlist->size (); i < mlist_sz; i++) | |
| { | |
| BaseMetric *m = mlist->fetch (i); | |
| if (m->get_flavors () & Metric::STATIC) | |
| { | |
| mlist->insert (i, mtr); | |
| return; | |
| } | |
| } | |
| } | |
| mlist->append (mtr); | |
| } | |
| BaseMetricTreeNode* | |
| DbeSession::get_reg_metrics_tree () | |
| { | |
| if (reg_metrics_tree == NULL) | |
| // Can't init earlier because BaseMetric() requires DbeSession::ql_parse | |
| reg_metrics_tree = new BaseMetricTreeNode (); | |
| return reg_metrics_tree; | |
| } | |
| void | |
| DbeSession::update_metric_tree (BaseMetric *m) | |
| { | |
| get_reg_metrics_tree ()->register_metric (m); | |
| } | |
| BaseMetric * | |
| DbeSession::register_metric_expr (BaseMetric::Type type, char *cmd, char *expr_spec) | |
| { | |
| BaseMetric *m = find_metric (type, cmd, expr_spec); | |
| if (m) | |
| return m; | |
| BaseMetric *bm = find_metric (type, cmd, NULL); // clone this version | |
| m = new BaseMetric (*bm); | |
| m->set_expr_spec (expr_spec); | |
| insert_metric (m, reg_metrics); | |
| return m; | |
| } | |
| BaseMetric * | |
| DbeSession::register_metric (BaseMetric::Type type) | |
| { | |
| BaseMetric *m = find_metric (type, NULL, NULL); | |
| if (m) | |
| return m; | |
| m = new BaseMetric (type); | |
| insert_metric (m, reg_metrics); | |
| update_metric_tree (m); | |
| return m; | |
| } | |
| BaseMetric * | |
| DbeSession::register_metric (Hwcentry *ctr, const char* aux, const char* username) | |
| { | |
| BaseMetric *m = find_metric (BaseMetric::HWCNTR, aux, NULL); | |
| if (m) | |
| // That may be a problem when metrics aren't an exact match. | |
| // For example, memoryspace is disabled in one experiment and not in another. | |
| return m; | |
| if (ctr->timecvt) | |
| { | |
| char *time_cmd = dbe_sprintf (NTXT ("t%s"), aux); | |
| char *time_username = dbe_sprintf (GTXT ("%s Time"), | |
| ctr->metric ? ctr->metric : | |
| (ctr->name ? ctr->name : ctr->int_name)); | |
| BaseMetric *m1; | |
| if (ipc_mode) | |
| { | |
| // Two visible metrics are presented in GUI | |
| m1 = new BaseMetric (ctr, aux, time_cmd, time_username, VAL_TIMEVAL); | |
| insert_metric (m1, reg_metrics); | |
| update_metric_tree (m1); | |
| m = new BaseMetric (ctr, aux, username, VAL_VALUE, m1); | |
| } | |
| else | |
| { | |
| // Only one visible metric is presented in er_print | |
| m1 = new BaseMetric (ctr, aux, time_cmd, time_username, VAL_TIMEVAL | VAL_INTERNAL); | |
| insert_metric (m1, reg_metrics); | |
| m = new BaseMetric (ctr, aux, username, VAL_TIMEVAL | VAL_VALUE, m1); | |
| } | |
| free (time_cmd); | |
| free (time_username); | |
| } | |
| else | |
| m = new BaseMetric (ctr, aux, username, VAL_VALUE); | |
| insert_metric (m, reg_metrics); | |
| update_metric_tree (m); | |
| return m; | |
| } | |
| BaseMetric * | |
| DbeSession::register_metric (char *name, char *username, char *_def) | |
| { | |
| BaseMetric *m = find_metric (BaseMetric::DERIVED, name, NULL); | |
| if (m) | |
| return m; | |
| Definition *p = Definition::add_definition (_def); | |
| if (p == NULL) | |
| return NULL; | |
| m = new BaseMetric (name, username, p); | |
| insert_metric (m, reg_metrics); | |
| update_metric_tree (m); | |
| return m; | |
| } | |
| void | |
| DbeSession::drop_metric (BaseMetric *mtr) | |
| { | |
| Countable *cnt; | |
| int index; | |
| Vec_loop (Countable*, metrics, index, cnt) | |
| { | |
| if (mtr == (BaseMetric *) cnt->item) | |
| { | |
| cnt->ref_count--; | |
| if (cnt->ref_count == 0) | |
| { | |
| // Remove this metric from all views | |
| DbeView *dbev; | |
| int index2; | |
| Vec_loop (DbeView*, views, index2, dbev) | |
| { | |
| dbev->reset_metrics (); | |
| } | |
| delete metrics->remove (index); | |
| delete mtr; | |
| return; | |
| } | |
| } | |
| } | |
| } | |
| BaseMetric * | |
| DbeSession::find_metric (BaseMetric::Type type, const char *cmd, const char *expr_spec) | |
| { | |
| for (int i = 0, sz = reg_metrics->size (); i < sz; i++) | |
| { | |
| BaseMetric *bm = reg_metrics->fetch (i); | |
| if (bm->get_type () == type && dbe_strcmp (bm->get_expr_spec (), expr_spec) == 0) | |
| { | |
| if ((type == BaseMetric::DERIVED || type == BaseMetric::HWCNTR) | |
| && dbe_strcmp (bm->get_cmd (), cmd) != 0) | |
| continue; | |
| return bm; | |
| } | |
| } | |
| return NULL; | |
| } | |
| BaseMetric * | |
| DbeSession::find_base_reg_metric (char * mcmd) | |
| { | |
| for (int i = 0, sz = reg_metrics->size (); i < sz; i++) | |
| { | |
| BaseMetric *bm = reg_metrics->fetch (i); | |
| if (bm->get_expr_spec () != NULL) | |
| continue; // skip compare metrics | |
| if (dbe_strcmp (bm->get_cmd (), mcmd) == 0) | |
| return bm; | |
| } | |
| return NULL; | |
| } | |
| Vector<BaseMetric*> * | |
| DbeSession::get_base_reg_metrics () | |
| { | |
| Vector<BaseMetric*> *mlist = new Vector<BaseMetric*>; | |
| Vector<BaseMetric*> *ml = get_all_reg_metrics (); | |
| for (int i = 0, sz = ml->size (); i < sz; i++) | |
| { | |
| BaseMetric *m = ml->fetch (i); | |
| if (m->get_expr_spec () == NULL) | |
| mlist->append (m); | |
| } | |
| return mlist; | |
| } | |
| void | |
| DbeSession::check_tab_avail () | |
| { | |
| DbeView *dbev; | |
| int index; | |
| // tell the views to update their tab lists | |
| Vec_loop (DbeView*, views, index, dbev) | |
| { | |
| dbev->get_settings ()->updateTabAvailability (); | |
| } | |
| } | |
| bool | |
| DbeSession::is_datamode_available () | |
| { | |
| Experiment *exp; | |
| int index; | |
| Vec_loop (Experiment*, exps, index, exp) | |
| { | |
| if (exp->dataspaceavail) | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool | |
| DbeSession::is_leaklist_available () | |
| { | |
| Experiment *exp; | |
| int index; | |
| Vec_loop (Experiment*, exps, index, exp) | |
| { | |
| if (exp->leaklistavail) | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool | |
| DbeSession::is_heapdata_available () | |
| { | |
| Experiment *exp; | |
| int index; | |
| Vec_loop (Experiment*, exps, index, exp) | |
| { | |
| if (exp->heapdataavail) | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool | |
| DbeSession::is_iodata_available () | |
| { | |
| Experiment *exp; | |
| int index; | |
| Vec_loop (Experiment*, exps, index, exp) | |
| { | |
| if (exp->iodataavail) | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool | |
| DbeSession::is_racelist_available () | |
| { | |
| Experiment *exp; | |
| int index; | |
| Vec_loop (Experiment*, exps, index, exp) | |
| { | |
| if (exp->racelistavail) | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool | |
| DbeSession::is_deadlocklist_available () | |
| { | |
| Experiment *exp; | |
| int index; | |
| Vec_loop (Experiment*, exps, index, exp) | |
| { | |
| if (exp->deadlocklistavail) | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool | |
| DbeSession::is_timeline_available () | |
| { | |
| Experiment *exp; | |
| int index; | |
| Vec_loop (Experiment*, exps, index, exp) | |
| { | |
| if (exp->timelineavail) | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool | |
| DbeSession::is_ifreq_available () | |
| { | |
| Experiment *exp; | |
| int index; | |
| Vec_loop (Experiment*, exps, index, exp) | |
| { | |
| if (exp->ifreqavail) | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool | |
| DbeSession::is_omp_available () | |
| { | |
| if (status_ompavail == -1) | |
| { | |
| status_ompavail = 0; | |
| for (int i = 0, sz = exps ? exps->size () : 0; i < sz; i++) | |
| { | |
| Experiment *exp = exps->fetch (i); | |
| if (exp->ompavail) | |
| { | |
| status_ompavail = 1; | |
| break; | |
| } | |
| } | |
| } | |
| return status_ompavail == 1; | |
| } | |
| bool | |
| DbeSession::has_java () | |
| { | |
| int status_has_java = 0; | |
| for (int i = 0, sz = exps ? exps->size () : 0; i < sz; i++) | |
| { | |
| Experiment *exp = exps->fetch (i); | |
| if (exp->has_java) | |
| { | |
| status_has_java = 1; | |
| break; | |
| } | |
| } | |
| return status_has_java == 1; | |
| } | |
| bool | |
| DbeSession::has_ompavail () | |
| { | |
| int status_has_ompavail = 0; | |
| for (int i = 0, sz = exps ? exps->size () : 0; i < sz; i++) | |
| { | |
| Experiment *exp = exps->fetch (i); | |
| if (exp->ompavail) | |
| { | |
| status_has_ompavail = 1; | |
| break; | |
| } | |
| } | |
| return status_has_ompavail == 1; | |
| } | |
| int | |
| DbeSession::get_clock (int whichexp) | |
| { | |
| // XXXX clock frequency should be an attribute of each CPU, | |
| // XXX and not a property of the session | |
| // if whichexp is -1, pick the first exp that has a clock | |
| // otherwise return the clock from the numbered experiment | |
| Experiment *exp; | |
| if (whichexp != -1) | |
| { | |
| exp = get_exp (whichexp); | |
| if (exp != NULL) | |
| return exp->clock; | |
| return 0; | |
| } | |
| int n = nexps (); | |
| for (int i = 0; i < n; i++) | |
| { | |
| exp = get_exp (i); | |
| if (exp != NULL && exp->clock != 0) | |
| return exp->clock; | |
| } | |
| return 0; | |
| } | |
| LoadObject * | |
| DbeSession::find_lobj_by_name (const char *lobj_name, int64_t cksum) | |
| { | |
| return loadObjMap->get (lobj_name, cksum); | |
| } | |
| static unsigned | |
| hash (char *s) | |
| { | |
| unsigned res = 0; | |
| for (int i = 0; i < 64 && *s; i++) | |
| res = res * 13 + *s++; | |
| return res; | |
| } | |
| // This method is introduced to fix performance | |
| // problems with the data space profiling in the | |
| // current release. A better design is desired. | |
| void | |
| DbeSession::dobj_updateHT (DataObject *dobj) | |
| { | |
| unsigned index = hash (dobj->get_unannotated_name ()) % HTableSize; | |
| List *list = new List; | |
| list->val = (void*) dobj; | |
| list->next = dnameHTable[index]; | |
| dnameHTable[index] = list; | |
| } | |
| DataObject * | |
| DbeSession::find_dobj_by_name (char *dobj_name) | |
| { | |
| unsigned index = hash (dobj_name) % HTableSize; | |
| List *list = dnameHTable[index]; | |
| for (; list; list = list->next) | |
| { | |
| DataObject *d = (DataObject*) list->val; | |
| if (strcmp (d->get_unannotated_name (), dobj_name) == 0) | |
| return d; | |
| } | |
| return (DataObject *) NULL; | |
| } | |
| DataObject * | |
| DbeSession::find_dobj_match (DataObject *dobj) | |
| { | |
| char *dobj_name = dobj->get_unannotated_name (); | |
| unsigned index = hash (dobj_name) % HTableSize; | |
| List *list = dnameHTable[index]; | |
| for (; list; list = list->next) | |
| { | |
| DataObject *d = (DataObject*) list->val; | |
| if (strcmp (d->get_unannotated_name (), dobj_name) == 0 | |
| && d->size == dobj->size && d->offset == dobj->offset | |
| && d->scope == dobj->scope) | |
| return d; | |
| } | |
| return (DataObject *) NULL; | |
| } | |
| DataObject * | |
| DbeSession::find_dobj_master (DataObject *dobj) | |
| { | |
| char *dobj_name = dobj->get_unannotated_name (); | |
| unsigned index = hash (dobj_name) % HTableSize; | |
| List *list = dnameHTable[index]; | |
| for (; list; list = list->next) | |
| { | |
| DataObject *d = (DataObject*) list->val; | |
| // XXXX should parent also match? | |
| if (strcmp (d->get_unannotated_name (), dobj_name) == 0 | |
| && d->size == dobj->size && d->offset == dobj->offset | |
| && d->master == NULL && d->scope == NULL) | |
| return d; | |
| } | |
| return (DataObject *) NULL; | |
| } | |
| Vector<DataObject*>* | |
| DbeSession::get_dobj_elements (DataObject *dobj) | |
| { | |
| DataObject *d; | |
| int index; | |
| Vector<DataObject*> *elements = new Vector<DataObject*>; | |
| if (dobj == d_total) | |
| return elements; | |
| Vec_loop (DataObject*, dobjs, index, d) | |
| { | |
| if (d->get_parent () && d->get_parent () == dobj) | |
| elements->append (d); | |
| } | |
| return elements; | |
| } | |
| Vector<LoadObject*>* | |
| DbeSession::get_text_segments () | |
| { | |
| LoadObject *lo; | |
| int index; | |
| Vector<LoadObject*> *tlobjs = new Vector<LoadObject*>; | |
| Vec_loop (LoadObject*, lobjs, index, lo) | |
| { | |
| if (lo->type == LoadObject::SEG_TEXT) | |
| tlobjs->append (lo); | |
| } | |
| return tlobjs; | |
| } | |
| static long long | |
| getNumber (const char *s, char * &last) | |
| { | |
| long long val; | |
| char *sp; | |
| errno = 0; | |
| val = strtoll (s, &sp, 0); | |
| if (errno == EINVAL) | |
| last = NULL; | |
| else | |
| { | |
| while (isspace (*sp)) | |
| sp++; | |
| last = sp; | |
| } | |
| return (val); | |
| } | |
| bool | |
| DbeSession::find_obj (FILE *dis_file, FILE *inp_file, Histable *&obj, | |
| char *name, const char *sel, Histable::Type type, bool xdefault) | |
| { | |
| Vector<Histable*> *obj_lst; | |
| int which = -1; | |
| char *last = NULL; | |
| if (type != Histable::FUNCTION && sel) | |
| { | |
| // check that a number has been provided | |
| which = (int) getNumber (sel, last); | |
| if (last == NULL || *last != '\0') | |
| { | |
| fprintf (stderr, GTXT ("Error: Invalid number entered: %s\n"), sel); | |
| sel = NULL; | |
| which = 0; | |
| } | |
| which--; | |
| } | |
| obj_lst = new Vector<Histable*>; | |
| switch (type) | |
| { | |
| case Histable::FUNCTION: | |
| obj = map_NametoFunction (name, obj_lst, sel); | |
| break; | |
| case Histable::MODULE: | |
| obj = map_NametoModule (name, obj_lst, which); | |
| break; | |
| case Histable::LOADOBJECT: | |
| obj = map_NametoLoadObject (name, obj_lst, which); | |
| break; | |
| case Histable::DOBJECT: | |
| obj = map_NametoDataObject (name, obj_lst, which); | |
| break; | |
| default: | |
| abort (); // unexpected Histable! | |
| } | |
| if ((obj == NULL) && (obj_lst->size () > 0)) | |
| { | |
| if (obj_lst->size () == 1) | |
| which = 0; | |
| else | |
| { | |
| if (sel && (which < 0 || which >= obj_lst->size ())) | |
| fprintf (stderr, GTXT ("Error: Invalid number entered: %s\n"), sel); | |
| if (xdefault) | |
| { | |
| fprintf (stderr, GTXT ("Default selection \"1\" made\n")); | |
| which = 0; | |
| } | |
| else | |
| { | |
| which = ask_which (dis_file, inp_file, obj_lst, name); | |
| if (which == -1) | |
| { | |
| delete obj_lst; | |
| return false; | |
| } | |
| } | |
| } | |
| obj = obj_lst->fetch (which); | |
| } | |
| delete obj_lst; | |
| return true; | |
| } | |
| int | |
| DbeSession::ask_which (FILE *dis_file, FILE *inp_file, | |
| Vector<Histable*> *list, char *name) | |
| { | |
| Histable *hitem; | |
| Function *func; | |
| Module *module; | |
| int which, index, index1; | |
| char *item_name, *lo_name, *fname, *last; | |
| char buf[BUFSIZ]; | |
| for (;;) | |
| { | |
| fprintf (dis_file, GTXT ("Available name list:\n")); | |
| fprintf (dis_file, GTXT ("%8d) Cancel\n"), 0); | |
| Vec_loop (Histable*, list, index, hitem) | |
| { | |
| index1 = index + 1; | |
| item_name = hitem->get_name (); | |
| switch (hitem->get_type ()) | |
| { | |
| case Histable::FUNCTION: | |
| func = (Function *) hitem; | |
| module = func->module; | |
| // id == -1 indicates er_src invocation | |
| if (module == NULL || (module->lang_code == Sp_lang_java | |
| && module->loadobject->id == -1)) | |
| fprintf (dis_file, NTXT ("%8d) %s\n"), index1, item_name); | |
| else | |
| { | |
| lo_name = module->loadobject->get_pathname (); | |
| fname = (module->file_name && *module->file_name) ? | |
| module->file_name : module->get_name (); | |
| if (fname && *fname) | |
| fprintf (dis_file, NTXT ("%8d) %s %s:0x%llx (%s)\n"), index1, | |
| item_name, lo_name, (ull_t) func->img_offset, fname); | |
| else | |
| fprintf (dis_file, NTXT ("%8d) %s %s:0x%llx\n"), index1, | |
| item_name, lo_name, (ull_t) func->img_offset); | |
| } | |
| break; | |
| case Histable::MODULE: | |
| module = (Module *) hitem; | |
| lo_name = module->loadobject->get_pathname (); | |
| if (name[strlen (name) - 1] == | |
| module->file_name[strlen (module->file_name) - 1]) | |
| fprintf (dis_file, NTXT ("%8d) %s(%s)\n"), index1, | |
| module->file_name, lo_name); | |
| else | |
| fprintf (dis_file, NTXT ("%8d) %s(%s)\n"), index1, item_name, | |
| lo_name); | |
| break; | |
| default: | |
| fprintf (dis_file, NTXT ("%8d) %s\n"), index1, item_name); | |
| break; | |
| } | |
| } | |
| if (inp_file != stdin) | |
| return -1; | |
| fprintf (dis_file, GTXT ("Enter selection: ")); | |
| if (fgets (buf, (int) sizeof (buf), inp_file) == NULL) | |
| { | |
| fprintf (stderr, GTXT ("Error: Invalid number entered:\n")); | |
| return -1; | |
| } | |
| which = (int) getNumber (buf, last); | |
| if (last && *last == '\0') | |
| if (which >= 0 && which <= list->size ()) | |
| return which - 1; | |
| fprintf (stderr, GTXT ("Error: Invalid number entered: %s\n"), buf); | |
| } | |
| } | |
| static bool | |
| match_basename (char *name, char *full_name, int len = -1) | |
| { | |
| if (full_name == NULL) | |
| return false; | |
| if (!strchr (name, '/')) | |
| full_name = get_basename (full_name); | |
| if (len == -1) | |
| return streq (name, full_name); | |
| return strncmp (name, full_name, len) == 0; | |
| } | |
| LoadObject * | |
| DbeSession::map_NametoLoadObject (char *name, Vector<Histable*> *list, int which) | |
| { | |
| // Search the tree to find the first module whose module name | |
| // matches "name" or whose source file name matches "name" | |
| // Issues: is the name a pathname, or a base name? | |
| // Should we look at suffix to disambiguate? | |
| LoadObject *loitem; | |
| int index; | |
| Vec_loop (LoadObject*, lobjs, index, loitem) | |
| { | |
| // try pathname first | |
| // if failed, try object name next | |
| if (match_basename (name, loitem->get_pathname ()) || | |
| match_basename (name, loitem->get_name ())) | |
| { | |
| if (which == list->size ()) | |
| return loitem; | |
| list->append (loitem); | |
| } | |
| } | |
| return (LoadObject *) NULL; | |
| } | |
| Module * | |
| DbeSession::map_NametoModule (char *name, Vector<Histable*> *list, int which) | |
| { | |
| // Search the tree to find the first loadobject whose loadobject name | |
| // matches "name". | |
| // Issues: is the name a pathname, or a base name? | |
| // Should we look at suffix to disambiguate? | |
| LoadObject *loitem; | |
| Module *mitem; | |
| int index1, index2; | |
| Vec_loop (LoadObject*, lobjs, index1, loitem) | |
| { | |
| Vec_loop (Module*, loitem->seg_modules, index2, mitem) | |
| { | |
| // try source name first | |
| // if failed, try object name next | |
| if (match_basename (name, mitem->file_name) || | |
| match_basename (name, mitem->get_name ())) | |
| { | |
| if (which == list->size ()) | |
| return mitem; | |
| list->append (mitem); | |
| } | |
| } | |
| } | |
| return (Module *) NULL; | |
| } | |
| Function * | |
| DbeSession::map_NametoFunction (char *name, Vector<Histable*> *list, | |
| const char *sel) | |
| { | |
| // Search the tree to find the first function whose | |
| // name matches "name". | |
| // Issues: is the name a full name, or a short name? | |
| // Is it a demangled name? If so, what about spaces | |
| // within the name? | |
| // Is there a way to return all names that match? | |
| // How can the user specify a particular function of that name? | |
| LoadObject *loitem; | |
| Function *fitem, *main_func = NULL; | |
| Module *mitem, *main_mod = NULL; | |
| int index1, index2, index3, which = -1; | |
| if (sel) | |
| { | |
| char *last = NULL; | |
| if (*sel == '@') | |
| { // 'sel' is "@seg_num:address" | |
| which = (int) getNumber (sel + 1, last); | |
| if (last == NULL || *last != ':' || (which < 0) || (which >= lobjs->size ())) | |
| { | |
| fprintf (stderr, GTXT ("Error: Invalid number entered: %s\n"), sel); | |
| return NULL; | |
| } | |
| uint64_t address = getNumber (last + 1, last); | |
| if (last == NULL || *last != '\0') | |
| { | |
| fprintf (stderr, GTXT ("Error: Invalid number entered: %s\n"), sel); | |
| return NULL; | |
| } | |
| loitem = lobjs->fetch (which); | |
| Vec_loop (Module*, loitem->seg_modules, index2, mitem) | |
| { | |
| Vec_loop (Function*, mitem->functions, index3, fitem) | |
| { | |
| if (address == fitem->img_offset && match_FName (name, fitem)) | |
| return fitem; | |
| } | |
| } | |
| return NULL; | |
| } | |
| which = (int) getNumber (sel, last); | |
| if (last == NULL || *last != '\0') | |
| { | |
| fprintf (stderr, GTXT ("Error: Invalid number entered: %s\n"), sel); | |
| return NULL; | |
| } | |
| which--; | |
| } | |
| int len_path = 0; | |
| char *with_path = name; | |
| name = StrRchr (name, '`'); | |
| if (name != with_path) | |
| len_path = (int) (name - with_path); | |
| else | |
| with_path = NULL; | |
| Vec_loop (LoadObject*, lobjs, index1, loitem) | |
| { | |
| Vec_loop (Module*, loitem->seg_modules, index2, mitem) | |
| { | |
| if (with_path) | |
| { // with file name | |
| // try source name first | |
| // if failed, try object name next | |
| if (!match_basename (with_path, mitem->file_name, len_path) && | |
| !match_basename (with_path, mitem->get_name (), len_path)) | |
| continue; | |
| } | |
| Vec_loop (Function*, mitem->functions, index3, fitem) | |
| { | |
| if (match_FName (name, fitem)) | |
| { | |
| if (which == list->size ()) | |
| return fitem; | |
| list->append (fitem); | |
| continue; | |
| } | |
| if (streq (fitem->get_name (), NTXT ("MAIN_")) && mitem->is_fortran ()) | |
| { | |
| main_func = fitem; | |
| main_mod = mitem; | |
| } | |
| } | |
| } | |
| } | |
| if (main_mod && main_func) | |
| { | |
| main_mod->read_stabs (); | |
| if (streq (main_func->get_match_name (), name) && which <= 1) | |
| return main_func; | |
| } | |
| return (Function *) NULL; | |
| } | |
| DataObject * | |
| DbeSession::map_NametoDataObject (char *name, Vector<Histable*> *list, | |
| int which) | |
| { | |
| // Search master list to find dataobjects whose names match "name" | |
| // selecting only the entry corresponding to "which" if it is not -1. | |
| // Issues: is the name fully qualified or only partially? | |
| DataObject *ditem = NULL; | |
| int index; | |
| char *full_name; | |
| Vec_loop (DataObject*, dobjs, index, ditem) | |
| { | |
| if (ditem->scope) continue; // skip non-master dataobjects | |
| // try fully-qualified dataobject name first | |
| if ((full_name = ditem->get_name ()) != NULL) | |
| { | |
| if (streq (name, full_name)) | |
| { | |
| if (which == list->size ()) | |
| return ditem; | |
| list->append (ditem); | |
| } | |
| } | |
| } | |
| if (list->size () > 0) | |
| return ditem; // return fully-qualified match | |
| // if fully-qualified name doesn't match anything, try a partial match | |
| Vec_loop (DataObject*, dobjs, index, ditem) | |
| { | |
| if (ditem->scope) continue; // skip non-master dataobjects | |
| // try fully-qualified dataobject name first | |
| if ((full_name = ditem->get_name ()) != NULL) | |
| { | |
| if (strstr (full_name, name)) | |
| { | |
| if (which == list->size ()) | |
| return ditem; | |
| list->append (ditem); | |
| } | |
| } | |
| } | |
| return (DataObject *) NULL; | |
| } | |
| bool | |
| DbeSession::match_FName (char *name, Function *func) | |
| { | |
| size_t len; | |
| char buf[MAXDBUF]; | |
| char *full_name; | |
| if (streq (func->get_name (), name)) // try full name comparison | |
| return true; | |
| if (streq (func->get_mangled_name (), name)) // try mangled name | |
| return true; | |
| if (streq (func->get_match_name (), name)) // try match name | |
| return true; | |
| Module *md = func->module; // try FORTRAN name | |
| if (md && md->is_fortran ()) | |
| { | |
| char *mangled_name = func->get_mangled_name (); | |
| len = strlen (name); | |
| if (((len + 1) == strlen (mangled_name)) && | |
| (strncmp (name, mangled_name, len) == 0)) | |
| return true; | |
| } | |
| snprintf (buf, sizeof (buf), NTXT ("%s"), func->get_name ()); | |
| full_name = buf; | |
| char *arg = NULL; // find modifier and C++ class name | |
| int i = get_paren (buf); | |
| if (i >= 0) | |
| { | |
| arg = buf + i; | |
| *arg = '\0'; | |
| } | |
| char *mod = strchr (full_name, ' '); | |
| char *cls = strchr (full_name, ':'); | |
| if (mod) | |
| { | |
| len = mod - full_name + 1; | |
| if (!strncmp (full_name, name, len)) | |
| name += len; | |
| full_name += len; | |
| if (streq (full_name, name)) // try without modifier | |
| return true; | |
| } | |
| size_t len_cmp = strlen (name); | |
| if (arg) | |
| { | |
| *arg = '('; | |
| len = arg - full_name; // try without 'args' | |
| if (len_cmp == len && !strncmp (full_name, name, len)) | |
| return true; | |
| if (cls) | |
| { | |
| len = arg - cls - 2; // and without 'class name' | |
| if ((len_cmp == len) && !strncmp (cls + 2, name, len)) | |
| return true; | |
| } | |
| } | |
| if (cls) | |
| { | |
| len = cls - full_name; // try C++ class name only | |
| if (len_cmp == len && !strncmp (full_name, name, len)) | |
| return true; | |
| if (streq (cls + 2, name)) // try without 'class name' | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool | |
| DbeSession::add_path (char *path) | |
| { | |
| return add_path (path, get_search_path ()); | |
| } | |
| bool | |
| DbeSession::add_classpath (char *path) | |
| { | |
| return add_path (path, classpath); | |
| } | |
| Vector<DbeFile*> * | |
| DbeSession::get_classpath () | |
| { | |
| if (classpath_df == NULL) | |
| classpath_df = new Vector<DbeFile*>; | |
| for (int i = classpath_df->size (), sz = classpath->size (); i < sz; i++) | |
| classpath_df->store (i, getDbeFile (classpath->fetch (i), | |
| DbeFile::F_DIR_OR_JAR)); | |
| return classpath_df; | |
| } | |
| bool | |
| DbeSession::add_path (char *path, Vector<char*> *pathes) | |
| { | |
| bool result = false; | |
| Vector <char *> *tokens = split_str (path, ':'); | |
| for (long j = 0, jsz = VecSize (tokens); j < jsz; j++) | |
| { | |
| char *spath = tokens->get (j); | |
| // Don't append path if it's already there | |
| bool got = false; | |
| for (int i = 0, sz = pathes->size (); i < sz; i++) | |
| { | |
| char *nm = pathes->get (i); | |
| if (streq (nm, spath)) | |
| { | |
| got = true; | |
| break; | |
| } | |
| } | |
| if (!got) | |
| { | |
| pathes->append (spath); | |
| result = true; | |
| } | |
| else | |
| free (spath); | |
| } | |
| delete tokens; | |
| return result; | |
| } | |
| void | |
| DbeSession::set_need_refind () | |
| { | |
| Vector<DbeFile*> *f_list = dbeFiles->values (); | |
| for (long i = 0, sz = f_list == NULL ? 0 : f_list->size (); i < sz; i++) | |
| { | |
| DbeFile *f = f_list->get (i); | |
| f->set_need_refind (true); | |
| } | |
| delete f_list; | |
| for (long i = 0, sz = sources == NULL ? 0 : sources->size (); i < sz; i++) | |
| { | |
| SourceFile *f = sources->get (i); | |
| if (f && f->dbeFile) | |
| f->dbeFile->set_need_refind (true); | |
| } | |
| } | |
| void | |
| DbeSession::set_search_path (Vector<char*> *path, bool reset) | |
| { | |
| if (reset) | |
| search_path->destroy (); | |
| for (int i = 0, sz = path == NULL ? 0 : path->size (); i < sz; i++) | |
| { | |
| char *name = path->fetch (i); | |
| if (add_path (name)) | |
| reset = true; | |
| } | |
| if (reset) | |
| { | |
| set_need_refind (); | |
| // now reset the string setting for it | |
| StringBuilder sb; | |
| for (int i = 0, sz = search_path == NULL ? 0 : search_path->size (); i < sz; i++) | |
| { | |
| char *name = search_path->fetch (i); | |
| if (sb.length () != 0) | |
| sb.append (':'); | |
| sb.append (name); | |
| } | |
| free (settings->str_search_path); | |
| settings->str_search_path = sb.toString (); | |
| } | |
| } | |
| void | |
| DbeSession::set_search_path (char *_lpath, bool reset) | |
| { | |
| Vector<char *> *path = new Vector<char*>; | |
| char *lpath = dbe_strdup (_lpath); | |
| for (char *s = lpath; s;) | |
| { | |
| path->append (s); | |
| s = strchr (s, ':'); | |
| if (s) | |
| { | |
| *s = 0; | |
| s++; | |
| } | |
| } | |
| set_search_path (path, reset); | |
| delete path; | |
| free (lpath); | |
| } | |
| void | |
| DbeSession::set_pathmaps (Vector<pathmap_t*> *newPathMap) | |
| { | |
| set_need_refind (); | |
| settings->set_pathmaps (newPathMap); | |
| } | |
| Vector<pathmap_t*> * | |
| DbeSession::get_pathmaps () | |
| { | |
| return settings->pathmaps; | |
| } | |
| void | |
| DbeSession::mobj_define (MemObjType_t *mobj) | |
| { | |
| settings->mobj_define (mobj, false); | |
| DbeView *dbev; | |
| int index; | |
| Vec_loop (DbeView*, views, index, dbev) | |
| { | |
| dbev->get_settings ()->mobj_define (mobj, false); | |
| } | |
| } | |
| void | |
| DbeSession::dump_segments (FILE *out) | |
| { | |
| int index; | |
| LoadObject *loitem; | |
| Vec_loop (LoadObject*, lobjs, index, loitem) | |
| { | |
| fprintf (out, NTXT ("Segment %d -- %s -- %s\n\n"), | |
| index, loitem->get_name (), loitem->get_pathname ()); | |
| loitem->dump_functions (out); | |
| fprintf (out, NTXT ("\n End Segment %d -- %s -- %s\n\n"), | |
| index, loitem->get_name (), loitem->get_pathname ()); | |
| } | |
| } | |
| void | |
| DbeSession::dump_dataobjects (FILE *out) | |
| { | |
| DataObject *ditem; | |
| int index; | |
| fprintf (out, NTXT ("\nMaster list of DataObjects:\n")); | |
| Vec_loop (DataObject*, dobjs, index, ditem) | |
| { | |
| Histable* scope = ditem->get_scope (); | |
| DataObject* parent = ditem->get_parent (); | |
| DataObject* master = ditem->get_master (); | |
| if (parent != NULL) | |
| fprintf (out, "id %6lld: [%4lld] parent = %6lld, offset = %+4lld %s\n", | |
| (ll_t) ditem->id, (ll_t) ditem->get_size (), | |
| (ll_t) parent->id, (ll_t) ditem->get_offset (), | |
| ditem->get_name ()); | |
| else | |
| { | |
| // parent is NULL | |
| fprintf (out, NTXT ("id %6lld: [%4lld] %s "), | |
| (ll_t) ditem->id, (ll_t) ditem->get_size (), | |
| ditem->get_name ()); | |
| if (master != NULL) | |
| fprintf (out, NTXT (" master=%lld "), (ll_t) master->id); | |
| else if (scope != NULL) | |
| fprintf (out, NTXT (" master=?? ")); | |
| else | |
| fprintf (out, NTXT (" MASTER ")); | |
| #if DEBUG | |
| if (scope != NULL) | |
| { | |
| switch (scope->get_type ()) | |
| { | |
| case Histable::LOADOBJECT: | |
| case Histable::FUNCTION: | |
| fprintf (out, NTXT ("%s"), scope->get_name ()); | |
| break; | |
| case Histable::MODULE: | |
| { | |
| char *filename = get_basename (scope->get_name ()); | |
| fprintf (out, NTXT ("%s"), filename); | |
| break; | |
| } | |
| default: | |
| fprintf (out, NTXT (" Unexpected scope %d:%s"), | |
| scope->get_type (), scope->get_name ()); | |
| } | |
| } | |
| #endif | |
| fprintf (out, NTXT ("\n")); | |
| } | |
| } | |
| } | |
| void | |
| DbeSession::dump_map (FILE *out) | |
| { | |
| Experiment *exp; | |
| int index; | |
| Vec_loop (Experiment*, exps, index, exp) | |
| { | |
| exp->dump_map (out); | |
| } | |
| } | |
| void | |
| DbeSession::dump_stacks (FILE *outfile) | |
| { | |
| Experiment *exp; | |
| int n = nexps (); | |
| FILE *f = (outfile == NULL ? stderr : outfile); | |
| for (int i = 0; i < n; i++) | |
| { | |
| exp = get_exp (i); | |
| fprintf (f, GTXT ("Experiment %d -- %s\n"), i, exp->get_expt_name ()); | |
| exp->dump_stacks (f); | |
| } | |
| } | |
| void | |
| DbeSession::propNames_name_store (int propId, const char *propName) | |
| { | |
| PropDescr *prop = new PropDescr (propId, propName); | |
| prop->flags = PRFLAG_NOSHOW; // do not show descriptions | |
| propNames->store (propId, prop); | |
| } | |
| void | |
| DbeSession::propNames_name_store (int propId, const char* propName, | |
| const char* propUname, VType_type dataType, | |
| int flags) | |
| { | |
| PropDescr *prop = new PropDescr (propId, propName); | |
| prop->vtype = dataType; | |
| prop->uname = dbe_strdup (propUname); | |
| prop->flags = flags; | |
| propNames->store (propId, prop); | |
| } | |
| char * | |
| DbeSession::propNames_name_fetch (int i) | |
| { | |
| PropDescr *prop = propNames->fetch (i); | |
| if (prop) | |
| return prop->name; | |
| return NULL; | |
| } | |
| int | |
| DbeSession::registerPropertyName (const char *name) | |
| { | |
| if (name == NULL) | |
| return PROP_NONE; | |
| for (int i = 0; i < propNames->size (); i++) | |
| { | |
| char *pname = propNames_name_fetch (i); | |
| if (pname && strcasecmp (pname, name) == 0) | |
| return i; | |
| } | |
| int propId = propNames->size (); | |
| propNames_name_store (propId, name); | |
| return propId; | |
| } | |
| int | |
| DbeSession::getPropIdByName (const char *name) | |
| { | |
| if (name == NULL) | |
| return PROP_NONE; | |
| for (int i = 0; i < propNames->size (); i++) | |
| { | |
| char *pname = propNames_name_fetch (i); | |
| if (pname && strcasecmp (pname, name) == 0) | |
| return i; | |
| } | |
| return PROP_NONE; | |
| } | |
| char * | |
| DbeSession::getPropName (int propId) | |
| { | |
| if (!propNames) | |
| return NULL; | |
| if (propId < 0 || propId >= propNames->size ()) | |
| return NULL; | |
| return dbe_strdup (propNames_name_fetch (propId)); | |
| } | |
| char * | |
| DbeSession::getPropUName (int propId) | |
| { | |
| if (!propNames) | |
| return NULL; | |
| if (propId < 0 || propId >= propNames->size ()) | |
| return NULL; | |
| PropDescr *prop = propNames->fetch (propId); | |
| if (prop) | |
| return dbe_strdup (prop->uname); | |
| return NULL; | |
| } | |
| void | |
| DbeSession::append (UserLabel *lbl) | |
| { | |
| if (lbl->expr) | |
| { | |
| if (userLabels == NULL) | |
| userLabels = new Vector<UserLabel*> (); | |
| userLabels->append (lbl); | |
| } | |
| } | |
| void | |
| DbeSession::append (SourceFile *sf) | |
| { | |
| sources->append (sf); | |
| objs->append (sf); | |
| } | |
| UserLabel * | |
| DbeSession::findUserLabel (char *name) | |
| { | |
| for (int i = 0, sz = userLabels ? userLabels->size () : 0; i < sz; i++) | |
| { | |
| UserLabel *lbl = userLabels->fetch (i); | |
| if (strcasecmp (lbl->name, name) == 0) | |
| return lbl; | |
| } | |
| return NULL; | |
| } | |
| Expression * | |
| DbeSession::findObjDefByName (char *name) | |
| { | |
| Expression *expr = NULL; | |
| MemObjType_t *mot = MemorySpace::findMemSpaceByName (name); | |
| if (mot != NULL) | |
| { | |
| char *index_expr_str = mot->index_expr; | |
| expr = ql_parse (index_expr_str); | |
| } | |
| if (expr == NULL) | |
| { | |
| int indxtype = findIndexSpaceByName (name); | |
| expr = getIndexSpaceExpr (indxtype); | |
| } | |
| if (expr == NULL) | |
| { | |
| UserLabel *ulbl = findUserLabel (name); | |
| if (ulbl) | |
| expr = ulbl->expr; | |
| } | |
| return expr; | |
| } | |
| Expression * | |
| DbeSession::ql_parse (const char *expr_spec) | |
| { | |
| /* (This slight duplication means we don't need to worry about copy | |
| constructors for the QL::Result, nor about the lifetime of the | |
| expr_spec.) */ | |
| if (expr_spec != NULL) | |
| { | |
| QL::Result result (expr_spec); | |
| QL::Parser qlparser (result); | |
| if (qlparser () != 0) | |
| return NULL; | |
| return result (); | |
| } | |
| else | |
| { | |
| QL::Result result; | |
| QL::Parser qlparser (result); | |
| if (qlparser () != 0) | |
| return NULL; | |
| return result (); | |
| } | |
| } | |
| Vector<void*> * | |
| DbeSession::getIndxObjDescriptions () | |
| { | |
| int size = dyn_indxobj_indx; | |
| if (size == 0) | |
| return NULL; | |
| Vector<int> *type = new Vector<int>(dyn_indxobj_indx); | |
| Vector<char*> *desc = new Vector<char*>(dyn_indxobj_indx); | |
| Vector<char*> *i18ndesc = new Vector<char*>(dyn_indxobj_indx); | |
| Vector<char> *mnemonic = new Vector<char>(dyn_indxobj_indx); | |
| Vector<int> *orderList = new Vector<int>(dyn_indxobj_indx); | |
| Vector<char*> *exprList = new Vector<char*>(dyn_indxobj_indx); | |
| Vector<char*> *sdesc = new Vector<char*>(dyn_indxobj_indx); | |
| Vector<char*> *ldesc = new Vector<char*>(dyn_indxobj_indx); | |
| for (long i = 0, sz = VecSize (dyn_indxobj); i < sz; i++) | |
| { | |
| IndexObjType_t *tot = dyn_indxobj->get (i); | |
| if (tot->memObj == NULL) | |
| { | |
| type->append ((int) tot->type); | |
| desc->append (dbe_strdup (tot->name)); | |
| i18ndesc->append (dbe_strdup (tot->i18n_name)); | |
| sdesc->append (dbe_strdup (tot->short_description)); | |
| ldesc->append (dbe_strdup (tot->long_description)); | |
| mnemonic->append (tot->mnemonic); | |
| orderList->append (settings->indx_tab_order->fetch (i)); | |
| exprList->append (dbe_strdup (tot->index_expr_str)); | |
| } | |
| } | |
| Vector<void*> *res = new Vector<void*>(8); | |
| res->store (0, type); | |
| res->store (1, desc); | |
| res->store (2, mnemonic); | |
| res->store (3, i18ndesc); | |
| res->store (4, orderList); | |
| res->store (5, exprList); | |
| res->store (6, sdesc); | |
| res->store (7, ldesc); | |
| return (res); | |
| } | |
| // Static function to get a vector of custom index object definitions | |
| Vector<void*> * | |
| DbeSession::getCustomIndxObjects () | |
| { | |
| Vector<char*> *name = new Vector<char*>; | |
| Vector<char*> *formula = new Vector<char*>; | |
| for (long i = dyn_indxobj_indx_fixed, sz = VecSize (dyn_indxobj); i < sz; i++) | |
| { | |
| IndexObjType_t *tot = dyn_indxobj->get (i); | |
| if (tot->memObj == NULL) | |
| { | |
| name->append (dbe_strdup (tot->name)); | |
| formula->append (dbe_strdup (tot->index_expr_str)); | |
| } | |
| } | |
| Vector<void*> *res = new Vector<void*>(2); | |
| res->store (0, name); | |
| res->store (1, formula); | |
| return (res); | |
| } | |
| // Static function to define a new index object type | |
| char * | |
| DbeSession::indxobj_define (const char *mname, char *i18nname, const char *index_expr_str, char *short_description, char *long_description) | |
| { | |
| if (mname == NULL) | |
| return dbe_strdup (GTXT ("No index object type name has been specified.")); | |
| if (isalpha ((int) (mname[0])) == 0) | |
| return dbe_sprintf (GTXT ("Index Object type name %s does not begin with an alphabetic character"), | |
| mname); | |
| const char *p = mname; | |
| while (*p != 0) | |
| { | |
| if ((isalnum ((int) (*p)) == 0) && (*p != '_')) | |
| return dbe_sprintf (GTXT ("Index Object type name %s contains a non-alphanumeric character"), | |
| mname); | |
| p++; | |
| } | |
| // make sure the name is not in use | |
| if (MemorySpace::findMemSpaceByName (mname) != NULL) | |
| return dbe_sprintf (GTXT ("Memory/Index Object type name %s is already defined"), | |
| mname); | |
| int idxx = findIndexSpaceByName (mname); | |
| if (idxx >= 0) | |
| { | |
| IndexObjType_t *mt = dyn_indxobj->fetch (idxx); | |
| if (strcmp (mt->index_expr_str, index_expr_str) == 0) | |
| // It's a redefinition, but the new definition is the same | |
| return NULL; | |
| return dbe_sprintf (GTXT ("Memory/Index Object type name %s is already defined"), | |
| mname); | |
| } | |
| if (index_expr_str == NULL) | |
| return dbe_strdup (GTXT ("No index-expr has been specified.")); | |
| if (strlen (index_expr_str) == 0) | |
| return dbe_sprintf (GTXT ("Index Object index expression is invalid: %s"), | |
| index_expr_str); | |
| // verify that the index expression parses correctly | |
| char *expr_str = dbe_strdup (index_expr_str); | |
| Expression *expr = ql_parse (expr_str); | |
| if (expr == NULL) | |
| return dbe_sprintf (GTXT ("Index Object index expression is invalid: %s"), | |
| expr_str); | |
| // It's OK, create the new table entry | |
| IndexObjType_t *tot = new IndexObjType_t; | |
| tot->type = dyn_indxobj_indx++; | |
| tot->name = dbe_strdup (mname); | |
| tot->i18n_name = dbe_strdup (i18nname); | |
| tot->short_description = dbe_strdup (short_description); | |
| tot->long_description = dbe_strdup (long_description); | |
| tot->index_expr_str = expr_str; | |
| tot->index_expr = expr; | |
| tot->mnemonic = mname[0]; | |
| // add it to the list | |
| dyn_indxobj->append (tot); | |
| idxobjs->append (new HashMap<uint64_t, Histable*>); | |
| // tell the session | |
| settings->indxobj_define (tot->type, false); | |
| DbeView *dbev; | |
| int index; | |
| Vec_loop (DbeView*, views, index, dbev) | |
| { | |
| dbev->addIndexSpace (tot->type); | |
| } | |
| return NULL; | |
| } | |
| char * | |
| DbeSession::getIndexSpaceName (int index) | |
| { | |
| if (index < 0 || index >= dyn_indxobj->size ()) | |
| return NULL; | |
| return dyn_indxobj->fetch (index)->name; | |
| } | |
| char * | |
| DbeSession::getIndexSpaceDescr (int index) | |
| { | |
| if (index < 0 || index >= dyn_indxobj->size ()) | |
| return NULL; | |
| return dyn_indxobj->fetch (index)->i18n_name; | |
| } | |
| Expression * | |
| DbeSession::getIndexSpaceExpr (int index) | |
| { | |
| if (index < 0 || index >= dyn_indxobj->size ()) | |
| return NULL; | |
| return dyn_indxobj->fetch (index)->index_expr; | |
| } | |
| char * | |
| DbeSession::getIndexSpaceExprStr (int index) | |
| { | |
| if (index < 0 || index >= dyn_indxobj->size ()) | |
| return NULL; | |
| return dyn_indxobj->fetch (index)->index_expr_str; | |
| } | |
| int | |
| DbeSession::findIndexSpaceByName (const char *mname) | |
| { | |
| int idx; | |
| IndexObjType_t *mt; | |
| Vec_loop (IndexObjType_t*, dyn_indxobj, idx, mt) | |
| { | |
| if (strcasecmp (mt->name, mname) == 0) | |
| return idx; | |
| } | |
| return -1; | |
| } | |
| void | |
| DbeSession::removeIndexSpaceByName (const char *mname) | |
| { | |
| IndexObjType_t *indObj = findIndexSpace (mname); | |
| if (indObj) | |
| indObj->name[0] = 0; | |
| } | |
| IndexObjType_t * | |
| DbeSession::getIndexSpace (int index) | |
| { | |
| return ((index < 0) || (index >= VecSize (dyn_indxobj))) ? NULL : dyn_indxobj->get (index); | |
| } | |
| IndexObjType_t * | |
| DbeSession::findIndexSpace (const char *mname) | |
| { | |
| return getIndexSpace (findIndexSpaceByName (mname)); | |
| } | |
| void | |
| DbeSession::get_filter_keywords (Vector<void*> *res) | |
| { | |
| Vector <char*> *kwCategory = (Vector<char*>*) res->fetch (0); | |
| Vector <char*> *kwCategoryI18N = (Vector<char*>*) res->fetch (1); | |
| Vector <char*> *kwDataType = (Vector<char*>*) res->fetch (2); | |
| Vector <char*> *kwKeyword = (Vector<char*>*) res->fetch (3); | |
| Vector <char*> *kwFormula = (Vector<char*>*) res->fetch (4); | |
| Vector <char*> *kwDescription = (Vector<char*>*) res->fetch (5); | |
| Vector <void*> *kwEnumDescs = (Vector<void*>*) res->fetch (6); | |
| char *vtypeNames[] = VTYPE_TYPE_NAMES; | |
| for (long i = 0, sz = userLabels ? userLabels->size () : 0; i < sz; i++) | |
| { | |
| UserLabel *lbl = userLabels->fetch (i); | |
| kwCategory->append (dbe_strdup (NTXT ("FK_LABEL"))); | |
| kwCategoryI18N->append (dbe_strdup (GTXT ("Labels"))); | |
| kwDataType->append (dbe_strdup (vtypeNames[TYPE_BOOL])); | |
| kwKeyword->append (dbe_strdup (lbl->name)); | |
| kwFormula->append (dbe_strdup (lbl->str_expr)); | |
| kwDescription->append (dbe_strdup (lbl->comment)); | |
| kwEnumDescs->append (NULL); | |
| } | |
| for (long i = 0, sz = propNames ? propNames->size () : 0; i < sz; i++) | |
| { | |
| PropDescr *prop = propNames->fetch (i); | |
| char *pname = prop ? prop->name : NULL; | |
| if (pname == NULL || *pname == 0 || prop->flags & PRFLAG_NOSHOW) | |
| continue; | |
| int vtypeNum = prop->vtype; | |
| if (vtypeNum < 0 || vtypeNum >= TYPE_LAST) | |
| vtypeNum = TYPE_NONE; | |
| kwCategory->append (dbe_strdup (NTXT ("FK_EVTPROP"))); //Event Property | |
| kwCategoryI18N->append (dbe_strdup (GTXT ("Misc. Definitions"))); | |
| kwDataType->append (dbe_strdup (vtypeNames[vtypeNum])); | |
| kwKeyword->append (dbe_strdup (pname)); | |
| kwFormula->append (NULL); | |
| kwDescription->append (dbe_strdup (prop->uname)); | |
| kwEnumDescs->append (NULL); | |
| } | |
| for (long i = 0, sz = dyn_indxobj ? dyn_indxobj->size () : 0; i < sz; i++) | |
| { | |
| IndexObjType_t *obj = dyn_indxobj->get (i); | |
| if (obj->memObj) | |
| continue; | |
| kwCategory->append (dbe_strdup (NTXT ("FK_IDXOBJ"))); | |
| kwCategoryI18N->append (dbe_strdup (GTXT ("Index Object Definitions"))); | |
| kwDataType->append (dbe_strdup (vtypeNames[TYPE_INT64])); | |
| kwKeyword->append (dbe_strdup (obj->name)); | |
| kwFormula->append (dbe_strdup (obj->index_expr_str)); | |
| kwDescription->append (dbe_strdup (obj->i18n_name)); | |
| kwEnumDescs->append (NULL); | |
| } | |
| } | |
| Histable * | |
| DbeSession::findIndexObject (int idxtype, uint64_t idx) | |
| { | |
| HashMap<uint64_t, Histable*> *iobjs = idxobjs->fetch (idxtype); | |
| return iobjs->get (idx); | |
| } | |
| Histable * | |
| DbeSession::createIndexObject (int idxtype, int64_t idx) | |
| { | |
| HashMap<uint64_t, Histable*> *iobjs = idxobjs->fetch (idxtype); | |
| Histable *idxobj = iobjs->get (idx); | |
| if (idxobj == NULL) | |
| { | |
| idxobj = new IndexObject (idxtype, idx); | |
| if (idx == -1) | |
| idxobj->set_name (dbe_strdup (GTXT ("<Unknown>"))); | |
| iobjs->put (idx, idxobj); | |
| } | |
| return idxobj; | |
| } | |
| Histable * | |
| DbeSession::createIndexObject (int idxtype, Histable *hobj) | |
| { | |
| HashMap<uint64_t, Histable*> *iobjs = idxobjs->fetch (idxtype); | |
| int64_t idx = hobj ? hobj->id : -1; | |
| Histable *idxobj = iobjs->get (idx); | |
| if (idxobj == NULL) | |
| { | |
| idxobj = new IndexObject (idxtype, hobj); | |
| if (idx == -1) | |
| idxobj->set_name (dbe_strdup (GTXT ("<Unknown>"))); | |
| iobjs->put (idx, idxobj); | |
| } | |
| return idxobj; | |
| } | |
| Histable * | |
| DbeSession::findObjectById (Histable::Type type, int subtype, uint64_t id) | |
| { | |
| switch (type) | |
| { | |
| case Histable::FUNCTION: | |
| case Histable::MODULE: | |
| case Histable::LOADOBJECT: | |
| return ( id < (uint64_t) objs->size ()) ? objs->fetch ((int) id) : NULL; | |
| case Histable::INDEXOBJ: | |
| return findIndexObject (subtype, id); | |
| // ignoring the following cases | |
| case Histable::INSTR: | |
| case Histable::LINE: | |
| case Histable::EADDR: | |
| case Histable::MEMOBJ: | |
| case Histable::PAGE: | |
| case Histable::DOBJECT: | |
| case Histable::SOURCEFILE: | |
| case Histable::IOACTFILE: | |
| case Histable::IOACTVFD: | |
| case Histable::IOCALLSTACK: | |
| case Histable::HEAPCALLSTACK: | |
| case Histable::OTHER: | |
| case Histable::EXPERIMENT: | |
| break; | |
| } | |
| return NULL; | |
| } | |
| // return a vector of Functions that match the regular expression input string | |
| Vector<JThread *> * | |
| DbeSession::match_java_threads (char *ustr, int matchParent, | |
| Vector<uint64_t> * &grids, | |
| Vector<uint64_t> * &expids) | |
| { | |
| if (ustr == NULL) | |
| return NULL; | |
| char *str = dbe_sprintf (NTXT ("^%s$"), ustr); | |
| regex_t regex_desc; | |
| int rc = regcomp (®ex_desc, str, REG_EXTENDED | REG_NOSUB | REG_NEWLINE); | |
| free (str); | |
| if (rc) // syntax error in parsing string | |
| return NULL; | |
| // allocate the new vector | |
| Vector<JThread *> *ret = new Vector<JThread*>; | |
| grids = new Vector<uint64_t>; | |
| expids = new Vector<uint64_t>; | |
| int index; | |
| JThread *jthread; | |
| int expid; | |
| Experiment* exp; | |
| Vec_loop (Experiment*, exps, expid, exp) | |
| { | |
| Vec_loop (JThread*, exp->get_jthreads (), index, jthread) | |
| { | |
| const char * name; | |
| if (matchParent) | |
| name = jthread->parent_name; | |
| else | |
| name = jthread->group_name; | |
| if (name == NULL) | |
| name = ""; | |
| if (!regexec (®ex_desc, name, 0, NULL, 0)) | |
| { | |
| // this one matches | |
| ret->append (jthread); | |
| grids->append (exp->groupId); | |
| expids->append (exp->getUserExpId ()); | |
| } | |
| } | |
| } | |
| regfree (®ex_desc); | |
| return ret; | |
| } | |
| // return a vector of Functions that match the regular expression input string | |
| Vector<Function *> * | |
| DbeSession::match_func_names (const char *ustr, Histable::NameFormat nfmt) | |
| { | |
| if (ustr == NULL) | |
| return NULL; | |
| char *str = dbe_sprintf (NTXT ("^%s$"), ustr); | |
| regex_t regex_desc; | |
| int rc = regcomp (®ex_desc, str, REG_EXTENDED | REG_NOSUB | REG_NEWLINE); | |
| free (str); | |
| if (rc) // syntax error in parsing string | |
| return NULL; | |
| // allocate the new vector | |
| Vector<Function *> *ret = new Vector<Function*>; | |
| int index; | |
| Histable *obj; | |
| Vec_loop (Histable*, objs, index, obj) | |
| { | |
| if (obj->get_type () == Histable::FUNCTION) | |
| { | |
| Function *func = (Function*) obj; | |
| if (!regexec (®ex_desc, func->get_name (nfmt), 0, NULL, 0)) | |
| // this one matches | |
| ret->append (func); | |
| } | |
| } | |
| regfree (®ex_desc); | |
| return ret; | |
| } | |
| // return a vector of Functions that match the regular expression input string | |
| Vector<FileData *> * | |
| DbeSession::match_file_names (char *ustr, Histable::NameFormat nfmt) | |
| { | |
| if (ustr == NULL) | |
| return NULL; | |
| char *str = dbe_sprintf (NTXT ("^%s$"), ustr); | |
| regex_t regex_desc; | |
| int rc = regcomp (®ex_desc, str, REG_EXTENDED | REG_NOSUB | REG_NEWLINE); | |
| free (str); | |
| if (rc) // syntax error in parsing string | |
| return NULL; | |
| // allocate the new vector | |
| Vector<FileData *> *ret = new Vector<FileData*>; | |
| int numExps = nexps (); | |
| DefaultMap<int64_t, FileData*>* fDataMap; | |
| Vector<FileData *> *fDataObjs; | |
| FileData *fData; | |
| int size; | |
| for (int i = 0; i < numExps; i++) | |
| { | |
| Experiment *exp = get_exp (i); | |
| fDataMap = exp->getFDataMap (); | |
| fDataObjs = fDataMap->values (); | |
| size = fDataObjs->size (); | |
| for (int j = 0; j < size; j++) | |
| { | |
| fData = fDataObjs->fetch (j); | |
| if (fData | |
| && !regexec (®ex_desc, fData->get_raw_name (nfmt), 0, NULL, 0)) | |
| // this one matches | |
| ret->append (fData); | |
| } | |
| } | |
| regfree (®ex_desc); | |
| return ret; | |
| } | |
| // return a vector of DataObjects that match the regular expression input string | |
| Vector<DataObject *> * | |
| DbeSession::match_dobj_names (char *ustr) | |
| { | |
| if (ustr == NULL) | |
| return NULL; | |
| char *str = dbe_sprintf (NTXT ("^%s$"), ustr); | |
| regex_t regex_desc; | |
| int rc = regcomp (®ex_desc, str, REG_EXTENDED | REG_NOSUB | REG_NEWLINE); | |
| free (str); | |
| if (rc) // syntax error in parsing string | |
| return NULL; | |
| // allocate the new vector | |
| Vector<DataObject *> *ret = new Vector<DataObject*>; | |
| int index; | |
| DataObject *ditem; | |
| Vec_loop (DataObject*, dobjs, index, ditem) | |
| { | |
| // does this one match | |
| if (!regexec (®ex_desc, ditem->get_name (), 0, NULL, 0)) | |
| // this one matches | |
| ret->append (ditem); | |
| } | |
| regfree (®ex_desc); | |
| return ret; | |
| } | |
| void | |
| DbeSession::dump (char *msg, Vector<BaseMetric*> *mlist) | |
| { | |
| if (msg) | |
| fprintf (stderr, "%s\n", msg); | |
| int sz = mlist ? mlist->size () : -1; | |
| for (int i = 0; i < sz; i++) | |
| { | |
| BaseMetric *m = mlist->fetch (i); | |
| char *s = m->dump (); | |
| fprintf (stderr, "%2d %s\n", i, s); | |
| free (s); | |
| } | |
| fprintf (stderr, "======END of mlist[%d] =========\n", sz); | |
| } | |
| void | |
| DbeSession::dump (char *msg, Vector<Metric*> *mlist) | |
| { | |
| if (msg) | |
| fprintf (stderr, "%s\n", msg); | |
| int sz = mlist ? mlist->size () : -1; | |
| for (int i = 0; i < sz; i++) | |
| { | |
| Metric *m = mlist->fetch (i); | |
| char *s = m->dump (); | |
| fprintf (stderr, "%2d %s\n", i, s); | |
| free (s); | |
| } | |
| fprintf (stderr, "======END of mlist[%d] =========\n", sz); | |
| } |