1 /* Copyright (C) 2021 Free Software Foundation, Inc.
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)
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. */
30 #include <sys/param.h>
36 #include "DbeCacheMap.h"
37 #include "DefaultHandler.h"
38 #include "DefaultMap2D.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"
54 #include "LoadObject.h"
60 #include "StringMap.h"
61 #include "UserLabel.h"
63 #include "dbe_types.h"
65 #include "cc_libcollector.h"
75 struct Experiment::UIDnode
82 struct Experiment::RawFramePacket
92 parseTStamp (const char *s)
94 hrtime_t ts = (hrtime_t) 0;
95 ts = (hrtime_t) atoi (s) * NANOSEC;
98 ts += (hrtime_t) atoi (s + 1);
102 class Experiment::ExperimentFile
114 ExperimentFile (Experiment *_exp, const char *_fname);
117 bool open (bool new_open = false);
140 int bufsz, ef_status;
144 class Experiment::ExperimentHandler : public DefaultHandler
148 ExperimentHandler (Experiment *_exp);
149 ~ExperimentHandler ();
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);
159 ignorableWhitespace (char*, int, int) { }
161 error (SAXParseException *e);
186 static int toInt (Attributes *attrs, const char *atr);
187 static char*toStr (Attributes *attrs, const char *atr);
188 void pushElem (Element);
193 Vector<Element> *stack;
194 Module *dynfuncModule;
195 DataDescriptor *dDscr;
196 PacketDescriptor *pDscr;
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)
217 ef_status = EF_NOT_OPENED;
219 fname = dbe_sprintf (NTXT ("%s/%s"), exp->expt_name, _fname);
222 Experiment::ExperimentFile::~ExperimentFile ()
230 Experiment::ExperimentFile::open (bool new_open)
234 fh = fopen64 (fname, NTXT ("r"));
237 ef_status = EF_FAILURE;
240 ef_status = EF_OPENED;
244 fseeko64 (fh, offset, SEEK_SET);
250 Experiment::ExperimentFile::fgets ()
255 buffer = (char *) malloc (bufsz);
258 buffer[bufsz - 1] = (char) 1; // sentinel
260 char *res = ::fgets (buffer, bufsz, fh);
263 while (buffer[bufsz - 1] == (char) 0)
265 int newsz = bufsz + 1024;
266 char *newbuf = (char *) malloc (newsz);
269 memcpy (newbuf, buffer, bufsz);
272 buffer[newsz - 1] = (char) 1; // sentinel
273 // we don't care about fgets result here
274 ::fgets (buffer + bufsz - 1, newsz - bufsz + 1, fh);
281 Experiment::ExperimentFile::close ()
285 offset = ftello64 (fh);
287 ef_status = EF_CLOSED;
293 //-------------------------------------------------- Experiment XML parser
295 Experiment::ExperimentHandler::toInt (Attributes *attrs, const char *atr)
297 const char *str = attrs->getValue (atr);
298 return str ? atoi (str) : 0;
302 Experiment::ExperimentHandler::toStr (Attributes *attrs, const char *atr)
304 const char *str = attrs->getValue (atr);
305 return dbe_strdup (str ? str : NTXT (""));
308 Experiment::ExperimentHandler::ExperimentHandler (Experiment *_exp)
311 stack = new Vector<Element>;
313 dynfuncModule = NULL;
318 mkind = (Cmsg_warn) - 1; // CMSG_NONE
323 Experiment::ExperimentHandler::~ExperimentHandler ()
330 Experiment::ExperimentHandler::endDocument ()
332 { // SP_TAG_STATE should be used to describe states, but it isn't
334 DataDescriptor *dd = exp->getDataDescriptor (DATA_HEAP);
337 PropDescr *prop = dd->getProp (PROP_HTYPE);
340 char * stateNames [HEAPTYPE_LAST] = HEAPTYPE_STATE_STRINGS;
341 char * stateUNames[HEAPTYPE_LAST] = HEAPTYPE_STATE_USTRINGS;
342 for (int ii = 0; ii < HEAPTYPE_LAST; ii++)
343 prop->addState (ii, stateNames[ii], stateUNames[ii]);
346 dd = exp->getDataDescriptor (DATA_IOTRACE);
349 PropDescr *prop = dd->getProp (PROP_IOTYPE);
352 char * stateNames [IOTRACETYPE_LAST] = IOTRACETYPE_STATE_STRINGS;
353 char * stateUNames[IOTRACETYPE_LAST] = IOTRACETYPE_STATE_USTRINGS;
354 for (int ii = 0; ii < IOTRACETYPE_LAST; ii++)
355 prop->addState (ii, stateNames[ii], stateUNames[ii]);
362 Experiment::ExperimentHandler::pushElem (Element elem)
365 stack->append (curElem);
369 Experiment::ExperimentHandler::popElem ()
371 stack->remove (stack->size () - 1);
372 curElem = stack->fetch (stack->size () - 1);
376 Experiment::ExperimentHandler::startElement (char*, char*, char *qName, Attributes *attrs)
378 DEBUG_CODE if (DEBUG_SAXPARSER) dump_startElement (qName, attrs);
379 if (strcmp (qName, SP_TAG_EXPERIMENT) == 0)
381 pushElem (EL_EXPERIMENT);
382 const char *str = attrs->getValue (NTXT ("version"));
385 int major = atoi (str);
386 str = strchr (str, '.');
387 int minor = str ? atoi (str + 1) : 0;
388 exp->exp_maj_version = major;
389 exp->exp_min_version = minor;
390 if (major != SUNPERF_VERNUM || minor != SUNPERF_VERNUM_MINOR)
392 // not the current version, see if we support some earlier versions
396 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"),
397 exp->get_expt_name (), major, minor);
398 // exp->errorq->append( new Emsg(CMSG_FATAL, sb) );
399 exp->status = FAILURE;
401 throw new SAXException (sb.toString ());
406 else if (strcmp (qName, SP_TAG_COLLECTOR) == 0)
407 pushElem (EL_COLLECTOR);
408 else if (strcmp (qName, SP_TAG_SETTING) == 0)
411 pushElem (EL_SETTING);
412 const char *str = attrs->getValue (SP_JCMD_LIMIT);
416 exp->coll_params.limit = atoi (str);
418 str = attrs->getValue (SP_JCMD_BLKSZ);
422 exp->blksz = strtol (str, NULL, 0);
424 str = attrs->getValue (SP_JCMD_STACKBASE);
428 exp->stack_base = strtoull (str, NULL, 0);
430 str = attrs->getValue (SP_JCMD_HWC_DEFAULT);
434 exp->hwc_default = true;
436 str = attrs->getValue (SP_JCMD_NOIDLE);
440 exp->commentq->append (new Emsg (CMSG_COMMENT,
441 GTXT ("*** Note: experiment does not have events from idle CPUs")));
443 str = attrs->getValue (SP_JCMD_FAKETIME);
447 exp->timelineavail = false;
448 exp->commentq->append (new Emsg (CMSG_COMMENT,
449 GTXT ("*** Note: experiment does not have timestamps; timeline unavailable")));
451 str = attrs->getValue (SP_JCMD_DELAYSTART);
455 exp->coll_params.start_delay = strdup (str);
457 str = attrs->getValue (SP_JCMD_TERMINATE);
461 exp->coll_params.terminate = strdup (str);
463 str = attrs->getValue (SP_JCMD_PAUSE_SIG);
467 exp->coll_params.pause_sig = strdup (str);
469 str = attrs->getValue (SP_JCMD_SAMPLE_PERIOD);
473 exp->coll_params.sample_periodic = 1;
474 exp->coll_params.sample_timer = atoi (str);
476 str = attrs->getValue (SP_JCMD_SAMPLE_SIG);
480 exp->coll_params.sample_sig = str;
482 str = attrs->getValue (SP_JCMD_SRCHPATH);
487 sb.sprintf (GTXT ("Search path: %s"), str);
488 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb));
489 dbeSession->add_classpath ((char*) str);
491 str = attrs->getValue (SP_JCMD_LINETRACE);
495 exp->coll_params.linetrace = strdup (str);
498 str = attrs->getValue (SP_JCMD_COLLENV);
503 sb.sprintf (GTXT (" Data collection environment variable: %s"), str);
504 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb));
508 int nattr = attrs->getLength ();
511 fprintf (stderr, "XXX Unexpected setting found; %d attributes:\n",
513 for (int k = 0; k < nattr; k++)
515 const char *qn = attrs->getQName (k);
516 const char *vl = attrs->getValue (k);
517 fprintf (stderr, "XXX %s = %s\n", qn, vl);
521 // END OF CODE FOR "setting"
523 else if (strcmp (qName, SP_TAG_SYSTEM) == 0)
525 pushElem (EL_SYSTEM);
526 const char *str = attrs->getValue (NTXT ("hostname"));
528 exp->hostname = strdup (str);
529 str = attrs->getValue (NTXT ("os"));
532 exp->os_version = strdup (str);
533 /* For Linux experiments expect sparse thread ID's */
534 if (strncmp (str, NTXT ("SunOS"), 5) != 0)
535 exp->sparse_threads = true;
537 str = attrs->getValue (NTXT ("arch"));
540 if (strcmp (str, "i86pc") == 0 || strcmp (str, "i686") == 0
541 || strcmp (str, "x86_64") == 0)
542 exp->platform = Intel;
543 else if (strcmp (str, "aarch64") == 0)
544 exp->platform = Aarch64;
546 exp->platform = Sparc;
547 exp->need_swap_endian = (DbeSession::platform == Sparc) ?
548 (exp->platform != Sparc) : (exp->platform == Sparc);
549 exp->architecture = strdup (str);
551 str = attrs->getValue (NTXT ("pagesz"));
553 exp->page_size = atoi (str);
554 str = attrs->getValue (NTXT ("npages"));
556 exp->npages = atoi (str);
558 else if (strcmp (qName, SP_TAG_POWERM) == 0)
559 pushElem (EL_POWERM);
560 else if (strcmp (qName, SP_TAG_FREQUENCY) == 0)
562 pushElem (EL_FREQUENCY);
563 const char *str = attrs->getValue (NTXT ("clk"));
565 exp->set_clock (atoi (str));
566 // check for frequency_scaling or turbo_mode recorded from libcollector under dbx
567 str = attrs->getValue (NTXT ("frequency_scaling"));
568 const char *str2 = attrs->getValue (NTXT ("turbo_mode"));
569 if (str != NULL || str2 != NULL)
572 else if (strcmp (qName, SP_TAG_CPU) == 0)
576 const char *str = attrs->getValue (NTXT ("clk"));
579 int clk = atoi (str);
580 if (exp->maxclock == 0)
587 if (clk < exp->minclock)
589 if (clk > exp->maxclock)
594 // check for frequency_scaling or turbo_mode
595 str = attrs->getValue (NTXT ("frequency_scaling"));
596 const char *str2 = attrs->getValue (NTXT ("turbo_mode"));
597 if (str != NULL || str2 != NULL)
600 else if (strcmp (qName, SP_TAG_PROCESS) == 0)
602 pushElem (EL_PROCESS);
603 const char *str = attrs->getValue (NTXT ("wsize"));
606 int wsz = atoi (str);
612 str = attrs->getValue (NTXT ("pid"));
614 exp->pid = atoi (str);
615 str = attrs->getValue (NTXT ("ppid"));
617 exp->ppid = atoi (str);
618 str = attrs->getValue (NTXT ("pgrp"));
620 exp->pgrp = atoi (str);
621 str = attrs->getValue (NTXT ("sid"));
623 exp->sid = atoi (str);
624 str = attrs->getValue (NTXT ("cwd"));
626 exp->ucwd = strdup (str);
627 str = attrs->getValue (NTXT ("pagesz"));
629 exp->page_size = atoi (str);
631 else if (strcmp (qName, SP_TAG_EVENT) == 0)
632 { // Start code for event
634 hrtime_t ts = (hrtime_t) 0;
635 const char *str = attrs->getValue (NTXT ("tstamp"));
637 ts = parseTStamp (str);
638 str = attrs->getValue (NTXT ("kind"));
641 if (strcmp (str, SP_JCMD_RUN) == 0)
644 exp->exp_start_time = ts;
645 str = attrs->getValue (NTXT ("time"));
647 exp->start_sec = atoll (str);
648 str = attrs->getValue (NTXT ("pid"));
650 exp->pid = atoi (str);
651 str = attrs->getValue (NTXT ("ppid"));
653 exp->ppid = atoi (str);
654 str = attrs->getValue (NTXT ("pgrp"));
656 exp->pgrp = atoi (str);
657 str = attrs->getValue (NTXT ("sid"));
659 exp->sid = atoi (str);
660 exp->status = Experiment::INCOMPLETE;
662 else if (strcmp (str, SP_JCMD_ARCHIVE) == 0)
665 sb.sprintf (GTXT ("er_archive run: XXXXXXX"));
666 exp->pprocq->append (new Emsg (CMSG_WARN, sb));
668 else if (strcmp (str, SP_JCMD_SAMPLE) == 0)
670 exp->update_last_event (exp->exp_start_time + ts); // ts is 0-based
671 str = attrs->getValue (NTXT ("id"));
672 int id = str ? atoi (str) : -1;
673 char *label = dbe_strdup (attrs->getValue (NTXT ("label")));
674 exp->process_sample_cmd (NULL, ts, id, label);
676 else if (strcmp (str, SP_JCMD_EXIT) == 0)
678 // don't treat EXIT as an event w.r.t. last_event and non_paused_time
679 exp->status = Experiment::SUCCESS;
681 else if (strcmp (str, SP_JCMD_CERROR) == 0)
684 str = attrs->getValue (NTXT ("id"));
689 str = attrs->getValue (NTXT ("ec"));
695 else if (strcmp (str, SP_JCMD_CWARN) == 0)
698 str = attrs->getValue (NTXT ("id"));
702 else if (strcmp (str, SP_JCMD_COMMENT) == 0)
704 mkind = CMSG_COMMENT;
705 str = attrs->getValue (NTXT ("id"));
708 str = attrs->getValue (NTXT ("text"));
712 sb.sprintf (GTXT ("*** Note: %s"), str);
713 exp->commentq->append (new Emsg (CMSG_COMMENT, sb));
716 else if (strcmp (str, SP_JCMD_DESC_START) == 0)
718 char *variant = toStr (attrs, NTXT ("variant"));
719 char *lineage = toStr (attrs, NTXT ("lineage"));
720 int follow = toInt (attrs, NTXT ("follow"));
721 char *msg = toStr (attrs, NTXT ("msg"));
722 exp->process_desc_start_cmd (NULL, ts, variant, lineage, follow, msg);
724 else if (strcmp (str, SP_JCMD_DESC_STARTED) == 0)
726 char *variant = toStr (attrs, NTXT ("variant"));
727 char *lineage = toStr (attrs, NTXT ("lineage"));
728 int follow = toInt (attrs, NTXT ("follow"));
729 char *msg = toStr (attrs, NTXT ("msg"));
730 exp->process_desc_started_cmd (NULL, ts, variant, lineage, follow, msg);
732 else if (strcmp (str, SP_JCMD_EXEC_START) == 0)
734 // if successful, acts like experiment termination - no "exit" entry will follow
735 exp->update_last_event (exp->exp_start_time + ts); // ts is 0-based
736 char *variant = toStr (attrs, NTXT ("variant"));
737 char *lineage = toStr (attrs, NTXT ("lineage"));
738 int follow = toInt (attrs, NTXT ("follow"));
739 char *msg = toStr (attrs, NTXT ("msg"));
740 exp->process_desc_start_cmd (NULL, ts, variant, lineage, follow, msg);
741 exp->exec_started = true;
743 else if (strcmp (str, SP_JCMD_EXEC_ERROR) == 0)
745 exp->update_last_event (exp->exp_start_time + ts); // ts is 0-based
746 char *variant = toStr (attrs, NTXT ("variant"));
747 char *lineage = toStr (attrs, NTXT ("lineage"));
748 int follow = toInt (attrs, NTXT ("follow"));
749 char *msg = toStr (attrs, NTXT ("msg"));
750 exp->process_desc_started_cmd (NULL, ts, variant, lineage, follow, msg);
751 exp->exec_started = false;
753 else if (strcmp (str, SP_JCMD_JTHRSTART) == 0)
755 char *name = dbe_strdup (attrs->getValue (NTXT ("name")));
756 char *grpname = dbe_strdup (attrs->getValue (NTXT ("grpname")));
757 char *prntname = dbe_strdup (attrs->getValue (NTXT ("prntname")));
758 str = attrs->getValue (NTXT ("tid"));
759 uint64_t tid = str ? strtoull (str, NULL, 0) : 0;
760 str = attrs->getValue (NTXT ("jthr"));
761 Vaddr jthr = str ? strtoull (str, NULL, 0) : 0;
762 str = attrs->getValue (NTXT ("jenv"));
763 Vaddr jenv = str ? strtoull (str, NULL, 0) : 0;
764 exp->process_jthr_start_cmd (NULL, name, grpname, prntname, tid, jthr, jenv, ts);
766 else if (strcmp (str, SP_JCMD_JTHREND) == 0)
768 str = attrs->getValue (NTXT ("tid"));
769 uint64_t tid = str ? strtoull (str, NULL, 0) : 0;
770 str = attrs->getValue (NTXT ("jthr"));
771 Vaddr jthr = str ? strtoull (str, NULL, 0) : 0;
772 str = attrs->getValue (NTXT ("jenv"));
773 Vaddr jenv = str ? strtoull (str, NULL, 0) : 0;
774 exp->process_jthr_end_cmd (NULL, tid, jthr, jenv, ts);
776 else if (strcmp (str, SP_JCMD_GCEND) == 0)
778 if (exp->getDataDescriptor (DATA_GCEVENT) == NULL)
779 exp->newDataDescriptor (DATA_GCEVENT);
780 exp->process_gc_end_cmd (ts);
782 else if (strcmp (str, SP_JCMD_GCSTART) == 0)
784 if (exp->getDataDescriptor (DATA_GCEVENT) == NULL)
785 exp->newDataDescriptor (DATA_GCEVENT);
786 exp->process_gc_start_cmd (ts);
788 else if (strcmp (str, SP_JCMD_PAUSE) == 0)
790 if (exp->resume_ts != MAX_TIME)
792 // data collection was active
793 hrtime_t delta = ts - exp->resume_ts;
794 exp->non_paused_time += delta;
795 exp->resume_ts = MAX_TIME; // collection is paused
798 str = attrs->getValue (NTXT ("name"));
800 sb.sprintf (GTXT ("Pause: %ld.%09ld"), (long) (ts / NANOSEC),
801 (long) (ts % NANOSEC));
803 sb.sprintf (GTXT ("Pause (%s): %ld.%09ld"), str,
804 (long) (ts / NANOSEC), (long) (ts % NANOSEC));
805 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb));
807 else if (strcmp (str, SP_JCMD_RESUME) == 0)
809 if (exp->resume_ts == MAX_TIME)
810 // data collection was paused
811 exp->resume_ts = ts; // remember start time
813 sb.sprintf (GTXT ("Resume: %ld.%09ld"), (long) (ts / NANOSEC), (long) (ts % NANOSEC));
814 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb));
815 if (exp->exp_start_time == ZERO_TIME)
816 exp->exp_start_time = ts;
818 else if (strcmp (str, SP_JCMD_THREAD_PAUSE) == 0)
820 str = attrs->getValue (NTXT ("tid"));
821 uint64_t tid = str ? strtoull (str, NULL, 0) : 0;
823 sb.sprintf (GTXT ("Thread %llu pause: %ld.%09ld"), (unsigned long long) tid,
824 (long) (ts / NANOSEC), (long) (ts % NANOSEC));
825 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb));
827 else if (strcmp (str, SP_JCMD_THREAD_RESUME) == 0)
829 str = attrs->getValue (NTXT ("tid"));
830 uint64_t tid = str ? strtoull (str, NULL, 0) : 0;
832 sb.sprintf (GTXT ("Thread %llu resume: %ld.%09ld"), (unsigned long long) tid,
833 (long) (ts / NANOSEC), (long) (ts % NANOSEC));
834 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb));
836 else if (strcmp (str, NTXT ("map")) == 0)
838 ts += exp->exp_start_time;
839 str = attrs->getValue (NTXT ("vaddr"));
840 Vaddr vaddr = str ? strtoull (str, NULL, 0) : 0;
841 str = attrs->getValue (NTXT ("size"));
842 int msize = str ? atoi (str) : 0;
843 str = attrs->getValue (NTXT ("foffset"));
844 int64_t offset = str ? strtoll (str, NULL, 0) : 0;
845 str = attrs->getValue (NTXT ("modes"));
846 int64_t modes = str ? strtoll (str, NULL, 0) : 0;
847 str = attrs->getValue (NTXT ("chksum"));
850 chksum = Elf::normalize_checksum (strtoll (str, NULL, 0));
851 char *name = (char *) attrs->getValue (NTXT ("name"));
852 str = attrs->getValue (NTXT ("object"));
853 if (strcmp (str, NTXT ("segment")) == 0)
855 if (strcmp (name, NTXT ("LinuxKernel")) == 0)
856 exp->process_Linux_kernel_cmd (ts);
858 exp->process_seg_map_cmd (NULL, ts, vaddr, msize, 0,
859 offset, modes, chksum, name);
861 else if (strcmp (str, NTXT ("function")) == 0)
863 exp->process_fn_load_cmd (dynfuncModule, name, vaddr, msize, ts);
864 dynfuncModule = NULL;
866 else if (strcmp (str, NTXT ("dynfunc")) == 0)
868 if (dynfuncModule == NULL)
870 dynfuncModule = dbeSession->createModule (exp->get_dynfunc_lo (DYNFUNC_SEGMENT), name);
871 dynfuncModule->flags |= MOD_FLAG_UNKNOWN;
872 dynfuncModule->set_file_name (dbe_strdup (dynfuncModule->getMainSrc ()->get_name ()));
874 (void) exp->create_dynfunc (dynfuncModule,
875 (char*) attrs->getValue (NTXT ("funcname")), vaddr, msize);
877 else if (strcmp (str, NTXT ("jcm")) == 0)
879 str = attrs->getValue (NTXT ("methodId"));
880 Vaddr mid = str ? strtoull (str, NULL, 0) : 0;
881 exp->process_jcm_load_cmd (NULL, mid, vaddr, msize, ts);
884 else if (strcmp (str, NTXT ("unmap")) == 0)
886 ts += exp->exp_start_time;
887 str = attrs->getValue (NTXT ("vaddr"));
888 Vaddr vaddr = str ? strtoull (str, NULL, 0) : 0;
889 exp->process_seg_unmap_cmd (NULL, ts, vaddr);
892 // end of code for event
894 else if (strcmp (qName, SP_TAG_PROFILE) == 0)
896 pushElem (EL_PROFILE);
897 const char *str = attrs->getValue (NTXT ("name"));
900 if (strcmp (str, NTXT ("profile")) == 0)
902 exp->coll_params.profile_mode = 1;
903 str = attrs->getValue (NTXT ("numstates"));
905 exp->coll_params.lms_magic_id = atoi (str);
906 str = attrs->getValue (NTXT ("ptimer"));
908 exp->coll_params.ptimer_usec = atoi (str); // microseconds
910 PropDescr *mstate_prop = NULL;
911 char * stateNames [/*LMS_NUM_STATES*/] = LMS_STATE_STRINGS;
912 char * stateUNames[/*LMS_NUM_STATES*/] = LMS_STATE_USTRINGS;
914 dDscr = exp->newDataDescriptor (DATA_CLOCK);
915 PropDescr *prop = new PropDescr (PROP_MSTATE, NTXT ("MSTATE"));
916 prop->uname = dbe_strdup (GTXT ("Thread state"));
917 prop->vtype = TYPE_UINT32;
918 // (states added below)
919 dDscr->addProperty (prop);
922 prop = new PropDescr (PROP_NTICK, NTXT ("NTICK"));
923 prop->uname = dbe_strdup (GTXT ("Number of Profiling Ticks"));
924 prop->vtype = TYPE_UINT32;
925 dDscr->addProperty (prop);
928 switch (exp->coll_params.lms_magic_id)
930 case LMS_MAGIC_ID_SOLARIS:
931 exp->register_metric (Metric::CP_TOTAL);
932 exp->register_metric (Metric::CP_TOTAL_CPU);
933 exp->register_metric (Metric::CP_LMS_USER);
934 exp->register_metric (Metric::CP_LMS_SYSTEM);
935 exp->register_metric (Metric::CP_LMS_TRAP);
936 exp->register_metric (Metric::CP_LMS_DFAULT);
937 exp->register_metric (Metric::CP_LMS_TFAULT);
938 exp->register_metric (Metric::CP_LMS_KFAULT);
939 exp->register_metric (Metric::CP_LMS_STOPPED);
940 exp->register_metric (Metric::CP_LMS_WAIT_CPU);
941 exp->register_metric (Metric::CP_LMS_SLEEP);
942 exp->register_metric (Metric::CP_LMS_USER_LOCK);
943 for (int ii = 0; ii < LMS_NUM_SOLARIS_MSTATES; ii++)
944 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]);
946 case LMS_MAGIC_ID_ERKERNEL_KERNEL:
947 exp->register_metric (Metric::CP_KERNEL_CPU);
949 int ii = LMS_KERNEL_CPU;
950 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]);
953 case LMS_MAGIC_ID_ERKERNEL_USER:
954 exp->register_metric (Metric::CP_TOTAL_CPU);
955 exp->register_metric (Metric::CP_LMS_USER);
956 exp->register_metric (Metric::CP_LMS_SYSTEM);
958 int ii = LMS_KERNEL_CPU;
959 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]);
961 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]);
963 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]);
966 case LMS_MAGIC_ID_LINUX:
967 exp->register_metric (Metric::CP_TOTAL_CPU);
969 int ii = LMS_LINUX_CPU;
970 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]);
978 else if (strcmp (str, NTXT ("heaptrace")) == 0)
980 exp->coll_params.heap_mode = 1;
981 exp->leaklistavail = true;
982 exp->heapdataavail = true;
983 exp->register_metric (Metric::HEAP_ALLOC_BYTES);
984 exp->register_metric (Metric::HEAP_ALLOC_CNT);
985 exp->register_metric (Metric::HEAP_LEAK_BYTES);
986 exp->register_metric (Metric::HEAP_LEAK_CNT);
987 dDscr = exp->newDataDescriptor (DATA_HEAP);
989 else if (strcmp (str, NTXT ("iotrace")) == 0)
991 exp->coll_params.io_mode = 1;
992 exp->iodataavail = true;
993 exp->register_metric (Metric::IO_READ_TIME);
994 exp->register_metric (Metric::IO_READ_BYTES);
995 exp->register_metric (Metric::IO_READ_CNT);
996 exp->register_metric (Metric::IO_WRITE_TIME);
997 exp->register_metric (Metric::IO_WRITE_BYTES);
998 exp->register_metric (Metric::IO_WRITE_CNT);
999 exp->register_metric (Metric::IO_OTHER_TIME);
1000 exp->register_metric (Metric::IO_OTHER_CNT);
1001 exp->register_metric (Metric::IO_ERROR_TIME);
1002 exp->register_metric (Metric::IO_ERROR_CNT);
1003 dDscr = exp->newDataDescriptor (DATA_IOTRACE);
1005 else if (strcmp (str, NTXT ("synctrace")) == 0)
1007 exp->coll_params.sync_mode = 1;
1008 str = attrs->getValue (NTXT ("threshold"));
1010 exp->coll_params.sync_threshold = atoi (str);
1011 str = attrs->getValue (NTXT ("scope"));
1013 exp->coll_params.sync_scope = atoi (str);
1014 else // Should only happen with old experiments; use the old default
1015 exp->coll_params.sync_scope = SYNCSCOPE_NATIVE | SYNCSCOPE_JAVA;
1016 exp->register_metric (Metric::SYNC_WAIT_TIME);
1017 exp->register_metric (Metric::SYNC_WAIT_COUNT);
1018 dDscr = exp->newDataDescriptor (DATA_SYNCH);
1020 else if (strcmp (str, NTXT ("omptrace")) == 0)
1022 exp->coll_params.omp_mode = 1;
1023 dDscr = exp->newDataDescriptor (DATA_OMP, DDFLAG_NOSHOW);
1025 else if (strcmp (str, NTXT ("hwcounter")) == 0)
1027 str = attrs->getValue (NTXT ("cpuver"));
1028 int cpuver = str ? atoi (str) : 0;
1029 char *counter = dbe_strdup (attrs->getValue (NTXT ("hwcname")));
1030 char *int_name = dbe_strdup (attrs->getValue (NTXT ("int_name"))); // may not be present
1031 str = attrs->getValue (NTXT ("interval"));
1032 int interval = str ? atoi (str) : 0;
1033 str = attrs->getValue (NTXT ("tag"));
1034 int tag = str ? atoi (str) : 0;
1035 str = attrs->getValue (NTXT ("memop"));
1036 int i_tpc = str ? atoi (str) : 0;
1037 char *modstr = dbe_strdup (attrs->getValue (NTXT ("modstr")));
1038 exp->process_hwcounter_cmd (NULL, cpuver, counter, int_name, interval, tag, i_tpc, modstr);
1039 dDscr = exp->newDataDescriptor (DATA_HWC);
1041 else if (strcmp (str, NTXT ("hwsimctr")) == 0)
1043 int cpuver = toInt (attrs, NTXT ("cpuver"));
1044 char *hwcname = dbe_strdup (attrs->getValue (NTXT ("hwcname")));
1045 char *int_name = dbe_strdup (attrs->getValue (NTXT ("int_name")));
1046 char *metric = dbe_strdup (attrs->getValue (NTXT ("metric")));
1047 int reg = toInt (attrs, NTXT ("reg_num"));
1048 int interval = toInt (attrs, NTXT ("interval"));
1049 int timecvt = toInt (attrs, NTXT ("timecvt"));
1050 int i_tpc = toInt (attrs, NTXT ("memop"));
1051 int tag = toInt (attrs, NTXT ("tag"));
1052 exp->process_hwsimctr_cmd (NULL, cpuver, hwcname, int_name, metric, reg,
1053 interval, timecvt, i_tpc, tag);
1054 dDscr = exp->newDataDescriptor (DATA_HWC);
1056 else if (strcmp (str, NTXT ("dversion")) == 0)
1057 exp->dversion = dbe_strdup (attrs->getValue (NTXT ("version")));
1058 else if (strcmp (str, NTXT ("jprofile")) == 0)
1060 exp->has_java = true;
1061 str = attrs->getValue (NTXT ("jversion"));
1063 exp->jversion = strdup (str);
1065 else if (strcmp (str, NTXT ("datarace")) == 0)
1067 exp->coll_params.race_mode = 1;
1068 exp->racelistavail = true;
1069 str = attrs->getValue (NTXT ("scheme"));
1070 exp->coll_params.race_stack = str ? atoi (str) : 0;
1071 exp->register_metric (Metric::RACCESS);
1072 dDscr = exp->newDataDescriptor (DATA_RACE);
1074 else if (strcmp (str, NTXT ("deadlock")) == 0)
1076 exp->coll_params.deadlock_mode = 1;
1077 exp->deadlocklistavail = true;
1078 exp->register_metric (Metric::DEADLOCKS);
1079 dDscr = exp->newDataDescriptor (DATA_DLCK);
1082 /* XXX -- obsolete tag, but is still written to experiments */
1083 else if (strcmp (qName, SP_TAG_DATAPTR) == 0)
1085 pushElem (EL_DATAPTR);
1088 else if (strcmp (qName, SP_TAG_PROFDATA) == 0)
1090 pushElem (EL_PROFDATA);
1091 // SS12 HWC experiments are not well structured
1092 const char *fname = attrs->getValue (NTXT ("fname"));
1093 if (fname && strcmp (fname, SP_HWCNTR_FILE) == 0)
1094 dDscr = exp->newDataDescriptor (DATA_HWC);
1096 else if (strcmp (qName, SP_TAG_PROFPCKT) == 0)
1098 pushElem (EL_PROFPCKT);
1099 const char *str = attrs->getValue (NTXT ("kind")); // see Pckt_type
1100 int kind = str ? atoi (str) : -1;
1103 if (exp->coll_params.omp_mode == 1)
1105 if (kind == OMP_PCKT)
1106 dDscr = exp->newDataDescriptor (DATA_OMP, DDFLAG_NOSHOW);
1107 else if (kind == OMP2_PCKT)
1108 dDscr = exp->newDataDescriptor (DATA_OMP2, DDFLAG_NOSHOW);
1109 else if (kind == OMP3_PCKT)
1110 dDscr = exp->newDataDescriptor (DATA_OMP3, DDFLAG_NOSHOW);
1111 else if (kind == OMP4_PCKT)
1112 dDscr = exp->newDataDescriptor (DATA_OMP4, DDFLAG_NOSHOW);
1113 else if (kind == OMP5_PCKT)
1114 dDscr = exp->newDataDescriptor (DATA_OMP5, DDFLAG_NOSHOW);
1116 pDscr = exp->newPacketDescriptor (kind, dDscr);
1119 else if (strcmp (qName, SP_TAG_FIELD) == 0)
1121 pushElem (EL_FIELD);
1124 const char *name = attrs->getValue (NTXT ("name"));
1127 int propID = dbeSession->registerPropertyName (name);
1128 propDscr = new PropDescr (propID, name);
1129 FieldDescr *fldDscr = new FieldDescr (propID, name);
1131 const char *str = attrs->getValue (NTXT ("type"));
1134 if (strcmp (str, NTXT ("INT32")) == 0)
1135 fldDscr->vtype = TYPE_INT32;
1136 else if (strcmp (str, NTXT ("UINT32")) == 0)
1137 fldDscr->vtype = TYPE_UINT32;
1138 else if (strcmp (str, NTXT ("INT64")) == 0)
1139 fldDscr->vtype = TYPE_INT64;
1140 else if (strcmp (str, NTXT ("UINT64")) == 0)
1141 fldDscr->vtype = TYPE_UINT64;
1142 else if (strcmp (str, NTXT ("STRING")) == 0)
1143 fldDscr->vtype = TYPE_STRING;
1144 else if (strcmp (str, NTXT ("DOUBLE")) == 0)
1145 fldDscr->vtype = TYPE_DOUBLE;
1146 else if (strcmp (str, NTXT ("DATE")) == 0)
1148 fldDscr->vtype = TYPE_DATE;
1149 const char *fmt = attrs->getValue (NTXT ("format"));
1150 fldDscr->format = strdup (fmt ? fmt : "");
1153 propDscr->vtype = fldDscr->vtype;
1155 // TYPE_DATE is converted to TYPE_UINT64 in propDscr
1156 if (fldDscr->vtype == TYPE_DATE)
1157 propDscr->vtype = TYPE_UINT64;
1159 // Fix some types until they are fixed in libcollector
1160 if (propID == PROP_VIRTPC || propID == PROP_PHYSPC)
1162 if (fldDscr->vtype == TYPE_INT32)
1163 propDscr->vtype = TYPE_UINT32;
1164 else if (fldDscr->vtype == TYPE_INT64)
1165 propDscr->vtype = TYPE_UINT64;
1168 // The following props get mapped to 32-bit values in readPacket
1169 if (propID == PROP_CPUID || propID == PROP_THRID
1170 || propID == PROP_LWPID)
1171 propDscr->vtype = TYPE_UINT32; // override experiment property
1173 str = attrs->getValue (NTXT ("uname"));
1175 propDscr->uname = strdup (PTXT ((char*) str));
1176 str = attrs->getValue (NTXT ("noshow"));
1177 if (str && atoi (str) != 0)
1178 propDscr->flags |= PRFLAG_NOSHOW;
1183 sb.sprintf (GTXT ("*** Error: data parsing failed. Log file is corrupted."));
1184 exp->warnq->append (new Emsg (CMSG_ERROR, sb));
1185 throw new SAXException (sb.toString ());
1188 dDscr->addProperty (propDscr);
1189 str = attrs->getValue (NTXT ("offset"));
1191 fldDscr->offset = atoi (str);
1192 pDscr->addField (fldDscr);
1195 else if (strcmp (qName, SP_TAG_STATE) == 0)
1197 pushElem (EL_STATE);
1198 if (propDscr != NULL)
1200 const char *str = attrs->getValue (NTXT ("value"));
1201 int value = str ? atoi (str) : -1;
1202 str = attrs->getValue (NTXT ("name"));
1203 const char *ustr = attrs->getValue (NTXT ("uname"));
1204 propDscr->addState (value, str, ustr);
1207 else if (strcmp (qName, SP_TAG_DTRACEFATAL) == 0)
1208 pushElem (EL_DTRACEFATAL);
1212 sb.sprintf (GTXT ("*** Warning: unrecognized element %s"), qName);
1213 exp->warnq->append (new Emsg (CMSG_WARN, sb));
1219 Experiment::ExperimentHandler::characters (char *ch, int start, int length)
1224 exp->cversion = dbe_strndup (ch + start, length);
1227 exp->process_arglist_cmd (NULL, dbe_strndup (ch + start, length));
1231 text = dbe_strndup (ch + start, length);
1239 Experiment::ExperimentHandler::endElement (char*, char*, char*)
1241 if (curElem == EL_EVENT && mkind >= 0 && mnum >= 0)
1245 str = dbe_sprintf ("%s -- %s", text != NULL ? text : "", strerror (mec));
1247 str = dbe_sprintf ("%s", text != NULL ? text : "");
1248 Emsg *msg = new Emsg (mkind, mnum, str);
1249 if (mkind == CMSG_WARN)
1251 if (mnum != COL_WARN_FSTYPE
1252 || dbeSession->check_ignore_fs_warn () == false)
1253 exp->warnq->append (msg);
1255 exp->commentq->append (msg);
1257 else if (mkind == CMSG_ERROR || mkind == CMSG_FATAL)
1258 exp->errorq->append (msg);
1259 else if (mkind == CMSG_COMMENT)
1260 exp->commentq->append (msg);
1263 mkind = (Cmsg_warn) - 1;
1267 else if (curElem == EL_PROFILE)
1269 else if (curElem == EL_PROFPCKT)
1271 else if (curElem == EL_FIELD)
1279 Experiment::ExperimentHandler::error (SAXParseException *e)
1282 sb.sprintf (GTXT ("%s at line %d, column %d"),
1283 e->getMessage (), e->getLineNumber (), e->getColumnNumber ());
1284 char *msg = sb.toString ();
1285 SAXException *e1 = new SAXException (msg);
1290 //-------------------------------------------------- Experiment
1292 Experiment::Experiment ()
1295 userExpId = expIdx = -1;
1298 children_exps = new Vector<Experiment*>;
1299 loadObjs = new Vector<LoadObject*>;
1300 loadObjMap = new StringMap<LoadObject*>(128, 128);
1303 // Initialize configuration information.
1309 architecture = NULL;
1317 exp_maj_version = 0;
1318 exp_min_version = 0;
1323 stack_base = 0xf0000000;
1329 hwc_default = false;
1332 // clear HWC event stats
1336 memset (&coll_params, 0, sizeof (coll_params));
1342 exec_started = false;
1343 timelineavail = true;
1344 leaklistavail = false;
1345 heapdataavail = false;
1346 iodataavail = false;
1347 dataspaceavail = false;
1349 racelistavail = false;
1350 deadlocklistavail = false;
1352 tiny_threshold = -1;
1358 gc_duration = ZERO_TIME;
1359 exp_start_time = ZERO_TIME; // not known. Wall-clock hrtime (not zero based)
1360 last_event = ZERO_TIME; // not known. Wall-clock hrtime (not zero based)
1361 non_paused_time = 0; // 0 non-paused time (will sum as experiment is processed)
1362 resume_ts = 0; // by default, collection is "resumed" (not paused) from time=0
1363 need_swap_endian = false;
1364 exp_rel_start_time_set = false;
1365 exp_rel_start_time = ZERO_TIME;
1367 hex_field_width = 8;
1368 hw_cpuver = CPUVER_UNDEFINED;
1369 machinemodel = NULL;
1372 fndr_arch_name = NULL;
1373 dyntext_name = NULL;
1376 dataDscrs = new Vector<DataDescriptor*>;
1377 for (int i = 0; i < DATA_LAST; ++i)
1378 dataDscrs->append (NULL);
1380 pcktDscrs = new Vector<PacketDescriptor*>;
1381 blksz = PROFILE_BUFFER_CHUNK;
1382 jthreads = new Vector<JThread*>;
1383 jthreads_idx = new Vector<JThread*>;
1384 gcevents = new Vector<GCEvent*>;
1385 gcevent_last_used = (GCEvent *) NULL;
1386 heapUnmapEvents = new Vector<UnmapChunk*>;
1388 cstackShowHide = NULL;
1389 frmpckts = new Vector<RawFramePacket*>;
1390 typedef DefaultMap2D<uint32_t, hrtime_t, uint64_t> OmpMap0;
1391 mapPRid = new OmpMap0 (OmpMap0::Interval);
1392 typedef DefaultMap2D<uint32_t, hrtime_t, void*> OmpMap;
1393 mapPReg = new OmpMap (OmpMap::Interval);
1394 mapTask = new OmpMap (OmpMap::Interval);
1401 uidnodes = new Vector<UIDnode*>;
1402 mrecs = new Vector<MapRecord*>;
1403 samples = new Vector<Sample*>;
1404 sample_last_used = (Sample *) NULL;
1405 first_sample_label = (char*) NULL;
1408 resolveFrameInfo = true;
1409 discardTiny = false;
1413 Experiment::~Experiment ()
1416 free (coll_params.linetrace);
1417 for (int i = 0; i < MAX_HWCOUNT; i++)
1419 free (coll_params.hw_aux_name[i]);
1420 free (coll_params.hw_username[i]);
1424 free (architecture);
1435 free (fndr_arch_name);
1436 free (dyntext_name);
1437 delete jthreads_idx;
1439 delete cstackShowHide;
1444 destroy_map (DbeFile *, archiveMap);
1448 delete children_exps;
1452 free (first_sample_label);
1453 free (machinemodel);
1455 dataDscrs->destroy ();
1457 pcktDscrs->destroy ();
1459 jthreads->destroy ();
1461 gcevents->destroy ();
1463 heapUnmapEvents->destroy ();
1464 delete heapUnmapEvents;
1465 frmpckts->destroy ();
1467 samples->destroy ();
1472 for (long i = 0; i < nchunks; i++)
1478 Experiment::init_cache ()
1482 smemHTable = new SegMem*[HTableSize];
1483 instHTable = new DbeInstr*[HTableSize];
1484 for (int i = 0; i < HTableSize; i++)
1486 smemHTable[i] = NULL;
1487 instHTable[i] = NULL;
1489 uidHTable = new UIDnode*[HTableSize];
1490 for (int i = 0; i < HTableSize; i++)
1491 uidHTable[i] = NULL;
1493 cstack = CallStack::getInstance (this);
1494 cstackShowHide = CallStack::getInstance (this);
1501 seg_items = new Vector<SegMem*>;
1502 maps = new PRBTree ();
1503 jmaps = NULL; // used by JAVA_CLASSES only
1507 min_thread = (uint64_t) - 1;
1510 min_lwp = (uint64_t) - 1;
1513 min_cpu = (uint64_t) - 1;
1517 commentq = new Emsgqueue (NTXT ("commentq"));
1518 runlogq = new Emsgqueue (NTXT ("runlogq"));
1519 errorq = new Emsgqueue (NTXT ("errorq"));
1520 warnq = new Emsgqueue (NTXT ("warnq"));
1521 notesq = new Emsgqueue (NTXT ("notesq"));
1522 pprocq = new Emsgqueue (NTXT ("pprocq"));
1525 metrics = new Vector<BaseMetric*>;
1526 tagObjs = new Vector<Vector<Histable*>*>;
1527 tagObjs->store (PROP_THRID, new Vector<Histable*>);
1528 tagObjs->store (PROP_LWPID, new Vector<Histable*>);
1529 tagObjs->store (PROP_CPUID, new Vector<Histable*>);
1530 tagObjs->store (PROP_EXPID, new Vector<Histable*>);
1531 sparse_threads = false;
1537 seg_items->destroy ();
1541 delete[] smemHTable;
1542 delete[] instHTable;
1558 Vec_loop (BaseMetric*, metrics, index, mtr)
1560 dbeSession->drop_metric (mtr);
1563 tagObjs->fetch (PROP_THRID)->destroy ();
1564 tagObjs->fetch (PROP_LWPID)->destroy ();
1565 tagObjs->fetch (PROP_CPUID)->destroy ();
1566 tagObjs->fetch (PROP_EXPID)->destroy ();
1567 tagObjs->destroy ();
1571 // These are the data files which can be read in parallel
1572 // for multiple sub-experiments.
1573 // Postpone calling resolve_frame_info()
1575 Experiment::read_experiment_data (bool read_ahead)
1578 read_frameinfo_file ();
1581 resolveFrameInfo = false;
1582 (void) get_profile_events ();
1583 resolveFrameInfo = true;
1587 Experiment::Exp_status
1588 Experiment::open_epilogue ()
1591 // set up mapping for tagObj(PROP_EXPID)
1592 (void) mapTagValue (PROP_EXPID, userExpId);
1595 if (last_event != ZERO_TIME)
1596 { // if last_event is known
1598 hrtime_t ts = last_event - exp_start_time;
1599 sb.sprintf (GTXT ("Experiment Ended: %ld.%09ld\nData Collection Duration: %ld.%09ld"),
1600 (long) (ts / NANOSEC), (long) (ts % NANOSEC),
1601 (long) (non_paused_time / NANOSEC),
1602 (long) (non_paused_time % NANOSEC));
1603 runlogq->append (new Emsg (CMSG_COMMENT, sb));
1606 // Check for incomplete experiment, and inform the user
1607 if (status == INCOMPLETE)
1609 if (exec_started == true)
1610 // experiment ended with the exec, not abnormally
1614 char * cmnt = GTXT ("*** Note: experiment was not closed");
1615 commentq->append (new Emsg (CMSG_COMMENT, cmnt));
1616 // runlogq->append(new Emsg(CMSG_COMMENT, cmnt));
1619 // write a descriptive header for the experiment
1624 Experiment::Exp_status
1625 Experiment::open (char *path)
1628 // Find experiment directory
1629 if (find_expdir (path) != SUCCESS)
1630 // message will have been queued and status set
1633 // Get creation time for experiment
1635 if (dbe_stat (path, &st) == 0)
1636 mtime = st.st_mtime;
1638 // Read the warnings file
1641 // Open the log file
1643 if (status == SUCCESS && last_event // last event is initialized
1644 && (last_event - exp_start_time) / 1000000 < tiny_threshold)
1646 // Process "tiny_threshold" (SP_ANALYZER_DISCARD_TINY_EXPERIMENTS)
1647 // At this point, we've only processed log.xml.
1648 // Note: if an experiment terminated abnormally, last_event will not yet
1649 // represent events from clock profiling and other metrics.
1650 // Other events will often have timestamps after the last log.xml entry.
1654 if (status == FAILURE)
1656 if (logFile->get_status () == ExperimentFile::EF_FAILURE)
1658 Emsg *m = new Emsg (CMSG_FATAL, GTXT ("*** Error: log file in experiment cannot be read"));
1661 else if (fetch_errors () == NULL)
1665 Emsg *m = new Emsg (CMSG_FATAL, GTXT ("*** Error: log does not show target starting"));
1670 Emsg *m = new Emsg (CMSG_FATAL, GTXT ("*** Error: log file in experiment could not be parsed"));
1681 GTXT ("*** Warning: system has variable clock frequency, which may cause variable execution times and inaccurate conversions of cycle counts into time."));
1682 warnq->append (new Emsg (CMSG_WARN, sb));
1685 // Read the notes file
1687 read_labels_file ();
1690 // The log file shows experiment started
1691 read_java_classes_file ();
1695 // Dyntext file has to be processed after loadobjects file
1696 // as we need to be able to map (vaddr,ts) to dynamic functions.
1697 read_dyntext_file ();
1699 // Read the overview file and create samples.
1700 // Profiling data hasn't been read yet so we may have
1701 // events after the last recorded sample.
1702 // We'll create a fake sample to cover all those
1704 read_overview_file ();
1706 // Check if instruction frequency data is available
1709 // Check if OMP data is available
1715 /* XXX -- update() is a no-op now, but may be needed for auto-update */
1716 Experiment::Exp_status
1717 Experiment::update ()
1723 Experiment::append (LoadObject *lo)
1725 loadObjs->append (lo);
1726 char *obj_name = lo->get_pathname ();
1727 char *bname = get_basename (obj_name);
1728 loadObjMap->put (obj_name, lo);
1729 loadObjMap->put (bname, lo);
1730 if (lo->flags & SEG_FLAG_EXE)
1731 loadObjMap->put (COMP_EXE_NAME, lo);
1735 Experiment::read_notes_file ()
1740 char *fname = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_NOTES_FILE);
1741 FILE *f = fopen (fname, NTXT ("r"));
1745 if (!dbeSession->is_interactive ())
1747 m = new Emsg (CMSG_COMMENT, NTXT ("Notes:"));
1753 char str[MAXPATHLEN];
1754 char *e = fgets (str, ((int) sizeof (str)) - 1, f);
1757 if (!dbeSession->is_interactive ())
1759 m = new Emsg (CMSG_COMMENT,
1760 "============================================================");
1765 size_t i = strlen (str);
1766 if (i > 0 && str[i - 1] == '\n')
1767 // remove trailing nl
1769 m = new Emsg (CMSG_COMMENT, str);
1776 Experiment::save_notes (char* text, bool handle_file)
1781 char *fname = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_NOTES_FILE);
1782 fnotes = fopen (fname, NTXT ("w"));
1786 (void) fprintf (fnotes, NTXT ("%s"), text);
1790 return 1; // Cannot write file
1793 Emsg *m = new Emsg (CMSG_COMMENT, text);
1800 Experiment::delete_notes (bool handle_file)
1804 char *fname = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_NOTES_FILE);
1805 if (unlink (fname) != 0)
1808 return 1; // Cannot delete file
1817 Experiment::read_warn_file ()
1819 int local_status = SUCCESS;
1821 ExperimentFile *warnFile = new ExperimentFile (this, SP_WARN_FILE);
1822 if (warnFile == NULL)
1824 if (!warnFile->open ())
1829 SAXParserFactory *factory = SAXParserFactory::newInstance ();
1830 SAXParser *saxParser = factory->newSAXParser ();
1831 DefaultHandler *dh = new ExperimentHandler (this);
1834 saxParser->parse ((File*) warnFile->fh, dh);
1836 catch (SAXException *e)
1838 // Fatal error in the parser
1840 sb.sprintf (NTXT ("%s: %s"), SP_WARN_FILE, e->getMessage ());
1841 char *str = sb.toString ();
1842 Emsg *m = new Emsg (CMSG_FATAL, str);
1844 local_status = FAILURE;
1852 return local_status;
1856 Experiment::read_log_file ()
1858 if (logFile == NULL)
1859 logFile = new ExperimentFile (this, SP_LOG_FILE);
1860 if (!logFile->open ())
1866 SAXParserFactory *factory = SAXParserFactory::newInstance ();
1867 SAXParser *saxParser = factory->newSAXParser ();
1868 DefaultHandler *dh = new ExperimentHandler (this);
1871 saxParser->parse ((File*) logFile->fh, dh);
1873 catch (SAXException *e)
1875 // Fatal error in the parser
1878 sb.sprintf (NTXT ("%s"), e->getMessage ());
1880 sb.sprintf (NTXT ("%s: %s"), SP_LOG_FILE, e->getMessage ());
1881 char *str = sb.toString ();
1882 Emsg *m = new Emsg (CMSG_FATAL, str);
1888 dbeSession->register_metric (GTXT ("IPC"), GTXT ("Instructions Per Cycle"),
1889 NTXT ("insts/cycles"));
1890 dbeSession->register_metric (GTXT ("CPI"), GTXT ("Cycles Per Instruction"),
1891 NTXT ("cycles/insts"));
1892 dbeSession->register_metric (GTXT ("K_IPC"),
1893 GTXT ("Kernel Instructions Per Cycle"),
1894 NTXT ("K_insts/K_cycles"));
1895 dbeSession->register_metric (GTXT ("K_CPI"),
1896 GTXT ("Kernel Cycles Per Instruction"),
1897 NTXT ("K_cycles/K_insts"));
1906 ////////////////////////////////////////////////////////////////////////////////
1907 // class Experiment::ExperimentLabelsHandler
1910 class Experiment::ExperimentLabelsHandler : public DefaultHandler
1914 ExperimentLabelsHandler (Experiment *_exp)
1919 ~ExperimentLabelsHandler () { };
1920 void startDocument () { }
1921 void endDocument () { }
1922 void endElement (char * /*uri*/, char * /*localName*/, char * /*qName*/) { }
1923 void characters (char * /*ch*/, int /*start*/, int /*length*/) { }
1924 void ignorableWhitespace (char*, int, int) { }
1925 void error (SAXParseException * /*e*/) { }
1927 void startElement (char *uri, char *localName, char *qName, Attributes *attrs);
1934 return s ? s : "NULL";
1939 hrtime_t time, tstamp;
1943 Experiment::ExperimentLabelsHandler::startElement (char*, char*, char *qName,
1946 DEBUG_CODE if (DEBUG_SAXPARSER) dump_startElement (qName, attrs);
1947 if (qName == NULL || strcmp (qName, NTXT ("id")) != 0)
1949 char *name = NULL, *all_times = NULL, *comment = NULL, *hostName = NULL;
1951 // long tm_zone = 0;
1952 hrtime_t startHrtime = (hrtime_t) 0;
1953 long long lbl_ts = 0;
1956 start_tv.tv_usec = start_tv.tv_sec = 0;
1957 for (int i = 0, sz = attrs ? attrs->getLength () : 0; i < sz; i++)
1959 const char *qn = attrs->getQName (i);
1960 const char *vl = attrs->getValue (i);
1961 if (strcmp (qn, NTXT ("name")) == 0)
1962 name = dbe_xml2str (vl);
1963 else if (strcmp (qn, NTXT ("cmd")) == 0)
1964 all_times = dbe_xml2str (vl);
1965 else if (strcmp (qn, NTXT ("comment")) == 0)
1966 comment = dbe_xml2str (vl);
1967 else if (strcmp (qn, NTXT ("relative")) == 0)
1968 relative = atoi (vl);
1969 else if (strcmp (qn, NTXT ("hostname")) == 0)
1970 hostName = dbe_xml2str (vl);
1971 else if (strcmp (qn, NTXT ("time")) == 0)
1972 startSec = atol (vl);
1973 else if (strcmp (qn, NTXT ("tstamp")) == 0)
1974 startHrtime = parseTStamp (vl);
1975 else if (strcmp (qn, NTXT ("lbl_ts")) == 0)
1978 lbl_ts = -parseTStamp (vl + 1);
1980 lbl_ts = parseTStamp (vl);
1983 if (name == NULL || hostName == NULL || (all_times == NULL && comment == NULL))
1991 UserLabel *lbl = new UserLabel (name);
1992 lbl->comment = comment;
1993 lbl->hostname = hostName;
1994 lbl->start_sec = startSec;
1995 lbl->start_hrtime = startHrtime;
1996 exp->userLabels->append (lbl);
1999 lbl->all_times = all_times;
2000 lbl->start_tv = start_tv;
2001 lbl->relative = relative;
2002 if (relative == UserLabel::REL_TIME)
2003 lbl->atime = lbl_ts;
2005 { // relative == UserLabel::CUR_TIME
2006 long long delta = 0;
2007 if (exp->hostname && strcmp (lbl->hostname, exp->hostname) == 0)
2008 delta = lbl_ts + (lbl->start_hrtime - exp->exp_start_time);
2010 for (int i = 0; i < exp->userLabels->size (); i++)
2012 UserLabel *firstLbl = exp->userLabels->fetch (i);
2013 if (strcmp (lbl->hostname, firstLbl->hostname) == 0)
2015 delta = lbl_ts + (lbl->start_hrtime - firstLbl->start_hrtime) +
2016 ((long long) (firstLbl->start_sec - exp->start_sec)) * NANOSEC;
2020 lbl->atime = delta > 0 ? delta : 0;
2026 sortUserLabels (const void *a, const void *b)
2028 UserLabel *l1 = *((UserLabel **) a);
2029 UserLabel *l2 = *((UserLabel **) b);
2030 int v = dbe_strcmp (l1->name, l2->name);
2033 if (l1->atime < l2->atime)
2035 else if (l1->atime > l2->atime)
2037 if (l1->id < l2->id)
2039 else if (l1->id > l2->id)
2045 append_string (char *s, char *str)
2048 return dbe_strdup (str);
2049 char *new_s = dbe_sprintf (NTXT ("%s %s"), s, str);
2055 Experiment::read_labels_file ()
2057 ExperimentFile *fp = new ExperimentFile (this, SP_LABELS_FILE);
2063 userLabels = new Vector<UserLabel*>();
2064 SAXParserFactory *factory = SAXParserFactory::newInstance ();
2065 SAXParser *saxParser = factory->newSAXParser ();
2066 DefaultHandler *dh = new ExperimentLabelsHandler (this);
2069 saxParser->parse ((File*) fp->fh, dh);
2071 catch (SAXException *e)
2073 // Fatal error in the parser
2075 sb.sprintf (NTXT ("%s: %s"), SP_LABELS_FILE, e->getMessage ());
2076 char *str = sb.toString ();
2077 Emsg *m = new Emsg (CMSG_FATAL, str);
2087 userLabels->sort (sortUserLabels);
2088 UserLabel::dump ("After sortUserLabels:", userLabels);
2089 UserLabel *ulbl = NULL;
2090 for (int i = 0, sz = userLabels->size (); i < sz; i++)
2092 UserLabel *lbl = userLabels->fetch (i);
2094 ulbl = new UserLabel (lbl->name);
2095 else if (dbe_strcmp (lbl->name, ulbl->name) != 0)
2097 ulbl->register_user_label (groupId);
2098 if (ulbl->expr == NULL)
2100 ulbl = new UserLabel (lbl->name);
2104 if (strncmp (lbl->all_times, NTXT ("start"), 5) == 0)
2108 ulbl->start_f = true;
2109 ulbl->timeStart = lbl->atime;
2116 ulbl->all_times = append_string (ulbl->all_times, lbl->all_times);
2117 ulbl->stop_f = true;
2118 ulbl->timeStop = lbl->atime;
2122 if (lbl->comment != NULL)
2123 ulbl->comment = append_string (ulbl->comment, lbl->comment);
2127 ulbl->register_user_label (groupId);
2128 if (ulbl->expr == NULL)
2131 Destroy (userLabels);
2135 Experiment::read_archives ()
2139 char *allocated_str = NULL;
2140 char *nm = get_arch_name ();
2141 DIR *exp_dir = opendir (nm);
2142 if (exp_dir == NULL)
2144 if (founder_exp == NULL)
2146 // Check if the user uses a subexperiment only
2147 nm = dbe_sprintf (NTXT ("%s/../%s"), expt_name, SP_ARCHIVES_DIR);
2148 exp_dir = opendir (nm);
2149 if (exp_dir == NULL)
2163 int dlen = sb.length ();
2164 free (allocated_str);
2165 archiveMap = new StringMap<DbeFile *>();
2167 struct dirent *entry = NULL;
2168 while ((entry = readdir (exp_dir)) != NULL)
2170 char *dname = entry->d_name;
2172 && (dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0')))
2173 // skip links to ./ or ../
2175 sb.setLength (dlen);
2177 char *fnm = sb.toString ();
2178 DbeFile *df = new DbeFile (fnm);
2179 df->set_location (fnm);
2180 df->filetype |= DbeFile::F_FILE;
2181 df->inArchive = true;
2182 df->experiment = this;
2183 archiveMap->put (dname, df);
2190 gen_file_name (const char *packet_name, const char *src_name)
2192 char *fnm, *bname = get_basename (packet_name);
2193 if (bname == packet_name)
2194 fnm = dbe_strdup (src_name);
2196 fnm = dbe_sprintf ("%.*s%s", (int) (bname - packet_name),
2197 packet_name, src_name);
2199 // convert "java.lang.Object/Integer.java" => "java/lang/Object/Integer.java"
2200 bname = get_basename (fnm);
2201 for (char *s = fnm; s < bname; s++)
2208 get_jlass_name (const char *nm)
2210 // Convert "Ljava/lang/Object;" => "java/lang/Object.class"
2213 size_t len = strlen (nm);
2214 if (nm[len - 1] == ';')
2215 return dbe_sprintf ("%.*s.class", (int) (len - 2), nm + 1);
2217 return dbe_strdup (nm);
2221 get_jmodule_name (const char *nm)
2223 // convert "Ljava/lang/Object;" => "java.lang.Object"
2226 size_t len = strlen (nm);
2227 if (nm[len - 1] == ';')
2229 char *mname = dbe_sprintf (NTXT ("%.*s"), (int) (len - 2), nm + 1);
2230 for (char *s = mname; *s; s++)
2236 return dbe_strdup (nm);
2240 Experiment::get_j_lo (const char *className, const char *fileName)
2242 char *class_name = get_jlass_name (className);
2243 Dprintf (DUMP_JCLASS_READER,
2244 "Experiment::get_j_lo: className='%s' class_name='%s' fileName='%s'\n",
2245 STR (className), STR (class_name), STR (fileName));
2246 LoadObject *lo = loadObjMap->get (class_name);
2249 lo = createLoadObject (class_name, fileName);
2250 lo->type = LoadObject::SEG_TEXT;
2251 lo->mtime = (time_t) 0;
2253 lo->set_platform (Java, wsize);
2254 lo->dbeFile->filetype |= DbeFile::F_FILE | DbeFile::F_JAVACLASS;
2256 Dprintf (DUMP_JCLASS_READER,
2257 "Experiment::get_j_lo: creates '%s' location='%s'\n",
2258 STR (lo->get_name ()), STR (lo->dbeFile->get_location (false)));
2265 Experiment::get_jclass (const char *className, const char *fileName)
2267 LoadObject *lo = get_j_lo (className, NULL);
2268 char *mod_name = get_jmodule_name (className);
2269 Module *mod = lo->find_module (mod_name);
2272 mod = dbeSession->createClassFile (mod_name);
2273 mod->loadobject = lo;
2274 if (strcmp (fileName, NTXT ("<Unknown>")) != 0)
2275 mod->set_file_name (gen_file_name (lo->get_pathname (), fileName));
2277 mod->set_file_name (dbe_strdup (fileName));
2278 lo->append_module (mod);
2281 else if (mod->file_name && (strcmp (mod->file_name, "<Unknown>") == 0)
2282 && strcmp (fileName, "<Unknown>") != 0)
2283 mod->set_file_name (gen_file_name (lo->get_pathname (), fileName));
2284 Dprintf (DUMP_JCLASS_READER,
2285 "Experiment::get_jclass: class_name='%s' mod_name='%s' fileName='%s'\n",
2286 mod->loadobject->get_pathname (), mod->get_name (), mod->file_name);
2291 #define ARCH_STRLEN(s) ( ( strlen(s) + 4 ) & ~0x3 )
2294 Experiment::read_java_classes_file ()
2296 char *data_file_name = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_JCLASSES_FILE);
2297 Data_window *dwin = new Data_window (data_file_name);
2298 free (data_file_name);
2299 if (dwin->not_opened ())
2304 dwin->need_swap_endian = need_swap_endian;
2305 jmaps = new PRBTree ();
2306 jmidHTable = new DbeCacheMap<unsigned long long, JMethod>;
2308 hrtime_t cur_loaded = 0;
2309 Module *cur_mod = NULL;
2310 for (int64_t offset = 0;;)
2312 CM_Packet *cpkt = (CM_Packet*) dwin->bind (offset, sizeof (CM_Packet));
2315 uint16_t v16 = (uint16_t) cpkt->tsize;
2316 size_t cpktsize = dwin->decode (v16);
2317 cpkt = (CM_Packet*) dwin->bind (offset, cpktsize);
2318 if ((cpkt == NULL) || (cpktsize == 0))
2320 char *buf = dbe_sprintf (GTXT ("archive file malformed %s"),
2322 errorq->append (new Emsg (CMSG_ERROR, buf));
2326 v16 = (uint16_t) cpkt->type;
2327 v16 = dwin->decode (v16);
2332 ARCH_jclass *ajcl = (ARCH_jclass*) cpkt;
2333 uint64_t class_id = dwin->decode (ajcl->class_id);
2334 char *className = ((char*) ajcl) + sizeof (*ajcl);
2335 char *fileName = className + ARCH_STRLEN (className);
2336 Dprintf (DUMP_JCLASS_READER,
2337 "read_java_classes_file: ARCH_JCLASS(Ox%x)"
2338 "class_id=Ox%llx className='%s' fileName='%s' \n",
2339 (int) v16, (long long) class_id, className, fileName);
2341 if (*className == 'L')
2342 { // Old libcollector generated '[' (one array dimension).
2343 cur_mod = get_jclass (className, fileName);
2344 cur_loaded = dwin->decode (ajcl->tstamp);
2345 jmaps->insert (class_id, cur_loaded, cur_mod);
2349 case ARCH_JCLASS_LOCATION:
2351 ARCH_jclass_location *ajcl = (ARCH_jclass_location *) cpkt;
2352 uint64_t class_id = dwin->decode (ajcl->class_id);
2353 char *className = ((char*) ajcl) + sizeof (*ajcl);
2354 char *fileName = className + ARCH_STRLEN (className);
2355 Dprintf (DUMP_JCLASS_READER,
2356 "read_java_classes_file: ARCH_JCLASS_LOCATION(Ox%x)"
2357 "class_id=Ox%llx className='%s' fileName='%s' \n",
2358 (int) v16, (long long) class_id, className, fileName);
2359 get_j_lo (className, fileName);
2364 if (cur_mod == NULL)
2366 ARCH_jmethod *ajmt = (ARCH_jmethod*) cpkt;
2367 uint64_t method_id = dwin->decode (ajmt->method_id);
2368 char *s_name = ((char*) ajmt) + sizeof (*ajmt);
2369 char *s_signature = s_name + ARCH_STRLEN (s_name);
2370 char *fullname = dbe_sprintf ("%s.%s", cur_mod->get_name (), s_name);
2371 Dprintf (DUMP_JCLASS_READER,
2372 "read_java_classes_file: ARCH_JMETHOD(Ox%x) "
2373 "method_id=Ox%llx name='%s' signature='%s' fullname='%s'\n",
2374 (int) v16, (long long) method_id, s_name,
2375 s_signature, fullname);
2376 JMethod *jmthd = cur_mod->find_jmethod (fullname, s_signature);
2379 jmthd = dbeSession->createJMethod ();
2380 jmthd->size = (unsigned) - 1; // unknown until later (maybe)
2381 jmthd->module = cur_mod;
2382 jmthd->set_signature (s_signature);
2383 jmthd->set_name (fullname);
2384 cur_mod->functions->append (jmthd);
2385 cur_mod->loadobject->functions->append (jmthd);
2386 Dprintf (DUMP_JCLASS_READER,
2387 "read_java_classes_file: ARCH_JMETHOD CREATE fullname=%s\n",
2390 jmaps->insert (method_id, cur_loaded, jmthd);
2395 Dprintf (DUMP_JCLASS_READER,
2396 "read_java_classes_file: type=Ox%x (%d) cpktsize=%d\n",
2397 (int) v16, (int) v16, (int) cpktsize);
2398 break; // ignore unknown packets
2407 Experiment::read_map_file ()
2409 ExperimentFile *mapFile = new ExperimentFile (this, SP_MAP_FILE);
2410 if (!mapFile->open ())
2416 SAXParserFactory *factory = SAXParserFactory::newInstance ();
2417 SAXParser *saxParser = factory->newSAXParser ();
2418 DefaultHandler *dh = new ExperimentHandler (this);
2421 saxParser->parse ((File*) mapFile->fh, dh);
2423 catch (SAXException *e)
2425 // Fatal error in the parser
2427 sb.sprintf (NTXT ("%s: %s"), SP_MAP_FILE, e->getMessage ());
2428 char *str = sb.toString ();
2429 Emsg *m = new Emsg (CMSG_FATAL, str);
2440 for (int i = 0, sz = mrecs ? mrecs->size () : 0; i < sz; i++)
2442 MapRecord *mrec = mrecs->fetch (i);
2443 SegMem *smem, *sm_lo, *sm_hi;
2446 case MapRecord::LOAD:
2448 smem->base = mrec->base;
2449 smem->size = mrec->size;
2450 smem->load_time = mrec->ts;
2451 smem->unload_time = MAX_TIME;
2452 smem->obj = mrec->obj;
2453 smem->set_file_offset (mrec->foff);
2454 seg_items->append (smem); // add to the master list
2456 // Check if the new segment overlaps other active segments
2457 sm_lo = (SegMem*) maps->locate (smem->base, smem->load_time);
2458 if (sm_lo && sm_lo->base + sm_lo->size > smem->base)
2460 // check to see if it is a duplicate record: same address and size, and
2461 if ((smem->base == sm_lo->base) && (smem->size == sm_lo->size))
2463 // addresses and sizes match, check name
2464 if (strstr (smem->obj->get_name (), sm_lo->obj->get_name ()) != NULL
2465 || strstr (sm_lo->obj->get_name (), smem->obj->get_name ()) != NULL)
2466 // this is a duplicate; just move on the the next map record
2469 GTXT ("*** Warning: Segment `%s' loaded with same address, size as `%s' [0x%llx-0x%llx]\n"),
2470 smem->obj->get_name (), sm_lo->obj->get_name (),
2471 sm_lo->base, sm_lo->base + sm_lo->size);
2474 // Not a duplicate; implicitly unload the old one
2475 // Note: implicit unloading causes high <Unknown>
2476 // when such overlapping is bogus
2478 sb.sprintf (GTXT ("*** Warning: Segment %s [0x%llx-0x%llx] overlaps %s [0x%llx-0x%llx], which has been implicitly unloaded"),
2479 smem->obj->get_name (), smem->base, smem->base + smem->size,
2480 sm_lo->obj->get_name (), sm_lo->base, sm_lo->base + sm_lo->size);
2481 warnq->append (new Emsg (CMSG_WARN, sb));
2484 // now look for other segments with which this might overlap
2485 sm_hi = (SegMem*) maps->locate_up (smem->base, smem->load_time);
2486 while (sm_hi && sm_hi->base < smem->base + smem->size)
2489 // Note: implicit unloading causes high <Unknown> when such overlapping is bogus
2490 // maps->remove( sm_hi->base, smem->load_time );
2492 sb.sprintf (GTXT ("*** Warning: Segment %s [0x%llx-0x%llx] overlaps %s [0x%llx-0x%llx], which has been implicitly unloaded"),
2493 smem->obj->get_name (), smem->base,
2494 smem->base + smem->size, sm_hi->obj->get_name (),
2495 sm_hi->base, sm_hi->base + sm_hi->size);
2496 warnq->append (new Emsg (CMSG_WARN, sb));
2497 sm_hi = (SegMem*) maps->locate_up (sm_hi->base + sm_hi->size,
2501 maps->insert (smem->base, smem->load_time, smem);
2503 case MapRecord::UNLOAD:
2504 smem = (SegMem*) maps->locate (mrec->base, mrec->ts);
2505 if (smem && smem->base == mrec->base)
2507 smem->unload_time = mrec->ts;
2508 maps->remove (mrec->base, mrec->ts);
2515 // See if there are comments or warnings for a load object;
2516 // if so, queue them to Experiment
2517 for (long i = 0, sz = loadObjs ? loadObjs->size () : 0; i < sz; i++)
2519 LoadObject *lo = loadObjs->get (i);
2520 for (Emsg *m = lo->fetch_warnings (); m; m = m->next)
2521 warnq->append (m->get_warn (), m->get_msg ());
2522 for (Emsg *m = lo->fetch_comments (); m; m = m->next)
2523 commentq->append (m->get_warn (), m->get_msg ());
2528 Experiment::read_frameinfo_file ()
2531 char *base_name = get_basename (expt_name);
2532 char *msg = dbe_sprintf (GTXT ("Loading CallStack Data: %s"), base_name);
2533 read_data_file ("data." SP_FRINFO_FILE, msg);
2535 frmpckts->sort (frUidCmp);
2536 uidnodes->sort (uidNodeCmp);
2540 Experiment::read_omp_preg ()
2542 // Parallel region descriptions
2543 DataDescriptor *pregDdscr = getDataDescriptor (DATA_OMP4);
2544 if (pregDdscr == NULL)
2546 DataView *pregData = pregDdscr->createView ();
2547 pregData->sort (PROP_CPRID); // omptrace PROP_CPRID
2549 // OpenMP enter parreg events
2550 DataDescriptor *dDscr = getDataDescriptor (DATA_OMP2);
2551 if (dDscr == NULL || dDscr->getSize () == 0)
2557 char *idxname = NTXT ("OMP_preg");
2558 delete dbeSession->indxobj_define (idxname, GTXT ("OpenMP Parallel Region"),
2559 NTXT ("CPRID"), NULL, NULL);
2560 int idxtype = dbeSession->findIndexSpaceByName (idxname);
2568 // Pre-create parallel region with id == 0
2569 Histable *preg0 = dbeSession->createIndexObject (idxtype, (int64_t) 0);
2570 preg0->set_name (dbe_strdup (GTXT ("Implicit OpenMP Parallel Region")));
2572 // Take care of the progress bar
2573 char *msg = dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"),
2574 get_basename (expt_name));
2575 theApplication->set_progress (0, msg);
2577 long deltaReport = 1000;
2578 long nextReport = 0;
2579 long errors_found = 0;
2580 Vector<Histable*> pregs;
2582 long size = dDscr->getSize ();
2583 for (long i = 0; i < size; ++i)
2585 if (i == nextReport)
2587 int percent = (int) (i * 100 / size);
2589 theApplication->set_progress (percent, NULL);
2590 nextReport += deltaReport;
2593 uint32_t thrid = dDscr->getIntValue (PROP_THRID, i);
2594 hrtime_t tstamp = dDscr->getLongValue (PROP_TSTAMP, i);
2595 uint64_t cprid = dDscr->getLongValue (PROP_CPRID, i); // omptrace CPRID
2596 mapPRid->put (thrid, tstamp, cprid);
2600 * We will use 2 pointers to make sure there is no loop.
2601 * First pointer "curpreg" goes to the next element,
2602 * second pointer "curpreg_loop_control" goes to the next->next element.
2603 * If these pointers have the same value - there is a loop.
2605 uint64_t curpreg_loop_control = cprid;
2606 Datum tval_loop_control;
2607 if (curpreg_loop_control != 0)
2609 tval_loop_control.setUINT64 (curpreg_loop_control);
2610 long idx = pregData->getIdxByVals (&tval_loop_control, DataView::REL_EQ);
2612 curpreg_loop_control = 0;
2614 curpreg_loop_control = pregData->getLongValue (PROP_PPRID, idx);
2616 for (uint64_t curpreg = cprid; curpreg != 0;)
2618 Histable *val = NULL;
2620 tval.setUINT64 (curpreg);
2621 long idx = pregData->getIdxByVals (&tval, DataView::REL_EQ);
2625 * Check if there is a loop
2627 if (0 != curpreg_loop_control)
2629 if (curpreg == curpreg_loop_control)
2632 if (1 == errors_found)
2634 Emsg *m = new Emsg (CMSG_WARN, GTXT ("*** Warning: circular links in OMP regions; data may not be correct."));
2640 uint64_t pragmapc = pregData->getLongValue (PROP_PRPC, idx);
2641 DbeInstr *instr = map_Vaddr_to_PC (pragmapc, tstamp);
2647 DbeLine *dbeline = (DbeLine*) instr->convertto (Histable::LINE);
2648 if (dbeline->lineno > 0)
2650 if (instr->func->usrfunc)
2651 dbeline = dbeline->sourceFile->find_dbeline
2652 (instr->func->usrfunc, dbeline->lineno);
2653 dbeline->set_flag (DbeLine::OMPPRAGMA);
2656 val = dbeSession->createIndexObject (idxtype, val);
2659 curpreg = pregData->getLongValue (PROP_PPRID, idx);
2661 * Update curpreg_loop_control
2663 if (0 != curpreg_loop_control)
2665 tval_loop_control.setUINT64 (curpreg_loop_control);
2666 idx = pregData->getIdxByVals
2667 (&tval_loop_control, DataView::REL_EQ);
2669 curpreg_loop_control = 0;
2672 curpreg_loop_control = pregData->getLongValue
2674 tval_loop_control.setUINT64 (curpreg_loop_control);
2675 idx = pregData->getIdxByVals
2676 (&tval_loop_control, DataView::REL_EQ);
2678 curpreg_loop_control = 0;
2680 curpreg_loop_control = pregData->getLongValue
2685 pregs.append (preg0);
2686 void *prstack = cstack->add_stack (&pregs);
2687 mapPReg->put (thrid, tstamp, prstack);
2689 theApplication->set_progress (0, NTXT (""));
2694 Experiment::read_omp_task ()
2697 DataDescriptor *taskDataDdscr = getDataDescriptor (DATA_OMP5);
2698 if (taskDataDdscr == NULL)
2701 //7035272: previously, DataView was global; now it's local...is this OK?
2702 DataView *taskData = taskDataDdscr->createView ();
2703 taskData->sort (PROP_TSKID); // omptrace PROP_TSKID
2705 // OpenMP enter task events
2706 DataDescriptor *dDscr = getDataDescriptor (DATA_OMP3);
2707 if (dDscr == NULL || dDscr->getSize () == 0)
2713 char *idxname = NTXT ("OMP_task");
2714 // delete a possible error message. Ugly.
2715 delete dbeSession->indxobj_define (idxname, GTXT ("OpenMP Task"), NTXT ("TSKID"), NULL, NULL);
2716 int idxtype = dbeSession->findIndexSpaceByName (idxname);
2724 // Pre-create task with id == 0
2725 Histable *task0 = dbeSession->createIndexObject (idxtype, (int64_t) 0);
2726 task0->set_name (dbe_strdup (GTXT ("OpenMP Task from Implicit Parallel Region")));
2728 // Take care of the progress bar
2729 char *msg = dbe_sprintf (GTXT ("Processing OpenMP Task Data: %s"), get_basename (expt_name));
2730 theApplication->set_progress (0, msg);
2732 long deltaReport = 1000;
2733 long nextReport = 0;
2735 Vector<Histable*> tasks;
2736 long size = dDscr->getSize ();
2737 long errors_found = 0;
2738 for (long i = 0; i < size; ++i)
2740 if (i == nextReport)
2742 int percent = (int) (i * 100 / size);
2744 theApplication->set_progress (percent, NULL);
2745 nextReport += deltaReport;
2748 uint32_t thrid = dDscr->getIntValue (PROP_THRID, i);
2749 hrtime_t tstamp = dDscr->getLongValue (PROP_TSTAMP, i);
2750 uint64_t tskid = dDscr->getLongValue (PROP_TSKID, i); //omptrace TSKID
2753 * We will use 2 pointers to make sure there is no loop.
2754 * First pointer "curtsk" goes to the next element,
2755 * second pointer "curtsk_loop_control" goes to the next->next element.
2756 * If these pointers have the same value - there is a loop.
2758 uint64_t curtsk_loop_control = tskid;
2759 Datum tval_loop_control;
2760 if (curtsk_loop_control != 0)
2762 tval_loop_control.setUINT64 (curtsk_loop_control);
2763 long idx = taskData->getIdxByVals (&tval_loop_control, DataView::REL_EQ);
2765 curtsk_loop_control = 0;
2767 curtsk_loop_control = taskData->getLongValue (PROP_PTSKID, idx);
2769 for (uint64_t curtsk = tskid; curtsk != 0;)
2771 Histable *val = NULL;
2774 tval.setUINT64 (curtsk);
2775 long idx = taskData->getIdxByVals (&tval, DataView::REL_EQ);
2779 * Check if there is a loop
2781 if (0 != curtsk_loop_control)
2783 if (curtsk == curtsk_loop_control)
2786 if (1 == errors_found)
2788 Emsg *m = new Emsg (CMSG_WARN, GTXT ("*** Warning: circular links in OMP tasks; data may not be correct."));
2794 uint64_t pragmapc = taskData->getLongValue (PROP_PRPC, idx);
2795 DbeInstr *instr = map_Vaddr_to_PC (pragmapc, tstamp);
2799 DbeLine *dbeline = (DbeLine*) instr->convertto (Histable::LINE);
2800 if (dbeline->lineno > 0)
2802 if (instr->func->usrfunc)
2803 dbeline = dbeline->sourceFile->find_dbeline
2804 (instr->func->usrfunc, dbeline->lineno);
2805 dbeline->set_flag (DbeLine::OMPPRAGMA);
2808 val = dbeSession->createIndexObject (idxtype, val);
2811 curtsk = taskData->getLongValue (PROP_PTSKID, idx);
2813 * Update curtsk_loop_control
2815 if (0 != curtsk_loop_control)
2817 tval_loop_control.setUINT64 (curtsk_loop_control);
2818 idx = taskData->getIdxByVals (&tval_loop_control, DataView::REL_EQ);
2820 curtsk_loop_control = 0;
2823 curtsk_loop_control = taskData->getLongValue (PROP_PTSKID, idx);
2824 tval_loop_control.setUINT64 (curtsk_loop_control);
2825 idx = taskData->getIdxByVals (&tval_loop_control,
2828 curtsk_loop_control = 0;
2830 curtsk_loop_control = taskData->getLongValue (PROP_PTSKID,
2835 tasks.append (task0);
2836 void *tskstack = cstack->add_stack (&tasks);
2837 mapTask->put (thrid, tstamp, tskstack);
2839 theApplication->set_progress (0, NTXT (""));
2844 Experiment::read_omp_file ()
2846 // DATA_OMP2 table is common between OpenMP 2.5 and 3.0 profiling
2847 DataDescriptor *dDscr = getDataDescriptor (DATA_OMP2);
2850 if (dDscr->getSize () == 0)
2852 char *base_name = get_basename (expt_name);
2853 char *msg = dbe_sprintf (GTXT ("Loading OpenMP Data: %s"), base_name);
2854 read_data_file (SP_OMPTRACE_FILE, msg);
2857 // OpenMP fork events
2858 dDscr = getDataDescriptor (DATA_OMP);
2859 long sz = dDscr->getSize ();
2863 msg = dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"),
2865 theApplication->set_progress (0, msg);
2867 long deltaReport = 5000;
2868 long nextReport = 0;
2869 for (int i = 0; i < sz; ++i)
2871 if (i == nextReport)
2873 int percent = (int) (i * 100 / sz);
2875 theApplication->set_progress (percent, NULL);
2876 nextReport += deltaReport;
2878 uint32_t thrid = dDscr->getIntValue (PROP_THRID, i);
2879 hrtime_t tstamp = dDscr->getLongValue (PROP_TSTAMP, i);
2880 uint64_t cprid = dDscr->getLongValue (PROP_CPRID, i); //omptrace
2881 mapPRid->put (thrid, tstamp, cprid);
2883 theApplication->set_progress (0, NTXT (""));
2886 openMPdata = dDscr->createView ();
2887 openMPdata->sort (PROP_CPRID); // omptrace PROP_CPRID
2889 // thread enters parreg events
2890 dDscr = getDataDescriptor (DATA_OMP2);
2891 sz = dDscr->getSize ();
2894 msg = dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"),
2896 theApplication->set_progress (0, msg);
2901 for (int i = 0; i < sz; ++i)
2903 if (i == nextReport)
2905 int percent = (int) (i * 100 / sz);
2907 theApplication->set_progress (percent, NULL);
2908 nextReport += deltaReport;
2910 uint32_t thrid = dDscr->getIntValue (PROP_THRID, i);
2911 hrtime_t tstamp = dDscr->getLongValue (PROP_TSTAMP, i);
2912 uint64_t cprid = dDscr->getLongValue (PROP_CPRID, i); //omptrace
2913 mapPRid->put (thrid, tstamp, cprid);
2915 theApplication->set_progress (0, NTXT (""));
2922 if (ompavail && coll_params.profile_mode)
2924 dbeSession->status_ompavail = 1;
2925 register_metric (Metric::OMP_WORK);
2926 register_metric (Metric::OMP_WAIT);
2927 register_metric (Metric::OMP_OVHD);
2928 if (coll_params.lms_magic_id == LMS_MAGIC_ID_SOLARIS)
2929 register_metric (Metric::OMP_MASTER_THREAD);
2935 Experiment::read_ifreq_file ()
2937 char *fname = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_IFREQ_FILE);
2938 FILE *f = fopen (fname, NTXT ("r"));
2946 ifreqq = new Emsgqueue (NTXT ("ifreqq"));
2951 char str[MAXPATHLEN];
2952 char *e = fgets (str, ((int) sizeof (str)) - 1, f);
2955 // end the list from the experiment
2956 m = new Emsg (CMSG_COMMENT,
2957 GTXT ("============================================================"));
2962 size_t i = strlen (str);
2963 if (i > 0 && str[i - 1] == '\n')
2964 // remove trailing nl
2967 m = new Emsg (CMSG_COMMENT, str);
2974 Experiment::getBaseFounder ()
2978 Experiment *founder = this;
2979 Experiment *parent = founder->founder_exp;
2983 parent = founder->founder_exp;
2985 baseFounder = founder;
2990 Experiment::getRelativeStartTime ()
2992 if (exp_rel_start_time_set)
2993 return exp_rel_start_time;
2994 Experiment *founder = getBaseFounder ();
2995 hrtime_t child_start = this->getStartTime ();
2996 hrtime_t founder_start = founder->getStartTime ();
2997 exp_rel_start_time = child_start - founder_start;
2998 if (child_start == 0 && founder_start)
2999 exp_rel_start_time = 0; // when descendents have incomplete log.xml
3000 exp_rel_start_time_set = true;
3001 return exp_rel_start_time;
3005 Experiment::get_raw_events (int data_id)
3007 DataDescriptor *dDscr;
3011 dDscr = get_profile_events ();
3014 dDscr = get_sync_events ();
3017 dDscr = get_hwc_events ();
3020 dDscr = get_heap_events ();
3023 dDscr = get_heapsz_events ();
3026 dDscr = get_iotrace_events ();
3029 dDscr = get_race_events ();
3032 dDscr = get_deadlock_events ();
3035 dDscr = get_sample_events ();
3038 dDscr = get_gc_events ();
3048 Experiment::base_data_id (int data_id)
3053 return DATA_HEAP; // DATA_HEAPSZ DataView is based on DATA_HEAP's DataView
3061 Experiment::create_derived_data_view (int data_id, DataView *dview)
3063 // dview contains filtered packets
3067 return create_heapsz_data_view (dview);
3075 Experiment::get_profile_events ()
3077 DataDescriptor *dDscr = getDataDescriptor (DATA_CLOCK);
3080 if (dDscr->getSize () == 0)
3082 char *base_name = get_basename (expt_name);
3083 char *msg = dbe_sprintf (GTXT ("Loading Profile Data: %s"), base_name);
3084 read_data_file (SP_PROFILE_FILE, msg);
3086 add_evt_time_to_profile_events (dDscr);
3087 resolve_frame_info (dDscr);
3089 else if (!dDscr->isResolveFrInfoDone ())
3090 resolve_frame_info (dDscr);
3095 Experiment::add_evt_time_to_profile_events (DataDescriptor *dDscr)
3097 if (coll_params.lms_magic_id != LMS_MAGIC_ID_SOLARIS)
3100 DataView *dview = dDscr->createView ();
3101 dview->sort (PROP_THRID, PROP_TSTAMP);
3103 // add PROP_EVT_TIME
3104 PropDescr* tmp_propDscr = new PropDescr (PROP_EVT_TIME, "EVT_TIME");
3105 tmp_propDscr->uname = dbe_strdup (GTXT ("Event duration"));
3106 tmp_propDscr->vtype = TYPE_INT64;
3107 dDscr->addProperty (tmp_propDscr);
3109 long sz = dview->getSize ();
3110 long long ptimer_usec = get_params ()->ptimer_usec;
3111 for (long i = 0; i < sz; i++)
3116 hrtime_t this_tstamp = dview->getLongValue (PROP_TSTAMP, i);
3117 long this_thrid = dview->getLongValue (PROP_THRID, i);
3118 for (jj = i + 1; jj < sz; jj++)
3120 hrtime_t tmp_tstamp = dview->getLongValue (PROP_TSTAMP, jj);
3121 if (tmp_tstamp != this_tstamp)
3123 long tmp_thrid = dview->getLongValue (PROP_THRID, jj);
3124 if (tmp_thrid != this_thrid)
3131 for (jj = i; jj < next_sample; jj++)
3132 nticks += dview->getLongValue (PROP_NTICK, jj);
3134 continue; // no duration
3137 hrtime_t duration = ptimer_usec * 1000LL * nticks; // nanoseconds
3138 for (jj = i; jj < next_sample; jj++)
3139 dview->setValue (PROP_EVT_TIME, jj, duration);
3146 Experiment::get_sync_events ()
3148 DataDescriptor *dDscr = getDataDescriptor (DATA_SYNCH);
3151 if (dDscr->getSize () > 0)
3156 char *base_name = get_basename (expt_name);
3157 char *msg = dbe_sprintf (GTXT ("Loading Synctrace Data: %s"), base_name);
3158 read_data_file (SP_SYNCTRACE_FILE, msg);
3160 resolve_frame_info (dDscr);
3163 // check for PROP_EVT_TIME
3164 PropDescr *tmp_propDscr = dDscr->getProp (PROP_EVT_TIME);
3168 // add PROP_EVT_TIME
3169 tmp_propDscr = new PropDescr (PROP_EVT_TIME, "EVT_TIME");
3170 tmp_propDscr->uname = dbe_strdup (GTXT ("Event duration"));
3171 tmp_propDscr->vtype = TYPE_INT64;
3172 dDscr->addProperty (tmp_propDscr);
3174 long sz = dDscr->getSize ();
3175 for (long i = 0; i < sz; i++)
3177 uint64_t event_duration = dDscr->getLongValue (PROP_TSTAMP, i);
3178 event_duration -= dDscr->getLongValue (PROP_SRQST, i);
3179 dDscr->setValue (PROP_EVT_TIME, i, event_duration);
3185 Experiment::get_hwc_events ()
3187 DataDescriptor *dDscr = getDataDescriptor (DATA_HWC);
3190 if (dDscr->getSize () == 0)
3192 char *base_name = get_basename (expt_name);
3193 char *msg = dbe_sprintf (GTXT ("Loading HW Profile Data: %s"), base_name);
3195 // clear HWC event stats
3198 read_data_file (SP_HWCNTR_FILE, msg);
3200 resolve_frame_info (dDscr);
3202 // describe the HW counters in PropDescr
3203 PropDescr *prop = dDscr->getProp (PROP_HWCTAG);
3206 Collection_params *cparam = get_params ();
3207 if (cparam->hw_mode != 0)
3208 for (int aux = 0; aux < MAX_HWCOUNT; aux++)
3209 if (cparam->hw_aux_name[aux])
3211 const char* cmdname = cparam->hw_aux_name[aux];
3212 const char* uname = cparam->hw_username[aux];
3213 prop->addState (aux, cmdname, uname);
3219 double dserrrate = 100.0 * ((double) dsnoxhwcevents) / ((double) dsevents);
3220 if ((dsevents > 0) && (dserrrate > 10.0))
3222 // warn the user that rate is high
3224 if (dbeSession->check_ignore_no_xhwcprof ())
3226 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"),
3227 base_name, dserrrate, (long long) dsnoxhwcevents,
3228 (long long) dsevents);
3231 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"),
3232 base_name, dserrrate, (long long) dsnoxhwcevents,
3233 (long long) dsevents);
3234 errorq->append (new Emsg (CMSG_WARN, sb));
3237 // see if we've scanned the data
3238 if (hwc_scanned == 0)
3240 // no, scan the packets to see how many are bogus, or represent lost interrupts
3243 // loop over the packets, counting the bad ones
3244 if (hwc_bogus != 0 || hwc_lost_int != 0)
3246 // hwc counter data had bogus packets and/or packets reflecting lost interrupts
3247 double bogus_rate = 100. * (double) hwc_bogus / (double) hwc_cnt;
3248 if (bogus_rate > 5.)
3252 GTXT ("WARNING: Too many invalid HW counter profile events (%ld/%ld = %3.2f%%) in experiment %d (`%s'); data may be unreliable"),
3253 (long) hwc_bogus, (long) hwc_cnt, bogus_rate,
3254 (int) userExpId, base_name);
3255 Emsg *m = new Emsg (CMSG_WARN, sb);
3266 Experiment::get_iotrace_events ()
3268 DataDescriptor *dDscr = getDataDescriptor (DATA_IOTRACE);
3272 if (dDscr->getSize () > 0)
3275 char *base_name = get_basename (expt_name);
3276 char *msg = dbe_sprintf (GTXT ("Loading IO Trace Data: %s"), base_name);
3277 read_data_file (SP_IOTRACE_FILE, msg);
3280 if (dDscr->getSize () == 0)
3282 resolve_frame_info (dDscr);
3284 // check for PROP_EVT_TIME
3285 PropDescr *tmp_propDscr = dDscr->getProp (PROP_EVT_TIME);
3289 // add PROP_EVT_TIME
3290 tmp_propDscr = new PropDescr (PROP_EVT_TIME, "EVT_TIME");
3291 tmp_propDscr->uname = dbe_strdup (GTXT ("Event duration"));
3292 tmp_propDscr->vtype = TYPE_INT64;
3293 dDscr->addProperty (tmp_propDscr);
3296 tmp_propDscr = new PropDescr (PROP_IOVFD, "IOVFD");
3297 tmp_propDscr->uname = dbe_strdup (GTXT ("Virtual File Descriptor"));
3298 tmp_propDscr->vtype = TYPE_INT64;
3299 dDscr->addProperty (tmp_propDscr);
3302 fDataMap = new DefaultMap<int64_t, FileData*>;
3305 vFdMap = new DefaultMap<int, int64_t>;
3307 static int64_t virtualFd = 0;
3311 fData = fDataMap->get (VIRTUAL_FD_STDIN);
3314 fData = new FileData (STDIN_FILENAME);
3315 fData->setVirtualFd (VIRTUAL_FD_STDIN);
3316 fData->id = VIRTUAL_FD_STDIN;
3317 fData->setFileDes (STDIN_FD);
3318 fDataMap->put (VIRTUAL_FD_STDIN, fData);
3319 vFdMap->put (STDIN_FD, VIRTUAL_FD_STDIN);
3322 fData = fDataMap->get (VIRTUAL_FD_STDOUT);
3325 fData = new FileData (STDOUT_FILENAME);
3326 fData->setVirtualFd (VIRTUAL_FD_STDOUT);
3327 fData->id = VIRTUAL_FD_STDOUT;
3328 fData->setFileDes (STDOUT_FD);
3329 fDataMap->put (VIRTUAL_FD_STDOUT, fData);
3330 vFdMap->put (STDOUT_FD, VIRTUAL_FD_STDOUT);
3333 fData = fDataMap->get (VIRTUAL_FD_STDERR);
3336 fData = new FileData (STDERR_FILENAME);
3337 fData->setVirtualFd (VIRTUAL_FD_STDERR);
3338 fData->id = VIRTUAL_FD_STDERR;
3339 fData->setFileDes (STDERR_FD);
3340 fDataMap->put (VIRTUAL_FD_STDERR, fData);
3341 vFdMap->put (STDERR_FD, VIRTUAL_FD_STDERR);
3344 fData = fDataMap->get (VIRTUAL_FD_OTHERIO);
3347 fData = new FileData (OTHERIO_FILENAME);
3348 fData->setVirtualFd (VIRTUAL_FD_OTHERIO);
3349 fData->id = VIRTUAL_FD_OTHERIO;
3350 fData->setFileDes (OTHERIO_FD);
3351 fDataMap->put (VIRTUAL_FD_OTHERIO, fData);
3354 DataView *dview = dDscr->createView ();
3355 dview->sort (PROP_TSTAMP);
3356 long sz = dview->getSize ();
3357 for (long i = 0; i < sz; i++)
3359 hrtime_t event_duration = dview->getLongValue (PROP_TSTAMP, i);
3360 hrtime_t event_start = dview->getLongValue (PROP_IORQST, i);
3361 if (event_start > 0)
3362 event_duration -= event_start;
3365 dview->setValue (PROP_EVT_TIME, i, event_duration);
3368 int64_t vFd = VIRTUAL_FD_NONE;
3370 int32_t origFd = -1;
3371 StringBuilder *sb = NULL;
3372 FileData *fDataOrig = NULL;
3373 FileSystem_type fsType;
3375 IOTrace_type ioType = (IOTrace_type) dview->getIntValue (PROP_IOTYPE, i);
3380 case READ_TRACE_ERROR:
3381 case WRITE_TRACE_ERROR:
3382 fd = dview->getIntValue (PROP_IOFD, i);
3383 vFd = vFdMap->get (fd);
3384 if (vFd == 0 || vFd == VIRTUAL_FD_NONE
3385 || (fData = fDataMap->get (vFd)) == NULL)
3387 fData = new FileData (UNKNOWNFD_FILENAME);
3388 fData->setVirtualFd (virtualFd);
3389 fData->setFsType ("N/A");
3390 fData->setFileDes (fd);
3391 fDataMap->put (virtualFd, fData);
3392 vFdMap->put (fd, virtualFd);
3396 dview->setValue (PROP_IOVFD, i, vFd);
3400 sb = (StringBuilder*) dview->getObjValue (PROP_IOFNAME, i);
3401 if (sb != NULL && sb->length () > 0)
3402 fName = sb->toString ();
3403 fd = dview->getIntValue (PROP_IOFD, i);
3404 origFd = dview->getIntValue (PROP_IOOFD, i);
3405 fsType = (FileSystem_type) dview->getIntValue (PROP_IOFSTYPE, i);
3409 fData = new FileData (fName);
3410 fDataMap->put (virtualFd, fData);
3411 vFdMap->put (fd, virtualFd);
3412 fData->setFileDes (fd);
3413 fData->setFsType (fsType);
3414 fData->setVirtualFd (virtualFd);
3418 else if (origFd > 0)
3420 vFd = vFdMap->get (origFd);
3421 if (vFd == 0 || vFd == VIRTUAL_FD_NONE)
3424 "*** Error I/O tracing: (open) cannot get the virtual file descriptor, fd=%d origFd=%d\n",
3428 else if ((fDataOrig = fDataMap->get (vFd)) == NULL)
3431 "*** Error IO tracing: (open) cannot get original FileData object, fd=%d origFd=%d\n",
3437 fName = fDataOrig->getFileName ();
3438 fData = new FileData (fName);
3439 fData->setFileDes (fd);
3440 fData->setFsType (fDataOrig->getFsType ());
3441 fData->setVirtualFd (virtualFd);
3442 fDataMap->put (virtualFd, fData);
3443 vFdMap->put (fd, virtualFd);
3450 vFd = vFdMap->get (fd);
3451 if (vFd == 0 || vFd == VIRTUAL_FD_NONE
3452 || (fData = fDataMap->get (vFd)) == NULL)
3454 fData = new FileData (UNKNOWNFD_FILENAME);
3455 fData->setVirtualFd (virtualFd);
3456 fData->setFsType ("N/A");
3457 fData->setFileDes (fd);
3458 fDataMap->put (virtualFd, fData);
3459 vFdMap->put (fd, virtualFd);
3467 NTXT ("*** Error IO tracing: (open) unknown open IO type, fd=%d origFd=%d\n"), fd, origFd);
3471 dview->setValue (PROP_IOVFD, i, vFd);
3474 case OPEN_TRACE_ERROR:
3477 sb = (StringBuilder*) dview->getObjValue (PROP_IOFNAME, i);
3478 if (sb != NULL && sb->length () > 0)
3479 fName = sb->toString ();
3480 fd = dview->getIntValue (PROP_IOFD, i);
3481 origFd = dview->getIntValue (PROP_IOOFD, i);
3482 fsType = (FileSystem_type) dview->getIntValue (PROP_IOFSTYPE, i);
3486 fData = new FileData (fName);
3487 fDataMap->put (virtualFd, fData);
3488 fData->setFileDes (fd);
3489 fData->setFsType (fsType);
3490 fData->setVirtualFd (virtualFd);
3494 else if (origFd > 0)
3496 vFd = vFdMap->get (origFd);
3497 if (vFd == 0 || vFd == VIRTUAL_FD_NONE)
3500 "*** Error IO tracing: (open error) cannot get the virtual file descriptor, fd=%d origFd=%d\n",
3504 else if ((fDataOrig = fDataMap->get (vFd)) == NULL)
3507 "*** Error IO tracing: (open error) cannot get original FileData object, fd=%d origFd=%d\n",
3513 fName = fDataOrig->getFileName ();
3514 fData = new FileData (fName);
3515 fData->setFileDes (fd);
3516 fData->setFsType (fDataOrig->getFsType ());
3517 fData->setVirtualFd (virtualFd);
3518 fDataMap->put (virtualFd, fData);
3524 dview->setValue (PROP_IOVFD, i, vFd);
3528 case CLOSE_TRACE_ERROR:
3529 fd = dview->getIntValue (PROP_IOFD, i);
3530 vFd = vFdMap->get (fd);
3531 if (vFd == 0 || vFd == VIRTUAL_FD_NONE)
3534 "*** Error IO tracing: (close) cannot get the virtual file descriptor, fd=%d\n",
3538 fData = fDataMap->get (vFd);
3542 "*** Error IO tracing: (close) cannot get the FileData object, fd=%d\n",
3547 vFdMap->put (fd, VIRTUAL_FD_NONE);
3548 dview->setValue (PROP_IOVFD, i, vFd);
3552 case OTHERIO_TRACE_ERROR:
3553 vFd = VIRTUAL_FD_OTHERIO;
3554 fData = fDataMap->get (vFd);
3558 "*** Error IO tracing: (other IO) cannot get the FileData object\n");
3562 dview->setValue (PROP_IOVFD, i, vFd);
3564 case IOTRACETYPE_LAST:
3575 Experiment::get_heap_events ()
3577 DataDescriptor *dDscr = getDataDescriptor (DATA_HEAP);
3580 if (dDscr->getSize () > 0)
3583 char *base_name = get_basename (expt_name);
3584 char *msg = dbe_sprintf (GTXT ("Loading Heap Trace Data: %s"), base_name);
3585 read_data_file (SP_HEAPTRACE_FILE, msg);
3588 if (dDscr->getSize () == 0)
3590 resolve_frame_info (dDscr);
3592 // Match FREE to MALLOC
3593 PropDescr *prop = new PropDescr (PROP_HLEAKED, NTXT ("HLEAKED"));
3594 prop->uname = dbe_strdup (GTXT ("Bytes Leaked"));
3595 prop->vtype = TYPE_UINT64;
3596 dDscr->addProperty (prop);
3598 prop = new PropDescr (PROP_HMEM_USAGE, NTXT ("HMEM_USAGE"));
3599 prop->uname = dbe_strdup (GTXT ("Heap Memory Usage"));
3600 prop->vtype = TYPE_UINT64;
3601 dDscr->addProperty (prop);
3603 prop = new PropDescr (PROP_HFREED, NTXT ("HFREED"));
3604 prop->uname = dbe_strdup (GTXT ("Bytes Freed"));
3605 prop->vtype = TYPE_UINT64;
3606 dDscr->addProperty (prop);
3608 prop = new PropDescr (PROP_HCUR_ALLOCS, NTXT ("HCUR_ALLOCS"));
3609 prop->uname = dbe_strdup (GTXT ("Net Bytes Allocated"));
3610 prop->vtype = TYPE_INT64;
3611 dDscr->addProperty (prop);
3613 prop = new PropDescr (PROP_HCUR_LEAKS, NTXT ("HCUR_LEAKS"));
3614 prop->uname = dbe_strdup (GTXT ("Net Bytes Leaked"));
3615 prop->vtype = TYPE_UINT64;
3616 dDscr->addProperty (prop);
3618 prop = new PropDescr (PROP_HCUR_NET_ALLOC, NTXT ("HCUR_NET_ALLOC"));
3619 prop->vtype = TYPE_INT64;
3620 prop->flags = DDFLAG_NOSHOW;
3621 dDscr->addProperty (prop);
3623 prop = new PropDescr (PROP_DDSCR_LNK, NTXT ("DDSCR_LNK"));
3624 prop->vtype = TYPE_UINT64;
3625 prop->flags = DDFLAG_NOSHOW;
3626 dDscr->addProperty (prop);
3628 prop = new PropDescr (PROP_VOIDP_OBJ, NTXT ("VOIDP_OBJ"));
3629 prop->vtype = TYPE_OBJ;
3630 prop->flags = DDFLAG_NOSHOW;
3631 dDscr->addProperty (prop);
3633 prop = new PropDescr (PROP_TSTAMP2, NTXT ("TSTAMP2"));
3634 prop->uname = dbe_strdup (GTXT ("End Timestamp (nanoseconds)"));
3635 prop->vtype = TYPE_UINT64;
3636 prop->flags = DDFLAG_NOSHOW;
3637 dDscr->addProperty (prop);
3639 DataView *dview = dDscr->createView ();
3640 dview->sort (PROP_TSTAMP);
3642 // Keep track of memory usage
3643 Size memoryUsage = 0;
3645 HeapMap *heapmap = new HeapMap ();
3646 long sz = dview->getSize ();
3647 for (long i = 0; i < sz; i++)
3650 Heap_type mtype = (Heap_type) dview->getIntValue (PROP_HTYPE, i);
3651 Vaddr vaddr = dview->getULongValue (PROP_HVADDR, i);
3652 Vaddr ovaddr = dview->getULongValue (PROP_HOVADDR, i);
3653 Size hsize = dview->getULongValue (PROP_HSIZE, i);
3654 hrtime_t tstamp = dview->getLongValue (PROP_TSTAMP, i);
3659 dview->setValue (PROP_TSTAMP2, i, (uint64_t) MAX_TIME);
3662 dview->setValue (PROP_HLEAKED, i, hsize);
3663 heapmap->allocate (vaddr, i + 1);
3665 // Increase heap size
3666 memoryUsage += hsize;
3667 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage);
3674 long idx = heapmap->deallocate (vaddr) - 1;
3677 // Decrease heap size
3678 Size leaked = dview->getLongValue (PROP_HLEAKED, idx);
3679 memoryUsage -= leaked;
3680 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage);
3682 Size alloc = dview->getLongValue (PROP_HSIZE, idx);
3683 // update allocation
3684 dview->setValue (PROP_HLEAKED, idx, (uint64_t) 0);
3685 dview->setValue (PROP_TSTAMP2, idx, tstamp);
3686 dview->setValue (PROP_DDSCR_LNK, idx, dview->getIdByIdx (i) + 1);
3687 // update this event
3688 dview->setValue (PROP_HFREED, i, alloc);
3694 dview->setValue (PROP_TSTAMP2, i, (uint64_t) MAX_TIME);
3697 long idx = heapmap->deallocate (ovaddr) - 1;
3700 // Decrease heap size
3701 Size leaked = dview->getLongValue (PROP_HLEAKED, idx);
3702 memoryUsage -= leaked;
3703 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage);
3705 Size alloc = dview->getLongValue (PROP_HSIZE, idx);
3706 // update allocation
3707 dview->setValue (PROP_HLEAKED, idx, (uint64_t) 0);
3708 dview->setValue (PROP_TSTAMP2, idx, tstamp);
3709 dview->setValue (PROP_DDSCR_LNK, idx, dview->getIdByIdx (i) + 1);
3710 // update this event
3711 dview->setValue (PROP_HFREED, i, alloc);
3716 dview->setValue (PROP_HLEAKED, i, hsize);
3717 heapmap->allocate (vaddr, i + 1);
3719 // Increase heap size
3720 memoryUsage += hsize;
3721 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage);
3726 // Adjust the size to be multiple of page_size
3727 //hsize = (( hsize - 1 ) / page_size + 1 ) * page_size;
3731 if (mtype == MMAP_TRACE)
3733 dview->setValue (PROP_TSTAMP2, i, (uint64_t) MAX_TIME);
3734 dview->setValue (PROP_HLEAKED, i, hsize);
3735 list = heapmap->mmap (vaddr, hsize, i);
3737 // Increase heap size
3738 memoryUsage += hsize;
3739 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage);
3743 list = heapmap->munmap (vaddr, hsize);
3745 // Set allocation size to zero
3746 // Note: We're currently reusing PROP_HSIZE to mean allocation size
3747 // If we ever need to save the original HSIZE, we'll need to
3748 // create a new PROP_* to represent event allocation size
3750 // For now, tuck the original size away as HOVADDR
3751 dview->setValue (PROP_HOVADDR, i, (uint64_t) hsize);
3752 dview->setValue (PROP_HSIZE, i, (uint64_t) 0);
3754 Size total_freed = 0;
3757 long idx = list->val;
3758 total_freed += list->size;
3759 Size leaked = dview->getLongValue (PROP_HLEAKED, idx);
3761 // Decrease heap size
3762 memoryUsage -= list->size;
3763 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage);
3765 Size leak_update = leaked - list->size;
3766 // update allocation
3767 dview->setValue (PROP_HLEAKED, idx, leak_update);
3768 // update allocation's list of frees
3770 UnmapChunk *copy = new UnmapChunk;
3771 heapUnmapEvents->append (copy);
3772 copy->val = dview->getIdByIdx (i);
3773 copy->size = list->size;
3774 copy->next = (UnmapChunk *) dview->getObjValue (PROP_VOIDP_OBJ, idx);
3775 dview->setObjValue (PROP_VOIDP_OBJ, idx, copy);
3777 if (leak_update <= 0)
3778 if (leak_update == 0)
3779 dview->setValue (PROP_TSTAMP2, idx, tstamp);
3780 UnmapChunk *t = list;
3784 // update this event
3786 // only need to write value if it is non-zero
3787 dview->setValue (PROP_HFREED, i, total_freed);
3790 // ignoring HEAPTYPE_LAST, which will never be recorded
3802 Experiment::get_heapsz_events ()
3804 DataDescriptor *dDscr = getDataDescriptor (DATA_HEAPSZ);
3807 dDscr = get_heap_events (); // derived from DATA_HEAP
3810 dDscr = newDataDescriptor (DATA_HEAPSZ, 0, dDscr);
3815 update_heapsz_packet (std::set<long> &pkt_id_set, DataView *dview,
3816 long alloc_pkt_id, int64_t net_alloc, uint64_t leaks)
3818 // pkt_id_set: set is updated to include packet
3819 // alloc_pkt_id: data descriptor id (NOT dview idx)
3820 // net_alloc: adjustment to net allocation for this packet (note: signed value)
3821 // leaks: leak bytes to attribute to alloc_pkt_id
3822 std::pair < std::set<long>::iterator, bool> ret;
3823 ret = pkt_id_set.insert (alloc_pkt_id); // add to set
3824 bool new_to_set = ret.second; // was not in set
3827 // Has been seen before, update values
3828 net_alloc += dview->getDataDescriptorValue (PROP_HCUR_NET_ALLOC, alloc_pkt_id);
3831 uint64_t old = dview->getDataDescriptorValue (PROP_HCUR_LEAKS, alloc_pkt_id);
3836 dview->setDataDescriptorValue (PROP_HCUR_NET_ALLOC, alloc_pkt_id, net_alloc);
3837 dview->setDataDescriptorValue (PROP_HCUR_LEAKS, alloc_pkt_id, leaks);
3841 Experiment::create_heapsz_data_view (DataView *heap_dview)
3843 // heap_dview has DATA_HEAP _filtered_ packets.
3844 // This creates, populates, and returns DATA_HEAPSZ DataView
3845 DataDescriptor *dDscr = get_heapsz_events ();
3848 std::set<long> pkt_id_set;
3849 DataView *dview = heap_dview;
3850 long sz = dview->getSize ();
3851 for (long i = 0; i < sz; i++)
3853 int64_t hsize = (int64_t) dview->getULongValue (PROP_HSIZE, i);
3854 uint64_t leaks = dview->getULongValue (PROP_HLEAKED, i);
3855 long alloc_pkt_id = dview->getIdByIdx (i);
3856 update_heapsz_packet (pkt_id_set, dview, alloc_pkt_id, hsize, leaks);
3859 UnmapChunk *mmap_frees = (UnmapChunk *) dview->getObjValue (PROP_VOIDP_OBJ, i); // mmap metadata
3862 // mmap: all frees associated with this packet
3865 long free_pkt_id = mmap_frees->val;
3866 int64_t free_sz = mmap_frees->size;
3867 update_heapsz_packet (pkt_id_set, dview, free_pkt_id, -free_sz, 0);
3868 mmap_frees = mmap_frees->next;
3873 // malloc: check for associated free
3874 long free_pkt_id = dview->getLongValue (PROP_DDSCR_LNK, i) - 1;
3875 if (free_pkt_id >= 0)
3876 update_heapsz_packet (pkt_id_set, dview, free_pkt_id, -hsize, 0);
3880 // create a new DataView based on the filtered-in and associated free events
3881 std::set<long>::iterator it;
3882 DataView *heapsz_dview = dDscr->createExtManagedView ();
3883 for (it = pkt_id_set.begin (); it != pkt_id_set.end (); ++it)
3885 long ddscr_pkt_id = *it;
3886 heapsz_dview->appendDataDescriptorId (ddscr_pkt_id);
3888 compute_heapsz_data_view (heapsz_dview);
3889 return heapsz_dview;
3893 Experiment::compute_heapsz_data_view (DataView *heapsz_dview)
3895 DataView *dview = heapsz_dview;
3897 // Keep track of memory usage
3898 int64_t currentAllocs = 0;
3899 Size currentLeaks = 0;
3900 dview->sort (PROP_TSTAMP);
3901 long sz = dview->getSize ();
3902 for (long i = 0; i < sz; i++)
3904 int64_t net_alloc = dview->getLongValue (PROP_HCUR_NET_ALLOC, i);
3905 currentAllocs += net_alloc;
3906 dview->setValue (PROP_HCUR_ALLOCS, i, currentAllocs);
3908 Size leaks = dview->getULongValue (PROP_HCUR_LEAKS, i);
3909 currentLeaks += leaks;
3910 dview->setValue (PROP_HCUR_LEAKS, i, currentLeaks);
3915 Experiment::DBG_memuse (Sample * s)
3917 DataDescriptor *dDscr = getDataDescriptor (DATA_HEAP);
3918 if (dDscr == NULL || dDscr->getSize () == 0)
3921 DataView *dview = dDscr->createView ();
3922 dview->sort (PROP_TSTAMP);
3923 hrtime_t ts1 = s->get_start_time ();
3924 hrtime_t ts2 = s->get_end_time ();
3926 HeapMap *heapmap = new HeapMap ();
3927 long sz = dview->getSize ();
3930 hrtime_t maxTime = 0;
3931 for (long i = 0; i < sz; i++)
3933 hrtime_t tstamp = dview->getLongValue (PROP_TSTAMP, i);
3939 Heap_type mtype = (Heap_type) dview->getIntValue (PROP_HTYPE, i);
3940 Vaddr vaddr = dview->getULongValue (PROP_HVADDR, i);
3941 Vaddr ovaddr = dview->getULongValue (PROP_HOVADDR, i);
3960 long idx = heapmap->deallocate (ovaddr) - 1;
3962 curSize -= dview->getULongValue (PROP_HSIZE, idx);
3966 heapmap->allocate (vaddr, i + 1);
3967 curSize += dview->getULongValue (PROP_HSIZE, i);
3968 if (curSize > maxSize)
3975 printf ("SAMPLE=%s (id=%d) MEMUSE=%lld TSTAMP=%lld\n", s->get_start_label (),
3976 s->get_number (), maxSize, maxTime - getStartTime ());
3982 Experiment::DBG_memuse (const char *sname)
3984 for (int i = 0; i < samples->size (); ++i)
3986 Sample *sample = samples->fetch (i);
3987 if (streq (sname, sample->get_start_label ()))
3989 DBG_memuse (sample);
3996 Experiment::get_race_events ()
3998 DataDescriptor *dDscr = getDataDescriptor (DATA_RACE);
4001 if (dDscr->getSize () == 0)
4003 char *base_name = get_basename (expt_name);
4004 char *msg = dbe_sprintf (GTXT ("Loading Race Data: %s"), base_name);
4005 read_data_file (SP_RACETRACE_FILE, msg);
4007 resolve_frame_info (dDscr);
4013 Experiment::get_deadlock_events ()
4015 DataDescriptor *dDscr = getDataDescriptor (DATA_DLCK);
4018 if (dDscr->getSize () == 0)
4020 char *base_name = get_basename (expt_name);
4021 char *msg = dbe_sprintf (GTXT ("Loading Deadlocks Data: %s"), base_name);
4022 read_data_file (SP_DEADLOCK_FILE, msg);
4024 resolve_frame_info (dDscr);
4030 Experiment::get_sample_events ()
4032 DataDescriptor *dDscr = getDataDescriptor (DATA_SAMPLE);
4035 if (dDscr->getSize () > 0)
4038 // read_overview_file(); //YXXX do this here at some point instead of:
4039 PropDescr *tmp_propDscr;
4040 tmp_propDscr = new PropDescr (PROP_SMPLOBJ, NTXT ("SMPLOBJ"));
4041 tmp_propDscr->uname = NULL;
4042 tmp_propDscr->vtype = TYPE_OBJ;
4043 dDscr->addProperty (tmp_propDscr);
4045 tmp_propDscr = new PropDescr (PROP_TSTAMP, NTXT ("TSTAMP"));
4046 tmp_propDscr->uname = dbe_strdup ("High resolution timestamp");
4047 tmp_propDscr->vtype = TYPE_UINT64;
4048 dDscr->addProperty (tmp_propDscr);
4050 tmp_propDscr = new PropDescr (PROP_SAMPLE, NTXT ("SAMPLE"));
4051 tmp_propDscr->uname = dbe_strdup ("Sample number");
4052 tmp_propDscr->vtype = TYPE_UINT64;
4053 dDscr->addProperty (tmp_propDscr);
4055 tmp_propDscr = new PropDescr (PROP_EVT_TIME, NTXT ("EVT_TIME"));
4056 tmp_propDscr->uname = dbe_strdup ("Event duration");
4057 tmp_propDscr->vtype = TYPE_UINT64;
4058 dDscr->addProperty (tmp_propDscr);
4060 long ssize = samples->size ();
4061 for (long ii = 0; ii < ssize; ii++)
4063 Sample * sample = samples->fetch (ii);
4064 long recn = dDscr->addRecord ();
4065 hrtime_t sduration = sample->get_end_time () - sample->get_start_time ();
4066 dDscr->setObjValue (PROP_SMPLOBJ, recn, sample);
4067 dDscr->setValue (PROP_SAMPLE, recn, sample->get_number ());
4068 dDscr->setValue (PROP_TSTAMP, recn, sample->get_end_time ());
4069 dDscr->setValue (PROP_EVT_TIME, recn, sduration);
4075 Experiment::get_gc_events ()
4077 DataDescriptor *dDscr = getDataDescriptor (DATA_GCEVENT);
4080 if (dDscr->getSize () > 0)
4083 // read_overview_file(); //YXXX do this here at some point instead of:
4084 PropDescr *tmp_propDscr;
4085 tmp_propDscr = new PropDescr (PROP_GCEVENTOBJ, NTXT ("GCEVENTOBJ"));
4086 tmp_propDscr->uname = NULL;
4087 tmp_propDscr->vtype = TYPE_OBJ;
4088 dDscr->addProperty (tmp_propDscr);
4090 tmp_propDscr = new PropDescr (PROP_TSTAMP, NTXT ("TSTAMP"));
4091 tmp_propDscr->uname = dbe_strdup ("High resolution timestamp");
4092 tmp_propDscr->vtype = TYPE_UINT64;
4093 dDscr->addProperty (tmp_propDscr);
4095 tmp_propDscr = new PropDescr (PROP_GCEVENT, NTXT ("GCEVENT"));
4096 tmp_propDscr->uname = dbe_strdup ("GCEvent number");
4097 tmp_propDscr->vtype = TYPE_UINT64;
4098 dDscr->addProperty (tmp_propDscr);
4100 tmp_propDscr = new PropDescr (PROP_EVT_TIME, NTXT ("EVT_TIME"));
4101 tmp_propDscr->uname = dbe_strdup ("Event duration");
4102 tmp_propDscr->vtype = TYPE_UINT64;
4103 dDscr->addProperty (tmp_propDscr);
4105 long ssize = gcevents->size ();
4106 for (long ii = 0; ii < ssize; ii++)
4108 GCEvent * gcevent = gcevents->fetch (ii);
4109 long recn = dDscr->addRecord ();
4110 hrtime_t sduration = gcevent->end - gcevent->start;
4111 dDscr->setObjValue (PROP_GCEVENTOBJ, recn, gcevent);
4112 dDscr->setValue (PROP_GCEVENT, recn, gcevent->id);
4113 dDscr->setValue (PROP_TSTAMP, recn, gcevent->end);
4114 dDscr->setValue (PROP_EVT_TIME, recn, sduration);
4120 Experiment::update_last_event (hrtime_t ts/*wall_ts*/)
4122 if (last_event == ZERO_TIME)
4124 // not yet initialized
4127 if (last_event - exp_start_time < ts - exp_start_time)
4128 // compare deltas to avoid hrtime_t wrap
4133 Experiment::write_header ()
4137 // write commentary to the experiment, describing the parameters
4138 if (dbeSession->ipc_mode || dbeSession->rdt_mode)
4140 // In GUI: print start time at the beginning
4141 time_t t = (time_t) start_sec;
4142 char *start_time = ctime (&t);
4143 if (start_time != NULL)
4146 sb.sprintf (GTXT ("Experiment started %s"), start_time);
4147 commentq->append (new Emsg (CMSG_COMMENT, sb));
4150 // write message with target arglist
4151 if (uarglist != NULL)
4154 sb.sprintf (GTXT ("\nTarget command (%s): '%s'"),
4155 (wsize == W32 ? "32-bit" : "64-bit"), uarglist);
4156 commentq->append (new Emsg (CMSG_COMMENT, sb));
4160 sb.sprintf (GTXT ("Process pid %d, ppid %d, pgrp %d, sid %d"),
4161 pid, ppid, pgrp, sid);
4162 commentq->append (new Emsg (CMSG_COMMENT, sb));
4164 // add comment for user name, if set
4165 if (username != NULL)
4168 sb.sprintf (GTXT ("User: `%s'"), username);
4169 commentq->append (new Emsg (CMSG_COMMENT, sb));
4172 // add comment for current working directory
4176 sb.sprintf (GTXT ("Current working directory: %s"), ucwd);
4177 commentq->append (new Emsg (CMSG_COMMENT, sb));
4180 // add comment for collector version string
4181 if (cversion != NULL)
4187 wstring = NTXT ("?");
4190 wstring = GTXT ("32-bit");
4193 wstring = GTXT ("64-bit");
4196 wstring = NTXT ("??");
4200 sb.sprintf (GTXT ("Collector version: `%s'; experiment version %d.%d (%s)"),
4201 cversion, exp_maj_version, exp_min_version, wstring);
4202 commentq->append (new Emsg (CMSG_COMMENT, sb));
4205 // add comment for driver version string (er_kernel)
4206 if (dversion != NULL)
4209 sb.sprintf (GTXT ("Kernel driver version: `%s'"), dversion);
4210 commentq->append (new Emsg (CMSG_COMMENT, sb));
4213 if (jversion != NULL)
4216 sb.sprintf (GTXT ("JVM version: `%s'"), jversion);
4217 commentq->append (new Emsg (CMSG_COMMENT, sb));
4220 // add comment for hostname, parameters
4221 if (hostname == NULL)
4222 hostname = dbe_strdup (GTXT ("unknown"));
4223 if (os_version == NULL)
4224 os_version = dbe_strdup (GTXT ("unknown"));
4225 if (architecture == NULL)
4226 architecture = dbe_strdup (GTXT ("unknown"));
4228 sb.sprintf (GTXT ("Host `%s', OS `%s', page size %d, architecture `%s'"),
4229 hostname, os_version, page_size, architecture);
4230 commentq->append (new Emsg (CMSG_COMMENT, sb));
4233 if (maxclock != minclock)
4237 GTXT (" %d CPUs, with clocks ranging from %d to %d MHz.; max of %d MHz. assumed"),
4238 ncpus, minclock, maxclock, clock);
4241 sb.sprintf (GTXT (" %d CPU%s, clock speed %d MHz."),
4242 ncpus, (ncpus == 1 ? NTXT ("") : "s"), clock);
4243 commentq->append (new Emsg (CMSG_COMMENT, sb));
4245 // add comment for machine memory size
4246 if (page_size > 0 && npages > 0)
4248 long long memsize = ((long long) npages * page_size) / (1024 * 1024);
4250 sb.sprintf (GTXT (" Memory: %d pages @ %d = %lld MB."),
4251 npages, page_size, memsize);
4252 commentq->append (new Emsg (CMSG_COMMENT, sb));
4255 // add comment for machine memory size
4256 if (machinemodel != NULL)
4259 sb.sprintf (GTXT (" Machine model: %s"), machinemodel);
4260 commentq->append (new Emsg (CMSG_COMMENT, sb));
4263 // add comment for start time
4264 time_t t = (time_t) start_sec;
4265 char *p = ctime (&t);
4268 sb.sprintf (GTXT ("Experiment started %s"), p);
4270 sb.sprintf (GTXT ("\nExperiment start not recorded"));
4271 write_coll_params ();
4272 commentq->append (new Emsg (CMSG_COMMENT, sb));
4273 commentq->appendqueue (runlogq);
4274 runlogq->mark_clear ();
4278 Experiment::write_coll_params ()
4282 // now write the various collection parameters as comments
4284 sb.append (GTXT ("Data collection parameters:"));
4285 commentq->append (new Emsg (CMSG_COMMENT, sb));
4286 if (coll_params.profile_mode == 1)
4289 sb.sprintf (GTXT (" Clock-profiling, interval = %d microsecs."),
4290 (int) (coll_params.ptimer_usec));
4291 commentq->append (new Emsg (CMSG_COMMENT, sb));
4293 if (coll_params.sync_mode == 1)
4296 char *scope_str = NTXT ("");
4297 switch (coll_params.sync_scope)
4300 scope_str = GTXT ("Native- and Java-APIs");
4302 case SYNCSCOPE_JAVA:
4303 scope_str = GTXT ("JAVA-APIs");
4305 case SYNCSCOPE_NATIVE:
4306 scope_str = GTXT ("Native-APIs");
4308 case SYNCSCOPE_JAVA | SYNCSCOPE_NATIVE:
4309 scope_str = GTXT ("Native- and Java-APIs");
4312 if (coll_params.sync_threshold < 0)
4313 sb.sprintf (GTXT (" Synchronization tracing, threshold = %d microsecs. (calibrated); %s"),
4314 -coll_params.sync_threshold, scope_str);
4316 sb.sprintf (GTXT (" Synchronization tracing, threshold = %d microsecs.; %s"),
4317 coll_params.sync_threshold, scope_str);
4318 commentq->append (new Emsg (CMSG_COMMENT, sb));
4320 if (coll_params.heap_mode == 1)
4323 sb.append (GTXT (" Heap tracing"));
4324 commentq->append (new Emsg (CMSG_COMMENT, sb));
4326 if (coll_params.io_mode == 1)
4329 sb.append (GTXT (" IO tracing"));
4330 commentq->append (new Emsg (CMSG_COMMENT, sb));
4332 if (coll_params.race_mode == 1)
4335 char *race_stack_name;
4336 switch (coll_params.race_stack)
4339 race_stack_name = GTXT ("dual-stack");
4342 race_stack_name = GTXT ("single-stack");
4345 race_stack_name = GTXT ("leaf");
4350 sb.sprintf (GTXT (" Datarace detection, %s"), race_stack_name);
4351 commentq->append (new Emsg (CMSG_COMMENT, sb));
4353 if (coll_params.deadlock_mode == 1)
4356 sb.append (GTXT (" Deadlock detection"));
4357 commentq->append (new Emsg (CMSG_COMMENT, sb));
4359 if (coll_params.hw_mode == 1)
4362 if (hwc_default == true)
4363 sb.append (GTXT (" HW counter-profiling (default); counters:"));
4365 sb.append (GTXT (" HW counter-profiling; counters:"));
4366 commentq->append (new Emsg (CMSG_COMMENT, sb));
4367 for (int i = 0; i < MAX_HWCOUNT; i++)
4369 if (!coll_params.hw_aux_name[i])
4372 sb.sprintf (GTXT (" %s, tag %d, interval %d, memop %d"),
4373 coll_params.hw_aux_name[i], i,
4374 coll_params.hw_interval[i], coll_params.hw_tpc[i]);
4375 commentq->append (new Emsg (CMSG_COMMENT, sb));
4378 if (coll_params.sample_periodic == 1)
4381 sb.sprintf (GTXT (" Periodic sampling, %d secs."),
4382 coll_params.sample_timer);
4383 commentq->append (new Emsg (CMSG_COMMENT, sb));
4385 if (coll_params.limit != 0)
4388 sb.sprintf (GTXT (" Experiment size limit, %d"),
4390 commentq->append (new Emsg (CMSG_COMMENT, sb));
4392 if (coll_params.linetrace != NULL)
4395 sb.sprintf (GTXT (" Follow descendant processes from: %s"),
4396 coll_params.linetrace);
4397 commentq->append (new Emsg (CMSG_COMMENT, sb));
4399 if (coll_params.pause_sig != NULL)
4402 sb.sprintf (GTXT (" Pause signal %s"), coll_params.pause_sig);
4403 commentq->append (new Emsg (CMSG_COMMENT, sb));
4405 if (coll_params.sample_sig != NULL)
4408 sb.sprintf (GTXT (" Sample signal %s"), coll_params.sample_sig);
4409 commentq->append (new Emsg (CMSG_COMMENT, sb));
4411 if (coll_params.start_delay != NULL)
4414 sb.sprintf (GTXT (" Data collection delay start %s seconds"), coll_params.start_delay);
4415 commentq->append (new Emsg (CMSG_COMMENT, sb));
4417 if (coll_params.terminate != NULL)
4420 sb.sprintf (GTXT (" Data collection termination after %s seconds"), coll_params.terminate);
4421 commentq->append (new Emsg (CMSG_COMMENT, sb));
4423 // add a blank line after data description
4424 commentq->append (new Emsg (CMSG_COMMENT, NTXT ("")));
4429 * Raw packet processing
4432 check_mstate (char *ptr, PacketDescriptor *pDscr, int arg)
4450 Vector<FieldDescr*> *fields = pDscr->getFields ();
4451 for (int i = 0, sz = fields->size (); i < sz; i++)
4453 FieldDescr *fDscr = fields->fetch (i);
4454 if (fDscr->propID == arg)
4455 return *((int*) (ptr + fDscr->offset));
4460 #define PACKET_ALIGNMENT 4
4463 Experiment::readPacket (Data_window *dwin, Data_window::Span *span)
4465 Common_packet *rcp = (Common_packet *) dwin->bind (span,
4466 sizeof (CommonHead_packet));
4471 if ((((long) rcp) % PACKET_ALIGNMENT) != 0)
4474 size = PROFILE_BUFFER_CHUNK - span->offset % PROFILE_BUFFER_CHUNK;
4477 v16 = (uint16_t) rcp->tsize;
4478 size = dwin->decode (v16);
4481 size = PROFILE_BUFFER_CHUNK - span->offset % PROFILE_BUFFER_CHUNK;
4484 rcp = (Common_packet *) dwin->bind (span, size);
4489 if ((((long) rcp) % PACKET_ALIGNMENT) != 0)
4492 size = PROFILE_BUFFER_CHUNK - span->offset % PROFILE_BUFFER_CHUNK;
4495 v16 = (uint16_t) rcp->type;
4496 uint32_t rcptype = dwin->decode (v16);
4497 if (rcptype == EMPTY_PCKT)
4499 if (rcptype == FRAME_PCKT)
4501 RawFramePacket *fp = new RawFramePacket;
4502 fp->uid = dwin->decode (((Frame_packet*) rcp)->uid);
4507 char *ptr = (char*) rcp + dwin->decode (((Frame_packet*) rcp)->hsize);
4508 if ((((long) ptr) % PACKET_ALIGNMENT) != 0)
4514 v16 = (uint16_t) ((Frame_packet*) rcp)->tsize;
4515 char *end = (char*) rcp + dwin->decode (v16);
4518 Common_info *cinfo = (Common_info*) ptr;
4519 uint32_t hsize = dwin->decode (cinfo->hsize);
4520 if (hsize == 0 || ptr + hsize > end)
4522 int kind = dwin->decode (cinfo->kind);
4523 bool compressed = false;
4524 if (kind & COMPRESSED_INFO)
4527 kind &= ~COMPRESSED_INFO;
4533 char *stack = ptr + sizeof (Stack_info);
4534 size_t stack_size = hsize - sizeof (Stack_info);
4535 uint64_t uidn = dwin->decode (((Stack_info*) cinfo)->uid);
4536 if (stack_size <= 0)
4538 fp->uidn = get_uid_node (uidn);
4541 uint64_t link_uid = (uint64_t) 0;
4544 stack_size -= sizeof (uint64_t);
4545 unsigned char *s = (unsigned char*) (stack + stack_size);
4547 for (size_t i = 0; i<sizeof (link_uid); i++)
4549 link_uid |= (uint64_t) * s++ << shift;
4554 fp->uidn = add_uid (dwin, uidn,
4555 (int) (stack_size / sizeof (uint32_t)),
4556 (uint32_t*) stack, link_uid);
4558 fp->uidn = add_uid (dwin, uidn,
4559 (int) (stack_size / sizeof (uint64_t)),
4560 (uint64_t*) stack, link_uid);
4565 char *stack = ptr + sizeof (Java_info);
4566 size_t stack_size = hsize - sizeof (Java_info);
4567 uint64_t uidj = dwin->decode (((Java_info*) cinfo)->uid);
4568 if (stack_size <= 0)
4570 fp->uidj = get_uid_node (uidj);
4574 uint64_t link_uid = (uint64_t) 0;
4577 stack_size -= sizeof (uint64_t);
4578 unsigned char *s = (unsigned char*) (stack + stack_size);
4580 for (size_t i = 0; i<sizeof (link_uid); i++)
4582 link_uid |= (uint64_t) * s++ << shift;
4587 fp->uidj = add_uid (dwin, uidj,
4588 (int) (stack_size / sizeof (uint32_t)),
4589 (uint32_t*) stack, link_uid);
4592 // bug 6909545: garbage in 64-bit JAVA_INFO
4593 char *nstack = (char*) malloc (stack_size);
4595 char *srcmax = stack + stack_size - sizeof (uint64_t);
4596 for (char *src = stack; src <= srcmax;)
4598 int64_t val = dwin->decode (*(int32_t*) src);
4599 *(uint64_t*) dst = dwin->decode (val);
4600 src += sizeof (uint64_t);
4601 dst += sizeof (uint64_t);
4604 fprintf (stderr, "er_print: Experiment::readPacket: Error in data: src=%llx greater than %llx\n",
4605 (long long) src, (long long) srcmax);
4608 *(uint64_t*) dst = *(uint64_t*) src;
4609 src += sizeof (uint64_t);
4610 dst += sizeof (uint64_t);
4612 fp->uidj = add_uid (dwin, uidj,
4613 (int) (stack_size / sizeof (uint64_t)),
4614 (uint64_t*) nstack, link_uid);
4620 fp->omp_state = dwin->decode (((OMP_info*) ptr)->omp_state);
4624 uint64_t omp_uid = dwin->decode (((OMP2_info*) ptr)->uid);
4625 fp->omp_uid = get_uid_node (omp_uid);
4626 fp->omp_state = dwin->decode (((OMP2_info*) ptr)->omp_state);
4634 frmpckts->append (fp);
4637 else if (rcptype == UID_PCKT)
4639 Uid_packet *uidp = (Uid_packet*) rcp;
4640 uint64_t uid = dwin->decode (uidp->uid);
4641 char *arr_bytes = (char*) (uidp + 1);
4642 v16 = (uint16_t) rcp->tsize;
4643 size_t arr_length = dwin->decode (v16) - sizeof (Uid_packet);
4644 if (arr_length <= 0)
4646 uint64_t link_uid = (uint64_t) 0;
4647 if (dwin->decode (uidp->flags) & COMPRESSED_INFO)
4649 arr_length -= sizeof (uint64_t);
4650 unsigned char *s = (unsigned char*) (arr_bytes + arr_length);
4652 for (size_t i = 0; i<sizeof (link_uid); i++)
4654 link_uid |= (uint64_t) * s++ << shift;
4659 add_uid (dwin, uid, (int) (arr_length / sizeof (uint32_t)),
4660 (uint32_t*) arr_bytes, link_uid);
4662 add_uid (dwin, uid, (int) (arr_length / sizeof (uint64_t)),
4663 (uint64_t*) arr_bytes, link_uid);
4667 PacketDescriptor *pcktDescr = getPacketDescriptor (rcptype);
4668 if (pcktDescr == NULL)
4670 DataDescriptor *dataDescr = pcktDescr->getDataDescriptor ();
4671 if (dataDescr == NULL)
4674 /* omazur: TBR START -- old experiment */
4675 if (rcptype == PROF_PCKT)
4677 // For backward compatibility with older SS12 experiments
4678 int numstates = get_params ()->lms_magic_id; // ugly, for old experiments
4679 if (numstates > LMS_NUM_SOLARIS_MSTATES)
4680 numstates = LMS_NUM_SOLARIS_MSTATES;
4681 for (int i = 0; i < numstates; i++)
4682 if (check_mstate ((char*) rcp, pcktDescr, PROP_UCPU + i))
4683 readPacket (dwin, (char*) rcp, pcktDescr, dataDescr, PROP_UCPU + i,
4687 readPacket (dwin, (char*) rcp, pcktDescr, dataDescr, 0, size);
4692 Experiment::readPacket (Data_window *dwin, char *ptr, PacketDescriptor *pDscr,
4693 DataDescriptor *dDscr, int arg, uint64_t pktsz)
4701 long recn = dDscr->addRecord ();
4702 Vector<FieldDescr*> *fields = pDscr->getFields ();
4703 int sz = fields->size ();
4704 for (int i = 0; i < sz; i++)
4706 FieldDescr *field = fields->fetch (i);
4707 v = (Value*) (ptr + field->offset);
4708 if (field->propID == arg)
4710 dDscr->setValue (PROP_NTICK, recn, dwin->decode (v->val32));
4711 dDscr->setValue (PROP_MSTATE, recn, (uint32_t) (field->propID - PROP_UCPU));
4713 if (field->propID == PROP_THRID || field->propID == PROP_LWPID
4714 || field->propID == PROP_CPUID)
4717 switch (field->vtype)
4721 tmp64 = dwin->decode (v->val32);
4725 tmp64 = dwin->decode (v->val64);
4737 uint32_t tag = mapTagValue ((Prop_type) field->propID, tmp64);
4738 dDscr->setValue (field->propID, recn, tag);
4742 switch (field->vtype)
4746 dDscr->setValue (field->propID, recn, dwin->decode (v->val32));
4750 dDscr->setValue (field->propID, recn, dwin->decode (v->val64));
4754 int len = (int) (pktsz - field->offset);
4755 if ((len > 0) && (ptr[field->offset] != 0))
4757 StringBuilder *sb = new StringBuilder ();
4758 sb->append (ptr + field->offset, 0, len);
4759 dDscr->setObjValue (field->propID, recn, sb);
4763 // ignoring the following cases (why?)
4777 #define PROG_BYTE 102400 // update progress bar every PROG_BYTE bytes
4780 Experiment::read_data_file (const char *fname, const char *msg)
4782 Data_window::Span span;
4783 off64_t total_len, remain_len;
4784 char *progress_bar_msg;
4785 int progress_bar_percent = -1;
4787 char *data_file_name = dbe_sprintf (NTXT ("%s/%s"), expt_name, fname);
4788 Data_window *dwin = new Data_window (data_file_name);
4789 // Here we can call stat(data_file_name) to get file size,
4790 // and call a function to reallocate vectors for clock profiling data
4791 free (data_file_name);
4792 if (dwin->not_opened ())
4797 dwin->need_swap_endian = need_swap_endian;
4800 span.length = dwin->get_fsize ();
4801 total_len = remain_len = span.length;
4802 progress_bar_msg = dbe_sprintf (NTXT ("%s %s"), NTXT (" "), msg);
4806 uint64_t pcktsz = readPacket (dwin, &span);
4809 // Update progress bar
4810 if ((span.length <= remain_len) && (remain_len > 0))
4812 int percent = (int) (100 * (total_len - remain_len) / total_len);
4813 if (percent > progress_bar_percent)
4815 progress_bar_percent += 10;
4816 theApplication->set_progress (percent, progress_bar_msg);
4818 remain_len -= PROG_BYTE;
4820 span.length -= pcktsz;
4821 span.offset += pcktsz;
4828 sb.sprintf (GTXT ("WARNING: There are %d invalid packet(s) in the %s file"),
4829 invalid_packet, fname);
4830 Emsg *m = new Emsg (CMSG_WARN, sb);
4834 theApplication->set_progress (0, NTXT (""));
4835 free (progress_bar_msg);
4839 Experiment::read_overview_file ()
4841 char *data_file_name = dbe_sprintf ("%s/%s", expt_name, SP_OVERVIEW_FILE);
4842 Data_window *dwin = new Data_window (data_file_name);
4843 free (data_file_name);
4844 if (dwin->not_opened ())
4849 dwin->need_swap_endian = need_swap_endian;
4850 newDataDescriptor (DATA_SAMPLE);
4852 Data_window::Span span;
4854 span.length = dwin->get_fsize ();
4856 PrUsage *data = NULL, *data_prev = NULL;
4858 int sample_number = 1;
4862 prDataSize = PrUsage::bind32Size ();
4864 prDataSize = PrUsage::bind64Size ();
4866 while (span.length > 0)
4869 data = new PrUsage ();
4871 void *dw = dwin->bind (&span, prDataSize);
4872 if ((dw == NULL) || (prDataSize > span.length))
4874 Emsg *m = new Emsg (CMSG_ERROR, GTXT ("Warning: overview data file can't be read"));
4882 data->bind32 (dw, need_swap_endian);
4884 data->bind64 (dw, need_swap_endian);
4885 span.length -= prDataSize;
4886 span.offset += prDataSize;
4888 // Skip the first packet
4889 if (data_prev == NULL)
4891 if (sample_number > samples->size ())
4892 { // inconsistent log/overview
4893 sample = new Sample (sample_number);
4894 char * label = GTXT ("<unknown>");
4895 sample->start_label = dbe_strdup (label);
4896 sample->end_label = dbe_strdup (label);
4897 samples->append (sample);
4900 sample = samples->fetch (sample_number - 1);
4902 sample->start_time = data_prev->pr_tstamp + 1;
4903 sample->end_time = data->pr_tstamp;
4904 sample->prusage = data_prev;
4906 data_prev->pr_rtime = data->pr_rtime - data_prev->pr_rtime;
4907 data_prev->pr_utime = data->pr_utime - data_prev->pr_utime;
4908 data_prev->pr_stime = data->pr_stime - data_prev->pr_stime;
4909 data_prev->pr_ttime = data->pr_ttime - data_prev->pr_ttime;
4910 data_prev->pr_tftime = data->pr_tftime - data_prev->pr_tftime;
4911 data_prev->pr_dftime = data->pr_dftime - data_prev->pr_dftime;
4912 data_prev->pr_kftime = data->pr_kftime - data_prev->pr_kftime;
4913 data_prev->pr_ltime = data->pr_ltime - data_prev->pr_ltime;
4914 data_prev->pr_slptime = data->pr_slptime - data_prev->pr_slptime;
4915 data_prev->pr_wtime = data->pr_wtime - data_prev->pr_wtime;
4916 data_prev->pr_stoptime = data->pr_stoptime - data_prev->pr_stoptime;
4917 data_prev->pr_minf = data->pr_minf - data_prev->pr_minf;
4918 data_prev->pr_majf = data->pr_majf - data_prev->pr_majf;
4919 data_prev->pr_nswap = data->pr_nswap - data_prev->pr_nswap;
4920 data_prev->pr_inblk = data->pr_inblk - data_prev->pr_inblk;
4921 data_prev->pr_oublk = data->pr_oublk - data_prev->pr_oublk;
4922 data_prev->pr_msnd = data->pr_msnd - data_prev->pr_msnd;
4923 data_prev->pr_mrcv = data->pr_mrcv - data_prev->pr_mrcv;
4924 data_prev->pr_sigs = data->pr_sigs - data_prev->pr_sigs;
4925 data_prev->pr_vctx = data->pr_vctx - data_prev->pr_vctx;
4926 data_prev->pr_ictx = data->pr_ictx - data_prev->pr_ictx;
4927 data_prev->pr_sysc = data->pr_sysc - data_prev->pr_sysc;
4928 data_prev->pr_ioch = data->pr_ioch - data_prev->pr_ioch;
4929 sample->get_usage (); // force validation
4932 for (long smpNum = samples->size (); smpNum >= sample_number; smpNum--)
4934 // overview file was truncated
4935 sample = samples->remove (smpNum - 1);
4941 // Update last_event so that getEndTime() covers
4942 // all loadobjects, too.
4943 update_last_event (data->pr_tstamp);
4951 Experiment::uidNodeCmp (const void *a, const void *b)
4953 UIDnode *nd1 = *(UIDnode**) a;
4954 UIDnode *nd2 = *(UIDnode**) b;
4955 if (nd1->uid == nd2->uid)
4957 return nd1->uid < nd2->uid ? -1 : 1;
4961 funcAddr (uint32_t val)
4963 if (val == (uint32_t) SP_LEAF_CHECK_MARKER)
4964 return (uint64_t) SP_LEAF_CHECK_MARKER;
4965 if (val == (uint32_t) SP_TRUNC_STACK_MARKER)
4966 return (uint64_t) SP_TRUNC_STACK_MARKER;
4967 if (val == (uint32_t) SP_FAILED_UNWIND_MARKER)
4968 return (uint64_t) SP_FAILED_UNWIND_MARKER;
4972 Experiment::UIDnode *
4973 Experiment::add_uid (Data_window *dwin, uint64_t uid, int size,
4974 uint32_t *array, uint64_t link_uid)
4976 if (uid == (uint64_t) 0)
4978 uint64_t val = funcAddr (dwin->decode (array[0]));
4979 UIDnode *node = NULL;
4980 UIDnode *res = get_uid_node (uid, val);
4981 UIDnode *next = res;
4982 for (int i = 0; i < size; i++)
4984 val = funcAddr (dwin->decode (array[i]));
4987 next = get_uid_node ((uint64_t) 0, val);
4995 else if (node->val != val) // Algorithmic error (should never happen)
4996 node->val = (uint64_t) SP_LEAF_CHECK_MARKER;
4998 if (next == NULL && link_uid != (uint64_t) 0 && node != NULL)
4999 node->next = get_uid_node (link_uid);
5003 Experiment::UIDnode *
5004 Experiment::add_uid (Data_window *dwin, uint64_t uid, int size, uint64_t *array, uint64_t link_uid)
5006 if (uid == (uint64_t) 0)
5008 UIDnode *node = NULL;
5009 uint64_t val = dwin->decode (array[0]);
5010 UIDnode *res = get_uid_node (uid, val);
5011 UIDnode *next = res;
5012 for (int i = 0; i < size; i++)
5014 val = dwin->decode (array[i]);
5017 next = get_uid_node ((uint64_t) 0, val);
5023 if (node->val == (uint64_t) 0)
5025 else if (node->val != val) // Algorithmic error (should never happen)
5026 node->val = (uint64_t) - 1;
5028 if (next == NULL && link_uid != (uint64_t) 0 && node != NULL)
5029 node->next = get_uid_node (link_uid);
5033 Experiment::UIDnode *
5034 Experiment::new_uid_node (uint64_t uid, uint64_t val)
5036 #define NCHUNKSTEP 1024
5037 if (nnodes >= nchunks * CHUNKSZ)
5039 // Reallocate Node chunk array
5040 UIDnode** old_chunks = chunks;
5041 chunks = new UIDnode*[nchunks + NCHUNKSTEP];
5042 memcpy (chunks, old_chunks, nchunks * sizeof (UIDnode*));
5043 nchunks += NCHUNKSTEP;
5044 delete[] old_chunks;
5045 // Clean future pointers
5046 memset (&chunks[nchunks - NCHUNKSTEP], 0, NCHUNKSTEP * sizeof (UIDnode*));
5049 if (NULL == chunks[nnodes / CHUNKSZ]) // Allocate new chunk for nodes.
5050 chunks[nnodes / CHUNKSZ] = new UIDnode[CHUNKSZ];
5051 UIDnode *node = &chunks[nnodes / CHUNKSZ][nnodes % CHUNKSZ];
5059 Experiment::UIDnode *
5060 Experiment::get_uid_node (uint64_t uid, uint64_t val)
5062 int hash = (((int) uid) >> 4) & (HTableSize - 1);
5063 if (uid != (uint64_t) 0)
5065 UIDnode *node = uidHTable[hash];
5066 if (node && node->uid == uid)
5069 UIDnode *node = new_uid_node (uid, val);
5070 if (uid != (uint64_t) 0)
5072 uidHTable[hash] = node;
5073 uidnodes->append (node);
5078 Experiment::UIDnode *
5079 Experiment::get_uid_node (uint64_t uid)
5081 if (uid == (uint64_t) 0)
5083 int hash = (((int) uid) >> 4) & (HTableSize - 1);
5084 UIDnode *node = uidHTable[hash];
5085 if (node && node->uid == uid)
5087 node = new_uid_node (uid, (uint64_t) 0);
5092 Experiment::UIDnode *
5093 Experiment::find_uid_node (uint64_t uid)
5095 int hash = (((int) uid) >> 4) & (HTableSize - 1);
5096 UIDnode *node = uidHTable[hash];
5097 if (node && node->uid == uid)
5100 int rt = uidnodes->size () - 1;
5103 int md = (lt + rt) / 2;
5104 node = uidnodes->fetch (md);
5105 if (node->uid < uid)
5107 else if (node->uid > uid)
5111 uidHTable[hash] = node;
5119 Experiment::frUidCmp (const void *a, const void *b)
5121 RawFramePacket *fp1 = *(RawFramePacket**) a;
5122 RawFramePacket *fp2 = *(RawFramePacket**) b;
5123 if (fp1->uid == fp2->uid)
5125 return fp1->uid < fp2->uid ? -1 : 1;
5128 Experiment::RawFramePacket *
5129 Experiment::find_frame_packet (uint64_t uid)
5132 int rt = frmpckts->size () - 1;
5135 int md = (lt + rt) / 2;
5136 RawFramePacket *fp = frmpckts->fetch (md);
5139 else if (fp->uid > uid)
5148 #define FRINFO_CACHEOPT_SIZE_LIMIT 4000000
5149 #define FRINFO_PIPELINE_SIZE_LIMIT 500000
5150 #define FRINFO_PIPELINE_NUM_STAGES 3
5152 // Pipelined execution of resolve_frame_info() and add_stack().
5153 // Since this is the largest time consuming part of loading an experiment (especially
5154 // so for large java experiments) - executing this part as a 3 stage pipeline can
5155 // give significant performance gain - and this concept can be aggressively applied
5156 // to enhance the gain further in future. The three stages are:
5157 // Phase 1: resolve_frame_info()
5158 // Phase 2: first part of add_stack() where the native stack is built
5159 // Phase 3: second part og add_stack() where the java stack is built
5160 // Phase 4: insert the native and java stacks into the stack map
5161 // The main thread operates in the first Phase and the other stages are
5162 // operated by a ssplib sequential queue - The threads working on the queues run concurrently
5163 // with each other and with the main thread. But within a particular queue, jobs are
5164 // executed sequentially
5167 // This is the second phase of the pipeline of resolve_frame_info and add_stack
5168 // It works on a chunk of iterations (size CSTCTX_CHUNK_SZ) and invokes add_stack()
5169 // for each one of them
5172 Experiment::resolve_frame_info (DataDescriptor *dDscr)
5174 if (!resolveFrameInfo)
5178 dDscr->setResolveFrInfoDone ();
5181 int propID = dbeSession->getPropIdByName (NTXT ("TSTAMP"));
5182 Data *dataTStamp = dDscr->getData (propID);
5183 if (dataTStamp == NULL)
5186 propID = dbeSession->getPropIdByName (NTXT ("FRINFO"));
5187 Data *dataFrinfo = dDscr->getData (propID);
5189 propID = dbeSession->getPropIdByName (NTXT ("THRID"));
5190 Data *dataThrId = dDscr->getData (propID);
5192 // We can get frame info either by FRINFO or by [THRID,STKIDX]
5193 if (dataFrinfo == NULL)
5196 char *propName = NTXT ("MSTACK");
5197 propID = dbeSession->getPropIdByName (propName);
5198 PropDescr *prMStack = new PropDescr (propID, propName);
5199 prMStack->uname = dbe_strdup (GTXT ("Machine Call Stack"));
5200 prMStack->vtype = TYPE_OBJ;
5201 dDscr->addProperty (prMStack);
5203 propName = NTXT ("USTACK");
5204 propID = dbeSession->getPropIdByName (propName);
5205 PropDescr *prUStack = new PropDescr (propID, propName);
5206 prUStack->uname = dbe_strdup (GTXT ("User Call Stack"));
5207 prUStack->vtype = TYPE_OBJ;
5208 dDscr->addProperty (prUStack);
5210 propName = NTXT ("XSTACK");
5211 propID = dbeSession->getPropIdByName (propName);
5212 PropDescr *prXStack = new PropDescr (propID, propName);
5213 prXStack->uname = dbe_strdup (GTXT ("Expert Call Stack"));
5214 prXStack->vtype = TYPE_OBJ;
5215 dDscr->addProperty (prXStack);
5217 propName = NTXT ("HSTACK");
5218 propID = dbeSession->getPropIdByName (propName);
5219 PropDescr *prHStack = new PropDescr (propID, propName);
5220 prHStack->uname = dbe_strdup (GTXT ("ShowHide Call Stack"));
5221 prHStack->vtype = TYPE_OBJ;
5222 dDscr->addProperty (prHStack);
5226 propName = NTXT ("JTHREAD");
5227 propID = dbeSession->getPropIdByName (propName);
5228 PropDescr *prJThread = new PropDescr (propID, propName);
5229 prJThread->uname = dbe_strdup (GTXT ("Java Thread"));
5230 prJThread->vtype = TYPE_OBJ;
5231 dDscr->addProperty (prJThread);
5236 PropDescr *prop = new PropDescr (PROP_OMPSTATE, NTXT ("OMPSTATE"));
5237 prop->uname = dbe_strdup (GTXT ("OpenMP state"));
5238 prop->vtype = TYPE_UINT32;
5239 char * stateNames [OMP_LAST_STATE] = OMP_THR_STATE_STRINGS;
5240 char * stateUNames[OMP_LAST_STATE] = OMP_THR_STATE_USTRINGS;
5241 for (int ii = 0; ii < OMP_LAST_STATE; ii++)
5242 prop->addState (ii, stateNames[ii], stateUNames[ii]);
5243 dDscr->addProperty (prop);
5245 // add PROP_CPRID to profiling data (not same as omptrace's PROP_CPRID)
5246 prop = dDscr->getProp (PROP_CPRID);
5249 VType_type type = prop->vtype;
5250 assert (type == TYPE_OBJ); //see 7040526
5252 prop = new PropDescr (PROP_CPRID, NTXT ("CPRID")); //profiling PROP_CPRID
5253 prop->uname = dbe_strdup (GTXT ("OpenMP parallel region"));
5254 prop->vtype = TYPE_OBJ;
5255 dDscr->addProperty (prop);
5257 // add PROP_TSKID to profiling data (not same as omptrace's PROP_TSKID)
5258 prop = dDscr->getProp (PROP_TSKID);
5261 VType_type type = prop->vtype;
5262 assert (type == TYPE_OBJ); //see 7040526
5264 prop = new PropDescr (PROP_TSKID, NTXT ("TSKID")); //profiling PROP_TSKID
5265 prop->uname = dbe_strdup (GTXT ("OpenMP task"));
5266 prop->vtype = TYPE_OBJ;
5267 dDscr->addProperty (prop);
5269 char *progress_bar_msg = dbe_sprintf (NTXT ("%s %s: %s"), NTXT (" "),
5270 GTXT ("Processing CallStack Data"),
5271 get_basename (expt_name));
5272 int progress_bar_percent = -1;
5273 long deltaReport = 5000;
5274 long nextReport = 0;
5276 long size = dDscr->getSize ();
5277 // bool resolve_frinfo_pipelined = size > FRINFO_PIPELINE_SIZE_LIMIT && !ompavail;
5278 bool resolve_frinfo_pipelined = false;
5280 Map<uint64_t, uint64_t> *nodeCache = NULL;
5281 Map<uint64_t, uint64_t> *frameInfoCache = NULL;
5282 if (size > FRINFO_CACHEOPT_SIZE_LIMIT && dversion == NULL)
5284 frameInfoCache = new CacheMap<uint64_t, uint64_t>;
5285 nodeCache = new CacheMap<uint64_t, uint64_t>;
5288 pushCnt = popCnt = pushCnt3 = popCnt3 = 0;
5291 FramePacket *fp = NULL;
5292 // DbeThreadPool * threadPool = new DbeThreadPool(5);
5293 fp = new FramePacket;
5294 fp->stack = new Vector<Vaddr>;
5295 fp->jstack = new Vector<Vaddr>;
5296 fp->ompstack = new Vector<Vaddr>;
5300 // piggyback on post-processing to calculate exp->last_event
5301 const hrtime_t _exp_start_time = getStartTime (); // wall clock time
5302 hrtime_t exp_duration = getLastEvent () == ZERO_TIME ? 0
5303 : getLastEvent () - _exp_start_time; // zero-based
5308 for (long i = 0; i < size; i++)
5310 if (i == nextReport)
5312 int percent = (int) (i * 100 / size);
5313 if (percent > progress_bar_percent)
5315 progress_bar_percent += 10;
5316 theApplication->set_progress (percent, progress_bar_msg);
5318 nextReport += deltaReport;
5321 uint32_t thrid = (uint32_t) dataThrId->fetchInt (i);
5322 hrtime_t tstamp = (hrtime_t) dataTStamp->fetchLong (i);
5324 // piggyback on post-processing to calculate exp->last_event
5326 hrtime_t relative_timestamp = tstamp - _exp_start_time;
5327 if (exp_duration < relative_timestamp)
5328 exp_duration = relative_timestamp;
5330 uint64_t frinfo = (uint64_t) dataFrinfo->fetchLong (i);
5332 RawFramePacket *rfp = NULL;
5335 // CacheMap does not work with NULL key
5336 if (frameInfoCache != NULL)
5337 rfp = (RawFramePacket *) frameInfoCache->get (frinfo);
5341 rfp = find_frame_packet (frinfo);
5344 if (frameInfoCache != NULL)
5345 frameInfoCache->put (frinfo, (uint64_t) rfp);
5352 // Process OpenMP properties
5355 fp->omp_state = rfp ? rfp->omp_state : 0;
5356 dDscr->setValue (PROP_OMPSTATE, i, fp->omp_state);
5358 fp->omp_cprid = mapPRid->get (thrid, tstamp, mapPRid->REL_EQLE);
5359 void *omp_preg = mapPReg->get (thrid, tstamp, mapPReg->REL_EQLE);
5362 char *idxname = NTXT ("OMP_preg");
5363 int idxtype = dbeSession->findIndexSpaceByName (idxname);
5366 Histable *preg0 = dbeSession->findObjectById (Histable::INDEXOBJ, idxtype, (int64_t) 0);
5369 Vector<Histable*> pregs;
5370 pregs.append (preg0);
5371 omp_preg = cstack->add_stack (&pregs);
5372 mapPReg->put (thrid, tstamp, omp_preg);
5376 dDscr->setObjValue (PROP_CPRID, i, omp_preg); //profiling PROP_CPRID
5377 void *omp_task = mapTask->get (thrid, tstamp, mapTask->REL_EQLE);
5380 char *idxname = NTXT ("OMP_task");
5381 int idxtype = dbeSession->findIndexSpaceByName (idxname);
5384 Histable *task0 = dbeSession->findObjectById (Histable::INDEXOBJ, idxtype, (int64_t) 0);
5387 Vector<Histable*> tasks;
5388 tasks.append (task0);
5389 omp_task = cstack->add_stack (&tasks);
5390 mapTask->put (thrid, tstamp, omp_task);
5394 dDscr->setObjValue (PROP_TSKID, i, omp_task); //profiling PROP_TSKID
5402 // Construct the native stack
5403 fp->stack->reset ();
5404 Vaddr leafpc = dDscr->getULongValue (PROP_LEAFPC, i);
5406 fp->stack->append (leafpc);
5407 UIDnode *node = rfp ? rfp->uidn : NULL;
5410 if (node->next == node)
5411 // this node contains link_uid
5412 node = find_uid_node (node->uid);
5415 fp->stack->append (node->val);
5420 int last = fp->stack->size () - 1;
5423 switch (fp->stack->fetch (last))
5425 case SP_TRUNC_STACK_MARKER:
5426 fp->truncated = (Vaddr) SP_TRUNC_STACK_MARKER;
5427 fp->stack->remove (last);
5429 case SP_FAILED_UNWIND_MARKER:
5430 fp->truncated = (Vaddr) SP_FAILED_UNWIND_MARKER;
5431 fp->stack->remove (last);
5436 // Construct the Java stack
5437 fp->jstack->reset ();
5438 node = rfp ? rfp->uidj : NULL;
5441 if (node->next == node)
5443 // this node contains link_uid
5447 // CacheMap does not work with NULL key
5448 if (nodeCache != NULL)
5449 n = (UIDnode *) nodeCache->get (node->uid);
5453 n = find_uid_node (node->uid);
5456 if (nodeCache != NULL)
5457 nodeCache->put (node->uid, (uint64_t) n);
5464 fp->jstack->append (node->val);
5468 fp->jtruncated = false;
5469 last = fp->jstack->size () - 1;
5470 if (last >= 1 && fp->jstack->fetch (last) == SP_TRUNC_STACK_MARKER)
5472 fp->jtruncated = true;
5473 fp->jstack->remove (last);
5474 fp->jstack->remove (last - 1);
5477 // Construct the OpenMP stack
5480 fp->ompstack->reset ();
5481 if (rfp && rfp->omp_uid)
5484 fp->ompstack->append (leafpc);
5485 node = rfp->omp_uid;
5488 if (node->next == node)
5489 // this node contains link_uid
5490 node = find_uid_node (node->uid);
5493 fp->ompstack->append (node->val);
5497 fp->omptruncated = false;
5498 last = fp->ompstack->size () - 1;
5501 switch (fp->ompstack->fetch (last))
5503 case SP_TRUNC_STACK_MARKER:
5504 fp->omptruncated = (Vaddr) SP_TRUNC_STACK_MARKER;
5505 fp->ompstack->remove (last);
5507 case SP_FAILED_UNWIND_MARKER:
5508 fp->omptruncated = (Vaddr) SP_FAILED_UNWIND_MARKER;
5509 fp->ompstack->remove (last);
5515 cstack->add_stack (dDscr, i, fp, NULL);
5518 // piggyback on post-processing to calculate exp->last_event
5520 hrtime_t exp_end_time = _exp_start_time + exp_duration;
5521 update_last_event (exp_end_time);
5528 GTXT ("*** Warning: %d frameinfo packets are missing from total of %d when resolving %s."),
5529 missed_fi, total_fi, dDscr->getName ());
5530 warnq->append (new Emsg (CMSG_WARN, sb));
5533 // threadPool->wait_group();
5534 // delete threadPool;
5535 theApplication->set_progress (0, NTXT (""));
5536 free (progress_bar_msg);
5537 if (!resolve_frinfo_pipelined && fp != NULL)
5539 delete fp->ompstack;
5544 delete frameInfoCache;
5545 frameInfoCache = NULL;
5551 Experiment::post_process ()
5553 // update non_paused_time after final update to "last_event"
5554 if (resume_ts != MAX_TIME && last_event)
5556 hrtime_t ts = last_event - exp_start_time;
5557 hrtime_t delta = ts - resume_ts;
5558 non_paused_time += delta;
5559 resume_ts = MAX_TIME; // collection is paused
5562 // GC: prune events outside of experiment duration, calculate GC duration, update indices
5565 gc_duration = ZERO_TIME;
5566 if (gcevents != NULL)
5568 // delete events that finish before exp_start_time or start after last_event
5569 for (int ii = 0; ii < gcevents->size ();)
5571 gcevent = gcevents->fetch (ii);
5572 if (gcevent->end - exp_start_time < 0
5573 || last_event - gcevent->start < 0)
5574 delete gcevents->remove (ii);
5579 Vec_loop (GCEvent*, gcevents, index, gcevent)
5581 gcevent->id = index + 1; // renumber to account for any deleted events
5582 if (gcevent->start - exp_start_time < 0 || gcevent->start == ZERO_TIME)
5583 // truncate events that start before experiment start
5584 gcevent->start = exp_start_time;
5585 if (last_event - gcevent->end < 0)
5586 // truncate events that end after experiment end
5587 gcevent->end = last_event;
5588 gc_duration += gcevent->end - gcevent->start;
5592 Experiment::Exp_status
5593 Experiment::find_expdir (char *path)
5595 // This function checks that the experiment directory
5596 // is of the proper form, and accessible
5600 expt_name = dbe_strdup (path);
5602 // Check that the name ends in .er
5603 size_t i = strlen (path);
5604 if (i > 0 && path[i - 1] == '/')
5607 if (i < 4 || strcmp (&path[i - 3], NTXT (".er")) != 0)
5609 Emsg *m = new Emsg (CMSG_FATAL,
5610 GTXT ("*** Error: not a valid experiment name"));
5616 // Check if new directory structure (i.e., no pointer file)
5617 if (dbe_stat (path, &sbuf))
5619 Emsg *m = new Emsg (CMSG_FATAL, GTXT ("*** Error: experiment not found"));
5624 if (S_ISDIR (sbuf.st_mode) == 0)
5626 // ignore pointer-file experiments
5627 Emsg *m = new Emsg (CMSG_FATAL,
5628 GTXT ("*** Error: experiment was recorded with an earlier version, and can not be read"));
5638 Experiment::purge ()
5640 // This routine will purge all of the caches of releasable storage.
5641 for (int i = 0; i < dataDscrs->size (); ++i)
5643 DataDescriptor *dataDscr = dataDscrs->fetch (i);
5644 if (dataDscr == NULL)
5649 delete cstackShowHide;
5650 cstack = CallStack::getInstance (this);
5651 cstackShowHide = CallStack::getInstance (this);
5655 Experiment::resetShowHideStack ()
5657 delete cstackShowHide;
5658 cstackShowHide = CallStack::getInstance (this);
5661 #define GET_INT_VAL(v, s, len) \
5662 for (v = len = 0; isdigit(*s); s++, len++) { v = v * 10 + (*s -'0'); }
5665 dir_name_cmp (const void *a, const void *b)
5667 char *s1 = *((char **) a);
5668 char *s2 = *((char **) b);
5671 if (isdigit (*s1) && isdigit (*s2))
5673 int v1, v2, len1, len2;
5674 GET_INT_VAL (v1, s1, len1);
5675 GET_INT_VAL (v2, s2, len2);
5691 Experiment::get_descendants_names ()
5693 char *dir_name = get_expt_name ();
5694 if (dir_name == NULL)
5696 DIR *exp_dir = opendir (dir_name);
5697 if (exp_dir == NULL)
5699 Vector<char*> *exp_names = new Vector<char*>();
5700 for (struct dirent *entry = readdir (exp_dir); entry;
5701 entry = readdir (exp_dir))
5703 if (entry->d_name[0] == '_' || strncmp (entry->d_name, "M_r", 3) == 0)
5705 char *dpath = dbe_sprintf (NTXT ("%s/%s"), dir_name, entry->d_name);
5707 if (dbe_stat (dpath, &sbuf) == 0 && S_ISDIR (sbuf.st_mode))
5708 exp_names->append (dpath);
5714 if (exp_names->size () == 0)
5719 exp_names->sort (dir_name_cmp);
5724 Experiment::create_dir (char *dname)
5726 if (mkdir (dname, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0)
5731 if (dbe_stat (dname, &sbuf) != 0 || S_ISDIR (sbuf.st_mode) == 0)
5733 char *buf = dbe_sprintf (GTXT ("Unable to create directory `%s'\n"),
5735 errorq->append (new Emsg (CMSG_ERROR, buf));
5743 Experiment::get_arch_name ()
5745 if (arch_name == NULL)
5747 // Determine the master experiment directory.
5748 // omazur: should do it in a less hacky way. XXXX
5749 char *ptr = strstr_r (expt_name, DESCENDANT_EXPT_KEY);
5750 ptr = ptr ? ptr + 3 : expt_name + strlen (expt_name);
5751 arch_name = dbe_sprintf (NTXT ("%.*s/%s"), (int) (ptr - expt_name),
5752 expt_name, SP_ARCHIVES_DIR);
5758 Experiment::get_fndr_arch_name ()
5760 if (fndr_arch_name == NULL)
5761 // Determine the founder experiment directory.
5762 fndr_arch_name = dbe_strdup (get_arch_name ());
5763 return fndr_arch_name;
5768 HASH_NAME_LEN = 11 // (64 / 6 + 1) = 11
5772 get_hash_string (char buf[HASH_NAME_LEN + 1], uint64_t hash)
5774 static const char *har =
5775 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
5776 for (int i = 0; i < HASH_NAME_LEN; i++)
5778 buf[i] = har[hash & 0x3f];
5781 buf[HASH_NAME_LEN] = 0;
5786 Experiment::getNameInArchive (const char *fname, bool archiveFile)
5788 char *aname = get_archived_name (fname, archiveFile);
5789 char *ret = dbe_sprintf (NTXT ("%s/%s"), get_arch_name (), aname);
5794 #define MAX_ARCHIVE_FILENAME_LEN (256 - HASH_NAME_LEN - 2)
5797 Experiment::get_archived_name (const char *fname, bool archiveFile)
5799 char *bname = get_basename (fname);
5802 char dirnameHash[HASH_NAME_LEN + 1];
5803 // Treat "a.out" and "./a.out" equally
5804 uint64_t hash = bname != fname ? crc64 (fname, bname - fname)
5805 : crc64 (NTXT ("./"), 2);
5806 get_hash_string (dirnameHash, hash);
5809 long bname_len = dbe_sstrlen (bname);
5810 if (bname_len > MAX_ARCHIVE_FILENAME_LEN)
5812 char basenameHash[HASH_NAME_LEN + 1];
5813 hash = crc64 (bname, bname_len);
5814 get_hash_string (basenameHash, hash);
5815 ret = dbe_sprintf ("%.*s%c%s_%s",
5816 MAX_ARCHIVE_FILENAME_LEN - HASH_NAME_LEN - 1,
5817 bname, archiveFile ? '.' : '_',
5818 dirnameHash, basenameHash);
5821 ret = dbe_sprintf ("%s%c%s", bname, archiveFile ? '.' : '_', dirnameHash);
5826 Experiment::checkFileInArchive (const char *fname, bool archiveFile)
5830 char *aname = get_archived_name (fname, archiveFile);
5831 DbeFile *df = archiveMap->get (aname);
5834 return strdup (df->get_location ());
5838 return founder_exp->checkFileInArchive (fname, archiveFile);
5846 SegMemCmp (const void *a, const void *b)
5848 SegMem *item1 = *((SegMem **) a);
5849 SegMem *item2 = *((SegMem **) b);
5850 return item1->unload_time > item2->unload_time ? 1 :
5851 item1->unload_time == item2->unload_time ? 0 : -1;
5855 Experiment::update_ts_in_maps (Vaddr addr, hrtime_t ts)
5857 Vector<SegMem *> *segMems = (Vector<SegMem *> *) maps->values ();
5858 if (!segMems->is_sorted ())
5860 Dprintf (DEBUG_MAPS, NTXT ("update_ts_in_maps: segMems.size=%lld\n"), (long long) segMems->size ());
5861 segMems->sort (SegMemCmp);
5863 for (int i = 0, sz = segMems ? segMems->size () : 0; i < sz; i++)
5865 SegMem *sm = segMems->fetch (i);
5866 if (ts < sm->unload_time)
5870 sm = segMems->fetch (i);
5871 if ((addr >= sm->base) && (addr < sm->base + sm->size))
5873 Dprintf (DEBUG_MAPS,
5874 "update_ts_in_maps: old:%u.%09u -> %u.%09u addr=0x%08llx size=%lld\n",
5875 (unsigned) (sm->load_time / NANOSEC),
5876 (unsigned) (sm->load_time % NANOSEC),
5877 (unsigned) (ts / NANOSEC), (unsigned) (ts % NANOSEC),
5878 (unsigned long long) sm->base, (long long) sm->size);
5879 maps->remove (sm->base, sm->load_time);
5881 maps->insert (sm->base, ts, sm);
5887 Dprintf (DEBUG_MAPS, "update_ts_in_maps: NOT FOUND %u.%09u addr=0x%08llx\n",
5888 (unsigned) (ts / NANOSEC), (unsigned) (ts % NANOSEC),
5889 (unsigned long long) addr);
5894 Experiment::map_Vaddr_to_PC (Vaddr addr, hrtime_t ts)
5896 // Look up in the hash table first
5897 int hash = (((int) addr) >> 8) & (HTableSize - 1);
5898 SegMem *si = smemHTable[hash];
5899 if (si == NULL || addr < si->base || addr >= si->base + si->size
5900 || ts < si->load_time || ts >= si->unload_time)
5902 // Not in the hash table
5903 si = (SegMem*) maps->locate (addr, ts);
5904 if (si == NULL || addr < si->base || addr >= si->base + si->size
5905 || ts < si->load_time || ts >= si->unload_time)
5907 si = update_ts_in_maps (addr, ts);
5909 return dbeSession->get_Unknown_Function ()->find_dbeinstr (PCInvlFlag, addr);
5911 smemHTable[hash] = si;
5914 // Calculate the file offset of 'addr'
5915 uint64_t f_offset = si->get_file_offset () + (addr - si->base);
5918 if (si->obj->get_type () == Histable::LOADOBJECT)
5920 LoadObject *lo = (LoadObject*) si->obj;
5921 lo->sync_read_stabs ();
5922 instr = lo->find_dbeinstr (f_offset);
5926 int hash2 = ((((int) addr) & 0xFFFC00) | (((int) f_offset) >> 2))
5928 instr = instHTable[hash2];
5929 if (instr == NULL || instr->func != si->obj || instr->addr != f_offset)
5931 // Not in the hash table
5932 Function *fp = (Function *) si->obj;
5933 instr = fp->find_dbeinstr (0, f_offset);
5934 instHTable[hash2] = instr;
5937 if (!instr->func->isUsed)
5939 instr->func->isUsed = true;
5940 instr->func->module->isUsed = true;
5941 instr->func->module->loadobject->isUsed = true;
5947 Experiment::map_event_to_Sample (hrtime_t ts)
5952 // Check if the last used sample is the right one,
5953 // if not then find it.
5954 if (sample_last_used && ts >= sample_last_used->start_time
5955 && ts <= sample_last_used->end_time)
5956 return sample_last_used;
5958 Vec_loop (Sample*, samples, index, sample)
5960 if ((ts >= sample->start_time) &&
5961 (ts <= sample->end_time))
5963 sample_last_used = sample;
5967 return (Sample*) NULL;
5971 Experiment::map_event_to_GCEvent (hrtime_t ts)
5976 // Check if the last used sample is the right one,
5977 // if not then find it.
5978 if (gcevent_last_used && ts >= gcevent_last_used->start
5979 && ts <= gcevent_last_used->end)
5980 return gcevent_last_used;
5981 Vec_loop (GCEvent*, gcevents, index, gcevent)
5983 if ((ts >= gcevent->start) &&
5984 (ts <= gcevent->end))
5986 gcevent_last_used = gcevent;
5990 return (GCEvent*) NULL;
5994 Experiment::map_jmid_to_PC (Vaddr mid, int bci, hrtime_t ts)
5996 if (mid == 0 || jmaps == NULL)
5997 // special case: no Java stack was recorded, bci - error code
5998 return dbeSession->get_JUnknown_Function ()->find_dbeinstr (0, bci);
6000 JMethod *jmthd = jmidHTable->get (mid);
6003 jmthd = (JMethod *) jmaps->locate_exact_match (mid, ts);
6005 jmidHTable->put (mid, jmthd);
6007 if (jmthd == NULL || jmthd->get_type () != Histable::FUNCTION)
6008 return dbeSession->get_JUnknown_Function ()->find_dbeinstr (0, (uint64_t) mid);
6009 return jmthd->find_dbeinstr (0, bci);
6013 Experiment::fetch_comments ()
6015 return commentq->fetch ();
6019 Experiment::fetch_runlogq ()
6021 return runlogq->fetch ();
6025 Experiment::fetch_errors ()
6027 return errorq->fetch ();
6031 Experiment::fetch_warnings ()
6033 return warnq->fetch ();
6037 Experiment::fetch_notes ()
6039 return notesq->fetch ();
6043 Experiment::fetch_ifreq ()
6045 return ifreqq->fetch ();
6049 Experiment::fetch_pprocq ()
6051 return pprocq->fetch ();
6055 Experiment::read_dyntext_file ()
6057 dyntext_name = dbe_sprintf ("%s/%s", expt_name, SP_DYNTEXT_FILE);
6058 Data_window *dwin = new Data_window (dyntext_name);
6059 if (dwin->not_opened ())
6064 dwin->need_swap_endian = need_swap_endian;
6066 Function *fp = NULL;
6067 char *progress_msg = NULL; // Message for the progress bar
6068 for (int64_t offset = 0;;)
6070 DT_common *cpckt = (DT_common *) dwin->bind (offset, sizeof (DT_common));
6073 size_t cpcktsize = dwin->decode (cpckt->size);
6074 cpckt = (DT_common *) dwin->bind (offset, cpcktsize);
6077 switch (dwin->decode (cpckt->type))
6081 DT_header *hdr = (DT_header*) cpckt;
6082 hrtime_t ts = dwin->decode (hdr->time) + exp_start_time;
6083 SegMem *si = (SegMem*) maps->locate (dwin->decode (hdr->vaddr), ts);
6084 fp = si ? (Function *) si->obj : NULL;
6085 if (fp && (fp->get_type () != Histable::FUNCTION
6086 || !(fp->flags & FUNC_FLAG_DYNAMIC)))
6093 fp->img_fname = dyntext_name;
6094 fp->img_offset = offset + sizeof (DT_common);
6095 if ((platform != Intel) && (platform != Amd64))
6097 // Find out 'save' instruction address for SPARC
6098 char *ptr = ((char*) cpckt) + sizeof (DT_common);
6099 size_t img_size = cpcktsize - sizeof (DT_common);
6100 for (size_t i = 0; i < img_size; i += 4)
6101 if (ptr[i] == (char) 0x9d && ptr[i + 1] == (char) 0xe3)
6112 char *srcname = dbe_strndup (((char*) cpckt) + sizeof (DT_common),
6113 cpcktsize - sizeof (DT_common));
6114 LoadObject *ds = fp->module ? fp->module->loadobject : NULL;
6115 assert (ds != NULL);
6116 Module *mod = dbeSession->createModule (ds, NULL);
6117 mod->set_file_name (srcname);
6121 // It's most likely (unknown). Remove fp from it.
6122 long idx = fp->module->functions->find (fp);
6124 fp->module->functions->remove (idx);
6127 mod->functions->append (fp);
6133 DT_lineno *ltab = (DT_lineno*) ((char*) cpckt + sizeof (DT_common));
6134 size_t sz = (cpcktsize - sizeof (DT_common)) / sizeof (DT_lineno);
6137 // Take care of the progress bar
6138 static int percent = 0;
6139 static long deltaReport = sz / 100; // 1000;
6140 static long nextReport = 0;
6141 static long progress_count = 0;
6142 fp->pushSrcFile (fp->getDefSrc (), 0);
6143 for (size_t i = 0; i < sz; i++)
6145 int lineno = dwin->decode (ltab[i].lineno);
6146 if (fp->usrfunc != NULL)
6148 // Update progress bar
6149 if (dbeSession->is_interactive ())
6151 if (progress_count == nextReport)
6156 if (NULL == progress_msg)
6158 progress_msg = dbe_sprintf (GTXT ("Processing Dynamic Text: %s"),
6159 get_basename (expt_name));
6161 theApplication->set_progress (percent, progress_msg);
6162 nextReport += deltaReport;
6167 DbeLine *dbeline = fp->usrfunc->mapPCtoLine (lineno, NULL);
6168 lineno = dbeline != NULL ? dbeline->lineno : -1;
6170 fp->add_PC_info (dwin->decode (ltab[i].offset), lineno);
6176 // skip unknown records
6179 offset += cpcktsize;
6181 free (progress_msg);
6187 Experiment::mapTagValue (Prop_type prop, uint64_t value)
6189 Vector<Histable*> *objs = tagObjs->fetch (prop);
6191 int rt = objs->size () - 1;
6194 int md = (lt + rt) / 2;
6195 Other *obj = (Other*) objs->fetch (md);
6196 if (obj->value64 < value)
6198 else if (obj->value64 > value)
6205 if (sparse_threads && (prop == PROP_THRID || prop == PROP_LWPID))
6206 tag = objs->size () + 1; // "+ 1" related to 7038295
6208 tag = (int) value; // truncation; See 6788767
6210 Other *obj = new Other ();
6211 obj->value64 = value;
6213 if (lt == objs->size ())
6216 objs->insert (lt, obj);
6218 // Update min and max tags
6219 if (prop == PROP_LWPID)
6221 if ((uint64_t) tag < min_lwp)
6222 min_lwp = (uint64_t) tag;
6223 if ((uint64_t) tag > max_lwp)
6224 max_lwp = (uint64_t) tag;
6227 else if (prop == PROP_THRID)
6229 if ((uint64_t) tag < min_thread)
6230 min_thread = (uint64_t) tag;
6231 if ((uint64_t) tag > max_thread)
6232 max_thread = (uint64_t) tag;
6235 else if (prop == PROP_CPUID)
6237 // On Solaris 8, we don't get CPU id -- don't change
6238 if (value != (uint64_t) - 1)
6239 {//YXXX is this related only to solaris 8?
6240 if ((uint64_t) tag < min_cpu)
6241 min_cpu = (uint64_t) tag;
6242 if ((uint64_t) tag > max_cpu)
6243 max_cpu = (uint64_t) tag;
6251 Experiment::getTagObjs (Prop_type prop)
6253 return tagObjs->fetch (prop);
6257 Experiment::getTagObj (Prop_type prop, uint32_t tag)
6259 Vector<Histable*> *objs = tagObjs->fetch (prop);
6262 for (int i = 0; i < objs->size (); i++)
6264 Other *obj = (Other*) objs->fetch (i);
6265 if (obj->tag == tag)
6272 Experiment::map_pckt_to_Jthread (uint32_t tid, hrtime_t tstamp)
6275 return JTHREAD_DEFAULT;
6277 int rt = jthreads_idx->size () - 1;
6280 int md = (lt + rt) / 2;
6281 JThread *jthread = jthreads_idx->fetch (md);
6282 if (jthread->tid < tid)
6284 else if (jthread->tid > tid)
6288 for (; jthread; jthread = jthread->next)
6289 if (tstamp >= jthread->start && tstamp < jthread->end)
6295 return JTHREAD_NONE;
6299 Experiment::get_jthread (uint32_t tid)
6302 return JTHREAD_DEFAULT;
6304 int rt = jthreads_idx->size () - 1;
6307 int md = (lt + rt) / 2;
6308 JThread *jthread = jthreads_idx->fetch (md);
6309 if (jthread->tid < tid)
6311 else if (jthread->tid > tid)
6315 JThread *jthread_first = jthread;
6316 while ((jthread = jthread->next) != NULL)
6317 if (!jthread->is_system () &&
6318 jthread->jthr_id < jthread_first->jthr_id)
6319 jthread_first = jthread;
6320 return jthread_first;
6324 return JTHREAD_NONE;
6329 Experiment::newDataDescriptor (int data_id, int flags,
6330 DataDescriptor *master_dDscr)
6332 DataDescriptor *dataDscr = NULL;
6333 if (data_id >= 0 && data_id < dataDscrs->size ())
6335 dataDscr = dataDscrs->fetch (data_id);
6336 if (dataDscr != NULL)
6340 assert (data_id >= 0 && data_id < DATA_LAST);
6341 const char *nm = get_prof_data_type_name (data_id);
6342 const char *uname = get_prof_data_type_uname (data_id);
6345 dataDscr = new DataDescriptor (data_id, nm, uname, master_dDscr);
6347 dataDscr = new DataDescriptor (data_id, nm, uname, flags);
6348 dataDscrs->store (data_id, dataDscr);
6352 Vector<DataDescriptor*> *
6353 Experiment::getDataDescriptors ()
6355 Vector<DataDescriptor*> *result = new Vector<DataDescriptor*>;
6356 for (int i = 0; i < dataDscrs->size (); ++i)
6359 dd = get_raw_events (i); // force data fetch
6361 result->append (dd);
6367 Experiment::getDataDescriptor (int data_id)
6369 if (data_id < 0 || data_id >= dataDscrs->size ())
6371 return dataDscrs->fetch (data_id);
6375 Experiment::newPacketDescriptor (int kind, DataDescriptor *dDscr)
6377 PacketDescriptor *pDscr = new PacketDescriptor (dDscr);
6378 pcktDscrs->store (kind, pDscr);
6383 Experiment::getPacketDescriptor (int kind)
6385 if (kind < 0 || kind >= pcktDscrs->size ())
6387 return pcktDscrs->fetch (kind);
6391 Experiment::set_clock (int clk)
6400 if (minclock == 0 || minclock > clk)
6406 JThread::is_system ()
6408 if (group_name == NULL)
6410 return strcmp (group_name, NTXT ("system")) == 0;
6414 Experiment::dump_stacks (FILE *outfile)
6416 cstack->print (outfile);
6420 Experiment::dump_map (FILE *outfile)
6424 fprintf (outfile, GTXT ("Experiment %s\n"), get_expt_name ());
6425 fprintf (outfile, GTXT ("Address Size (hex) Load time Unload time Checksum Name\n"));
6426 Vec_loop (SegMem*, seg_items, index, s)
6430 hr2timestruc (&load, (s->load_time - exp_start_time));
6431 if (load.tv_nsec < 0)
6434 load.tv_nsec += NANOSEC;
6436 if (s->unload_time == MAX_TIME)
6442 hr2timestruc (&unload, (s->unload_time - exp_start_time));
6443 if (load.tv_nsec < 0)
6446 load.tv_nsec += NANOSEC;
6449 "0x%08llx %8lld (0x%08llx) %5lld.%09lld %5lld.%09lld \"%s\"\n",
6450 (long long) s->base, (long long) s->size, (long long) s->size,
6451 (long long) load.tv_sec, (long long) load.tv_nsec,
6452 (long long) unload.tv_sec, (long long) unload.tv_nsec,
6453 s->obj->get_name ());
6455 fprintf (outfile, NTXT ("\n"));
6459 * Copy file to archive
6463 * @return 0 - success, 1 - error
6466 Experiment::copy_file_to_archive (const char *name, const char *aname, int hide_msg)
6469 int fd_w = ::open64 (aname, O_WRONLY | O_CREAT | O_EXCL, 0644);
6472 if (errno == EEXIST)
6474 fprintf (stderr, GTXT ("er_archive: unable to copy `%s': %s\n"),
6475 name, STR (strerror (errno)));
6479 if (dbe_stat_file (name, NULL) != 0)
6481 fprintf (stderr, GTXT ("er_archive: cannot access file `%s': %s\n"),
6482 name, STR (strerror (errno)));
6487 int fd_r = ::open64 (name, O_RDONLY);
6490 fprintf (stderr, GTXT ("er_archive: unable to open `%s': %s\n"),
6491 name, strerror (errno));
6498 fprintf (stderr, GTXT ("Copying `%s' to `%s'\n"), name, aname);
6499 bool do_unlink = false;
6502 unsigned char buf[65536];
6504 n = (int) read (fd_r, (void *) buf, sizeof (buf));
6507 n1 = (int) write (fd_w, buf, n);
6510 fprintf (stderr, GTXT ("er_archive: unable to write %d bytes to `%s': %s\n"),
6511 n, aname, STR (strerror (errno)));
6518 struct stat64 s_buf;
6519 if (fstat64 (fd_r, &s_buf) == 0)
6521 struct utimbuf u_buf;
6522 u_buf.actime = s_buf.st_atime;
6523 u_buf.modtime = s_buf.st_mtime;
6524 utime (aname, &u_buf);
6530 fprintf (stderr, GTXT ("er_archive: remove %s\n"), aname);
6538 * Copy file to common archive
6540 * Calculate checksum
6541 * Generate file name to be created in common archive
6542 * Check if it is not in common archive yet
6543 * Copy file to the common archive directory if it is not there yet
6544 * Create symbolic link: "aname" -> "caname", where "caname" is the name in common archive
6545 * @param name - original file name
6546 * @param aname - file name in experiment archive
6547 * @param common_archive - common archive directory
6548 * @return 0 - success, 1 - error
6551 Experiment::copy_file_to_common_archive (const char *name, const char *aname,
6553 const char *common_archive,
6556 if (!name || !aname || !common_archive)
6559 fprintf (stderr, GTXT ("er_archive: Internal error: file name is NULL\n"));
6561 fprintf (stderr, GTXT ("er_archive: Internal error: file name in archive is NULL\n"));
6562 if (!common_archive)
6563 fprintf (stderr, GTXT ("er_archive: Internal error: path to common archive is NULL\n"));
6566 // Check if file is already archived
6567 if (dbe_stat (aname, NULL) == 0)
6568 return 0; // File is already archived
6569 // Generate full path to common archive directory
6571 char *abs_aname = NULL;
6572 if ((common_archive[0] != '/') || (aname[0] != '/'))
6574 long size = pathconf (NTXT ("."), _PC_PATH_MAX);
6577 fprintf (stderr, GTXT ("er_archive: Fatal error: pathconf(\".\", _PC_PATH_MAX) failed\n"));
6580 char *buf = (char *) malloc ((size_t) size);
6583 fprintf (stderr, GTXT ("er_archive: Fatal error: unable to allocate memory\n"));
6586 char *ptr = getcwd (buf, (size_t) size);
6589 fprintf (stderr, GTXT ("er_archive: Fatal error: cannot determine current directory\n"));
6593 if (common_archive[0] != '/')
6594 cad = dbe_sprintf (NTXT ("%s/%s"), ptr, common_archive);
6596 cad = dbe_strdup (common_archive);
6597 if (aname[0] != '/')
6598 abs_aname = dbe_sprintf (NTXT ("%s/%s"), ptr, aname);
6600 abs_aname = dbe_strdup (aname);
6605 cad = dbe_strdup (common_archive);
6606 abs_aname = dbe_strdup (aname);
6608 // Calculate checksum
6609 char * errmsg = NULL;
6610 uint32_t crcval = get_cksum (name, &errmsg);
6617 fprintf (stderr, GTXT ("er_archive: Fatal error: %s\n"), errmsg);
6622 GTXT ("er_archive: Fatal error: get_cksum(%s) returned %d\n"),
6626 // Generate file name to be created in common archive
6627 char *fname = get_basename (name);
6628 char *abs_caname = dbe_sprintf (NTXT ("%s/%u_%s"), cad, crcval, fname);
6629 if (abs_caname == NULL)
6634 GTXT ("er_archive: Fatal error: unable to allocate memory\n"));
6637 // Check if full name is not too long
6638 long len = dbe_sstrlen (abs_caname);
6639 long max = pathconf (cad, _PC_PATH_MAX);
6640 if ((max < 0) || (len <= 0))
6642 fprintf (stderr, GTXT ("er_archive: Fatal error: pathconf(%s, _PC_PATH_MAX) failed\n"),
6651 // Try to truncate the name
6652 if ((len - max) <= dbe_sstrlen (fname))
6654 // Yes, we can do it
6655 abs_caname[max - 1] = 0;
6657 fprintf (stderr, GTXT ("er_archive: file path is too long - truncated:%s\n"),
6661 // Check if file name is not too long
6662 char *cafname = get_basename (abs_caname);
6663 len = dbe_sstrlen (cafname);
6664 max = pathconf (cad, _PC_NAME_MAX);
6665 if ((max < 0) || (len <= 0))
6667 fprintf (stderr, GTXT ("er_archive: Fatal error: pathconf(%s, _PC_NAME_MAX) failed\n"),
6676 // Try to truncate the name
6677 if ((len - max) <= dbe_sstrlen (fname))
6679 // Yes, we can do it
6680 cafname[max - 1] = 0;
6682 fprintf (stderr, GTXT ("er_archive: file name is too long - truncated:%s\n"),
6686 // Copy file to the common archive directory if it is not there yet
6688 if (dbe_stat_file (abs_caname, NULL) != 0)
6690 // Use temporary file to avoid synchronization problems
6691 char *t = dbe_sprintf ("%s/archive_%llx", cad, (unsigned long long) gethrtime());
6693 // Copy file to temporary file
6694 res = copy_file_to_archive (name, t, hide_msg); // hide messages
6697 fprintf (stderr, GTXT ("er_archive: Fatal error: cannot copy file %s to temporary file: %s\n"),
6705 // Set read-only permissions
6706 struct stat64 statbuf;
6707 if (0 == dbe_stat_file (name, &statbuf))
6709 mode_t mask = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
6710 mode_t mode = statbuf.st_mode & mask;
6713 // Try to rename temporary file "t" to "abs_caname"
6714 // res = link(t, abs_caname); // link() fails on some f/s - use rename()
6715 res = rename (t, abs_caname);
6718 if (errno != EEXIST)
6720 fprintf (stderr, GTXT ("er_archive: Fatal error: rename(%s, %s) returned error: %d\n"),
6721 t, abs_caname, res);
6728 // File "abs_caname" is already there - continue
6738 if (common_archive[0] != '/' && aname[0] != '/')
6740 // compare one relative path to another and find common beginning
6741 char *rel_caname = dbe_sprintf ("%s/%s", common_archive, cafname);
6742 if (rel_caname == NULL)
6744 fprintf (stderr, GTXT ("er_archive: Fatal error: unable to allocate memory\n"));
6747 lname = get_relative_link (rel_caname, aname);
6752 if (abs_aname == NULL)
6754 fprintf (stderr, GTXT ("er_archive: Fatal error: unable to allocate memory\n"));
6757 lname = get_relative_link (abs_caname, abs_aname);
6760 else // absolute path
6761 lname = dbe_strdup (abs_caname);
6765 fprintf (stderr, GTXT ("er_archive: Fatal error: unable to allocate memory\n"));
6768 // Create symbolic link: aname -> lname
6769 if (dbe_stat_file (abs_caname, NULL) == 0)
6771 res = symlink (lname, aname);
6774 fprintf (stderr, GTXT ("er_archive: Fatal error: symlink(%s, %s) returned error: %d (errno=%s)\n"),
6775 lname, aname, res, strerror (errno));
6781 fprintf (stderr, GTXT ("Created symbolic link %s to file in common archive: %s\n"),
6786 fprintf (stderr, GTXT ("er_archive: Internal error: file does not exist in common archive: %s\n"),
6796 * Copy file to archive
6800 * @param common_archive
6801 * @return 0 - success
6804 Experiment::copy_file (char *name, char *aname, int hide_msg, char *common_archive, int relative_path)
6808 if (0 == copy_file_to_common_archive (name, aname, hide_msg,
6809 common_archive, relative_path))
6811 // Error. For now - fatal error. Message is already printed.
6812 fprintf (stderr, GTXT ("er_archive: Fatal error: cannot copy file %s to common archive %s\n"),
6813 name, common_archive);
6816 return (copy_file_to_archive (name, aname, hide_msg));
6820 Experiment::createLoadObject (const char *path, uint64_t chksum)
6822 LoadObject *lo = dbeSession->createLoadObject (path, chksum);
6823 if (lo->firstExp == NULL)
6824 lo->firstExp = this;
6829 Experiment::createLoadObject (const char *path, const char *runTimePath)
6831 DbeFile *df = findFileInArchive (path, runTimePath);
6832 if (df && (df->get_stat () == NULL))
6833 df = NULL; // No access to file
6834 LoadObject *lo = dbeSession->createLoadObject (path, runTimePath, df);
6835 if (df && (lo->dbeFile->get_location (false) == NULL))
6837 lo->dbeFile->set_location (df->get_location ());
6838 lo->dbeFile->inArchive = df->inArchive;
6839 lo->dbeFile->sbuf = df->sbuf;
6840 lo->dbeFile->experiment = df->experiment;
6841 lo->firstExp = df->experiment;
6843 if (lo->firstExp == NULL)
6845 lo->firstExp = this;
6846 lo->dbeFile->experiment = this;
6852 Experiment::get_source (const char *path)
6854 if (founder_exp && (founder_exp != this))
6855 return founder_exp->get_source (path);
6856 if (sourcesMap == NULL)
6857 sourcesMap = new StringMap<SourceFile*>(1024, 1024);
6858 if (strncmp (path, NTXT ("./"), 2) == 0)
6860 SourceFile *sf = sourcesMap->get (path);
6863 char *fnm = checkFileInArchive (path, false);
6866 sf = new SourceFile (path);
6867 dbeSession->append (sf);
6868 DbeFile *df = sf->dbeFile;
6869 df->set_location (fnm);
6870 df->inArchive = true;
6871 df->check_access (fnm); // init 'sbuf'
6872 df->sbuf.st_mtime = 0; // Don't check timestamps
6876 sf = dbeSession->createSourceFile (path);
6877 sourcesMap->put (path, sf);
6882 Experiment::get_comparable_objs ()
6884 update_comparable_objs ();
6885 if (comparable_objs || dbeSession->expGroups->size () <= 1)
6886 return comparable_objs;
6887 comparable_objs = new Vector<Histable*>(dbeSession->expGroups->size ());
6888 for (long i = 0, sz = dbeSession->expGroups->size (); i < sz; i++)
6890 ExpGroup *gr = dbeSession->expGroups->get (i);
6891 if (groupId == gr->groupId)
6893 comparable_objs->append (this);
6897 for (long i1 = 0, sz1 = gr->exps ? gr->exps->size () : 0; i1 < sz1; i1++)
6899 Experiment *exp = gr->exps->get (i1);
6900 if ((exp->comparable_objs == NULL) && (dbe_strcmp (utargname, exp->utargname) == 0))
6902 exp->phaseCompareIdx = phaseCompareIdx;
6904 h->comparable_objs = comparable_objs;
6908 comparable_objs->append (h);
6910 dump_comparable_objs ();
6911 return comparable_objs;
6915 Experiment::findFileInArchive (const char *fname)
6919 char *aname = get_archived_name (fname);
6920 DbeFile *df = archiveMap->get (aname);
6925 return founder_exp->findFileInArchive (fname);
6930 Experiment::findFileInArchive (const char *className, const char *runTimePath)
6935 const char *fnm = NULL;
6936 if (strncmp (runTimePath, NTXT ("zip:"), 4) == 0)
6937 fnm = runTimePath + 4;
6938 else if (strncmp (runTimePath, NTXT ("jar:file:"), 9) == 0)
6939 fnm = runTimePath + 9;
6942 const char *s = strchr (fnm, '!');
6945 char *s1 = dbe_strndup (fnm, s - fnm);
6946 df = findFileInArchive (s1);
6950 df = findFileInArchive (fnm);
6952 df->filetype |= DbeFile::F_JAR_FILE;
6954 else if (strncmp (runTimePath, NTXT ("file:"), 5) == 0)
6956 fnm = runTimePath + 5;
6957 df = findFileInArchive (fnm);
6960 df = findFileInArchive (runTimePath);
6963 df = findFileInArchive (className);