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