]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gprofng/src/DbeSession.cc
gprofng: a new GNU profiler
[thirdparty/binutils-gdb.git] / gprofng / src / DbeSession.cc
1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2 Contributed by Oracle.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
20
21 #include "config.h"
22 #include <ctype.h>
23 #include <stdio.h>
24 #include <dirent.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <errno.h>
28 #include <sys/param.h>
29
30 #include "util.h"
31 #include "Application.h"
32 #include "Experiment.h"
33 #include "ExpGroup.h"
34 #include "Expression.h"
35 #include "DataObject.h"
36 #include "Elf.h"
37 #include "Function.h"
38 #include "DbeSession.h"
39 #include "LoadObject.h"
40 #include "DbeSyncMap.h"
41 #include "DbeThread.h"
42 #include "ClassFile.h"
43 #include "IndexObject.h"
44 #include "PathTree.h"
45 #include "Print.h"
46 #include "QLParser.tab.hh"
47 #include "DbeView.h"
48 #include "MemorySpace.h"
49 #include "Module.h"
50 #include "SourceFile.h"
51 #include "StringBuilder.h"
52 #include "BaseMetric.h"
53 #include "BaseMetricTreeNode.h"
54 #include "Command.h"
55 #include "UserLabel.h"
56 #include "StringMap.h"
57 #include "DbeFile.h"
58 #include "DbeJarFile.h"
59 #include "IOActivity.h"
60 #include "HeapActivity.h"
61
62 // This is a universal List structure to organize objects
63 // of various types, even if different.
64 struct List
65 {
66 List *next;
67 void *val;
68 };
69
70 struct Countable
71 {
72 Countable (void *_item)
73 {
74 item = _item;
75 ref_count = 0;
76 }
77
78 void *item;
79 int ref_count;
80 };
81
82 Platform_t DbeSession::platform =
83 #if ARCH(SPARC)
84 Sparc;
85 #elif ARCH(Aarch64)
86 Aarch64;
87 #else // ARCH(Intel)
88 Intel;
89 #endif
90
91 // This constant determines the size of the data object name hash table.
92 static const int HTableSize = 8192;
93 static int DEFAULT_TINY_THRESHOLD = -1;
94
95 unsigned int mpmt_debug_opt = 0;
96 DbeSession *dbeSession = NULL;
97
98 DbeSession::DbeSession (Settings *_settings, bool _ipc_mode, bool _rdt_mode)
99 {
100 dbeSession = this;
101 ipc_mode = _ipc_mode;
102 rdt_mode = _rdt_mode;
103 settings = new Settings (_settings);
104 views = new Vector<DbeView*>;
105 exps = new Vector<Experiment*>;
106 lobjs = new Vector<LoadObject*>;
107 objs = new Vector<Histable*>;
108 dobjs = new Vector<DataObject*>;
109 metrics = new Vector<Countable*>;
110 reg_metrics = new Vector<BaseMetric*>;
111 hwcentries = NULL;
112 reg_metrics_tree = NULL; // BaseMetric() requires DbeSession::ql_parse
113 idxobjs = new Vector<HashMap<uint64_t, Histable*>*>;
114 tmp_files = new Vector<char*>;
115 search_path = new Vector<char*>;
116 classpath = new Vector<char*>;
117 classpath_df = NULL;
118 expGroups = new Vector<ExpGroup*>;
119 sourcesMap = new HashMap<char*, SourceFile*>;
120 sources = new Vector<SourceFile*>;
121 comp_lobjs = new HashMap<char*, LoadObject*>;
122 comp_dbelines = new HashMap<char*, DbeLine*>;
123 comp_sources = new HashMap<char*, SourceFile*>;
124 loadObjMap = new DbeSyncMap<LoadObject>;
125 f_special = new Vector<Function*>(LastSpecialFunction);
126 omp_functions = new Vector<Function*>(OMP_LAST_STATE);
127 interactive = false;
128 lib_visibility_used = false;
129
130 // Define all known property names
131 propNames = new Vector<PropDescr*>;
132 propNames_name_store (PROP_NONE, NTXT (""));
133 propNames_name_store (PROP_ATSTAMP, NTXT ("ATSTAMP"));
134 propNames_name_store (PROP_ETSTAMP, NTXT ("ETSTAMP"));
135 propNames_name_store (PROP_TSTAMP, NTXT ("TSTAMP"));
136 propNames_name_store (PROP_THRID, NTXT ("THRID"));
137 propNames_name_store (PROP_LWPID, NTXT ("LWPID"));
138 propNames_name_store (PROP_CPUID, NTXT ("CPUID"));
139 propNames_name_store (PROP_FRINFO, NTXT ("FRINFO"));
140 propNames_name_store (PROP_EVT_TIME, NTXT ("EVT_TIME"));
141
142 // Samples
143 propNames_name_store (PROP_SMPLOBJ, NTXT ("SMPLOBJ"));
144 propNames_name_store (PROP_SAMPLE, NTXT ("SAMPLE"));
145
146 // GCEvents
147 propNames_name_store (PROP_GCEVENTOBJ, NTXT ("GCEVENTOBJ"));
148 propNames_name_store (PROP_GCEVENT, NTXT ("GCEVENT"));
149
150 // Metadata used by some packet types
151 propNames_name_store (PROP_VOIDP_OBJ, NTXT ("VOIDP_OBJ"),
152 NULL, TYPE_UINT64, DDFLAG_NOSHOW);
153
154 // Clock profiling properties
155 propNames_name_store (PROP_UCPU, NTXT ("UCPU"));
156 propNames_name_store (PROP_SCPU, NTXT ("SCPU"));
157 propNames_name_store (PROP_TRAP, NTXT ("TRAP"));
158 propNames_name_store (PROP_TFLT, NTXT ("TFLT"));
159 propNames_name_store (PROP_DFLT, NTXT ("DFLT"));
160 propNames_name_store (PROP_KFLT, NTXT ("KFLT"));
161 propNames_name_store (PROP_ULCK, NTXT ("ULCK"));
162 propNames_name_store (PROP_TSLP, NTXT ("TSLP"));
163 propNames_name_store (PROP_WCPU, NTXT ("WCPU"));
164 propNames_name_store (PROP_TSTP, NTXT ("TSTP"));
165
166 propNames_name_store (PROP_MSTATE, NTXT ("MSTATE"));
167 propNames_name_store (PROP_NTICK, NTXT ("NTICK"));
168 propNames_name_store (PROP_OMPSTATE, NTXT ("OMPSTATE"));
169
170 // Synchronization tracing properties
171 propNames_name_store (PROP_SRQST, NTXT ("SRQST"));
172 propNames_name_store (PROP_SOBJ, NTXT ("SOBJ"));
173
174 // Hardware counter profiling properties
175 propNames_name_store (PROP_HWCTAG, NTXT ("HWCTAG"));
176 propNames_name_store (PROP_HWCINT, NTXT ("HWCINT"));
177 propNames_name_store (PROP_VADDR, NTXT ("VADDR"));
178 propNames_name_store (PROP_PADDR, NTXT ("PADDR"));
179 propNames_name_store (PROP_VIRTPC, NTXT ("VIRTPC"));
180 propNames_name_store (PROP_PHYSPC, NTXT ("PHYSPC"));
181 propNames_name_store (PROP_LWP_LGRP_HOME, NTXT ("LWP_LGRP_HOME"));
182 propNames_name_store (PROP_PS_LGRP_HOME, NTXT ("PS_LGRP_HOME"));
183 propNames_name_store (PROP_EA_PAGESIZE, NTXT ("EA_PAGESIZE"));
184 propNames_name_store (PROP_EA_LGRP, NTXT ("EA_LGRP"));
185 propNames_name_store (PROP_PC_PAGESIZE, NTXT ("PC_PAGESIZE"));
186 propNames_name_store (PROP_PC_LGRP, NTXT ("PC_LGRP"));
187 propNames_name_store (PROP_HWCDOBJ, NTXT ("HWCDOBJ"));
188 propNames_name_store (PROP_MEM_LAT, NTXT ("MEM_LAT"));
189 propNames_name_store (PROP_MEM_SRC, NTXT ("MEM_SRC"));
190
191 // Heap tracing properties
192 propNames_name_store (PROP_HTYPE, NTXT ("HTYPE"));
193 propNames_name_store (PROP_HSIZE, NTXT ("HSIZE"));
194 propNames_name_store (PROP_HVADDR, NTXT ("HVADDR"));
195 propNames_name_store (PROP_HOVADDR, NTXT ("HOVADDR"));
196 propNames_name_store (PROP_HLEAKED, NTXT ("HLEAKED"),
197 GTXT ("Leaked bytes"), TYPE_UINT64, 0);
198 propNames_name_store (PROP_HMEM_USAGE, NTXT ("HMEM_USAGE"));
199 propNames_name_store (PROP_HFREED, NTXT ("HFREED"),
200 GTXT ("Freed bytes"), TYPE_UINT64, 0);
201 propNames_name_store (PROP_HCUR_ALLOCS, NTXT ("HCUR_ALLOCS"),
202 GTXT ("Current allocations"), TYPE_INT64, 0);
203 propNames_name_store (PROP_HCUR_NET_ALLOC, NTXT ("HCUR_NET_ALLOC"),
204 NULL, TYPE_INT64, DDFLAG_NOSHOW);
205 propNames_name_store (PROP_HCUR_LEAKS, NTXT ("HCUR_LEAKS"),
206 GTXT ("Current leaks"), TYPE_UINT64, 0);
207 propNames_name_store (PROP_DDSCR_LNK, NTXT ("DDSCR_LNK"),
208 NULL, TYPE_UINT64, DDFLAG_NOSHOW);
209
210 // IO tracing properties
211 propNames_name_store (PROP_IOTYPE, NTXT ("IOTYPE"));
212 propNames_name_store (PROP_IOFD, NTXT ("IOFD"));
213 propNames_name_store (PROP_IONBYTE, NTXT ("IONBYTE"));
214 propNames_name_store (PROP_IORQST, NTXT ("IORQST"));
215 propNames_name_store (PROP_IOOFD, NTXT ("IOOFD"));
216 propNames_name_store (PROP_IOFNAME, NTXT ("IOFNAME"));
217 propNames_name_store (PROP_IOVFD, NTXT ("IOVFD"));
218 propNames_name_store (PROP_IOFSTYPE, NTXT ("IOFSTYPE"));
219
220 // omptrace raw properties
221 propNames_name_store (PROP_CPRID, NTXT ("CPRID"));
222 propNames_name_store (PROP_PPRID, NTXT ("PPRID"));
223 propNames_name_store (PROP_TSKID, NTXT ("TSKID"));
224 propNames_name_store (PROP_PTSKID, NTXT ("PTSKID"));
225 propNames_name_store (PROP_PRPC, NTXT ("PRPC"));
226
227 // Data race detection properties
228 propNames_name_store (PROP_RID, NTXT ("RID"));
229 propNames_name_store (PROP_RTYPE, NTXT ("RTYPE"));
230 propNames_name_store (PROP_LEAFPC, NTXT ("LEAFPC"));
231 propNames_name_store (PROP_RVADDR, NTXT ("RVADDR"));
232 propNames_name_store (PROP_RCNT, NTXT ("RCNT"));
233
234 // Deadlock detection properties
235 propNames_name_store (PROP_DID, NTXT ("DID"));
236 propNames_name_store (PROP_DLTYPE, NTXT ("DLTYPE"));
237 propNames_name_store (PROP_DTYPE, NTXT ("DTYPE"));
238 propNames_name_store (PROP_DVADDR, NTXT ("DVADDR"));
239
240 // Synthetic properties (queries only)
241 propNames_name_store (PROP_STACK, NTXT ("STACK"));
242 propNames_name_store (PROP_MSTACK, NTXT ("MSTACK"));
243 propNames_name_store (PROP_USTACK, NTXT ("USTACK"));
244 propNames_name_store (PROP_XSTACK, NTXT ("XSTACK"));
245 propNames_name_store (PROP_HSTACK, NTXT ("HSTACK"));
246 propNames_name_store (PROP_STACKID, NTXT ("STACKID"));
247 //propNames_name_store( PROP_CPRID, NTXT("CPRID") );
248 //propNames_name_store( PROP_TSKID, NTXT("TSKID") );
249 propNames_name_store (PROP_JTHREAD, NTXT ("JTHREAD"),
250 GTXT ("Java thread number"), TYPE_UINT64, 0);
251
252 propNames_name_store (PROP_LEAF, NTXT ("LEAF"));
253 propNames_name_store (PROP_DOBJ, NTXT ("DOBJ"));
254 propNames_name_store (PROP_SAMPLE_MAP, NTXT ("SAMPLE_MAP"));
255 propNames_name_store (PROP_GCEVENT_MAP, NTXT ("GCEVENT_MAP"));
256 propNames_name_store (PROP_PID, NTXT ("PID"),
257 GTXT ("Process id"), TYPE_UINT64, 0);
258 propNames_name_store (PROP_EXPID, NTXT ("EXPID"),
259 GTXT ("Experiment id"), TYPE_UINT64, DDFLAG_NOSHOW);
260 propNames_name_store (PROP_EXPID_CMP, NTXT ("EXPID_CMP"),
261 GTXT ("Comparable Experiment Id"), TYPE_UINT64,
262 DDFLAG_NOSHOW); //YXXX find better description
263 propNames_name_store (PROP_EXPGRID, NTXT ("EXPGRID"),
264 GTXT ("Comparison Group id"), TYPE_UINT64, 0);
265 propNames_name_store (PROP_PARREG, NTXT ("PARREG"));
266 propNames_name_store (PROP_TSTAMP_LO, NTXT ("TSTAMP_LO"),
267 GTXT ("Start Timestamp (nanoseconds)"), TYPE_UINT64, 0);
268 propNames_name_store (PROP_TSTAMP_HI, NTXT ("TSTAMP_HI"),
269 GTXT ("End Timestamp (nanoseconds)"), TYPE_UINT64, 0);
270 propNames_name_store (PROP_TSTAMP2, NTXT ("TSTAMP2"),
271 GTXT ("End Timestamp (nanoseconds)"), TYPE_UINT64,
272 DDFLAG_NOSHOW);
273 propNames_name_store (PROP_FREQ_MHZ, NTXT ("FREQ_MHZ"),
274 GTXT ("CPU Frequency, MHz"), TYPE_UINT32, 0);
275 propNames_name_store (PROP_NTICK_USEC, NTXT ("NTICK_USEC"),
276 GTXT ("Clock Profiling Interval, Microseconds"),
277 TYPE_UINT64, 0);
278
279 propNames_name_store (PROP_IOHEAPBYTES, NTXT ("IOHEAPBYTES"));
280
281 propNames_name_store (PROP_STACKL, NTXT ("STACKL"));
282 propNames_name_store (PROP_MSTACKL, NTXT ("MSTACKL"));
283 propNames_name_store (PROP_USTACKL, NTXT ("USTACKL"));
284 propNames_name_store (PROP_XSTACKL, NTXT ("XSTACKL"));
285
286 propNames_name_store (PROP_STACKI, NTXT ("STACKI"));
287 propNames_name_store (PROP_MSTACKI, NTXT ("MSTACKI"));
288 propNames_name_store (PROP_USTACKI, NTXT ("USTACKI"));
289 propNames_name_store (PROP_XSTACKI, NTXT ("XSTACKI"));
290
291 // Make sure predefined names are not used for dynamic properties
292 propNames_name_store (PROP_LAST, NTXT (""));
293
294 localized_SP_UNKNOWN_NAME = GTXT ("(unknown)");
295
296 // define Index objects
297 dyn_indxobj = new Vector<IndexObjType_t*>();
298 dyn_indxobj_indx = 0;
299 char *s = dbe_sprintf (NTXT ("((EXPID_CMP<<%llu) | THRID)"),
300 (unsigned long long) IndexObject::INDXOBJ_EXPID_SHIFT);
301 indxobj_define (NTXT ("Threads"), GTXT ("Threads"), s, NULL, NULL);
302 free (s);
303 indxobj_define (NTXT ("CPUs"), GTXT ("CPUs"), NTXT ("(CPUID)"), NULL, NULL);
304 indxobj_define (NTXT ("Samples"), GTXT ("Samples"), NTXT ("(SAMPLE_MAP)"),
305 NULL, NULL);
306 indxobj_define (NTXT ("GCEvents"), GTXT ("GCEvents"), NTXT ("(GCEVENT_MAP)"),
307 NULL, NULL);
308 indxobj_define (NTXT ("Seconds"), GTXT ("Seconds"),
309 NTXT ("(TSTAMP/1000000000)"), NULL, NULL);
310 indxobj_define (NTXT ("Processes"), GTXT ("Processes"), NTXT ("(EXPID_CMP)"),
311 NULL, NULL);
312 s = dbe_sprintf (NTXT ("((EXPGRID<<%llu) | (EXPID<<%llu))"),
313 (unsigned long long) IndexObject::INDXOBJ_EXPGRID_SHIFT,
314 (unsigned long long) IndexObject::INDXOBJ_EXPID_SHIFT);
315 indxobj_define (NTXT ("Experiment_IDs"), GTXT ("Experiment_IDs"), s, NULL, NULL);
316 free (s);
317 indxobj_define (NTXT ("Datasize"), GTXT ("Datasize"),
318 "(IOHEAPBYTES==0?0:"
319 "((IOHEAPBYTES<=(1<<0)?(1<<0):"
320 "((IOHEAPBYTES<=(1<<2)?(1<<2):"
321 "((IOHEAPBYTES<=(1<<4)?(1<<4):"
322 "((IOHEAPBYTES<=(1<<6)?(1<<6):"
323 "((IOHEAPBYTES<=(1<<8)?(1<<8):"
324 "((IOHEAPBYTES<=(1<<10)?(1<<10):"
325 "((IOHEAPBYTES<=(1<<12)?(1<<12):"
326 "((IOHEAPBYTES<=(1<<14)?(1<<14):"
327 "((IOHEAPBYTES<=(1<<16)?(1<<16):"
328 "((IOHEAPBYTES<=(1<<18)?(1<<18):"
329 "((IOHEAPBYTES<=(1<<20)?(1<<20):"
330 "((IOHEAPBYTES<=(1<<22)?(1<<22):"
331 "((IOHEAPBYTES<=(1<<24)?(1<<24):"
332 "((IOHEAPBYTES<=(1<<26)?(1<<26):"
333 "((IOHEAPBYTES<=(1<<28)?(1<<28):"
334 "((IOHEAPBYTES<=(1<<30)?(1<<30):"
335 "((IOHEAPBYTES<=(1<<32)?(1<<32):"
336 "((IOHEAPBYTES<=(1<<34)?(1<<34):"
337 "((IOHEAPBYTES<=(1<<36)?(1<<36):"
338 "((IOHEAPBYTES<=(1<<38)?(1<<38):"
339 "((IOHEAPBYTES<=(1<<40)?(1<<40):"
340 "((IOHEAPBYTES<=(1<<42)?(1<<42):"
341 "((IOHEAPBYTES<=(1<<44)?(1<<44):"
342 "((IOHEAPBYTES<=(1<<46)?(1<<46):"
343 "((IOHEAPBYTES<=(1<<48)?(1<<48):"
344 "((IOHEAPBYTES<=(1<<50)?(1<<50):"
345 "(IOHEAPBYTES==-1?-1:(1<<50|1)"
346 "))))))))))))))))))))))))))))))))))))))))))))))))))))))",
347 NULL, NULL);
348 indxobj_define (NTXT ("Duration"), GTXT ("Duration"),
349 "((TSTAMP_HI-TSTAMP_LO)==0?0:"
350 "(((TSTAMP_HI-TSTAMP_LO)<=1000?1000:"
351 "(((TSTAMP_HI-TSTAMP_LO)<=10000?10000:"
352 "(((TSTAMP_HI-TSTAMP_LO)<=100000?100000:"
353 "(((TSTAMP_HI-TSTAMP_LO)<=1000000?1000000:"
354 "(((TSTAMP_HI-TSTAMP_LO)<=10000000?10000000:"
355 "(((TSTAMP_HI-TSTAMP_LO)<=100000000?100000000:"
356 "(((TSTAMP_HI-TSTAMP_LO)<=1000000000?1000000000:"
357 "(((TSTAMP_HI-TSTAMP_LO)<=10000000000?10000000000:"
358 "(((TSTAMP_HI-TSTAMP_LO)<=100000000000?100000000000:"
359 "(((TSTAMP_HI-TSTAMP_LO)<=1000000000000?1000000000000:"
360 "(((TSTAMP_HI-TSTAMP_LO)<=10000000000000?10000000000000:"
361 "(10000000000001))))))))))))))))))))))))", NULL, NULL);
362 dyn_indxobj_indx_fixed = dyn_indxobj_indx;
363 Elf::elf_init ();
364 defExpName = NULL;
365 mach_model_loaded = NULL;
366 tmp_dir_name = NULL;
367 settings->read_rc (ipc_mode || rdt_mode);
368
369 init ();
370 }
371
372 DbeSession::~DbeSession ()
373 {
374 Destroy (views);
375 Destroy (exps);
376 Destroy (dobjs);
377 Destroy (metrics);
378 Destroy (search_path);
379 Destroy (classpath);
380 Destroy (propNames);
381 Destroy (expGroups);
382 Destroy (userLabels);
383 if (hwcentries)
384 {
385 for (long i = 0, sz = hwcentries->size (); i < sz; i++)
386 {
387 Hwcentry *h = hwcentries->get (i);
388 free (h->int_name);
389 free (h->name);
390 delete h;
391 }
392 delete hwcentries;
393 }
394
395 if (idxobjs)
396 {
397 for (int i = 0; i < idxobjs->size (); ++i)
398 {
399 HashMap<uint64_t, Histable*> *hMap = idxobjs->get (i);
400 if (hMap)
401 {
402 hMap->values ()->destroy ();
403 delete hMap;
404 }
405 }
406 delete idxobjs;
407 }
408
409 for (int i = 0; i < HTableSize; i++)
410 {
411 List *list = dnameHTable[i];
412 while (list)
413 {
414 List *tmp = list;
415 list = list->next;
416 delete tmp;
417 }
418 }
419 delete[] dnameHTable;
420 delete classpath_df;
421 Destroy (objs);
422 Destroy (reg_metrics);
423 Destroy (dyn_indxobj);
424 delete lobjs;
425 delete f_special;
426 destroy_map (DbeFile *, dbeFiles);
427 destroy_map (DbeJarFile *, dbeJarFiles);
428 delete loadObjMap;
429 delete omp_functions;
430 delete sourcesMap;
431 delete sources;
432 delete comp_lobjs;
433 delete comp_dbelines;
434 delete comp_sources;
435 delete reg_metrics_tree;
436 delete settings;
437 free (mach_model_loaded);
438
439 if (defExpName != NULL)
440 {
441 StringBuilder *sb = new StringBuilder ();
442 sb->append (NTXT ("/bin/rm -rf "));
443 sb->append (defExpName);
444 char *cmd = sb->toString ();
445 system (cmd);
446 free (cmd);
447 delete sb;
448 free (defExpName);
449 }
450 unlink_tmp_files ();
451 delete tmp_files;
452 dbeSession = NULL;
453 }
454
455 void
456 DbeSession::unlink_tmp_files ()
457 {
458 if (tmp_files)
459 {
460 for (int i = 0, sz = tmp_files->size (); i < sz; i++)
461 unlink (tmp_files->fetch (i));
462 tmp_files->destroy ();
463 delete tmp_files;
464 tmp_files = NULL;
465 }
466 if (tmp_dir_name)
467 {
468 char *cmd = dbe_sprintf (NTXT ("/bin/rm -rf %s"), tmp_dir_name);
469 system (cmd);
470 free (cmd);
471 free (tmp_dir_name);
472 tmp_dir_name = NULL;
473 }
474 }
475
476 char *
477 DbeSession::get_tmp_file_name (const char *nm, bool for_java)
478 {
479 if (tmp_dir_name == NULL)
480 {
481 tmp_dir_name = dbe_sprintf (NTXT ("/tmp/analyzer.%llu.%lld"),
482 (unsigned long long) getuid (), (long long) getpid ());
483 mkdir (tmp_dir_name, S_IRWXU);
484 }
485 char *fnm = dbe_sprintf (NTXT ("%s/%s"), tmp_dir_name, nm);
486 if (for_java)
487 for (char *s = fnm + strlen (tmp_dir_name) + 1; *s; s++)
488 if (*s == '/')
489 *s = '.';
490 return fnm;
491 }
492
493 void
494 DbeSession::init ()
495 {
496 user_exp_id_counter = 0;
497 status_ompavail = 0;
498 archive_mode = 0;
499
500 #if DEBUG
501 char *s = getenv (NTXT ("MPMT_DEBUG"));
502 if (s)
503 mpmt_debug_opt = atoi (s);
504 #endif /* DEBUG */
505 dbeFiles = new StringMap<DbeFile*>();
506 dbeJarFiles = new StringMap<DbeJarFile*>(128, 128);
507
508 // set up the initial (after .rc file reading) search path
509 set_search_path (settings->str_search_path, true);
510 userLabels = NULL;
511
512 // Preset all objects as they may reuse each other
513 lo_unknown = NULL;
514 f_unknown = NULL;
515 j_unknown = NULL;
516 lo_total = NULL;
517 sf_unknown = NULL;
518 f_total = NULL;
519 f_jvm = NULL;
520 d_total = NULL;
521 d_scalars = NULL;
522 d_unknown = NULL;
523 expGroups->destroy ();
524 f_special->reset ();
525 for (int i = 0; i < LastSpecialFunction; i++)
526 f_special->append (NULL);
527
528 lo_omp = NULL;
529 omp_functions->reset ();
530 for (int i = 0; i < OMP_LAST_STATE; i++)
531 omp_functions->append (NULL);
532
533 // make sure the metric list is initialized
534 register_metric (Metric::SIZES);
535 register_metric (Metric::ADDRESS);
536 register_metric (Metric::ONAME);
537
538 // This is needed only to maintain loadobject id's
539 // for <Total> and <Unknown> in tests
540 (void) get_Unknown_LoadObject ();
541 (void) get_Total_LoadObject ();
542
543 // Create the data object name hash table.
544 dnameHTable = new List*[HTableSize];
545 for (int i = 0; i < HTableSize; i++)
546 dnameHTable[i] = NULL;
547
548 d_total = createDataObject ();
549 d_total->set_name (NTXT ("<Total>"));
550
551 // XXXX <Scalars> only appropriate for Program/Data-oriented analyses
552 d_scalars = createDataObject ();
553 d_scalars->set_name (GTXT ("<Scalars>"));
554
555 d_unknown = createDataObject ();
556 d_unknown->set_name (GTXT ("<Unknown>"));
557
558 // assign d_unknown's children so data_olayout has consistent sorting
559 for (unsigned pp_code = 1; pp_code < NUM_ABS_PP_CODES + 2; pp_code++)
560 {
561 char *errcode;
562 DataObject* dobj = createDataObject ();
563 switch (pp_code)
564 {
565 case NUM_ABS_PP_CODES + 1:
566 errcode = PTXT (DOBJ_UNDETERMINED);
567 break;
568 case NUM_ABS_PP_CODES:
569 errcode = PTXT (DOBJ_UNSPECIFIED);
570 break;
571 case NUM_ABS_PP_CODES - 1:
572 errcode = PTXT (DOBJ_UNIDENTIFIED);
573 break;
574 default:
575 errcode = PTXT (ABS_PP_CODES[pp_code]);
576 }
577 dobj->parent = d_unknown;
578 dobj->set_dobjname (errcode, NULL); // dobj->parent must already be set
579 }
580
581 for (unsigned rt_code = 1; rt_code < NUM_ABS_RT_CODES - 1; rt_code++)
582 {
583 DataObject* dobj = createDataObject ();
584 dobj->parent = d_unknown;
585 dobj->set_dobjname (PTXT (ABS_RT_CODES[rt_code]), NULL); // dobj->parent must already be set
586 }
587 }
588
589 void
590 DbeSession::reset_data ()
591 {
592 for (long i = 0, sz = VecSize (idxobjs); i < sz; ++i)
593 if (idxobjs->get (i))
594 idxobjs->get (i)->reset ();
595 }
596
597 void
598 DbeSession::reset ()
599 {
600 loadObjMap->reset ();
601 DbeView *dbev;
602 int index;
603
604 Vec_loop (DbeView*, views, index, dbev)
605 {
606 dbev->reset ();
607 }
608
609 destroy_map (DbeFile *, dbeFiles);
610 destroy_map (DbeJarFile *, dbeJarFiles);
611 exps->destroy ();
612 lobjs->reset (); // all LoadObjects belong to objs
613 dobjs->destroy (); // deletes d_unknown and d_total as well
614 objs->destroy ();
615 comp_lobjs->clear ();
616 comp_dbelines->clear ();
617 comp_sources->clear ();
618 sourcesMap->clear ();
619 sources->reset ();
620
621 // Delete the data object name hash table.
622 for (int i = 0; i < HTableSize; i++)
623 {
624 List *list = dnameHTable[i];
625 while (list)
626 {
627 List *tmp = list;
628 list = list->next;
629 delete tmp;
630 }
631 }
632 delete[] dnameHTable;
633
634 // IndexObect definitions remain, objects themselves may go
635 for (int i = 0; i < idxobjs->size (); ++i)
636 {
637 HashMap<uint64_t, Histable*> *v = idxobjs->fetch (i);
638 if (v != NULL)
639 {
640 v->values ()->destroy ();
641 v->clear ();
642 }
643 }
644 init ();
645 }
646
647 Vector<SourceFile*> *
648 DbeSession::get_sources ()
649 {
650 return sources;
651 }
652
653 DbeFile *
654 DbeSession::getDbeFile (char *filename, int filetype)
655 {
656 Dprintf (DEBUG_DBE_FILE, NTXT ("DbeSession::getDbeFile filetype=0x%x %s\n"), filetype, filename);
657 if (strncmp (filename, NTXT ("./"), 2) == 0)
658 filename += 2;
659 DbeFile *dbeFile = dbeFiles->get (filename);
660 if (dbeFile == NULL)
661 {
662 dbeFile = new DbeFile (filename);
663 dbeFiles->put (filename, dbeFile);
664 }
665 dbeFile->filetype |= filetype;
666 return dbeFile;
667 }
668
669 LoadObject *
670 DbeSession::get_Total_LoadObject ()
671 {
672 if (lo_total == NULL)
673 {
674 lo_total = createLoadObject (NTXT ("<Total>"));
675 lo_total->dbeFile->filetype |= DbeFile::F_FICTION;
676 }
677 return lo_total;
678 }
679
680 Function *
681 DbeSession::get_Total_Function ()
682 {
683 if (f_total == NULL)
684 {
685 f_total = createFunction ();
686 f_total->flags |= FUNC_FLAG_SIMULATED | FUNC_FLAG_NO_OFFSET;
687 f_total->set_name (NTXT ("<Total>"));
688 Module *mod = get_Total_LoadObject ()->noname;
689 f_total->module = mod;
690 mod->functions->append (f_total);
691 }
692 return f_total;
693 }
694
695 LoadObject *
696 DbeSession::get_Unknown_LoadObject ()
697 {
698 if (lo_unknown == NULL)
699 {
700 lo_unknown = createLoadObject (GTXT ("<Unknown>"));
701 lo_unknown->type = LoadObject::SEG_TEXT; // makes it expandable
702 lo_unknown->dbeFile->filetype |= DbeFile::F_FICTION;
703
704 // force creation of the <Unknown> function
705 (void) get_Unknown_Function ();
706 }
707 return lo_unknown;
708 }
709
710 SourceFile *
711 DbeSession::get_Unknown_Source ()
712 {
713 if (sf_unknown == NULL)
714 {
715 sf_unknown = createSourceFile (localized_SP_UNKNOWN_NAME);
716 sf_unknown->dbeFile->filetype |= DbeFile::F_FICTION;
717 sf_unknown->flags |= SOURCE_FLAG_UNKNOWN;
718 }
719 return sf_unknown;
720 }
721
722 Function *
723 DbeSession::get_Unknown_Function ()
724 {
725 if (f_unknown == NULL)
726 {
727 f_unknown = createFunction ();
728 f_unknown->flags |= FUNC_FLAG_SIMULATED;
729 f_unknown->set_name (GTXT ("<Unknown>"));
730 Module *mod = get_Unknown_LoadObject ()->noname;
731 f_unknown->module = mod;
732 mod->functions->append (f_unknown);
733 }
734 return f_unknown;
735 }
736
737 // LIBRARY_VISIBILITY
738
739 Function *
740 DbeSession::create_hide_function (LoadObject *lo)
741 {
742 Function *h_function = createFunction ();
743 h_function->set_name (lo->get_name ());
744 h_function->module = lo->noname;
745 h_function->isHideFunc = true;
746 lo->noname->functions->append (h_function);
747 return h_function;
748 }
749
750 Function *
751 DbeSession::get_JUnknown_Function ()
752 {
753 if (j_unknown == NULL)
754 {
755 j_unknown = createFunction ();
756 j_unknown->flags |= FUNC_FLAG_SIMULATED;
757 j_unknown->set_name (GTXT ("<no Java callstack recorded>"));
758 Module *mod = get_Unknown_LoadObject ()->noname;
759 j_unknown->module = mod;
760 mod->functions->append (j_unknown);
761 }
762 return j_unknown;
763 }
764
765 Function *
766 DbeSession::get_jvm_Function ()
767 {
768 if (f_jvm == NULL)
769 {
770 f_jvm = createFunction ();
771 f_jvm->flags |= FUNC_FLAG_SIMULATED | FUNC_FLAG_NO_OFFSET;
772 f_jvm->set_name (GTXT ("<JVM-System>"));
773
774 // Find the JVM LoadObject
775 LoadObject *jvm = get_Unknown_LoadObject ();
776 for (int i = 0; i < lobjs->size (); ++i)
777 {
778 LoadObject *lo = lobjs->fetch (i);
779 if (lo->flags & SEG_FLAG_JVM)
780 {
781 jvm = lo;
782 break;
783 }
784 }
785 Module *mod = jvm->noname;
786 f_jvm->module = mod;
787 mod->functions->append (f_jvm);
788 // XXXX is it required? no consistency among all special functions
789 // jvm->functions->append( f_jvm );
790 }
791 return f_jvm;
792 }
793
794 Function *
795 DbeSession::getSpecialFunction (SpecialFunction kind)
796 {
797 if (kind < 0 || kind >= LastSpecialFunction)
798 return NULL;
799
800 Function *func = f_special->fetch (kind);
801 if (func == NULL)
802 {
803 char *fname;
804 switch (kind)
805 {
806 case TruncatedStackFunc:
807 fname = GTXT ("<Truncated-stack>");
808 break;
809 case FailedUnwindFunc:
810 fname = GTXT ("<Stack-unwind-failed>");
811 break;
812 default:
813 return NULL;
814 }
815 func = createFunction ();
816 func->flags |= FUNC_FLAG_SIMULATED | FUNC_FLAG_NO_OFFSET;
817 Module *mod = get_Total_LoadObject ()->noname;
818 func->module = mod;
819 mod->functions->append (func);
820 func->set_name (fname);
821 f_special->store (kind, func);
822 }
823 return func;
824 }
825
826 LoadObject *
827 DbeSession::get_OMP_LoadObject ()
828 {
829 if (lo_omp == NULL)
830 {
831 for (int i = 0, sz = lobjs->size (); i < sz; i++)
832 {
833 LoadObject *lo = lobjs->fetch (i);
834 if (lo->flags & SEG_FLAG_OMP)
835 {
836 lo_omp = lo;
837 return lo_omp;
838 }
839 }
840 lo_omp = createLoadObject (GTXT ("<OMP>"));
841 lo_omp->type = LoadObject::SEG_TEXT;
842 lo_omp->dbeFile->filetype |= DbeFile::F_FICTION;
843 }
844 return lo_omp;
845 }
846
847 Function *
848 DbeSession::get_OMP_Function (int n)
849 {
850 if (n < 0 || n >= OMP_LAST_STATE)
851 return NULL;
852
853 Function *func = omp_functions->fetch (n);
854 if (func == NULL)
855 {
856 char *fname;
857 switch (n)
858 {
859 case OMP_OVHD_STATE:
860 fname = GTXT ("<OMP-overhead>");
861 break;
862 case OMP_IDLE_STATE:
863 fname = GTXT ("<OMP-idle>");
864 break;
865 case OMP_RDUC_STATE:
866 fname = GTXT ("<OMP-reduction>");
867 break;
868 case OMP_IBAR_STATE:
869 fname = GTXT ("<OMP-implicit_barrier>");
870 break;
871 case OMP_EBAR_STATE:
872 fname = GTXT ("<OMP-explicit_barrier>");
873 break;
874 case OMP_LKWT_STATE:
875 fname = GTXT ("<OMP-lock_wait>");
876 break;
877 case OMP_CTWT_STATE:
878 fname = GTXT ("<OMP-critical_section_wait>");
879 break;
880 case OMP_ODWT_STATE:
881 fname = GTXT ("<OMP-ordered_section_wait>");
882 break;
883 case OMP_ATWT_STATE:
884 fname = GTXT ("<OMP-atomic_wait>");
885 break;
886 default:
887 return NULL;
888 }
889 func = createFunction ();
890 func->flags |= FUNC_FLAG_SIMULATED | FUNC_FLAG_NO_OFFSET;
891 func->set_name (fname);
892
893 LoadObject *omp = get_OMP_LoadObject ();
894 func->module = omp->noname;
895 omp->noname->functions->append (func);
896 omp->functions->append (func);
897 omp_functions->store (n, func);
898 }
899 return func;
900 }
901
902 // Divide the original createExperiment() into two steps
903 // In part1, we just create the data structure, in part2, if
904 // we decide to keep the experiment around, add it to various
905 // lists in DbeSession
906 Experiment *
907 DbeSession::createExperimentPart1 ()
908 {
909 Experiment *exp = new Experiment ();
910 return exp;
911 }
912
913 void
914 DbeSession::createExperimentPart2 (Experiment *exp)
915 {
916 int ind = expGroups->size ();
917 if (ind > 0)
918 {
919 ExpGroup *gr = expGroups->fetch (ind - 1);
920 exp->groupId = gr->groupId;
921 gr->append (exp);
922 }
923 exp->setExpIdx (exps->size ());
924 exp->setUserExpId (++user_exp_id_counter);
925 exps->append (exp);
926 }
927
928 Experiment *
929 DbeSession::createExperiment ()
930 {
931 Experiment *exp = new Experiment ();
932 append (exp);
933 return exp;
934 }
935
936 void
937 DbeSession::append (Experiment *exp)
938 {
939 exp->setExpIdx (exps->size ());
940 exp->setUserExpId (++user_exp_id_counter);
941 exps->append (exp);
942 if (exp->founder_exp)
943 {
944 if (exp->founder_exp->children_exps == NULL)
945 exp->founder_exp->children_exps = new Vector<Experiment *>;
946 exp->founder_exp->children_exps->append (exp);
947 if (exp->founder_exp->groupId > 0)
948 {
949 exp->groupId = exp->founder_exp->groupId;
950 expGroups->get (exp->groupId - 1)->append (exp);
951 }
952 }
953 if (exp->groupId == 0)
954 {
955 long ind = VecSize (expGroups);
956 if (ind > 0)
957 {
958 ExpGroup *gr = expGroups->get (ind - 1);
959 exp->groupId = gr->groupId;
960 gr->append (exp);
961 }
962 }
963 }
964
965 void
966 DbeSession::append (Hwcentry *h)
967 {
968 if (hwcentries == NULL)
969 hwcentries = new Vector<Hwcentry*>;
970 hwcentries->append (h);
971 }
972
973 int
974 DbeSession::ngoodexps ()
975 {
976 return exps->size ();
977 }
978
979 int
980 DbeSession::createView (int index, int cloneindex)
981 {
982 // ensure that there is no view with that index
983 DbeView *dbev = getView (index);
984 if (dbev != NULL)
985 abort ();
986
987 // find the view to be cloned
988 dbev = getView (cloneindex);
989 DbeView *newview;
990 if (dbev == NULL)
991 newview = new DbeView (theApplication, settings, index);
992 else
993 newview = new DbeView (dbev, index);
994 views->append (newview);
995 return index;
996 }
997
998 DbeView *
999 DbeSession::getView (int index)
1000 {
1001 int i;
1002 DbeView *dbev;
1003 Vec_loop (DbeView*, views, i, dbev)
1004 {
1005 if (dbev->vindex == index)
1006 return dbev;
1007 }
1008 return NULL;
1009 }
1010
1011 void
1012 DbeSession::dropView (int index)
1013 {
1014 int i;
1015 DbeView *dbev;
1016
1017 Vec_loop (DbeView*, views, i, dbev)
1018 {
1019 if (dbev->vindex == index)
1020 {
1021 views->remove (i);
1022 delete dbev;
1023 return;
1024 }
1025 }
1026 // view not found; ignore for now
1027 }
1028
1029 Vector<char*> *
1030 DbeSession::get_group_or_expt (char *path)
1031 {
1032 Vector<char*> *exp_list = new Vector<char*>;
1033 FILE *fptr;
1034 char *new_path, buf[MAXPATHLEN], name[MAXPATHLEN];
1035
1036 fptr = fopen (path, NTXT ("r"));
1037 if (!fptr || !fgets (buf, (int) sizeof (buf), fptr)
1038 || strncmp (buf, SP_GROUP_HEADER, strlen (SP_GROUP_HEADER)))
1039 {
1040 // it's not an experiment group
1041 new_path = dbe_strdup (path);
1042 new_path = canonical_path (new_path);
1043 exp_list->append (new_path);
1044 }
1045 else
1046 {
1047 // it is an experiment group, read the list to get them all
1048 while (fgets (buf, (int) sizeof (buf), fptr))
1049 {
1050 if ((*buf != '#') && (sscanf (buf, NTXT ("%s"), name) == 1))
1051 {
1052 new_path = dbe_strdup (name);
1053 new_path = canonical_path (new_path);
1054 exp_list->append (new_path);
1055 }
1056 }
1057 }
1058 if (fptr)
1059 fclose (fptr);
1060 return exp_list;
1061 }
1062
1063 #define GET_INT_VAL(v, s, len) \
1064 for (v = len = 0; isdigit(*s); s++, len++) { v = v * 10 + (*s -'0'); }
1065
1066 static int
1067 dir_name_cmp (const void *a, const void *b)
1068 {
1069 char *s1 = *((char **) a);
1070 char *s2 = *((char **) b);
1071 while (*s1)
1072 {
1073 if (isdigit (*s1) && isdigit (*s2))
1074 {
1075 int v1, v2, len1, len2;
1076 GET_INT_VAL (v1, s1, len1);
1077 GET_INT_VAL (v2, s2, len2);
1078 if (v1 != v2)
1079 return v1 - v2;
1080 if (len1 != len2)
1081 return len2 - len1;
1082 continue;
1083 }
1084 if (*s1 != *s2)
1085 break;
1086 s1++;
1087 s2++;
1088 }
1089 return *s1 - *s2;
1090 }
1091
1092 static int
1093 read_experiment_data_in_parallel (void *arg)
1094 {
1095 exp_ctx *ctx = (exp_ctx *) arg;
1096 Experiment *dexp = ctx->exp;
1097 bool read_ahead = ctx->read_ahead;
1098 dexp->read_experiment_data (read_ahead);
1099 free (ctx);
1100 return 0;
1101 }
1102
1103 void
1104 DbeSession::open_experiment (Experiment *exp, char *path)
1105 {
1106 exp->open (path);
1107 if (exp->get_status () != Experiment::FAILURE)
1108 exp->read_experiment_data (false);
1109 exp->open_epilogue ();
1110
1111 // Update all DbeViews
1112 for (int i = 0, sz = views->size (); i < sz; i++)
1113 {
1114 DbeView *dbev = views->fetch (i);
1115 dbev->add_experiment (exp->getExpIdx (), true);
1116 }
1117
1118 if (exp->get_status () == Experiment::FAILURE)
1119 {
1120 check_tab_avail ();
1121 return;
1122 }
1123
1124 char *discard_tiny = getenv (NTXT ("SP_ANALYZER_DISCARD_TINY_EXPERIMENTS"));
1125 int user_specified_tiny_threshold = DEFAULT_TINY_THRESHOLD; // in milliseconds
1126 if (discard_tiny != NULL)
1127 {
1128 user_specified_tiny_threshold = (atoi (discard_tiny));
1129 if (user_specified_tiny_threshold < 0)
1130 user_specified_tiny_threshold = DEFAULT_TINY_THRESHOLD;
1131 }
1132
1133 // Open descendant experiments
1134 DIR *exp_dir = opendir (path);
1135 if (exp_dir == NULL)
1136 {
1137 check_tab_avail ();
1138 return;
1139 }
1140
1141 Vector<char*> *exp_names = new Vector<char*>();
1142 struct dirent *entry = NULL;
1143 while ((entry = readdir (exp_dir)) != NULL)
1144 {
1145 if (entry->d_name[0] != '_')
1146 continue;
1147 size_t len = strlen (entry->d_name);
1148 if (len < 3 || strcmp (entry->d_name + len - 3, NTXT (".er")) != 0)
1149 continue;
1150 exp_names->append (dbe_strdup (entry->d_name));
1151 }
1152 closedir (exp_dir);
1153 exp_names->sort (dir_name_cmp);
1154 Experiment **t_exp_list = new Experiment *[exp_names->size ()];
1155 int nsubexps = 0;
1156
1157 for (int j = 0, jsz = exp_names->size (); j < jsz; j++)
1158 {
1159 t_exp_list[j] = NULL;
1160
1161 char *lineage_name = exp_names->fetch (j);
1162 struct stat64 sbuf;
1163 char *dpath = dbe_sprintf (NTXT ("%s/%s"), path, lineage_name);
1164
1165 // look for experiments with no profile collected
1166 if (user_specified_tiny_threshold == DEFAULT_TINY_THRESHOLD)
1167 {
1168 char *frinfoname = dbe_sprintf (NTXT ("%s/%s"), dpath, "data." SP_FRINFO_FILE);
1169 int st = dbe_stat (frinfoname, &sbuf);
1170 free (frinfoname);
1171 if (st == 0)
1172 {
1173 // if no profile/trace data do not process this experiment any further
1174 if (sbuf.st_size == 0)
1175 {
1176 free (dpath);
1177 continue;
1178 }
1179 }
1180 }
1181 else
1182 { // check if dpath is a directory
1183 if (dbe_stat (dpath, &sbuf) != 0)
1184 {
1185 free (dpath);
1186 continue;
1187 }
1188 else if (!S_ISDIR (sbuf.st_mode))
1189 {
1190 free (dpath);
1191 continue;
1192 }
1193 }
1194 size_t lineage_name_len = strlen (lineage_name);
1195 lineage_name[lineage_name_len - 3] = 0; /* remove .er */
1196 Experiment *dexp = new Experiment ();
1197 dexp->founder_exp = exp;
1198 if (user_specified_tiny_threshold > DEFAULT_TINY_THRESHOLD)
1199 {
1200 dexp->setTinyThreshold (user_specified_tiny_threshold);
1201 dexp->open (dpath);
1202 if (dexp->isDiscardedTinyExperiment ())
1203 {
1204 delete dexp;
1205 free (dpath);
1206 continue;
1207 }
1208 }
1209 else
1210 dexp->open (dpath);
1211 append (dexp);
1212 t_exp_list[j] = dexp;
1213 nsubexps++;
1214 dexp->set_clock (exp->clock);
1215
1216 // DbeView add_experiment() is split into two parts
1217 // add_subexperiment() is called repeeatedly for
1218 // all sub_experiments, later add_experiment_epilogue() finishes up the task
1219 for (int i = 0, sz = views->size (); i < sz; i++)
1220 {
1221 DbeView *dbev = views->fetch (i);
1222 bool enabled = settings->check_en_desc (lineage_name, dexp->utargname);
1223 dbev->add_subexperiment (dexp->getExpIdx (), enabled);
1224 }
1225 free (dpath);
1226 }
1227
1228 for (int i = 0, sz = views->size (); i < sz; i++)
1229 {
1230 DbeView *dbev = views->fetch (i);
1231 dbev->add_experiment_epilogue ();
1232 }
1233
1234 DbeThreadPool * threadPool = new DbeThreadPool (-1);
1235 for (int j = 0, jsz = exp_names->size (); j < jsz; j++)
1236 {
1237 if (t_exp_list[j] == NULL) continue;
1238 Experiment *dexp = t_exp_list[j];
1239 exp_ctx *new_ctx = (exp_ctx*) malloc (sizeof (exp_ctx));
1240 new_ctx->path = NULL;
1241 new_ctx->exp = dexp;
1242 new_ctx->ds = this;
1243 new_ctx->read_ahead = true;
1244 DbeQueue *q = new DbeQueue (read_experiment_data_in_parallel, new_ctx);
1245 threadPool->put_queue (q);
1246 }
1247 threadPool->wait_queues ();
1248 delete threadPool;
1249
1250 for (long j = 0, jsz = exp_names->size (); j < jsz; j++)
1251 {
1252 if (t_exp_list[j] == NULL) continue;
1253 Experiment *dexp = t_exp_list[j];
1254 dexp->open_epilogue ();
1255 }
1256 exp_names->destroy ();
1257 delete[] t_exp_list;
1258 delete exp_names;
1259
1260 // update setting for leaklist and dataspace
1261 check_tab_avail ();
1262 }
1263
1264 void
1265 DbeSession::append_mesgs (StringBuilder *sb, char *path, Experiment *exp)
1266 {
1267 if (exp->fetch_errors () != NULL)
1268 {
1269 // yes, there were errors
1270 char *ststr = pr_mesgs (exp->fetch_errors (), NTXT (""), NTXT (""));
1271 sb->append (path);
1272 sb->append (NTXT (": "));
1273 sb->append (ststr);
1274 free (ststr);
1275 }
1276
1277 Emsg *m = exp->fetch_warnings ();
1278 if (m != NULL)
1279 {
1280 sb->append (path);
1281 sb->append (NTXT (": "));
1282 if (!is_interactive ())
1283 sb->append (GTXT ("Experiment has warnings, see header for details\n"));
1284 else
1285 sb->append (GTXT ("Experiment has warnings, see experiment panel for details\n"));
1286 }
1287
1288 // Check for descendant experiments that are not loaded
1289 int num_desc = VecSize (exp->children_exps);
1290 if ((num_desc > 0) && !settings->check_en_desc (NULL, NULL))
1291 {
1292 char *s;
1293 if (!is_interactive ())
1294 s = dbe_sprintf (GTXT ("Has %d descendant(s), use commands controlling selection to load descendant data\n"), num_desc);
1295 else
1296 s = dbe_sprintf (GTXT ("Has %d descendant(s), use filter panel to load descendant data\n"), num_desc);
1297 sb->append (path);
1298 sb->append (NTXT (": "));
1299 sb->append (s);
1300 free (s);
1301 }
1302 }
1303
1304 Experiment *
1305 DbeSession::get_exp (int exp_ind)
1306 {
1307 if (exp_ind < 0 || exp_ind >= exps->size ())
1308 return NULL;
1309 Experiment *exp = exps->fetch (exp_ind);
1310 exp->setExpIdx (exp_ind);
1311 return exp;
1312 }
1313
1314 Vector<Vector<char*>*> *
1315 DbeSession::getExperimensGroups ()
1316 {
1317 if (dbeSession->expGroups == NULL || dbeSession->expGroups->size () == 0)
1318 return NULL;
1319 bool compare_mode = expGroups->size () > 1;
1320 Vector<Vector<char*>*> *groups = new Vector<Vector<char*>*> (
1321 compare_mode ? expGroups->size () : 1);
1322 for (int i = 0; i < expGroups->size (); i++)
1323 {
1324 ExpGroup *grp = expGroups->fetch (i);
1325 Vector<Experiment*> *founders = grp->get_founders ();
1326 if (founders && founders->size () != 0)
1327 {
1328 Vector<char *> *names = new Vector<char*> (founders->size ());
1329 for (int j = 0; j < founders->size (); j++)
1330 {
1331 Experiment *exp = founders->fetch (j);
1332 names->append (dbe_strdup (exp->get_expt_name ()));
1333 }
1334 if (compare_mode || groups->size () == 0)
1335 groups->append (names);
1336 else
1337 groups->fetch (0)->addAll (names);
1338 }
1339 delete founders;
1340 }
1341 return groups;
1342 }
1343
1344 char *
1345 DbeSession::setExperimentsGroups (Vector<Vector<char*>*> *groups)
1346 {
1347 StringBuilder sb;
1348 for (int i = 0; i < groups->size (); i++)
1349 {
1350 Vector<char *> *names = groups->fetch (i);
1351 ExpGroup *grp;
1352 if (names->size () == 1)
1353 grp = new ExpGroup (names->fetch (0));
1354 else
1355 {
1356 char *nm = dbe_sprintf (GTXT ("Group %d"), i + 1);
1357 grp = new ExpGroup (nm);
1358 free (nm);
1359 }
1360 expGroups->append (grp);
1361 grp->groupId = expGroups->size ();
1362
1363 for (int j = 0; j < names->size (); j++)
1364 {
1365 char *path = names->fetch (j);
1366 size_t len = strlen (path);
1367 if ((len > 4) && !strcmp (path + len - 4, NTXT (".erg")))
1368 {
1369 Vector<char*> *lst = get_group_or_expt (path);
1370 for (int j1 = 0; j1 < lst->size (); j1++)
1371 {
1372 Experiment *exp = new Experiment ();
1373 append (exp);
1374 open_experiment (exp, lst->get (j1));
1375 if (exp->get_status () == Experiment::FAILURE)
1376 append_mesgs (&sb, path, exp);
1377 }
1378 lst->destroy ();
1379 delete lst;
1380 }
1381 else
1382 {
1383 Experiment *exp = new Experiment ();
1384 append (exp);
1385 open_experiment (exp, path);
1386 if (exp->get_status () == Experiment::FAILURE)
1387 append_mesgs (&sb, path, exp);
1388 }
1389 }
1390 }
1391
1392 for (int i = 0, sz = views->size (); i < sz; i++)
1393 {
1394 DbeView *dbev = views->fetch (i);
1395 dbev->update_advanced_filter ();
1396 int cmp = dbev->get_settings ()->get_compare_mode ();
1397 dbev->set_compare_mode (CMP_DISABLE);
1398 dbev->set_compare_mode (cmp);
1399 }
1400 return sb.length () == 0 ? NULL : sb.toString ();
1401 }
1402
1403 char *
1404 DbeSession::drop_experiment (int exp_ind)
1405 {
1406 DbeView *dbev;
1407 int index;
1408 Experiment *exp2;
1409
1410 status_ompavail = -1;
1411 Experiment *exp = exps->fetch (exp_ind);
1412
1413 // If this is a sub experiment, don't do it
1414 if (exp->founder_exp != NULL) // this is a sub experiment; don't do it
1415 return (dbe_strdup (GTXT ("Can not drop subexperiments")));
1416
1417 if (VecSize (exp->children_exps) > 0)
1418 for (;;)
1419 {
1420 // search the list of experiments to find all that have this one as founder
1421 bool found = false;
1422 Vec_loop (Experiment*, exps, index, exp2)
1423 {
1424 if (exp2->founder_exp == exp)
1425 {
1426 exp2->founder_exp = NULL;
1427 drop_experiment (index);
1428 found = true;
1429 break;
1430 }
1431 }
1432 if (found == false)
1433 break;
1434 }
1435
1436 // then proceed to finish the drop
1437 Vec_loop (DbeView*, views, index, dbev)
1438 {
1439 dbev->drop_experiment (exp_ind);
1440 }
1441
1442 int old_cnt = expGroups->size ();
1443 for (int i = 0; i < old_cnt; i++)
1444 {
1445 ExpGroup *gr = expGroups->fetch (i);
1446 if (gr->groupId == exp->groupId)
1447 {
1448 gr->drop_experiment (exp);
1449 if ((gr->founder == NULL) && (gr->exps->size () == 0))
1450 {
1451 delete gr;
1452 expGroups->remove (i);
1453 }
1454 break;
1455 }
1456 }
1457 delete exps->remove (exp_ind);
1458 if (old_cnt != expGroups->size ())
1459 {
1460 for (int i = 0, sz = expGroups->size (); i < sz; i++)
1461 {
1462 ExpGroup *gr = expGroups->fetch (i);
1463 gr->groupId = i + 1;
1464 Vector<Experiment*> *expList = gr->exps;
1465 for (int i1 = 0, sz1 = expList->size (); i1 < sz1; i1++)
1466 expList->fetch (i1)->groupId = gr->groupId;
1467 }
1468 for (int i = 0, sz = views->size (); i < sz; i++)
1469 {
1470 dbev = views->fetch (i);
1471 int cmp = dbev->get_compare_mode ();
1472 dbev->set_compare_mode (CMP_DISABLE);
1473 dbev->set_compare_mode (cmp);
1474 }
1475 }
1476 check_tab_avail (); // update tab availability
1477 return NULL;
1478 }
1479
1480 int
1481 DbeSession::find_experiment (char *path)
1482 {
1483 Experiment *exp;
1484 int index;
1485 Vec_loop (Experiment*, exps, index, exp)
1486 {
1487 if (strcmp (exp->get_expt_name (), path) == 0)
1488 return exp->getExpIdx ();
1489 }
1490 return -1;
1491 }
1492
1493 LoadObject *
1494 DbeSession::createLoadObject (const char *nm, int64_t cksum)
1495 {
1496 return loadObjMap->sync_create_item (nm, cksum);
1497 }
1498
1499 LoadObject *
1500 DbeSession::createLoadObject (const char *nm, const char *runTimePath, DbeFile *df)
1501 {
1502 return loadObjMap->sync_create_item (nm, runTimePath, df);
1503 }
1504
1505 void
1506 DbeSession::append (LoadObject *lobj)
1507 {
1508 Histable *obj = lobj; // workaround for a C++ problem
1509 objs->append (obj);
1510 lobj->id = objs->size () - 1;
1511 lobjs->append (lobj);
1512 lobj->seg_idx = lobjs->size () - 1;
1513 char *loname = lobj->get_pathname ();
1514 dbeFiles->put (loname, lobj->dbeFile);
1515 }
1516
1517 DbeJarFile *
1518 DbeSession::get_JarFile (const char *name)
1519 {
1520 DbeJarFile *jf = dbeJarFiles->get (name);
1521 if (jf == NULL)
1522 {
1523 jf = new DbeJarFile (name);
1524 dbeJarFiles->put (name, jf);
1525 }
1526 return jf;
1527 }
1528
1529 Module *
1530 DbeSession::createModule (LoadObject *lo, const char *nm)
1531 {
1532 Module *mod = new Module ();
1533 Histable *obj = mod; // workaround for a C++ problem
1534 objs->append (obj);
1535 mod->id = objs->size () - 1;
1536 mod->loadobject = lo;
1537 mod->set_name (dbe_strdup (nm ? nm : localized_SP_UNKNOWN_NAME));
1538 lo->seg_modules->append (mod);
1539 return mod;
1540 }
1541
1542 Module *
1543 DbeSession::createUnknownModule (LoadObject *lo)
1544 {
1545 Module *mod = createModule (lo, localized_SP_UNKNOWN_NAME);
1546 mod->flags |= MOD_FLAG_UNKNOWN;
1547 mod->set_file_name (dbe_strdup (localized_SP_UNKNOWN_NAME));
1548 return mod;
1549 }
1550
1551 SourceFile *
1552 DbeSession::createSourceFile (const char *_path)
1553 {
1554 char *path = (char *) _path;
1555 if (strncmp (path, NTXT ("./"), 2) == 0)
1556 path += 2;
1557 SourceFile *source = sourcesMap->get (path);
1558 if (source == NULL)
1559 {
1560 source = new SourceFile (path);
1561 (void) sourcesMap->put (path, source);
1562 append (source);
1563 }
1564 return source;
1565 }
1566
1567 Function *
1568 DbeSession::createFunction ()
1569 {
1570 Function *func = new Function (objs->size ());
1571 Histable *obj = func; // workaround for a C++ problem
1572 objs->append (obj);
1573 return func;
1574 }
1575
1576 JMethod *
1577 DbeSession::createJMethod ()
1578 {
1579 JMethod *jmthd = new JMethod (objs->size ());
1580 Histable *obj = jmthd; // workaround for a C++ problem
1581 objs->append (obj);
1582 return jmthd;
1583 }
1584
1585 Module *
1586 DbeSession::createClassFile (char *className)
1587 {
1588 ClassFile *cls = new ClassFile ();
1589 cls->set_name (className);
1590 char *clpath = cls->get_java_file_name (className, true);
1591 cls->dbeFile = getDbeFile (clpath, DbeFile::F_JAVACLASS);
1592 free (clpath);
1593 Histable *obj = cls; // workaround for a C++ problem
1594 objs->append (obj);
1595 cls->id = objs->size () - 1;
1596 return cls;
1597 }
1598
1599 Histable *
1600 DbeSession::createHistObject (Histable::Type type)
1601 {
1602 switch (type)
1603 {
1604 case Histable::DOBJECT:
1605 {
1606 DataObject *dataobj = new DataObject ();
1607 dobjs->append (dataobj);
1608 dataobj->id = dobjs->size () - 1;
1609 return dataobj;
1610 }
1611 default:
1612 assert (0);
1613 }
1614 return NULL;
1615 }
1616
1617 DataObject *
1618 DbeSession::createDataObject ()
1619 {
1620 DataObject *dataobj = new DataObject ();
1621 dobjs->append (dataobj);
1622 dataobj->id = dobjs->size () - 1;
1623 return dataobj;
1624 }
1625
1626 DataObject *
1627 DbeSession::createDataObject (DataObject *dobj, DataObject *parent)
1628 {
1629 DataObject *dataobj = new DataObject ();
1630 dataobj->size = dobj->size;
1631 dataobj->offset = dobj->offset;
1632 dataobj->parent = parent;
1633 dataobj->set_dobjname (dobj->get_typename (), dobj->get_instname ());
1634 dobjs->append (dataobj);
1635 dataobj->id = dobjs->size () - 1;
1636 return dataobj;
1637 }
1638
1639 DataObject *
1640 DbeSession::createMasterDataObject (DataObject *dobj)
1641 {
1642 DataObject *parent = NULL;
1643 if (dobj->parent)
1644 { // define master parent first
1645 parent = find_dobj_master (dobj->parent);
1646 if (!parent)
1647 { // clone master from this dataobject parent
1648 parent = createDataObject (dobj->parent);
1649 parent->scope = NULL; // master is scope-less
1650 Dprintf (DEBUG_DATAOBJ,
1651 "Master DataObject(%llu) cloned from (%llu) %s\n",
1652 (ull_t) parent->id, (ull_t) dobj->parent->id,
1653 dobj->parent->get_name ());
1654 // clone master DataObject elements
1655 Vector<DataObject*> *delem = get_dobj_elements (dobj->parent);
1656 int element_index = 0;
1657 DataObject *element = NULL;
1658 Vec_loop (DataObject*, delem, element_index, element)
1659 {
1660 DataObject *master_element = createDataObject (element, parent);
1661 master_element->scope = NULL; // master is scope-less
1662 Dprintf (DEBUG_DATAOBJ,
1663 "Member DataObject(%llu) cloned from (%llu) %s\n",
1664 (ull_t) master_element->id, (ull_t) element->id,
1665 element->get_name ());
1666 }
1667 }
1668 else
1669 Dprintf (DEBUG_DATAOBJ, "Master DataObject(%llu) clone found (%llu) %s\n",
1670 (ull_t) parent->id, (ull_t) dobj->parent->id,
1671 dobj->parent->get_name ());
1672 }
1673
1674 DataObject *master = find_dobj_master (dobj);
1675 if (!master)
1676 { // clone master from this dataobject
1677 master = createDataObject (dobj, parent);
1678 master->scope = NULL; // master is scope-less
1679 Dprintf (DEBUG_DATAOBJ, "Master DataObject(%llu) cloned from (%llu) %s\n",
1680 (ull_t) master->id, (ull_t) dobj->id, dobj->get_name ());
1681 }
1682 else
1683 Dprintf (DEBUG_DATAOBJ, "Master DataObject(%llu) clone found (%llu) %s\n",
1684 (ull_t) master->id, (ull_t) dobj->id, dobj->get_name ());
1685 return master;
1686 }
1687
1688 void
1689 DbeSession::insert_metric (BaseMetric *mtr, Vector<BaseMetric*> *mlist)
1690 {
1691 if ((mtr->get_flavors () & Metric::STATIC) == 0)
1692 {
1693 // insert in front of the first STATIC
1694 for (int i = 0, mlist_sz = mlist->size (); i < mlist_sz; i++)
1695 {
1696 BaseMetric *m = mlist->fetch (i);
1697 if (m->get_flavors () & Metric::STATIC)
1698 {
1699 mlist->insert (i, mtr);
1700 return;
1701 }
1702 }
1703 }
1704 mlist->append (mtr);
1705 }
1706
1707 BaseMetricTreeNode*
1708 DbeSession::get_reg_metrics_tree ()
1709 {
1710 if (reg_metrics_tree == NULL)
1711 // Can't init earlier because BaseMetric() requires DbeSession::ql_parse
1712 reg_metrics_tree = new BaseMetricTreeNode ();
1713 return reg_metrics_tree;
1714 }
1715
1716 void
1717 DbeSession::update_metric_tree (BaseMetric *m)
1718 {
1719 get_reg_metrics_tree ()->register_metric (m);
1720 }
1721
1722 BaseMetric *
1723 DbeSession::register_metric_expr (BaseMetric::Type type, char *cmd, char *expr_spec)
1724 {
1725 BaseMetric *m = find_metric (type, cmd, expr_spec);
1726 if (m)
1727 return m;
1728 BaseMetric *bm = find_metric (type, cmd, NULL); // clone this version
1729 m = new BaseMetric (*bm);
1730 m->set_expr_spec (expr_spec);
1731 insert_metric (m, reg_metrics);
1732 return m;
1733 }
1734
1735 BaseMetric *
1736 DbeSession::register_metric (BaseMetric::Type type)
1737 {
1738 BaseMetric *m = find_metric (type, NULL, NULL);
1739 if (m)
1740 return m;
1741 m = new BaseMetric (type);
1742 insert_metric (m, reg_metrics);
1743 update_metric_tree (m);
1744 return m;
1745 }
1746
1747 BaseMetric *
1748 DbeSession::register_metric (Hwcentry *ctr, const char* aux, const char* username)
1749 {
1750 BaseMetric *m = find_metric (BaseMetric::HWCNTR, aux, NULL);
1751 if (m)
1752 // That may be a problem when metrics aren't an exact match.
1753 // For example, memoryspace is disabled in one experiment and not in another.
1754 return m;
1755 if (ctr->timecvt)
1756 {
1757 char *time_cmd = dbe_sprintf (NTXT ("t%s"), aux);
1758 char *time_username = dbe_sprintf (GTXT ("%s Time"),
1759 ctr->metric ? ctr->metric :
1760 (ctr->name ? ctr->name : ctr->int_name));
1761 BaseMetric *m1;
1762 if (ipc_mode)
1763 {
1764 // Two visible metrics are presented in GUI
1765 m1 = new BaseMetric (ctr, aux, time_cmd, time_username, VAL_TIMEVAL);
1766 insert_metric (m1, reg_metrics);
1767 update_metric_tree (m1);
1768 m = new BaseMetric (ctr, aux, username, VAL_VALUE, m1);
1769 }
1770 else
1771 {
1772 // Only one visible metric is presented in er_print
1773 m1 = new BaseMetric (ctr, aux, time_cmd, time_username, VAL_TIMEVAL | VAL_INTERNAL);
1774 insert_metric (m1, reg_metrics);
1775 m = new BaseMetric (ctr, aux, username, VAL_TIMEVAL | VAL_VALUE, m1);
1776 }
1777 free (time_cmd);
1778 free (time_username);
1779 }
1780 else
1781 m = new BaseMetric (ctr, aux, username, VAL_VALUE);
1782 insert_metric (m, reg_metrics);
1783 update_metric_tree (m);
1784 return m;
1785 }
1786
1787 BaseMetric *
1788 DbeSession::register_metric (char *name, char *username, char *_def)
1789 {
1790 BaseMetric *m = find_metric (BaseMetric::DERIVED, name, NULL);
1791 if (m)
1792 return m;
1793 Definition *p = Definition::add_definition (_def);
1794 if (p == NULL)
1795 return NULL;
1796 m = new BaseMetric (name, username, p);
1797 insert_metric (m, reg_metrics);
1798 update_metric_tree (m);
1799 return m;
1800 }
1801
1802 void
1803 DbeSession::drop_metric (BaseMetric *mtr)
1804 {
1805 Countable *cnt;
1806 int index;
1807
1808 Vec_loop (Countable*, metrics, index, cnt)
1809 {
1810 if (mtr == (BaseMetric *) cnt->item)
1811 {
1812 cnt->ref_count--;
1813 if (cnt->ref_count == 0)
1814 {
1815 // Remove this metric from all views
1816 DbeView *dbev;
1817 int index2;
1818 Vec_loop (DbeView*, views, index2, dbev)
1819 {
1820 dbev->reset_metrics ();
1821 }
1822 delete metrics->remove (index);
1823 delete mtr;
1824 return;
1825 }
1826 }
1827 }
1828 }
1829
1830 BaseMetric *
1831 DbeSession::find_metric (BaseMetric::Type type, const char *cmd, const char *expr_spec)
1832 {
1833 for (int i = 0, sz = reg_metrics->size (); i < sz; i++)
1834 {
1835 BaseMetric *bm = reg_metrics->fetch (i);
1836 if (bm->get_type () == type && dbe_strcmp (bm->get_expr_spec (), expr_spec) == 0)
1837 {
1838 if ((type == BaseMetric::DERIVED || type == BaseMetric::HWCNTR)
1839 && dbe_strcmp (bm->get_cmd (), cmd) != 0)
1840 continue;
1841 return bm;
1842 }
1843 }
1844 return NULL;
1845 }
1846
1847 BaseMetric *
1848 DbeSession::find_base_reg_metric (char * mcmd)
1849 {
1850 for (int i = 0, sz = reg_metrics->size (); i < sz; i++)
1851 {
1852 BaseMetric *bm = reg_metrics->fetch (i);
1853 if (bm->get_expr_spec () != NULL)
1854 continue; // skip compare metrics
1855 if (dbe_strcmp (bm->get_cmd (), mcmd) == 0)
1856 return bm;
1857 }
1858 return NULL;
1859 }
1860
1861 Vector<BaseMetric*> *
1862 DbeSession::get_base_reg_metrics ()
1863 {
1864 Vector<BaseMetric*> *mlist = new Vector<BaseMetric*>;
1865 Vector<BaseMetric*> *ml = get_all_reg_metrics ();
1866 for (int i = 0, sz = ml->size (); i < sz; i++)
1867 {
1868 BaseMetric *m = ml->fetch (i);
1869 if (m->get_expr_spec () == NULL)
1870 mlist->append (m);
1871 }
1872 return mlist;
1873 }
1874
1875 void
1876 DbeSession::check_tab_avail ()
1877 {
1878 DbeView *dbev;
1879 int index;
1880 // tell the views to update their tab lists
1881 Vec_loop (DbeView*, views, index, dbev)
1882 {
1883 dbev->get_settings ()->updateTabAvailability ();
1884 }
1885 }
1886
1887 bool
1888 DbeSession::is_datamode_available ()
1889 {
1890 Experiment *exp;
1891 int index;
1892 Vec_loop (Experiment*, exps, index, exp)
1893 {
1894 if (exp->dataspaceavail)
1895 return true;
1896 }
1897 return false;
1898 }
1899
1900 bool
1901 DbeSession::is_leaklist_available ()
1902 {
1903 Experiment *exp;
1904 int index;
1905 Vec_loop (Experiment*, exps, index, exp)
1906 {
1907 if (exp->leaklistavail)
1908 return true;
1909 }
1910 return false;
1911 }
1912
1913 bool
1914 DbeSession::is_heapdata_available ()
1915 {
1916 Experiment *exp;
1917 int index;
1918 Vec_loop (Experiment*, exps, index, exp)
1919 {
1920 if (exp->heapdataavail)
1921 return true;
1922 }
1923 return false;
1924 }
1925
1926 bool
1927 DbeSession::is_iodata_available ()
1928 {
1929 Experiment *exp;
1930 int index;
1931 Vec_loop (Experiment*, exps, index, exp)
1932 {
1933 if (exp->iodataavail)
1934 return true;
1935 }
1936 return false;
1937 }
1938
1939 bool
1940 DbeSession::is_racelist_available ()
1941 {
1942 Experiment *exp;
1943 int index;
1944 Vec_loop (Experiment*, exps, index, exp)
1945 {
1946 if (exp->racelistavail)
1947 return true;
1948 }
1949 return false;
1950 }
1951
1952 bool
1953 DbeSession::is_deadlocklist_available ()
1954 {
1955 Experiment *exp;
1956 int index;
1957 Vec_loop (Experiment*, exps, index, exp)
1958 {
1959 if (exp->deadlocklistavail)
1960 return true;
1961 }
1962 return false;
1963 }
1964
1965 bool
1966 DbeSession::is_timeline_available ()
1967 {
1968 Experiment *exp;
1969 int index;
1970 Vec_loop (Experiment*, exps, index, exp)
1971 {
1972 if (exp->timelineavail)
1973 return true;
1974 }
1975 return false;
1976 }
1977
1978 bool
1979 DbeSession::is_ifreq_available ()
1980 {
1981 Experiment *exp;
1982 int index;
1983 Vec_loop (Experiment*, exps, index, exp)
1984 {
1985 if (exp->ifreqavail)
1986 return true;
1987 }
1988 return false;
1989 }
1990
1991 bool
1992 DbeSession::is_omp_available ()
1993 {
1994 if (status_ompavail == -1)
1995 {
1996 status_ompavail = 0;
1997 for (int i = 0, sz = exps ? exps->size () : 0; i < sz; i++)
1998 {
1999 Experiment *exp = exps->fetch (i);
2000 if (exp->ompavail)
2001 {
2002 status_ompavail = 1;
2003 break;
2004 }
2005 }
2006 }
2007 return status_ompavail == 1;
2008 }
2009
2010 bool
2011 DbeSession::has_java ()
2012 {
2013 int status_has_java = 0;
2014 for (int i = 0, sz = exps ? exps->size () : 0; i < sz; i++)
2015 {
2016 Experiment *exp = exps->fetch (i);
2017 if (exp->has_java)
2018 {
2019 status_has_java = 1;
2020 break;
2021 }
2022 }
2023 return status_has_java == 1;
2024 }
2025
2026 bool
2027 DbeSession::has_ompavail ()
2028 {
2029 int status_has_ompavail = 0;
2030 for (int i = 0, sz = exps ? exps->size () : 0; i < sz; i++)
2031 {
2032 Experiment *exp = exps->fetch (i);
2033 if (exp->ompavail)
2034 {
2035 status_has_ompavail = 1;
2036 break;
2037 }
2038 }
2039 return status_has_ompavail == 1;
2040 }
2041
2042 int
2043 DbeSession::get_clock (int whichexp)
2044 {
2045 // XXXX clock frequency should be an attribute of each CPU,
2046 // XXX and not a property of the session
2047 // if whichexp is -1, pick the first exp that has a clock
2048 // otherwise return the clock from the numbered experiment
2049 Experiment *exp;
2050 if (whichexp != -1)
2051 {
2052 exp = get_exp (whichexp);
2053 if (exp != NULL)
2054 return exp->clock;
2055 return 0;
2056 }
2057 int n = nexps ();
2058 for (int i = 0; i < n; i++)
2059 {
2060 exp = get_exp (i);
2061 if (exp != NULL && exp->clock != 0)
2062 return exp->clock;
2063 }
2064 return 0;
2065 }
2066
2067 LoadObject *
2068 DbeSession::find_lobj_by_name (const char *lobj_name, int64_t cksum)
2069 {
2070 return loadObjMap->get (lobj_name, cksum);
2071 }
2072
2073 static unsigned
2074 hash (char *s)
2075 {
2076 unsigned res = 0;
2077 for (int i = 0; i < 64 && *s; i++)
2078 res = res * 13 + *s++;
2079 return res;
2080 }
2081
2082 // This method is introduced to fix performance
2083 // problems with the data space profiling in the
2084 // current release. A better design is desired.
2085 void
2086 DbeSession::dobj_updateHT (DataObject *dobj)
2087 {
2088 unsigned index = hash (dobj->get_unannotated_name ()) % HTableSize;
2089 List *list = new List;
2090 list->val = (void*) dobj;
2091 list->next = dnameHTable[index];
2092 dnameHTable[index] = list;
2093 }
2094
2095 DataObject *
2096 DbeSession::find_dobj_by_name (char *dobj_name)
2097 {
2098 unsigned index = hash (dobj_name) % HTableSize;
2099 List *list = dnameHTable[index];
2100 for (; list; list = list->next)
2101 {
2102 DataObject *d = (DataObject*) list->val;
2103 if (strcmp (d->get_unannotated_name (), dobj_name) == 0)
2104 return d;
2105 }
2106 return (DataObject *) NULL;
2107 }
2108
2109 DataObject *
2110 DbeSession::find_dobj_match (DataObject *dobj)
2111 {
2112 char *dobj_name = dobj->get_unannotated_name ();
2113 unsigned index = hash (dobj_name) % HTableSize;
2114 List *list = dnameHTable[index];
2115 for (; list; list = list->next)
2116 {
2117 DataObject *d = (DataObject*) list->val;
2118 if (strcmp (d->get_unannotated_name (), dobj_name) == 0
2119 && d->size == dobj->size && d->offset == dobj->offset
2120 && d->scope == dobj->scope)
2121 return d;
2122 }
2123 return (DataObject *) NULL;
2124 }
2125
2126 DataObject *
2127 DbeSession::find_dobj_master (DataObject *dobj)
2128 {
2129 char *dobj_name = dobj->get_unannotated_name ();
2130 unsigned index = hash (dobj_name) % HTableSize;
2131 List *list = dnameHTable[index];
2132 for (; list; list = list->next)
2133 {
2134 DataObject *d = (DataObject*) list->val;
2135 // XXXX should parent also match?
2136 if (strcmp (d->get_unannotated_name (), dobj_name) == 0
2137 && d->size == dobj->size && d->offset == dobj->offset
2138 && d->master == NULL && d->scope == NULL)
2139 return d;
2140 }
2141 return (DataObject *) NULL;
2142 }
2143
2144 Vector<DataObject*>*
2145 DbeSession::get_dobj_elements (DataObject *dobj)
2146 {
2147 DataObject *d;
2148 int index;
2149 Vector<DataObject*> *elements = new Vector<DataObject*>;
2150 if (dobj == d_total)
2151 return elements;
2152 Vec_loop (DataObject*, dobjs, index, d)
2153 {
2154 if (d->get_parent () && d->get_parent () == dobj)
2155 elements->append (d);
2156 }
2157 return elements;
2158 }
2159
2160 Vector<LoadObject*>*
2161 DbeSession::get_text_segments ()
2162 {
2163 LoadObject *lo;
2164 int index;
2165 Vector<LoadObject*> *tlobjs = new Vector<LoadObject*>;
2166 Vec_loop (LoadObject*, lobjs, index, lo)
2167 {
2168 if (lo->type == LoadObject::SEG_TEXT)
2169 tlobjs->append (lo);
2170 }
2171 return tlobjs;
2172 }
2173
2174 static long long
2175 getNumber (const char *s, char * &last)
2176 {
2177 long long val;
2178 char *sp;
2179 errno = 0;
2180 val = strtoll (s, &sp, 0);
2181 if (errno == EINVAL)
2182 last = NULL;
2183 else
2184 {
2185 while (isspace (*sp))
2186 sp++;
2187 last = sp;
2188 }
2189 return (val);
2190 }
2191
2192 bool
2193 DbeSession::find_obj (FILE *dis_file, FILE *inp_file, Histable *&obj,
2194 char *name, const char *sel, Histable::Type type, bool xdefault)
2195 {
2196 Vector<Histable*> *obj_lst;
2197 int which = -1;
2198 char *last = NULL;
2199 if (type != Histable::FUNCTION && sel)
2200 {
2201 // check that a number has been provided
2202 which = (int) getNumber (sel, last);
2203 if (last == NULL || *last != '\0')
2204 {
2205 fprintf (stderr, GTXT ("Error: Invalid number entered: %s\n"), sel);
2206 sel = NULL;
2207 which = 0;
2208 }
2209 which--;
2210 }
2211 obj_lst = new Vector<Histable*>;
2212 switch (type)
2213 {
2214 case Histable::FUNCTION:
2215 obj = map_NametoFunction (name, obj_lst, sel);
2216 break;
2217 case Histable::MODULE:
2218 obj = map_NametoModule (name, obj_lst, which);
2219 break;
2220 case Histable::LOADOBJECT:
2221 obj = map_NametoLoadObject (name, obj_lst, which);
2222 break;
2223 case Histable::DOBJECT:
2224 obj = map_NametoDataObject (name, obj_lst, which);
2225 break;
2226 default:
2227 abort (); // unexpected Histable!
2228 }
2229
2230 if ((obj == NULL) && (obj_lst->size () > 0))
2231 {
2232 if (obj_lst->size () == 1)
2233 which = 0;
2234 else
2235 {
2236 if (sel && (which < 0 || which >= obj_lst->size ()))
2237 fprintf (stderr, GTXT ("Error: Invalid number entered: %s\n"), sel);
2238 if (xdefault)
2239 {
2240 fprintf (stderr, GTXT ("Default selection \"1\" made\n"));
2241 which = 0;
2242 }
2243 else
2244 {
2245 which = ask_which (dis_file, inp_file, obj_lst, name);
2246 if (which == -1)
2247 {
2248 delete obj_lst;
2249 return false;
2250 }
2251 }
2252 }
2253 obj = obj_lst->fetch (which);
2254 }
2255 delete obj_lst;
2256 return true;
2257 }
2258
2259 int
2260 DbeSession::ask_which (FILE *dis_file, FILE *inp_file,
2261 Vector<Histable*> *list, char *name)
2262 {
2263 Histable *hitem;
2264 Function *func;
2265 Module *module;
2266 int which, index, index1;
2267 char *item_name, *lo_name, *fname, *last;
2268 char buf[BUFSIZ];
2269 for (;;)
2270 {
2271 fprintf (dis_file, GTXT ("Available name list:\n"));
2272 fprintf (dis_file, GTXT ("%8d) Cancel\n"), 0);
2273 Vec_loop (Histable*, list, index, hitem)
2274 {
2275 index1 = index + 1;
2276 item_name = hitem->get_name ();
2277 switch (hitem->get_type ())
2278 {
2279 case Histable::FUNCTION:
2280 func = (Function *) hitem;
2281 module = func->module;
2282
2283 // id == -1 indicates er_src invocation
2284 if (module == NULL || (module->lang_code == Sp_lang_java
2285 && module->loadobject->id == -1))
2286 fprintf (dis_file, NTXT ("%8d) %s\n"), index1, item_name);
2287 else
2288 {
2289 lo_name = module->loadobject->get_pathname ();
2290 fname = (module->file_name && *module->file_name) ?
2291 module->file_name : module->get_name ();
2292 if (fname && *fname)
2293 fprintf (dis_file, NTXT ("%8d) %s %s:0x%llx (%s)\n"), index1,
2294 item_name, lo_name, (ull_t) func->img_offset, fname);
2295 else
2296 fprintf (dis_file, NTXT ("%8d) %s %s:0x%llx\n"), index1,
2297 item_name, lo_name, (ull_t) func->img_offset);
2298 }
2299 break;
2300 case Histable::MODULE:
2301 module = (Module *) hitem;
2302 lo_name = module->loadobject->get_pathname ();
2303 if (name[strlen (name) - 1] ==
2304 module->file_name[strlen (module->file_name) - 1])
2305 fprintf (dis_file, NTXT ("%8d) %s(%s)\n"), index1,
2306 module->file_name, lo_name);
2307 else
2308 fprintf (dis_file, NTXT ("%8d) %s(%s)\n"), index1, item_name,
2309 lo_name);
2310 break;
2311 default:
2312 fprintf (dis_file, NTXT ("%8d) %s\n"), index1, item_name);
2313 break;
2314 }
2315 }
2316 if (inp_file != stdin)
2317 return -1;
2318 fprintf (dis_file, GTXT ("Enter selection: "));
2319 if (fgets (buf, (int) sizeof (buf), inp_file) == NULL)
2320 {
2321 fprintf (stderr, GTXT ("Error: Invalid number entered:\n"));
2322 return -1;
2323 }
2324 which = (int) getNumber (buf, last);
2325 if (last && *last == '\0')
2326 if (which >= 0 && which <= list->size ())
2327 return which - 1;
2328 fprintf (stderr, GTXT ("Error: Invalid number entered: %s\n"), buf);
2329 }
2330 }
2331
2332 static bool
2333 match_basename (char *name, char *full_name, int len = -1)
2334 {
2335 if (full_name == NULL)
2336 return false;
2337 if (!strchr (name, '/'))
2338 full_name = get_basename (full_name);
2339 if (len == -1)
2340 return streq (name, full_name);
2341 return strncmp (name, full_name, len) == 0;
2342 }
2343
2344 LoadObject *
2345 DbeSession::map_NametoLoadObject (char *name, Vector<Histable*> *list, int which)
2346 {
2347 // Search the tree to find the first module whose module name
2348 // matches "name" or whose source file name matches "name"
2349 // Issues: is the name a pathname, or a base name?
2350 // Should we look at suffix to disambiguate?
2351 LoadObject *loitem;
2352 int index;
2353 Vec_loop (LoadObject*, lobjs, index, loitem)
2354 {
2355 // try pathname first
2356 // if failed, try object name next
2357 if (match_basename (name, loitem->get_pathname ()) ||
2358 match_basename (name, loitem->get_name ()))
2359 {
2360 if (which == list->size ())
2361 return loitem;
2362 list->append (loitem);
2363 }
2364 }
2365 return (LoadObject *) NULL;
2366 }
2367
2368 Module *
2369 DbeSession::map_NametoModule (char *name, Vector<Histable*> *list, int which)
2370 {
2371 // Search the tree to find the first loadobject whose loadobject name
2372 // matches "name".
2373
2374 // Issues: is the name a pathname, or a base name?
2375 // Should we look at suffix to disambiguate?
2376 LoadObject *loitem;
2377 Module *mitem;
2378 int index1, index2;
2379 Vec_loop (LoadObject*, lobjs, index1, loitem)
2380 {
2381 Vec_loop (Module*, loitem->seg_modules, index2, mitem)
2382 {
2383 // try source name first
2384 // if failed, try object name next
2385 if (match_basename (name, mitem->file_name) ||
2386 match_basename (name, mitem->get_name ()))
2387 {
2388 if (which == list->size ())
2389 return mitem;
2390 list->append (mitem);
2391 }
2392 }
2393 }
2394 return (Module *) NULL;
2395 }
2396
2397 Function *
2398 DbeSession::map_NametoFunction (char *name, Vector<Histable*> *list,
2399 const char *sel)
2400 {
2401 // Search the tree to find the first function whose
2402 // name matches "name".
2403 // Issues: is the name a full name, or a short name?
2404 // Is it a demangled name? If so, what about spaces
2405 // within the name?
2406 // Is there a way to return all names that match?
2407 // How can the user specify a particular function of that name?
2408 LoadObject *loitem;
2409 Function *fitem, *main_func = NULL;
2410 Module *mitem, *main_mod = NULL;
2411 int index1, index2, index3, which = -1;
2412 if (sel)
2413 {
2414 char *last = NULL;
2415 if (*sel == '@')
2416 { // 'sel' is "@seg_num:address"
2417 which = (int) getNumber (sel + 1, last);
2418 if (last == NULL || *last != ':' || (which < 0) || (which >= lobjs->size ()))
2419 {
2420 fprintf (stderr, GTXT ("Error: Invalid number entered: %s\n"), sel);
2421 return NULL;
2422 }
2423 uint64_t address = getNumber (last + 1, last);
2424 if (last == NULL || *last != '\0')
2425 {
2426 fprintf (stderr, GTXT ("Error: Invalid number entered: %s\n"), sel);
2427 return NULL;
2428 }
2429 loitem = lobjs->fetch (which);
2430 Vec_loop (Module*, loitem->seg_modules, index2, mitem)
2431 {
2432 Vec_loop (Function*, mitem->functions, index3, fitem)
2433 {
2434 if (address == fitem->img_offset && match_FName (name, fitem))
2435 return fitem;
2436 }
2437 }
2438 return NULL;
2439 }
2440
2441 which = (int) getNumber (sel, last);
2442 if (last == NULL || *last != '\0')
2443 {
2444 fprintf (stderr, GTXT ("Error: Invalid number entered: %s\n"), sel);
2445 return NULL;
2446 }
2447 which--;
2448 }
2449
2450 int len_path = 0;
2451 char *with_path = name;
2452 name = StrRchr (name, '`');
2453 if (name != with_path)
2454 len_path = (int) (name - with_path);
2455 else
2456 with_path = NULL;
2457
2458 Vec_loop (LoadObject*, lobjs, index1, loitem)
2459 {
2460 Vec_loop (Module*, loitem->seg_modules, index2, mitem)
2461 {
2462 if (with_path)
2463 { // with file name
2464 // try source name first
2465 // if failed, try object name next
2466 if (!match_basename (with_path, mitem->file_name, len_path) &&
2467 !match_basename (with_path, mitem->get_name (), len_path))
2468 continue;
2469 }
2470 Vec_loop (Function*, mitem->functions, index3, fitem)
2471 {
2472 if (match_FName (name, fitem))
2473 {
2474 if (which == list->size ())
2475 return fitem;
2476 list->append (fitem);
2477 continue;
2478 }
2479 if (streq (fitem->get_name (), NTXT ("MAIN_")) && mitem->is_fortran ())
2480 {
2481 main_func = fitem;
2482 main_mod = mitem;
2483 }
2484 }
2485 }
2486 }
2487
2488 if (main_mod && main_func)
2489 {
2490 main_mod->read_stabs ();
2491 if (streq (main_func->get_match_name (), name) && which <= 1)
2492 return main_func;
2493 }
2494 return (Function *) NULL;
2495 }
2496
2497 DataObject *
2498 DbeSession::map_NametoDataObject (char *name, Vector<Histable*> *list,
2499 int which)
2500 {
2501 // Search master list to find dataobjects whose names match "name"
2502 // selecting only the entry corresponding to "which" if it is not -1.
2503 // Issues: is the name fully qualified or only partially?
2504 DataObject *ditem = NULL;
2505 int index;
2506 char *full_name;
2507 Vec_loop (DataObject*, dobjs, index, ditem)
2508 {
2509 if (ditem->scope) continue; // skip non-master dataobjects
2510
2511 // try fully-qualified dataobject name first
2512 if ((full_name = ditem->get_name ()) != NULL)
2513 {
2514 if (streq (name, full_name))
2515 {
2516 if (which == list->size ())
2517 return ditem;
2518 list->append (ditem);
2519 }
2520 }
2521 }
2522 if (list->size () > 0)
2523 return ditem; // return fully-qualified match
2524
2525 // if fully-qualified name doesn't match anything, try a partial match
2526 Vec_loop (DataObject*, dobjs, index, ditem)
2527 {
2528 if (ditem->scope) continue; // skip non-master dataobjects
2529
2530 // try fully-qualified dataobject name first
2531 if ((full_name = ditem->get_name ()) != NULL)
2532 {
2533 if (strstr (full_name, name))
2534 {
2535 if (which == list->size ())
2536 return ditem;
2537 list->append (ditem);
2538 }
2539 }
2540 }
2541 return (DataObject *) NULL;
2542 }
2543
2544 bool
2545 DbeSession::match_FName (char *name, Function *func)
2546 {
2547 size_t len;
2548 char buf[MAXDBUF];
2549 char *full_name;
2550 if (streq (func->get_name (), name)) // try full name comparison
2551 return true;
2552 if (streq (func->get_mangled_name (), name)) // try mangled name
2553 return true;
2554 if (streq (func->get_match_name (), name)) // try match name
2555 return true;
2556
2557 Module *md = func->module; // try FORTRAN name
2558 if (md && md->is_fortran ())
2559 {
2560 char *mangled_name = func->get_mangled_name ();
2561 len = strlen (name);
2562 if (((len + 1) == strlen (mangled_name)) &&
2563 (strncmp (name, mangled_name, len) == 0))
2564 return true;
2565 }
2566 snprintf (buf, sizeof (buf), NTXT ("%s"), func->get_name ());
2567 full_name = buf;
2568 char *arg = NULL; // find modifier and C++ class name
2569 int i = get_paren (buf);
2570 if (i >= 0)
2571 {
2572 arg = buf + i;
2573 *arg = '\0';
2574 }
2575
2576 char *mod = strchr (full_name, ' ');
2577 char *cls = strchr (full_name, ':');
2578
2579 if (mod)
2580 {
2581 len = mod - full_name + 1;
2582 if (!strncmp (full_name, name, len))
2583 name += len;
2584 full_name += len;
2585 if (streq (full_name, name)) // try without modifier
2586 return true;
2587 }
2588
2589 size_t len_cmp = strlen (name);
2590 if (arg)
2591 {
2592 *arg = '(';
2593 len = arg - full_name; // try without 'args'
2594 if (len_cmp == len && !strncmp (full_name, name, len))
2595 return true;
2596 if (cls)
2597 {
2598 len = arg - cls - 2; // and without 'class name'
2599 if ((len_cmp == len) && !strncmp (cls + 2, name, len))
2600 return true;
2601 }
2602 }
2603
2604 if (cls)
2605 {
2606 len = cls - full_name; // try C++ class name only
2607 if (len_cmp == len && !strncmp (full_name, name, len))
2608 return true;
2609 if (streq (cls + 2, name)) // try without 'class name'
2610 return true;
2611 }
2612 return false;
2613 }
2614
2615 bool
2616 DbeSession::add_path (char *path)
2617 {
2618 return add_path (path, get_search_path ());
2619 }
2620
2621 bool
2622 DbeSession::add_classpath (char *path)
2623 {
2624 return add_path (path, classpath);
2625 }
2626
2627 Vector<DbeFile*> *
2628 DbeSession::get_classpath ()
2629 {
2630 if (classpath_df == NULL)
2631 classpath_df = new Vector<DbeFile*>;
2632 for (int i = classpath_df->size (), sz = classpath->size (); i < sz; i++)
2633 classpath_df->store (i, getDbeFile (classpath->fetch (i),
2634 DbeFile::F_DIR_OR_JAR));
2635 return classpath_df;
2636 }
2637
2638 bool
2639 DbeSession::add_path (char *path, Vector<char*> *pathes)
2640 {
2641 bool result = false;
2642 Vector <char *> *tokens = split_str (path, ':');
2643 for (long j = 0, jsz = VecSize (tokens); j < jsz; j++)
2644 {
2645 char *spath = tokens->get (j);
2646 // Don't append path if it's already there
2647 bool got = false;
2648 for (int i = 0, sz = pathes->size (); i < sz; i++)
2649 {
2650 char *nm = pathes->get (i);
2651 if (streq (nm, spath))
2652 {
2653 got = true;
2654 break;
2655 }
2656 }
2657 if (!got)
2658 {
2659 pathes->append (spath);
2660 result = true;
2661 }
2662 else
2663 free (spath);
2664 }
2665 delete tokens;
2666 return result;
2667 }
2668
2669 void
2670 DbeSession::set_need_refind ()
2671 {
2672 Vector<DbeFile*> *f_list = dbeFiles->values ();
2673 for (long i = 0, sz = f_list == NULL ? 0 : f_list->size (); i < sz; i++)
2674 {
2675 DbeFile *f = f_list->get (i);
2676 f->set_need_refind (true);
2677 }
2678 delete f_list;
2679 for (long i = 0, sz = sources == NULL ? 0 : sources->size (); i < sz; i++)
2680 {
2681 SourceFile *f = sources->get (i);
2682 if (f && f->dbeFile)
2683 f->dbeFile->set_need_refind (true);
2684 }
2685 }
2686
2687 void
2688 DbeSession::set_search_path (Vector<char*> *path, bool reset)
2689 {
2690 if (reset)
2691 search_path->destroy ();
2692 for (int i = 0, sz = path == NULL ? 0 : path->size (); i < sz; i++)
2693 {
2694 char *name = path->fetch (i);
2695 if (add_path (name))
2696 reset = true;
2697 }
2698 if (reset)
2699 {
2700 set_need_refind ();
2701
2702 // now reset the string setting for it
2703 StringBuilder sb;
2704 for (int i = 0, sz = search_path == NULL ? 0 : search_path->size (); i < sz; i++)
2705 {
2706 char *name = search_path->fetch (i);
2707 if (sb.length () != 0)
2708 sb.append (':');
2709 sb.append (name);
2710 }
2711 free (settings->str_search_path);
2712 settings->str_search_path = sb.toString ();
2713 }
2714 }
2715
2716 void
2717 DbeSession::set_search_path (char *_lpath, bool reset)
2718 {
2719 Vector<char *> *path = new Vector<char*>;
2720 char *lpath = dbe_strdup (_lpath);
2721 for (char *s = lpath; s;)
2722 {
2723 path->append (s);
2724 s = strchr (s, ':');
2725 if (s)
2726 {
2727 *s = 0;
2728 s++;
2729 }
2730 }
2731 set_search_path (path, reset);
2732 delete path;
2733 free (lpath);
2734 }
2735
2736 void
2737 DbeSession::set_pathmaps (Vector<pathmap_t*> *newPathMap)
2738 {
2739 set_need_refind ();
2740 settings->set_pathmaps (newPathMap);
2741 }
2742
2743 Vector<pathmap_t*> *
2744 DbeSession::get_pathmaps ()
2745 {
2746 return settings->pathmaps;
2747 }
2748
2749 void
2750 DbeSession::mobj_define (MemObjType_t *mobj)
2751 {
2752 settings->mobj_define (mobj, false);
2753 DbeView *dbev;
2754 int index;
2755 Vec_loop (DbeView*, views, index, dbev)
2756 {
2757 dbev->get_settings ()->mobj_define (mobj, false);
2758 }
2759 }
2760
2761 void
2762 DbeSession::dump_segments (FILE *out)
2763 {
2764 int index;
2765 LoadObject *loitem;
2766 Vec_loop (LoadObject*, lobjs, index, loitem)
2767 {
2768 fprintf (out, NTXT ("Segment %d -- %s -- %s\n\n"),
2769 index, loitem->get_name (), loitem->get_pathname ());
2770 loitem->dump_functions (out);
2771 fprintf (out, NTXT ("\n End Segment %d -- %s -- %s\n\n"),
2772 index, loitem->get_name (), loitem->get_pathname ());
2773 }
2774 }
2775
2776 void
2777 DbeSession::dump_dataobjects (FILE *out)
2778 {
2779 DataObject *ditem;
2780 int index;
2781
2782 fprintf (out, NTXT ("\nMaster list of DataObjects:\n"));
2783 Vec_loop (DataObject*, dobjs, index, ditem)
2784 {
2785 Histable* scope = ditem->get_scope ();
2786 DataObject* parent = ditem->get_parent ();
2787 DataObject* master = ditem->get_master ();
2788 if (parent != NULL)
2789 fprintf (out, "id %6lld: [%4lld] parent = %6lld, offset = %+4lld %s\n",
2790 (ll_t) ditem->id, (ll_t) ditem->get_size (),
2791 (ll_t) parent->id, (ll_t) ditem->get_offset (),
2792 ditem->get_name ());
2793 else
2794 {
2795 // parent is NULL
2796 fprintf (out, NTXT ("id %6lld: [%4lld] %s "),
2797 (ll_t) ditem->id, (ll_t) ditem->get_size (),
2798 ditem->get_name ());
2799 if (master != NULL)
2800 fprintf (out, NTXT (" master=%lld "), (ll_t) master->id);
2801 else if (scope != NULL)
2802 fprintf (out, NTXT (" master=?? "));
2803 else
2804 fprintf (out, NTXT (" MASTER "));
2805 #if DEBUG
2806 if (scope != NULL)
2807 {
2808 switch (scope->get_type ())
2809 {
2810 case Histable::LOADOBJECT:
2811 case Histable::FUNCTION:
2812 fprintf (out, NTXT ("%s"), scope->get_name ());
2813 break;
2814 case Histable::MODULE:
2815 {
2816 char *filename = get_basename (scope->get_name ());
2817 fprintf (out, NTXT ("%s"), filename);
2818 break;
2819 }
2820 default:
2821 fprintf (out, NTXT (" Unexpected scope %d:%s"),
2822 scope->get_type (), scope->get_name ());
2823 }
2824 }
2825 #endif
2826 fprintf (out, NTXT ("\n"));
2827 }
2828 }
2829 }
2830
2831 void
2832 DbeSession::dump_map (FILE *out)
2833 {
2834 Experiment *exp;
2835 int index;
2836 Vec_loop (Experiment*, exps, index, exp)
2837 {
2838 exp->dump_map (out);
2839 }
2840 }
2841
2842 void
2843 DbeSession::dump_stacks (FILE *outfile)
2844 {
2845 Experiment *exp;
2846 int n = nexps ();
2847 FILE *f = (outfile == NULL ? stderr : outfile);
2848 for (int i = 0; i < n; i++)
2849 {
2850 exp = get_exp (i);
2851 fprintf (f, GTXT ("Experiment %d -- %s\n"), i, exp->get_expt_name ());
2852 exp->dump_stacks (f);
2853 }
2854 }
2855
2856 void
2857 DbeSession::propNames_name_store (int propId, const char *propName)
2858 {
2859 PropDescr *prop = new PropDescr (propId, propName);
2860 prop->flags = PRFLAG_NOSHOW; // do not show descriptions
2861 propNames->store (propId, prop);
2862 }
2863
2864 void
2865 DbeSession::propNames_name_store (int propId, const char* propName,
2866 const char* propUname, VType_type dataType,
2867 int flags)
2868 {
2869 PropDescr *prop = new PropDescr (propId, propName);
2870 prop->vtype = dataType;
2871 prop->uname = dbe_strdup (propUname);
2872 prop->flags = flags;
2873 propNames->store (propId, prop);
2874 }
2875
2876 char *
2877 DbeSession::propNames_name_fetch (int i)
2878 {
2879 PropDescr *prop = propNames->fetch (i);
2880 if (prop)
2881 return prop->name;
2882 return NULL;
2883 }
2884
2885 int
2886 DbeSession::registerPropertyName (const char *name)
2887 {
2888 if (name == NULL)
2889 return PROP_NONE;
2890 for (int i = 0; i < propNames->size (); i++)
2891 {
2892 char *pname = propNames_name_fetch (i);
2893 if (pname && strcasecmp (pname, name) == 0)
2894 return i;
2895 }
2896 int propId = propNames->size ();
2897 propNames_name_store (propId, name);
2898 return propId;
2899 }
2900
2901 int
2902 DbeSession::getPropIdByName (const char *name)
2903 {
2904 if (name == NULL)
2905 return PROP_NONE;
2906 for (int i = 0; i < propNames->size (); i++)
2907 {
2908 char *pname = propNames_name_fetch (i);
2909 if (pname && strcasecmp (pname, name) == 0)
2910 return i;
2911 }
2912 return PROP_NONE;
2913 }
2914
2915 char *
2916 DbeSession::getPropName (int propId)
2917 {
2918 if (!propNames)
2919 return NULL;
2920 if (propId < 0 || propId >= propNames->size ())
2921 return NULL;
2922 return dbe_strdup (propNames_name_fetch (propId));
2923 }
2924
2925 char *
2926 DbeSession::getPropUName (int propId)
2927 {
2928 if (!propNames)
2929 return NULL;
2930 if (propId < 0 || propId >= propNames->size ())
2931 return NULL;
2932 PropDescr *prop = propNames->fetch (propId);
2933 if (prop)
2934 return dbe_strdup (prop->uname);
2935 return NULL;
2936 }
2937
2938 void
2939 DbeSession::append (UserLabel *lbl)
2940 {
2941 if (lbl->expr)
2942 {
2943 if (userLabels == NULL)
2944 userLabels = new Vector<UserLabel*> ();
2945 userLabels->append (lbl);
2946 }
2947 }
2948
2949 void
2950 DbeSession::append (SourceFile *sf)
2951 {
2952 sources->append (sf);
2953 objs->append (sf);
2954 }
2955
2956 UserLabel *
2957 DbeSession::findUserLabel (char *name)
2958 {
2959 for (int i = 0, sz = userLabels ? userLabels->size () : 0; i < sz; i++)
2960 {
2961 UserLabel *lbl = userLabels->fetch (i);
2962 if (strcasecmp (lbl->name, name) == 0)
2963 return lbl;
2964 }
2965 return NULL;
2966 }
2967
2968 Expression *
2969 DbeSession::findObjDefByName (char *name)
2970 {
2971 Expression *expr = NULL;
2972
2973 MemObjType_t *mot = MemorySpace::findMemSpaceByName (name);
2974 if (mot != NULL)
2975 {
2976 char *index_expr_str = mot->index_expr;
2977 expr = ql_parse (index_expr_str);
2978 }
2979
2980 if (expr == NULL)
2981 {
2982 int indxtype = findIndexSpaceByName (name);
2983 expr = getIndexSpaceExpr (indxtype);
2984 }
2985 if (expr == NULL)
2986 {
2987 UserLabel *ulbl = findUserLabel (name);
2988 if (ulbl)
2989 expr = ulbl->expr;
2990 }
2991 return expr;
2992 }
2993
2994 Expression *
2995 DbeSession::ql_parse (const char *expr_spec)
2996 {
2997 /* (This slight duplication means we don't need to worry about copy
2998 constructors for the QL::Result, nor about the lifetime of the
2999 expr_spec.) */
3000 if (expr_spec != NULL)
3001 {
3002 QL::Result result (expr_spec);
3003 QL::Parser qlparser (result);
3004 if (qlparser () != 0)
3005 return NULL;
3006 return result ();
3007 }
3008 else
3009 {
3010 QL::Result result;
3011 QL::Parser qlparser (result);
3012 if (qlparser () != 0)
3013 return NULL;
3014 return result ();
3015 }
3016 }
3017
3018 Vector<void*> *
3019 DbeSession::getIndxObjDescriptions ()
3020 {
3021 int size = dyn_indxobj_indx;
3022 if (size == 0)
3023 return NULL;
3024 Vector<int> *type = new Vector<int>(dyn_indxobj_indx);
3025 Vector<char*> *desc = new Vector<char*>(dyn_indxobj_indx);
3026 Vector<char*> *i18ndesc = new Vector<char*>(dyn_indxobj_indx);
3027 Vector<char> *mnemonic = new Vector<char>(dyn_indxobj_indx);
3028 Vector<int> *orderList = new Vector<int>(dyn_indxobj_indx);
3029 Vector<char*> *exprList = new Vector<char*>(dyn_indxobj_indx);
3030 Vector<char*> *sdesc = new Vector<char*>(dyn_indxobj_indx);
3031 Vector<char*> *ldesc = new Vector<char*>(dyn_indxobj_indx);
3032
3033 for (long i = 0, sz = VecSize (dyn_indxobj); i < sz; i++)
3034 {
3035 IndexObjType_t *tot = dyn_indxobj->get (i);
3036 if (tot->memObj == NULL)
3037 {
3038 type->append ((int) tot->type);
3039 desc->append (dbe_strdup (tot->name));
3040 i18ndesc->append (dbe_strdup (tot->i18n_name));
3041 sdesc->append (dbe_strdup (tot->short_description));
3042 ldesc->append (dbe_strdup (tot->long_description));
3043 mnemonic->append (tot->mnemonic);
3044 orderList->append (settings->indx_tab_order->fetch (i));
3045 exprList->append (dbe_strdup (tot->index_expr_str));
3046 }
3047 }
3048 Vector<void*> *res = new Vector<void*>(8);
3049 res->store (0, type);
3050 res->store (1, desc);
3051 res->store (2, mnemonic);
3052 res->store (3, i18ndesc);
3053 res->store (4, orderList);
3054 res->store (5, exprList);
3055 res->store (6, sdesc);
3056 res->store (7, ldesc);
3057 return (res);
3058 }
3059
3060 // Static function to get a vector of custom index object definitions
3061 Vector<void*> *
3062 DbeSession::getCustomIndxObjects ()
3063 {
3064 Vector<char*> *name = new Vector<char*>;
3065 Vector<char*> *formula = new Vector<char*>;
3066 for (long i = dyn_indxobj_indx_fixed, sz = VecSize (dyn_indxobj); i < sz; i++)
3067 {
3068 IndexObjType_t *tot = dyn_indxobj->get (i);
3069 if (tot->memObj == NULL)
3070 {
3071 name->append (dbe_strdup (tot->name));
3072 formula->append (dbe_strdup (tot->index_expr_str));
3073 }
3074 }
3075 Vector<void*> *res = new Vector<void*>(2);
3076 res->store (0, name);
3077 res->store (1, formula);
3078 return (res);
3079 }
3080
3081 // Static function to define a new index object type
3082 char *
3083 DbeSession::indxobj_define (const char *mname, char *i18nname, const char *index_expr_str, char *short_description, char *long_description)
3084 {
3085 if (mname == NULL)
3086 return dbe_strdup (GTXT ("No index object type name has been specified."));
3087 if (isalpha ((int) (mname[0])) == 0)
3088 return dbe_sprintf (GTXT ("Index Object type name %s does not begin with an alphabetic character"),
3089 mname);
3090 const char *p = mname;
3091 while (*p != 0)
3092 {
3093 if ((isalnum ((int) (*p)) == 0) && (*p != '_'))
3094 return dbe_sprintf (GTXT ("Index Object type name %s contains a non-alphanumeric character"),
3095 mname);
3096 p++;
3097 }
3098
3099 // make sure the name is not in use
3100 if (MemorySpace::findMemSpaceByName (mname) != NULL)
3101 return dbe_sprintf (GTXT ("Memory/Index Object type name %s is already defined"),
3102 mname);
3103
3104 int idxx = findIndexSpaceByName (mname);
3105 if (idxx >= 0)
3106 {
3107 IndexObjType_t *mt = dyn_indxobj->fetch (idxx);
3108 if (strcmp (mt->index_expr_str, index_expr_str) == 0)
3109 // It's a redefinition, but the new definition is the same
3110 return NULL;
3111 return dbe_sprintf (GTXT ("Memory/Index Object type name %s is already defined"),
3112 mname);
3113 }
3114 if (index_expr_str == NULL)
3115 return dbe_strdup (GTXT ("No index-expr has been specified."));
3116 if (strlen (index_expr_str) == 0)
3117 return dbe_sprintf (GTXT ("Index Object index expression is invalid: %s"),
3118 index_expr_str);
3119
3120 // verify that the index expression parses correctly
3121 char *expr_str = dbe_strdup (index_expr_str);
3122 Expression *expr = ql_parse (expr_str);
3123 if (expr == NULL)
3124 return dbe_sprintf (GTXT ("Index Object index expression is invalid: %s"),
3125 expr_str);
3126
3127 // It's OK, create the new table entry
3128 IndexObjType_t *tot = new IndexObjType_t;
3129 tot->type = dyn_indxobj_indx++;
3130 tot->name = dbe_strdup (mname);
3131 tot->i18n_name = dbe_strdup (i18nname);
3132 tot->short_description = dbe_strdup (short_description);
3133 tot->long_description = dbe_strdup (long_description);
3134 tot->index_expr_str = expr_str;
3135 tot->index_expr = expr;
3136 tot->mnemonic = mname[0];
3137
3138 // add it to the list
3139 dyn_indxobj->append (tot);
3140 idxobjs->append (new HashMap<uint64_t, Histable*>);
3141
3142 // tell the session
3143 settings->indxobj_define (tot->type, false);
3144
3145 DbeView *dbev;
3146 int index;
3147 Vec_loop (DbeView*, views, index, dbev)
3148 {
3149 dbev->addIndexSpace (tot->type);
3150 }
3151 return NULL;
3152 }
3153
3154 char *
3155 DbeSession::getIndexSpaceName (int index)
3156 {
3157 if (index < 0 || index >= dyn_indxobj->size ())
3158 return NULL;
3159 return dyn_indxobj->fetch (index)->name;
3160 }
3161
3162 char *
3163 DbeSession::getIndexSpaceDescr (int index)
3164 {
3165 if (index < 0 || index >= dyn_indxobj->size ())
3166 return NULL;
3167 return dyn_indxobj->fetch (index)->i18n_name;
3168 }
3169
3170 Expression *
3171 DbeSession::getIndexSpaceExpr (int index)
3172 {
3173 if (index < 0 || index >= dyn_indxobj->size ())
3174 return NULL;
3175 return dyn_indxobj->fetch (index)->index_expr;
3176 }
3177
3178 char *
3179 DbeSession::getIndexSpaceExprStr (int index)
3180 {
3181 if (index < 0 || index >= dyn_indxobj->size ())
3182 return NULL;
3183 return dyn_indxobj->fetch (index)->index_expr_str;
3184 }
3185
3186 int
3187 DbeSession::findIndexSpaceByName (const char *mname)
3188 {
3189 int idx;
3190 IndexObjType_t *mt;
3191 Vec_loop (IndexObjType_t*, dyn_indxobj, idx, mt)
3192 {
3193 if (strcasecmp (mt->name, mname) == 0)
3194 return idx;
3195 }
3196 return -1;
3197 }
3198
3199 void
3200 DbeSession::removeIndexSpaceByName (const char *mname)
3201 {
3202 IndexObjType_t *indObj = findIndexSpace (mname);
3203 if (indObj)
3204 indObj->name[0] = 0;
3205 }
3206
3207 IndexObjType_t *
3208 DbeSession::getIndexSpace (int index)
3209 {
3210 return ((index < 0) || (index >= VecSize (dyn_indxobj))) ? NULL : dyn_indxobj->get (index);
3211 }
3212
3213 IndexObjType_t *
3214 DbeSession::findIndexSpace (const char *mname)
3215 {
3216 return getIndexSpace (findIndexSpaceByName (mname));
3217 }
3218
3219 void
3220 DbeSession::get_filter_keywords (Vector<void*> *res)
3221 {
3222 Vector <char*> *kwCategory = (Vector<char*>*) res->fetch (0);
3223 Vector <char*> *kwCategoryI18N = (Vector<char*>*) res->fetch (1);
3224 Vector <char*> *kwDataType = (Vector<char*>*) res->fetch (2);
3225 Vector <char*> *kwKeyword = (Vector<char*>*) res->fetch (3);
3226 Vector <char*> *kwFormula = (Vector<char*>*) res->fetch (4);
3227 Vector <char*> *kwDescription = (Vector<char*>*) res->fetch (5);
3228 Vector <void*> *kwEnumDescs = (Vector<void*>*) res->fetch (6);
3229
3230 char *vtypeNames[] = VTYPE_TYPE_NAMES;
3231 for (long i = 0, sz = userLabels ? userLabels->size () : 0; i < sz; i++)
3232 {
3233 UserLabel *lbl = userLabels->fetch (i);
3234 kwCategory->append (dbe_strdup (NTXT ("FK_LABEL")));
3235 kwCategoryI18N->append (dbe_strdup (GTXT ("Labels")));
3236 kwDataType->append (dbe_strdup (vtypeNames[TYPE_BOOL]));
3237 kwKeyword->append (dbe_strdup (lbl->name));
3238 kwFormula->append (dbe_strdup (lbl->str_expr));
3239 kwDescription->append (dbe_strdup (lbl->comment));
3240 kwEnumDescs->append (NULL);
3241 }
3242
3243 for (long i = 0, sz = propNames ? propNames->size () : 0; i < sz; i++)
3244 {
3245 PropDescr *prop = propNames->fetch (i);
3246 char *pname = prop ? prop->name : NULL;
3247 if (pname == NULL || *pname == 0 || prop->flags & PRFLAG_NOSHOW)
3248 continue;
3249 int vtypeNum = prop->vtype;
3250 if (vtypeNum < 0 || vtypeNum >= TYPE_LAST)
3251 vtypeNum = TYPE_NONE;
3252 kwCategory->append (dbe_strdup (NTXT ("FK_EVTPROP"))); //Event Property
3253 kwCategoryI18N->append (dbe_strdup (GTXT ("Misc. Definitions")));
3254 kwDataType->append (dbe_strdup (vtypeNames[vtypeNum]));
3255 kwKeyword->append (dbe_strdup (pname));
3256 kwFormula->append (NULL);
3257 kwDescription->append (dbe_strdup (prop->uname));
3258 kwEnumDescs->append (NULL);
3259 }
3260
3261 for (long i = 0, sz = dyn_indxobj ? dyn_indxobj->size () : 0; i < sz; i++)
3262 {
3263 IndexObjType_t *obj = dyn_indxobj->get (i);
3264 if (obj->memObj)
3265 continue;
3266 kwCategory->append (dbe_strdup (NTXT ("FK_IDXOBJ")));
3267 kwCategoryI18N->append (dbe_strdup (GTXT ("Index Object Definitions")));
3268 kwDataType->append (dbe_strdup (vtypeNames[TYPE_INT64]));
3269 kwKeyword->append (dbe_strdup (obj->name));
3270 kwFormula->append (dbe_strdup (obj->index_expr_str));
3271 kwDescription->append (dbe_strdup (obj->i18n_name));
3272 kwEnumDescs->append (NULL);
3273 }
3274 }
3275
3276 Histable *
3277 DbeSession::findIndexObject (int idxtype, uint64_t idx)
3278 {
3279 HashMap<uint64_t, Histable*> *iobjs = idxobjs->fetch (idxtype);
3280 return iobjs->get (idx);
3281 }
3282
3283 Histable *
3284 DbeSession::createIndexObject (int idxtype, int64_t idx)
3285 {
3286 HashMap<uint64_t, Histable*> *iobjs = idxobjs->fetch (idxtype);
3287
3288 Histable *idxobj = iobjs->get (idx);
3289 if (idxobj == NULL)
3290 {
3291 idxobj = new IndexObject (idxtype, idx);
3292 if (idx == -1)
3293 idxobj->set_name (dbe_strdup (GTXT ("<Unknown>")));
3294 iobjs->put (idx, idxobj);
3295 }
3296
3297 return idxobj;
3298 }
3299
3300 Histable *
3301 DbeSession::createIndexObject (int idxtype, Histable *hobj)
3302 {
3303 HashMap<uint64_t, Histable*> *iobjs = idxobjs->fetch (idxtype);
3304 int64_t idx = hobj ? hobj->id : -1;
3305 Histable *idxobj = iobjs->get (idx);
3306 if (idxobj == NULL)
3307 {
3308 idxobj = new IndexObject (idxtype, hobj);
3309 if (idx == -1)
3310 idxobj->set_name (dbe_strdup (GTXT ("<Unknown>")));
3311 iobjs->put (idx, idxobj);
3312 }
3313
3314 return idxobj;
3315 }
3316
3317 Histable *
3318 DbeSession::findObjectById (Histable::Type type, int subtype, uint64_t id)
3319 {
3320 switch (type)
3321 {
3322 case Histable::FUNCTION:
3323 case Histable::MODULE:
3324 case Histable::LOADOBJECT:
3325 return ( id < (uint64_t) objs->size ()) ? objs->fetch ((int) id) : NULL;
3326 case Histable::INDEXOBJ:
3327 return findIndexObject (subtype, id);
3328 // ignoring the following cases
3329 case Histable::INSTR:
3330 case Histable::LINE:
3331 case Histable::EADDR:
3332 case Histable::MEMOBJ:
3333 case Histable::PAGE:
3334 case Histable::DOBJECT:
3335 case Histable::SOURCEFILE:
3336 case Histable::IOACTFILE:
3337 case Histable::IOACTVFD:
3338 case Histable::IOCALLSTACK:
3339 case Histable::HEAPCALLSTACK:
3340 case Histable::OTHER:
3341 case Histable::EXPERIMENT:
3342 break;
3343 }
3344 return NULL;
3345 }
3346
3347 // return a vector of Functions that match the regular expression input string
3348 Vector<JThread *> *
3349 DbeSession::match_java_threads (char *ustr, int matchParent,
3350 Vector<uint64_t> * &grids,
3351 Vector<uint64_t> * &expids)
3352 {
3353 if (ustr == NULL)
3354 return NULL;
3355
3356 char *str = dbe_sprintf (NTXT ("^%s$"), ustr);
3357 regex_t regex_desc;
3358 int rc = regcomp (&regex_desc, str, REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
3359 free (str);
3360 if (rc) // syntax error in parsing string
3361 return NULL;
3362
3363 // allocate the new vector
3364 Vector<JThread *> *ret = new Vector<JThread*>;
3365 grids = new Vector<uint64_t>;
3366 expids = new Vector<uint64_t>;
3367
3368 int index;
3369 JThread *jthread;
3370 int expid;
3371 Experiment* exp;
3372 Vec_loop (Experiment*, exps, expid, exp)
3373 {
3374
3375 Vec_loop (JThread*, exp->get_jthreads (), index, jthread)
3376 {
3377 const char * name;
3378 if (matchParent)
3379 name = jthread->parent_name;
3380 else
3381 name = jthread->group_name;
3382 if (name == NULL)
3383 name = "";
3384 if (!regexec (&regex_desc, name, 0, NULL, 0))
3385 {
3386 // this one matches
3387 ret->append (jthread);
3388 grids->append (exp->groupId);
3389 expids->append (exp->getUserExpId ());
3390 }
3391 }
3392 }
3393
3394 regfree (&regex_desc);
3395 return ret;
3396 }
3397
3398 // return a vector of Functions that match the regular expression input string
3399 Vector<Function *> *
3400 DbeSession::match_func_names (const char *ustr, Histable::NameFormat nfmt)
3401 {
3402 if (ustr == NULL)
3403 return NULL;
3404 char *str = dbe_sprintf (NTXT ("^%s$"), ustr);
3405 regex_t regex_desc;
3406 int rc = regcomp (&regex_desc, str, REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
3407 free (str);
3408 if (rc) // syntax error in parsing string
3409 return NULL;
3410
3411 // allocate the new vector
3412 Vector<Function *> *ret = new Vector<Function*>;
3413
3414 int index;
3415 Histable *obj;
3416 Vec_loop (Histable*, objs, index, obj)
3417 {
3418 if (obj->get_type () == Histable::FUNCTION)
3419 {
3420 Function *func = (Function*) obj;
3421 if (!regexec (&regex_desc, func->get_name (nfmt), 0, NULL, 0))
3422 // this one matches
3423 ret->append (func);
3424 }
3425 }
3426 regfree (&regex_desc);
3427 return ret;
3428 }
3429
3430 // return a vector of Functions that match the regular expression input string
3431 Vector<FileData *> *
3432 DbeSession::match_file_names (char *ustr, Histable::NameFormat nfmt)
3433 {
3434 if (ustr == NULL)
3435 return NULL;
3436 char *str = dbe_sprintf (NTXT ("^%s$"), ustr);
3437 regex_t regex_desc;
3438 int rc = regcomp (&regex_desc, str, REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
3439 free (str);
3440 if (rc) // syntax error in parsing string
3441 return NULL;
3442
3443 // allocate the new vector
3444 Vector<FileData *> *ret = new Vector<FileData*>;
3445 int numExps = nexps ();
3446 DefaultMap<int64_t, FileData*>* fDataMap;
3447 Vector<FileData *> *fDataObjs;
3448 FileData *fData;
3449 int size;
3450 for (int i = 0; i < numExps; i++)
3451 {
3452 Experiment *exp = get_exp (i);
3453 fDataMap = exp->getFDataMap ();
3454 fDataObjs = fDataMap->values ();
3455 size = fDataObjs->size ();
3456 for (int j = 0; j < size; j++)
3457 {
3458 fData = fDataObjs->fetch (j);
3459 if (fData
3460 && !regexec (&regex_desc, fData->get_raw_name (nfmt), 0, NULL, 0))
3461 // this one matches
3462 ret->append (fData);
3463 }
3464 }
3465 regfree (&regex_desc);
3466 return ret;
3467 }
3468
3469 // return a vector of DataObjects that match the regular expression input string
3470 Vector<DataObject *> *
3471 DbeSession::match_dobj_names (char *ustr)
3472 {
3473 if (ustr == NULL)
3474 return NULL;
3475 char *str = dbe_sprintf (NTXT ("^%s$"), ustr);
3476 regex_t regex_desc;
3477 int rc = regcomp (&regex_desc, str, REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
3478 free (str);
3479 if (rc) // syntax error in parsing string
3480 return NULL;
3481
3482 // allocate the new vector
3483 Vector<DataObject *> *ret = new Vector<DataObject*>;
3484 int index;
3485 DataObject *ditem;
3486 Vec_loop (DataObject*, dobjs, index, ditem)
3487 {
3488 // does this one match
3489 if (!regexec (&regex_desc, ditem->get_name (), 0, NULL, 0))
3490 // this one matches
3491 ret->append (ditem);
3492 }
3493 regfree (&regex_desc);
3494 return ret;
3495 }
3496
3497 void
3498 DbeSession::dump (char *msg, Vector<BaseMetric*> *mlist)
3499 {
3500 if (msg)
3501 fprintf (stderr, "%s\n", msg);
3502 int sz = mlist ? mlist->size () : -1;
3503 for (int i = 0; i < sz; i++)
3504 {
3505 BaseMetric *m = mlist->fetch (i);
3506 char *s = m->dump ();
3507 fprintf (stderr, "%2d %s\n", i, s);
3508 free (s);
3509 }
3510 fprintf (stderr, "======END of mlist[%d] =========\n", sz);
3511 }
3512
3513 void
3514 DbeSession::dump (char *msg, Vector<Metric*> *mlist)
3515 {
3516 if (msg)
3517 fprintf (stderr, "%s\n", msg);
3518 int sz = mlist ? mlist->size () : -1;
3519 for (int i = 0; i < sz; i++)
3520 {
3521 Metric *m = mlist->fetch (i);
3522 char *s = m->dump ();
3523 fprintf (stderr, "%2d %s\n", i, s);
3524 free (s);
3525 }
3526 fprintf (stderr, "======END of mlist[%d] =========\n", sz);
3527 }