arm: Support pac_key_* register operand for MRS/MSR in Armv8.1-M Mainline
[binutils-gdb.git] / gprofng / src / Experiment.cc
blobc1e125229180520a634eb564ea8d4aa34cbd02ef
1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
2 Contributed by Oracle.
4 This file is part of GNU Binutils.
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.
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.
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. */
21 #include "config.h"
22 #include <errno.h>
23 #include <utime.h>
24 #include <alloca.h>
25 #include <dirent.h>
26 #include <ctype.h>
27 #include <unistd.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <sys/param.h>
31 #include <set>
33 #include "util.h"
34 #include "CacheMap.h"
35 #include "DbeFile.h"
36 #include "DbeCacheMap.h"
37 #include "DefaultHandler.h"
38 #include "DefaultMap2D.h"
39 #include "Emsg.h"
40 #include "Elf.h"
41 #include "SAXParser.h"
42 #include "SAXParserFactory.h"
43 #include "StringBuilder.h"
44 #include "DbeSession.h"
45 #include "DbeThread.h"
46 #include "Application.h"
47 #include "CallStack.h"
48 #include "Experiment.h"
49 #include "Exp_Layout.h"
50 #include "DataStream.h"
51 #include "Expression.h"
52 #include "Function.h"
53 #include "HeapMap.h"
54 #include "LoadObject.h"
55 #include "Module.h"
56 #include "Ovw_data.h"
57 #include "PRBTree.h"
58 #include "Sample.h"
59 #include "SegMem.h"
60 #include "StringMap.h"
61 #include "UserLabel.h"
62 #include "Table.h"
63 #include "dbe_types.h"
64 #include "FileData.h"
65 #include "cc_libcollector.h"
66 #include "ExpGroup.h"
68 int nPush;
69 int nPop;
70 int pushCnt;
71 int popCnt;
72 int pushCnt3;
73 int popCnt3;
75 struct Experiment::UIDnode
77 uint64_t uid;
78 uint64_t val;
79 UIDnode *next;
82 struct Experiment::RawFramePacket
84 uint64_t uid;
85 UIDnode *uidn;
86 UIDnode *uidj;
87 UIDnode *omp_uid;
88 uint32_t omp_state;
91 static hrtime_t
92 parseTStamp (const char *s)
94 hrtime_t ts = (hrtime_t) 0;
95 ts = (hrtime_t) atoi (s) * NANOSEC;
96 s = strchr (s, '.');
97 if (s != NULL)
98 ts += (hrtime_t) atoi (s + 1);
99 return ts;
102 class Experiment::ExperimentFile
104 public:
106 enum
108 EF_NOT_OPENED,
109 EF_OPENED,
110 EF_CLOSED,
111 EF_FAILURE
114 ExperimentFile (Experiment *_exp, const char *_fname);
115 ~ExperimentFile ();
117 bool open (bool new_open = false);
119 char *
120 get_name ()
122 return fname;
125 inline int
126 get_status ()
128 return ef_status;
131 char *fgets ();
132 void close ();
134 FILE *fh;
136 private:
137 Experiment *exp;
138 char *fname;
139 off64_t offset;
140 int bufsz, ef_status;
141 char *buffer;
144 class Experiment::ExperimentHandler : public DefaultHandler
146 public:
148 ExperimentHandler (Experiment *_exp);
149 ~ExperimentHandler ();
151 void
152 startDocument () { }
153 void endDocument ();
154 void startElement (char *uri, char *localName, char *qName, Attributes *attrs);
155 void endElement (char *uri, char *localName, char *qName);
156 void characters (char *ch, int start, int length);
158 void
159 ignorableWhitespace (char*, int, int) { }
160 void
161 error (SAXParseException *e);
163 private:
165 enum Element
167 EL_NONE,
168 EL_EXPERIMENT,
169 EL_COLLECTOR,
170 EL_SETTING,
171 EL_PROCESS,
172 EL_SYSTEM,
173 EL_EVENT,
174 EL_PROFILE,
175 EL_DATAPTR,
176 EL_PROFDATA,
177 EL_PROFPCKT,
178 EL_FIELD,
179 EL_CPU,
180 EL_STATE,
181 EL_FREQUENCY,
182 EL_POWERM,
183 EL_DTRACEFATAL
186 static int toInt (Attributes *attrs, const char *atr);
187 static char*toStr (Attributes *attrs, const char *atr);
188 void pushElem (Element);
189 void popElem ();
191 Experiment *exp;
192 Element curElem;
193 Vector<Element> *stack;
194 Module *dynfuncModule;
195 DataDescriptor *dDscr;
196 PacketDescriptor *pDscr;
197 PropDescr *propDscr;
198 char *text;
199 Cmsg_warn mkind;
200 int mnum;
201 int mec;
205 // HTableSize is the size of smemHTable and instHTable
206 // omazur: both HTableSize and the hash function haven't been tuned;
207 static const int HTableSize = 8192;
209 //-------------------------------------------------- Experiment file handler
211 Experiment::ExperimentFile::ExperimentFile (Experiment *_exp, const char *_fname)
213 exp = _exp;
214 fh = NULL;
215 bufsz = 0;
216 buffer = NULL;
217 ef_status = EF_NOT_OPENED;
218 offset = 0;
219 fname = dbe_sprintf (NTXT ("%s/%s"), exp->expt_name, _fname);
222 Experiment::ExperimentFile::~ExperimentFile ()
224 close ();
225 free (buffer);
226 free (fname);
229 bool
230 Experiment::ExperimentFile::open (bool new_open)
232 if (fh == NULL)
234 fh = fopen64 (fname, NTXT ("r"));
235 if (fh == NULL)
237 ef_status = EF_FAILURE;
238 return false;
240 ef_status = EF_OPENED;
241 if (new_open)
242 offset = 0;
243 if (offset != 0)
244 fseeko64 (fh, offset, SEEK_SET);
246 return true;
249 char *
250 Experiment::ExperimentFile::fgets ()
252 if (bufsz == 0)
254 bufsz = 1024;
255 buffer = (char *) xmalloc (bufsz);
256 buffer[bufsz - 1] = (char) 1; // sentinel
258 char *res = ::fgets (buffer, bufsz, fh);
259 if (res == NULL)
260 return NULL;
261 while (buffer[bufsz - 1] == (char) 0)
263 int newsz = bufsz + 1024;
264 char *newbuf = (char *) xmalloc (newsz);
265 memcpy (newbuf, buffer, bufsz);
266 free (buffer);
267 buffer = newbuf;
268 buffer[newsz - 1] = (char) 1; // sentinel
269 // we don't care about fgets result here
270 ::fgets (buffer + bufsz - 1, newsz - bufsz + 1, fh);
271 bufsz = newsz;
273 return buffer;
276 void
277 Experiment::ExperimentFile::close ()
279 if (fh)
281 offset = ftello64 (fh);
282 fclose (fh);
283 ef_status = EF_CLOSED;
284 fh = NULL;
289 //-------------------------------------------------- Experiment XML parser
291 Experiment::ExperimentHandler::toInt (Attributes *attrs, const char *atr)
293 const char *str = attrs->getValue (atr);
294 return str ? atoi (str) : 0;
297 char *
298 Experiment::ExperimentHandler::toStr (Attributes *attrs, const char *atr)
300 const char *str = attrs->getValue (atr);
301 return dbe_strdup (str ? str : NTXT (""));
304 Experiment::ExperimentHandler::ExperimentHandler (Experiment *_exp)
306 exp = _exp;
307 stack = new Vector<Element>;
308 pushElem (EL_NONE);
309 dynfuncModule = NULL;
310 dDscr = NULL;
311 pDscr = NULL;
312 propDscr = NULL;
313 text = NULL;
314 mkind = CMSG_NONE;
315 mnum = -1;
316 mec = -1;
319 Experiment::ExperimentHandler::~ExperimentHandler ()
321 delete stack;
322 free (text);
325 void
326 Experiment::ExperimentHandler::endDocument ()
328 { // SP_TAG_STATE should be used to describe states, but it isn't
329 // let's do it here:
330 DataDescriptor *dd = exp->getDataDescriptor (DATA_HEAP);
331 if (dd != NULL)
333 PropDescr *prop = dd->getProp (PROP_HTYPE);
334 if (prop != NULL)
336 char * stateNames [HEAPTYPE_LAST] = HEAPTYPE_STATE_STRINGS;
337 char * stateUNames[HEAPTYPE_LAST] = HEAPTYPE_STATE_USTRINGS;
338 for (int ii = 0; ii < HEAPTYPE_LAST; ii++)
339 prop->addState (ii, stateNames[ii], stateUNames[ii]);
342 dd = exp->getDataDescriptor (DATA_IOTRACE);
343 if (dd != NULL)
345 PropDescr *prop = dd->getProp (PROP_IOTYPE);
346 if (prop != NULL)
348 char * stateNames [IOTRACETYPE_LAST] = IOTRACETYPE_STATE_STRINGS;
349 char * stateUNames[IOTRACETYPE_LAST] = IOTRACETYPE_STATE_USTRINGS;
350 for (int ii = 0; ii < IOTRACETYPE_LAST; ii++)
351 prop->addState (ii, stateNames[ii], stateUNames[ii]);
357 void
358 Experiment::ExperimentHandler::pushElem (Element elem)
360 curElem = elem;
361 stack->append (curElem);
364 void
365 Experiment::ExperimentHandler::popElem ()
367 curElem = stack->remove (stack->size () - 1);
370 void
371 Experiment::ExperimentHandler::startElement (char*, char*, char *qName, Attributes *attrs)
373 DEBUG_CODE if (DEBUG_SAXPARSER) dump_startElement (qName, attrs);
374 if (strcmp (qName, SP_TAG_EXPERIMENT) == 0)
376 pushElem (EL_EXPERIMENT);
377 const char *str = attrs->getValue (NTXT ("version"));
378 if (str != NULL)
380 int major = atoi (str);
381 str = strchr (str, '.');
382 int minor = str ? atoi (str + 1) : 0;
383 exp->exp_maj_version = major;
384 exp->exp_min_version = minor;
385 if (major != SUNPERF_VERNUM || minor != SUNPERF_VERNUM_MINOR)
387 // not the current version, see if we support some earlier versions
388 if (major < 12)
390 StringBuilder sb;
391 sb.sprintf (GTXT ("*** Error: experiment %s version %d.%d is not supported;\nuse the version of the tools that recorded the experiment to read it"),
392 exp->get_expt_name (), major, minor);
393 // exp->errorq->append( new Emsg(CMSG_FATAL, sb) );
394 exp->status = FAILURE;
395 exp->obsolete = 1;
396 throw new SAXException (sb.toString ());
401 else if (strcmp (qName, SP_TAG_COLLECTOR) == 0)
402 pushElem (EL_COLLECTOR);
403 else if (strcmp (qName, SP_TAG_SETTING) == 0)
405 int found = 0;
406 pushElem (EL_SETTING);
407 const char *str = attrs->getValue (SP_JCMD_LIMIT);
408 if (str != NULL)
410 found = 1;
411 exp->coll_params.limit = atoi (str);
413 str = attrs->getValue (SP_JCMD_BLKSZ);
414 if (str != NULL)
416 found = 1;
417 exp->blksz = strtol (str, NULL, 0);
419 str = attrs->getValue (SP_JCMD_STACKBASE);
420 if (str)
422 found = 1;
423 exp->stack_base = strtoull (str, NULL, 0);
425 str = attrs->getValue (SP_JCMD_HWC_DEFAULT);
426 if (str != NULL)
428 found = 1;
429 exp->hwc_default = true;
431 str = attrs->getValue (SP_JCMD_NOIDLE);
432 if (str != NULL)
434 found = 1;
435 exp->commentq->append (new Emsg (CMSG_COMMENT,
436 GTXT ("*** Note: experiment does not have events from idle CPUs")));
438 str = attrs->getValue (SP_JCMD_FAKETIME);
439 if (str != NULL)
441 found = 1;
442 exp->timelineavail = false;
443 exp->commentq->append (new Emsg (CMSG_COMMENT,
444 GTXT ("*** Note: experiment does not have timestamps; timeline unavailable")));
446 str = attrs->getValue (SP_JCMD_DELAYSTART);
447 if (str != NULL)
449 found = 1;
450 exp->coll_params.start_delay = xstrdup (str);
452 str = attrs->getValue (SP_JCMD_TERMINATE);
453 if (str != NULL)
455 found = 1;
456 exp->coll_params.terminate = xstrdup (str);
458 str = attrs->getValue (SP_JCMD_PAUSE_SIG);
459 if (str != NULL)
461 found = 1;
462 exp->coll_params.pause_sig = xstrdup (str);
464 str = attrs->getValue (SP_JCMD_SAMPLE_PERIOD);
465 if (str != NULL)
467 found = 1;
468 exp->coll_params.sample_periodic = 1;
469 exp->coll_params.sample_timer = atoi (str);
471 str = attrs->getValue (SP_JCMD_SAMPLE_SIG);
472 if (str != NULL)
474 found = 1;
475 exp->coll_params.sample_sig = str;
477 str = attrs->getValue (SP_JCMD_SRCHPATH);
478 if (str != NULL)
480 found = 1;
481 StringBuilder sb;
482 sb.sprintf (GTXT ("Search path: %s"), str);
483 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb));
484 dbeSession->add_classpath ((char*) str);
486 str = attrs->getValue (SP_JCMD_LINETRACE);
487 if (str != NULL)
489 found = 1;
490 exp->coll_params.linetrace = xstrdup (str);
493 str = attrs->getValue (SP_JCMD_COLLENV);
494 if (str != NULL)
496 found = 1;
497 StringBuilder sb;
498 sb.sprintf (GTXT (" Data collection environment variable: %s"), str);
499 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb));
501 if (found == 0)
503 int nattr = attrs->getLength ();
504 if (nattr != 0)
506 fprintf (stderr, "XXX Unexpected setting found; %d attributes:\n",
507 nattr);
508 for (int k = 0; k < nattr; k++)
510 const char *qn = attrs->getQName (k);
511 const char *vl = attrs->getValue (k);
512 fprintf (stderr, "XXX %s = %s\n", qn, vl);
516 // END OF CODE FOR "setting"
518 else if (strcmp (qName, SP_TAG_SYSTEM) == 0)
520 pushElem (EL_SYSTEM);
521 const char *str = attrs->getValue (NTXT ("hostname"));
522 if (str != NULL)
523 exp->hostname = xstrdup (str);
524 str = attrs->getValue (NTXT ("os"));
525 if (str != NULL)
527 exp->os_version = xstrdup (str);
528 /* For Linux experiments expect sparse thread ID's */
529 if (strncmp (str, NTXT ("SunOS"), 5) != 0)
530 exp->sparse_threads = true;
532 str = attrs->getValue (NTXT ("arch"));
533 if (str != NULL)
535 if (strcmp (str, "i86pc") == 0 || strcmp (str, "i686") == 0
536 || strcmp (str, "x86_64") == 0)
537 exp->platform = Intel;
538 else if (strcmp (str, "aarch64") == 0)
539 exp->platform = Aarch64;
540 else if (strcmp (str, "riscv64") == 0)
541 exp->platform = RISCV;
542 else
543 exp->platform = Sparc;
544 exp->need_swap_endian = (DbeSession::platform == Sparc) ?
545 (exp->platform != Sparc) : (exp->platform == Sparc);
546 exp->architecture = xstrdup (str);
548 str = attrs->getValue (NTXT ("pagesz"));
549 if (str != NULL)
550 exp->page_size = atoi (str);
551 str = attrs->getValue (NTXT ("npages"));
552 if (str != NULL)
553 exp->npages = atoi (str);
555 else if (strcmp (qName, SP_TAG_POWERM) == 0)
556 pushElem (EL_POWERM);
557 else if (strcmp (qName, SP_TAG_FREQUENCY) == 0)
559 pushElem (EL_FREQUENCY);
560 const char *str = attrs->getValue (NTXT ("clk"));
561 if (str != NULL)
562 exp->set_clock (atoi (str));
563 // check for frequency_scaling or turbo_mode recorded from libcollector under dbx
564 str = attrs->getValue (NTXT ("frequency_scaling"));
565 const char *str2 = attrs->getValue (NTXT ("turbo_mode"));
566 if (str != NULL || str2 != NULL)
567 exp->varclock = 1;
569 else if (strcmp (qName, SP_TAG_CPU) == 0)
571 pushElem (EL_CPU);
572 exp->ncpus++;
573 const char *str = attrs->getValue (NTXT ("clk"));
574 if (str != NULL)
576 int clk = atoi (str);
577 if (exp->maxclock == 0)
579 exp->minclock = clk;
580 exp->maxclock = clk;
582 else
584 if (clk < exp->minclock)
585 exp->minclock = clk;
586 if (clk > exp->maxclock)
587 exp->maxclock = clk;
589 exp->clock = clk;
591 // check for frequency_scaling or turbo_mode
592 str = attrs->getValue (NTXT ("frequency_scaling"));
593 const char *str2 = attrs->getValue (NTXT ("turbo_mode"));
594 if (str != NULL || str2 != NULL)
595 exp->varclock = 1;
597 else if (strcmp (qName, SP_TAG_PROCESS) == 0)
599 pushElem (EL_PROCESS);
600 const char *str = attrs->getValue (NTXT ("wsize"));
601 if (str != NULL)
603 int wsz = atoi (str);
604 if (wsz == 32)
605 exp->wsize = W32;
606 else if (wsz == 64)
607 exp->wsize = W64;
609 str = attrs->getValue (NTXT ("pid"));
610 if (str != NULL)
611 exp->pid = atoi (str);
612 str = attrs->getValue (NTXT ("ppid"));
613 if (str != NULL)
614 exp->ppid = atoi (str);
615 str = attrs->getValue (NTXT ("pgrp"));
616 if (str != NULL)
617 exp->pgrp = atoi (str);
618 str = attrs->getValue (NTXT ("sid"));
619 if (str != NULL)
620 exp->sid = atoi (str);
621 str = attrs->getValue (NTXT ("cwd"));
622 if (str != NULL)
623 exp->ucwd = xstrdup (str);
624 str = attrs->getValue (NTXT ("pagesz"));
625 if (str != NULL)
626 exp->page_size = atoi (str);
628 else if (strcmp (qName, SP_TAG_EVENT) == 0)
629 { // Start code for event
630 pushElem (EL_EVENT);
631 hrtime_t ts = (hrtime_t) 0;
632 const char *str = attrs->getValue (NTXT ("tstamp"));
633 if (str != NULL)
634 ts = parseTStamp (str);
635 str = attrs->getValue (NTXT ("kind"));
636 if (str != NULL)
638 if (strcmp (str, SP_JCMD_RUN) == 0)
640 exp->broken = 0;
641 exp->exp_start_time = ts;
642 str = attrs->getValue (NTXT ("time"));
643 if (str != NULL)
644 exp->start_sec = atoll (str);
645 str = attrs->getValue (NTXT ("pid"));
646 if (str != NULL)
647 exp->pid = atoi (str);
648 str = attrs->getValue (NTXT ("ppid"));
649 if (str != NULL)
650 exp->ppid = atoi (str);
651 str = attrs->getValue (NTXT ("pgrp"));
652 if (str != NULL)
653 exp->pgrp = atoi (str);
654 str = attrs->getValue (NTXT ("sid"));
655 if (str != NULL)
656 exp->sid = atoi (str);
657 exp->status = Experiment::INCOMPLETE;
659 else if (strcmp (str, SP_JCMD_ARCHIVE) == 0)
661 StringBuilder sb;
662 sb.sprintf (GTXT ("gprofng-archive run: XXXXXXX"));
663 exp->pprocq->append (new Emsg (CMSG_WARN, sb));
665 else if (strcmp (str, SP_JCMD_SAMPLE) == 0)
667 exp->update_last_event (exp->exp_start_time + ts); // ts is 0-based
668 str = attrs->getValue (NTXT ("id"));
669 int id = str ? atoi (str) : -1;
670 char *label = dbe_strdup (attrs->getValue (NTXT ("label")));
671 exp->process_sample_cmd (NULL, ts, id, label);
673 else if (strcmp (str, SP_JCMD_EXIT) == 0)
675 // don't treat EXIT as an event w.r.t. last_event and non_paused_time
676 exp->status = Experiment::SUCCESS;
678 else if (strcmp (str, SP_JCMD_CERROR) == 0)
680 mkind = CMSG_ERROR;
681 str = attrs->getValue (NTXT ("id"));
682 if (str != NULL)
684 mnum = atoi (str);
686 str = attrs->getValue (NTXT ("ec"));
687 if (str != NULL)
689 mec = atoi (str);
692 else if (strcmp (str, SP_JCMD_CWARN) == 0)
694 mkind = CMSG_WARN;
695 str = attrs->getValue (NTXT ("id"));
696 if (str != NULL)
697 mnum = atoi (str);
699 else if (strcmp (str, SP_JCMD_COMMENT) == 0)
701 mkind = CMSG_COMMENT;
702 str = attrs->getValue (NTXT ("id"));
703 if (str != NULL)
704 mnum = atoi (str);
705 str = attrs->getValue (NTXT ("text"));
706 if (str != NULL)
708 StringBuilder sb;
709 sb.sprintf (GTXT ("*** Note: %s"), str);
710 exp->commentq->append (new Emsg (CMSG_COMMENT, sb));
713 else if (strcmp (str, SP_JCMD_DESC_START) == 0)
715 char *variant = toStr (attrs, NTXT ("variant"));
716 char *lineage = toStr (attrs, NTXT ("lineage"));
717 int follow = toInt (attrs, NTXT ("follow"));
718 char *msg = toStr (attrs, NTXT ("msg"));
719 exp->process_desc_start_cmd (NULL, ts, variant, lineage, follow, msg);
721 else if (strcmp (str, SP_JCMD_DESC_STARTED) == 0)
723 char *variant = toStr (attrs, NTXT ("variant"));
724 char *lineage = toStr (attrs, NTXT ("lineage"));
725 int follow = toInt (attrs, NTXT ("follow"));
726 char *msg = toStr (attrs, NTXT ("msg"));
727 exp->process_desc_started_cmd (NULL, ts, variant, lineage, follow, msg);
729 else if (strcmp (str, SP_JCMD_EXEC_START) == 0)
731 // if successful, acts like experiment termination - no "exit" entry will follow
732 exp->update_last_event (exp->exp_start_time + ts); // ts is 0-based
733 char *variant = toStr (attrs, NTXT ("variant"));
734 char *lineage = toStr (attrs, NTXT ("lineage"));
735 int follow = toInt (attrs, NTXT ("follow"));
736 char *msg = toStr (attrs, NTXT ("msg"));
737 exp->process_desc_start_cmd (NULL, ts, variant, lineage, follow, msg);
738 exp->exec_started = true;
740 else if (strcmp (str, SP_JCMD_EXEC_ERROR) == 0)
742 exp->update_last_event (exp->exp_start_time + ts); // ts is 0-based
743 char *variant = toStr (attrs, NTXT ("variant"));
744 char *lineage = toStr (attrs, NTXT ("lineage"));
745 int follow = toInt (attrs, NTXT ("follow"));
746 char *msg = toStr (attrs, NTXT ("msg"));
747 exp->process_desc_started_cmd (NULL, ts, variant, lineage, follow, msg);
748 exp->exec_started = false;
750 else if (strcmp (str, SP_JCMD_JTHRSTART) == 0)
752 char *name = dbe_strdup (attrs->getValue (NTXT ("name")));
753 char *grpname = dbe_strdup (attrs->getValue (NTXT ("grpname")));
754 char *prntname = dbe_strdup (attrs->getValue (NTXT ("prntname")));
755 str = attrs->getValue (NTXT ("tid"));
756 uint64_t tid = str ? strtoull (str, NULL, 0) : 0;
757 str = attrs->getValue (NTXT ("jthr"));
758 Vaddr jthr = str ? strtoull (str, NULL, 0) : 0;
759 str = attrs->getValue (NTXT ("jenv"));
760 Vaddr jenv = str ? strtoull (str, NULL, 0) : 0;
761 exp->process_jthr_start_cmd (NULL, name, grpname, prntname, tid, jthr, jenv, ts);
763 else if (strcmp (str, SP_JCMD_JTHREND) == 0)
765 str = attrs->getValue (NTXT ("tid"));
766 uint64_t tid = str ? strtoull (str, NULL, 0) : 0;
767 str = attrs->getValue (NTXT ("jthr"));
768 Vaddr jthr = str ? strtoull (str, NULL, 0) : 0;
769 str = attrs->getValue (NTXT ("jenv"));
770 Vaddr jenv = str ? strtoull (str, NULL, 0) : 0;
771 exp->process_jthr_end_cmd (NULL, tid, jthr, jenv, ts);
773 else if (strcmp (str, SP_JCMD_GCEND) == 0)
775 if (exp->getDataDescriptor (DATA_GCEVENT) == NULL)
776 exp->newDataDescriptor (DATA_GCEVENT);
777 exp->process_gc_end_cmd (ts);
779 else if (strcmp (str, SP_JCMD_GCSTART) == 0)
781 if (exp->getDataDescriptor (DATA_GCEVENT) == NULL)
782 exp->newDataDescriptor (DATA_GCEVENT);
783 exp->process_gc_start_cmd (ts);
785 else if (strcmp (str, SP_JCMD_PAUSE) == 0)
787 if (exp->resume_ts != MAX_TIME)
789 // data collection was active
790 hrtime_t delta = ts - exp->resume_ts;
791 exp->non_paused_time += delta;
792 exp->resume_ts = MAX_TIME; // collection is paused
794 StringBuilder sb;
795 str = attrs->getValue (NTXT ("name"));
796 if (str == NULL)
797 sb.sprintf (GTXT ("Pause: %ld.%09ld"), (long) (ts / NANOSEC),
798 (long) (ts % NANOSEC));
799 else
800 sb.sprintf (GTXT ("Pause (%s): %ld.%09ld"), str,
801 (long) (ts / NANOSEC), (long) (ts % NANOSEC));
802 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb));
804 else if (strcmp (str, SP_JCMD_RESUME) == 0)
806 if (exp->resume_ts == MAX_TIME)
807 // data collection was paused
808 exp->resume_ts = ts; // remember start time
809 StringBuilder sb;
810 sb.sprintf (GTXT ("Resume: %ld.%09ld"), (long) (ts / NANOSEC), (long) (ts % NANOSEC));
811 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb));
812 if (exp->exp_start_time == ZERO_TIME)
813 exp->exp_start_time = ts;
815 else if (strcmp (str, SP_JCMD_THREAD_PAUSE) == 0)
817 str = attrs->getValue (NTXT ("tid"));
818 uint64_t tid = str ? strtoull (str, NULL, 0) : 0;
819 StringBuilder sb;
820 sb.sprintf (GTXT ("Thread %llu pause: %ld.%09ld"), (unsigned long long) tid,
821 (long) (ts / NANOSEC), (long) (ts % NANOSEC));
822 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb));
824 else if (strcmp (str, SP_JCMD_THREAD_RESUME) == 0)
826 str = attrs->getValue (NTXT ("tid"));
827 uint64_t tid = str ? strtoull (str, NULL, 0) : 0;
828 StringBuilder sb;
829 sb.sprintf (GTXT ("Thread %llu resume: %ld.%09ld"), (unsigned long long) tid,
830 (long) (ts / NANOSEC), (long) (ts % NANOSEC));
831 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb));
833 else if (strcmp (str, NTXT ("map")) == 0)
835 ts += exp->exp_start_time;
836 str = attrs->getValue (NTXT ("vaddr"));
837 Vaddr vaddr = str ? strtoull (str, NULL, 0) : 0;
838 str = attrs->getValue (NTXT ("size"));
839 int msize = str ? atoi (str) : 0;
840 str = attrs->getValue (NTXT ("foffset"));
841 int64_t offset = str ? strtoll (str, NULL, 0) : 0;
842 str = attrs->getValue (NTXT ("modes"));
843 int64_t modes = str ? strtoll (str, NULL, 0) : 0;
844 str = attrs->getValue (NTXT ("chksum"));
845 int64_t chksum = 0;
846 if (str)
847 chksum = Elf::normalize_checksum (strtoll (str, NULL, 0));
848 char *name = (char *) attrs->getValue (NTXT ("name"));
849 str = attrs->getValue (NTXT ("object"));
850 if (strcmp (str, NTXT ("segment")) == 0)
852 if (strcmp (name, NTXT ("LinuxKernel")) == 0)
853 exp->process_Linux_kernel_cmd (ts);
854 else
855 exp->process_seg_map_cmd (NULL, ts, vaddr, msize, 0,
856 offset, modes, chksum, name);
858 else if (strcmp (str, NTXT ("function")) == 0)
860 exp->process_fn_load_cmd (dynfuncModule, name, vaddr, msize, ts);
861 dynfuncModule = NULL;
863 else if (strcmp (str, NTXT ("dynfunc")) == 0)
865 if (dynfuncModule == NULL)
867 dynfuncModule = dbeSession->createModule (exp->get_dynfunc_lo (DYNFUNC_SEGMENT), name);
868 dynfuncModule->flags |= MOD_FLAG_UNKNOWN;
869 dynfuncModule->set_file_name (dbe_strdup (dynfuncModule->getMainSrc ()->get_name ()));
871 (void) exp->create_dynfunc (dynfuncModule,
872 (char*) attrs->getValue (NTXT ("funcname")), vaddr, msize);
874 else if (strcmp (str, NTXT ("jcm")) == 0)
876 str = attrs->getValue (NTXT ("methodId"));
877 Vaddr mid = str ? strtoull (str, NULL, 0) : 0;
878 exp->process_jcm_load_cmd (NULL, mid, vaddr, msize, ts);
881 else if (strcmp (str, NTXT ("unmap")) == 0)
883 ts += exp->exp_start_time;
884 str = attrs->getValue (NTXT ("vaddr"));
885 Vaddr vaddr = str ? strtoull (str, NULL, 0) : 0;
886 exp->process_seg_unmap_cmd (NULL, ts, vaddr);
889 // end of code for event
891 else if (strcmp (qName, SP_TAG_PROFILE) == 0)
893 pushElem (EL_PROFILE);
894 const char *str = attrs->getValue (NTXT ("name"));
895 if (str == NULL)
896 return;
897 if (strcmp (str, NTXT ("profile")) == 0)
899 exp->coll_params.profile_mode = 1;
900 str = attrs->getValue (NTXT ("numstates"));
901 if (str != NULL)
902 exp->coll_params.lms_magic_id = atoi (str);
903 str = attrs->getValue (NTXT ("ptimer"));
904 if (str != NULL)
905 exp->coll_params.ptimer_usec = atoi (str); // microseconds
907 PropDescr *mstate_prop = NULL;
908 char * stateNames [/*LMS_NUM_STATES*/] = LMS_STATE_STRINGS;
909 char * stateUNames[/*LMS_NUM_STATES*/] = LMS_STATE_USTRINGS;
911 dDscr = exp->newDataDescriptor (DATA_CLOCK);
912 PropDescr *prop = new PropDescr (PROP_MSTATE, NTXT ("MSTATE"));
913 prop->uname = dbe_strdup (GTXT ("Thread state"));
914 prop->vtype = TYPE_UINT32;
915 // (states added below)
916 dDscr->addProperty (prop);
917 mstate_prop = prop;
919 prop = new PropDescr (PROP_NTICK, NTXT ("NTICK"));
920 prop->uname = dbe_strdup (GTXT ("Number of Profiling Ticks"));
921 prop->vtype = TYPE_UINT32;
922 dDscr->addProperty (prop);
925 switch (exp->coll_params.lms_magic_id)
927 case LMS_MAGIC_ID_SOLARIS:
928 exp->register_metric (Metric::CP_TOTAL);
929 exp->register_metric (Metric::CP_TOTAL_CPU);
930 exp->register_metric (Metric::CP_LMS_USER);
931 exp->register_metric (Metric::CP_LMS_SYSTEM);
932 exp->register_metric (Metric::CP_LMS_TRAP);
933 exp->register_metric (Metric::CP_LMS_DFAULT);
934 exp->register_metric (Metric::CP_LMS_TFAULT);
935 exp->register_metric (Metric::CP_LMS_KFAULT);
936 exp->register_metric (Metric::CP_LMS_STOPPED);
937 exp->register_metric (Metric::CP_LMS_WAIT_CPU);
938 exp->register_metric (Metric::CP_LMS_SLEEP);
939 exp->register_metric (Metric::CP_LMS_USER_LOCK);
940 for (int ii = 0; ii < LMS_NUM_SOLARIS_MSTATES; ii++)
941 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]);
942 break;
943 case LMS_MAGIC_ID_ERKERNEL_KERNEL:
944 exp->register_metric (Metric::CP_KERNEL_CPU);
946 int ii = LMS_KERNEL_CPU;
947 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]);
949 break;
950 case LMS_MAGIC_ID_ERKERNEL_USER:
951 exp->register_metric (Metric::CP_TOTAL_CPU);
952 exp->register_metric (Metric::CP_LMS_USER);
953 exp->register_metric (Metric::CP_LMS_SYSTEM);
955 int ii = LMS_KERNEL_CPU;
956 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]);
957 ii = LMS_USER;
958 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]);
959 ii = LMS_SYSTEM;
960 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]);
962 break;
963 case LMS_MAGIC_ID_LINUX:
964 exp->register_metric (Metric::CP_TOTAL_CPU);
966 int ii = LMS_LINUX_CPU;
967 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]);
969 break;
970 default:
971 // odd
972 break;
975 else if (strcmp (str, NTXT ("heaptrace")) == 0)
977 exp->coll_params.heap_mode = 1;
978 exp->leaklistavail = true;
979 exp->heapdataavail = true;
980 exp->register_metric (Metric::HEAP_ALLOC_BYTES);
981 exp->register_metric (Metric::HEAP_ALLOC_CNT);
982 exp->register_metric (Metric::HEAP_LEAK_BYTES);
983 exp->register_metric (Metric::HEAP_LEAK_CNT);
984 dDscr = exp->newDataDescriptor (DATA_HEAP);
986 else if (strcmp (str, NTXT ("iotrace")) == 0)
988 exp->coll_params.io_mode = 1;
989 exp->iodataavail = true;
990 exp->register_metric (Metric::IO_READ_TIME);
991 exp->register_metric (Metric::IO_READ_BYTES);
992 exp->register_metric (Metric::IO_READ_CNT);
993 exp->register_metric (Metric::IO_WRITE_TIME);
994 exp->register_metric (Metric::IO_WRITE_BYTES);
995 exp->register_metric (Metric::IO_WRITE_CNT);
996 exp->register_metric (Metric::IO_OTHER_TIME);
997 exp->register_metric (Metric::IO_OTHER_CNT);
998 exp->register_metric (Metric::IO_ERROR_TIME);
999 exp->register_metric (Metric::IO_ERROR_CNT);
1000 dDscr = exp->newDataDescriptor (DATA_IOTRACE);
1002 else if (strcmp (str, NTXT ("synctrace")) == 0)
1004 exp->coll_params.sync_mode = 1;
1005 str = attrs->getValue (NTXT ("threshold"));
1006 if (str != NULL)
1007 exp->coll_params.sync_threshold = atoi (str);
1008 str = attrs->getValue (NTXT ("scope"));
1009 if (str != NULL)
1010 exp->coll_params.sync_scope = atoi (str);
1011 else // Should only happen with old experiments; use the old default
1012 exp->coll_params.sync_scope = SYNCSCOPE_NATIVE | SYNCSCOPE_JAVA;
1013 exp->register_metric (Metric::SYNC_WAIT_TIME);
1014 exp->register_metric (Metric::SYNC_WAIT_COUNT);
1015 dDscr = exp->newDataDescriptor (DATA_SYNCH);
1017 else if (strcmp (str, NTXT ("omptrace")) == 0)
1019 exp->coll_params.omp_mode = 1;
1020 dDscr = exp->newDataDescriptor (DATA_OMP, DDFLAG_NOSHOW);
1022 else if (strcmp (str, NTXT ("hwcounter")) == 0)
1024 str = attrs->getValue (NTXT ("cpuver"));
1025 int cpuver = str ? atoi (str) : 0;
1026 char *counter = dbe_strdup (attrs->getValue (NTXT ("hwcname")));
1027 char *int_name = dbe_strdup (attrs->getValue (NTXT ("int_name"))); // may not be present
1028 str = attrs->getValue (NTXT ("interval"));
1029 int interval = str ? atoi (str) : 0;
1030 str = attrs->getValue (NTXT ("tag"));
1031 int tag = str ? atoi (str) : 0;
1032 str = attrs->getValue (NTXT ("memop"));
1033 int i_tpc = str ? atoi (str) : 0;
1034 char *modstr = dbe_strdup (attrs->getValue (NTXT ("modstr")));
1035 exp->process_hwcounter_cmd (NULL, cpuver, counter, int_name, interval, tag, i_tpc, modstr);
1036 dDscr = exp->newDataDescriptor (DATA_HWC);
1038 else if (strcmp (str, NTXT ("hwsimctr")) == 0)
1040 int cpuver = toInt (attrs, NTXT ("cpuver"));
1041 char *hwcname = dbe_strdup (attrs->getValue (NTXT ("hwcname")));
1042 char *int_name = dbe_strdup (attrs->getValue (NTXT ("int_name")));
1043 char *metric = dbe_strdup (attrs->getValue (NTXT ("metric")));
1044 int reg = toInt (attrs, NTXT ("reg_num"));
1045 int interval = toInt (attrs, NTXT ("interval"));
1046 int timecvt = toInt (attrs, NTXT ("timecvt"));
1047 int i_tpc = toInt (attrs, NTXT ("memop"));
1048 int tag = toInt (attrs, NTXT ("tag"));
1049 exp->process_hwsimctr_cmd (NULL, cpuver, hwcname, int_name, metric, reg,
1050 interval, timecvt, i_tpc, tag);
1051 dDscr = exp->newDataDescriptor (DATA_HWC);
1053 else if (strcmp (str, NTXT ("dversion")) == 0)
1054 exp->dversion = dbe_strdup (attrs->getValue (NTXT ("version")));
1055 else if (strcmp (str, NTXT ("jprofile")) == 0)
1057 exp->has_java = true;
1058 str = attrs->getValue (NTXT ("jversion"));
1059 if (str != NULL)
1060 exp->jversion = xstrdup (str);
1062 else if (strcmp (str, NTXT ("datarace")) == 0)
1064 exp->coll_params.race_mode = 1;
1065 exp->racelistavail = true;
1066 str = attrs->getValue (NTXT ("scheme"));
1067 exp->coll_params.race_stack = str ? atoi (str) : 0;
1068 exp->register_metric (Metric::RACCESS);
1069 dDscr = exp->newDataDescriptor (DATA_RACE);
1071 else if (strcmp (str, NTXT ("deadlock")) == 0)
1073 exp->coll_params.deadlock_mode = 1;
1074 exp->deadlocklistavail = true;
1075 exp->register_metric (Metric::DEADLOCKS);
1076 dDscr = exp->newDataDescriptor (DATA_DLCK);
1079 /* XXX -- obsolete tag, but is still written to experiments */
1080 else if (strcmp (qName, SP_TAG_DATAPTR) == 0)
1082 pushElem (EL_DATAPTR);
1083 return;
1085 else if (strcmp (qName, SP_TAG_PROFDATA) == 0)
1087 pushElem (EL_PROFDATA);
1088 // SS12 HWC experiments are not well structured
1089 const char *fname = attrs->getValue (NTXT ("fname"));
1090 if (fname && strcmp (fname, SP_HWCNTR_FILE) == 0)
1091 dDscr = exp->newDataDescriptor (DATA_HWC);
1093 else if (strcmp (qName, SP_TAG_PROFPCKT) == 0)
1095 pushElem (EL_PROFPCKT);
1096 const char *str = attrs->getValue (NTXT ("kind")); // see Pckt_type
1097 int kind = str ? atoi (str) : -1;
1098 if (kind < 0)
1099 return;
1100 if (exp->coll_params.omp_mode == 1)
1102 if (kind == OMP_PCKT)
1103 dDscr = exp->newDataDescriptor (DATA_OMP, DDFLAG_NOSHOW);
1104 else if (kind == OMP2_PCKT)
1105 dDscr = exp->newDataDescriptor (DATA_OMP2, DDFLAG_NOSHOW);
1106 else if (kind == OMP3_PCKT)
1107 dDscr = exp->newDataDescriptor (DATA_OMP3, DDFLAG_NOSHOW);
1108 else if (kind == OMP4_PCKT)
1109 dDscr = exp->newDataDescriptor (DATA_OMP4, DDFLAG_NOSHOW);
1110 else if (kind == OMP5_PCKT)
1111 dDscr = exp->newDataDescriptor (DATA_OMP5, DDFLAG_NOSHOW);
1113 pDscr = exp->newPacketDescriptor (kind, dDscr);
1114 return;
1116 else if (strcmp (qName, SP_TAG_FIELD) == 0)
1118 pushElem (EL_FIELD);
1119 if (pDscr != NULL)
1121 const char *name = attrs->getValue (NTXT ("name"));
1122 if (name == NULL)
1123 return;
1124 int propID = dbeSession->registerPropertyName (name);
1125 propDscr = new PropDescr (propID, name);
1126 FieldDescr *fldDscr = new FieldDescr (propID, name);
1128 const char *str = attrs->getValue (NTXT ("type"));
1129 if (str)
1131 if (strcmp (str, NTXT ("INT32")) == 0)
1132 fldDscr->vtype = TYPE_INT32;
1133 else if (strcmp (str, NTXT ("UINT32")) == 0)
1134 fldDscr->vtype = TYPE_UINT32;
1135 else if (strcmp (str, NTXT ("INT64")) == 0)
1136 fldDscr->vtype = TYPE_INT64;
1137 else if (strcmp (str, NTXT ("UINT64")) == 0)
1138 fldDscr->vtype = TYPE_UINT64;
1139 else if (strcmp (str, NTXT ("STRING")) == 0)
1140 fldDscr->vtype = TYPE_STRING;
1141 else if (strcmp (str, NTXT ("DOUBLE")) == 0)
1142 fldDscr->vtype = TYPE_DOUBLE;
1143 else if (strcmp (str, NTXT ("DATE")) == 0)
1145 fldDscr->vtype = TYPE_DATE;
1146 const char *fmt = attrs->getValue (NTXT ("format"));
1147 fldDscr->format = xstrdup (fmt ? fmt : "");
1150 propDscr->vtype = fldDscr->vtype;
1152 // TYPE_DATE is converted to TYPE_UINT64 in propDscr
1153 if (fldDscr->vtype == TYPE_DATE)
1154 propDscr->vtype = TYPE_UINT64;
1156 // Fix some types until they are fixed in libcollector
1157 if (propID == PROP_VIRTPC || propID == PROP_PHYSPC)
1159 if (fldDscr->vtype == TYPE_INT32)
1160 propDscr->vtype = TYPE_UINT32;
1161 else if (fldDscr->vtype == TYPE_INT64)
1162 propDscr->vtype = TYPE_UINT64;
1165 // The following props get mapped to 32-bit values in readPacket
1166 if (propID == PROP_CPUID || propID == PROP_THRID
1167 || propID == PROP_LWPID)
1168 propDscr->vtype = TYPE_UINT32; // override experiment property
1170 str = attrs->getValue (NTXT ("uname"));
1171 if (str)
1172 propDscr->uname = xstrdup (PTXT ((char*) str));
1173 str = attrs->getValue (NTXT ("noshow"));
1174 if (str && atoi (str) != 0)
1175 propDscr->flags |= PRFLAG_NOSHOW;
1177 if (dDscr == NULL)
1179 StringBuilder sb;
1180 sb.sprintf (GTXT ("*** Error: data parsing failed. Log file is corrupted."));
1181 exp->warnq->append (new Emsg (CMSG_ERROR, sb));
1182 throw new SAXException (sb.toString ());
1185 dDscr->addProperty (propDscr);
1186 str = attrs->getValue (NTXT ("offset"));
1187 if (str)
1188 fldDscr->offset = atoi (str);
1189 pDscr->addField (fldDscr);
1192 else if (strcmp (qName, SP_TAG_STATE) == 0)
1194 pushElem (EL_STATE);
1195 if (propDscr != NULL)
1197 const char *str = attrs->getValue (NTXT ("value"));
1198 int value = str ? atoi (str) : -1;
1199 str = attrs->getValue (NTXT ("name"));
1200 const char *ustr = attrs->getValue (NTXT ("uname"));
1201 propDscr->addState (value, str, ustr);
1204 else if (strcmp (qName, SP_TAG_DTRACEFATAL) == 0)
1205 pushElem (EL_DTRACEFATAL);
1206 else
1208 StringBuilder sb;
1209 sb.sprintf (GTXT ("*** Warning: unrecognized element %s"), qName);
1210 exp->warnq->append (new Emsg (CMSG_WARN, sb));
1211 pushElem (EL_NONE);
1215 void
1216 Experiment::ExperimentHandler::characters (char *ch, int start, int length)
1218 switch (curElem)
1220 case EL_COLLECTOR:
1221 exp->cversion = dbe_strndup (ch + start, length);
1222 break;
1223 case EL_PROCESS:
1224 exp->process_arglist_cmd (NULL, dbe_strndup (ch + start, length));
1225 break;
1226 case EL_EVENT:
1227 free (text);
1228 text = dbe_strndup (ch + start, length);
1229 break;
1230 default:
1231 break;
1235 void
1236 Experiment::ExperimentHandler::endElement (char*, char*, char*)
1238 if (curElem == EL_EVENT && mkind != CMSG_NONE && mnum >= 0)
1240 char *str;
1241 if (mec > 0)
1242 str = dbe_sprintf ("%s -- %s", text != NULL ? text : "", strerror (mec));
1243 else
1244 str = dbe_sprintf ("%s", text != NULL ? text : "");
1245 Emsg *msg = new Emsg (mkind, mnum, str);
1246 if (mkind == CMSG_WARN)
1248 if (mnum != COL_WARN_FSTYPE
1249 || dbeSession->check_ignore_fs_warn () == false)
1250 exp->warnq->append (msg);
1251 else
1252 exp->commentq->append (msg);
1254 else if (mkind == CMSG_ERROR || mkind == CMSG_FATAL)
1255 exp->errorq->append (msg);
1256 else if (mkind == CMSG_COMMENT)
1257 exp->commentq->append (msg);
1258 else
1259 delete msg;
1260 mkind = CMSG_NONE;
1261 mnum = -1;
1262 mec = -1;
1264 else if (curElem == EL_PROFILE)
1265 dDscr = NULL;
1266 else if (curElem == EL_PROFPCKT)
1267 pDscr = NULL;
1268 else if (curElem == EL_FIELD)
1269 propDscr = NULL;
1270 free (text);
1271 text = NULL;
1272 popElem ();
1275 void
1276 Experiment::ExperimentHandler::error (SAXParseException *e)
1278 StringBuilder sb;
1279 sb.sprintf (GTXT ("%s at line %d, column %d"),
1280 e->getMessage (), e->getLineNumber (), e->getColumnNumber ());
1281 char *msg = sb.toString ();
1282 SAXException *e1 = new SAXException (msg);
1283 free (msg);
1284 throw ( e1);
1287 //-------------------------------------------------- Experiment
1289 Experiment::Experiment ()
1291 groupId = 0;
1292 userExpId = expIdx = -1;
1293 founder_exp = NULL;
1294 baseFounder = NULL;
1295 children_exps = new Vector<Experiment*>;
1296 loadObjs = new Vector<LoadObject*>;
1297 loadObjMap = new StringMap<LoadObject*>(128, 128);
1298 sourcesMap = NULL;
1300 // Initialize configuration information.
1301 status = FAILURE;
1302 start_sec = 0;
1303 mtime = 0;
1304 hostname = NULL;
1305 username = NULL;
1306 architecture = NULL;
1307 os_version = NULL;
1308 uarglist = NULL;
1309 utargname = NULL;
1310 ucwd = NULL;
1311 cversion = NULL;
1312 dversion = NULL;
1313 jversion = NULL;
1314 exp_maj_version = 0;
1315 exp_min_version = 0;
1316 platform = Unknown;
1317 wsize = Wnone;
1318 page_size = 4096;
1319 npages = 0;
1320 stack_base = 0xf0000000;
1321 broken = 1;
1322 obsolete = 0;
1323 hwc_bogus = 0;
1324 hwc_lost_int = 0;
1325 hwc_scanned = 0;
1326 hwc_default = false;
1327 invalid_packet = 0;
1329 // clear HWC event stats
1330 dsevents = 0;
1331 dsnoxhwcevents = 0;
1333 memset (&coll_params, 0, sizeof (coll_params));
1334 ncpus = 0;
1335 minclock = 0;
1336 maxclock = 0;
1337 clock = 0;
1338 varclock = 0;
1339 exec_started = false;
1340 timelineavail = true;
1341 leaklistavail = false;
1342 heapdataavail = false;
1343 iodataavail = false;
1344 dataspaceavail = false;
1345 ifreqavail = false;
1346 racelistavail = false;
1347 deadlocklistavail = false;
1348 ompavail = false;
1349 tiny_threshold = -1;
1350 pid = 0;
1351 ppid = 0;
1352 pgrp = 0;
1353 sid = 0;
1355 gc_duration = ZERO_TIME;
1356 exp_start_time = ZERO_TIME; // not known. Wall-clock hrtime (not zero based)
1357 last_event = ZERO_TIME; // not known. Wall-clock hrtime (not zero based)
1358 non_paused_time = 0; // 0 non-paused time (will sum as experiment is processed)
1359 resume_ts = 0; // by default, collection is "resumed" (not paused) from time=0
1360 need_swap_endian = false;
1361 exp_rel_start_time_set = false;
1362 exp_rel_start_time = ZERO_TIME;
1363 has_java = false;
1364 hex_field_width = 8;
1365 hw_cpuver = CPUVER_UNDEFINED;
1366 machinemodel = NULL;
1367 expt_name = NULL;
1368 arch_name = NULL;
1369 fndr_arch_name = NULL;
1370 dyntext_name = NULL;
1371 logFile = NULL;
1373 dataDscrs = new Vector<DataDescriptor*>;
1374 for (int i = 0; i < DATA_LAST; ++i)
1375 dataDscrs->append (NULL);
1377 pcktDscrs = new Vector<PacketDescriptor*>;
1378 blksz = PROFILE_BUFFER_CHUNK;
1379 jthreads = new Vector<JThread*>;
1380 jthreads_idx = new Vector<JThread*>;
1381 gcevents = new Vector<GCEvent*>;
1382 gcevent_last_used = (GCEvent *) NULL;
1383 heapUnmapEvents = new Vector<UnmapChunk*>;
1384 cstack = NULL;
1385 cstackShowHide = NULL;
1386 frmpckts = new Vector<RawFramePacket*>;
1387 typedef DefaultMap2D<uint32_t, hrtime_t, uint64_t> OmpMap0;
1388 mapPRid = new OmpMap0 (OmpMap0::Interval);
1389 typedef DefaultMap2D<uint32_t, hrtime_t, void*> OmpMap;
1390 mapPReg = new OmpMap (OmpMap::Interval);
1391 mapTask = new OmpMap (OmpMap::Interval);
1392 openMPdata = NULL;
1393 archiveMap = NULL;
1394 nnodes = 0;
1395 nchunks = 0;
1396 chunks = NULL;
1397 uidHTable = NULL;
1398 uidnodes = new Vector<UIDnode*>;
1399 mrecs = new Vector<MapRecord*>;
1400 samples = new Vector<Sample*>;
1401 sample_last_used = (Sample *) NULL;
1402 first_sample_label = (char*) NULL;
1403 fDataMap = NULL;
1404 vFdMap = NULL;
1405 resolveFrameInfo = true;
1406 discardTiny = false;
1407 init ();
1410 Experiment::~Experiment ()
1412 fini ();
1413 free (coll_params.linetrace);
1414 for (int i = 0; i < MAX_HWCOUNT; i++)
1416 free (coll_params.hw_aux_name[i]);
1417 free (coll_params.hw_username[i]);
1419 free (hostname);
1420 free (username);
1421 free (architecture);
1422 free (os_version);
1423 free (uarglist);
1424 free (utargname);
1425 free (ucwd);
1426 free (cversion);
1427 free (dversion);
1428 free (jversion);
1429 delete logFile;
1430 free (expt_name);
1431 free (arch_name);
1432 free (fndr_arch_name);
1433 free (dyntext_name);
1434 delete jthreads_idx;
1435 delete cstack;
1436 delete cstackShowHide;
1437 delete mapPRid;
1438 delete mapPReg;
1439 delete mapTask;
1440 delete openMPdata;
1441 destroy_map (DbeFile *, archiveMap);
1442 delete[] uidHTable;
1443 delete uidnodes;
1444 delete mrecs;
1445 delete children_exps;
1446 delete loadObjs;
1447 delete loadObjMap;
1448 delete sourcesMap;
1449 free (first_sample_label);
1450 free (machinemodel);
1452 dataDscrs->destroy ();
1453 delete dataDscrs;
1454 pcktDscrs->destroy ();
1455 delete pcktDscrs;
1456 jthreads->destroy ();
1457 delete jthreads;
1458 gcevents->destroy ();
1459 delete gcevents;
1460 heapUnmapEvents->destroy ();
1461 delete heapUnmapEvents;
1462 frmpckts->destroy ();
1463 delete frmpckts;
1464 samples->destroy ();
1465 delete samples;
1466 delete fDataMap;
1467 delete vFdMap;
1469 for (long i = 0; i < nchunks; i++)
1470 delete[] chunks[i];
1471 delete[] chunks;
1474 void
1475 Experiment::init_cache ()
1477 if (smemHTable)
1478 return;
1479 smemHTable = new SegMem*[HTableSize];
1480 instHTable = new DbeInstr*[HTableSize];
1481 for (int i = 0; i < HTableSize; i++)
1483 smemHTable[i] = NULL;
1484 instHTable[i] = NULL;
1486 uidHTable = new UIDnode*[HTableSize];
1487 for (int i = 0; i < HTableSize; i++)
1488 uidHTable[i] = NULL;
1490 cstack = CallStack::getInstance (this);
1491 cstackShowHide = CallStack::getInstance (this);
1494 void
1495 Experiment::init ()
1497 userLabels = NULL;
1498 seg_items = new Vector<SegMem*>;
1499 maps = new PRBTree ();
1500 jmaps = NULL; // used by JAVA_CLASSES only
1501 jmidHTable = NULL;
1502 smemHTable = NULL;
1503 instHTable = NULL;
1504 min_thread = (uint64_t) - 1;
1505 max_thread = 0;
1506 thread_cnt = 0;
1507 min_lwp = (uint64_t) - 1;
1508 max_lwp = 0;
1509 lwp_cnt = 0;
1510 min_cpu = (uint64_t) - 1;
1511 max_cpu = 0;
1512 cpu_cnt = 0;
1514 commentq = new Emsgqueue (NTXT ("commentq"));
1515 runlogq = new Emsgqueue (NTXT ("runlogq"));
1516 errorq = new Emsgqueue (NTXT ("errorq"));
1517 warnq = new Emsgqueue (NTXT ("warnq"));
1518 notesq = new Emsgqueue (NTXT ("notesq"));
1519 pprocq = new Emsgqueue (NTXT ("pprocq"));
1520 ifreqq = NULL;
1522 metrics = new Vector<BaseMetric*>;
1523 tagObjs = new Vector<Vector<Histable*>*>;
1524 tagObjs->store (PROP_THRID, new Vector<Histable*>);
1525 tagObjs->store (PROP_LWPID, new Vector<Histable*>);
1526 tagObjs->store (PROP_CPUID, new Vector<Histable*>);
1527 tagObjs->store (PROP_EXPID, new Vector<Histable*>);
1528 sparse_threads = false;
1531 void
1532 Experiment::fini ()
1534 seg_items->destroy ();
1535 delete seg_items;
1536 delete maps;
1537 delete jmaps;
1538 delete[] smemHTable;
1539 delete[] instHTable;
1540 delete jmidHTable;
1541 delete commentq;
1542 delete runlogq;
1543 delete errorq;
1544 delete warnq;
1545 delete notesq;
1546 delete pprocq;
1547 if (ifreqq != NULL)
1549 delete ifreqq;
1550 ifreqq = NULL;
1553 int index;
1554 BaseMetric *mtr;
1555 Vec_loop (BaseMetric*, metrics, index, mtr)
1557 dbeSession->drop_metric (mtr);
1559 delete metrics;
1560 tagObjs->fetch (PROP_THRID)->destroy ();
1561 tagObjs->fetch (PROP_LWPID)->destroy ();
1562 tagObjs->fetch (PROP_CPUID)->destroy ();
1563 tagObjs->fetch (PROP_EXPID)->destroy ();
1564 tagObjs->destroy ();
1565 delete tagObjs;
1568 // These are the data files which can be read in parallel
1569 // for multiple sub-experiments.
1570 // Postpone calling resolve_frame_info()
1571 void
1572 Experiment::read_experiment_data (bool read_ahead)
1575 read_frameinfo_file ();
1576 if (read_ahead)
1578 resolveFrameInfo = false;
1579 (void) get_profile_events ();
1580 resolveFrameInfo = true;
1584 Experiment::Exp_status
1585 Experiment::open_epilogue ()
1588 // set up mapping for tagObj(PROP_EXPID)
1589 (void) mapTagValue (PROP_EXPID, userExpId);
1591 post_process ();
1592 if (last_event != ZERO_TIME)
1593 { // if last_event is known
1594 StringBuilder sb;
1595 hrtime_t ts = last_event - exp_start_time;
1596 sb.sprintf (GTXT ("Experiment Ended: %ld.%09ld\nData Collection Duration: %ld.%09ld"),
1597 (long) (ts / NANOSEC), (long) (ts % NANOSEC),
1598 (long) (non_paused_time / NANOSEC),
1599 (long) (non_paused_time % NANOSEC));
1600 runlogq->append (new Emsg (CMSG_COMMENT, sb));
1603 // Check for incomplete experiment, and inform the user
1604 if (status == INCOMPLETE)
1606 if (exec_started == true)
1607 // experiment ended with the exec, not abnormally
1608 status = SUCCESS;
1609 else
1611 char * cmnt = GTXT ("*** Note: experiment was not closed");
1612 commentq->append (new Emsg (CMSG_COMMENT, cmnt));
1613 // runlogq->append(new Emsg(CMSG_COMMENT, cmnt));
1616 // write a descriptive header for the experiment
1617 write_header ();
1618 return status;
1621 Experiment::Exp_status
1622 Experiment::open (char *path)
1625 // Find experiment directory
1626 if (find_expdir (path) != SUCCESS)
1627 // message will have been queued and status set
1628 return status;
1630 // Get creation time for experiment
1631 dbe_stat_t st;
1632 if (dbe_stat (path, &st) == 0)
1633 mtime = st.st_mtime;
1635 // Read the warnings file
1636 read_warn_file ();
1638 // Open the log file
1639 read_log_file ();
1640 if (status == SUCCESS && last_event // last event is initialized
1641 && (last_event - exp_start_time) / 1000000 < tiny_threshold)
1643 // Process "tiny_threshold" (SP_ANALYZER_DISCARD_TINY_EXPERIMENTS)
1644 // At this point, we've only processed log.xml.
1645 // Note: if an experiment terminated abnormally, last_event will not yet
1646 // represent events from clock profiling and other metrics.
1647 // Other events will often have timestamps after the last log.xml entry.
1648 discardTiny = true;
1649 return status;
1651 if (status == FAILURE)
1653 if (logFile->get_status () == ExperimentFile::EF_FAILURE)
1655 Emsg *m = new Emsg (CMSG_FATAL, GTXT ("*** Error: log file in experiment cannot be read"));
1656 errorq->append (m);
1658 else if (fetch_errors () == NULL)
1660 if (broken == 1)
1662 Emsg *m = new Emsg (CMSG_FATAL, GTXT ("*** Error: log does not show target starting"));
1663 errorq->append (m);
1665 else
1667 Emsg *m = new Emsg (CMSG_FATAL, GTXT ("*** Error: log file in experiment could not be parsed"));
1668 errorq->append (m);
1671 return status;
1673 init_cache ();
1674 if (varclock != 0)
1676 StringBuilder sb;
1677 sb.sprintf (
1678 GTXT ("*** Warning: system has variable clock frequency, which may cause variable execution times and inaccurate conversions of cycle counts into time."));
1679 warnq->append (new Emsg (CMSG_WARN, sb));
1682 // Read the notes file
1683 read_notes_file ();
1684 read_labels_file ();
1685 read_archives ();
1687 // The log file shows experiment started
1688 read_java_classes_file ();
1690 read_map_file ();
1692 // Dyntext file has to be processed after loadobjects file
1693 // as we need to be able to map (vaddr,ts) to dynamic functions.
1694 read_dyntext_file ();
1696 // Read the overview file and create samples.
1697 // Profiling data hasn't been read yet so we may have
1698 // events after the last recorded sample.
1699 // We'll create a fake sample to cover all those
1700 // events later.
1701 read_overview_file ();
1703 // Check if instruction frequency data is available
1704 read_ifreq_file ();
1706 // Check if OMP data is available
1707 read_omp_file ();
1709 return status;
1712 /* XXX -- update() is a no-op now, but may be needed for auto-update */
1713 Experiment::Exp_status
1714 Experiment::update ()
1716 return status;
1719 void
1720 Experiment::append (LoadObject *lo)
1722 loadObjs->append (lo);
1723 char *obj_name = lo->get_pathname ();
1724 char *bname = get_basename (obj_name);
1725 loadObjMap->put (obj_name, lo);
1726 loadObjMap->put (bname, lo);
1727 if (lo->flags & SEG_FLAG_EXE)
1728 loadObjMap->put (COMP_EXE_NAME, lo);
1731 void
1732 Experiment::read_notes_file ()
1734 Emsg *m;
1736 // Open log file:
1737 char *fname = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_NOTES_FILE);
1738 FILE *f = fopen (fname, NTXT ("r"));
1739 free (fname);
1740 if (f == NULL)
1741 return;
1742 if (!dbeSession->is_interactive ())
1744 m = new Emsg (CMSG_COMMENT, NTXT ("Notes:"));
1745 notesq->append (m);
1748 while (1)
1750 char str[MAXPATHLEN];
1751 char *e = fgets (str, ((int) sizeof (str)) - 1, f);
1752 if (e == NULL)
1754 if (!dbeSession->is_interactive ())
1756 m = new Emsg (CMSG_COMMENT,
1757 "============================================================");
1758 notesq->append (m);
1760 break;
1762 size_t i = strlen (str);
1763 if (i > 0 && str[i - 1] == '\n')
1764 // remove trailing nl
1765 str[i - 1] = 0;
1766 m = new Emsg (CMSG_COMMENT, str);
1767 notesq->append (m);
1769 (void) fclose (f);
1773 Experiment::save_notes (char* text, bool handle_file)
1775 if (handle_file)
1777 FILE *fnotes;
1778 char *fname = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_NOTES_FILE);
1779 fnotes = fopen (fname, NTXT ("w"));
1780 free (fname);
1781 if (fnotes != NULL)
1783 (void) fprintf (fnotes, NTXT ("%s"), text);
1784 fclose (fnotes);
1786 else
1787 return 1; // Cannot write file
1789 notesq->clear ();
1790 Emsg *m = new Emsg (CMSG_COMMENT, text);
1791 notesq->append (m);
1793 return 0;
1797 Experiment::delete_notes (bool handle_file)
1799 if (handle_file)
1801 char *fname = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_NOTES_FILE);
1802 if (unlink (fname) != 0)
1804 free (fname);
1805 return 1; // Cannot delete file
1807 free (fname);
1809 notesq->clear ();
1810 return 0;
1814 Experiment::read_warn_file ()
1816 int local_status = SUCCESS;
1818 ExperimentFile *warnFile = new ExperimentFile (this, SP_WARN_FILE);
1819 if (warnFile == NULL)
1820 return FAILURE;
1821 if (!warnFile->open ())
1823 delete warnFile;
1824 return FAILURE;
1826 SAXParserFactory *factory = SAXParserFactory::newInstance ();
1827 SAXParser *saxParser = factory->newSAXParser ();
1828 DefaultHandler *dh = new ExperimentHandler (this);
1831 saxParser->parse ((File*) warnFile->fh, dh);
1833 catch (SAXException *e)
1835 // Fatal error in the parser
1836 StringBuilder sb;
1837 sb.sprintf (NTXT ("%s: %s"), SP_WARN_FILE, e->getMessage ());
1838 char *str = sb.toString ();
1839 Emsg *m = new Emsg (CMSG_FATAL, str);
1840 errorq->append (m);
1841 local_status = FAILURE;
1842 delete e;
1844 delete warnFile;
1845 delete dh;
1846 delete saxParser;
1847 delete factory;
1849 return local_status;
1853 Experiment::read_log_file ()
1855 if (logFile == NULL)
1856 logFile = new ExperimentFile (this, SP_LOG_FILE);
1857 if (!logFile->open ())
1859 status = FAILURE;
1860 return status;
1863 SAXParserFactory *factory = SAXParserFactory::newInstance ();
1864 SAXParser *saxParser = factory->newSAXParser ();
1865 DefaultHandler *dh = new ExperimentHandler (this);
1868 saxParser->parse ((File*) logFile->fh, dh);
1870 catch (SAXException *e)
1872 // Fatal error in the parser
1873 StringBuilder sb;
1874 if (obsolete == 1)
1875 sb.sprintf (NTXT ("%s"), e->getMessage ());
1876 else
1877 sb.sprintf (NTXT ("%s: %s"), SP_LOG_FILE, e->getMessage ());
1878 char *str = sb.toString ();
1879 Emsg *m = new Emsg (CMSG_FATAL, str);
1880 errorq->append (m);
1881 status = FAILURE;
1882 delete e;
1884 logFile->close ();
1885 dbeSession->register_metric (GTXT ("IPC"), GTXT ("Instructions Per Cycle"),
1886 NTXT ("insts/cycles"));
1887 dbeSession->register_metric (GTXT ("CPI"), GTXT ("Cycles Per Instruction"),
1888 NTXT ("cycles/insts"));
1889 dbeSession->register_metric (GTXT ("K_IPC"),
1890 GTXT ("Kernel Instructions Per Cycle"),
1891 NTXT ("K_insts/K_cycles"));
1892 dbeSession->register_metric (GTXT ("K_CPI"),
1893 GTXT ("Kernel Cycles Per Instruction"),
1894 NTXT ("K_cycles/K_insts"));
1896 delete dh;
1897 delete saxParser;
1898 delete factory;
1900 return status;
1903 ////////////////////////////////////////////////////////////////////////////////
1904 // class Experiment::ExperimentLabelsHandler
1907 class Experiment::ExperimentLabelsHandler : public DefaultHandler
1909 public:
1911 ExperimentLabelsHandler (Experiment *_exp)
1913 exp = _exp;
1916 ~ExperimentLabelsHandler () { };
1917 void startDocument () { }
1918 void endDocument () { }
1919 void endElement (char * /*uri*/, char * /*localName*/, char * /*qName*/) { }
1920 void characters (char * /*ch*/, int /*start*/, int /*length*/) { }
1921 void ignorableWhitespace (char*, int, int) { }
1922 void error (SAXParseException * /*e*/) { }
1924 void startElement (char *uri, char *localName, char *qName, Attributes *attrs);
1926 private:
1928 inline const char *
1929 s2s (const char *s)
1931 return s ? s : "NULL";
1934 Experiment *exp;
1937 void
1938 Experiment::ExperimentLabelsHandler::startElement (char*, char*, char *qName,
1939 Attributes *attrs)
1941 DEBUG_CODE if (DEBUG_SAXPARSER) dump_startElement (qName, attrs);
1942 if (qName == NULL || strcmp (qName, NTXT ("id")) != 0)
1943 return;
1944 char *name = NULL, *all_times = NULL, *comment = NULL, *hostName = NULL;
1945 long startSec = 0;
1946 // long tm_zone = 0;
1947 hrtime_t startHrtime = (hrtime_t) 0;
1948 long long lbl_ts = 0;
1949 int relative = 0;
1950 timeval start_tv;
1951 start_tv.tv_usec = start_tv.tv_sec = 0;
1952 for (int i = 0, sz = attrs ? attrs->getLength () : 0; i < sz; i++)
1954 const char *qn = attrs->getQName (i);
1955 const char *vl = attrs->getValue (i);
1956 if (strcmp (qn, NTXT ("name")) == 0)
1957 name = dbe_xml2str (vl);
1958 else if (strcmp (qn, NTXT ("cmd")) == 0)
1959 all_times = dbe_xml2str (vl);
1960 else if (strcmp (qn, NTXT ("comment")) == 0)
1961 comment = dbe_xml2str (vl);
1962 else if (strcmp (qn, NTXT ("relative")) == 0)
1963 relative = atoi (vl);
1964 else if (strcmp (qn, NTXT ("hostname")) == 0)
1965 hostName = dbe_xml2str (vl);
1966 else if (strcmp (qn, NTXT ("time")) == 0)
1967 startSec = atol (vl);
1968 else if (strcmp (qn, NTXT ("tstamp")) == 0)
1969 startHrtime = parseTStamp (vl);
1970 else if (strcmp (qn, NTXT ("lbl_ts")) == 0)
1972 if (*vl == '-')
1973 lbl_ts = -parseTStamp (vl + 1);
1974 else
1975 lbl_ts = parseTStamp (vl);
1978 if (name == NULL || hostName == NULL || (all_times == NULL && comment == NULL))
1980 free (name);
1981 free (hostName);
1982 free (all_times);
1983 free (comment);
1984 return;
1986 UserLabel *lbl = new UserLabel (name);
1987 lbl->comment = comment;
1988 lbl->hostname = hostName;
1989 lbl->start_sec = startSec;
1990 lbl->start_hrtime = startHrtime;
1991 exp->userLabels->append (lbl);
1992 if (all_times)
1994 lbl->all_times = all_times;
1995 lbl->start_tv = start_tv;
1996 lbl->relative = relative;
1997 if (relative == UserLabel::REL_TIME)
1998 lbl->atime = lbl_ts;
1999 else
2000 { // relative == UserLabel::CUR_TIME
2001 long long delta = 0;
2002 if (exp->hostname && strcmp (lbl->hostname, exp->hostname) == 0)
2003 delta = lbl_ts + (lbl->start_hrtime - exp->exp_start_time);
2004 else
2005 for (int i = 0; i < exp->userLabels->size (); i++)
2007 UserLabel *firstLbl = exp->userLabels->fetch (i);
2008 if (strcmp (lbl->hostname, firstLbl->hostname) == 0)
2010 delta = lbl_ts + (lbl->start_hrtime - firstLbl->start_hrtime) +
2011 ((long long) (firstLbl->start_sec - exp->start_sec)) * NANOSEC;
2012 break;
2015 lbl->atime = delta > 0 ? delta : 0;
2020 static int
2021 sortUserLabels (const void *a, const void *b)
2023 UserLabel *l1 = *((UserLabel **) a);
2024 UserLabel *l2 = *((UserLabel **) b);
2025 int v = dbe_strcmp (l1->name, l2->name);
2026 if (v != 0)
2027 return v;
2028 if (l1->atime < l2->atime)
2029 return -1;
2030 else if (l1->atime > l2->atime)
2031 return 1;
2032 if (l1->id < l2->id)
2033 return -1;
2034 else if (l1->id > l2->id)
2035 return 1;
2036 return 0;
2039 static char *
2040 append_string (char *s, char *str)
2042 if (s == NULL)
2043 return dbe_strdup (str);
2044 char *new_s = dbe_sprintf (NTXT ("%s %s"), s, str);
2045 free (s);
2046 return new_s;
2049 void
2050 Experiment::read_labels_file ()
2052 ExperimentFile *fp = new ExperimentFile (this, SP_LABELS_FILE);
2053 if (!fp->open ())
2055 delete fp;
2056 return;
2058 userLabels = new Vector<UserLabel*>();
2059 SAXParserFactory *factory = SAXParserFactory::newInstance ();
2060 SAXParser *saxParser = factory->newSAXParser ();
2061 DefaultHandler *dh = new ExperimentLabelsHandler (this);
2064 saxParser->parse ((File*) fp->fh, dh);
2066 catch (SAXException *e)
2068 // Fatal error in the parser
2069 StringBuilder sb;
2070 sb.sprintf (NTXT ("%s: %s"), SP_LABELS_FILE, e->getMessage ());
2071 char *str = sb.toString ();
2072 Emsg *m = new Emsg (CMSG_FATAL, str);
2073 errorq->append (m);
2074 delete e;
2076 fp->close ();
2077 delete fp;
2078 delete dh;
2079 delete saxParser;
2080 delete factory;
2082 userLabels->sort (sortUserLabels);
2083 UserLabel::dump ("After sortUserLabels:", userLabels);
2084 UserLabel *ulbl = NULL;
2085 for (int i = 0, sz = userLabels->size (); i < sz; i++)
2087 UserLabel *lbl = userLabels->fetch (i);
2088 if (ulbl == NULL)
2089 ulbl = new UserLabel (lbl->name);
2090 else if (dbe_strcmp (lbl->name, ulbl->name) != 0)
2091 { // new Label
2092 ulbl->register_user_label (groupId);
2093 if (ulbl->expr == NULL)
2094 delete ulbl;
2095 ulbl = new UserLabel (lbl->name);
2097 if (lbl->all_times)
2099 if (strncmp (lbl->all_times, NTXT ("start"), 5) == 0)
2101 if (!ulbl->start_f)
2103 ulbl->start_f = true;
2104 ulbl->timeStart = lbl->atime;
2107 else
2108 { // stop
2109 if (!ulbl->start_f)
2110 continue;
2111 ulbl->all_times = append_string (ulbl->all_times, lbl->all_times);
2112 ulbl->stop_f = true;
2113 ulbl->timeStop = lbl->atime;
2114 ulbl->gen_expr ();
2117 if (lbl->comment != NULL)
2118 ulbl->comment = append_string (ulbl->comment, lbl->comment);
2120 if (ulbl)
2122 ulbl->register_user_label (groupId);
2123 if (ulbl->expr == NULL)
2124 delete ulbl;
2126 Destroy (userLabels);
2129 void
2130 Experiment::read_archives ()
2132 if (founder_exp)
2133 return;
2134 char *allocated_str = NULL;
2135 char *nm = get_arch_name ();
2136 DIR *exp_dir = opendir (nm);
2137 if (exp_dir == NULL)
2139 if (founder_exp == NULL)
2141 // Check if the user uses a subexperiment only
2142 nm = dbe_sprintf (NTXT ("%s/../%s"), expt_name, SP_ARCHIVES_DIR);
2143 exp_dir = opendir (nm);
2144 if (exp_dir == NULL)
2146 free (nm);
2147 return;
2149 allocated_str = nm;
2151 else
2152 return;
2155 StringBuilder sb;
2156 sb.append (nm);
2157 sb.append ('/');
2158 int dlen = sb.length ();
2159 free (allocated_str);
2160 archiveMap = new StringMap<DbeFile *>();
2162 struct dirent *entry = NULL;
2163 while ((entry = readdir (exp_dir)) != NULL)
2165 char *dname = entry->d_name;
2166 if (dname[0] == '.'
2167 && (dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0')))
2168 // skip links to ./ or ../
2169 continue;
2170 sb.setLength (dlen);
2171 sb.append (dname);
2172 char *fnm = sb.toString ();
2173 DbeFile *df = new DbeFile (fnm);
2174 df->set_location (fnm);
2175 df->filetype |= DbeFile::F_FILE;
2176 df->inArchive = true;
2177 df->experiment = this;
2178 archiveMap->put (dname, df);
2179 free (fnm);
2181 closedir (exp_dir);
2184 static char *
2185 gen_file_name (const char *packet_name, const char *src_name)
2187 char *fnm, *bname = get_basename (packet_name);
2188 if (bname == packet_name)
2189 fnm = dbe_strdup (src_name);
2190 else
2191 fnm = dbe_sprintf ("%.*s%s", (int) (bname - packet_name),
2192 packet_name, src_name);
2194 // convert "java.lang.Object/Integer.java" => "java/lang/Object/Integer.java"
2195 bname = get_basename (fnm);
2196 for (char *s = fnm; s < bname; s++)
2197 if (*s == '.')
2198 *s = '/';
2199 return fnm;
2202 static char *
2203 get_jlass_name (const char *nm)
2205 // Convert "Ljava/lang/Object;" => "java/lang/Object.class"
2206 if (*nm == 'L')
2208 size_t len = strlen (nm);
2209 if (nm[len - 1] == ';')
2210 return dbe_sprintf ("%.*s.class", (int) (len - 2), nm + 1);
2212 return dbe_strdup (nm);
2215 static char *
2216 get_jmodule_name (const char *nm)
2218 // convert "Ljava/lang/Object;" => "java.lang.Object"
2219 if (*nm == 'L')
2221 size_t len = strlen (nm);
2222 if (nm[len - 1] == ';')
2224 char *mname = dbe_sprintf (NTXT ("%.*s"), (int) (len - 2), nm + 1);
2225 for (char *s = mname; *s; s++)
2226 if (*s == '/')
2227 *s = '.';
2228 return mname;
2231 return dbe_strdup (nm);
2234 LoadObject *
2235 Experiment::get_j_lo (const char *className, const char *fileName)
2237 char *class_name = get_jlass_name (className);
2238 Dprintf (DUMP_JCLASS_READER,
2239 "Experiment::get_j_lo: className='%s' class_name='%s' fileName='%s'\n",
2240 STR (className), STR (class_name), STR (fileName));
2241 LoadObject *lo = loadObjMap->get (class_name);
2242 if (lo == NULL)
2244 lo = createLoadObject (class_name, fileName);
2245 lo->type = LoadObject::SEG_TEXT;
2246 lo->mtime = (time_t) 0;
2247 lo->size = 0;
2248 lo->set_platform (Java, wsize);
2249 lo->dbeFile->filetype |= DbeFile::F_FILE | DbeFile::F_JAVACLASS;
2250 append (lo);
2251 Dprintf (DUMP_JCLASS_READER,
2252 "Experiment::get_j_lo: creates '%s' location='%s'\n",
2253 STR (lo->get_name ()), STR (lo->dbeFile->get_location (false)));
2255 free (class_name);
2256 return lo;
2259 Module *
2260 Experiment::get_jclass (const char *className, const char *fileName)
2262 LoadObject *lo = get_j_lo (className, NULL);
2263 char *mod_name = get_jmodule_name (className);
2264 Module *mod = lo->find_module (mod_name);
2265 if (mod == NULL)
2267 mod = dbeSession->createClassFile (mod_name);
2268 mod->loadobject = lo;
2269 if (strcmp (fileName, NTXT ("<Unknown>")) != 0)
2270 mod->set_file_name (gen_file_name (lo->get_pathname (), fileName));
2271 else
2272 mod->set_file_name (dbe_strdup (fileName));
2273 lo->append_module (mod);
2274 mod_name = NULL;
2276 else if (mod->file_name && (strcmp (mod->file_name, "<Unknown>") == 0)
2277 && strcmp (fileName, "<Unknown>") != 0)
2278 mod->set_file_name (gen_file_name (lo->get_pathname (), fileName));
2279 Dprintf (DUMP_JCLASS_READER,
2280 "Experiment::get_jclass: class_name='%s' mod_name='%s' fileName='%s'\n",
2281 mod->loadobject->get_pathname (), mod->get_name (), mod->file_name);
2282 free (mod_name);
2283 return mod;
2286 #define ARCH_STRLEN(s) ( ( strlen(s) + 4 ) & ~0x3 )
2289 Experiment::read_java_classes_file ()
2291 char *data_file_name = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_JCLASSES_FILE);
2292 Data_window *dwin = new Data_window (data_file_name);
2293 free (data_file_name);
2294 if (dwin->not_opened ())
2296 delete dwin;
2297 return INCOMPLETE;
2299 dwin->need_swap_endian = need_swap_endian;
2300 jmaps = new PRBTree ();
2301 jmidHTable = new DbeCacheMap<unsigned long long, JMethod>;
2303 hrtime_t cur_loaded = 0;
2304 Module *cur_mod = NULL;
2305 for (int64_t offset = 0;;)
2307 CM_Packet *cpkt = (CM_Packet*) dwin->bind (offset, sizeof (CM_Packet));
2308 if (cpkt == NULL)
2309 break;
2310 uint16_t v16 = (uint16_t) cpkt->tsize;
2311 size_t cpktsize = dwin->decode (v16);
2312 cpkt = (CM_Packet*) dwin->bind (offset, cpktsize);
2313 if ((cpkt == NULL) || (cpktsize == 0))
2315 char *buf = dbe_sprintf (GTXT ("archive file malformed %s"),
2316 arch_name);
2317 errorq->append (new Emsg (CMSG_ERROR, buf));
2318 free (buf);
2319 break;
2321 v16 = (uint16_t) cpkt->type;
2322 v16 = dwin->decode (v16);
2323 switch (v16)
2325 case ARCH_JCLASS:
2327 ARCH_jclass *ajcl = (ARCH_jclass*) cpkt;
2328 uint64_t class_id = dwin->decode (ajcl->class_id);
2329 char *className = ((char*) ajcl) + sizeof (*ajcl);
2330 char *fileName = className + ARCH_STRLEN (className);
2331 Dprintf (DUMP_JCLASS_READER,
2332 "read_java_classes_file: ARCH_JCLASS(Ox%x)"
2333 "class_id=Ox%llx className='%s' fileName='%s' \n",
2334 (int) v16, (long long) class_id, className, fileName);
2335 cur_mod = NULL;
2336 if (*className == 'L')
2337 { // Old libcollector generated '[' (one array dimension).
2338 cur_mod = get_jclass (className, fileName);
2339 cur_loaded = dwin->decode (ajcl->tstamp);
2340 jmaps->insert (class_id, cur_loaded, cur_mod);
2342 break;
2344 case ARCH_JCLASS_LOCATION:
2346 ARCH_jclass_location *ajcl = (ARCH_jclass_location *) cpkt;
2347 uint64_t class_id = dwin->decode (ajcl->class_id);
2348 char *className = ((char*) ajcl) + sizeof (*ajcl);
2349 char *fileName = className + ARCH_STRLEN (className);
2350 Dprintf (DUMP_JCLASS_READER,
2351 "read_java_classes_file: ARCH_JCLASS_LOCATION(Ox%x)"
2352 "class_id=Ox%llx className='%s' fileName='%s' \n",
2353 (int) v16, (long long) class_id, className, fileName);
2354 get_j_lo (className, fileName);
2355 break;
2357 case ARCH_JMETHOD:
2359 if (cur_mod == NULL)
2360 break;
2361 ARCH_jmethod *ajmt = (ARCH_jmethod*) cpkt;
2362 uint64_t method_id = dwin->decode (ajmt->method_id);
2363 char *s_name = ((char*) ajmt) + sizeof (*ajmt);
2364 char *s_signature = s_name + ARCH_STRLEN (s_name);
2365 char *fullname = dbe_sprintf ("%s.%s", cur_mod->get_name (), s_name);
2366 Dprintf (DUMP_JCLASS_READER,
2367 "read_java_classes_file: ARCH_JMETHOD(Ox%x) "
2368 "method_id=Ox%llx name='%s' signature='%s' fullname='%s'\n",
2369 (int) v16, (long long) method_id, s_name,
2370 s_signature, fullname);
2371 JMethod *jmthd = cur_mod->find_jmethod (fullname, s_signature);
2372 if (jmthd == NULL)
2374 jmthd = dbeSession->createJMethod ();
2375 jmthd->size = (unsigned) - 1; // unknown until later (maybe)
2376 jmthd->module = cur_mod;
2377 jmthd->set_signature (s_signature);
2378 jmthd->set_name (fullname);
2379 cur_mod->functions->append (jmthd);
2380 cur_mod->loadobject->functions->append (jmthd);
2381 Dprintf (DUMP_JCLASS_READER,
2382 "read_java_classes_file: ARCH_JMETHOD CREATE fullname=%s\n",
2383 fullname);
2385 jmaps->insert (method_id, cur_loaded, jmthd);
2386 free (fullname);
2387 break;
2389 default:
2390 Dprintf (DUMP_JCLASS_READER,
2391 "read_java_classes_file: type=Ox%x (%d) cpktsize=%d\n",
2392 (int) v16, (int) v16, (int) cpktsize);
2393 break; // ignore unknown packets
2395 offset += cpktsize;
2397 delete dwin;
2398 return SUCCESS;
2401 void
2402 Experiment::read_map_file ()
2404 ExperimentFile *mapFile = new ExperimentFile (this, SP_MAP_FILE);
2405 if (!mapFile->open ())
2407 delete mapFile;
2408 return;
2411 SAXParserFactory *factory = SAXParserFactory::newInstance ();
2412 SAXParser *saxParser = factory->newSAXParser ();
2413 DefaultHandler *dh = new ExperimentHandler (this);
2416 saxParser->parse ((File*) mapFile->fh, dh);
2418 catch (SAXException *e)
2420 // Fatal error in the parser
2421 StringBuilder sb;
2422 sb.sprintf (NTXT ("%s: %s"), SP_MAP_FILE, e->getMessage ());
2423 char *str = sb.toString ();
2424 Emsg *m = new Emsg (CMSG_FATAL, str);
2425 errorq->append (m);
2426 status = FAILURE;
2427 free (str);
2428 delete e;
2430 delete mapFile;
2431 delete dh;
2432 delete saxParser;
2433 delete factory;
2435 for (int i = 0, sz = mrecs ? mrecs->size () : 0; i < sz; i++)
2437 MapRecord *mrec = mrecs->fetch (i);
2438 SegMem *smem, *sm_lo, *sm_hi;
2439 switch (mrec->kind)
2441 case MapRecord::LOAD:
2442 smem = new SegMem;
2443 smem->base = mrec->base;
2444 smem->size = mrec->size;
2445 smem->load_time = mrec->ts;
2446 smem->unload_time = MAX_TIME;
2447 smem->obj = mrec->obj;
2448 smem->set_file_offset (mrec->foff);
2449 seg_items->append (smem); // add to the master list
2451 // Check if the new segment overlaps other active segments
2452 sm_lo = (SegMem*) maps->locate (smem->base, smem->load_time);
2453 if (sm_lo && sm_lo->base + sm_lo->size > smem->base)
2455 // check to see if it is a duplicate record: same address and size, and
2456 if ((smem->base == sm_lo->base) && (smem->size == sm_lo->size))
2458 // addresses and sizes match, check name
2459 if (strstr (smem->obj->get_name (), sm_lo->obj->get_name ()) != NULL
2460 || strstr (sm_lo->obj->get_name (), smem->obj->get_name ()) != NULL)
2461 // this is a duplicate; just move on the the next map record
2462 continue;
2463 fprintf (stderr,
2464 GTXT ("*** Warning: Segment `%s' loaded with same address, size as `%s' [0x%llx-0x%llx]\n"),
2465 smem->obj->get_name (), sm_lo->obj->get_name (),
2466 sm_lo->base, sm_lo->base + sm_lo->size);
2469 // Not a duplicate; implicitly unload the old one
2470 // Note: implicit unloading causes high <Unknown>
2471 // when such overlapping is bogus
2472 StringBuilder sb;
2473 sb.sprintf (GTXT ("*** Warning: Segment %s [0x%llx-0x%llx] overlaps %s [0x%llx-0x%llx], which has been implicitly unloaded"),
2474 smem->obj->get_name (), smem->base, smem->base + smem->size,
2475 sm_lo->obj->get_name (), sm_lo->base, sm_lo->base + sm_lo->size);
2476 warnq->append (new Emsg (CMSG_WARN, sb));
2479 // now look for other segments with which this might overlap
2480 sm_hi = (SegMem*) maps->locate_up (smem->base, smem->load_time);
2481 while (sm_hi && sm_hi->base < smem->base + smem->size)
2484 // Note: implicit unloading causes high <Unknown> when such overlapping is bogus
2485 // maps->remove( sm_hi->base, smem->load_time );
2486 StringBuilder sb;
2487 sb.sprintf (GTXT ("*** Warning: Segment %s [0x%llx-0x%llx] overlaps %s [0x%llx-0x%llx], which has been implicitly unloaded"),
2488 smem->obj->get_name (), smem->base,
2489 smem->base + smem->size, sm_hi->obj->get_name (),
2490 sm_hi->base, sm_hi->base + sm_hi->size);
2491 warnq->append (new Emsg (CMSG_WARN, sb));
2492 sm_hi = (SegMem*) maps->locate_up (sm_hi->base + sm_hi->size,
2493 smem->load_time);
2496 maps->insert (smem->base, smem->load_time, smem);
2497 break;
2498 case MapRecord::UNLOAD:
2499 smem = (SegMem*) maps->locate (mrec->base, mrec->ts);
2500 if (smem && smem->base == mrec->base)
2502 smem->unload_time = mrec->ts;
2503 maps->remove (mrec->base, mrec->ts);
2505 break;
2508 mrecs->destroy ();
2510 // See if there are comments or warnings for a load object;
2511 // if so, queue them to Experiment
2512 for (long i = 0, sz = loadObjs ? loadObjs->size () : 0; i < sz; i++)
2514 LoadObject *lo = loadObjs->get (i);
2515 for (Emsg *m = lo->fetch_warnings (); m; m = m->next)
2516 warnq->append (m->get_warn (), m->get_msg ());
2517 for (Emsg *m = lo->fetch_comments (); m; m = m->next)
2518 commentq->append (m->get_warn (), m->get_msg ());
2522 void
2523 Experiment::read_frameinfo_file ()
2525 init_cache ();
2526 char *base_name = get_basename (expt_name);
2527 char *msg = dbe_sprintf (GTXT ("Loading CallStack Data: %s"), base_name);
2528 read_data_file ("data." SP_FRINFO_FILE, msg);
2529 free (msg);
2530 frmpckts->sort (frUidCmp);
2531 uidnodes->sort (uidNodeCmp);
2534 void
2535 Experiment::read_omp_preg ()
2537 // Parallel region descriptions
2538 DataDescriptor *pregDdscr = getDataDescriptor (DATA_OMP4);
2539 if (pregDdscr == NULL)
2540 return;
2541 DataView *pregData = pregDdscr->createView ();
2542 pregData->sort (PROP_CPRID); // omptrace PROP_CPRID
2544 // OpenMP enter parreg events
2545 DataDescriptor *dDscr = getDataDescriptor (DATA_OMP2);
2546 if (dDscr == NULL || dDscr->getSize () == 0)
2548 delete pregData;
2549 return;
2552 char *idxname = NTXT ("OMP_preg");
2553 delete dbeSession->indxobj_define (idxname, GTXT ("OpenMP Parallel Region"),
2554 NTXT ("CPRID"), NULL, NULL);
2555 int idxtype = dbeSession->findIndexSpaceByName (idxname);
2556 if (idxtype < 0)
2558 delete pregData;
2559 return;
2561 ompavail = true;
2563 // Pre-create parallel region with id == 0
2564 Histable *preg0 = dbeSession->createIndexObject (idxtype, (int64_t) 0);
2565 preg0->set_name (dbe_strdup (GTXT ("Implicit OpenMP Parallel Region")));
2567 // Take care of the progress bar
2568 char *msg = dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"),
2569 get_basename (expt_name));
2570 theApplication->set_progress (0, msg);
2571 free (msg);
2572 long deltaReport = 1000;
2573 long nextReport = 0;
2574 long errors_found = 0;
2575 Vector<Histable*> pregs;
2577 long size = dDscr->getSize ();
2578 for (long i = 0; i < size; ++i)
2580 if (i == nextReport)
2582 int percent = (int) (i * 100 / size);
2583 if (percent > 0)
2584 theApplication->set_progress (percent, NULL);
2585 nextReport += deltaReport;
2588 uint32_t thrid = dDscr->getIntValue (PROP_THRID, i);
2589 hrtime_t tstamp = dDscr->getLongValue (PROP_TSTAMP, i);
2590 uint64_t cprid = dDscr->getLongValue (PROP_CPRID, i); // omptrace CPRID
2591 mapPRid->put (thrid, tstamp, cprid);
2593 pregs.reset ();
2595 * We will use 2 pointers to make sure there is no loop.
2596 * First pointer "curpreg" goes to the next element,
2597 * second pointer "curpreg_loop_control" goes to the next->next element.
2598 * If these pointers have the same value - there is a loop.
2600 uint64_t curpreg_loop_control = cprid;
2601 Datum tval_loop_control;
2602 if (curpreg_loop_control != 0)
2604 tval_loop_control.setUINT64 (curpreg_loop_control);
2605 long idx = pregData->getIdxByVals (&tval_loop_control, DataView::REL_EQ);
2606 if (idx < 0)
2607 curpreg_loop_control = 0;
2608 else
2609 curpreg_loop_control = pregData->getLongValue (PROP_PPRID, idx);
2611 for (uint64_t curpreg = cprid; curpreg != 0;)
2613 Histable *val = NULL;
2614 Datum tval;
2615 tval.setUINT64 (curpreg);
2616 long idx = pregData->getIdxByVals (&tval, DataView::REL_EQ);
2617 if (idx < 0)
2618 break;
2620 * Check if there is a loop
2622 if (0 != curpreg_loop_control)
2624 if (curpreg == curpreg_loop_control)
2626 errors_found++;
2627 if (1 == errors_found)
2629 Emsg *m = new Emsg (CMSG_WARN, GTXT ("*** Warning: circular links in OMP regions; data may not be correct."));
2630 warnq->append (m);
2632 break;
2635 uint64_t pragmapc = pregData->getLongValue (PROP_PRPC, idx);
2636 DbeInstr *instr = map_Vaddr_to_PC (pragmapc, tstamp);
2637 if (instr == NULL)
2639 break;
2641 val = instr;
2642 DbeLine *dbeline = (DbeLine*) instr->convertto (Histable::LINE);
2643 if (dbeline->lineno > 0)
2645 if (instr->func->usrfunc)
2646 dbeline = dbeline->sourceFile->find_dbeline
2647 (instr->func->usrfunc, dbeline->lineno);
2648 dbeline->set_flag (DbeLine::OMPPRAGMA);
2649 val = dbeline;
2651 val = dbeSession->createIndexObject (idxtype, val);
2652 pregs.append (val);
2654 curpreg = pregData->getLongValue (PROP_PPRID, idx);
2656 * Update curpreg_loop_control
2658 if (0 != curpreg_loop_control)
2660 tval_loop_control.setUINT64 (curpreg_loop_control);
2661 idx = pregData->getIdxByVals
2662 (&tval_loop_control, DataView::REL_EQ);
2663 if (idx < 0)
2664 curpreg_loop_control = 0;
2665 else
2667 curpreg_loop_control = pregData->getLongValue
2668 (PROP_PPRID, idx);
2669 tval_loop_control.setUINT64 (curpreg_loop_control);
2670 idx = pregData->getIdxByVals
2671 (&tval_loop_control, DataView::REL_EQ);
2672 if (idx < 0)
2673 curpreg_loop_control = 0;
2674 else
2675 curpreg_loop_control = pregData->getLongValue
2676 (PROP_PPRID, idx);
2680 pregs.append (preg0);
2681 void *prstack = cstack->add_stack (&pregs);
2682 mapPReg->put (thrid, tstamp, prstack);
2684 theApplication->set_progress (0, NTXT (""));
2685 delete pregData;
2688 void
2689 Experiment::read_omp_task ()
2691 // Task description
2692 DataDescriptor *taskDataDdscr = getDataDescriptor (DATA_OMP5);
2693 if (taskDataDdscr == NULL)
2694 return;
2696 //7035272: previously, DataView was global; now it's local...is this OK?
2697 DataView *taskData = taskDataDdscr->createView ();
2698 taskData->sort (PROP_TSKID); // omptrace PROP_TSKID
2700 // OpenMP enter task events
2701 DataDescriptor *dDscr = getDataDescriptor (DATA_OMP3);
2702 if (dDscr == NULL || dDscr->getSize () == 0)
2704 delete taskData;
2705 return;
2708 char *idxname = NTXT ("OMP_task");
2709 // delete a possible error message. Ugly.
2710 delete dbeSession->indxobj_define (idxname, GTXT ("OpenMP Task"), NTXT ("TSKID"), NULL, NULL);
2711 int idxtype = dbeSession->findIndexSpaceByName (idxname);
2712 if (idxtype < 0)
2714 delete taskData;
2715 return;
2717 ompavail = true;
2719 // Pre-create task with id == 0
2720 Histable *task0 = dbeSession->createIndexObject (idxtype, (int64_t) 0);
2721 task0->set_name (dbe_strdup (GTXT ("OpenMP Task from Implicit Parallel Region")));
2723 // Take care of the progress bar
2724 char *msg = dbe_sprintf (GTXT ("Processing OpenMP Task Data: %s"), get_basename (expt_name));
2725 theApplication->set_progress (0, msg);
2726 free (msg);
2727 long deltaReport = 1000;
2728 long nextReport = 0;
2730 Vector<Histable*> tasks;
2731 long size = dDscr->getSize ();
2732 long errors_found = 0;
2733 for (long i = 0; i < size; ++i)
2735 if (i == nextReport)
2737 int percent = (int) (i * 100 / size);
2738 if (percent > 0)
2739 theApplication->set_progress (percent, NULL);
2740 nextReport += deltaReport;
2743 uint32_t thrid = dDscr->getIntValue (PROP_THRID, i);
2744 hrtime_t tstamp = dDscr->getLongValue (PROP_TSTAMP, i);
2745 uint64_t tskid = dDscr->getLongValue (PROP_TSKID, i); //omptrace TSKID
2746 tasks.reset ();
2748 * We will use 2 pointers to make sure there is no loop.
2749 * First pointer "curtsk" goes to the next element,
2750 * second pointer "curtsk_loop_control" goes to the next->next element.
2751 * If these pointers have the same value - there is a loop.
2753 uint64_t curtsk_loop_control = tskid;
2754 Datum tval_loop_control;
2755 if (curtsk_loop_control != 0)
2757 tval_loop_control.setUINT64 (curtsk_loop_control);
2758 long idx = taskData->getIdxByVals (&tval_loop_control, DataView::REL_EQ);
2759 if (idx < 0)
2760 curtsk_loop_control = 0;
2761 else
2762 curtsk_loop_control = taskData->getLongValue (PROP_PTSKID, idx);
2764 for (uint64_t curtsk = tskid; curtsk != 0;)
2766 Histable *val = NULL;
2768 Datum tval;
2769 tval.setUINT64 (curtsk);
2770 long idx = taskData->getIdxByVals (&tval, DataView::REL_EQ);
2771 if (idx < 0)
2772 break;
2774 * Check if there is a loop
2776 if (0 != curtsk_loop_control)
2778 if (curtsk == curtsk_loop_control)
2780 errors_found++;
2781 if (1 == errors_found)
2783 Emsg *m = new Emsg (CMSG_WARN, GTXT ("*** Warning: circular links in OMP tasks; data may not be correct."));
2784 warnq->append (m);
2786 break;
2789 uint64_t pragmapc = taskData->getLongValue (PROP_PRPC, idx);
2790 DbeInstr *instr = map_Vaddr_to_PC (pragmapc, tstamp);
2791 if (instr == NULL)
2792 break;
2793 val = instr;
2794 DbeLine *dbeline = (DbeLine*) instr->convertto (Histable::LINE);
2795 if (dbeline->lineno > 0)
2797 if (instr->func->usrfunc)
2798 dbeline = dbeline->sourceFile->find_dbeline
2799 (instr->func->usrfunc, dbeline->lineno);
2800 dbeline->set_flag (DbeLine::OMPPRAGMA);
2801 val = dbeline;
2803 val = dbeSession->createIndexObject (idxtype, val);
2804 tasks.append (val);
2806 curtsk = taskData->getLongValue (PROP_PTSKID, idx);
2808 * Update curtsk_loop_control
2810 if (0 != curtsk_loop_control)
2812 tval_loop_control.setUINT64 (curtsk_loop_control);
2813 idx = taskData->getIdxByVals (&tval_loop_control, DataView::REL_EQ);
2814 if (idx < 0)
2815 curtsk_loop_control = 0;
2816 else
2818 curtsk_loop_control = taskData->getLongValue (PROP_PTSKID, idx);
2819 tval_loop_control.setUINT64 (curtsk_loop_control);
2820 idx = taskData->getIdxByVals (&tval_loop_control,
2821 DataView::REL_EQ);
2822 if (idx < 0)
2823 curtsk_loop_control = 0;
2824 else
2825 curtsk_loop_control = taskData->getLongValue (PROP_PTSKID,
2826 idx);
2830 tasks.append (task0);
2831 void *tskstack = cstack->add_stack (&tasks);
2832 mapTask->put (thrid, tstamp, tskstack);
2834 theApplication->set_progress (0, NTXT (""));
2835 delete taskData;
2838 void
2839 Experiment::read_omp_file ()
2841 // DATA_OMP2 table is common between OpenMP 2.5 and 3.0 profiling
2842 DataDescriptor *dDscr = getDataDescriptor (DATA_OMP2);
2843 if (dDscr == NULL)
2844 return;
2845 if (dDscr->getSize () == 0)
2847 char *base_name = get_basename (expt_name);
2848 char *msg = dbe_sprintf (GTXT ("Loading OpenMP Data: %s"), base_name);
2849 read_data_file (SP_OMPTRACE_FILE, msg);
2850 free (msg);
2852 // OpenMP fork events
2853 dDscr = getDataDescriptor (DATA_OMP);
2854 long sz = dDscr->getSize ();
2855 if (sz > 0)
2857 // progress bar
2858 msg = dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"),
2859 base_name);
2860 theApplication->set_progress (0, msg);
2861 free (msg);
2862 long deltaReport = 5000;
2863 long nextReport = 0;
2864 for (int i = 0; i < sz; ++i)
2866 if (i == nextReport)
2868 int percent = (int) (i * 100 / sz);
2869 if (percent > 0)
2870 theApplication->set_progress (percent, NULL);
2871 nextReport += deltaReport;
2873 uint32_t thrid = dDscr->getIntValue (PROP_THRID, i);
2874 hrtime_t tstamp = dDscr->getLongValue (PROP_TSTAMP, i);
2875 uint64_t cprid = dDscr->getLongValue (PROP_CPRID, i); //omptrace
2876 mapPRid->put (thrid, tstamp, cprid);
2878 theApplication->set_progress (0, NTXT (""));
2880 ompavail = true;
2881 openMPdata = dDscr->createView ();
2882 openMPdata->sort (PROP_CPRID); // omptrace PROP_CPRID
2884 // thread enters parreg events
2885 dDscr = getDataDescriptor (DATA_OMP2);
2886 sz = dDscr->getSize ();
2888 // progress bar
2889 msg = dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"),
2890 base_name);
2891 theApplication->set_progress (0, msg);
2892 free (msg);
2893 deltaReport = 5000;
2894 nextReport = 0;
2896 for (int i = 0; i < sz; ++i)
2898 if (i == nextReport)
2900 int percent = (int) (i * 100 / sz);
2901 if (percent > 0)
2902 theApplication->set_progress (percent, NULL);
2903 nextReport += deltaReport;
2905 uint32_t thrid = dDscr->getIntValue (PROP_THRID, i);
2906 hrtime_t tstamp = dDscr->getLongValue (PROP_TSTAMP, i);
2907 uint64_t cprid = dDscr->getLongValue (PROP_CPRID, i); //omptrace
2908 mapPRid->put (thrid, tstamp, cprid);
2910 theApplication->set_progress (0, NTXT (""));
2912 else
2914 read_omp_preg ();
2915 read_omp_task ();
2917 if (ompavail && coll_params.profile_mode)
2919 dbeSession->status_ompavail = 1;
2920 register_metric (Metric::OMP_WORK);
2921 register_metric (Metric::OMP_WAIT);
2922 register_metric (Metric::OMP_OVHD);
2923 if (coll_params.lms_magic_id == LMS_MAGIC_ID_SOLARIS)
2924 register_metric (Metric::OMP_MASTER_THREAD);
2929 void
2930 Experiment::read_ifreq_file ()
2932 char *fname = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_IFREQ_FILE);
2933 FILE *f = fopen (fname, NTXT ("r"));
2934 free (fname);
2935 if (f == NULL)
2937 ifreqavail = false;
2938 return;
2940 ifreqavail = true;
2941 ifreqq = new Emsgqueue (NTXT ("ifreqq"));
2943 while (1)
2945 Emsg *m;
2946 char str[MAXPATHLEN];
2947 char *e = fgets (str, ((int) sizeof (str)) - 1, f);
2948 if (e == NULL)
2950 // end the list from the experiment
2951 m = new Emsg (CMSG_COMMENT,
2952 GTXT ("============================================================"));
2953 ifreqq->append (m);
2954 break;
2956 // get the string
2957 size_t i = strlen (str);
2958 if (i > 0 && str[i - 1] == '\n')
2959 // remove trailing nl
2960 str[i - 1] = 0;
2961 // and append it
2962 m = new Emsg (CMSG_COMMENT, str);
2963 ifreqq->append (m);
2965 (void) fclose (f);
2968 Experiment *
2969 Experiment::getBaseFounder ()
2971 if (baseFounder)
2972 return baseFounder;
2973 Experiment *founder = this;
2974 Experiment *parent = founder->founder_exp;
2975 while (parent)
2977 founder = parent;
2978 parent = founder->founder_exp;
2980 baseFounder = founder;
2981 return baseFounder;
2984 hrtime_t
2985 Experiment::getRelativeStartTime ()
2987 if (exp_rel_start_time_set)
2988 return exp_rel_start_time;
2989 Experiment *founder = getBaseFounder ();
2990 hrtime_t child_start = this->getStartTime ();
2991 hrtime_t founder_start = founder->getStartTime ();
2992 exp_rel_start_time = child_start - founder_start;
2993 if (child_start == 0 && founder_start)
2994 exp_rel_start_time = 0; // when descendents have incomplete log.xml
2995 exp_rel_start_time_set = true;
2996 return exp_rel_start_time;
2999 DataDescriptor *
3000 Experiment::get_raw_events (int data_id)
3002 DataDescriptor *dDscr;
3003 switch (data_id)
3005 case DATA_CLOCK:
3006 dDscr = get_profile_events ();
3007 break;
3008 case DATA_SYNCH:
3009 dDscr = get_sync_events ();
3010 break;
3011 case DATA_HWC:
3012 dDscr = get_hwc_events ();
3013 break;
3014 case DATA_HEAP:
3015 dDscr = get_heap_events ();
3016 break;
3017 case DATA_HEAPSZ:
3018 dDscr = get_heapsz_events ();
3019 break;
3020 case DATA_IOTRACE:
3021 dDscr = get_iotrace_events ();
3022 break;
3023 case DATA_RACE:
3024 dDscr = get_race_events ();
3025 break;
3026 case DATA_DLCK:
3027 dDscr = get_deadlock_events ();
3028 break;
3029 case DATA_SAMPLE:
3030 dDscr = get_sample_events ();
3031 break;
3032 case DATA_GCEVENT:
3033 dDscr = get_gc_events ();
3034 break;
3035 default:
3036 dDscr = NULL;
3037 break;
3039 return dDscr;
3043 Experiment::base_data_id (int data_id)
3045 switch (data_id)
3047 case DATA_HEAPSZ:
3048 return DATA_HEAP; // DATA_HEAPSZ DataView is based on DATA_HEAP's DataView
3049 default:
3050 break;
3052 return data_id;
3055 DataView *
3056 Experiment::create_derived_data_view (int data_id, DataView *dview)
3058 // dview contains filtered packets
3059 switch (data_id)
3061 case DATA_HEAPSZ:
3062 return create_heapsz_data_view (dview);
3063 default:
3064 break;
3066 return NULL;
3069 DataDescriptor *
3070 Experiment::get_profile_events ()
3072 DataDescriptor *dDscr = getDataDescriptor (DATA_CLOCK);
3073 if (dDscr == NULL)
3074 return NULL;
3075 if (dDscr->getSize () == 0)
3077 char *base_name = get_basename (expt_name);
3078 char *msg = dbe_sprintf (GTXT ("Loading Profile Data: %s"), base_name);
3079 read_data_file (SP_PROFILE_FILE, msg);
3080 free (msg);
3081 add_evt_time_to_profile_events (dDscr);
3082 resolve_frame_info (dDscr);
3084 else if (!dDscr->isResolveFrInfoDone ())
3085 resolve_frame_info (dDscr);
3086 return dDscr;
3089 void
3090 Experiment::add_evt_time_to_profile_events (DataDescriptor *dDscr)
3092 if (coll_params.lms_magic_id != LMS_MAGIC_ID_SOLARIS)
3093 return;
3095 DataView *dview = dDscr->createView ();
3096 dview->sort (PROP_THRID, PROP_TSTAMP);
3098 // add PROP_EVT_TIME
3099 PropDescr* tmp_propDscr = new PropDescr (PROP_EVT_TIME, "EVT_TIME");
3100 tmp_propDscr->uname = dbe_strdup (GTXT ("Event duration"));
3101 tmp_propDscr->vtype = TYPE_INT64;
3102 dDscr->addProperty (tmp_propDscr);
3104 long sz = dview->getSize ();
3105 long long ptimer_usec = get_params ()->ptimer_usec;
3106 for (long i = 0; i < sz; i++)
3108 int next_sample;
3109 int jj;
3111 hrtime_t this_tstamp = dview->getLongValue (PROP_TSTAMP, i);
3112 long this_thrid = dview->getLongValue (PROP_THRID, i);
3113 for (jj = i + 1; jj < sz; jj++)
3115 hrtime_t tmp_tstamp = dview->getLongValue (PROP_TSTAMP, jj);
3116 if (tmp_tstamp != this_tstamp)
3117 break;
3118 long tmp_thrid = dview->getLongValue (PROP_THRID, jj);
3119 if (tmp_thrid != this_thrid)
3120 break;
3122 next_sample = jj;
3125 long nticks = 0;
3126 for (jj = i; jj < next_sample; jj++)
3127 nticks += dview->getLongValue (PROP_NTICK, jj);
3128 if (nticks <= 1)
3129 continue; // no duration
3131 nticks--;
3132 hrtime_t duration = ptimer_usec * 1000LL * nticks; // nanoseconds
3133 for (jj = i; jj < next_sample; jj++)
3134 dview->setValue (PROP_EVT_TIME, jj, duration);
3135 i = jj - 1;
3137 delete dview;
3140 DataDescriptor *
3141 Experiment::get_sync_events ()
3143 DataDescriptor *dDscr = getDataDescriptor (DATA_SYNCH);
3144 if (dDscr == NULL)
3145 return NULL;
3146 if (dDscr->getSize () > 0)
3147 return dDscr;
3149 // fetch data
3151 char *base_name = get_basename (expt_name);
3152 char *msg = dbe_sprintf (GTXT ("Loading Synctrace Data: %s"), base_name);
3153 read_data_file (SP_SYNCTRACE_FILE, msg);
3154 free (msg);
3155 resolve_frame_info (dDscr);
3158 // check for PROP_EVT_TIME
3159 PropDescr *tmp_propDscr = dDscr->getProp (PROP_EVT_TIME);
3160 if (tmp_propDscr)
3161 return dDscr;
3163 // add PROP_EVT_TIME
3164 tmp_propDscr = new PropDescr (PROP_EVT_TIME, "EVT_TIME");
3165 tmp_propDscr->uname = dbe_strdup (GTXT ("Event duration"));
3166 tmp_propDscr->vtype = TYPE_INT64;
3167 dDscr->addProperty (tmp_propDscr);
3169 long sz = dDscr->getSize ();
3170 for (long i = 0; i < sz; i++)
3172 uint64_t event_duration = dDscr->getLongValue (PROP_TSTAMP, i);
3173 event_duration -= dDscr->getLongValue (PROP_SRQST, i);
3174 dDscr->setValue (PROP_EVT_TIME, i, event_duration);
3176 return dDscr;
3179 DataDescriptor *
3180 Experiment::get_hwc_events ()
3182 DataDescriptor *dDscr = getDataDescriptor (DATA_HWC);
3183 if (dDscr == NULL)
3184 return NULL;
3185 if (dDscr->getSize () == 0)
3187 char *base_name = get_basename (expt_name);
3188 char *msg = dbe_sprintf (GTXT ("Loading HW Profile Data: %s"), base_name);
3190 // clear HWC event stats
3191 dsevents = 0;
3192 dsnoxhwcevents = 0;
3193 read_data_file (SP_HWCNTR_FILE, msg);
3194 free (msg);
3195 resolve_frame_info (dDscr);
3197 // describe the HW counters in PropDescr
3198 PropDescr *prop = dDscr->getProp (PROP_HWCTAG);
3199 if (prop)
3201 Collection_params *cparam = get_params ();
3202 if (cparam->hw_mode != 0)
3203 for (int aux = 0; aux < MAX_HWCOUNT; aux++)
3204 if (cparam->hw_aux_name[aux])
3206 const char* cmdname = cparam->hw_aux_name[aux];
3207 const char* uname = cparam->hw_username[aux];
3208 prop->addState (aux, cmdname, uname);
3211 else
3212 assert (0);
3214 double dserrrate = 100.0 * ((double) dsnoxhwcevents) / ((double) dsevents);
3215 if ((dsevents > 0) && (dserrrate > 10.0))
3217 // warn the user that rate is high
3218 StringBuilder sb;
3219 if (dbeSession->check_ignore_no_xhwcprof ())
3220 sb.sprintf (
3221 GTXT ("Warning: experiment %s has %.1f%%%% (%lld of %lld) dataspace events that were accepted\n without verification; data may be incorrect or misleading\n recompile with -xhwcprof and rerecord to get better data\n"),
3222 base_name, dserrrate, (long long) dsnoxhwcevents,
3223 (long long) dsevents);
3224 else
3225 sb.sprintf (
3226 GTXT ("Warning: experiment %s has %.1f%%%% (%lld of %lld) dataspace events that could not be verified\n recompile with -xhwcprof and rerecord to get better data\n"),
3227 base_name, dserrrate, (long long) dsnoxhwcevents,
3228 (long long) dsevents);
3229 errorq->append (new Emsg (CMSG_WARN, sb));
3232 // see if we've scanned the data
3233 if (hwc_scanned == 0)
3235 // no, scan the packets to see how many are bogus, or represent lost interrupts
3236 long hwc_cnt = 0;
3238 // loop over the packets, counting the bad ones
3239 if (hwc_bogus != 0 || hwc_lost_int != 0)
3241 // hwc counter data had bogus packets and/or packets reflecting lost interrupts
3242 double bogus_rate = 100. * (double) hwc_bogus / (double) hwc_cnt;
3243 if (bogus_rate > 5.)
3245 StringBuilder sb;
3246 sb.sprintf (
3247 GTXT ("WARNING: Too many invalid HW counter profile events (%ld/%ld = %3.2f%%) in experiment %d (`%s'); data may be unreliable"),
3248 (long) hwc_bogus, (long) hwc_cnt, bogus_rate,
3249 (int) userExpId, base_name);
3250 Emsg *m = new Emsg (CMSG_WARN, sb);
3251 warnq->append (m);
3253 hwc_scanned = 1;
3257 return dDscr;
3260 DataDescriptor *
3261 Experiment::get_iotrace_events ()
3263 DataDescriptor *dDscr = getDataDescriptor (DATA_IOTRACE);
3264 if (dDscr == NULL)
3265 return NULL;
3267 if (dDscr->getSize () > 0)
3268 return dDscr;
3270 char *base_name = get_basename (expt_name);
3271 char *msg = dbe_sprintf (GTXT ("Loading IO Trace Data: %s"), base_name);
3272 read_data_file (SP_IOTRACE_FILE, msg);
3273 free (msg);
3275 if (dDscr->getSize () == 0)
3276 return dDscr;
3277 resolve_frame_info (dDscr);
3279 // check for PROP_EVT_TIME
3280 PropDescr *tmp_propDscr = dDscr->getProp (PROP_EVT_TIME);
3281 if (tmp_propDscr)
3282 return dDscr;
3284 // add PROP_EVT_TIME
3285 tmp_propDscr = new PropDescr (PROP_EVT_TIME, "EVT_TIME");
3286 tmp_propDscr->uname = dbe_strdup (GTXT ("Event duration"));
3287 tmp_propDscr->vtype = TYPE_INT64;
3288 dDscr->addProperty (tmp_propDscr);
3290 // add PROP_IOVFD
3291 tmp_propDscr = new PropDescr (PROP_IOVFD, "IOVFD");
3292 tmp_propDscr->uname = dbe_strdup (GTXT ("Virtual File Descriptor"));
3293 tmp_propDscr->vtype = TYPE_INT64;
3294 dDscr->addProperty (tmp_propDscr);
3296 delete fDataMap;
3297 fDataMap = new DefaultMap<int64_t, FileData*>;
3299 delete vFdMap;
3300 vFdMap = new DefaultMap<int, int64_t>;
3302 static int64_t virtualFd = 0;
3304 FileData *fData;
3305 virtualFd += 10;
3306 fData = fDataMap->get (VIRTUAL_FD_STDIN);
3307 if (fData == NULL)
3309 fData = new FileData (STDIN_FILENAME);
3310 fData->setVirtualFd (VIRTUAL_FD_STDIN);
3311 fData->id = VIRTUAL_FD_STDIN;
3312 fData->setFileDes (STDIN_FD);
3313 fDataMap->put (VIRTUAL_FD_STDIN, fData);
3314 vFdMap->put (STDIN_FD, VIRTUAL_FD_STDIN);
3317 fData = fDataMap->get (VIRTUAL_FD_STDOUT);
3318 if (fData == NULL)
3320 fData = new FileData (STDOUT_FILENAME);
3321 fData->setVirtualFd (VIRTUAL_FD_STDOUT);
3322 fData->id = VIRTUAL_FD_STDOUT;
3323 fData->setFileDes (STDOUT_FD);
3324 fDataMap->put (VIRTUAL_FD_STDOUT, fData);
3325 vFdMap->put (STDOUT_FD, VIRTUAL_FD_STDOUT);
3328 fData = fDataMap->get (VIRTUAL_FD_STDERR);
3329 if (fData == NULL)
3331 fData = new FileData (STDERR_FILENAME);
3332 fData->setVirtualFd (VIRTUAL_FD_STDERR);
3333 fData->id = VIRTUAL_FD_STDERR;
3334 fData->setFileDes (STDERR_FD);
3335 fDataMap->put (VIRTUAL_FD_STDERR, fData);
3336 vFdMap->put (STDERR_FD, VIRTUAL_FD_STDERR);
3339 fData = fDataMap->get (VIRTUAL_FD_OTHERIO);
3340 if (fData == NULL)
3342 fData = new FileData (OTHERIO_FILENAME);
3343 fData->setVirtualFd (VIRTUAL_FD_OTHERIO);
3344 fData->id = VIRTUAL_FD_OTHERIO;
3345 fData->setFileDes (OTHERIO_FD);
3346 fDataMap->put (VIRTUAL_FD_OTHERIO, fData);
3349 DataView *dview = dDscr->createView ();
3350 dview->sort (PROP_TSTAMP);
3351 long sz = dview->getSize ();
3352 for (long i = 0; i < sz; i++)
3354 hrtime_t event_duration = dview->getLongValue (PROP_TSTAMP, i);
3355 hrtime_t event_start = dview->getLongValue (PROP_IORQST, i);
3356 if (event_start > 0)
3357 event_duration -= event_start;
3358 else
3359 event_duration = 0;
3360 dview->setValue (PROP_EVT_TIME, i, event_duration);
3362 int32_t fd = -1;
3363 int64_t vFd = VIRTUAL_FD_NONE;
3364 char *fName = NULL;
3365 int32_t origFd = -1;
3366 StringBuilder *sb = NULL;
3367 FileData *fDataOrig = NULL;
3368 FileSystem_type fsType;
3370 IOTrace_type ioType = (IOTrace_type) dview->getIntValue (PROP_IOTYPE, i);
3371 switch (ioType)
3373 case READ_TRACE:
3374 case WRITE_TRACE:
3375 case READ_TRACE_ERROR:
3376 case WRITE_TRACE_ERROR:
3377 fd = dview->getIntValue (PROP_IOFD, i);
3378 vFd = vFdMap->get (fd);
3379 if (vFd == 0 || vFd == VIRTUAL_FD_NONE
3380 || (fData = fDataMap->get (vFd)) == NULL)
3382 fData = new FileData (UNKNOWNFD_FILENAME);
3383 fData->setVirtualFd (virtualFd);
3384 fData->setFsType ("N/A");
3385 fData->setFileDes (fd);
3386 fDataMap->put (virtualFd, fData);
3387 vFdMap->put (fd, virtualFd);
3388 vFd = virtualFd;
3389 virtualFd++;
3391 dview->setValue (PROP_IOVFD, i, vFd);
3392 break;
3393 case OPEN_TRACE:
3394 fName = NULL;
3395 sb = (StringBuilder*) dview->getObjValue (PROP_IOFNAME, i);
3396 if (sb != NULL && sb->length () > 0)
3397 fName = sb->toString ();
3398 fd = dview->getIntValue (PROP_IOFD, i);
3399 origFd = dview->getIntValue (PROP_IOOFD, i);
3400 fsType = (FileSystem_type) dview->getIntValue (PROP_IOFSTYPE, i);
3402 if (fName != NULL)
3404 fData = new FileData (fName);
3405 fDataMap->put (virtualFd, fData);
3406 vFdMap->put (fd, virtualFd);
3407 fData->setFileDes (fd);
3408 fData->setFsType (fsType);
3409 fData->setVirtualFd (virtualFd);
3410 vFd = virtualFd;
3411 virtualFd++;
3413 else if (origFd > 0)
3415 vFd = vFdMap->get (origFd);
3416 if (vFd == 0 || vFd == VIRTUAL_FD_NONE)
3418 Dprintf (DEBUG_IO,
3419 "*** Error I/O tracing: (open) cannot get the virtual file descriptor, fd=%d origFd=%d\n",
3420 fd, origFd);
3421 continue;
3423 else if ((fDataOrig = fDataMap->get (vFd)) == NULL)
3425 Dprintf (DEBUG_IO,
3426 "*** Error IO tracing: (open) cannot get original FileData object, fd=%d origFd=%d\n",
3427 fd, origFd);
3428 continue;
3430 else
3432 fName = fDataOrig->getFileName ();
3433 fData = new FileData (fName);
3434 fData->setFileDes (fd);
3435 fData->setFsType (fDataOrig->getFsType ());
3436 fData->setVirtualFd (virtualFd);
3437 fDataMap->put (virtualFd, fData);
3438 vFdMap->put (fd, virtualFd);
3439 vFd = virtualFd;
3440 virtualFd++;
3443 else if (fd >= 0)
3445 vFd = vFdMap->get (fd);
3446 if (vFd == 0 || vFd == VIRTUAL_FD_NONE
3447 || (fData = fDataMap->get (vFd)) == NULL)
3449 fData = new FileData (UNKNOWNFD_FILENAME);
3450 fData->setVirtualFd (virtualFd);
3451 fData->setFsType ("N/A");
3452 fData->setFileDes (fd);
3453 fDataMap->put (virtualFd, fData);
3454 vFdMap->put (fd, virtualFd);
3455 vFd = virtualFd;
3456 virtualFd++;
3459 else
3461 Dprintf (DEBUG_IO,
3462 NTXT ("*** Error IO tracing: (open) unknown open IO type, fd=%d origFd=%d\n"), fd, origFd);
3463 continue;
3466 dview->setValue (PROP_IOVFD, i, vFd);
3467 break;
3469 case OPEN_TRACE_ERROR:
3470 fName = NULL;
3472 sb = (StringBuilder*) dview->getObjValue (PROP_IOFNAME, i);
3473 if (sb != NULL && sb->length () > 0)
3474 fName = sb->toString ();
3475 fd = dview->getIntValue (PROP_IOFD, i);
3476 origFd = dview->getIntValue (PROP_IOOFD, i);
3477 fsType = (FileSystem_type) dview->getIntValue (PROP_IOFSTYPE, i);
3479 if (fName != NULL)
3481 fData = new FileData (fName);
3482 fDataMap->put (virtualFd, fData);
3483 fData->setFileDes (fd);
3484 fData->setFsType (fsType);
3485 fData->setVirtualFd (virtualFd);
3486 vFd = virtualFd;
3487 virtualFd++;
3489 else if (origFd > 0)
3491 vFd = vFdMap->get (origFd);
3492 if (vFd == 0 || vFd == VIRTUAL_FD_NONE)
3494 Dprintf (DEBUG_IO,
3495 "*** Error IO tracing: (open error) cannot get the virtual file descriptor, fd=%d origFd=%d\n",
3496 fd, origFd);
3497 continue;
3499 else if ((fDataOrig = fDataMap->get (vFd)) == NULL)
3501 Dprintf (DEBUG_IO,
3502 "*** Error IO tracing: (open error) cannot get original FileData object, fd=%d origFd=%d\n",
3503 fd, origFd);
3504 continue;
3506 else
3508 fName = fDataOrig->getFileName ();
3509 fData = new FileData (fName);
3510 fData->setFileDes (fd);
3511 fData->setFsType (fDataOrig->getFsType ());
3512 fData->setVirtualFd (virtualFd);
3513 fDataMap->put (virtualFd, fData);
3514 vFd = virtualFd;
3515 virtualFd++;
3519 dview->setValue (PROP_IOVFD, i, vFd);
3520 break;
3522 case CLOSE_TRACE:
3523 case CLOSE_TRACE_ERROR:
3524 fd = dview->getIntValue (PROP_IOFD, i);
3525 vFd = vFdMap->get (fd);
3526 if (vFd == 0 || vFd == VIRTUAL_FD_NONE)
3528 Dprintf (DEBUG_IO,
3529 "*** Error IO tracing: (close) cannot get the virtual file descriptor, fd=%d\n",
3530 fd);
3531 continue;
3533 fData = fDataMap->get (vFd);
3534 if (fData == NULL)
3536 Dprintf (DEBUG_IO,
3537 "*** Error IO tracing: (close) cannot get the FileData object, fd=%d\n",
3538 fd);
3539 continue;
3542 vFdMap->put (fd, VIRTUAL_FD_NONE);
3543 dview->setValue (PROP_IOVFD, i, vFd);
3544 break;
3546 case OTHERIO_TRACE:
3547 case OTHERIO_TRACE_ERROR:
3548 vFd = VIRTUAL_FD_OTHERIO;
3549 fData = fDataMap->get (vFd);
3550 if (fData == NULL)
3552 Dprintf (DEBUG_IO,
3553 "*** Error IO tracing: (other IO) cannot get the FileData object\n");
3554 continue;
3557 dview->setValue (PROP_IOVFD, i, vFd);
3558 break;
3559 case IOTRACETYPE_LAST:
3560 break;
3564 delete dview;
3566 return dDscr;
3569 DataDescriptor *
3570 Experiment::get_heap_events ()
3572 DataDescriptor *dDscr = getDataDescriptor (DATA_HEAP);
3573 if (dDscr == NULL)
3574 return NULL;
3575 if (dDscr->getSize () > 0)
3576 return dDscr;
3578 char *base_name = get_basename (expt_name);
3579 char *msg = dbe_sprintf (GTXT ("Loading Heap Trace Data: %s"), base_name);
3580 read_data_file (SP_HEAPTRACE_FILE, msg);
3581 free (msg);
3583 if (dDscr->getSize () == 0)
3584 return dDscr;
3585 resolve_frame_info (dDscr);
3587 // Match FREE to MALLOC
3588 PropDescr *prop = new PropDescr (PROP_HLEAKED, NTXT ("HLEAKED"));
3589 prop->uname = dbe_strdup (GTXT ("Bytes Leaked"));
3590 prop->vtype = TYPE_UINT64;
3591 dDscr->addProperty (prop);
3593 prop = new PropDescr (PROP_HMEM_USAGE, NTXT ("HMEM_USAGE"));
3594 prop->uname = dbe_strdup (GTXT ("Heap Memory Usage"));
3595 prop->vtype = TYPE_UINT64;
3596 dDscr->addProperty (prop);
3598 prop = new PropDescr (PROP_HFREED, NTXT ("HFREED"));
3599 prop->uname = dbe_strdup (GTXT ("Bytes Freed"));
3600 prop->vtype = TYPE_UINT64;
3601 dDscr->addProperty (prop);
3603 prop = new PropDescr (PROP_HCUR_ALLOCS, NTXT ("HCUR_ALLOCS"));
3604 prop->uname = dbe_strdup (GTXT ("Net Bytes Allocated"));
3605 prop->vtype = TYPE_INT64;
3606 dDscr->addProperty (prop);
3608 prop = new PropDescr (PROP_HCUR_LEAKS, NTXT ("HCUR_LEAKS"));
3609 prop->uname = dbe_strdup (GTXT ("Net Bytes Leaked"));
3610 prop->vtype = TYPE_UINT64;
3611 dDscr->addProperty (prop);
3613 prop = new PropDescr (PROP_HCUR_NET_ALLOC, NTXT ("HCUR_NET_ALLOC"));
3614 prop->vtype = TYPE_INT64;
3615 prop->flags = DDFLAG_NOSHOW;
3616 dDscr->addProperty (prop);
3618 prop = new PropDescr (PROP_DDSCR_LNK, NTXT ("DDSCR_LNK"));
3619 prop->vtype = TYPE_UINT64;
3620 prop->flags = DDFLAG_NOSHOW;
3621 dDscr->addProperty (prop);
3623 prop = new PropDescr (PROP_VOIDP_OBJ, NTXT ("VOIDP_OBJ"));
3624 prop->vtype = TYPE_OBJ;
3625 prop->flags = DDFLAG_NOSHOW;
3626 dDscr->addProperty (prop);
3628 prop = new PropDescr (PROP_TSTAMP2, NTXT ("TSTAMP2"));
3629 prop->uname = dbe_strdup (GTXT ("End Timestamp (nanoseconds)"));
3630 prop->vtype = TYPE_UINT64;
3631 prop->flags = DDFLAG_NOSHOW;
3632 dDscr->addProperty (prop);
3634 DataView *dview = dDscr->createView ();
3635 dview->sort (PROP_TSTAMP);
3637 // Keep track of memory usage
3638 Size memoryUsage = 0;
3640 HeapMap *heapmap = new HeapMap ();
3641 long sz = dview->getSize ();
3642 for (long i = 0; i < sz; i++)
3645 Heap_type mtype = (Heap_type) dview->getIntValue (PROP_HTYPE, i);
3646 Vaddr vaddr = dview->getULongValue (PROP_HVADDR, i);
3647 Vaddr ovaddr = dview->getULongValue (PROP_HOVADDR, i);
3648 Size hsize = dview->getULongValue (PROP_HSIZE, i);
3649 hrtime_t tstamp = dview->getLongValue (PROP_TSTAMP, i);
3651 switch (mtype)
3653 case MALLOC_TRACE:
3654 dview->setValue (PROP_TSTAMP2, i, (uint64_t) MAX_TIME);
3655 if (vaddr)
3657 dview->setValue (PROP_HLEAKED, i, hsize);
3658 heapmap->allocate (vaddr, i + 1);
3660 // Increase heap size
3661 memoryUsage += hsize;
3662 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage);
3664 break;
3666 case FREE_TRACE:
3667 if (vaddr)
3669 long idx = heapmap->deallocate (vaddr) - 1;
3670 if (idx >= 0)
3672 // Decrease heap size
3673 Size leaked = dview->getLongValue (PROP_HLEAKED, idx);
3674 memoryUsage -= leaked;
3675 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage);
3677 Size alloc = dview->getLongValue (PROP_HSIZE, idx);
3678 // update allocation
3679 dview->setValue (PROP_HLEAKED, idx, (uint64_t) 0);
3680 dview->setValue (PROP_TSTAMP2, idx, tstamp);
3681 dview->setValue (PROP_DDSCR_LNK, idx, dview->getIdByIdx (i) + 1);
3682 // update this event
3683 dview->setValue (PROP_HFREED, i, alloc);
3686 break;
3688 case REALLOC_TRACE:
3689 dview->setValue (PROP_TSTAMP2, i, (uint64_t) MAX_TIME);
3690 if (ovaddr)
3692 long idx = heapmap->deallocate (ovaddr) - 1;
3693 if (idx >= 0)
3695 // Decrease heap size
3696 Size leaked = dview->getLongValue (PROP_HLEAKED, idx);
3697 memoryUsage -= leaked;
3698 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage);
3700 Size alloc = dview->getLongValue (PROP_HSIZE, idx);
3701 // update allocation
3702 dview->setValue (PROP_HLEAKED, idx, (uint64_t) 0);
3703 dview->setValue (PROP_TSTAMP2, idx, tstamp);
3704 dview->setValue (PROP_DDSCR_LNK, idx, dview->getIdByIdx (i) + 1);
3705 // update this event
3706 dview->setValue (PROP_HFREED, i, alloc);
3709 if (vaddr)
3711 dview->setValue (PROP_HLEAKED, i, hsize);
3712 heapmap->allocate (vaddr, i + 1);
3714 // Increase heap size
3715 memoryUsage += hsize;
3716 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage);
3718 break;
3719 case MMAP_TRACE:
3720 case MUNMAP_TRACE:
3721 // Adjust the size to be multiple of page_size
3722 //hsize = (( hsize - 1 ) / page_size + 1 ) * page_size;
3723 if (vaddr)
3725 UnmapChunk *list;
3726 if (mtype == MMAP_TRACE)
3728 dview->setValue (PROP_TSTAMP2, i, (uint64_t) MAX_TIME);
3729 dview->setValue (PROP_HLEAKED, i, hsize);
3730 list = heapmap->mmap (vaddr, hsize, i);
3732 // Increase heap size
3733 memoryUsage += hsize;
3734 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage);
3736 else
3737 { // MUNMAP_TRACE
3738 list = heapmap->munmap (vaddr, hsize);
3740 // Set allocation size to zero
3741 // Note: We're currently reusing PROP_HSIZE to mean allocation size
3742 // If we ever need to save the original HSIZE, we'll need to
3743 // create a new PROP_* to represent event allocation size
3745 // For now, tuck the original size away as HOVADDR
3746 dview->setValue (PROP_HOVADDR, i, (uint64_t) hsize);
3747 dview->setValue (PROP_HSIZE, i, (uint64_t) 0);
3749 Size total_freed = 0;
3750 while (list)
3752 long idx = list->val;
3753 total_freed += list->size;
3754 Size leaked = dview->getLongValue (PROP_HLEAKED, idx);
3756 // Decrease heap size
3757 memoryUsage -= list->size;
3758 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage);
3760 Size leak_update = leaked - list->size;
3761 // update allocation
3762 dview->setValue (PROP_HLEAKED, idx, leak_update);
3763 // update allocation's list of frees
3765 UnmapChunk *copy = new UnmapChunk;
3766 heapUnmapEvents->append (copy);
3767 copy->val = dview->getIdByIdx (i);
3768 copy->size = list->size;
3769 copy->next = (UnmapChunk *) dview->getObjValue (PROP_VOIDP_OBJ, idx);
3770 dview->setObjValue (PROP_VOIDP_OBJ, idx, copy);
3772 if (leak_update <= 0)
3773 if (leak_update == 0)
3774 dview->setValue (PROP_TSTAMP2, idx, tstamp);
3775 UnmapChunk *t = list;
3776 list = list->next;
3777 delete t;
3779 // update this event
3780 if (total_freed)
3781 // only need to write value if it is non-zero
3782 dview->setValue (PROP_HFREED, i, total_freed);
3784 break;
3785 // ignoring HEAPTYPE_LAST, which will never be recorded
3786 case HEAPTYPE_LAST:
3787 break;
3790 delete heapmap;
3791 delete dview;
3793 return dDscr;
3796 DataDescriptor *
3797 Experiment::get_heapsz_events ()
3799 DataDescriptor *dDscr = getDataDescriptor (DATA_HEAPSZ);
3800 if (dDscr)
3801 return dDscr;
3802 dDscr = get_heap_events (); // derived from DATA_HEAP
3803 if (dDscr == NULL)
3804 return NULL;
3805 dDscr = newDataDescriptor (DATA_HEAPSZ, 0, dDscr);
3806 return dDscr;
3809 static void
3810 update_heapsz_packet (std::set<long> &pkt_id_set, DataView *dview,
3811 long alloc_pkt_id, int64_t net_alloc, uint64_t leaks)
3813 // pkt_id_set: set is updated to include packet
3814 // alloc_pkt_id: data descriptor id (NOT dview idx)
3815 // net_alloc: adjustment to net allocation for this packet (note: signed value)
3816 // leaks: leak bytes to attribute to alloc_pkt_id
3817 std::pair < std::set<long>::iterator, bool> ret;
3818 ret = pkt_id_set.insert (alloc_pkt_id); // add to set
3819 bool new_to_set = ret.second; // was not in set
3820 if (!new_to_set)
3822 // Has been seen before, update values
3823 net_alloc += dview->getDataDescriptorValue (PROP_HCUR_NET_ALLOC, alloc_pkt_id);
3824 if (leaks)
3826 uint64_t old = dview->getDataDescriptorValue (PROP_HCUR_LEAKS, alloc_pkt_id);
3827 if (old != 0)
3828 leaks = old;
3831 dview->setDataDescriptorValue (PROP_HCUR_NET_ALLOC, alloc_pkt_id, net_alloc);
3832 dview->setDataDescriptorValue (PROP_HCUR_LEAKS, alloc_pkt_id, leaks);
3835 DataView *
3836 Experiment::create_heapsz_data_view (DataView *heap_dview)
3838 // heap_dview has DATA_HEAP _filtered_ packets.
3839 // This creates, populates, and returns DATA_HEAPSZ DataView
3840 DataDescriptor *dDscr = get_heapsz_events ();
3841 if (dDscr == NULL)
3842 return NULL;
3843 std::set<long> pkt_id_set;
3844 DataView *dview = heap_dview;
3845 long sz = dview->getSize ();
3846 for (long i = 0; i < sz; i++)
3848 int64_t hsize = (int64_t) dview->getULongValue (PROP_HSIZE, i);
3849 uint64_t leaks = dview->getULongValue (PROP_HLEAKED, i);
3850 long alloc_pkt_id = dview->getIdByIdx (i);
3851 update_heapsz_packet (pkt_id_set, dview, alloc_pkt_id, hsize, leaks);
3853 // linked free
3854 UnmapChunk *mmap_frees = (UnmapChunk *) dview->getObjValue (PROP_VOIDP_OBJ, i); // mmap metadata
3855 if (mmap_frees)
3857 // mmap: all frees associated with this packet
3858 while (mmap_frees)
3860 long free_pkt_id = mmap_frees->val;
3861 int64_t free_sz = mmap_frees->size;
3862 update_heapsz_packet (pkt_id_set, dview, free_pkt_id, -free_sz, 0);
3863 mmap_frees = mmap_frees->next;
3866 else
3868 // malloc: check for associated free
3869 long free_pkt_id = dview->getLongValue (PROP_DDSCR_LNK, i) - 1;
3870 if (free_pkt_id >= 0)
3871 update_heapsz_packet (pkt_id_set, dview, free_pkt_id, -hsize, 0);
3875 // create a new DataView based on the filtered-in and associated free events
3876 std::set<long>::iterator it;
3877 DataView *heapsz_dview = dDscr->createExtManagedView ();
3878 for (it = pkt_id_set.begin (); it != pkt_id_set.end (); ++it)
3880 long ddscr_pkt_id = *it;
3881 heapsz_dview->appendDataDescriptorId (ddscr_pkt_id);
3883 compute_heapsz_data_view (heapsz_dview);
3884 return heapsz_dview;
3887 void
3888 Experiment::compute_heapsz_data_view (DataView *heapsz_dview)
3890 DataView *dview = heapsz_dview;
3892 // Keep track of memory usage
3893 int64_t currentAllocs = 0;
3894 Size currentLeaks = 0;
3895 dview->sort (PROP_TSTAMP);
3896 long sz = dview->getSize ();
3897 for (long i = 0; i < sz; i++)
3899 int64_t net_alloc = dview->getLongValue (PROP_HCUR_NET_ALLOC, i);
3900 currentAllocs += net_alloc;
3901 dview->setValue (PROP_HCUR_ALLOCS, i, currentAllocs);
3903 Size leaks = dview->getULongValue (PROP_HCUR_LEAKS, i);
3904 currentLeaks += leaks;
3905 dview->setValue (PROP_HCUR_LEAKS, i, currentLeaks);
3909 void
3910 Experiment::DBG_memuse (Sample * s)
3912 DataDescriptor *dDscr = getDataDescriptor (DATA_HEAP);
3913 if (dDscr == NULL || dDscr->getSize () == 0)
3914 return;
3916 DataView *dview = dDscr->createView ();
3917 dview->sort (PROP_TSTAMP);
3918 hrtime_t ts1 = s->get_start_time ();
3919 hrtime_t ts2 = s->get_end_time ();
3921 HeapMap *heapmap = new HeapMap ();
3922 long sz = dview->getSize ();
3923 Size maxSize = 0;
3924 Size curSize = 0;
3925 hrtime_t maxTime = 0;
3926 for (long i = 0; i < sz; i++)
3928 hrtime_t tstamp = dview->getLongValue (PROP_TSTAMP, i);
3929 if (tstamp < ts1)
3930 continue;
3931 if (tstamp >= ts2)
3932 break;
3934 Heap_type mtype = (Heap_type) dview->getIntValue (PROP_HTYPE, i);
3935 Vaddr vaddr = dview->getULongValue (PROP_HVADDR, i);
3936 Vaddr ovaddr = dview->getULongValue (PROP_HOVADDR, i);
3937 switch (mtype)
3939 case REALLOC_TRACE:
3940 break;
3941 case MALLOC_TRACE:
3942 ovaddr = 0;
3943 break;
3944 case FREE_TRACE:
3945 ovaddr = vaddr;
3946 vaddr = 0;
3947 break;
3948 default:
3949 vaddr = 0;
3950 ovaddr = 0;
3951 break;
3953 if (ovaddr)
3955 long idx = heapmap->deallocate (ovaddr) - 1;
3956 if (idx >= 0)
3957 curSize -= dview->getULongValue (PROP_HSIZE, idx);
3959 if (vaddr)
3961 heapmap->allocate (vaddr, i + 1);
3962 curSize += dview->getULongValue (PROP_HSIZE, i);
3963 if (curSize > maxSize)
3965 maxSize = curSize;
3966 maxTime = tstamp;
3970 printf ("SAMPLE=%s (id=%d) MEMUSE=%lld TSTAMP=%lld\n", s->get_start_label (),
3971 s->get_number (), maxSize, maxTime - getStartTime ());
3972 delete dview;
3973 delete heapmap;
3976 void
3977 Experiment::DBG_memuse (const char *sname)
3979 for (int i = 0; i < samples->size (); ++i)
3981 Sample *sample = samples->fetch (i);
3982 if (streq (sname, sample->get_start_label ()))
3984 DBG_memuse (sample);
3985 break;
3990 DataDescriptor *
3991 Experiment::get_race_events ()
3993 DataDescriptor *dDscr = getDataDescriptor (DATA_RACE);
3994 if (dDscr == NULL)
3995 return NULL;
3996 if (dDscr->getSize () == 0)
3998 char *base_name = get_basename (expt_name);
3999 char *msg = dbe_sprintf (GTXT ("Loading Race Data: %s"), base_name);
4000 read_data_file (SP_RACETRACE_FILE, msg);
4001 free (msg);
4002 resolve_frame_info (dDscr);
4004 return dDscr;
4007 DataDescriptor *
4008 Experiment::get_deadlock_events ()
4010 DataDescriptor *dDscr = getDataDescriptor (DATA_DLCK);
4011 if (dDscr == NULL)
4012 return NULL;
4013 if (dDscr->getSize () == 0)
4015 char *base_name = get_basename (expt_name);
4016 char *msg = dbe_sprintf (GTXT ("Loading Deadlocks Data: %s"), base_name);
4017 read_data_file (SP_DEADLOCK_FILE, msg);
4018 free (msg);
4019 resolve_frame_info (dDscr);
4021 return dDscr;
4024 DataDescriptor *
4025 Experiment::get_sample_events ()
4027 DataDescriptor *dDscr = getDataDescriptor (DATA_SAMPLE);
4028 if (dDscr == NULL)
4029 return NULL;
4030 if (dDscr->getSize () > 0)
4031 return dDscr;
4033 // read_overview_file(); //YXXX do this here at some point instead of:
4034 PropDescr *tmp_propDscr;
4035 tmp_propDscr = new PropDescr (PROP_SMPLOBJ, NTXT ("SMPLOBJ"));
4036 tmp_propDscr->uname = NULL;
4037 tmp_propDscr->vtype = TYPE_OBJ;
4038 dDscr->addProperty (tmp_propDscr);
4040 tmp_propDscr = new PropDescr (PROP_TSTAMP, NTXT ("TSTAMP"));
4041 tmp_propDscr->uname = dbe_strdup ("High resolution timestamp");
4042 tmp_propDscr->vtype = TYPE_UINT64;
4043 dDscr->addProperty (tmp_propDscr);
4045 tmp_propDscr = new PropDescr (PROP_SAMPLE, NTXT ("SAMPLE"));
4046 tmp_propDscr->uname = dbe_strdup ("Sample number");
4047 tmp_propDscr->vtype = TYPE_UINT64;
4048 dDscr->addProperty (tmp_propDscr);
4050 tmp_propDscr = new PropDescr (PROP_EVT_TIME, NTXT ("EVT_TIME"));
4051 tmp_propDscr->uname = dbe_strdup ("Event duration");
4052 tmp_propDscr->vtype = TYPE_UINT64;
4053 dDscr->addProperty (tmp_propDscr);
4055 long ssize = samples->size ();
4056 for (long ii = 0; ii < ssize; ii++)
4058 Sample * sample = samples->fetch (ii);
4059 long recn = dDscr->addRecord ();
4060 hrtime_t sduration = sample->get_end_time () - sample->get_start_time ();
4061 dDscr->setObjValue (PROP_SMPLOBJ, recn, sample);
4062 dDscr->setValue (PROP_SAMPLE, recn, sample->get_number ());
4063 dDscr->setValue (PROP_TSTAMP, recn, sample->get_end_time ());
4064 dDscr->setValue (PROP_EVT_TIME, recn, sduration);
4066 return dDscr;
4069 DataDescriptor *
4070 Experiment::get_gc_events ()
4072 DataDescriptor *dDscr = getDataDescriptor (DATA_GCEVENT);
4073 if (dDscr == NULL)
4074 return NULL;
4075 if (dDscr->getSize () > 0)
4076 return dDscr;
4078 // read_overview_file(); //YXXX do this here at some point instead of:
4079 PropDescr *tmp_propDscr;
4080 tmp_propDscr = new PropDescr (PROP_GCEVENTOBJ, NTXT ("GCEVENTOBJ"));
4081 tmp_propDscr->uname = NULL;
4082 tmp_propDscr->vtype = TYPE_OBJ;
4083 dDscr->addProperty (tmp_propDscr);
4085 tmp_propDscr = new PropDescr (PROP_TSTAMP, NTXT ("TSTAMP"));
4086 tmp_propDscr->uname = dbe_strdup ("High resolution timestamp");
4087 tmp_propDscr->vtype = TYPE_UINT64;
4088 dDscr->addProperty (tmp_propDscr);
4090 tmp_propDscr = new PropDescr (PROP_GCEVENT, NTXT ("GCEVENT"));
4091 tmp_propDscr->uname = dbe_strdup ("GCEvent number");
4092 tmp_propDscr->vtype = TYPE_UINT64;
4093 dDscr->addProperty (tmp_propDscr);
4095 tmp_propDscr = new PropDescr (PROP_EVT_TIME, NTXT ("EVT_TIME"));
4096 tmp_propDscr->uname = dbe_strdup ("Event duration");
4097 tmp_propDscr->vtype = TYPE_UINT64;
4098 dDscr->addProperty (tmp_propDscr);
4100 long ssize = gcevents->size ();
4101 for (long ii = 0; ii < ssize; ii++)
4103 GCEvent * gcevent = gcevents->fetch (ii);
4104 long recn = dDscr->addRecord ();
4105 hrtime_t sduration = gcevent->end - gcevent->start;
4106 dDscr->setObjValue (PROP_GCEVENTOBJ, recn, gcevent);
4107 dDscr->setValue (PROP_GCEVENT, recn, gcevent->id);
4108 dDscr->setValue (PROP_TSTAMP, recn, gcevent->end);
4109 dDscr->setValue (PROP_EVT_TIME, recn, sduration);
4111 return dDscr;
4114 void
4115 Experiment::update_last_event (hrtime_t ts/*wall_ts*/)
4117 if (last_event == ZERO_TIME)
4119 // not yet initialized
4120 last_event = ts;
4122 if (last_event - exp_start_time < ts - exp_start_time)
4123 // compare deltas to avoid hrtime_t wrap
4124 last_event = ts;
4127 void
4128 Experiment::write_header ()
4130 StringBuilder sb;
4132 // write commentary to the experiment, describing the parameters
4133 if (dbeSession->ipc_mode || dbeSession->rdt_mode)
4135 // In GUI: print start time at the beginning
4136 time_t t = (time_t) start_sec;
4137 char *start_time = ctime (&t);
4138 if (start_time != NULL)
4140 sb.setLength (0);
4141 sb.sprintf (GTXT ("Experiment started %s"), start_time);
4142 commentq->append (new Emsg (CMSG_COMMENT, sb));
4145 // write message with target arglist
4146 if (uarglist != NULL)
4148 sb.setLength (0);
4149 sb.sprintf (GTXT ("\nTarget command (%s): '%s'"),
4150 (wsize == W32 ? "32-bit" : "64-bit"), uarglist);
4151 commentq->append (new Emsg (CMSG_COMMENT, sb));
4154 sb.setLength (0);
4155 sb.sprintf (GTXT ("Process pid %d, ppid %d, pgrp %d, sid %d"),
4156 pid, ppid, pgrp, sid);
4157 commentq->append (new Emsg (CMSG_COMMENT, sb));
4159 // add comment for user name, if set
4160 if (username != NULL)
4162 sb.setLength (0);
4163 sb.sprintf (GTXT ("User: `%s'"), username);
4164 commentq->append (new Emsg (CMSG_COMMENT, sb));
4167 // add comment for current working directory
4168 if (ucwd != NULL)
4170 sb.setLength (0);
4171 sb.sprintf (GTXT ("Current working directory: %s"), ucwd);
4172 commentq->append (new Emsg (CMSG_COMMENT, sb));
4175 // add comment for collector version string
4176 if (cversion != NULL)
4178 char *wstring;
4179 switch (wsize)
4181 case Wnone:
4182 wstring = NTXT ("?");
4183 break;
4184 case W32:
4185 wstring = GTXT ("32-bit");
4186 break;
4187 case W64:
4188 wstring = GTXT ("64-bit");
4189 break;
4190 default:
4191 wstring = NTXT ("??");
4192 break;
4194 sb.setLength (0);
4195 sb.sprintf (GTXT ("Collector version: `%s'; experiment version %d.%d (%s)"),
4196 cversion, exp_maj_version, exp_min_version, wstring);
4197 commentq->append (new Emsg (CMSG_COMMENT, sb));
4200 // add comment for driver version string (er_kernel)
4201 if (dversion != NULL)
4203 sb.setLength (0);
4204 sb.sprintf (GTXT ("Kernel driver version: `%s'"), dversion);
4205 commentq->append (new Emsg (CMSG_COMMENT, sb));
4208 if (jversion != NULL)
4210 sb.setLength (0);
4211 sb.sprintf (GTXT ("JVM version: `%s'"), jversion);
4212 commentq->append (new Emsg (CMSG_COMMENT, sb));
4215 // add comment for hostname, parameters
4216 if (hostname == NULL)
4217 hostname = dbe_strdup (GTXT ("unknown"));
4218 if (os_version == NULL)
4219 os_version = dbe_strdup (GTXT ("unknown"));
4220 if (architecture == NULL)
4221 architecture = dbe_strdup (GTXT ("unknown"));
4222 sb.setLength (0);
4223 sb.sprintf (GTXT ("Host `%s', OS `%s', page size %d, architecture `%s'"),
4224 hostname, os_version, page_size, architecture);
4225 commentq->append (new Emsg (CMSG_COMMENT, sb));
4227 sb.setLength (0);
4228 if (maxclock != minclock)
4230 clock = maxclock;
4231 sb.sprintf (
4232 GTXT (" %d CPUs, with clocks ranging from %d to %d MHz.; max of %d MHz. assumed"),
4233 ncpus, minclock, maxclock, clock);
4235 else
4236 sb.sprintf (GTXT (" %d CPU%s, clock speed %d MHz."),
4237 ncpus, (ncpus == 1 ? NTXT ("") : "s"), clock);
4238 commentq->append (new Emsg (CMSG_COMMENT, sb));
4240 // add comment for machine memory size
4241 if (page_size > 0 && npages > 0)
4243 long long memsize = ((long long) npages * page_size) / (1024 * 1024);
4244 sb.setLength (0);
4245 sb.sprintf (GTXT (" Memory: %d pages @ %d = %lld MB."),
4246 npages, page_size, memsize);
4247 commentq->append (new Emsg (CMSG_COMMENT, sb));
4250 // add comment for machine memory size
4251 if (machinemodel != NULL)
4253 sb.setLength (0);
4254 sb.sprintf (GTXT (" Machine model: %s"), machinemodel);
4255 commentq->append (new Emsg (CMSG_COMMENT, sb));
4258 // add comment for start time
4259 time_t t = (time_t) start_sec;
4260 char *p = ctime (&t);
4261 sb.setLength (0);
4262 if (p != NULL)
4263 sb.sprintf (GTXT ("Experiment started %s"), p);
4264 else
4265 sb.sprintf (GTXT ("\nExperiment start not recorded"));
4266 write_coll_params ();
4267 commentq->append (new Emsg (CMSG_COMMENT, sb));
4268 commentq->appendqueue (runlogq);
4269 runlogq->mark_clear ();
4272 void
4273 Experiment::write_coll_params ()
4275 StringBuilder sb;
4277 // now write the various collection parameters as comments
4278 sb.setLength (0);
4279 sb.append (GTXT ("Data collection parameters:"));
4280 commentq->append (new Emsg (CMSG_COMMENT, sb));
4281 if (coll_params.profile_mode == 1)
4283 sb.setLength (0);
4284 sb.sprintf (GTXT (" Clock-profiling, interval = %d microsecs."),
4285 (int) (coll_params.ptimer_usec));
4286 commentq->append (new Emsg (CMSG_COMMENT, sb));
4288 if (coll_params.sync_mode == 1)
4290 sb.setLength (0);
4291 char *scope_str = NTXT ("");
4292 switch (coll_params.sync_scope)
4294 case 0:
4295 scope_str = GTXT ("Native- and Java-APIs");
4296 break;
4297 case SYNCSCOPE_JAVA:
4298 scope_str = GTXT ("JAVA-APIs");
4299 break;
4300 case SYNCSCOPE_NATIVE:
4301 scope_str = GTXT ("Native-APIs");
4302 break;
4303 case SYNCSCOPE_JAVA | SYNCSCOPE_NATIVE:
4304 scope_str = GTXT ("Native- and Java-APIs");
4305 break;
4307 if (coll_params.sync_threshold < 0)
4308 sb.sprintf (GTXT (" Synchronization tracing, threshold = %d microsecs. (calibrated); %s"),
4309 -coll_params.sync_threshold, scope_str);
4310 else
4311 sb.sprintf (GTXT (" Synchronization tracing, threshold = %d microsecs.; %s"),
4312 coll_params.sync_threshold, scope_str);
4313 commentq->append (new Emsg (CMSG_COMMENT, sb));
4315 if (coll_params.heap_mode == 1)
4317 sb.setLength (0);
4318 sb.append (GTXT (" Heap tracing"));
4319 commentq->append (new Emsg (CMSG_COMMENT, sb));
4321 if (coll_params.io_mode == 1)
4323 sb.setLength (0);
4324 sb.append (GTXT (" IO tracing"));
4325 commentq->append (new Emsg (CMSG_COMMENT, sb));
4327 if (coll_params.race_mode == 1)
4329 sb.setLength (0);
4330 char *race_stack_name;
4331 switch (coll_params.race_stack)
4333 case 0:
4334 race_stack_name = GTXT ("dual-stack");
4335 break;
4336 case 1:
4337 race_stack_name = GTXT ("single-stack");
4338 break;
4339 case 2:
4340 race_stack_name = GTXT ("leaf");
4341 break;
4342 default:
4343 abort ();
4345 sb.sprintf (GTXT (" Datarace detection, %s"), race_stack_name);
4346 commentq->append (new Emsg (CMSG_COMMENT, sb));
4348 if (coll_params.deadlock_mode == 1)
4350 sb.setLength (0);
4351 sb.append (GTXT (" Deadlock detection"));
4352 commentq->append (new Emsg (CMSG_COMMENT, sb));
4354 if (coll_params.hw_mode == 1)
4356 sb.setLength (0);
4357 if (hwc_default == true)
4358 sb.append (GTXT (" HW counter-profiling (default); counters:"));
4359 else
4360 sb.append (GTXT (" HW counter-profiling; counters:"));
4361 commentq->append (new Emsg (CMSG_COMMENT, sb));
4362 for (int i = 0; i < MAX_HWCOUNT; i++)
4364 if (!coll_params.hw_aux_name[i])
4365 continue;
4366 sb.setLength (0);
4367 sb.sprintf (GTXT (" %s, tag %d, interval %d, memop %d"),
4368 coll_params.hw_aux_name[i], i,
4369 coll_params.hw_interval[i], coll_params.hw_tpc[i]);
4370 commentq->append (new Emsg (CMSG_COMMENT, sb));
4373 if (coll_params.sample_periodic == 1)
4375 sb.setLength (0);
4376 sb.sprintf (GTXT (" Periodic sampling, %d secs."),
4377 coll_params.sample_timer);
4378 commentq->append (new Emsg (CMSG_COMMENT, sb));
4380 if (coll_params.limit != 0)
4382 sb.setLength (0);
4383 sb.sprintf (GTXT (" Experiment size limit, %d"),
4384 coll_params.limit);
4385 commentq->append (new Emsg (CMSG_COMMENT, sb));
4387 if (coll_params.linetrace != NULL)
4389 sb.setLength (0);
4390 sb.sprintf (GTXT (" Follow descendant processes from: %s"),
4391 coll_params.linetrace);
4392 commentq->append (new Emsg (CMSG_COMMENT, sb));
4394 if (coll_params.pause_sig != NULL)
4396 sb.setLength (0);
4397 sb.sprintf (GTXT (" Pause signal %s"), coll_params.pause_sig);
4398 commentq->append (new Emsg (CMSG_COMMENT, sb));
4400 if (coll_params.sample_sig != NULL)
4402 sb.setLength (0);
4403 sb.sprintf (GTXT (" Sample signal %s"), coll_params.sample_sig);
4404 commentq->append (new Emsg (CMSG_COMMENT, sb));
4406 if (coll_params.start_delay != NULL)
4408 sb.setLength (0);
4409 sb.sprintf (GTXT (" Data collection delay start %s seconds"), coll_params.start_delay);
4410 commentq->append (new Emsg (CMSG_COMMENT, sb));
4412 if (coll_params.terminate != NULL)
4414 sb.setLength (0);
4415 sb.sprintf (GTXT (" Data collection termination after %s seconds"), coll_params.terminate);
4416 commentq->append (new Emsg (CMSG_COMMENT, sb));
4418 // add a blank line after data description
4419 commentq->append (new Emsg (CMSG_COMMENT, NTXT ("")));
4424 * Raw packet processing
4426 static int
4427 check_mstate (char *ptr, PacketDescriptor *pDscr, int arg)
4429 switch (arg)
4431 case PROP_UCPU:
4432 case PROP_SCPU:
4433 case PROP_TRAP:
4434 case PROP_TFLT:
4435 case PROP_DFLT:
4436 case PROP_KFLT:
4437 case PROP_ULCK:
4438 case PROP_TSLP:
4439 case PROP_WCPU:
4440 case PROP_TSTP:
4441 break;
4442 default:
4443 return 0;
4445 Vector<FieldDescr*> *fields = pDscr->getFields ();
4446 for (int i = 0, sz = fields->size (); i < sz; i++)
4448 FieldDescr *fDscr = fields->fetch (i);
4449 if (fDscr->propID == arg)
4450 return *((int*) (ptr + fDscr->offset));
4452 return 0;
4455 #define PACKET_ALIGNMENT 4
4457 uint64_t
4458 Experiment::readPacket (Data_window *dwin, Data_window::Span *span)
4460 Common_packet *rcp = (Common_packet *) dwin->bind (span,
4461 sizeof (CommonHead_packet));
4462 uint16_t v16;
4463 uint64_t size = 0;
4464 if (rcp)
4466 if ((((long) rcp) % PACKET_ALIGNMENT) != 0)
4468 invalid_packet++;
4469 size = PROFILE_BUFFER_CHUNK - span->offset % PROFILE_BUFFER_CHUNK;
4470 return size;
4472 v16 = (uint16_t) rcp->tsize;
4473 size = dwin->decode (v16);
4474 if (size == 0)
4476 size = PROFILE_BUFFER_CHUNK - span->offset % PROFILE_BUFFER_CHUNK;
4477 return size;
4479 rcp = (Common_packet *) dwin->bind (span, size);
4481 if (rcp == NULL)
4482 return 0;
4484 if ((((long) rcp) % PACKET_ALIGNMENT) != 0)
4486 invalid_packet++;
4487 size = PROFILE_BUFFER_CHUNK - span->offset % PROFILE_BUFFER_CHUNK;
4488 return size;
4490 v16 = (uint16_t) rcp->type;
4491 uint32_t rcptype = dwin->decode (v16);
4492 if (rcptype == EMPTY_PCKT)
4493 return size;
4494 if (rcptype == FRAME_PCKT)
4496 RawFramePacket *fp = new RawFramePacket;
4497 fp->uid = dwin->decode (((Frame_packet*) rcp)->uid);
4498 fp->uidn = NULL;
4499 fp->uidj = NULL;
4500 fp->omp_uid = NULL;
4501 fp->omp_state = 0;
4502 char *ptr = (char*) rcp + dwin->decode (((Frame_packet*) rcp)->hsize);
4503 if ((((long) ptr) % PACKET_ALIGNMENT) != 0)
4505 invalid_packet++;
4506 delete fp;
4507 return size;
4509 v16 = (uint16_t) ((Frame_packet*) rcp)->tsize;
4510 char *end = (char*) rcp + dwin->decode (v16);
4511 for (; ptr < end;)
4513 Common_info *cinfo = (Common_info*) ptr;
4514 uint32_t hsize = dwin->decode (cinfo->hsize);
4515 if (hsize == 0 || ptr + hsize > end)
4516 break;
4517 int kind = dwin->decode (cinfo->kind);
4518 bool compressed = false;
4519 if (kind & COMPRESSED_INFO)
4521 compressed = true;
4522 kind &= ~COMPRESSED_INFO;
4524 switch (kind)
4526 case STACK_INFO:
4528 char *stack = ptr + sizeof (Stack_info);
4529 size_t stack_size = hsize - sizeof (Stack_info);
4530 uint64_t uidn = dwin->decode (((Stack_info*) cinfo)->uid);
4531 if (stack_size <= 0)
4533 fp->uidn = get_uid_node (uidn);
4534 break;
4536 uint64_t link_uid = (uint64_t) 0;
4537 if (compressed)
4539 stack_size -= sizeof (uint64_t);
4540 unsigned char *s = (unsigned char*) (stack + stack_size);
4541 int shift = 0;
4542 for (size_t i = 0; i<sizeof (link_uid); i++)
4544 link_uid |= (uint64_t) * s++ << shift;
4545 shift += 8;
4548 if (wsize == W32)
4549 fp->uidn = add_uid (dwin, uidn,
4550 (int) (stack_size / sizeof (uint32_t)),
4551 (uint32_t*) stack, link_uid);
4552 else
4553 fp->uidn = add_uid (dwin, uidn,
4554 (int) (stack_size / sizeof (uint64_t)),
4555 (uint64_t*) stack, link_uid);
4556 break;
4558 case JAVA_INFO:
4560 char *stack = ptr + sizeof (Java_info);
4561 size_t stack_size = hsize - sizeof (Java_info);
4562 uint64_t uidj = dwin->decode (((Java_info*) cinfo)->uid);
4563 if (stack_size <= 0)
4565 fp->uidj = get_uid_node (uidj);
4566 break;
4569 uint64_t link_uid = (uint64_t) 0;
4570 if (compressed)
4572 stack_size -= sizeof (uint64_t);
4573 unsigned char *s = (unsigned char*) (stack + stack_size);
4574 int shift = 0;
4575 for (size_t i = 0; i<sizeof (link_uid); i++)
4577 link_uid |= (uint64_t) * s++ << shift;
4578 shift += 8;
4581 if (wsize == W32)
4582 fp->uidj = add_uid (dwin, uidj,
4583 (int) (stack_size / sizeof (uint32_t)),
4584 (uint32_t*) stack, link_uid);
4585 else
4587 // bug 6909545: garbage in 64-bit JAVA_INFO
4588 char *nstack = (char*) xmalloc (stack_size);
4589 char *dst = nstack;
4590 char *srcmax = stack + stack_size - sizeof (uint64_t);
4591 for (char *src = stack; src <= srcmax;)
4593 int64_t val = dwin->decode (*(int32_t*) src);
4594 *(uint64_t*) dst = dwin->decode (val);
4595 src += sizeof (uint64_t);
4596 dst += sizeof (uint64_t);
4597 if (src > srcmax)
4599 fprintf (stderr, "er_print: Experiment::readPacket: Error in data: src=%llx greater than %llx\n",
4600 (long long) src, (long long) srcmax);
4601 break;
4603 *(uint64_t*) dst = *(uint64_t*) src;
4604 src += sizeof (uint64_t);
4605 dst += sizeof (uint64_t);
4607 fp->uidj = add_uid (dwin, uidj,
4608 (int) (stack_size / sizeof (uint64_t)),
4609 (uint64_t*) nstack, link_uid);
4610 free (nstack);
4612 break;
4614 case OMP_INFO:
4615 fp->omp_state = dwin->decode (((OMP_info*) ptr)->omp_state);
4616 break;
4617 case OMP2_INFO:
4619 uint64_t omp_uid = dwin->decode (((OMP2_info*) ptr)->uid);
4620 fp->omp_uid = get_uid_node (omp_uid);
4621 fp->omp_state = dwin->decode (((OMP2_info*) ptr)->omp_state);
4622 break;
4624 default:
4625 break;
4627 ptr += hsize;
4629 frmpckts->append (fp);
4630 return size;
4632 else if (rcptype == UID_PCKT)
4634 Uid_packet *uidp = (Uid_packet*) rcp;
4635 uint64_t uid = dwin->decode (uidp->uid);
4636 char *arr_bytes = (char*) (uidp + 1);
4637 v16 = (uint16_t) rcp->tsize;
4638 size_t arr_length = dwin->decode (v16) - sizeof (Uid_packet);
4639 if (arr_length <= 0)
4640 return size;
4641 uint64_t link_uid = (uint64_t) 0;
4642 if (dwin->decode (uidp->flags) & COMPRESSED_INFO)
4644 arr_length -= sizeof (uint64_t);
4645 unsigned char *s = (unsigned char*) (arr_bytes + arr_length);
4646 int shift = 0;
4647 for (size_t i = 0; i<sizeof (link_uid); i++)
4649 link_uid |= (uint64_t) * s++ << shift;
4650 shift += 8;
4653 if (wsize == W32)
4654 add_uid (dwin, uid, (int) (arr_length / sizeof (uint32_t)),
4655 (uint32_t*) arr_bytes, link_uid);
4656 else
4657 add_uid (dwin, uid, (int) (arr_length / sizeof (uint64_t)),
4658 (uint64_t*) arr_bytes, link_uid);
4659 return size;
4662 PacketDescriptor *pcktDescr = getPacketDescriptor (rcptype);
4663 if (pcktDescr == NULL)
4664 return size;
4665 DataDescriptor *dataDescr = pcktDescr->getDataDescriptor ();
4666 if (dataDescr == NULL)
4667 return size;
4669 /* omazur: TBR START -- old experiment */
4670 if (rcptype == PROF_PCKT)
4672 // For backward compatibility with older SS12 experiments
4673 int numstates = get_params ()->lms_magic_id; // ugly, for old experiments
4674 if (numstates > LMS_NUM_SOLARIS_MSTATES)
4675 numstates = LMS_NUM_SOLARIS_MSTATES;
4676 for (int i = 0; i < numstates; i++)
4677 if (check_mstate ((char*) rcp, pcktDescr, PROP_UCPU + i))
4678 readPacket (dwin, (char*) rcp, pcktDescr, dataDescr, PROP_UCPU + i,
4679 size);
4681 else
4682 readPacket (dwin, (char*) rcp, pcktDescr, dataDescr, 0, size);
4683 return size;
4686 static uint32_t get_v32(char *p)
4688 uint32_t v;
4689 memcpy (&v, p, sizeof(uint32_t));
4690 return v;
4693 static uint64_t get_v64(char *p)
4695 uint64_t v;
4696 memcpy (&v, p, sizeof(uint64_t));
4697 return v;
4700 void
4701 Experiment::readPacket (Data_window *dwin, char *ptr, PacketDescriptor *pDscr,
4702 DataDescriptor *dDscr, int arg, uint64_t pktsz)
4704 long recn = dDscr->addRecord ();
4705 Vector<FieldDescr*> *fields = pDscr->getFields ();
4706 uint32_t v32;
4707 uint64_t v64;
4708 int sz = fields->size ();
4709 for (int i = 0; i < sz; i++)
4711 FieldDescr *field = fields->fetch (i);
4712 if (field->propID == arg)
4714 v32 = get_v32(ptr + field->offset);
4715 dDscr->setValue (PROP_NTICK, recn, dwin->decode (v32));
4716 dDscr->setValue (PROP_MSTATE, recn, (uint32_t) (field->propID - PROP_UCPU));
4718 if (field->propID == PROP_THRID || field->propID == PROP_LWPID
4719 || field->propID == PROP_CPUID)
4721 uint64_t tmp64 = 0;
4722 switch (field->vtype)
4724 case TYPE_INT32:
4725 case TYPE_UINT32:
4726 v32 = get_v32 (ptr + field->offset);
4727 tmp64 = dwin->decode (v32);
4728 break;
4729 case TYPE_INT64:
4730 case TYPE_UINT64:
4731 v64 = get_v64 (ptr + field->offset);
4732 tmp64 = dwin->decode (v64);
4733 break;
4734 case TYPE_STRING:
4735 case TYPE_DOUBLE:
4736 case TYPE_OBJ:
4737 case TYPE_DATE:
4738 case TYPE_BOOL:
4739 case TYPE_ENUM:
4740 case TYPE_LAST:
4741 case TYPE_NONE:
4742 break;
4744 uint32_t tag = mapTagValue ((Prop_type) field->propID, tmp64);
4745 dDscr->setValue (field->propID, recn, tag);
4747 else
4749 switch (field->vtype)
4751 case TYPE_INT32:
4752 case TYPE_UINT32:
4753 v32 = get_v32 (ptr + field->offset);
4754 dDscr->setValue (field->propID, recn, dwin->decode (v32));
4755 break;
4756 case TYPE_INT64:
4757 case TYPE_UINT64:
4758 v64 = get_v64 (ptr + field->offset);
4759 dDscr->setValue (field->propID, recn, dwin->decode (v64));
4760 break;
4761 case TYPE_STRING:
4763 int len = (int) (pktsz - field->offset);
4764 if ((len > 0) && (ptr[field->offset] != 0))
4766 StringBuilder *sb = new StringBuilder ();
4767 sb->append (ptr + field->offset, 0, len);
4768 dDscr->setObjValue (field->propID, recn, sb);
4770 break;
4772 // ignoring the following cases (why?)
4773 case TYPE_DOUBLE:
4774 case TYPE_OBJ:
4775 case TYPE_DATE:
4776 case TYPE_BOOL:
4777 case TYPE_ENUM:
4778 case TYPE_LAST:
4779 case TYPE_NONE:
4780 break;
4786 #define PROG_BYTE 102400 // update progress bar every PROG_BYTE bytes
4788 void
4789 Experiment::read_data_file (const char *fname, const char *msg)
4791 Data_window::Span span;
4792 off64_t total_len, remain_len;
4793 char *progress_bar_msg;
4794 int progress_bar_percent = -1;
4796 char *data_file_name = dbe_sprintf (NTXT ("%s/%s"), expt_name, fname);
4797 Data_window *dwin = new Data_window (data_file_name);
4798 // Here we can call stat(data_file_name) to get file size,
4799 // and call a function to reallocate vectors for clock profiling data
4800 free (data_file_name);
4801 if (dwin->not_opened ())
4803 delete dwin;
4804 return;
4806 dwin->need_swap_endian = need_swap_endian;
4808 span.offset = 0;
4809 span.length = dwin->get_fsize ();
4810 total_len = remain_len = span.length;
4811 progress_bar_msg = dbe_sprintf (NTXT ("%s %s"), NTXT (" "), msg);
4812 invalid_packet = 0;
4813 for (;;)
4815 uint64_t pcktsz = readPacket (dwin, &span);
4816 if (pcktsz == 0)
4817 break;
4818 // Update progress bar
4819 if ((span.length <= remain_len) && (remain_len > 0))
4821 int percent = (int) (100 * (total_len - remain_len) / total_len);
4822 if (percent > progress_bar_percent)
4824 progress_bar_percent += 10;
4825 theApplication->set_progress (percent, progress_bar_msg);
4827 remain_len -= PROG_BYTE;
4829 span.length -= pcktsz;
4830 span.offset += pcktsz;
4832 delete dwin;
4834 if (invalid_packet)
4836 StringBuilder sb;
4837 sb.sprintf (GTXT ("WARNING: There are %d invalid packet(s) in the %s file"),
4838 invalid_packet, fname);
4839 Emsg *m = new Emsg (CMSG_WARN, sb);
4840 warnq->append (m);
4843 theApplication->set_progress (0, NTXT (""));
4844 free (progress_bar_msg);
4848 Experiment::read_overview_file ()
4850 char *data_file_name = dbe_sprintf ("%s/%s", expt_name, SP_OVERVIEW_FILE);
4851 Data_window *dwin = new Data_window (data_file_name);
4852 free (data_file_name);
4853 if (dwin->not_opened ())
4855 delete dwin;
4856 return 0;
4858 dwin->need_swap_endian = need_swap_endian;
4859 newDataDescriptor (DATA_SAMPLE);
4861 Data_window::Span span;
4862 span.offset = 0;
4863 span.length = dwin->get_fsize ();
4865 PrUsage *data = NULL, *data_prev = NULL;
4866 Sample *sample;
4867 int sample_number = 1;
4869 int64_t prDataSize;
4870 if (wsize == W32)
4871 prDataSize = PrUsage::bind32Size ();
4872 else
4873 prDataSize = PrUsage::bind64Size ();
4875 while (span.length > 0)
4877 data_prev = data;
4878 data = new PrUsage ();
4880 void *dw = dwin->bind (&span, prDataSize);
4881 if ((dw == NULL) || (prDataSize > span.length))
4883 Emsg *m = new Emsg (CMSG_ERROR, GTXT ("Warning: overview data file can't be read"));
4884 warnq->append (m);
4885 status = FAILURE;
4886 delete dwin;
4887 return status;
4890 if (wsize == W32)
4891 data->bind32 (dw, need_swap_endian);
4892 else
4893 data->bind64 (dw, need_swap_endian);
4894 span.length -= prDataSize;
4895 span.offset += prDataSize;
4897 // Skip the first packet
4898 if (data_prev == NULL)
4899 continue;
4900 if (sample_number > samples->size ())
4901 { // inconsistent log/overview
4902 sample = new Sample (sample_number);
4903 char * label = GTXT ("<unknown>");
4904 sample->start_label = dbe_strdup (label);
4905 sample->end_label = dbe_strdup (label);
4906 samples->append (sample);
4908 else
4909 sample = samples->fetch (sample_number - 1);
4910 sample_number++;
4911 sample->start_time = data_prev->pr_tstamp + 1;
4912 sample->end_time = data->pr_tstamp;
4913 sample->prusage = data_prev;
4915 data_prev->pr_rtime = data->pr_rtime - data_prev->pr_rtime;
4916 data_prev->pr_utime = data->pr_utime - data_prev->pr_utime;
4917 data_prev->pr_stime = data->pr_stime - data_prev->pr_stime;
4918 data_prev->pr_ttime = data->pr_ttime - data_prev->pr_ttime;
4919 data_prev->pr_tftime = data->pr_tftime - data_prev->pr_tftime;
4920 data_prev->pr_dftime = data->pr_dftime - data_prev->pr_dftime;
4921 data_prev->pr_kftime = data->pr_kftime - data_prev->pr_kftime;
4922 data_prev->pr_ltime = data->pr_ltime - data_prev->pr_ltime;
4923 data_prev->pr_slptime = data->pr_slptime - data_prev->pr_slptime;
4924 data_prev->pr_wtime = data->pr_wtime - data_prev->pr_wtime;
4925 data_prev->pr_stoptime = data->pr_stoptime - data_prev->pr_stoptime;
4926 data_prev->pr_minf = data->pr_minf - data_prev->pr_minf;
4927 data_prev->pr_majf = data->pr_majf - data_prev->pr_majf;
4928 data_prev->pr_nswap = data->pr_nswap - data_prev->pr_nswap;
4929 data_prev->pr_inblk = data->pr_inblk - data_prev->pr_inblk;
4930 data_prev->pr_oublk = data->pr_oublk - data_prev->pr_oublk;
4931 data_prev->pr_msnd = data->pr_msnd - data_prev->pr_msnd;
4932 data_prev->pr_mrcv = data->pr_mrcv - data_prev->pr_mrcv;
4933 data_prev->pr_sigs = data->pr_sigs - data_prev->pr_sigs;
4934 data_prev->pr_vctx = data->pr_vctx - data_prev->pr_vctx;
4935 data_prev->pr_ictx = data->pr_ictx - data_prev->pr_ictx;
4936 data_prev->pr_sysc = data->pr_sysc - data_prev->pr_sysc;
4937 data_prev->pr_ioch = data->pr_ioch - data_prev->pr_ioch;
4938 sample->get_usage (); // force validation
4941 for (long smpNum = samples->size (); smpNum >= sample_number; smpNum--)
4943 // overview file was truncated
4944 sample = samples->remove (smpNum - 1);
4945 delete sample;
4948 if (data)
4950 // Update last_event so that getEndTime() covers
4951 // all loadobjects, too.
4952 update_last_event (data->pr_tstamp);
4953 delete data;
4955 delete dwin;
4956 return SUCCESS;
4960 Experiment::uidNodeCmp (const void *a, const void *b)
4962 UIDnode *nd1 = *(UIDnode**) a;
4963 UIDnode *nd2 = *(UIDnode**) b;
4964 if (nd1->uid == nd2->uid)
4965 return 0;
4966 return nd1->uid < nd2->uid ? -1 : 1;
4969 static uint64_t
4970 funcAddr (uint32_t val)
4972 if (val == (uint32_t) SP_LEAF_CHECK_MARKER)
4973 return (uint64_t) SP_LEAF_CHECK_MARKER;
4974 if (val == (uint32_t) SP_TRUNC_STACK_MARKER)
4975 return (uint64_t) SP_TRUNC_STACK_MARKER;
4976 if (val == (uint32_t) SP_FAILED_UNWIND_MARKER)
4977 return (uint64_t) SP_FAILED_UNWIND_MARKER;
4978 return val;
4981 Experiment::UIDnode *
4982 Experiment::add_uid (Data_window *dwin, uint64_t uid, int size,
4983 uint32_t *array, uint64_t link_uid)
4985 if (uid == (uint64_t) 0)
4986 return NULL;
4987 uint64_t val = funcAddr (dwin->decode (array[0]));
4988 UIDnode *node = NULL;
4989 UIDnode *res = get_uid_node (uid, val);
4990 UIDnode *next = res;
4991 for (int i = 0; i < size; i++)
4993 val = funcAddr (dwin->decode (array[i]));
4994 if (next == NULL)
4996 next = get_uid_node ((uint64_t) 0, val);
4997 if (node != NULL)
4998 node->next = next;
5000 node = next;
5001 next = node->next;
5002 if (node->val == 0)
5003 node->val = val;
5004 else if (node->val != val) // Algorithmic error (should never happen)
5005 node->val = (uint64_t) SP_LEAF_CHECK_MARKER;
5007 if (next == NULL && link_uid != (uint64_t) 0 && node != NULL)
5008 node->next = get_uid_node (link_uid);
5009 return res;
5012 Experiment::UIDnode *
5013 Experiment::add_uid (Data_window *dwin, uint64_t uid, int size, uint64_t *array, uint64_t link_uid)
5015 if (uid == (uint64_t) 0)
5016 return NULL;
5017 UIDnode *node = NULL;
5018 uint64_t val = dwin->decode (array[0]);
5019 UIDnode *res = get_uid_node (uid, val);
5020 UIDnode *next = res;
5021 for (int i = 0; i < size; i++)
5023 val = dwin->decode (array[i]);
5024 if (next == NULL)
5026 next = get_uid_node ((uint64_t) 0, val);
5027 if (node != NULL)
5028 node->next = next;
5030 node = next;
5031 next = node->next;
5032 if (node->val == (uint64_t) 0)
5033 node->val = val;
5034 else if (node->val != val) // Algorithmic error (should never happen)
5035 node->val = (uint64_t) - 1;
5037 if (next == NULL && link_uid != (uint64_t) 0 && node != NULL)
5038 node->next = get_uid_node (link_uid);
5039 return res;
5042 Experiment::UIDnode *
5043 Experiment::new_uid_node (uint64_t uid, uint64_t val)
5045 #define NCHUNKSTEP 1024
5046 if (nnodes >= nchunks * CHUNKSZ)
5048 // Reallocate Node chunk array
5049 UIDnode** old_chunks = chunks;
5050 chunks = new UIDnode*[nchunks + NCHUNKSTEP];
5051 if (old_chunks)
5052 memcpy (chunks, old_chunks, nchunks * sizeof (UIDnode*));
5053 nchunks += NCHUNKSTEP;
5054 delete[] old_chunks;
5055 // Clean future pointers
5056 memset (&chunks[nchunks - NCHUNKSTEP], 0, NCHUNKSTEP * sizeof (UIDnode*));
5059 if (NULL == chunks[nnodes / CHUNKSZ]) // Allocate new chunk for nodes.
5060 chunks[nnodes / CHUNKSZ] = new UIDnode[CHUNKSZ];
5061 UIDnode *node = &chunks[nnodes / CHUNKSZ][nnodes % CHUNKSZ];
5062 node->uid = uid;
5063 node->val = val;
5064 node->next = NULL;
5065 nnodes++;
5066 return node;
5069 Experiment::UIDnode *
5070 Experiment::get_uid_node (uint64_t uid, uint64_t val)
5072 int hash = (((int) uid) >> 4) & (HTableSize - 1);
5073 if (uid != (uint64_t) 0)
5075 UIDnode *node = uidHTable[hash];
5076 if (node && node->uid == uid)
5077 return node;
5079 UIDnode *node = new_uid_node (uid, val);
5080 if (uid != (uint64_t) 0)
5082 uidHTable[hash] = node;
5083 uidnodes->append (node);
5085 return node;
5088 Experiment::UIDnode *
5089 Experiment::get_uid_node (uint64_t uid)
5091 if (uid == (uint64_t) 0)
5092 return NULL;
5093 int hash = (((int) uid) >> 4) & (HTableSize - 1);
5094 UIDnode *node = uidHTable[hash];
5095 if (node && node->uid == uid)
5096 return node;
5097 node = new_uid_node (uid, (uint64_t) 0);
5098 node->next = node;
5099 return node;
5102 Experiment::UIDnode *
5103 Experiment::find_uid_node (uint64_t uid)
5105 int hash = (((int) uid) >> 4) & (HTableSize - 1);
5106 UIDnode *node = uidHTable[hash];
5107 if (node && node->uid == uid)
5108 return node;
5109 int lt = 0;
5110 int rt = uidnodes->size () - 1;
5111 while (lt <= rt)
5113 int md = (lt + rt) / 2;
5114 node = uidnodes->fetch (md);
5115 if (node->uid < uid)
5116 lt = md + 1;
5117 else if (node->uid > uid)
5118 rt = md - 1;
5119 else
5121 uidHTable[hash] = node;
5122 return node;
5125 return NULL;
5129 Experiment::frUidCmp (const void *a, const void *b)
5131 RawFramePacket *fp1 = *(RawFramePacket**) a;
5132 RawFramePacket *fp2 = *(RawFramePacket**) b;
5133 if (fp1->uid == fp2->uid)
5134 return 0;
5135 return fp1->uid < fp2->uid ? -1 : 1;
5138 Experiment::RawFramePacket *
5139 Experiment::find_frame_packet (uint64_t uid)
5141 int lt = 0;
5142 int rt = frmpckts->size () - 1;
5143 while (lt <= rt)
5145 int md = (lt + rt) / 2;
5146 RawFramePacket *fp = frmpckts->fetch (md);
5147 if (fp->uid < uid)
5148 lt = md + 1;
5149 else if (fp->uid > uid)
5150 rt = md - 1;
5151 else
5152 return fp;
5155 return NULL;
5158 #define FRINFO_CACHEOPT_SIZE_LIMIT 4000000
5159 #define FRINFO_PIPELINE_SIZE_LIMIT 500000
5160 #define FRINFO_PIPELINE_NUM_STAGES 3
5162 // Pipelined execution of resolve_frame_info() and add_stack().
5163 // Since this is the largest time consuming part of loading an experiment (especially
5164 // so for large java experiments) - executing this part as a 3 stage pipeline can
5165 // give significant performance gain - and this concept can be aggressively applied
5166 // to enhance the gain further in future. The three stages are:
5167 // Phase 1: resolve_frame_info()
5168 // Phase 2: first part of add_stack() where the native stack is built
5169 // Phase 3: second part og add_stack() where the java stack is built
5170 // Phase 4: insert the native and java stacks into the stack map
5171 // The main thread operates in the first Phase and the other stages are
5172 // operated by a ssplib sequential queue - The threads working on the queues run concurrently
5173 // with each other and with the main thread. But within a particular queue, jobs are
5174 // executed sequentially
5177 // This is the second phase of the pipeline of resolve_frame_info and add_stack
5178 // It works on a chunk of iterations (size CSTCTX_CHUNK_SZ) and invokes add_stack()
5179 // for each one of them
5181 void
5182 Experiment::resolve_frame_info (DataDescriptor *dDscr)
5184 if (!resolveFrameInfo)
5185 return;
5186 if (NULL == cstack)
5187 return;
5188 dDscr->setResolveFrInfoDone ();
5190 // Check for TSTAMP
5191 int propID = dbeSession->getPropIdByName (NTXT ("TSTAMP"));
5192 Data *dataTStamp = dDscr->getData (propID);
5193 if (dataTStamp == NULL)
5194 return;
5196 propID = dbeSession->getPropIdByName (NTXT ("FRINFO"));
5197 Data *dataFrinfo = dDscr->getData (propID);
5199 propID = dbeSession->getPropIdByName (NTXT ("THRID"));
5200 Data *dataThrId = dDscr->getData (propID);
5202 // We can get frame info either by FRINFO or by [THRID,STKIDX]
5203 if (dataFrinfo == NULL)
5204 return;
5206 char *propName = NTXT ("MSTACK");
5207 propID = dbeSession->getPropIdByName (propName);
5208 PropDescr *prMStack = new PropDescr (propID, propName);
5209 prMStack->uname = dbe_strdup (GTXT ("Machine Call Stack"));
5210 prMStack->vtype = TYPE_OBJ;
5211 dDscr->addProperty (prMStack);
5213 propName = NTXT ("USTACK");
5214 propID = dbeSession->getPropIdByName (propName);
5215 PropDescr *prUStack = new PropDescr (propID, propName);
5216 prUStack->uname = dbe_strdup (GTXT ("User Call Stack"));
5217 prUStack->vtype = TYPE_OBJ;
5218 dDscr->addProperty (prUStack);
5220 propName = NTXT ("XSTACK");
5221 propID = dbeSession->getPropIdByName (propName);
5222 PropDescr *prXStack = new PropDescr (propID, propName);
5223 prXStack->uname = dbe_strdup (GTXT ("Expert Call Stack"));
5224 prXStack->vtype = TYPE_OBJ;
5225 dDscr->addProperty (prXStack);
5227 propName = NTXT ("HSTACK");
5228 propID = dbeSession->getPropIdByName (propName);
5229 PropDescr *prHStack = new PropDescr (propID, propName);
5230 prHStack->uname = dbe_strdup (GTXT ("ShowHide Call Stack"));
5231 prHStack->vtype = TYPE_OBJ;
5232 dDscr->addProperty (prHStack);
5234 if (has_java)
5236 propName = NTXT ("JTHREAD");
5237 propID = dbeSession->getPropIdByName (propName);
5238 PropDescr *prJThread = new PropDescr (propID, propName);
5239 prJThread->uname = dbe_strdup (GTXT ("Java Thread"));
5240 prJThread->vtype = TYPE_OBJ;
5241 dDscr->addProperty (prJThread);
5244 if (ompavail)
5246 PropDescr *prop = new PropDescr (PROP_OMPSTATE, NTXT ("OMPSTATE"));
5247 prop->uname = dbe_strdup (GTXT ("OpenMP state"));
5248 prop->vtype = TYPE_UINT32;
5249 char * stateNames [OMP_LAST_STATE] = OMP_THR_STATE_STRINGS;
5250 char * stateUNames[OMP_LAST_STATE] = OMP_THR_STATE_USTRINGS;
5251 for (int ii = 0; ii < OMP_LAST_STATE; ii++)
5252 prop->addState (ii, stateNames[ii], stateUNames[ii]);
5253 dDscr->addProperty (prop);
5255 // add PROP_CPRID to profiling data (not same as omptrace's PROP_CPRID)
5256 prop = dDscr->getProp (PROP_CPRID);
5257 if (prop)
5259 VType_type type = prop->vtype;
5260 assert (type == TYPE_OBJ); //see 7040526
5262 prop = new PropDescr (PROP_CPRID, NTXT ("CPRID")); //profiling PROP_CPRID
5263 prop->uname = dbe_strdup (GTXT ("OpenMP parallel region"));
5264 prop->vtype = TYPE_OBJ;
5265 dDscr->addProperty (prop);
5267 // add PROP_TSKID to profiling data (not same as omptrace's PROP_TSKID)
5268 prop = dDscr->getProp (PROP_TSKID);
5269 if (prop)
5271 VType_type type = prop->vtype;
5272 assert (type == TYPE_OBJ); //see 7040526
5274 prop = new PropDescr (PROP_TSKID, NTXT ("TSKID")); //profiling PROP_TSKID
5275 prop->uname = dbe_strdup (GTXT ("OpenMP task"));
5276 prop->vtype = TYPE_OBJ;
5277 dDscr->addProperty (prop);
5279 char *progress_bar_msg = dbe_sprintf (NTXT ("%s %s: %s"), NTXT (" "),
5280 GTXT ("Processing CallStack Data"),
5281 get_basename (expt_name));
5282 int progress_bar_percent = -1;
5283 long deltaReport = 5000;
5284 long nextReport = 0;
5286 long size = dDscr->getSize ();
5287 // bool resolve_frinfo_pipelined = size > FRINFO_PIPELINE_SIZE_LIMIT && !ompavail;
5288 bool resolve_frinfo_pipelined = false;
5290 Map<uint64_t, uint64_t> *nodeCache = NULL;
5291 Map<uint64_t, uint64_t> *frameInfoCache = NULL;
5292 if (size > FRINFO_CACHEOPT_SIZE_LIMIT && dversion == NULL)
5294 frameInfoCache = new CacheMap<uint64_t, uint64_t>;
5295 nodeCache = new CacheMap<uint64_t, uint64_t>;
5298 pushCnt = popCnt = pushCnt3 = popCnt3 = 0;
5299 nPush = nPop = 0;
5301 FramePacket *fp = NULL;
5302 // DbeThreadPool * threadPool = new DbeThreadPool(5);
5303 fp = new FramePacket;
5304 fp->stack = new Vector<Vaddr>;
5305 fp->jstack = new Vector<Vaddr>;
5306 fp->ompstack = new Vector<Vaddr>;
5307 fp->omp_state = 0;
5308 fp->mpi_state = 0;
5310 // piggyback on post-processing to calculate exp->last_event
5311 const hrtime_t _exp_start_time = getStartTime (); // wall clock time
5312 hrtime_t exp_duration = getLastEvent () == ZERO_TIME ? 0
5313 : getLastEvent () - _exp_start_time; // zero-based
5315 int missed_fi = 0;
5316 int total_fi = 0;
5318 for (long i = 0; i < size; i++)
5320 if (i == nextReport)
5322 int percent = (int) (i * 100 / size);
5323 if (percent > progress_bar_percent)
5325 progress_bar_percent += 10;
5326 theApplication->set_progress (percent, progress_bar_msg);
5328 nextReport += deltaReport;
5331 uint32_t thrid = (uint32_t) dataThrId->fetchInt (i);
5332 hrtime_t tstamp = (hrtime_t) dataTStamp->fetchLong (i);
5334 // piggyback on post-processing to calculate exp->last_event
5336 hrtime_t relative_timestamp = tstamp - _exp_start_time;
5337 if (exp_duration < relative_timestamp)
5338 exp_duration = relative_timestamp;
5340 uint64_t frinfo = (uint64_t) dataFrinfo->fetchLong (i);
5342 RawFramePacket *rfp = NULL;
5343 if (frinfo)
5345 // CacheMap does not work with NULL key
5346 if (frameInfoCache != NULL)
5347 rfp = (RawFramePacket *) frameInfoCache->get (frinfo);
5349 if (rfp == 0)
5351 rfp = find_frame_packet (frinfo);
5352 if (rfp != 0)
5354 if (frameInfoCache != NULL)
5355 frameInfoCache->put (frinfo, (uint64_t) rfp);
5357 else
5358 missed_fi++;
5359 total_fi++;
5362 // Process OpenMP properties
5363 if (ompavail)
5365 fp->omp_state = rfp ? rfp->omp_state : 0;
5366 dDscr->setValue (PROP_OMPSTATE, i, fp->omp_state);
5368 fp->omp_cprid = mapPRid->get (thrid, tstamp, mapPRid->REL_EQLE);
5369 void *omp_preg = mapPReg->get (thrid, tstamp, mapPReg->REL_EQLE);
5370 if (!omp_preg)
5372 char *idxname = NTXT ("OMP_preg");
5373 int idxtype = dbeSession->findIndexSpaceByName (idxname);
5374 if (idxtype != -1)
5376 Histable *preg0 = dbeSession->findObjectById (Histable::INDEXOBJ, idxtype, (int64_t) 0);
5377 if (preg0)
5379 Vector<Histable*> pregs;
5380 pregs.append (preg0);
5381 omp_preg = cstack->add_stack (&pregs);
5382 mapPReg->put (thrid, tstamp, omp_preg);
5386 dDscr->setObjValue (PROP_CPRID, i, omp_preg); //profiling PROP_CPRID
5387 void *omp_task = mapTask->get (thrid, tstamp, mapTask->REL_EQLE);
5388 if (!omp_task)
5390 char *idxname = NTXT ("OMP_task");
5391 int idxtype = dbeSession->findIndexSpaceByName (idxname);
5392 if (idxtype != -1)
5394 Histable *task0 = dbeSession->findObjectById (Histable::INDEXOBJ, idxtype, (int64_t) 0);
5395 if (task0)
5397 Vector<Histable*> tasks;
5398 tasks.append (task0);
5399 omp_task = cstack->add_stack (&tasks);
5400 mapTask->put (thrid, tstamp, omp_task);
5404 dDscr->setObjValue (PROP_TSKID, i, omp_task); //profiling PROP_TSKID
5406 else
5408 fp->omp_state = 0;
5409 fp->omp_cprid = 0;
5412 // Construct the native stack
5413 fp->stack->reset ();
5414 Vaddr leafpc = dDscr->getULongValue (PROP_LEAFPC, i);
5415 if (leafpc)
5416 fp->stack->append (leafpc);
5417 UIDnode *node = rfp ? rfp->uidn : NULL;
5418 while (node)
5420 if (node->next == node)
5421 // this node contains link_uid
5422 node = find_uid_node (node->uid);
5423 else
5425 fp->stack->append (node->val);
5426 node = node->next;
5429 fp->truncated = 0;
5430 int last = fp->stack->size () - 1;
5431 if (last >= 0)
5433 switch (fp->stack->fetch (last))
5435 case SP_TRUNC_STACK_MARKER:
5436 fp->truncated = (Vaddr) SP_TRUNC_STACK_MARKER;
5437 fp->stack->remove (last);
5438 break;
5439 case SP_FAILED_UNWIND_MARKER:
5440 fp->truncated = (Vaddr) SP_FAILED_UNWIND_MARKER;
5441 fp->stack->remove (last);
5442 break;
5446 // Construct the Java stack
5447 fp->jstack->reset ();
5448 node = rfp ? rfp->uidj : NULL;
5449 while (node)
5451 if (node->next == node)
5453 // this node contains link_uid
5454 UIDnode *n = NULL;
5455 if (node->uid)
5457 // CacheMap does not work with NULL key
5458 if (nodeCache != NULL)
5459 n = (UIDnode *) nodeCache->get (node->uid);
5461 if (n == NULL)
5463 n = find_uid_node (node->uid);
5464 if (n != NULL)
5466 if (nodeCache != NULL)
5467 nodeCache->put (node->uid, (uint64_t) n);
5470 node = n;
5472 else
5474 fp->jstack->append (node->val);
5475 node = node->next;
5478 fp->jtruncated = false;
5479 last = fp->jstack->size () - 1;
5480 if (last >= 1 && fp->jstack->fetch (last) == SP_TRUNC_STACK_MARKER)
5482 fp->jtruncated = true;
5483 fp->jstack->remove (last);
5484 fp->jstack->remove (last - 1);
5487 // Construct the OpenMP stack
5488 if (ompavail)
5490 fp->ompstack->reset ();
5491 if (rfp && rfp->omp_uid)
5493 if (leafpc)
5494 fp->ompstack->append (leafpc);
5495 node = rfp->omp_uid;
5496 while (node)
5498 if (node->next == node)
5499 // this node contains link_uid
5500 node = find_uid_node (node->uid);
5501 else
5503 fp->ompstack->append (node->val);
5504 node = node->next;
5507 fp->omptruncated = false;
5508 last = fp->ompstack->size () - 1;
5509 if (last >= 0)
5511 switch (fp->ompstack->fetch (last))
5513 case SP_TRUNC_STACK_MARKER:
5514 fp->omptruncated = (Vaddr) SP_TRUNC_STACK_MARKER;
5515 fp->ompstack->remove (last);
5516 break;
5517 case SP_FAILED_UNWIND_MARKER:
5518 fp->omptruncated = (Vaddr) SP_FAILED_UNWIND_MARKER;
5519 fp->ompstack->remove (last);
5520 break;
5525 cstack->add_stack (dDscr, i, fp, NULL);
5528 // piggyback on post-processing to calculate exp->last_event
5530 hrtime_t exp_end_time = _exp_start_time + exp_duration;
5531 update_last_event (exp_end_time);
5534 if (missed_fi > 0)
5536 StringBuilder sb;
5537 sb.sprintf (
5538 GTXT ("*** Warning: %d frameinfo packets are missing from total of %d when resolving %s."),
5539 missed_fi, total_fi, dDscr->getName ());
5540 warnq->append (new Emsg (CMSG_WARN, sb));
5543 // threadPool->wait_group();
5544 // delete threadPool;
5545 theApplication->set_progress (0, NTXT (""));
5546 free (progress_bar_msg);
5547 if (!resolve_frinfo_pipelined && fp != NULL)
5549 delete fp->ompstack;
5550 delete fp->jstack;
5551 delete fp->stack;
5552 delete fp;
5554 delete frameInfoCache;
5555 frameInfoCache = NULL;
5556 delete nodeCache;
5557 nodeCache = NULL;
5560 void
5561 Experiment::post_process ()
5563 // update non_paused_time after final update to "last_event"
5564 if (resume_ts != MAX_TIME && last_event)
5566 hrtime_t ts = last_event - exp_start_time;
5567 hrtime_t delta = ts - resume_ts;
5568 non_paused_time += delta;
5569 resume_ts = MAX_TIME; // collection is paused
5572 // GC: prune events outside of experiment duration, calculate GC duration, update indices
5573 int index;
5574 GCEvent * gcevent;
5575 gc_duration = ZERO_TIME;
5576 if (gcevents != NULL)
5578 // delete events that finish before exp_start_time or start after last_event
5579 for (int ii = 0; ii < gcevents->size ();)
5581 gcevent = gcevents->fetch (ii);
5582 if (gcevent->end - exp_start_time < 0
5583 || last_event - gcevent->start < 0)
5584 delete gcevents->remove (ii);
5585 else
5586 ii++;
5589 Vec_loop (GCEvent*, gcevents, index, gcevent)
5591 gcevent->id = index + 1; // renumber to account for any deleted events
5592 if (gcevent->start - exp_start_time < 0 || gcevent->start == ZERO_TIME)
5593 // truncate events that start before experiment start
5594 gcevent->start = exp_start_time;
5595 if (last_event - gcevent->end < 0)
5596 // truncate events that end after experiment end
5597 gcevent->end = last_event;
5598 gc_duration += gcevent->end - gcevent->start;
5602 Experiment::Exp_status
5603 Experiment::find_expdir (char *path)
5605 // This function checks that the experiment directory
5606 // is of the proper form, and accessible
5607 dbe_stat_t sbuf;
5609 // Save the name
5610 expt_name = dbe_strdup (path);
5612 // Check that the name ends in .er
5613 size_t i = strlen (path);
5614 if (i > 0 && path[i - 1] == '/')
5615 path[--i] = '\0';
5617 if (i < 4 || strcmp (&path[i - 3], NTXT (".er")) != 0)
5619 Emsg *m = new Emsg (CMSG_FATAL,
5620 GTXT ("*** Error: not a valid experiment name"));
5621 errorq->append (m);
5622 status = FAILURE;
5623 return FAILURE;
5626 // Check if new directory structure (i.e., no pointer file)
5627 if (dbe_stat (path, &sbuf))
5629 Emsg *m = new Emsg (CMSG_FATAL, GTXT ("*** Error: experiment not found"));
5630 errorq->append (m);
5631 status = FAILURE;
5632 return FAILURE;
5634 if (S_ISDIR (sbuf.st_mode) == 0)
5636 // ignore pointer-file experiments
5637 Emsg *m = new Emsg (CMSG_FATAL,
5638 GTXT ("*** Error: experiment was recorded with an earlier version, and can not be read"));
5639 errorq->append (m);
5640 obsolete = 1;
5641 status = FAILURE;
5642 return FAILURE;
5644 return SUCCESS;
5647 void
5648 Experiment::purge ()
5650 // This routine will purge all of the caches of releasable storage.
5651 for (int i = 0; i < dataDscrs->size (); ++i)
5653 DataDescriptor *dataDscr = dataDscrs->fetch (i);
5654 if (dataDscr == NULL)
5655 continue;
5656 dataDscr->reset ();
5658 delete cstack;
5659 delete cstackShowHide;
5660 cstack = CallStack::getInstance (this);
5661 cstackShowHide = CallStack::getInstance (this);
5664 void
5665 Experiment::resetShowHideStack ()
5667 delete cstackShowHide;
5668 cstackShowHide = CallStack::getInstance (this);
5671 #define GET_INT_VAL(v, s, len) \
5672 for (v = len = 0; isdigit(*s); s++, len++) { v = v * 10 + (*s -'0'); }
5674 static int
5675 dir_name_cmp (const void *a, const void *b)
5677 char *s1 = *((char **) a);
5678 char *s2 = *((char **) b);
5679 while (*s1)
5681 if (isdigit (*s1) && isdigit (*s2))
5683 int v1, v2, len1, len2;
5684 GET_INT_VAL (v1, s1, len1);
5685 GET_INT_VAL (v2, s2, len2);
5686 if (v1 != v2)
5687 return v1 - v2;
5688 if (len1 != len2)
5689 return len2 - len1;
5690 continue;
5692 if (*s1 != *s2)
5693 break;
5694 s1++;
5695 s2++;
5697 return *s1 - *s2;
5700 Vector<char*> *
5701 Experiment::get_descendants_names ()
5703 char *dir_name = get_expt_name ();
5704 if (dir_name == NULL)
5705 return NULL;
5706 DIR *exp_dir = opendir (dir_name);
5707 if (exp_dir == NULL)
5708 return NULL;
5709 Vector<char*> *exp_names = new Vector<char*>();
5710 for (struct dirent *entry = readdir (exp_dir); entry;
5711 entry = readdir (exp_dir))
5713 if (entry->d_name[0] == '_' || strncmp (entry->d_name, "M_r", 3) == 0)
5715 char *dpath = dbe_sprintf (NTXT ("%s/%s"), dir_name, entry->d_name);
5716 dbe_stat_t sbuf;
5717 if (dbe_stat (dpath, &sbuf) == 0 && S_ISDIR (sbuf.st_mode))
5718 exp_names->append (dpath);
5719 else
5720 free (dpath);
5723 closedir (exp_dir);
5724 if (exp_names->size () == 0)
5726 delete exp_names;
5727 return NULL;
5729 exp_names->sort (dir_name_cmp);
5730 return exp_names;
5733 bool
5734 Experiment::create_dir (char *dname)
5736 if (mkdir (dname, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0)
5738 return true;
5740 dbe_stat_t sbuf;
5741 if (dbe_stat (dname, &sbuf) != 0 || S_ISDIR (sbuf.st_mode) == 0)
5743 char *buf = dbe_sprintf (GTXT ("Unable to create directory `%s'\n"),
5744 dname);
5745 errorq->append (new Emsg (CMSG_ERROR, buf));
5746 free (buf);
5747 return false;
5749 return true;
5752 char *
5753 Experiment::get_arch_name ()
5755 if (arch_name == NULL)
5757 // Determine the master experiment directory.
5758 // omazur: should do it in a less hacky way. XXXX
5759 char *ptr = strstr_r (expt_name, DESCENDANT_EXPT_KEY);
5760 ptr = ptr ? ptr + 3 : expt_name + strlen (expt_name);
5761 arch_name = dbe_sprintf (NTXT ("%.*s/%s"), (int) (ptr - expt_name),
5762 expt_name, SP_ARCHIVES_DIR);
5764 return arch_name;
5767 char *
5768 Experiment::get_fndr_arch_name ()
5770 if (fndr_arch_name == NULL)
5771 // Determine the founder experiment directory.
5772 fndr_arch_name = dbe_strdup (get_arch_name ());
5773 return fndr_arch_name;
5776 enum
5778 HASH_NAME_LEN = 11 // (64 / 6 + 1) = 11
5781 static char *
5782 get_hash_string (char buf[HASH_NAME_LEN + 1], uint64_t hash)
5784 static const char *har =
5785 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
5786 for (int i = 0; i < HASH_NAME_LEN; i++)
5788 buf[i] = har[hash & 0x3f];
5789 hash = hash >> 6;
5791 buf[HASH_NAME_LEN] = 0;
5792 return buf;
5795 char *
5796 Experiment::getNameInArchive (const char *fname, bool archiveFile)
5798 char *aname = get_archived_name (fname, archiveFile);
5799 char *ret = dbe_sprintf (NTXT ("%s/%s"), get_arch_name (), aname);
5800 free (aname);
5801 return ret;
5804 #define MAX_ARCHIVE_FILENAME_LEN (256 - HASH_NAME_LEN - 2)
5806 char *
5807 Experiment::get_archived_name (const char *fname, bool archiveFile)
5809 char *bname = get_basename (fname);
5811 // dirname_hash:
5812 char dirnameHash[HASH_NAME_LEN + 1];
5813 // Treat "a.out" and "./a.out" equally
5814 uint64_t hash = bname != fname ? crc64 (fname, bname - fname)
5815 : crc64 (NTXT ("./"), 2);
5816 get_hash_string (dirnameHash, hash);
5818 char *ret;
5819 long bname_len = dbe_sstrlen (bname);
5820 if (bname_len > MAX_ARCHIVE_FILENAME_LEN)
5822 char basenameHash[HASH_NAME_LEN + 1];
5823 hash = crc64 (bname, bname_len);
5824 get_hash_string (basenameHash, hash);
5825 ret = dbe_sprintf ("%.*s%c%s_%s",
5826 MAX_ARCHIVE_FILENAME_LEN - HASH_NAME_LEN - 1,
5827 bname, archiveFile ? '.' : '_',
5828 dirnameHash, basenameHash);
5830 else
5831 ret = dbe_sprintf ("%s%c%s", bname, archiveFile ? '.' : '_', dirnameHash);
5832 return ret;
5835 char *
5836 Experiment::checkFileInArchive (const char *fname, bool archiveFile)
5838 if (archiveMap)
5840 char *aname = get_archived_name (fname, archiveFile);
5841 DbeFile *df = archiveMap->get (aname);
5842 free (aname);
5843 if (df)
5844 return xstrdup (df->get_location ());
5845 return NULL;
5847 if (founder_exp)
5848 return founder_exp->checkFileInArchive (fname, archiveFile);
5849 return NULL;
5853 // Comparing SegMem
5855 static int
5856 SegMemCmp (const void *a, const void *b)
5858 SegMem *item1 = *((SegMem **) a);
5859 SegMem *item2 = *((SegMem **) b);
5860 return item1->unload_time > item2->unload_time ? 1 :
5861 item1->unload_time == item2->unload_time ? 0 : -1;
5864 SegMem*
5865 Experiment::update_ts_in_maps (Vaddr addr, hrtime_t ts)
5867 Vector<void *> *segMems = maps->values ();
5868 if (segMems && !segMems->is_sorted ())
5870 Dprintf (DEBUG_MAPS, NTXT ("update_ts_in_maps: segMems.size=%lld\n"), (long long) segMems->size ());
5871 segMems->sort (SegMemCmp);
5873 for (int i = 0, sz = segMems ? segMems->size () : 0; i < sz; i++)
5875 SegMem *sm = (SegMem *) segMems->fetch (i);
5876 if (ts < sm->unload_time)
5878 for (; i < sz; i++)
5880 sm = (SegMem *) segMems->fetch (i);
5881 if ((addr >= sm->base) && (addr < sm->base + sm->size))
5883 Dprintf (DEBUG_MAPS,
5884 "update_ts_in_maps: old:%u.%09u -> %u.%09u addr=0x%08llx size=%lld\n",
5885 (unsigned) (sm->load_time / NANOSEC),
5886 (unsigned) (sm->load_time % NANOSEC),
5887 (unsigned) (ts / NANOSEC), (unsigned) (ts % NANOSEC),
5888 (unsigned long long) sm->base, (long long) sm->size);
5889 maps->remove (sm->base, sm->load_time);
5890 sm->load_time = ts;
5891 maps->insert (sm->base, ts, sm);
5892 return sm;
5897 Dprintf (DEBUG_MAPS, "update_ts_in_maps: NOT FOUND %u.%09u addr=0x%08llx\n",
5898 (unsigned) (ts / NANOSEC), (unsigned) (ts % NANOSEC),
5899 (unsigned long long) addr);
5900 return NULL;
5903 DbeInstr*
5904 Experiment::map_Vaddr_to_PC (Vaddr addr, hrtime_t ts)
5906 // Look up in the hash table first
5907 int hash = (((int) addr) >> 8) & (HTableSize - 1);
5908 SegMem *si = smemHTable[hash];
5909 if (si == NULL || addr < si->base || addr >= si->base + si->size
5910 || ts < si->load_time || ts >= si->unload_time)
5912 // Not in the hash table
5913 si = (SegMem*) maps->locate (addr, ts);
5914 if (si == NULL || addr < si->base || addr >= si->base + si->size
5915 || ts < si->load_time || ts >= si->unload_time)
5917 si = update_ts_in_maps (addr, ts);
5918 if (si == NULL)
5919 return dbeSession->get_Unknown_Function ()->find_dbeinstr (PCInvlFlag, addr);
5921 smemHTable[hash] = si;
5924 // Calculate the file offset of 'addr'
5925 uint64_t f_offset = si->get_file_offset () + (addr - si->base);
5927 DbeInstr *instr;
5928 if (si->obj->get_type () == Histable::LOADOBJECT)
5930 LoadObject *lo = (LoadObject*) si->obj;
5931 lo->sync_read_stabs ();
5932 instr = lo->find_dbeinstr (f_offset);
5934 else
5936 int hash2 = ((((int) addr) & 0xFFFC00) | (((int) f_offset) >> 2))
5937 & (HTableSize - 1);
5938 instr = instHTable[hash2];
5939 if (instr == NULL || instr->func != si->obj || instr->addr != f_offset)
5941 // Not in the hash table
5942 Function *fp = (Function *) si->obj;
5943 instr = fp->find_dbeinstr (0, f_offset);
5944 instHTable[hash2] = instr;
5947 if (!instr->func->isUsed)
5949 instr->func->isUsed = true;
5950 instr->func->module->isUsed = true;
5951 instr->func->module->loadobject->isUsed = true;
5953 return instr;
5956 Sample *
5957 Experiment::map_event_to_Sample (hrtime_t ts)
5959 Sample *sample;
5960 int index;
5962 // Check if the last used sample is the right one,
5963 // if not then find it.
5964 if (sample_last_used && ts >= sample_last_used->start_time
5965 && ts <= sample_last_used->end_time)
5966 return sample_last_used;
5968 Vec_loop (Sample*, samples, index, sample)
5970 if ((ts >= sample->start_time) &&
5971 (ts <= sample->end_time))
5973 sample_last_used = sample;
5974 return sample;
5977 return (Sample*) NULL;
5980 GCEvent *
5981 Experiment::map_event_to_GCEvent (hrtime_t ts)
5983 GCEvent *gcevent;
5984 int index;
5986 // Check if the last used sample is the right one,
5987 // if not then find it.
5988 if (gcevent_last_used && ts >= gcevent_last_used->start
5989 && ts <= gcevent_last_used->end)
5990 return gcevent_last_used;
5991 Vec_loop (GCEvent*, gcevents, index, gcevent)
5993 if ((ts >= gcevent->start) &&
5994 (ts <= gcevent->end))
5996 gcevent_last_used = gcevent;
5997 return gcevent;
6000 return (GCEvent*) NULL;
6003 DbeInstr*
6004 Experiment::map_jmid_to_PC (Vaddr mid, int bci, hrtime_t ts)
6006 if (mid == 0 || jmaps == NULL)
6007 // special case: no Java stack was recorded, bci - error code
6008 return dbeSession->get_JUnknown_Function ()->find_dbeinstr (0, bci);
6010 JMethod *jmthd = jmidHTable->get (mid);
6011 if (jmthd == NULL)
6013 jmthd = (JMethod *) jmaps->locate_exact_match (mid, ts);
6014 if (jmthd)
6015 jmidHTable->put (mid, jmthd);
6017 if (jmthd == NULL || jmthd->get_type () != Histable::FUNCTION)
6018 return dbeSession->get_JUnknown_Function ()->find_dbeinstr (0, (uint64_t) mid);
6019 return jmthd->find_dbeinstr (0, bci);
6022 Emsg *
6023 Experiment::fetch_comments ()
6025 return commentq->fetch ();
6028 Emsg *
6029 Experiment::fetch_runlogq ()
6031 return runlogq->fetch ();
6034 Emsg *
6035 Experiment::fetch_errors ()
6037 return errorq->fetch ();
6040 Emsg *
6041 Experiment::fetch_warnings ()
6043 return warnq->fetch ();
6046 Emsg *
6047 Experiment::fetch_notes ()
6049 return notesq->fetch ();
6052 Emsg *
6053 Experiment::fetch_ifreq ()
6055 return ifreqq->fetch ();
6058 Emsg *
6059 Experiment::fetch_pprocq ()
6061 return pprocq->fetch ();
6065 Experiment::read_dyntext_file ()
6067 dyntext_name = dbe_sprintf ("%s/%s", expt_name, SP_DYNTEXT_FILE);
6068 Data_window *dwin = new Data_window (dyntext_name);
6069 if (dwin->not_opened ())
6071 delete dwin;
6072 return 1;
6074 dwin->need_swap_endian = need_swap_endian;
6076 Function *fp = NULL;
6077 char *progress_msg = NULL; // Message for the progress bar
6078 for (int64_t offset = 0;;)
6080 DT_common *cpckt = (DT_common *) dwin->bind (offset, sizeof (DT_common));
6081 if (cpckt == NULL)
6082 break;
6083 size_t cpcktsize = dwin->decode (cpckt->size);
6084 cpckt = (DT_common *) dwin->bind (offset, cpcktsize);
6085 if (cpckt == NULL)
6086 break;
6087 switch (dwin->decode (cpckt->type))
6089 case DT_HEADER:
6091 DT_header *hdr = (DT_header*) cpckt;
6092 hrtime_t ts = dwin->decode (hdr->time) + exp_start_time;
6093 SegMem *si = (SegMem*) maps->locate (dwin->decode (hdr->vaddr), ts);
6094 fp = si ? (Function *) si->obj : NULL;
6095 if (fp && (fp->get_type () != Histable::FUNCTION
6096 || !(fp->flags & FUNC_FLAG_DYNAMIC)))
6097 fp = NULL;
6098 break;
6100 case DT_CODE:
6101 if (fp)
6103 fp->img_fname = dyntext_name;
6104 fp->img_offset = offset + sizeof (DT_common);
6105 if ((platform != Intel) && (platform != Amd64))
6106 { //ARCH(SPARC)
6107 // Find out 'save' instruction address for SPARC
6108 char *ptr = ((char*) cpckt) + sizeof (DT_common);
6109 size_t img_size = cpcktsize - sizeof (DT_common);
6110 for (size_t i = 0; i < img_size; i += 4)
6111 if (ptr[i] == (char) 0x9d && ptr[i + 1] == (char) 0xe3)
6113 fp->save_addr = i;
6114 break;
6118 break;
6119 case DT_SRCFILE:
6120 if (fp)
6122 char *srcname = dbe_strndup (((char*) cpckt) + sizeof (DT_common),
6123 cpcktsize - sizeof (DT_common));
6124 LoadObject *ds = fp->module ? fp->module->loadobject : NULL;
6125 assert (ds != NULL);
6126 Module *mod = dbeSession->createModule (ds, NULL);
6127 mod->set_file_name (srcname);
6129 if (fp->module)
6131 // It's most likely (unknown). Remove fp from it.
6132 long idx = fp->module->functions->find (fp);
6133 if (idx >= 0)
6134 fp->module->functions->remove (idx);
6136 fp->module = mod;
6137 mod->functions->append (fp);
6139 break;
6140 case DT_LTABLE:
6141 if (fp)
6143 DT_lineno *ltab = (DT_lineno*) ((char*) cpckt + sizeof (DT_common));
6144 size_t sz = (cpcktsize - sizeof (DT_common)) / sizeof (DT_lineno);
6145 if (sz <= 0)
6146 break;
6147 // Take care of the progress bar
6148 static int percent = 0;
6149 static long deltaReport = sz / 100; // 1000;
6150 static long nextReport = 0;
6151 static long progress_count = 0;
6152 fp->pushSrcFile (fp->getDefSrc (), 0);
6153 for (size_t i = 0; i < sz; i++)
6155 int lineno = dwin->decode (ltab[i].lineno);
6156 if (fp->usrfunc != NULL)
6158 // Update progress bar
6159 if (dbeSession->is_interactive ())
6161 if (progress_count == nextReport)
6163 if (percent < 99)
6165 percent++;
6166 if (NULL == progress_msg)
6168 progress_msg = dbe_sprintf (GTXT ("Processing Dynamic Text: %s"),
6169 get_basename (expt_name));
6171 theApplication->set_progress (percent, progress_msg);
6172 nextReport += deltaReport;
6175 progress_count++;
6177 DbeLine *dbeline = fp->usrfunc->mapPCtoLine (lineno, NULL);
6178 lineno = dbeline != NULL ? dbeline->lineno : -1;
6180 fp->add_PC_info (dwin->decode (ltab[i].offset), lineno);
6182 fp->popSrcFile ();
6184 break;
6185 default:
6186 // skip unknown records
6187 break;
6189 offset += cpcktsize;
6191 free (progress_msg);
6192 delete dwin;
6193 return 0;
6196 uint32_t
6197 Experiment::mapTagValue (Prop_type prop, uint64_t value)
6199 Vector<Histable*> *objs = tagObjs->fetch (prop);
6200 int lt = 0;
6201 int rt = objs->size () - 1;
6202 while (lt <= rt)
6204 int md = (lt + rt) / 2;
6205 Other *obj = (Other*) objs->fetch (md);
6206 if (obj->value64 < value)
6207 lt = md + 1;
6208 else if (obj->value64 > value)
6209 rt = md - 1;
6210 else
6211 return obj->tag;
6214 uint32_t tag;
6215 if (sparse_threads && (prop == PROP_THRID || prop == PROP_LWPID))
6216 tag = objs->size () + 1; // "+ 1" related to 7038295
6217 else
6218 tag = (int) value; // truncation; See 6788767
6220 Other *obj = new Other ();
6221 obj->value64 = value;
6222 obj->tag = tag;
6223 if (lt == objs->size ())
6224 objs->append (obj);
6225 else
6226 objs->insert (lt, obj);
6228 // Update min and max tags
6229 if (prop == PROP_LWPID)
6231 if ((uint64_t) tag < min_lwp)
6232 min_lwp = (uint64_t) tag;
6233 if ((uint64_t) tag > max_lwp)
6234 max_lwp = (uint64_t) tag;
6235 lwp_cnt++;
6237 else if (prop == PROP_THRID)
6239 if ((uint64_t) tag < min_thread)
6240 min_thread = (uint64_t) tag;
6241 if ((uint64_t) tag > max_thread)
6242 max_thread = (uint64_t) tag;
6243 thread_cnt++;
6245 else if (prop == PROP_CPUID)
6247 // On Solaris 8, we don't get CPU id -- don't change
6248 if (value != (uint64_t) - 1)
6249 {//YXXX is this related only to solaris 8?
6250 if ((uint64_t) tag < min_cpu)
6251 min_cpu = (uint64_t) tag;
6252 if ((uint64_t) tag > max_cpu)
6253 max_cpu = (uint64_t) tag;
6255 cpu_cnt++;
6257 return obj->tag;
6260 Vector<Histable*> *
6261 Experiment::getTagObjs (Prop_type prop)
6263 return tagObjs->fetch (prop);
6266 Histable *
6267 Experiment::getTagObj (Prop_type prop, uint32_t tag)
6269 Vector<Histable*> *objs = tagObjs->fetch (prop);
6270 if (objs == NULL)
6271 return NULL;
6272 for (int i = 0; i < objs->size (); i++)
6274 Other *obj = (Other*) objs->fetch (i);
6275 if (obj->tag == tag)
6276 return obj;
6278 return NULL;
6281 JThread *
6282 Experiment::map_pckt_to_Jthread (uint32_t tid, hrtime_t tstamp)
6284 if (!has_java)
6285 return JTHREAD_DEFAULT;
6286 int lt = 0;
6287 int rt = jthreads_idx->size () - 1;
6288 while (lt <= rt)
6290 int md = (lt + rt) / 2;
6291 JThread *jthread = jthreads_idx->fetch (md);
6292 if (jthread->tid < tid)
6293 lt = md + 1;
6294 else if (jthread->tid > tid)
6295 rt = md - 1;
6296 else
6298 for (; jthread; jthread = jthread->next)
6299 if (tstamp >= jthread->start && tstamp < jthread->end)
6300 return jthread;
6301 break;
6305 return JTHREAD_NONE;
6308 JThread*
6309 Experiment::get_jthread (uint32_t tid)
6311 if (!has_java)
6312 return JTHREAD_DEFAULT;
6313 int lt = 0;
6314 int rt = jthreads_idx->size () - 1;
6315 while (lt <= rt)
6317 int md = (lt + rt) / 2;
6318 JThread *jthread = jthreads_idx->fetch (md);
6319 if (jthread->tid < tid)
6320 lt = md + 1;
6321 else if (jthread->tid > tid)
6322 rt = md - 1;
6323 else
6325 JThread *jthread_first = jthread;
6326 while ((jthread = jthread->next) != NULL)
6327 if (!jthread->is_system () &&
6328 jthread->jthr_id < jthread_first->jthr_id)
6329 jthread_first = jthread;
6330 return jthread_first;
6334 return JTHREAD_NONE;
6337 // SS12 experiment
6338 DataDescriptor *
6339 Experiment::newDataDescriptor (int data_id, int flags,
6340 DataDescriptor *master_dDscr)
6342 DataDescriptor *dataDscr = NULL;
6343 if (data_id >= 0 && data_id < dataDscrs->size ())
6345 dataDscr = dataDscrs->fetch (data_id);
6346 if (dataDscr != NULL)
6347 return dataDscr;
6350 assert (data_id >= 0 && data_id < DATA_LAST);
6351 const char *nm = get_prof_data_type_name (data_id);
6352 const char *uname = get_prof_data_type_uname (data_id);
6354 if (master_dDscr)
6355 dataDscr = new DataDescriptor (data_id, nm, uname, master_dDscr);
6356 else
6357 dataDscr = new DataDescriptor (data_id, nm, uname, flags);
6358 dataDscrs->store (data_id, dataDscr);
6359 return dataDscr;
6362 Vector<DataDescriptor*> *
6363 Experiment::getDataDescriptors ()
6365 Vector<DataDescriptor*> *result = new Vector<DataDescriptor*>;
6366 for (int i = 0; i < dataDscrs->size (); ++i)
6368 DataDescriptor *dd;
6369 dd = get_raw_events (i); // force data fetch
6370 if (dd != NULL)
6371 result->append (dd);
6373 return result;
6376 DataDescriptor *
6377 Experiment::getDataDescriptor (int data_id)
6379 if (data_id < 0 || data_id >= dataDscrs->size ())
6380 return NULL;
6381 return dataDscrs->fetch (data_id);
6384 PacketDescriptor *
6385 Experiment::newPacketDescriptor (int kind, DataDescriptor *dDscr)
6387 PacketDescriptor *pDscr = new PacketDescriptor (dDscr);
6388 pcktDscrs->store (kind, pDscr);
6389 return pDscr;
6392 PacketDescriptor *
6393 Experiment::getPacketDescriptor (int kind)
6395 if (kind < 0 || kind >= pcktDscrs->size ())
6396 return NULL;
6397 return pcktDscrs->fetch (kind);
6400 void
6401 Experiment::set_clock (int clk)
6403 if (clk > 0)
6405 if (maxclock < clk)
6407 maxclock = clk;
6408 clock = maxclock;
6410 if (minclock == 0 || minclock > clk)
6411 minclock = clk;
6415 bool
6416 JThread::is_system ()
6418 if (group_name == NULL)
6419 return false;
6420 return strcmp (group_name, NTXT ("system")) == 0;
6423 void
6424 Experiment::dump_stacks (FILE *outfile)
6426 cstack->print (outfile);
6429 void
6430 Experiment::dump_map (FILE *outfile)
6432 int index;
6433 SegMem *s;
6434 fprintf (outfile, GTXT ("Experiment %s\n"), get_expt_name ());
6435 fprintf (outfile, GTXT ("Address Size (hex) Load time Unload time Checksum Name\n"));
6436 Vec_loop (SegMem*, seg_items, index, s)
6438 timestruc_t load;
6439 timestruc_t unload;
6440 hr2timestruc (&load, (s->load_time - exp_start_time));
6441 if (load.tv_nsec < 0)
6443 load.tv_sec--;
6444 load.tv_nsec += NANOSEC;
6446 if (s->unload_time == MAX_TIME)
6448 unload.tv_sec = 0;
6449 unload.tv_nsec = 0;
6451 else
6452 hr2timestruc (&unload, (s->unload_time - exp_start_time));
6453 if (load.tv_nsec < 0)
6455 load.tv_sec--;
6456 load.tv_nsec += NANOSEC;
6458 fprintf (outfile,
6459 "0x%08llx %8lld (0x%08llx) %5lld.%09lld %5lld.%09lld \"%s\"\n",
6460 (long long) s->base, (long long) s->size, (long long) s->size,
6461 (long long) load.tv_sec, (long long) load.tv_nsec,
6462 (long long) unload.tv_sec, (long long) unload.tv_nsec,
6463 s->obj->get_name ());
6465 fprintf (outfile, NTXT ("\n"));
6469 * Copy file to archive
6470 * @param name
6471 * @param aname
6472 * @param hide_msg
6473 * @return 0 - success, 1 - error
6476 Experiment::copy_file_to_archive (const char *name, const char *aname, int hide_msg)
6478 errno = 0;
6479 int fd_w = ::open64 (aname, O_WRONLY | O_CREAT | O_EXCL, 0644);
6480 if (fd_w == -1)
6482 if (errno == EEXIST)
6483 return 0;
6484 fprintf (stderr, GTXT ("gprofng-archive: unable to copy `%s': %s\n"),
6485 name, STR (strerror (errno)));
6486 return 1;
6489 if (dbe_stat_file (name, NULL) != 0)
6491 fprintf (stderr, GTXT ("gprofng-archive: cannot access file `%s': %s\n"),
6492 name, STR (strerror (errno)));
6493 close (fd_w);
6494 return 1;
6497 int fd_r = ::open64 (name, O_RDONLY);
6498 if (fd_r == -1)
6500 fprintf (stderr, GTXT ("gprofng-archive: unable to open `%s': %s\n"),
6501 name, strerror (errno));
6502 close (fd_w);
6503 unlink (aname);
6504 return 1;
6507 if (!hide_msg)
6508 fprintf (stderr, GTXT ("Copying `%s' to `%s'\n"), name, aname);
6509 bool do_unlink = false;
6510 for (;;)
6512 unsigned char buf[65536];
6513 int n, n1;
6514 n = (int) read (fd_r, (void *) buf, sizeof (buf));
6515 if (n <= 0)
6516 break;
6517 n1 = (int) write (fd_w, buf, n);
6518 if (n != n1)
6520 fprintf (stderr, GTXT ("gprofng-archive: unable to write %d bytes to `%s': %s\n"),
6521 n, aname, STR (strerror (errno)));
6522 do_unlink = true;
6523 break;
6526 close (fd_w);
6528 dbe_stat_t s_buf;
6529 if (fstat64 (fd_r, &s_buf) == 0)
6531 struct utimbuf u_buf;
6532 u_buf.actime = s_buf.st_atime;
6533 u_buf.modtime = s_buf.st_mtime;
6534 utime (aname, &u_buf);
6536 close (fd_r);
6537 if (do_unlink)
6539 if (!hide_msg)
6540 fprintf (stderr, GTXT ("gprofng-archive: remove %s\n"), aname);
6541 unlink (aname);
6542 return 1;
6544 return 0;
6548 * Copy file to common archive
6549 * Algorithm:
6550 * Calculate checksum
6551 * Generate file name to be created in common archive
6552 * Check if it is not in common archive yet
6553 * Copy file to the common archive directory if it is not there yet
6554 * Create symbolic link: "aname" -> "caname", where "caname" is the name in common archive
6555 * @param name - original file name
6556 * @param aname - file name in experiment archive
6557 * @param common_archive - common archive directory
6558 * @return 0 - success, 1 - error
6561 Experiment::copy_file_to_common_archive (const char *name, const char *aname,
6562 int hide_msg,
6563 const char *common_archive,
6564 int relative_path)
6566 if (!name || !aname || !common_archive)
6568 if (!name)
6569 fprintf (stderr, GTXT ("gprofng-archive: Internal error: file name is NULL\n"));
6570 if (!aname)
6571 fprintf (stderr, GTXT ("gprofng-archive: Internal error: file name in archive is NULL\n"));
6572 if (!common_archive)
6573 fprintf (stderr, GTXT ("gprofng-archive: Internal error: path to common archive is NULL\n"));
6574 return 1;
6576 // Check if file is already archived
6577 if (dbe_stat (aname, NULL) == 0)
6578 return 0; // File is already archived
6579 // Generate full path to common archive directory
6580 char *cad = NULL;
6581 char *abs_aname = NULL;
6582 if ((common_archive[0] != '/') || (aname[0] != '/'))
6584 long size = pathconf (NTXT ("."), _PC_PATH_MAX);
6585 if (size < 0)
6587 fprintf (stderr, GTXT ("gprofng-archive: Fatal error: pathconf(\".\", _PC_PATH_MAX) failed\n"));
6588 return 1;
6590 char *buf = (char *) xmalloc ((size_t) size);
6591 char *ptr = getcwd (buf, (size_t) size);
6592 if (ptr == NULL)
6594 fprintf (stderr, GTXT ("gprofng-archive: Fatal error: cannot determine current directory\n"));
6595 free (buf);
6596 return 1;
6598 if (common_archive[0] != '/')
6599 cad = dbe_sprintf (NTXT ("%s/%s"), ptr, common_archive);
6600 else
6601 cad = dbe_strdup (common_archive);
6602 if (aname[0] != '/')
6603 abs_aname = dbe_sprintf (NTXT ("%s/%s"), ptr, aname);
6604 else
6605 abs_aname = dbe_strdup (aname);
6606 free (buf);
6608 else
6610 cad = dbe_strdup (common_archive);
6611 abs_aname = dbe_strdup (aname);
6613 // Calculate checksum
6614 char * errmsg = NULL;
6615 uint32_t crcval = get_cksum (name, &errmsg);
6616 if (0 == crcval)
6617 { // error
6618 free (cad);
6619 free (abs_aname);
6620 if (NULL != errmsg)
6622 fprintf (stderr, GTXT ("gprofng-archive: Fatal error: %s\n"), errmsg);
6623 free (errmsg);
6624 return 1;
6626 fprintf (stderr,
6627 GTXT ("gprofng-archive: Fatal error: get_cksum(%s) returned %d\n"),
6628 name, crcval);
6629 return 1;
6631 // Generate file name to be created in common archive
6632 char *fname = get_basename (name);
6633 char *abs_caname = dbe_sprintf (NTXT ("%s/%u_%s"), cad, crcval, fname);
6634 if (abs_caname == NULL)
6636 free (cad);
6637 free (abs_aname);
6638 fprintf (stderr,
6639 GTXT ("gprofng-archive: Fatal error: unable to allocate memory\n"));
6640 return 1;
6642 // Check if full name is not too long
6643 long len = dbe_sstrlen (abs_caname);
6644 long max = pathconf (cad, _PC_PATH_MAX);
6645 if ((max < 0) || (len <= 0))
6646 { // unknown error
6647 fprintf (stderr, GTXT ("gprofng-archive: Fatal error: pathconf(%s, _PC_PATH_MAX) failed\n"),
6648 cad);
6649 free (abs_caname);
6650 free (cad);
6651 free (abs_aname);
6652 return 1;
6654 if (len >= max)
6656 // Try to truncate the name
6657 if ((len - max) <= dbe_sstrlen (fname))
6659 // Yes, we can do it
6660 abs_caname[max - 1] = 0;
6661 if (!hide_msg)
6662 fprintf (stderr, GTXT ("gprofng-archive: file path is too long - truncated:%s\n"),
6663 abs_caname);
6666 // Check if file name is not too long
6667 char *cafname = get_basename (abs_caname);
6668 len = dbe_sstrlen (cafname);
6669 max = pathconf (cad, _PC_NAME_MAX);
6670 if ((max < 0) || (len <= 0))
6671 { // unknown error
6672 fprintf (stderr, GTXT ("gprofng-archive: Fatal error: pathconf(%s, _PC_NAME_MAX) failed\n"),
6673 cad);
6674 free (abs_caname);
6675 free (cad);
6676 free (abs_aname);
6677 return 1;
6679 if (len >= max)
6681 // Try to truncate the name
6682 if ((len - max) <= dbe_sstrlen (fname))
6684 // Yes, we can do it
6685 cafname[max - 1] = 0;
6686 if (!hide_msg)
6687 fprintf (stderr, GTXT ("gprofng-archive: file name is too long - truncated:%s\n"),
6688 abs_caname);
6691 // Copy file to the common archive directory if it is not there yet
6692 int res = 0;
6693 if (dbe_stat_file (abs_caname, NULL) != 0)
6695 // Use temporary file to avoid synchronization problems
6696 char *t = dbe_sprintf ("%s/archive_%llx", cad, (unsigned long long) gethrtime());
6697 free (cad);
6698 // Copy file to temporary file
6699 res = copy_file_to_archive (name, t, hide_msg); // hide messages
6700 if (res != 0)
6702 fprintf (stderr, GTXT ("gprofng-archive: Fatal error: cannot copy file %s to temporary file: %s\n"),
6703 name, t);
6704 unlink (t);
6705 free (t);
6706 free (abs_caname);
6707 free (abs_aname);
6708 return 1;
6710 // Set read-only permissions
6711 dbe_stat_t statbuf;
6712 if (0 == dbe_stat_file (name, &statbuf))
6714 mode_t mask = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
6715 mode_t mode = statbuf.st_mode & mask;
6716 chmod (t, mode);
6718 // Try to rename temporary file "t" to "abs_caname"
6719 // res = link(t, abs_caname); // link() fails on some f/s - use rename()
6720 res = rename (t, abs_caname);
6721 if (res != 0)
6723 if (errno != EEXIST)
6725 fprintf (stderr, GTXT ("gprofng-archive: Fatal error: rename(%s, %s) returned error: %d\n"),
6726 t, abs_caname, res);
6727 unlink (t);
6728 free (t);
6729 free (abs_caname);
6730 free (abs_aname);
6731 return 1;
6733 // File "abs_caname" is already there - continue
6735 unlink (t);
6736 free (t);
6738 else
6739 free (cad);
6740 char *lname = NULL;
6741 if (relative_path)
6743 if (common_archive[0] != '/' && aname[0] != '/')
6745 // compare one relative path to another and find common beginning
6746 char *rel_caname = dbe_sprintf ("%s/%s", common_archive, cafname);
6747 if (rel_caname == NULL)
6749 fprintf (stderr, GTXT ("gprofng-archive: Fatal error: unable to allocate memory\n"));
6750 return 1;
6752 lname = get_relative_link (rel_caname, aname);
6753 free (rel_caname);
6755 else
6757 if (abs_aname == NULL)
6759 fprintf (stderr, GTXT ("gprofng-archive: Fatal error: unable to allocate memory\n"));
6760 return 1;
6762 lname = get_relative_link (abs_caname, abs_aname);
6765 else // absolute path
6766 lname = dbe_strdup (abs_caname);
6767 free (abs_aname);
6768 if (lname == NULL)
6770 fprintf (stderr, GTXT ("gprofng-archive: Fatal error: unable to allocate memory\n"));
6771 return 1;
6773 // Create symbolic link: aname -> lname
6774 if (dbe_stat_file (abs_caname, NULL) == 0)
6776 res = symlink (lname, aname);
6777 if (res != 0)
6779 fprintf (stderr, GTXT ("gprofng-archive: Fatal error: symlink(%s, %s) returned error: %d (errno=%s)\n"),
6780 lname, aname, res, strerror (errno));
6781 free (abs_caname);
6782 free (lname);
6783 return 1;
6785 if (!hide_msg)
6786 fprintf (stderr, GTXT ("Created symbolic link %s to file in common archive: %s\n"),
6787 aname, lname);
6789 else
6791 fprintf (stderr, GTXT ("gprofng-archive: Internal error: file does not exist in common archive: %s\n"),
6792 abs_caname);
6793 res = 1;
6795 free (abs_caname);
6796 free (lname);
6797 return res;
6801 * Copy file to archive
6802 * @param name
6803 * @param aname
6804 * @param hide_msg
6805 * @param common_archive
6806 * @return 0 - success
6809 Experiment::copy_file (char *name, char *aname, int hide_msg, char *common_archive, int relative_path)
6811 if (common_archive)
6813 if (0 == copy_file_to_common_archive (name, aname, hide_msg,
6814 common_archive, relative_path))
6815 return 0;
6816 // Error. For now - fatal error. Message is already printed.
6817 fprintf (stderr, GTXT ("gprofng-archive: Fatal error: cannot copy file %s to common archive %s\n"),
6818 name, common_archive);
6819 return 1;
6821 return (copy_file_to_archive (name, aname, hide_msg));
6824 LoadObject *
6825 Experiment::createLoadObject (const char *path, uint64_t chksum)
6827 LoadObject *lo = dbeSession->createLoadObject (path, chksum);
6828 if (lo->firstExp == NULL)
6829 lo->firstExp = this;
6830 return lo;
6833 LoadObject *
6834 Experiment::createLoadObject (const char *path, const char *runTimePath)
6836 DbeFile *df = findFileInArchive (path, runTimePath);
6837 if (df && (df->get_stat () == NULL))
6838 df = NULL; // No access to file
6839 LoadObject *lo = dbeSession->createLoadObject (path, runTimePath, df);
6840 if (df && (lo->dbeFile->get_location (false) == NULL))
6842 lo->dbeFile->set_location (df->get_location ());
6843 lo->dbeFile->inArchive = df->inArchive;
6844 lo->dbeFile->sbuf = df->sbuf;
6845 lo->dbeFile->experiment = df->experiment;
6846 lo->firstExp = df->experiment;
6848 if (lo->firstExp == NULL)
6850 lo->firstExp = this;
6851 lo->dbeFile->experiment = this;
6853 return lo;
6856 SourceFile *
6857 Experiment::get_source (const char *path)
6859 if (founder_exp && (founder_exp != this))
6860 return founder_exp->get_source (path);
6861 if (sourcesMap == NULL)
6862 sourcesMap = new StringMap<SourceFile*>(1024, 1024);
6863 if (strncmp (path, NTXT ("./"), 2) == 0)
6864 path += 2;
6865 SourceFile *sf = sourcesMap->get (path);
6866 if (sf)
6867 return sf;
6868 char *fnm = checkFileInArchive (path, false);
6869 if (fnm)
6871 sf = new SourceFile (path);
6872 dbeSession->append (sf);
6873 DbeFile *df = sf->dbeFile;
6874 df->set_location (fnm);
6875 df->inArchive = true;
6876 df->check_access (fnm); // init 'sbuf'
6877 df->sbuf.st_mtime = 0; // Don't check timestamps
6878 free (fnm);
6880 else
6881 sf = dbeSession->createSourceFile (path);
6882 sourcesMap->put (path, sf);
6883 return sf;
6886 Vector<Histable*> *
6887 Experiment::get_comparable_objs ()
6889 update_comparable_objs ();
6890 if (comparable_objs || dbeSession->expGroups->size () <= 1)
6891 return comparable_objs;
6892 comparable_objs = new Vector<Histable*>(dbeSession->expGroups->size ());
6893 for (long i = 0, sz = dbeSession->expGroups->size (); i < sz; i++)
6895 ExpGroup *gr = dbeSession->expGroups->get (i);
6896 if (groupId == gr->groupId)
6898 comparable_objs->append (this);
6899 continue;
6901 Histable *h = NULL;
6902 for (long i1 = 0, sz1 = gr->exps ? gr->exps->size () : 0; i1 < sz1; i1++)
6904 Experiment *exp = gr->exps->get (i1);
6905 if ((exp->comparable_objs == NULL) && (dbe_strcmp (utargname, exp->utargname) == 0))
6907 exp->phaseCompareIdx = phaseCompareIdx;
6908 h = exp;
6909 h->comparable_objs = comparable_objs;
6910 break;
6913 comparable_objs->append (h);
6915 dump_comparable_objs ();
6916 return comparable_objs;
6919 DbeFile *
6920 Experiment::findFileInArchive (const char *fname)
6922 if (archiveMap)
6924 char *aname = get_archived_name (fname);
6925 DbeFile *df = archiveMap->get (aname);
6926 free (aname);
6927 return df;
6929 if (founder_exp)
6930 return founder_exp->findFileInArchive (fname);
6931 return NULL;
6934 DbeFile *
6935 Experiment::findFileInArchive (const char *className, const char *runTimePath)
6937 DbeFile *df = NULL;
6938 if (runTimePath)
6940 const char *fnm = NULL;
6941 if (strncmp (runTimePath, NTXT ("zip:"), 4) == 0)
6942 fnm = runTimePath + 4;
6943 else if (strncmp (runTimePath, NTXT ("jar:file:"), 9) == 0)
6944 fnm = runTimePath + 9;
6945 if (fnm)
6947 const char *s = strchr (fnm, '!');
6948 if (s)
6950 char *s1 = dbe_strndup (fnm, s - fnm);
6951 df = findFileInArchive (s1);
6952 free (s1);
6954 else
6955 df = findFileInArchive (fnm);
6956 if (df)
6957 df->filetype |= DbeFile::F_JAR_FILE;
6959 else if (strncmp (runTimePath, NTXT ("file:"), 5) == 0)
6961 fnm = runTimePath + 5;
6962 df = findFileInArchive (fnm);
6964 else
6965 df = findFileInArchive (runTimePath);
6967 if (df == NULL)
6968 df = findFileInArchive (className);
6969 return df;