1/* Copyright (C) 2021 Free Software Foundation, Inc. 2 Contributed by Oracle. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21#include "config.h" 22#include <errno.h> 23#include <utime.h> 24#include <alloca.h> 25#include <dirent.h> 26#include <ctype.h> 27#include <unistd.h> 28#include <stdio.h> 29#include <stdlib.h> 30#include <sys/param.h> 31#include <set> 32 33#include "util.h" 34#include "CacheMap.h" 35#include "DbeFile.h" 36#include "DbeCacheMap.h" 37#include "DefaultHandler.h" 38#include "DefaultMap2D.h" 39#include "Emsg.h" 40#include "Elf.h" 41#include "SAXParser.h" 42#include "SAXParserFactory.h" 43#include "StringBuilder.h" 44#include "DbeSession.h" 45#include "DbeThread.h" 46#include "Application.h" 47#include "CallStack.h" 48#include "Experiment.h" 49#include "Exp_Layout.h" 50#include "DataStream.h" 51#include "Expression.h" 52#include "Function.h" 53#include "HeapMap.h" 54#include "LoadObject.h" 55#include "Module.h" 56#include "Ovw_data.h" 57#include "PRBTree.h" 58#include "Sample.h" 59#include "SegMem.h" 60#include "StringMap.h" 61#include "UserLabel.h" 62#include "Table.h" 63#include "dbe_types.h" 64#include "FileData.h" 65#include "cc_libcollector.h" 66#include "ExpGroup.h" 67 68int nPush; 69int nPop; 70int pushCnt; 71int popCnt; 72int pushCnt3; 73int popCnt3; 74 75struct Experiment::UIDnode 76{ 77 uint64_t uid; 78 uint64_t val; 79 UIDnode *next; 80}; 81 82struct Experiment::RawFramePacket 83{ 84 uint64_t uid; 85 UIDnode *uidn; 86 UIDnode *uidj; 87 UIDnode *omp_uid; 88 uint32_t omp_state; 89}; 90 91static hrtime_t 92parseTStamp (const char *s) 93{ 94 hrtime_t ts = (hrtime_t) 0; 95 ts = (hrtime_t) atoi (s) * NANOSEC; 96 s = strchr (s, '.'); 97 if (s != NULL) 98 ts += (hrtime_t) atoi (s + 1); 99 return ts; 100} 101 102class Experiment::ExperimentFile 103{ 104public: 105 106 enum 107 { 108 EF_NOT_OPENED, 109 EF_OPENED, 110 EF_CLOSED, 111 EF_FAILURE 112 }; 113 114 ExperimentFile (Experiment *_exp, const char *_fname); 115 ~ExperimentFile (); 116 117 bool open (bool new_open = false); 118 119 char * 120 get_name () 121 { 122 return fname; 123 } 124 125 inline int 126 get_status () 127 { 128 return ef_status; 129 } 130 131 char *fgets (); 132 void close (); 133 134 FILE *fh; 135 136private: 137 Experiment *exp; 138 char *fname; 139 off64_t offset; 140 int bufsz, ef_status; 141 char *buffer; 142}; 143 144class Experiment::ExperimentHandler : public DefaultHandler 145{ 146public: 147 148 ExperimentHandler (Experiment *_exp); 149 ~ExperimentHandler (); 150 151 void 152 startDocument () { } 153 void endDocument (); 154 void startElement (char *uri, char *localName, char *qName, Attributes *attrs); 155 void endElement (char *uri, char *localName, char *qName); 156 void characters (char *ch, int start, int length); 157 158 void 159 ignorableWhitespace (char*, int, int) { } 160 void 161 error (SAXParseException *e); 162 163private: 164 165 enum Element 166 { 167 EL_NONE, 168 EL_EXPERIMENT, 169 EL_COLLECTOR, 170 EL_SETTING, 171 EL_PROCESS, 172 EL_SYSTEM, 173 EL_EVENT, 174 EL_PROFILE, 175 EL_DATAPTR, 176 EL_PROFDATA, 177 EL_PROFPCKT, 178 EL_FIELD, 179 EL_CPU, 180 EL_STATE, 181 EL_FREQUENCY, 182 EL_POWERM, 183 EL_DTRACEFATAL 184 }; 185 186 static int toInt (Attributes *attrs, const char *atr); 187 static char*toStr (Attributes *attrs, const char *atr); 188 void pushElem (Element); 189 void popElem (); 190 191 Experiment *exp; 192 Element curElem; 193 Vector<Element> *stack; 194 Module *dynfuncModule; 195 DataDescriptor *dDscr; 196 PacketDescriptor *pDscr; 197 PropDescr *propDscr; 198 char *text; 199 Cmsg_warn mkind; 200 int mnum; 201 int mec; 202}; 203 204 205// HTableSize is the size of smemHTable and instHTable 206// omazur: both HTableSize and the hash function haven't been tuned; 207static const int HTableSize = 8192; 208 209//-------------------------------------------------- Experiment file handler 210 211Experiment::ExperimentFile::ExperimentFile (Experiment *_exp, const char *_fname) 212{ 213 exp = _exp; 214 fh = NULL; 215 bufsz = 0; 216 buffer = NULL; 217 ef_status = EF_NOT_OPENED; 218 offset = 0; 219 fname = dbe_sprintf (NTXT ("%s/%s"), exp->expt_name, _fname); 220} 221 222Experiment::ExperimentFile::~ExperimentFile () 223{ 224 close (); 225 free (buffer); 226 free (fname); 227} 228 229bool 230Experiment::ExperimentFile::open (bool new_open) 231{ 232 if (fh == NULL) 233 { 234 fh = fopen64 (fname, NTXT ("r")); 235 if (fh == NULL) 236 { 237 ef_status = EF_FAILURE; 238 return false; 239 } 240 ef_status = EF_OPENED; 241 if (new_open) 242 offset = 0; 243 if (offset != 0) 244 fseeko64 (fh, offset, SEEK_SET); 245 } 246 return true; 247} 248 249char * 250Experiment::ExperimentFile::fgets () 251{ 252 if (bufsz == 0) 253 { 254 bufsz = 1024; 255 buffer = (char *) malloc (bufsz); 256 if (buffer == NULL) 257 return NULL; 258 buffer[bufsz - 1] = (char) 1; // sentinel 259 } 260 char *res = ::fgets (buffer, bufsz, fh); 261 if (res == NULL) 262 return NULL; 263 while (buffer[bufsz - 1] == (char) 0) 264 { 265 int newsz = bufsz + 1024; 266 char *newbuf = (char *) malloc (newsz); 267 if (newbuf == NULL) 268 return NULL; 269 memcpy (newbuf, buffer, bufsz); 270 free (buffer); 271 buffer = newbuf; 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); 275 bufsz = newsz; 276 } 277 return buffer; 278} 279 280void 281Experiment::ExperimentFile::close () 282{ 283 if (fh) 284 { 285 offset = ftello64 (fh); 286 fclose (fh); 287 ef_status = EF_CLOSED; 288 fh = NULL; 289 } 290} 291 292 293//-------------------------------------------------- Experiment XML parser 294int 295Experiment::ExperimentHandler::toInt (Attributes *attrs, const char *atr) 296{ 297 const char *str = attrs->getValue (atr); 298 return str ? atoi (str) : 0; 299} 300 301char * 302Experiment::ExperimentHandler::toStr (Attributes *attrs, const char *atr) 303{ 304 const char *str = attrs->getValue (atr); 305 return dbe_strdup (str ? str : NTXT ("")); 306} 307 308Experiment::ExperimentHandler::ExperimentHandler (Experiment *_exp) 309{ 310 exp = _exp; 311 stack = new Vector<Element>; 312 pushElem (EL_NONE); 313 dynfuncModule = NULL; 314 dDscr = NULL; 315 pDscr = NULL; 316 propDscr = NULL; 317 text = NULL; 318 mkind = (Cmsg_warn) - 1; // CMSG_NONE 319 mnum = -1; 320 mec = -1; 321} 322 323Experiment::ExperimentHandler::~ExperimentHandler () 324{ 325 delete stack; 326 free (text); 327} 328 329void 330Experiment::ExperimentHandler::endDocument () 331{ 332 { // SP_TAG_STATE should be used to describe states, but it isn't 333 // let's do it here: 334 DataDescriptor *dd = exp->getDataDescriptor (DATA_HEAP); 335 if (dd != NULL) 336 { 337 PropDescr *prop = dd->getProp (PROP_HTYPE); 338 if (prop != NULL) 339 { 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]); 344 } 345 } 346 dd = exp->getDataDescriptor (DATA_IOTRACE); 347 if (dd != NULL) 348 { 349 PropDescr *prop = dd->getProp (PROP_IOTYPE); 350 if (prop != NULL) 351 { 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]); 356 } 357 } 358 } 359} 360 361void 362Experiment::ExperimentHandler::pushElem (Element elem) 363{ 364 curElem = elem; 365 stack->append (curElem); 366} 367 368void 369Experiment::ExperimentHandler::popElem () 370{ 371 stack->remove (stack->size () - 1); 372 curElem = stack->fetch (stack->size () - 1); 373} 374 375void 376Experiment::ExperimentHandler::startElement (char*, char*, char *qName, Attributes *attrs) 377{ 378 DEBUG_CODE if (DEBUG_SAXPARSER) dump_startElement (qName, attrs); 379 if (strcmp (qName, SP_TAG_EXPERIMENT) == 0) 380 { 381 pushElem (EL_EXPERIMENT); 382 const char *str = attrs->getValue (NTXT ("version")); 383 if (str != NULL) 384 { 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) 391 { 392 // not the current version, see if we support some earlier versions 393 if (major < 12) 394 { 395 StringBuilder sb; 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; 400 exp->obsolete = 1; 401 throw new SAXException (sb.toString ()); 402 } 403 } 404 } 405 } 406 else if (strcmp (qName, SP_TAG_COLLECTOR) == 0) 407 pushElem (EL_COLLECTOR); 408 else if (strcmp (qName, SP_TAG_SETTING) == 0) 409 { 410 int found = 0; 411 pushElem (EL_SETTING); 412 const char *str = attrs->getValue (SP_JCMD_LIMIT); 413 if (str != NULL) 414 { 415 found = 1; 416 exp->coll_params.limit = atoi (str); 417 } 418 str = attrs->getValue (SP_JCMD_BLKSZ); 419 if (str != NULL) 420 { 421 found = 1; 422 exp->blksz = strtol (str, NULL, 0); 423 } 424 str = attrs->getValue (SP_JCMD_STACKBASE); 425 if (str) 426 { 427 found = 1; 428 exp->stack_base = strtoull (str, NULL, 0); 429 } 430 str = attrs->getValue (SP_JCMD_HWC_DEFAULT); 431 if (str != NULL) 432 { 433 found = 1; 434 exp->hwc_default = true; 435 } 436 str = attrs->getValue (SP_JCMD_NOIDLE); 437 if (str != NULL) 438 { 439 found = 1; 440 exp->commentq->append (new Emsg (CMSG_COMMENT, 441 GTXT ("*** Note: experiment does not have events from idle CPUs"))); 442 } 443 str = attrs->getValue (SP_JCMD_FAKETIME); 444 if (str != NULL) 445 { 446 found = 1; 447 exp->timelineavail = false; 448 exp->commentq->append (new Emsg (CMSG_COMMENT, 449 GTXT ("*** Note: experiment does not have timestamps; timeline unavailable"))); 450 } 451 str = attrs->getValue (SP_JCMD_DELAYSTART); 452 if (str != NULL) 453 { 454 found = 1; 455 exp->coll_params.start_delay = strdup (str); 456 } 457 str = attrs->getValue (SP_JCMD_TERMINATE); 458 if (str != NULL) 459 { 460 found = 1; 461 exp->coll_params.terminate = strdup (str); 462 } 463 str = attrs->getValue (SP_JCMD_PAUSE_SIG); 464 if (str != NULL) 465 { 466 found = 1; 467 exp->coll_params.pause_sig = strdup (str); 468 } 469 str = attrs->getValue (SP_JCMD_SAMPLE_PERIOD); 470 if (str != NULL) 471 { 472 found = 1; 473 exp->coll_params.sample_periodic = 1; 474 exp->coll_params.sample_timer = atoi (str); 475 } 476 str = attrs->getValue (SP_JCMD_SAMPLE_SIG); 477 if (str != NULL) 478 { 479 found = 1; 480 exp->coll_params.sample_sig = str; 481 } 482 str = attrs->getValue (SP_JCMD_SRCHPATH); 483 if (str != NULL) 484 { 485 found = 1; 486 StringBuilder sb; 487 sb.sprintf (GTXT ("Search path: %s"), str); 488 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb)); 489 dbeSession->add_classpath ((char*) str); 490 } 491 str = attrs->getValue (SP_JCMD_LINETRACE); 492 if (str != NULL) 493 { 494 found = 1; 495 exp->coll_params.linetrace = strdup (str); 496 } 497 498 str = attrs->getValue (SP_JCMD_COLLENV); 499 if (str != NULL) 500 { 501 found = 1; 502 StringBuilder sb; 503 sb.sprintf (GTXT (" Data collection environment variable: %s"), str); 504 exp->runlogq->append (new Emsg (CMSG_COMMENT, sb)); 505 } 506 if (found == 0) 507 { 508 int nattr = attrs->getLength (); 509 if (nattr != 0) 510 { 511 fprintf (stderr, "XXX Unexpected setting found; %d attributes:\n", 512 nattr); 513 for (int k = 0; k < nattr; k++) 514 { 515 const char *qn = attrs->getQName (k); 516 const char *vl = attrs->getValue (k); 517 fprintf (stderr, "XXX %s = %s\n", qn, vl); 518 } 519 } 520 } 521 // END OF CODE FOR "setting" 522 } 523 else if (strcmp (qName, SP_TAG_SYSTEM) == 0) 524 { 525 pushElem (EL_SYSTEM); 526 const char *str = attrs->getValue (NTXT ("hostname")); 527 if (str != NULL) 528 exp->hostname = strdup (str); 529 str = attrs->getValue (NTXT ("os")); 530 if (str != NULL) 531 { 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; 536 } 537 str = attrs->getValue (NTXT ("arch")); 538 if (str != NULL) 539 { 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; 545 else 546 exp->platform = Sparc; 547 exp->need_swap_endian = (DbeSession::platform == Sparc) ? 548 (exp->platform != Sparc) : (exp->platform == Sparc); 549 exp->architecture = strdup (str); 550 } 551 str = attrs->getValue (NTXT ("pagesz")); 552 if (str != NULL) 553 exp->page_size = atoi (str); 554 str = attrs->getValue (NTXT ("npages")); 555 if (str != NULL) 556 exp->npages = atoi (str); 557 } 558 else if (strcmp (qName, SP_TAG_POWERM) == 0) 559 pushElem (EL_POWERM); 560 else if (strcmp (qName, SP_TAG_FREQUENCY) == 0) 561 { 562 pushElem (EL_FREQUENCY); 563 const char *str = attrs->getValue (NTXT ("clk")); 564 if (str != NULL) 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) 570 exp->varclock = 1; 571 } 572 else if (strcmp (qName, SP_TAG_CPU) == 0) 573 { 574 pushElem (EL_CPU); 575 exp->ncpus++; 576 const char *str = attrs->getValue (NTXT ("clk")); 577 if (str != NULL) 578 { 579 int clk = atoi (str); 580 if (exp->maxclock == 0) 581 { 582 exp->minclock = clk; 583 exp->maxclock = clk; 584 } 585 else 586 { 587 if (clk < exp->minclock) 588 exp->minclock = clk; 589 if (clk > exp->maxclock) 590 exp->maxclock = clk; 591 } 592 exp->clock = clk; 593 } 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) 598 exp->varclock = 1; 599 } 600 else if (strcmp (qName, SP_TAG_PROCESS) == 0) 601 { 602 pushElem (EL_PROCESS); 603 const char *str = attrs->getValue (NTXT ("wsize")); 604 if (str != NULL) 605 { 606 int wsz = atoi (str); 607 if (wsz == 32) 608 exp->wsize = W32; 609 else if (wsz == 64) 610 exp->wsize = W64; 611 } 612 str = attrs->getValue (NTXT ("pid")); 613 if (str != NULL) 614 exp->pid = atoi (str); 615 str = attrs->getValue (NTXT ("ppid")); 616 if (str != NULL) 617 exp->ppid = atoi (str); 618 str = attrs->getValue (NTXT ("pgrp")); 619 if (str != NULL) 620 exp->pgrp = atoi (str); 621 str = attrs->getValue (NTXT ("sid")); 622 if (str != NULL) 623 exp->sid = atoi (str); 624 str = attrs->getValue (NTXT ("cwd")); 625 if (str != NULL) 626 exp->ucwd = strdup (str); 627 str = attrs->getValue (NTXT ("pagesz")); 628 if (str != NULL) 629 exp->page_size = atoi (str); 630 } 631 else if (strcmp (qName, SP_TAG_EVENT) == 0) 632 { // Start code for event 633 pushElem (EL_EVENT); 634 hrtime_t ts = (hrtime_t) 0; 635 const char *str = attrs->getValue (NTXT ("tstamp")); 636 if (str != NULL) 637 ts = parseTStamp (str); 638 str = attrs->getValue (NTXT ("kind")); 639 if (str != NULL) 640 { 641 if (strcmp (str, SP_JCMD_RUN) == 0) 642 { 643 exp->broken = 0; 644 exp->exp_start_time = ts; 645 str = attrs->getValue (NTXT ("time")); 646 if (str != NULL) 647 exp->start_sec = atoll (str); 648 str = attrs->getValue (NTXT ("pid")); 649 if (str != NULL) 650 exp->pid = atoi (str); 651 str = attrs->getValue (NTXT ("ppid")); 652 if (str != NULL) 653 exp->ppid = atoi (str); 654 str = attrs->getValue (NTXT ("pgrp")); 655 if (str != NULL) 656 exp->pgrp = atoi (str); 657 str = attrs->getValue (NTXT ("sid")); 658 if (str != NULL) 659 exp->sid = atoi (str); 660 exp->status = Experiment::INCOMPLETE; 661 } 662 else if (strcmp (str, SP_JCMD_ARCHIVE) == 0) 663 { 664 StringBuilder sb; 665 sb.sprintf (GTXT ("er_archive run: XXXXXXX")); 666 exp->pprocq->append (new Emsg (CMSG_WARN, sb)); 667 } 668 else if (strcmp (str, SP_JCMD_SAMPLE) == 0) 669 { 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); 675 } 676 else if (strcmp (str, SP_JCMD_EXIT) == 0) 677 { 678 // don't treat EXIT as an event w.r.t. last_event and non_paused_time 679 exp->status = Experiment::SUCCESS; 680 } 681 else if (strcmp (str, SP_JCMD_CERROR) == 0) 682 { 683 mkind = CMSG_ERROR; 684 str = attrs->getValue (NTXT ("id")); 685 if (str != NULL) 686 { 687 mnum = atoi (str); 688 } 689 str = attrs->getValue (NTXT ("ec")); 690 if (str != NULL) 691 { 692 mec = atoi (str); 693 } 694 } 695 else if (strcmp (str, SP_JCMD_CWARN) == 0) 696 { 697 mkind = CMSG_WARN; 698 str = attrs->getValue (NTXT ("id")); 699 if (str != NULL) 700 mnum = atoi (str); 701 } 702 else if (strcmp (str, SP_JCMD_COMMENT) == 0) 703 { 704 mkind = CMSG_COMMENT; 705 str = attrs->getValue (NTXT ("id")); 706 if (str != NULL) 707 mnum = atoi (str); 708 str = attrs->getValue (NTXT ("text")); 709 if (str != NULL) 710 { 711 StringBuilder sb; 712 sb.sprintf (GTXT ("*** Note: %s"), str); 713 exp->commentq->append (new Emsg (CMSG_COMMENT, sb)); 714 } 715 } 716 else if (strcmp (str, SP_JCMD_DESC_START) == 0) 717 { 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); 723 } 724 else if (strcmp (str, SP_JCMD_DESC_STARTED) == 0) 725 { 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); 731 } 732 else if (strcmp (str, SP_JCMD_EXEC_START) == 0) 733 { 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; 742 } 743 else if (strcmp (str, SP_JCMD_EXEC_ERROR) == 0) 744 { 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; 752 } 753 else if (strcmp (str, SP_JCMD_JTHRSTART) == 0) 754 { 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); 765 } 766 else if (strcmp (str, SP_JCMD_JTHREND) == 0) 767 { 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); 775 } 776 else if (strcmp (str, SP_JCMD_GCEND) == 0) 777 { 778 if (exp->getDataDescriptor (DATA_GCEVENT) == NULL) 779 exp->newDataDescriptor (DATA_GCEVENT); 780 exp->process_gc_end_cmd (ts); 781 } 782 else if (strcmp (str, SP_JCMD_GCSTART) == 0) 783 { 784 if (exp->getDataDescriptor (DATA_GCEVENT) == NULL) 785 exp->newDataDescriptor (DATA_GCEVENT); 786 exp->process_gc_start_cmd (ts); 787 } 788 else if (strcmp (str, SP_JCMD_PAUSE) == 0) 789 { 790 if (exp->resume_ts != MAX_TIME) 791 { 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 796 } 797 StringBuilder sb; 798 str = attrs->getValue (NTXT ("name")); 799 if (str == NULL) 800 sb.sprintf (GTXT ("Pause: %ld.%09ld"), (long) (ts / NANOSEC), 801 (long) (ts % NANOSEC)); 802 else 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)); 806 } 807 else if (strcmp (str, SP_JCMD_RESUME) == 0) 808 { 809 if (exp->resume_ts == MAX_TIME) 810 // data collection was paused 811 exp->resume_ts = ts; // remember start time 812 StringBuilder sb; 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; 817 } 818 else if (strcmp (str, SP_JCMD_THREAD_PAUSE) == 0) 819 { 820 str = attrs->getValue (NTXT ("tid")); 821 uint64_t tid = str ? strtoull (str, NULL, 0) : 0; 822 StringBuilder sb; 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)); 826 } 827 else if (strcmp (str, SP_JCMD_THREAD_RESUME) == 0) 828 { 829 str = attrs->getValue (NTXT ("tid")); 830 uint64_t tid = str ? strtoull (str, NULL, 0) : 0; 831 StringBuilder sb; 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)); 835 } 836 else if (strcmp (str, NTXT ("map")) == 0) 837 { 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")); 848 int64_t chksum = 0; 849 if (str) 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) 854 { 855 if (strcmp (name, NTXT ("LinuxKernel")) == 0) 856 exp->process_Linux_kernel_cmd (ts); 857 else 858 exp->process_seg_map_cmd (NULL, ts, vaddr, msize, 0, 859 offset, modes, chksum, name); 860 } 861 else if (strcmp (str, NTXT ("function")) == 0) 862 { 863 exp->process_fn_load_cmd (dynfuncModule, name, vaddr, msize, ts); 864 dynfuncModule = NULL; 865 } 866 else if (strcmp (str, NTXT ("dynfunc")) == 0) 867 { 868 if (dynfuncModule == NULL) 869 { 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 ())); 873 } 874 (void) exp->create_dynfunc (dynfuncModule, 875 (char*) attrs->getValue (NTXT ("funcname")), vaddr, msize); 876 } 877 else if (strcmp (str, NTXT ("jcm")) == 0) 878 { 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); 882 } 883 } 884 else if (strcmp (str, NTXT ("unmap")) == 0) 885 { 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); 890 } 891 } 892 // end of code for event 893 } 894 else if (strcmp (qName, SP_TAG_PROFILE) == 0) 895 { 896 pushElem (EL_PROFILE); 897 const char *str = attrs->getValue (NTXT ("name")); 898 if (str == NULL) 899 return; 900 if (strcmp (str, NTXT ("profile")) == 0) 901 { 902 exp->coll_params.profile_mode = 1; 903 str = attrs->getValue (NTXT ("numstates")); 904 if (str != NULL) 905 exp->coll_params.lms_magic_id = atoi (str); 906 str = attrs->getValue (NTXT ("ptimer")); 907 if (str != NULL) 908 exp->coll_params.ptimer_usec = atoi (str); // microseconds 909 910 PropDescr *mstate_prop = NULL; 911 char * stateNames [/*LMS_NUM_STATES*/] = LMS_STATE_STRINGS; 912 char * stateUNames[/*LMS_NUM_STATES*/] = LMS_STATE_USTRINGS; 913 { 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); 920 mstate_prop = prop; 921 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); 926 } 927 928 switch (exp->coll_params.lms_magic_id) 929 { 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]); 945 break; 946 case LMS_MAGIC_ID_ERKERNEL_KERNEL: 947 exp->register_metric (Metric::CP_KERNEL_CPU); 948 { 949 int ii = LMS_KERNEL_CPU; 950 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]); 951 } 952 break; 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); 957 { 958 int ii = LMS_KERNEL_CPU; 959 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]); 960 ii = LMS_USER; 961 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]); 962 ii = LMS_SYSTEM; 963 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]); 964 } 965 break; 966 case LMS_MAGIC_ID_LINUX: 967 exp->register_metric (Metric::CP_TOTAL_CPU); 968 { 969 int ii = LMS_LINUX_CPU; 970 mstate_prop->addState (ii, stateNames[ii], stateUNames[ii]); 971 } 972 break; 973 default: 974 // odd 975 break; 976 } 977 } 978 else if (strcmp (str, NTXT ("heaptrace")) == 0) 979 { 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); 988 } 989 else if (strcmp (str, NTXT ("iotrace")) == 0) 990 { 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); 1004 } 1005 else if (strcmp (str, NTXT ("synctrace")) == 0) 1006 { 1007 exp->coll_params.sync_mode = 1; 1008 str = attrs->getValue (NTXT ("threshold")); 1009 if (str != NULL) 1010 exp->coll_params.sync_threshold = atoi (str); 1011 str = attrs->getValue (NTXT ("scope")); 1012 if (str != NULL) 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); 1019 } 1020 else if (strcmp (str, NTXT ("omptrace")) == 0) 1021 { 1022 exp->coll_params.omp_mode = 1; 1023 dDscr = exp->newDataDescriptor (DATA_OMP, DDFLAG_NOSHOW); 1024 } 1025 else if (strcmp (str, NTXT ("hwcounter")) == 0) 1026 { 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); 1040 } 1041 else if (strcmp (str, NTXT ("hwsimctr")) == 0) 1042 { 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); 1055 } 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) 1059 { 1060 exp->has_java = true; 1061 str = attrs->getValue (NTXT ("jversion")); 1062 if (str != NULL) 1063 exp->jversion = strdup (str); 1064 } 1065 else if (strcmp (str, NTXT ("datarace")) == 0) 1066 { 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); 1073 } 1074 else if (strcmp (str, NTXT ("deadlock")) == 0) 1075 { 1076 exp->coll_params.deadlock_mode = 1; 1077 exp->deadlocklistavail = true; 1078 exp->register_metric (Metric::DEADLOCKS); 1079 dDscr = exp->newDataDescriptor (DATA_DLCK); 1080 } 1081 } 1082 /* XXX -- obsolete tag, but is still written to experiments */ 1083 else if (strcmp (qName, SP_TAG_DATAPTR) == 0) 1084 { 1085 pushElem (EL_DATAPTR); 1086 return; 1087 } 1088 else if (strcmp (qName, SP_TAG_PROFDATA) == 0) 1089 { 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); 1095 } 1096 else if (strcmp (qName, SP_TAG_PROFPCKT) == 0) 1097 { 1098 pushElem (EL_PROFPCKT); 1099 const char *str = attrs->getValue (NTXT ("kind")); // see Pckt_type 1100 int kind = str ? atoi (str) : -1; 1101 if (kind < 0) 1102 return; 1103 if (exp->coll_params.omp_mode == 1) 1104 { 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); 1115 } 1116 pDscr = exp->newPacketDescriptor (kind, dDscr); 1117 return; 1118 } 1119 else if (strcmp (qName, SP_TAG_FIELD) == 0) 1120 { 1121 pushElem (EL_FIELD); 1122 if (pDscr != NULL) 1123 { 1124 const char *name = attrs->getValue (NTXT ("name")); 1125 if (name == NULL) 1126 return; 1127 int propID = dbeSession->registerPropertyName (name); 1128 propDscr = new PropDescr (propID, name); 1129 FieldDescr *fldDscr = new FieldDescr (propID, name); 1130 1131 const char *str = attrs->getValue (NTXT ("type")); 1132 if (str) 1133 { 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) 1147 { 1148 fldDscr->vtype = TYPE_DATE; 1149 const char *fmt = attrs->getValue (NTXT ("format")); 1150 fldDscr->format = strdup (fmt ? fmt : ""); 1151 } 1152 } 1153 propDscr->vtype = fldDscr->vtype; 1154 1155 // TYPE_DATE is converted to TYPE_UINT64 in propDscr 1156 if (fldDscr->vtype == TYPE_DATE) 1157 propDscr->vtype = TYPE_UINT64; 1158 1159 // Fix some types until they are fixed in libcollector 1160 if (propID == PROP_VIRTPC || propID == PROP_PHYSPC) 1161 { 1162 if (fldDscr->vtype == TYPE_INT32) 1163 propDscr->vtype = TYPE_UINT32; 1164 else if (fldDscr->vtype == TYPE_INT64) 1165 propDscr->vtype = TYPE_UINT64; 1166 } 1167 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 1172 1173 str = attrs->getValue (NTXT ("uname")); 1174 if (str) 1175 propDscr->uname = strdup (PTXT ((char*) str)); 1176 str = attrs->getValue (NTXT ("noshow")); 1177 if (str && atoi (str) != 0) 1178 propDscr->flags |= PRFLAG_NOSHOW; 1179 1180 if (dDscr == NULL) 1181 { 1182 StringBuilder sb; 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 ()); 1186 } 1187 1188 dDscr->addProperty (propDscr); 1189 str = attrs->getValue (NTXT ("offset")); 1190 if (str) 1191 fldDscr->offset = atoi (str); 1192 pDscr->addField (fldDscr); 1193 } 1194 } 1195 else if (strcmp (qName, SP_TAG_STATE) == 0) 1196 { 1197 pushElem (EL_STATE); 1198 if (propDscr != NULL) 1199 { 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); 1205 } 1206 } 1207 else if (strcmp (qName, SP_TAG_DTRACEFATAL) == 0) 1208 pushElem (EL_DTRACEFATAL); 1209 else 1210 { 1211 StringBuilder sb; 1212 sb.sprintf (GTXT ("*** Warning: unrecognized element %s"), qName); 1213 exp->warnq->append (new Emsg (CMSG_WARN, sb)); 1214 pushElem (EL_NONE); 1215 } 1216} 1217 1218void 1219Experiment::ExperimentHandler::characters (char *ch, int start, int length) 1220{ 1221 switch (curElem) 1222 { 1223 case EL_COLLECTOR: 1224 exp->cversion = dbe_strndup (ch + start, length); 1225 break; 1226 case EL_PROCESS: 1227 exp->process_arglist_cmd (NULL, dbe_strndup (ch + start, length)); 1228 break; 1229 case EL_EVENT: 1230 free (text); 1231 text = dbe_strndup (ch + start, length); 1232 break; 1233 default: 1234 break; 1235 } 1236} 1237 1238void 1239Experiment::ExperimentHandler::endElement (char*, char*, char*) 1240{ 1241 if (curElem == EL_EVENT && mkind >= 0 && mnum >= 0) 1242 { 1243 char *str; 1244 if (mec > 0) 1245 str = dbe_sprintf ("%s -- %s", text != NULL ? text : "", strerror (mec)); 1246 else 1247 str = dbe_sprintf ("%s", text != NULL ? text : ""); 1248 Emsg *msg = new Emsg (mkind, mnum, str); 1249 if (mkind == CMSG_WARN) 1250 { 1251 if (mnum != COL_WARN_FSTYPE 1252 || dbeSession->check_ignore_fs_warn () == false) 1253 exp->warnq->append (msg); 1254 else 1255 exp->commentq->append (msg); 1256 } 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); 1261 else 1262 delete msg; 1263 mkind = (Cmsg_warn) - 1; 1264 mnum = -1; 1265 mec = -1; 1266 } 1267 else if (curElem == EL_PROFILE) 1268 dDscr = NULL; 1269 else if (curElem == EL_PROFPCKT) 1270 pDscr = NULL; 1271 else if (curElem == EL_FIELD) 1272 propDscr = NULL; 1273 free (text); 1274 text = NULL; 1275 popElem (); 1276} 1277 1278void 1279Experiment::ExperimentHandler::error (SAXParseException *e) 1280{ 1281 StringBuilder sb; 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); 1286 free (msg); 1287 throw ( e1); 1288} 1289 1290//-------------------------------------------------- Experiment 1291 1292Experiment::Experiment () 1293{ 1294 groupId = 0; 1295 userExpId = expIdx = -1; 1296 founder_exp = NULL; 1297 baseFounder = NULL; 1298 children_exps = new Vector<Experiment*>; 1299 loadObjs = new Vector<LoadObject*>; 1300 loadObjMap = new StringMap<LoadObject*>(128, 128); 1301 sourcesMap = NULL; 1302 1303 // Initialize configuration information. 1304 status = FAILURE; 1305 start_sec = 0; 1306 mtime = 0; 1307 hostname = NULL; 1308 username = NULL; 1309 architecture = NULL; 1310 os_version = NULL; 1311 uarglist = NULL; 1312 utargname = NULL; 1313 ucwd = NULL; 1314 cversion = NULL; 1315 dversion = NULL; 1316 jversion = NULL; 1317 exp_maj_version = 0; 1318 exp_min_version = 0; 1319 platform = Unknown; 1320 wsize = Wnone; 1321 page_size = 4096; 1322 npages = 0; 1323 stack_base = 0xf0000000; 1324 broken = 1; 1325 obsolete = 0; 1326 hwc_bogus = 0; 1327 hwc_lost_int = 0; 1328 hwc_scanned = 0; 1329 hwc_default = false; 1330 invalid_packet = 0; 1331 1332 // clear HWC event stats 1333 dsevents = 0; 1334 dsnoxhwcevents = 0; 1335 1336 memset (&coll_params, 0, sizeof (coll_params)); 1337 ncpus = 0; 1338 minclock = 0; 1339 maxclock = 0; 1340 clock = 0; 1341 varclock = 0; 1342 exec_started = false; 1343 timelineavail = true; 1344 leaklistavail = false; 1345 heapdataavail = false; 1346 iodataavail = false; 1347 dataspaceavail = false; 1348 ifreqavail = false; 1349 racelistavail = false; 1350 deadlocklistavail = false; 1351 ompavail = false; 1352 tiny_threshold = -1; 1353 pid = 0; 1354 ppid = 0; 1355 pgrp = 0; 1356 sid = 0; 1357 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; 1366 has_java = false; 1367 hex_field_width = 8; 1368 hw_cpuver = CPUVER_UNDEFINED; 1369 machinemodel = NULL; 1370 expt_name = NULL; 1371 arch_name = NULL; 1372 fndr_arch_name = NULL; 1373 logFile = NULL; 1374 1375 dataDscrs = new Vector<DataDescriptor*>; 1376 for (int i = 0; i < DATA_LAST; ++i) 1377 dataDscrs->append (NULL); 1378 1379 pcktDscrs = new Vector<PacketDescriptor*>; 1380 blksz = PROFILE_BUFFER_CHUNK; 1381 jthreads = new Vector<JThread*>; 1382 jthreads_idx = new Vector<JThread*>; 1383 gcevents = new Vector<GCEvent*>; 1384 gcevent_last_used = (GCEvent *) NULL; 1385 heapUnmapEvents = new Vector<UnmapChunk*>; 1386 cstack = NULL; 1387 cstackShowHide = NULL; 1388 frmpckts = new Vector<RawFramePacket*>; 1389 typedef DefaultMap2D<uint32_t, hrtime_t, uint64_t> OmpMap0; 1390 mapPRid = new OmpMap0 (OmpMap0::Interval); 1391 typedef DefaultMap2D<uint32_t, hrtime_t, void*> OmpMap; 1392 mapPReg = new OmpMap (OmpMap::Interval); 1393 mapTask = new OmpMap (OmpMap::Interval); 1394 openMPdata = NULL; 1395 archiveMap = NULL; 1396 nnodes = 0; 1397 nchunks = 0; 1398 chunks = 0; 1399 uidHTable = NULL; 1400 uidnodes = new Vector<UIDnode*>; 1401 mrecs = new Vector<MapRecord*>; 1402 samples = new Vector<Sample*>; 1403 sample_last_used = (Sample *) NULL; 1404 first_sample_label = (char*) NULL; 1405 fDataMap = NULL; 1406 vFdMap = NULL; 1407 resolveFrameInfo = true; 1408 discardTiny = false; 1409 init (); 1410} 1411 1412Experiment::~Experiment () 1413{ 1414 fini (); 1415 free (coll_params.linetrace); 1416 for (int i = 0; i < MAX_HWCOUNT; i++) 1417 { 1418 free (coll_params.hw_aux_name[i]); 1419 free (coll_params.hw_username[i]); 1420 } 1421 free (hostname); 1422 free (username); 1423 free (architecture); 1424 free (os_version); 1425 free (uarglist); 1426 free (utargname); 1427 free (ucwd); 1428 free (cversion); 1429 free (dversion); 1430 free (jversion); 1431 delete logFile; 1432 free (expt_name); 1433 free (arch_name); 1434 free (fndr_arch_name); 1435 delete jthreads_idx; 1436 delete cstack; 1437 delete cstackShowHide; 1438 delete mapPRid; 1439 delete mapPReg; 1440 delete mapTask; 1441 delete openMPdata; 1442 destroy_map (DbeFile *, archiveMap); 1443 delete[] uidHTable; 1444 delete uidnodes; 1445 delete mrecs; 1446 delete children_exps; 1447 delete loadObjs; 1448 delete loadObjMap; 1449 delete sourcesMap; 1450 free (first_sample_label); 1451 free (machinemodel); 1452 1453 dataDscrs->destroy (); 1454 delete dataDscrs; 1455 pcktDscrs->destroy (); 1456 delete pcktDscrs; 1457 jthreads->destroy (); 1458 delete jthreads; 1459 gcevents->destroy (); 1460 delete gcevents; 1461 heapUnmapEvents->destroy (); 1462 delete heapUnmapEvents; 1463 frmpckts->destroy (); 1464 delete frmpckts; 1465 samples->destroy (); 1466 delete samples; 1467 delete fDataMap; 1468 delete vFdMap; 1469 1470 for (long i = 0; i < nchunks; i++) 1471 delete[] chunks[i]; 1472 delete[] chunks; 1473} 1474 1475void 1476Experiment::init_cache () 1477{ 1478 if (smemHTable) 1479 return; 1480 smemHTable = new SegMem*[HTableSize]; 1481 instHTable = new DbeInstr*[HTableSize]; 1482 for (int i = 0; i < HTableSize; i++) 1483 { 1484 smemHTable[i] = NULL; 1485 instHTable[i] = NULL; 1486 } 1487 uidHTable = new UIDnode*[HTableSize]; 1488 for (int i = 0; i < HTableSize; i++) 1489 uidHTable[i] = NULL; 1490 1491 cstack = CallStack::getInstance (this); 1492 cstackShowHide = CallStack::getInstance (this); 1493} 1494 1495void 1496Experiment::init () 1497{ 1498 userLabels = NULL; 1499 seg_items = new Vector<SegMem*>; 1500 maps = new PRBTree (); 1501 jmaps = NULL; // used by JAVA_CLASSES only 1502 jmidHTable = NULL; 1503 smemHTable = NULL; 1504 instHTable = NULL; 1505 min_thread = (uint64_t) - 1; 1506 max_thread = 0; 1507 thread_cnt = 0; 1508 min_lwp = (uint64_t) - 1; 1509 max_lwp = 0; 1510 lwp_cnt = 0; 1511 min_cpu = (uint64_t) - 1; 1512 max_cpu = 0; 1513 cpu_cnt = 0; 1514 1515 commentq = new Emsgqueue (NTXT ("commentq")); 1516 runlogq = new Emsgqueue (NTXT ("runlogq")); 1517 errorq = new Emsgqueue (NTXT ("errorq")); 1518 warnq = new Emsgqueue (NTXT ("warnq")); 1519 notesq = new Emsgqueue (NTXT ("notesq")); 1520 pprocq = new Emsgqueue (NTXT ("pprocq")); 1521 ifreqq = NULL; 1522 1523 metrics = new Vector<BaseMetric*>; 1524 tagObjs = new Vector<Vector<Histable*>*>; 1525 tagObjs->store (PROP_THRID, new Vector<Histable*>); 1526 tagObjs->store (PROP_LWPID, new Vector<Histable*>); 1527 tagObjs->store (PROP_CPUID, new Vector<Histable*>); 1528 tagObjs->store (PROP_EXPID, new Vector<Histable*>); 1529 sparse_threads = false; 1530} 1531 1532void 1533Experiment::fini () 1534{ 1535 seg_items->destroy (); 1536 delete seg_items; 1537 delete maps; 1538 delete jmaps; 1539 delete[] smemHTable; 1540 delete[] instHTable; 1541 delete jmidHTable; 1542 delete commentq; 1543 delete runlogq; 1544 delete errorq; 1545 delete warnq; 1546 delete notesq; 1547 delete pprocq; 1548 if (ifreqq != NULL) 1549 { 1550 delete ifreqq; 1551 ifreqq = NULL; 1552 } 1553 1554 int index; 1555 BaseMetric *mtr; 1556 Vec_loop (BaseMetric*, metrics, index, mtr) 1557 { 1558 dbeSession->drop_metric (mtr); 1559 } 1560 delete metrics; 1561 tagObjs->fetch (PROP_THRID)->destroy (); 1562 tagObjs->fetch (PROP_LWPID)->destroy (); 1563 tagObjs->fetch (PROP_CPUID)->destroy (); 1564 tagObjs->fetch (PROP_EXPID)->destroy (); 1565 tagObjs->destroy (); 1566 delete tagObjs; 1567} 1568 1569// These are the data files which can be read in parallel 1570// for multiple sub-experiments. 1571// Postpone calling resolve_frame_info() 1572void 1573Experiment::read_experiment_data (bool read_ahead) 1574{ 1575 1576 read_frameinfo_file (); 1577 if (read_ahead) 1578 { 1579 resolveFrameInfo = false; 1580 (void) get_profile_events (); 1581 resolveFrameInfo = true; 1582 } 1583} 1584 1585Experiment::Exp_status 1586Experiment::open_epilogue () 1587{ 1588 1589 // set up mapping for tagObj(PROP_EXPID) 1590 (void) mapTagValue (PROP_EXPID, userExpId); 1591 1592 post_process (); 1593 if (last_event != ZERO_TIME) 1594 { // if last_event is known 1595 StringBuilder sb; 1596 hrtime_t ts = last_event - exp_start_time; 1597 sb.sprintf (GTXT ("Experiment Ended: %ld.%09ld\nData Collection Duration: %ld.%09ld"), 1598 (long) (ts / NANOSEC), (long) (ts % NANOSEC), 1599 (long) (non_paused_time / NANOSEC), 1600 (long) (non_paused_time % NANOSEC)); 1601 runlogq->append (new Emsg (CMSG_COMMENT, sb)); 1602 } 1603 1604 // Check for incomplete experiment, and inform the user 1605 if (status == INCOMPLETE) 1606 { 1607 if (exec_started == true) 1608 // experiment ended with the exec, not abnormally 1609 status = SUCCESS; 1610 else 1611 { 1612 char * cmnt = GTXT ("*** Note: experiment was not closed"); 1613 commentq->append (new Emsg (CMSG_COMMENT, cmnt)); 1614 // runlogq->append(new Emsg(CMSG_COMMENT, cmnt)); 1615 } 1616 } 1617 // write a descriptive header for the experiment 1618 write_header (); 1619 return status; 1620} 1621 1622Experiment::Exp_status 1623Experiment::open (char *path) 1624{ 1625 1626 // Find experiment directory 1627 if (find_expdir (path) != SUCCESS) 1628 // message will have been queued and status set 1629 return status; 1630 1631 // Get creation time for experiment 1632 struct stat64 st; 1633 if (dbe_stat (path, &st) == 0) 1634 mtime = st.st_mtime; 1635 1636 // Read the warnings file 1637 read_warn_file (); 1638 1639 // Open the log file 1640 read_log_file (); 1641 if (status == SUCCESS && last_event // last event is initialized 1642 && (last_event - exp_start_time) / 1000000 < tiny_threshold) 1643 { 1644 // Process "tiny_threshold" (SP_ANALYZER_DISCARD_TINY_EXPERIMENTS) 1645 // At this point, we've only processed log.xml. 1646 // Note: if an experiment terminated abnormally, last_event will not yet 1647 // represent events from clock profiling and other metrics. 1648 // Other events will often have timestamps after the last log.xml entry. 1649 discardTiny = true; 1650 return status; 1651 } 1652 if (status == FAILURE) 1653 { 1654 if (logFile->get_status () == ExperimentFile::EF_FAILURE) 1655 { 1656 Emsg *m = new Emsg (CMSG_FATAL, GTXT ("*** Error: log file in experiment cannot be read")); 1657 errorq->append (m); 1658 } 1659 else if (fetch_errors () == NULL) 1660 { 1661 if (broken == 1) 1662 { 1663 Emsg *m = new Emsg (CMSG_FATAL, GTXT ("*** Error: log does not show target starting")); 1664 errorq->append (m); 1665 } 1666 else 1667 { 1668 Emsg *m = new Emsg (CMSG_FATAL, GTXT ("*** Error: log file in experiment could not be parsed")); 1669 errorq->append (m); 1670 } 1671 } 1672 return status; 1673 } 1674 init_cache (); 1675 if (varclock != 0) 1676 { 1677 StringBuilder sb; 1678 sb.sprintf ( 1679 GTXT ("*** Warning: system has variable clock frequency, which may cause variable execution times and inaccurate conversions of cycle counts into time.")); 1680 warnq->append (new Emsg (CMSG_WARN, sb)); 1681 } 1682 1683 // Read the notes file 1684 read_notes_file (); 1685 read_labels_file (); 1686 read_archives (); 1687 1688 // The log file shows experiment started 1689 read_java_classes_file (); 1690 1691 read_map_file (); 1692 1693 // Dyntext file has to be processed after loadobjects file 1694 // as we need to be able to map (vaddr,ts) to dynamic functions. 1695 read_dyntext_file (); 1696 1697 // Read the overview file and create samples. 1698 // Profiling data hasn't been read yet so we may have 1699 // events after the last recorded sample. 1700 // We'll create a fake sample to cover all those 1701 // events later. 1702 read_overview_file (); 1703 1704 // Check if instruction frequency data is available 1705 read_ifreq_file (); 1706 1707 // Check if OMP data is available 1708 read_omp_file (); 1709 1710 return status; 1711} 1712 1713/* XXX -- update() is a no-op now, but may be needed for auto-update */ 1714Experiment::Exp_status 1715Experiment::update () 1716{ 1717 return status; 1718} 1719 1720void 1721Experiment::append (LoadObject *lo) 1722{ 1723 loadObjs->append (lo); 1724 char *obj_name = lo->get_pathname (); 1725 char *bname = get_basename (obj_name); 1726 loadObjMap->put (obj_name, lo); 1727 loadObjMap->put (bname, lo); 1728 if (lo->flags & SEG_FLAG_EXE) 1729 loadObjMap->put (COMP_EXE_NAME, lo); 1730} 1731 1732void 1733Experiment::read_notes_file () 1734{ 1735 Emsg *m; 1736 1737 // Open log file: 1738 char *fname = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_NOTES_FILE); 1739 FILE *f = fopen (fname, NTXT ("r")); 1740 free (fname); 1741 if (f == NULL) 1742 return; 1743 if (!dbeSession->is_interactive ()) 1744 { 1745 m = new Emsg (CMSG_COMMENT, NTXT ("Notes:")); 1746 notesq->append (m); 1747 } 1748 1749 while (1) 1750 { 1751 char str[MAXPATHLEN]; 1752 char *e = fgets (str, ((int) sizeof (str)) - 1, f); 1753 if (e == NULL) 1754 { 1755 if (!dbeSession->is_interactive ()) 1756 { 1757 m = new Emsg (CMSG_COMMENT, 1758 "============================================================"); 1759 notesq->append (m); 1760 } 1761 break; 1762 } 1763 size_t i = strlen (str); 1764 if (i > 0 && str[i - 1] == '\n') 1765 // remove trailing nl 1766 str[i - 1] = 0; 1767 m = new Emsg (CMSG_COMMENT, str); 1768 notesq->append (m); 1769 } 1770 (void) fclose (f); 1771} 1772 1773int 1774Experiment::save_notes (char* text, bool handle_file) 1775{ 1776 if (handle_file) 1777 { 1778 FILE *fnotes; 1779 char *fname = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_NOTES_FILE); 1780 fnotes = fopen (fname, NTXT ("w")); 1781 free (fname); 1782 if (fnotes != NULL) 1783 { 1784 (void) fprintf (fnotes, NTXT ("%s"), text); 1785 fclose (fnotes); 1786 } 1787 else 1788 return 1; // Cannot write file 1789 } 1790 notesq->clear (); 1791 Emsg *m = new Emsg (CMSG_COMMENT, text); 1792 notesq->append (m); 1793 1794 return 0; 1795} 1796 1797int 1798Experiment::delete_notes (bool handle_file) 1799{ 1800 if (handle_file) 1801 { 1802 char *fname = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_NOTES_FILE); 1803 if (unlink (fname) != 0) 1804 { 1805 free (fname); 1806 return 1; // Cannot delete file 1807 } 1808 free (fname); 1809 } 1810 notesq->clear (); 1811 return 0; 1812} 1813 1814int 1815Experiment::read_warn_file () 1816{ 1817 int local_status = SUCCESS; 1818 1819 ExperimentFile *warnFile = new ExperimentFile (this, SP_WARN_FILE); 1820 if (warnFile == NULL) 1821 return FAILURE; 1822 if (!warnFile->open ()) 1823 { 1824 delete warnFile; 1825 return FAILURE; 1826 } 1827 SAXParserFactory *factory = SAXParserFactory::newInstance (); 1828 SAXParser *saxParser = factory->newSAXParser (); 1829 DefaultHandler *dh = new ExperimentHandler (this); 1830 try 1831 { 1832 saxParser->parse ((File*) warnFile->fh, dh); 1833 } 1834 catch (SAXException *e) 1835 { 1836 // Fatal error in the parser 1837 StringBuilder sb; 1838 sb.sprintf (NTXT ("%s: %s"), SP_WARN_FILE, e->getMessage ()); 1839 char *str = sb.toString (); 1840 Emsg *m = new Emsg (CMSG_FATAL, str); 1841 errorq->append (m); 1842 local_status = FAILURE; 1843 delete e; 1844 } 1845 delete warnFile; 1846 delete dh; 1847 delete saxParser; 1848 delete factory; 1849 1850 return local_status; 1851} 1852 1853int 1854Experiment::read_log_file () 1855{ 1856 if (logFile == NULL) 1857 logFile = new ExperimentFile (this, SP_LOG_FILE); 1858 if (!logFile->open ()) 1859 { 1860 status = FAILURE; 1861 return status; 1862 } 1863 1864 SAXParserFactory *factory = SAXParserFactory::newInstance (); 1865 SAXParser *saxParser = factory->newSAXParser (); 1866 DefaultHandler *dh = new ExperimentHandler (this); 1867 try 1868 { 1869 saxParser->parse ((File*) logFile->fh, dh); 1870 } 1871 catch (SAXException *e) 1872 { 1873 // Fatal error in the parser 1874 StringBuilder sb; 1875 if (obsolete == 1) 1876 sb.sprintf (NTXT ("%s"), e->getMessage ()); 1877 else 1878 sb.sprintf (NTXT ("%s: %s"), SP_LOG_FILE, e->getMessage ()); 1879 char *str = sb.toString (); 1880 Emsg *m = new Emsg (CMSG_FATAL, str); 1881 errorq->append (m); 1882 status = FAILURE; 1883 delete e; 1884 } 1885 logFile->close (); 1886 dbeSession->register_metric (GTXT ("IPC"), GTXT ("Instructions Per Cycle"), 1887 NTXT ("insts/cycles")); 1888 dbeSession->register_metric (GTXT ("CPI"), GTXT ("Cycles Per Instruction"), 1889 NTXT ("cycles/insts")); 1890 dbeSession->register_metric (GTXT ("K_IPC"), 1891 GTXT ("Kernel Instructions Per Cycle"), 1892 NTXT ("K_insts/K_cycles")); 1893 dbeSession->register_metric (GTXT ("K_CPI"), 1894 GTXT ("Kernel Cycles Per Instruction"), 1895 NTXT ("K_cycles/K_insts")); 1896 1897 delete dh; 1898 delete saxParser; 1899 delete factory; 1900 1901 return status; 1902} 1903 1904//////////////////////////////////////////////////////////////////////////////// 1905// class Experiment::ExperimentLabelsHandler 1906// 1907 1908class Experiment::ExperimentLabelsHandler : public DefaultHandler 1909{ 1910public: 1911 1912 ExperimentLabelsHandler (Experiment *_exp) 1913 { 1914 exp = _exp; 1915 } 1916 1917 ~ExperimentLabelsHandler () { }; 1918 void startDocument () { } 1919 void endDocument () { } 1920 void endElement (char * /*uri*/, char * /*localName*/, char * /*qName*/) { } 1921 void characters (char * /*ch*/, int /*start*/, int /*length*/) { } 1922 void ignorableWhitespace (char*, int, int) { } 1923 void error (SAXParseException * /*e*/) { } 1924 1925 void startElement (char *uri, char *localName, char *qName, Attributes *attrs); 1926 1927private: 1928 1929 inline const char * 1930 s2s (const char *s) 1931 { 1932 return s ? s : "NULL"; 1933 } 1934 1935 Experiment *exp; 1936 char *hostname; 1937 hrtime_t time, tstamp; 1938}; 1939 1940void 1941Experiment::ExperimentLabelsHandler::startElement (char*, char*, char *qName, 1942 Attributes *attrs) 1943{ 1944 DEBUG_CODE if (DEBUG_SAXPARSER) dump_startElement (qName, attrs); 1945 if (qName == NULL || strcmp (qName, NTXT ("id")) != 0) 1946 return; 1947 char *name = NULL, *all_times = NULL, *comment = NULL, *hostName = NULL; 1948 long startSec = 0; 1949 // long tm_zone = 0; 1950 hrtime_t startHrtime = (hrtime_t) 0; 1951 long long lbl_ts = 0; 1952 int relative = 0; 1953 timeval start_tv; 1954 start_tv.tv_usec = start_tv.tv_sec = 0; 1955 for (int i = 0, sz = attrs ? attrs->getLength () : 0; i < sz; i++) 1956 { 1957 const char *qn = attrs->getQName (i); 1958 const char *vl = attrs->getValue (i); 1959 if (strcmp (qn, NTXT ("name")) == 0) 1960 name = dbe_xml2str (vl); 1961 else if (strcmp (qn, NTXT ("cmd")) == 0) 1962 all_times = dbe_xml2str (vl); 1963 else if (strcmp (qn, NTXT ("comment")) == 0) 1964 comment = dbe_xml2str (vl); 1965 else if (strcmp (qn, NTXT ("relative")) == 0) 1966 relative = atoi (vl); 1967 else if (strcmp (qn, NTXT ("hostname")) == 0) 1968 hostName = dbe_xml2str (vl); 1969 else if (strcmp (qn, NTXT ("time")) == 0) 1970 startSec = atol (vl); 1971 else if (strcmp (qn, NTXT ("tstamp")) == 0) 1972 startHrtime = parseTStamp (vl); 1973 else if (strcmp (qn, NTXT ("lbl_ts")) == 0) 1974 { 1975 if (*vl == '-') 1976 lbl_ts = -parseTStamp (vl + 1); 1977 else 1978 lbl_ts = parseTStamp (vl); 1979 } 1980 } 1981 if (name == NULL || hostName == NULL || (all_times == NULL && comment == NULL)) 1982 { 1983 free (name); 1984 free (hostName); 1985 free (all_times); 1986 free (comment); 1987 return; 1988 } 1989 UserLabel *lbl = new UserLabel (name); 1990 lbl->comment = comment; 1991 lbl->hostname = hostName; 1992 lbl->start_sec = startSec; 1993 lbl->start_hrtime = startHrtime; 1994 exp->userLabels->append (lbl); 1995 if (all_times) 1996 { 1997 lbl->all_times = all_times; 1998 lbl->start_tv = start_tv; 1999 lbl->relative = relative; 2000 if (relative == UserLabel::REL_TIME) 2001 lbl->atime = lbl_ts; 2002 else 2003 { // relative == UserLabel::CUR_TIME 2004 long long delta = 0; 2005 if (exp->hostname && strcmp (lbl->hostname, exp->hostname) == 0) 2006 delta = lbl_ts + (lbl->start_hrtime - exp->exp_start_time); 2007 else 2008 for (int i = 0; i < exp->userLabels->size (); i++) 2009 { 2010 UserLabel *firstLbl = exp->userLabels->fetch (i); 2011 if (strcmp (lbl->hostname, firstLbl->hostname) == 0) 2012 { 2013 delta = lbl_ts + (lbl->start_hrtime - firstLbl->start_hrtime) + 2014 ((long long) (firstLbl->start_sec - exp->start_sec)) * NANOSEC; 2015 break; 2016 } 2017 } 2018 lbl->atime = delta > 0 ? delta : 0; 2019 } 2020 } 2021} 2022 2023static int 2024sortUserLabels (const void *a, const void *b) 2025{ 2026 UserLabel *l1 = *((UserLabel **) a); 2027 UserLabel *l2 = *((UserLabel **) b); 2028 int v = dbe_strcmp (l1->name, l2->name); 2029 if (v != 0) 2030 return v; 2031 if (l1->atime < l2->atime) 2032 return -1; 2033 else if (l1->atime > l2->atime) 2034 return 1; 2035 if (l1->id < l2->id) 2036 return -1; 2037 else if (l1->id > l2->id) 2038 return 1; 2039 return 0; 2040} 2041 2042static char * 2043append_string (char *s, char *str) 2044{ 2045 if (s == NULL) 2046 return dbe_strdup (str); 2047 char *new_s = dbe_sprintf (NTXT ("%s %s"), s, str); 2048 free (s); 2049 return new_s; 2050} 2051 2052void 2053Experiment::read_labels_file () 2054{ 2055 ExperimentFile *fp = new ExperimentFile (this, SP_LABELS_FILE); 2056 if (!fp->open ()) 2057 { 2058 delete fp; 2059 return; 2060 } 2061 userLabels = new Vector<UserLabel*>(); 2062 SAXParserFactory *factory = SAXParserFactory::newInstance (); 2063 SAXParser *saxParser = factory->newSAXParser (); 2064 DefaultHandler *dh = new ExperimentLabelsHandler (this); 2065 try 2066 { 2067 saxParser->parse ((File*) fp->fh, dh); 2068 } 2069 catch (SAXException *e) 2070 { 2071 // Fatal error in the parser 2072 StringBuilder sb; 2073 sb.sprintf (NTXT ("%s: %s"), SP_LABELS_FILE, e->getMessage ()); 2074 char *str = sb.toString (); 2075 Emsg *m = new Emsg (CMSG_FATAL, str); 2076 errorq->append (m); 2077 delete e; 2078 } 2079 fp->close (); 2080 delete fp; 2081 delete dh; 2082 delete saxParser; 2083 delete factory; 2084 2085 userLabels->sort (sortUserLabels); 2086 UserLabel::dump ("After sortUserLabels:", userLabels); 2087 UserLabel *ulbl = NULL; 2088 for (int i = 0, sz = userLabels->size (); i < sz; i++) 2089 { 2090 UserLabel *lbl = userLabels->fetch (i); 2091 if (ulbl == NULL) 2092 ulbl = new UserLabel (lbl->name); 2093 else if (dbe_strcmp (lbl->name, ulbl->name) != 0) 2094 { // new Label 2095 ulbl->register_user_label (groupId); 2096 if (ulbl->expr == NULL) 2097 delete ulbl; 2098 ulbl = new UserLabel (lbl->name); 2099 } 2100 if (lbl->all_times) 2101 { 2102 if (strncmp (lbl->all_times, NTXT ("start"), 5) == 0) 2103 { 2104 if (!ulbl->start_f) 2105 { 2106 ulbl->start_f = true; 2107 ulbl->timeStart = lbl->atime; 2108 } 2109 } 2110 else 2111 { // stop 2112 if (!ulbl->start_f) 2113 continue; 2114 ulbl->all_times = append_string (ulbl->all_times, lbl->all_times); 2115 ulbl->stop_f = true; 2116 ulbl->timeStop = lbl->atime; 2117 ulbl->gen_expr (); 2118 } 2119 } 2120 if (lbl->comment != NULL) 2121 ulbl->comment = append_string (ulbl->comment, lbl->comment); 2122 } 2123 if (ulbl) 2124 { 2125 ulbl->register_user_label (groupId); 2126 if (ulbl->expr == NULL) 2127 delete ulbl; 2128 } 2129 Destroy (userLabels); 2130} 2131 2132void 2133Experiment::read_archives () 2134{ 2135 if (founder_exp) 2136 return; 2137 char *allocated_str = NULL; 2138 char *nm = get_arch_name (); 2139 DIR *exp_dir = opendir (nm); 2140 if (exp_dir == NULL) 2141 { 2142 if (founder_exp == NULL) 2143 { 2144 // Check if the user uses a subexperiment only 2145 nm = dbe_sprintf (NTXT ("%s/../%s"), expt_name, SP_ARCHIVES_DIR); 2146 exp_dir = opendir (nm); 2147 if (exp_dir == NULL) 2148 { 2149 free (nm); 2150 return; 2151 } 2152 allocated_str = nm; 2153 } 2154 else 2155 return; 2156 } 2157 2158 StringBuilder sb; 2159 sb.append (nm); 2160 sb.append ('/'); 2161 int dlen = sb.length (); 2162 free (allocated_str); 2163 archiveMap = new StringMap<DbeFile *>(); 2164 2165 struct dirent *entry = NULL; 2166 while ((entry = readdir (exp_dir)) != NULL) 2167 { 2168 char *dname = entry->d_name; 2169 if (dname[0] == '.' 2170 && (dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0'))) 2171 // skip links to ./ or ../ 2172 continue; 2173 sb.setLength (dlen); 2174 sb.append (dname); 2175 char *fnm = sb.toString (); 2176 DbeFile *df = new DbeFile (fnm); 2177 df->set_location (fnm); 2178 df->filetype |= DbeFile::F_FILE; 2179 df->inArchive = true; 2180 df->experiment = this; 2181 archiveMap->put (dname, df); 2182 free (fnm); 2183 } 2184 closedir (exp_dir); 2185} 2186 2187static char * 2188gen_file_name (const char *packet_name, const char *src_name) 2189{ 2190 char *fnm, *bname = get_basename (packet_name); 2191 if (bname == packet_name) 2192 fnm = dbe_strdup (src_name); 2193 else 2194 fnm = dbe_sprintf ("%.*s%s", (int) (bname - packet_name), 2195 packet_name, src_name); 2196 2197 // convert "java.lang.Object/Integer.java" => "java/lang/Object/Integer.java" 2198 bname = get_basename (fnm); 2199 for (char *s = fnm; s < bname; s++) 2200 if (*s == '.') 2201 *s = '/'; 2202 return fnm; 2203} 2204 2205static char * 2206get_jlass_name (const char *nm) 2207{ 2208 // Convert "Ljava/lang/Object;" => "java/lang/Object.class" 2209 if (*nm == 'L') 2210 { 2211 size_t len = strlen (nm); 2212 if (nm[len - 1] == ';') 2213 return dbe_sprintf ("%.*s.class", (int) (len - 2), nm + 1); 2214 } 2215 return dbe_strdup (nm); 2216} 2217 2218static char * 2219get_jmodule_name (const char *nm) 2220{ 2221 // convert "Ljava/lang/Object;" => "java.lang.Object" 2222 if (*nm == 'L') 2223 { 2224 size_t len = strlen (nm); 2225 if (nm[len - 1] == ';') 2226 { 2227 char *mname = dbe_sprintf (NTXT ("%.*s"), (int) (len - 2), nm + 1); 2228 for (char *s = mname; *s; s++) 2229 if (*s == '/') 2230 *s = '.'; 2231 return mname; 2232 } 2233 } 2234 return dbe_strdup (nm); 2235} 2236 2237LoadObject * 2238Experiment::get_j_lo (const char *className, const char *fileName) 2239{ 2240 char *class_name = get_jlass_name (className); 2241 Dprintf (DUMP_JCLASS_READER, 2242 "Experiment::get_j_lo: className='%s' class_name='%s' fileName='%s'\n", 2243 STR (className), STR (class_name), STR (fileName)); 2244 LoadObject *lo = loadObjMap->get (class_name); 2245 if (lo == NULL) 2246 { 2247 lo = createLoadObject (class_name, fileName); 2248 lo->type = LoadObject::SEG_TEXT; 2249 lo->mtime = (time_t) 0; 2250 lo->size = 0; 2251 lo->set_platform (Java, wsize); 2252 lo->dbeFile->filetype |= DbeFile::F_FILE | DbeFile::F_JAVACLASS; 2253 append (lo); 2254 Dprintf (DUMP_JCLASS_READER, 2255 "Experiment::get_j_lo: creates '%s' location='%s'\n", 2256 STR (lo->get_name ()), STR (lo->dbeFile->get_location (false))); 2257 } 2258 free (class_name); 2259 return lo; 2260} 2261 2262Module * 2263Experiment::get_jclass (const char *className, const char *fileName) 2264{ 2265 LoadObject *lo = get_j_lo (className, NULL); 2266 char *mod_name = get_jmodule_name (className); 2267 Module *mod = lo->find_module (mod_name); 2268 if (mod == NULL) 2269 { 2270 mod = dbeSession->createClassFile (mod_name); 2271 mod->loadobject = lo; 2272 if (strcmp (fileName, NTXT ("<Unknown>")) != 0) 2273 mod->set_file_name (gen_file_name (lo->get_pathname (), fileName)); 2274 else 2275 mod->set_file_name (dbe_strdup (fileName)); 2276 lo->append_module (mod); 2277 mod_name = NULL; 2278 } 2279 else if (mod->file_name && (strcmp (mod->file_name, "<Unknown>") == 0) 2280 && strcmp (fileName, "<Unknown>") != 0) 2281 mod->set_file_name (gen_file_name (lo->get_pathname (), fileName)); 2282 Dprintf (DUMP_JCLASS_READER, 2283 "Experiment::get_jclass: class_name='%s' mod_name='%s' fileName='%s'\n", 2284 mod->loadobject->get_pathname (), mod->get_name (), mod->file_name); 2285 free (mod_name); 2286 return mod; 2287} 2288 2289#define ARCH_STRLEN(s) ( ( strlen(s) + 4 ) & ~0x3 ) 2290 2291int 2292Experiment::read_java_classes_file () 2293{ 2294 char *data_file_name = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_JCLASSES_FILE); 2295 Data_window *dwin = new Data_window (data_file_name); 2296 free (data_file_name); 2297 if (dwin->not_opened ()) 2298 { 2299 delete dwin; 2300 return INCOMPLETE; 2301 } 2302 dwin->need_swap_endian = need_swap_endian; 2303 jmaps = new PRBTree (); 2304 jmidHTable = new DbeCacheMap<unsigned long long, JMethod>; 2305 2306 hrtime_t cur_loaded = 0; 2307 Module *cur_mod = NULL; 2308 for (int64_t offset = 0;;) 2309 { 2310 CM_Packet *cpkt = (CM_Packet*) dwin->bind (offset, sizeof (CM_Packet)); 2311 if (cpkt == NULL) 2312 break; 2313 uint16_t v16 = (uint16_t) cpkt->tsize; 2314 size_t cpktsize = dwin->decode (v16); 2315 cpkt = (CM_Packet*) dwin->bind (offset, cpktsize); 2316 if ((cpkt == NULL) || (cpktsize == 0)) 2317 { 2318 char *buf = dbe_sprintf (GTXT ("archive file malformed %s"), 2319 arch_name); 2320 errorq->append (new Emsg (CMSG_ERROR, buf)); 2321 free (buf); 2322 break; 2323 } 2324 v16 = (uint16_t) cpkt->type; 2325 v16 = dwin->decode (v16); 2326 switch (v16) 2327 { 2328 case ARCH_JCLASS: 2329 { 2330 ARCH_jclass *ajcl = (ARCH_jclass*) cpkt; 2331 uint64_t class_id = dwin->decode (ajcl->class_id); 2332 char *className = ((char*) ajcl) + sizeof (*ajcl); 2333 char *fileName = className + ARCH_STRLEN (className); 2334 Dprintf (DUMP_JCLASS_READER, 2335 "read_java_classes_file: ARCH_JCLASS(Ox%x)" 2336 "class_id=Ox%llx className='%s' fileName='%s' \n", 2337 (int) v16, (long long) class_id, className, fileName); 2338 cur_mod = NULL; 2339 if (*className == 'L') 2340 { // Old libcollector generated '[' (one array dimension). 2341 cur_mod = get_jclass (className, fileName); 2342 cur_loaded = dwin->decode (ajcl->tstamp); 2343 jmaps->insert (class_id, cur_loaded, cur_mod); 2344 } 2345 break; 2346 } 2347 case ARCH_JCLASS_LOCATION: 2348 { 2349 ARCH_jclass_location *ajcl = (ARCH_jclass_location *) cpkt; 2350 uint64_t class_id = dwin->decode (ajcl->class_id); 2351 char *className = ((char*) ajcl) + sizeof (*ajcl); 2352 char *fileName = className + ARCH_STRLEN (className); 2353 Dprintf (DUMP_JCLASS_READER, 2354 "read_java_classes_file: ARCH_JCLASS_LOCATION(Ox%x)" 2355 "class_id=Ox%llx className='%s' fileName='%s' \n", 2356 (int) v16, (long long) class_id, className, fileName); 2357 get_j_lo (className, fileName); 2358 break; 2359 } 2360 case ARCH_JMETHOD: 2361 { 2362 if (cur_mod == NULL) 2363 break; 2364 ARCH_jmethod *ajmt = (ARCH_jmethod*) cpkt; 2365 uint64_t method_id = dwin->decode (ajmt->method_id); 2366 char *s_name = ((char*) ajmt) + sizeof (*ajmt); 2367 char *s_signature = s_name + ARCH_STRLEN (s_name); 2368 char *fullname = dbe_sprintf ("%s.%s", cur_mod->get_name (), s_name); 2369 Dprintf (DUMP_JCLASS_READER, 2370 "read_java_classes_file: ARCH_JMETHOD(Ox%x) " 2371 "method_id=Ox%llx name='%s' signature='%s' fullname='%s'\n", 2372 (int) v16, (long long) method_id, s_name, 2373 s_signature, fullname); 2374 JMethod *jmthd = cur_mod->find_jmethod (fullname, s_signature); 2375 if (jmthd == NULL) 2376 { 2377 jmthd = dbeSession->createJMethod (); 2378 jmthd->size = (unsigned) - 1; // unknown until later (maybe) 2379 jmthd->module = cur_mod; 2380 jmthd->set_signature (s_signature); 2381 jmthd->set_name (fullname); 2382 cur_mod->functions->append (jmthd); 2383 cur_mod->loadobject->functions->append (jmthd); 2384 Dprintf (DUMP_JCLASS_READER, 2385 "read_java_classes_file: ARCH_JMETHOD CREATE fullname=%s\n", 2386 fullname); 2387 } 2388 jmaps->insert (method_id, cur_loaded, jmthd); 2389 free (fullname); 2390 break; 2391 } 2392 default: 2393 Dprintf (DUMP_JCLASS_READER, 2394 "read_java_classes_file: type=Ox%x (%d) cpktsize=%d\n", 2395 (int) v16, (int) v16, (int) cpktsize); 2396 break; // ignore unknown packets 2397 } 2398 offset += cpktsize; 2399 } 2400 delete dwin; 2401 return SUCCESS; 2402} 2403 2404void 2405Experiment::read_map_file () 2406{ 2407 ExperimentFile *mapFile = new ExperimentFile (this, SP_MAP_FILE); 2408 if (!mapFile->open ()) 2409 { 2410 delete mapFile; 2411 return; 2412 } 2413 2414 SAXParserFactory *factory = SAXParserFactory::newInstance (); 2415 SAXParser *saxParser = factory->newSAXParser (); 2416 DefaultHandler *dh = new ExperimentHandler (this); 2417 try 2418 { 2419 saxParser->parse ((File*) mapFile->fh, dh); 2420 } 2421 catch (SAXException *e) 2422 { 2423 // Fatal error in the parser 2424 StringBuilder sb; 2425 sb.sprintf (NTXT ("%s: %s"), SP_MAP_FILE, e->getMessage ()); 2426 char *str = sb.toString (); 2427 Emsg *m = new Emsg (CMSG_FATAL, str); 2428 errorq->append (m); 2429 status = FAILURE; 2430 free (str); 2431 delete e; 2432 } 2433 delete mapFile; 2434 delete dh; 2435 delete saxParser; 2436 delete factory; 2437 2438 for (int i = 0, sz = mrecs ? mrecs->size () : 0; i < sz; i++) 2439 { 2440 MapRecord *mrec = mrecs->fetch (i); 2441 SegMem *smem, *sm_lo, *sm_hi; 2442 switch (mrec->kind) 2443 { 2444 case MapRecord::LOAD: 2445 smem = new SegMem; 2446 smem->base = mrec->base; 2447 smem->size = mrec->size; 2448 smem->load_time = mrec->ts; 2449 smem->unload_time = MAX_TIME; 2450 smem->obj = mrec->obj; 2451 smem->set_file_offset (mrec->foff); 2452 seg_items->append (smem); // add to the master list 2453 2454 // Check if the new segment overlaps other active segments 2455 sm_lo = (SegMem*) maps->locate (smem->base, smem->load_time); 2456 if (sm_lo && sm_lo->base + sm_lo->size > smem->base) 2457 { 2458 // check to see if it is a duplicate record: same address and size, and 2459 if ((smem->base == sm_lo->base) && (smem->size == sm_lo->size)) 2460 { 2461 // addresses and sizes match, check name 2462 if (strstr (smem->obj->get_name (), sm_lo->obj->get_name ()) != NULL 2463 || strstr (sm_lo->obj->get_name (), smem->obj->get_name ()) != NULL) 2464 // this is a duplicate; just move on the the next map record 2465 continue; 2466 fprintf (stderr, 2467 GTXT ("*** Warning: Segment `%s' loaded with same address, size as `%s' [0x%llx-0x%llx]\n"), 2468 smem->obj->get_name (), sm_lo->obj->get_name (), 2469 sm_lo->base, sm_lo->base + sm_lo->size); 2470 } 2471 2472 // Not a duplicate; implicitly unload the old one 2473 // Note: implicit unloading causes high <Unknown> 2474 // when such overlapping is bogus 2475 StringBuilder sb; 2476 sb.sprintf (GTXT ("*** Warning: Segment %s [0x%llx-0x%llx] overlaps %s [0x%llx-0x%llx], which has been implicitly unloaded"), 2477 smem->obj->get_name (), smem->base, smem->base + smem->size, 2478 sm_lo->obj->get_name (), sm_lo->base, sm_lo->base + sm_lo->size); 2479 warnq->append (new Emsg (CMSG_WARN, sb)); 2480 } 2481 2482 // now look for other segments with which this might overlap 2483 sm_hi = (SegMem*) maps->locate_up (smem->base, smem->load_time); 2484 while (sm_hi && sm_hi->base < smem->base + smem->size) 2485 { 2486 2487 // Note: implicit unloading causes high <Unknown> when such overlapping is bogus 2488 // maps->remove( sm_hi->base, smem->load_time ); 2489 StringBuilder sb; 2490 sb.sprintf (GTXT ("*** Warning: Segment %s [0x%llx-0x%llx] overlaps %s [0x%llx-0x%llx], which has been implicitly unloaded"), 2491 smem->obj->get_name (), smem->base, 2492 smem->base + smem->size, sm_hi->obj->get_name (), 2493 sm_hi->base, sm_hi->base + sm_hi->size); 2494 warnq->append (new Emsg (CMSG_WARN, sb)); 2495 sm_hi = (SegMem*) maps->locate_up (sm_hi->base + sm_hi->size, 2496 smem->load_time); 2497 } 2498 2499 maps->insert (smem->base, smem->load_time, smem); 2500 break; 2501 case MapRecord::UNLOAD: 2502 smem = (SegMem*) maps->locate (mrec->base, mrec->ts); 2503 if (smem && smem->base == mrec->base) 2504 { 2505 smem->unload_time = mrec->ts; 2506 maps->remove (mrec->base, mrec->ts); 2507 } 2508 break; 2509 } 2510 } 2511 mrecs->destroy (); 2512 2513 // See if there are comments or warnings for a load object; 2514 // if so, queue them to Experiment 2515 for (long i = 0, sz = loadObjs ? loadObjs->size () : 0; i < sz; i++) 2516 { 2517 LoadObject *lo = loadObjs->get (i); 2518 for (Emsg *m = lo->fetch_warnings (); m; m = m->next) 2519 warnq->append (m->get_warn (), m->get_msg ()); 2520 for (Emsg *m = lo->fetch_comments (); m; m = m->next) 2521 commentq->append (m->get_warn (), m->get_msg ()); 2522 } 2523} 2524 2525void 2526Experiment::read_frameinfo_file () 2527{ 2528 init_cache (); 2529 char *base_name = get_basename (expt_name); 2530 char *msg = dbe_sprintf (GTXT ("Loading CallStack Data: %s"), base_name); 2531 read_data_file ("data." SP_FRINFO_FILE, msg); 2532 free (msg); 2533 frmpckts->sort (frUidCmp); 2534 uidnodes->sort (uidNodeCmp); 2535} 2536 2537void 2538Experiment::read_omp_preg () 2539{ 2540 // Parallel region descriptions 2541 DataDescriptor *pregDdscr = getDataDescriptor (DATA_OMP4); 2542 if (pregDdscr == NULL) 2543 return; 2544 DataView *pregData = pregDdscr->createView (); 2545 pregData->sort (PROP_CPRID); // omptrace PROP_CPRID 2546 2547 // OpenMP enter parreg events 2548 DataDescriptor *dDscr = getDataDescriptor (DATA_OMP2); 2549 if (dDscr == NULL || dDscr->getSize () == 0) 2550 { 2551 delete pregData; 2552 return; 2553 } 2554 2555 char *idxname = NTXT ("OMP_preg"); 2556 delete dbeSession->indxobj_define (idxname, GTXT ("OpenMP Parallel Region"), 2557 NTXT ("CPRID"), NULL, NULL); 2558 int idxtype = dbeSession->findIndexSpaceByName (idxname); 2559 if (idxtype < 0) 2560 { 2561 delete pregData; 2562 return; 2563 } 2564 ompavail = true; 2565 2566 // Pre-create parallel region with id == 0 2567 Histable *preg0 = dbeSession->createIndexObject (idxtype, (int64_t) 0); 2568 preg0->set_name (dbe_strdup (GTXT ("Implicit OpenMP Parallel Region"))); 2569 2570 // Take care of the progress bar 2571 char *msg = dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"), 2572 get_basename (expt_name)); 2573 theApplication->set_progress (0, msg); 2574 free (msg); 2575 long deltaReport = 1000; 2576 long nextReport = 0; 2577 long errors_found = 0; 2578 Vector<Histable*> pregs; 2579 2580 long size = dDscr->getSize (); 2581 for (long i = 0; i < size; ++i) 2582 { 2583 if (i == nextReport) 2584 { 2585 int percent = (int) (i * 100 / size); 2586 if (percent > 0) 2587 theApplication->set_progress (percent, NULL); 2588 nextReport += deltaReport; 2589 } 2590 2591 uint32_t thrid = dDscr->getIntValue (PROP_THRID, i); 2592 hrtime_t tstamp = dDscr->getLongValue (PROP_TSTAMP, i); 2593 uint64_t cprid = dDscr->getLongValue (PROP_CPRID, i); // omptrace CPRID 2594 mapPRid->put (thrid, tstamp, cprid); 2595 2596 pregs.reset (); 2597 /* 2598 * We will use 2 pointers to make sure there is no loop. 2599 * First pointer "curpreg" goes to the next element, 2600 * second pointer "curpreg_loop_control" goes to the next->next element. 2601 * If these pointers have the same value - there is a loop. 2602 */ 2603 uint64_t curpreg_loop_control = cprid; 2604 Datum tval_loop_control; 2605 if (curpreg_loop_control != 0) 2606 { 2607 tval_loop_control.setUINT64 (curpreg_loop_control); 2608 long idx = pregData->getIdxByVals (&tval_loop_control, DataView::REL_EQ); 2609 if (idx < 0) 2610 curpreg_loop_control = 0; 2611 else 2612 curpreg_loop_control = pregData->getLongValue (PROP_PPRID, idx); 2613 } 2614 for (uint64_t curpreg = cprid; curpreg != 0;) 2615 { 2616 Histable *val = NULL; 2617 Datum tval; 2618 tval.setUINT64 (curpreg); 2619 long idx = pregData->getIdxByVals (&tval, DataView::REL_EQ); 2620 if (idx < 0) 2621 break; 2622 /* 2623 * Check if there is a loop 2624 */ 2625 if (0 != curpreg_loop_control) 2626 { 2627 if (curpreg == curpreg_loop_control) 2628 { 2629 errors_found++; 2630 if (1 == errors_found) 2631 { 2632 Emsg *m = new Emsg (CMSG_WARN, GTXT ("*** Warning: circular links in OMP regions; data may not be correct.")); 2633 warnq->append (m); 2634 } 2635 break; 2636 } 2637 } 2638 uint64_t pragmapc = pregData->getLongValue (PROP_PRPC, idx); 2639 DbeInstr *instr = map_Vaddr_to_PC (pragmapc, tstamp); 2640 if (instr == NULL) 2641 { 2642 break; 2643 } 2644 val = instr; 2645 DbeLine *dbeline = (DbeLine*) instr->convertto (Histable::LINE); 2646 if (dbeline->lineno > 0) 2647 { 2648 if (instr->func->usrfunc) 2649 dbeline = dbeline->sourceFile->find_dbeline 2650 (instr->func->usrfunc, dbeline->lineno); 2651 dbeline->set_flag (DbeLine::OMPPRAGMA); 2652 val = dbeline; 2653 } 2654 val = dbeSession->createIndexObject (idxtype, val); 2655 pregs.append (val); 2656 2657 curpreg = pregData->getLongValue (PROP_PPRID, idx); 2658 /* 2659 * Update curpreg_loop_control 2660 */ 2661 if (0 != curpreg_loop_control) 2662 { 2663 tval_loop_control.setUINT64 (curpreg_loop_control); 2664 idx = pregData->getIdxByVals 2665 (&tval_loop_control, DataView::REL_EQ); 2666 if (idx < 0) 2667 curpreg_loop_control = 0; 2668 else 2669 { 2670 curpreg_loop_control = pregData->getLongValue 2671 (PROP_PPRID, idx); 2672 tval_loop_control.setUINT64 (curpreg_loop_control); 2673 idx = pregData->getIdxByVals 2674 (&tval_loop_control, DataView::REL_EQ); 2675 if (idx < 0) 2676 curpreg_loop_control = 0; 2677 else 2678 curpreg_loop_control = pregData->getLongValue 2679 (PROP_PPRID, idx); 2680 } 2681 } 2682 } 2683 pregs.append (preg0); 2684 void *prstack = cstack->add_stack (&pregs); 2685 mapPReg->put (thrid, tstamp, prstack); 2686 } 2687 theApplication->set_progress (0, NTXT ("")); 2688 delete pregData; 2689} 2690 2691void 2692Experiment::read_omp_task () 2693{ 2694 // Task description 2695 DataDescriptor *taskDataDdscr = getDataDescriptor (DATA_OMP5); 2696 if (taskDataDdscr == NULL) 2697 return; 2698 2699 //7035272: previously, DataView was global; now it's local...is this OK? 2700 DataView *taskData = taskDataDdscr->createView (); 2701 taskData->sort (PROP_TSKID); // omptrace PROP_TSKID 2702 2703 // OpenMP enter task events 2704 DataDescriptor *dDscr = getDataDescriptor (DATA_OMP3); 2705 if (dDscr == NULL || dDscr->getSize () == 0) 2706 { 2707 delete taskData; 2708 return; 2709 } 2710 2711 char *idxname = NTXT ("OMP_task"); 2712 // delete a possible error message. Ugly. 2713 delete dbeSession->indxobj_define (idxname, GTXT ("OpenMP Task"), NTXT ("TSKID"), NULL, NULL); 2714 int idxtype = dbeSession->findIndexSpaceByName (idxname); 2715 if (idxtype < 0) 2716 { 2717 delete taskData; 2718 return; 2719 } 2720 ompavail = true; 2721 2722 // Pre-create task with id == 0 2723 Histable *task0 = dbeSession->createIndexObject (idxtype, (int64_t) 0); 2724 task0->set_name (dbe_strdup (GTXT ("OpenMP Task from Implicit Parallel Region"))); 2725 2726 // Take care of the progress bar 2727 char *msg = dbe_sprintf (GTXT ("Processing OpenMP Task Data: %s"), get_basename (expt_name)); 2728 theApplication->set_progress (0, msg); 2729 free (msg); 2730 long deltaReport = 1000; 2731 long nextReport = 0; 2732 2733 Vector<Histable*> tasks; 2734 long size = dDscr->getSize (); 2735 long errors_found = 0; 2736 for (long i = 0; i < size; ++i) 2737 { 2738 if (i == nextReport) 2739 { 2740 int percent = (int) (i * 100 / size); 2741 if (percent > 0) 2742 theApplication->set_progress (percent, NULL); 2743 nextReport += deltaReport; 2744 } 2745 2746 uint32_t thrid = dDscr->getIntValue (PROP_THRID, i); 2747 hrtime_t tstamp = dDscr->getLongValue (PROP_TSTAMP, i); 2748 uint64_t tskid = dDscr->getLongValue (PROP_TSKID, i); //omptrace TSKID 2749 tasks.reset (); 2750 /* 2751 * We will use 2 pointers to make sure there is no loop. 2752 * First pointer "curtsk" goes to the next element, 2753 * second pointer "curtsk_loop_control" goes to the next->next element. 2754 * If these pointers have the same value - there is a loop. 2755 */ 2756 uint64_t curtsk_loop_control = tskid; 2757 Datum tval_loop_control; 2758 if (curtsk_loop_control != 0) 2759 { 2760 tval_loop_control.setUINT64 (curtsk_loop_control); 2761 long idx = taskData->getIdxByVals (&tval_loop_control, DataView::REL_EQ); 2762 if (idx < 0) 2763 curtsk_loop_control = 0; 2764 else 2765 curtsk_loop_control = taskData->getLongValue (PROP_PTSKID, idx); 2766 } 2767 for (uint64_t curtsk = tskid; curtsk != 0;) 2768 { 2769 Histable *val = NULL; 2770 2771 Datum tval; 2772 tval.setUINT64 (curtsk); 2773 long idx = taskData->getIdxByVals (&tval, DataView::REL_EQ); 2774 if (idx < 0) 2775 break; 2776 /* 2777 * Check if there is a loop 2778 */ 2779 if (0 != curtsk_loop_control) 2780 { 2781 if (curtsk == curtsk_loop_control) 2782 { 2783 errors_found++; 2784 if (1 == errors_found) 2785 { 2786 Emsg *m = new Emsg (CMSG_WARN, GTXT ("*** Warning: circular links in OMP tasks; data may not be correct.")); 2787 warnq->append (m); 2788 } 2789 break; 2790 } 2791 } 2792 uint64_t pragmapc = taskData->getLongValue (PROP_PRPC, idx); 2793 DbeInstr *instr = map_Vaddr_to_PC (pragmapc, tstamp); 2794 if (instr == NULL) 2795 break; 2796 val = instr; 2797 DbeLine *dbeline = (DbeLine*) instr->convertto (Histable::LINE); 2798 if (dbeline->lineno > 0) 2799 { 2800 if (instr->func->usrfunc) 2801 dbeline = dbeline->sourceFile->find_dbeline 2802 (instr->func->usrfunc, dbeline->lineno); 2803 dbeline->set_flag (DbeLine::OMPPRAGMA); 2804 val = dbeline; 2805 } 2806 val = dbeSession->createIndexObject (idxtype, val); 2807 tasks.append (val); 2808 2809 curtsk = taskData->getLongValue (PROP_PTSKID, idx); 2810 /* 2811 * Update curtsk_loop_control 2812 */ 2813 if (0 != curtsk_loop_control) 2814 { 2815 tval_loop_control.setUINT64 (curtsk_loop_control); 2816 idx = taskData->getIdxByVals (&tval_loop_control, DataView::REL_EQ); 2817 if (idx < 0) 2818 curtsk_loop_control = 0; 2819 else 2820 { 2821 curtsk_loop_control = taskData->getLongValue (PROP_PTSKID, idx); 2822 tval_loop_control.setUINT64 (curtsk_loop_control); 2823 idx = taskData->getIdxByVals (&tval_loop_control, 2824 DataView::REL_EQ); 2825 if (idx < 0) 2826 curtsk_loop_control = 0; 2827 else 2828 curtsk_loop_control = taskData->getLongValue (PROP_PTSKID, 2829 idx); 2830 } 2831 } 2832 } 2833 tasks.append (task0); 2834 void *tskstack = cstack->add_stack (&tasks); 2835 mapTask->put (thrid, tstamp, tskstack); 2836 } 2837 theApplication->set_progress (0, NTXT ("")); 2838 delete taskData; 2839} 2840 2841void 2842Experiment::read_omp_file () 2843{ 2844 // DATA_OMP2 table is common between OpenMP 2.5 and 3.0 profiling 2845 DataDescriptor *dDscr = getDataDescriptor (DATA_OMP2); 2846 if (dDscr == NULL) 2847 return; 2848 if (dDscr->getSize () == 0) 2849 { 2850 char *base_name = get_basename (expt_name); 2851 char *msg = dbe_sprintf (GTXT ("Loading OpenMP Data: %s"), base_name); 2852 read_data_file (SP_OMPTRACE_FILE, msg); 2853 free (msg); 2854 2855 // OpenMP fork events 2856 dDscr = getDataDescriptor (DATA_OMP); 2857 long sz = dDscr->getSize (); 2858 if (sz > 0) 2859 { 2860 // progress bar 2861 msg = dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"), 2862 base_name); 2863 theApplication->set_progress (0, msg); 2864 free (msg); 2865 long deltaReport = 5000; 2866 long nextReport = 0; 2867 for (int i = 0; i < sz; ++i) 2868 { 2869 if (i == nextReport) 2870 { 2871 int percent = (int) (i * 100 / sz); 2872 if (percent > 0) 2873 theApplication->set_progress (percent, NULL); 2874 nextReport += deltaReport; 2875 } 2876 uint32_t thrid = dDscr->getIntValue (PROP_THRID, i); 2877 hrtime_t tstamp = dDscr->getLongValue (PROP_TSTAMP, i); 2878 uint64_t cprid = dDscr->getLongValue (PROP_CPRID, i); //omptrace 2879 mapPRid->put (thrid, tstamp, cprid); 2880 } 2881 theApplication->set_progress (0, NTXT ("")); 2882 2883 ompavail = true; 2884 openMPdata = dDscr->createView (); 2885 openMPdata->sort (PROP_CPRID); // omptrace PROP_CPRID 2886 2887 // thread enters parreg events 2888 dDscr = getDataDescriptor (DATA_OMP2); 2889 sz = dDscr->getSize (); 2890 2891 // progress bar 2892 msg = dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"), 2893 base_name); 2894 theApplication->set_progress (0, msg); 2895 free (msg); 2896 deltaReport = 5000; 2897 nextReport = 0; 2898 2899 for (int i = 0; i < sz; ++i) 2900 { 2901 if (i == nextReport) 2902 { 2903 int percent = (int) (i * 100 / sz); 2904 if (percent > 0) 2905 theApplication->set_progress (percent, NULL); 2906 nextReport += deltaReport; 2907 } 2908 uint32_t thrid = dDscr->getIntValue (PROP_THRID, i); 2909 hrtime_t tstamp = dDscr->getLongValue (PROP_TSTAMP, i); 2910 uint64_t cprid = dDscr->getLongValue (PROP_CPRID, i); //omptrace 2911 mapPRid->put (thrid, tstamp, cprid); 2912 } 2913 theApplication->set_progress (0, NTXT ("")); 2914 } 2915 else 2916 { 2917 read_omp_preg (); 2918 read_omp_task (); 2919 } 2920 if (ompavail && coll_params.profile_mode) 2921 { 2922 dbeSession->status_ompavail = 1; 2923 register_metric (Metric::OMP_WORK); 2924 register_metric (Metric::OMP_WAIT); 2925 register_metric (Metric::OMP_OVHD); 2926 if (coll_params.lms_magic_id == LMS_MAGIC_ID_SOLARIS) 2927 register_metric (Metric::OMP_MASTER_THREAD); 2928 } 2929 } 2930} 2931 2932void 2933Experiment::read_ifreq_file () 2934{ 2935 char *fname = dbe_sprintf (NTXT ("%s/%s"), expt_name, SP_IFREQ_FILE); 2936 FILE *f = fopen (fname, NTXT ("r")); 2937 free (fname); 2938 if (f == NULL) 2939 { 2940 ifreqavail = false; 2941 return; 2942 } 2943 ifreqavail = true; 2944 ifreqq = new Emsgqueue (NTXT ("ifreqq")); 2945 2946 while (1) 2947 { 2948 Emsg *m; 2949 char str[MAXPATHLEN]; 2950 char *e = fgets (str, ((int) sizeof (str)) - 1, f); 2951 if (e == NULL) 2952 { 2953 // end the list from the experiment 2954 m = new Emsg (CMSG_COMMENT, 2955 GTXT ("============================================================")); 2956 ifreqq->append (m); 2957 break; 2958 } 2959 // get the string 2960 size_t i = strlen (str); 2961 if (i > 0 && str[i - 1] == '\n') 2962 // remove trailing nl 2963 str[i - 1] = 0; 2964 // and append it 2965 m = new Emsg (CMSG_COMMENT, str); 2966 ifreqq->append (m); 2967 } 2968 (void) fclose (f); 2969} 2970 2971Experiment * 2972Experiment::getBaseFounder () 2973{ 2974 if (baseFounder) 2975 return baseFounder; 2976 Experiment *founder = this; 2977 Experiment *parent = founder->founder_exp; 2978 while (parent) 2979 { 2980 founder = parent; 2981 parent = founder->founder_exp; 2982 } 2983 baseFounder = founder; 2984 return baseFounder; 2985} 2986 2987hrtime_t 2988Experiment::getRelativeStartTime () 2989{ 2990 if (exp_rel_start_time_set) 2991 return exp_rel_start_time; 2992 Experiment *founder = getBaseFounder (); 2993 hrtime_t child_start = this->getStartTime (); 2994 hrtime_t founder_start = founder->getStartTime (); 2995 exp_rel_start_time = child_start - founder_start; 2996 if (child_start == 0 && founder_start) 2997 exp_rel_start_time = 0; // when descendents have incomplete log.xml 2998 exp_rel_start_time_set = true; 2999 return exp_rel_start_time; 3000} 3001 3002DataDescriptor * 3003Experiment::get_raw_events (int data_id) 3004{ 3005 DataDescriptor *dDscr; 3006 switch (data_id) 3007 { 3008 case DATA_CLOCK: 3009 dDscr = get_profile_events (); 3010 break; 3011 case DATA_SYNCH: 3012 dDscr = get_sync_events (); 3013 break; 3014 case DATA_HWC: 3015 dDscr = get_hwc_events (); 3016 break; 3017 case DATA_HEAP: 3018 dDscr = get_heap_events (); 3019 break; 3020 case DATA_HEAPSZ: 3021 dDscr = get_heapsz_events (); 3022 break; 3023 case DATA_IOTRACE: 3024 dDscr = get_iotrace_events (); 3025 break; 3026 case DATA_RACE: 3027 dDscr = get_race_events (); 3028 break; 3029 case DATA_DLCK: 3030 dDscr = get_deadlock_events (); 3031 break; 3032 case DATA_SAMPLE: 3033 dDscr = get_sample_events (); 3034 break; 3035 case DATA_GCEVENT: 3036 dDscr = get_gc_events (); 3037 break; 3038 default: 3039 dDscr = NULL; 3040 break; 3041 } 3042 return dDscr; 3043} 3044 3045int 3046Experiment::base_data_id (int data_id) 3047{ 3048 switch (data_id) 3049 { 3050 case DATA_HEAPSZ: 3051 return DATA_HEAP; // DATA_HEAPSZ DataView is based on DATA_HEAP's DataView 3052 default: 3053 break; 3054 } 3055 return data_id; 3056} 3057 3058DataView * 3059Experiment::create_derived_data_view (int data_id, DataView *dview) 3060{ 3061 // dview contains filtered packets 3062 switch (data_id) 3063 { 3064 case DATA_HEAPSZ: 3065 return create_heapsz_data_view (dview); 3066 default: 3067 break; 3068 } 3069 return NULL; 3070} 3071 3072DataDescriptor * 3073Experiment::get_profile_events () 3074{ 3075 DataDescriptor *dDscr = getDataDescriptor (DATA_CLOCK); 3076 if (dDscr == NULL) 3077 return NULL; 3078 if (dDscr->getSize () == 0) 3079 { 3080 char *base_name = get_basename (expt_name); 3081 char *msg = dbe_sprintf (GTXT ("Loading Profile Data: %s"), base_name); 3082 read_data_file (SP_PROFILE_FILE, msg); 3083 free (msg); 3084 add_evt_time_to_profile_events (dDscr); 3085 resolve_frame_info (dDscr); 3086 } 3087 else if (!dDscr->isResolveFrInfoDone ()) 3088 resolve_frame_info (dDscr); 3089 return dDscr; 3090} 3091 3092void 3093Experiment::add_evt_time_to_profile_events (DataDescriptor *dDscr) 3094{ 3095 if (coll_params.lms_magic_id != LMS_MAGIC_ID_SOLARIS) 3096 return; 3097 3098 DataView *dview = dDscr->createView (); 3099 dview->sort (PROP_THRID, PROP_TSTAMP); 3100 3101 // add PROP_EVT_TIME 3102 PropDescr* tmp_propDscr = new PropDescr (PROP_EVT_TIME, "EVT_TIME"); 3103 tmp_propDscr->uname = dbe_strdup (GTXT ("Event duration")); 3104 tmp_propDscr->vtype = TYPE_INT64; 3105 dDscr->addProperty (tmp_propDscr); 3106 3107 long sz = dview->getSize (); 3108 long long ptimer_usec = get_params ()->ptimer_usec; 3109 for (long i = 0; i < sz; i++) 3110 { 3111 int next_sample; 3112 int jj; 3113 { 3114 hrtime_t this_tstamp = dview->getLongValue (PROP_TSTAMP, i); 3115 long this_thrid = dview->getLongValue (PROP_THRID, i); 3116 for (jj = i + 1; jj < sz; jj++) 3117 { 3118 hrtime_t tmp_tstamp = dview->getLongValue (PROP_TSTAMP, jj); 3119 if (tmp_tstamp != this_tstamp) 3120 break; 3121 long tmp_thrid = dview->getLongValue (PROP_THRID, jj); 3122 if (tmp_thrid != this_thrid) 3123 break; 3124 } 3125 next_sample = jj; 3126 } 3127 3128 long nticks = 0; 3129 for (jj = i; jj < next_sample; jj++) 3130 nticks += dview->getLongValue (PROP_NTICK, jj); 3131 if (nticks <= 1) 3132 continue; // no duration 3133 3134 nticks--; 3135 hrtime_t duration = ptimer_usec * 1000LL * nticks; // nanoseconds 3136 for (jj = i; jj < next_sample; jj++) 3137 dview->setValue (PROP_EVT_TIME, jj, duration); 3138 i = jj - 1; 3139 } 3140 delete dview; 3141} 3142 3143DataDescriptor * 3144Experiment::get_sync_events () 3145{ 3146 DataDescriptor *dDscr = getDataDescriptor (DATA_SYNCH); 3147 if (dDscr == NULL) 3148 return NULL; 3149 if (dDscr->getSize () > 0) 3150 return dDscr; 3151 3152 // fetch data 3153 { 3154 char *base_name = get_basename (expt_name); 3155 char *msg = dbe_sprintf (GTXT ("Loading Synctrace Data: %s"), base_name); 3156 read_data_file (SP_SYNCTRACE_FILE, msg); 3157 free (msg); 3158 resolve_frame_info (dDscr); 3159 } 3160 3161 // check for PROP_EVT_TIME 3162 PropDescr *tmp_propDscr = dDscr->getProp (PROP_EVT_TIME); 3163 if (tmp_propDscr) 3164 return dDscr; 3165 3166 // add PROP_EVT_TIME 3167 tmp_propDscr = new PropDescr (PROP_EVT_TIME, "EVT_TIME"); 3168 tmp_propDscr->uname = dbe_strdup (GTXT ("Event duration")); 3169 tmp_propDscr->vtype = TYPE_INT64; 3170 dDscr->addProperty (tmp_propDscr); 3171 3172 long sz = dDscr->getSize (); 3173 for (long i = 0; i < sz; i++) 3174 { 3175 uint64_t event_duration = dDscr->getLongValue (PROP_TSTAMP, i); 3176 event_duration -= dDscr->getLongValue (PROP_SRQST, i); 3177 dDscr->setValue (PROP_EVT_TIME, i, event_duration); 3178 } 3179 return dDscr; 3180} 3181 3182DataDescriptor * 3183Experiment::get_hwc_events () 3184{ 3185 DataDescriptor *dDscr = getDataDescriptor (DATA_HWC); 3186 if (dDscr == NULL) 3187 return NULL; 3188 if (dDscr->getSize () == 0) 3189 { 3190 char *base_name = get_basename (expt_name); 3191 char *msg = dbe_sprintf (GTXT ("Loading HW Profile Data: %s"), base_name); 3192 3193 // clear HWC event stats 3194 dsevents = 0; 3195 dsnoxhwcevents = 0; 3196 read_data_file (SP_HWCNTR_FILE, msg); 3197 free (msg); 3198 resolve_frame_info (dDscr); 3199 3200 // describe the HW counters in PropDescr 3201 PropDescr *prop = dDscr->getProp (PROP_HWCTAG); 3202 if (prop) 3203 { 3204 Collection_params *cparam = get_params (); 3205 if (cparam->hw_mode != 0) 3206 for (int aux = 0; aux < MAX_HWCOUNT; aux++) 3207 if (cparam->hw_aux_name[aux]) 3208 { 3209 const char* cmdname = cparam->hw_aux_name[aux]; 3210 const char* uname = cparam->hw_username[aux]; 3211 prop->addState (aux, cmdname, uname); 3212 } 3213 } 3214 else 3215 assert (0); 3216 3217 double dserrrate = 100.0 * ((double) dsnoxhwcevents) / ((double) dsevents); 3218 if ((dsevents > 0) && (dserrrate > 10.0)) 3219 { 3220 // warn the user that rate is high 3221 StringBuilder sb; 3222 if (dbeSession->check_ignore_no_xhwcprof ()) 3223 sb.sprintf ( 3224 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"), 3225 base_name, dserrrate, (long long) dsnoxhwcevents, 3226 (long long) dsevents); 3227 else 3228 sb.sprintf ( 3229 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"), 3230 base_name, dserrrate, (long long) dsnoxhwcevents, 3231 (long long) dsevents); 3232 errorq->append (new Emsg (CMSG_WARN, sb)); 3233 } 3234 3235 // see if we've scanned the data 3236 if (hwc_scanned == 0) 3237 { 3238 // no, scan the packets to see how many are bogus, or represent lost interrupts 3239 long hwc_cnt = 0; 3240 3241 // loop over the packets, counting the bad ones 3242 if (hwc_bogus != 0 || hwc_lost_int != 0) 3243 { 3244 // hwc counter data had bogus packets and/or packets reflecting lost interrupts 3245 double bogus_rate = 100. * (double) hwc_bogus / (double) hwc_cnt; 3246 if (bogus_rate > 5.) 3247 { 3248 StringBuilder sb; 3249 sb.sprintf ( 3250 GTXT ("WARNING: Too many invalid HW counter profile events (%ld/%ld = %3.2f%%) in experiment %d (`%s'); data may be unreliable"), 3251 (long) hwc_bogus, (long) hwc_cnt, bogus_rate, 3252 (int) userExpId, base_name); 3253 Emsg *m = new Emsg (CMSG_WARN, sb); 3254 warnq->append (m); 3255 } 3256 hwc_scanned = 1; 3257 } 3258 } 3259 } 3260 return dDscr; 3261} 3262 3263DataDescriptor * 3264Experiment::get_iotrace_events () 3265{ 3266 DataDescriptor *dDscr = getDataDescriptor (DATA_IOTRACE); 3267 if (dDscr == NULL) 3268 return NULL; 3269 3270 if (dDscr->getSize () > 0) 3271 return dDscr; 3272 3273 char *base_name = get_basename (expt_name); 3274 char *msg = dbe_sprintf (GTXT ("Loading IO Trace Data: %s"), base_name); 3275 read_data_file (SP_IOTRACE_FILE, msg); 3276 free (msg); 3277 3278 if (dDscr->getSize () == 0) 3279 return dDscr; 3280 resolve_frame_info (dDscr); 3281 3282 // check for PROP_EVT_TIME 3283 PropDescr *tmp_propDscr = dDscr->getProp (PROP_EVT_TIME); 3284 if (tmp_propDscr) 3285 return dDscr; 3286 3287 // add PROP_EVT_TIME 3288 tmp_propDscr = new PropDescr (PROP_EVT_TIME, "EVT_TIME"); 3289 tmp_propDscr->uname = dbe_strdup (GTXT ("Event duration")); 3290 tmp_propDscr->vtype = TYPE_INT64; 3291 dDscr->addProperty (tmp_propDscr); 3292 3293 // add PROP_IOVFD 3294 tmp_propDscr = new PropDescr (PROP_IOVFD, "IOVFD"); 3295 tmp_propDscr->uname = dbe_strdup (GTXT ("Virtual File Descriptor")); 3296 tmp_propDscr->vtype = TYPE_INT64; 3297 dDscr->addProperty (tmp_propDscr); 3298 3299 delete fDataMap; 3300 fDataMap = new DefaultMap<int64_t, FileData*>; 3301 3302 delete vFdMap; 3303 vFdMap = new DefaultMap<int, int64_t>; 3304 3305 static int64_t virtualFd = 0; 3306 3307 FileData *fData; 3308 virtualFd += 10; 3309 fData = fDataMap->get (VIRTUAL_FD_STDIN); 3310 if (fData == NULL) 3311 { 3312 fData = new FileData (STDIN_FILENAME); 3313 fData->setVirtualFd (VIRTUAL_FD_STDIN); 3314 fData->id = VIRTUAL_FD_STDIN; 3315 fData->setFileDes (STDIN_FD); 3316 fDataMap->put (VIRTUAL_FD_STDIN, fData); 3317 vFdMap->put (STDIN_FD, VIRTUAL_FD_STDIN); 3318 } 3319 3320 fData = fDataMap->get (VIRTUAL_FD_STDOUT); 3321 if (fData == NULL) 3322 { 3323 fData = new FileData (STDOUT_FILENAME); 3324 fData->setVirtualFd (VIRTUAL_FD_STDOUT); 3325 fData->id = VIRTUAL_FD_STDOUT; 3326 fData->setFileDes (STDOUT_FD); 3327 fDataMap->put (VIRTUAL_FD_STDOUT, fData); 3328 vFdMap->put (STDOUT_FD, VIRTUAL_FD_STDOUT); 3329 } 3330 3331 fData = fDataMap->get (VIRTUAL_FD_STDERR); 3332 if (fData == NULL) 3333 { 3334 fData = new FileData (STDERR_FILENAME); 3335 fData->setVirtualFd (VIRTUAL_FD_STDERR); 3336 fData->id = VIRTUAL_FD_STDERR; 3337 fData->setFileDes (STDERR_FD); 3338 fDataMap->put (VIRTUAL_FD_STDERR, fData); 3339 vFdMap->put (STDERR_FD, VIRTUAL_FD_STDERR); 3340 } 3341 3342 fData = fDataMap->get (VIRTUAL_FD_OTHERIO); 3343 if (fData == NULL) 3344 { 3345 fData = new FileData (OTHERIO_FILENAME); 3346 fData->setVirtualFd (VIRTUAL_FD_OTHERIO); 3347 fData->id = VIRTUAL_FD_OTHERIO; 3348 fData->setFileDes (OTHERIO_FD); 3349 fDataMap->put (VIRTUAL_FD_OTHERIO, fData); 3350 } 3351 3352 DataView *dview = dDscr->createView (); 3353 dview->sort (PROP_TSTAMP); 3354 long sz = dview->getSize (); 3355 for (long i = 0; i < sz; i++) 3356 { 3357 hrtime_t event_duration = dview->getLongValue (PROP_TSTAMP, i); 3358 hrtime_t event_start = dview->getLongValue (PROP_IORQST, i); 3359 if (event_start > 0) 3360 event_duration -= event_start; 3361 else 3362 event_duration = 0; 3363 dview->setValue (PROP_EVT_TIME, i, event_duration); 3364 3365 int32_t fd = -1; 3366 int64_t vFd = VIRTUAL_FD_NONE; 3367 char *fName = NULL; 3368 int32_t origFd = -1; 3369 StringBuilder *sb = NULL; 3370 FileData *fDataOrig = NULL; 3371 FileSystem_type fsType; 3372 3373 IOTrace_type ioType = (IOTrace_type) dview->getIntValue (PROP_IOTYPE, i); 3374 switch (ioType) 3375 { 3376 case READ_TRACE: 3377 case WRITE_TRACE: 3378 case READ_TRACE_ERROR: 3379 case WRITE_TRACE_ERROR: 3380 fd = dview->getIntValue (PROP_IOFD, i); 3381 vFd = vFdMap->get (fd); 3382 if (vFd == 0 || vFd == VIRTUAL_FD_NONE 3383 || (fData = fDataMap->get (vFd)) == NULL) 3384 { 3385 fData = new FileData (UNKNOWNFD_FILENAME); 3386 fData->setVirtualFd (virtualFd); 3387 fData->setFsType ("N/A"); 3388 fData->setFileDes (fd); 3389 fDataMap->put (virtualFd, fData); 3390 vFdMap->put (fd, virtualFd); 3391 vFd = virtualFd; 3392 virtualFd++; 3393 } 3394 dview->setValue (PROP_IOVFD, i, vFd); 3395 break; 3396 case OPEN_TRACE: 3397 fName = NULL; 3398 sb = (StringBuilder*) dview->getObjValue (PROP_IOFNAME, i); 3399 if (sb != NULL && sb->length () > 0) 3400 fName = sb->toString (); 3401 fd = dview->getIntValue (PROP_IOFD, i); 3402 origFd = dview->getIntValue (PROP_IOOFD, i); 3403 fsType = (FileSystem_type) dview->getIntValue (PROP_IOFSTYPE, i); 3404 3405 if (fName != NULL) 3406 { 3407 fData = new FileData (fName); 3408 fDataMap->put (virtualFd, fData); 3409 vFdMap->put (fd, virtualFd); 3410 fData->setFileDes (fd); 3411 fData->setFsType (fsType); 3412 fData->setVirtualFd (virtualFd); 3413 vFd = virtualFd; 3414 virtualFd++; 3415 } 3416 else if (origFd > 0) 3417 { 3418 vFd = vFdMap->get (origFd); 3419 if (vFd == 0 || vFd == VIRTUAL_FD_NONE) 3420 { 3421 Dprintf (DEBUG_IO, 3422 "*** Error I/O tracing: (open) cannot get the virtual file descriptor, fd=%d origFd=%d\n", 3423 fd, origFd); 3424 continue; 3425 } 3426 else if ((fDataOrig = fDataMap->get (vFd)) == NULL) 3427 { 3428 Dprintf (DEBUG_IO, 3429 "*** Error IO tracing: (open) cannot get original FileData object, fd=%d origFd=%d\n", 3430 fd, origFd); 3431 continue; 3432 } 3433 else 3434 { 3435 fName = fDataOrig->getFileName (); 3436 fData = new FileData (fName); 3437 fData->setFileDes (fd); 3438 fData->setFsType (fDataOrig->getFsType ()); 3439 fData->setVirtualFd (virtualFd); 3440 fDataMap->put (virtualFd, fData); 3441 vFdMap->put (fd, virtualFd); 3442 vFd = virtualFd; 3443 virtualFd++; 3444 } 3445 } 3446 else if (fd >= 0) 3447 { 3448 vFd = vFdMap->get (fd); 3449 if (vFd == 0 || vFd == VIRTUAL_FD_NONE 3450 || (fData = fDataMap->get (vFd)) == NULL) 3451 { 3452 fData = new FileData (UNKNOWNFD_FILENAME); 3453 fData->setVirtualFd (virtualFd); 3454 fData->setFsType ("N/A"); 3455 fData->setFileDes (fd); 3456 fDataMap->put (virtualFd, fData); 3457 vFdMap->put (fd, virtualFd); 3458 vFd = virtualFd; 3459 virtualFd++; 3460 } 3461 } 3462 else 3463 { 3464 Dprintf (DEBUG_IO, 3465 NTXT ("*** Error IO tracing: (open) unknown open IO type, fd=%d origFd=%d\n"), fd, origFd); 3466 continue; 3467 } 3468 3469 dview->setValue (PROP_IOVFD, i, vFd); 3470 break; 3471 3472 case OPEN_TRACE_ERROR: 3473 fName = NULL; 3474 3475 sb = (StringBuilder*) dview->getObjValue (PROP_IOFNAME, i); 3476 if (sb != NULL && sb->length () > 0) 3477 fName = sb->toString (); 3478 fd = dview->getIntValue (PROP_IOFD, i); 3479 origFd = dview->getIntValue (PROP_IOOFD, i); 3480 fsType = (FileSystem_type) dview->getIntValue (PROP_IOFSTYPE, i); 3481 3482 if (fName != NULL) 3483 { 3484 fData = new FileData (fName); 3485 fDataMap->put (virtualFd, fData); 3486 fData->setFileDes (fd); 3487 fData->setFsType (fsType); 3488 fData->setVirtualFd (virtualFd); 3489 vFd = virtualFd; 3490 virtualFd++; 3491 } 3492 else if (origFd > 0) 3493 { 3494 vFd = vFdMap->get (origFd); 3495 if (vFd == 0 || vFd == VIRTUAL_FD_NONE) 3496 { 3497 Dprintf (DEBUG_IO, 3498 "*** Error IO tracing: (open error) cannot get the virtual file descriptor, fd=%d origFd=%d\n", 3499 fd, origFd); 3500 continue; 3501 } 3502 else if ((fDataOrig = fDataMap->get (vFd)) == NULL) 3503 { 3504 Dprintf (DEBUG_IO, 3505 "*** Error IO tracing: (open error) cannot get original FileData object, fd=%d origFd=%d\n", 3506 fd, origFd); 3507 continue; 3508 } 3509 else 3510 { 3511 fName = fDataOrig->getFileName (); 3512 fData = new FileData (fName); 3513 fData->setFileDes (fd); 3514 fData->setFsType (fDataOrig->getFsType ()); 3515 fData->setVirtualFd (virtualFd); 3516 fDataMap->put (virtualFd, fData); 3517 vFd = virtualFd; 3518 virtualFd++; 3519 } 3520 } 3521 3522 dview->setValue (PROP_IOVFD, i, vFd); 3523 break; 3524 3525 case CLOSE_TRACE: 3526 case CLOSE_TRACE_ERROR: 3527 fd = dview->getIntValue (PROP_IOFD, i); 3528 vFd = vFdMap->get (fd); 3529 if (vFd == 0 || vFd == VIRTUAL_FD_NONE) 3530 { 3531 Dprintf (DEBUG_IO, 3532 "*** Error IO tracing: (close) cannot get the virtual file descriptor, fd=%d\n", 3533 fd); 3534 continue; 3535 } 3536 fData = fDataMap->get (vFd); 3537 if (fData == NULL) 3538 { 3539 Dprintf (DEBUG_IO, 3540 "*** Error IO tracing: (close) cannot get the FileData object, fd=%d\n", 3541 fd); 3542 continue; 3543 } 3544 3545 vFdMap->put (fd, VIRTUAL_FD_NONE); 3546 dview->setValue (PROP_IOVFD, i, vFd); 3547 break; 3548 3549 case OTHERIO_TRACE: 3550 case OTHERIO_TRACE_ERROR: 3551 vFd = VIRTUAL_FD_OTHERIO; 3552 fData = fDataMap->get (vFd); 3553 if (fData == NULL) 3554 { 3555 Dprintf (DEBUG_IO, 3556 "*** Error IO tracing: (other IO) cannot get the FileData object\n"); 3557 continue; 3558 } 3559 3560 dview->setValue (PROP_IOVFD, i, vFd); 3561 break; 3562 case IOTRACETYPE_LAST: 3563 break; 3564 } 3565 } 3566 3567 delete dview; 3568 3569 return dDscr; 3570} 3571 3572DataDescriptor * 3573Experiment::get_heap_events () 3574{ 3575 DataDescriptor *dDscr = getDataDescriptor (DATA_HEAP); 3576 if (dDscr == NULL) 3577 return NULL; 3578 if (dDscr->getSize () > 0) 3579 return dDscr; 3580 3581 char *base_name = get_basename (expt_name); 3582 char *msg = dbe_sprintf (GTXT ("Loading Heap Trace Data: %s"), base_name); 3583 read_data_file (SP_HEAPTRACE_FILE, msg); 3584 free (msg); 3585 3586 if (dDscr->getSize () == 0) 3587 return dDscr; 3588 resolve_frame_info (dDscr); 3589 3590 // Match FREE to MALLOC 3591 PropDescr *prop = new PropDescr (PROP_HLEAKED, NTXT ("HLEAKED")); 3592 prop->uname = dbe_strdup (GTXT ("Bytes Leaked")); 3593 prop->vtype = TYPE_UINT64; 3594 dDscr->addProperty (prop); 3595 3596 prop = new PropDescr (PROP_HMEM_USAGE, NTXT ("HMEM_USAGE")); 3597 prop->uname = dbe_strdup (GTXT ("Heap Memory Usage")); 3598 prop->vtype = TYPE_UINT64; 3599 dDscr->addProperty (prop); 3600 3601 prop = new PropDescr (PROP_HFREED, NTXT ("HFREED")); 3602 prop->uname = dbe_strdup (GTXT ("Bytes Freed")); 3603 prop->vtype = TYPE_UINT64; 3604 dDscr->addProperty (prop); 3605 3606 prop = new PropDescr (PROP_HCUR_ALLOCS, NTXT ("HCUR_ALLOCS")); 3607 prop->uname = dbe_strdup (GTXT ("Net Bytes Allocated")); 3608 prop->vtype = TYPE_INT64; 3609 dDscr->addProperty (prop); 3610 3611 prop = new PropDescr (PROP_HCUR_LEAKS, NTXT ("HCUR_LEAKS")); 3612 prop->uname = dbe_strdup (GTXT ("Net Bytes Leaked")); 3613 prop->vtype = TYPE_UINT64; 3614 dDscr->addProperty (prop); 3615 3616 prop = new PropDescr (PROP_HCUR_NET_ALLOC, NTXT ("HCUR_NET_ALLOC")); 3617 prop->vtype = TYPE_INT64; 3618 prop->flags = DDFLAG_NOSHOW; 3619 dDscr->addProperty (prop); 3620 3621 prop = new PropDescr (PROP_DDSCR_LNK, NTXT ("DDSCR_LNK")); 3622 prop->vtype = TYPE_UINT64; 3623 prop->flags = DDFLAG_NOSHOW; 3624 dDscr->addProperty (prop); 3625 3626 prop = new PropDescr (PROP_VOIDP_OBJ, NTXT ("VOIDP_OBJ")); 3627 prop->vtype = TYPE_OBJ; 3628 prop->flags = DDFLAG_NOSHOW; 3629 dDscr->addProperty (prop); 3630 3631 prop = new PropDescr (PROP_TSTAMP2, NTXT ("TSTAMP2")); 3632 prop->uname = dbe_strdup (GTXT ("End Timestamp (nanoseconds)")); 3633 prop->vtype = TYPE_UINT64; 3634 prop->flags = DDFLAG_NOSHOW; 3635 dDscr->addProperty (prop); 3636 3637 DataView *dview = dDscr->createView (); 3638 dview->sort (PROP_TSTAMP); 3639 3640 // Keep track of memory usage 3641 Size memoryUsage = 0; 3642 3643 HeapMap *heapmap = new HeapMap (); 3644 long sz = dview->getSize (); 3645 for (long i = 0; i < sz; i++) 3646 { 3647 3648 Heap_type mtype = (Heap_type) dview->getIntValue (PROP_HTYPE, i); 3649 Vaddr vaddr = dview->getULongValue (PROP_HVADDR, i); 3650 Vaddr ovaddr = dview->getULongValue (PROP_HOVADDR, i); 3651 Size hsize = dview->getULongValue (PROP_HSIZE, i); 3652 hrtime_t tstamp = dview->getLongValue (PROP_TSTAMP, i); 3653 3654 switch (mtype) 3655 { 3656 case MALLOC_TRACE: 3657 dview->setValue (PROP_TSTAMP2, i, (uint64_t) MAX_TIME); 3658 if (vaddr) 3659 { 3660 dview->setValue (PROP_HLEAKED, i, hsize); 3661 heapmap->allocate (vaddr, i + 1); 3662 3663 // Increase heap size 3664 memoryUsage += hsize; 3665 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage); 3666 } 3667 break; 3668 3669 case FREE_TRACE: 3670 if (vaddr) 3671 { 3672 long idx = heapmap->deallocate (vaddr) - 1; 3673 if (idx >= 0) 3674 { 3675 // Decrease heap size 3676 Size leaked = dview->getLongValue (PROP_HLEAKED, idx); 3677 memoryUsage -= leaked; 3678 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage); 3679 3680 Size alloc = dview->getLongValue (PROP_HSIZE, idx); 3681 // update allocation 3682 dview->setValue (PROP_HLEAKED, idx, (uint64_t) 0); 3683 dview->setValue (PROP_TSTAMP2, idx, tstamp); 3684 dview->setValue (PROP_DDSCR_LNK, idx, dview->getIdByIdx (i) + 1); 3685 // update this event 3686 dview->setValue (PROP_HFREED, i, alloc); 3687 } 3688 } 3689 break; 3690 3691 case REALLOC_TRACE: 3692 dview->setValue (PROP_TSTAMP2, i, (uint64_t) MAX_TIME); 3693 if (ovaddr) 3694 { 3695 long idx = heapmap->deallocate (ovaddr) - 1; 3696 if (idx >= 0) 3697 { 3698 // Decrease heap size 3699 Size leaked = dview->getLongValue (PROP_HLEAKED, idx); 3700 memoryUsage -= leaked; 3701 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage); 3702 3703 Size alloc = dview->getLongValue (PROP_HSIZE, idx); 3704 // update allocation 3705 dview->setValue (PROP_HLEAKED, idx, (uint64_t) 0); 3706 dview->setValue (PROP_TSTAMP2, idx, tstamp); 3707 dview->setValue (PROP_DDSCR_LNK, idx, dview->getIdByIdx (i) + 1); 3708 // update this event 3709 dview->setValue (PROP_HFREED, i, alloc); 3710 } 3711 } 3712 if (vaddr) 3713 { 3714 dview->setValue (PROP_HLEAKED, i, hsize); 3715 heapmap->allocate (vaddr, i + 1); 3716 3717 // Increase heap size 3718 memoryUsage += hsize; 3719 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage); 3720 } 3721 break; 3722 case MMAP_TRACE: 3723 case MUNMAP_TRACE: 3724 // Adjust the size to be multiple of page_size 3725 //hsize = (( hsize - 1 ) / page_size + 1 ) * page_size; 3726 if (vaddr) 3727 { 3728 UnmapChunk *list; 3729 if (mtype == MMAP_TRACE) 3730 { 3731 dview->setValue (PROP_TSTAMP2, i, (uint64_t) MAX_TIME); 3732 dview->setValue (PROP_HLEAKED, i, hsize); 3733 list = heapmap->mmap (vaddr, hsize, i); 3734 3735 // Increase heap size 3736 memoryUsage += hsize; 3737 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage); 3738 } 3739 else 3740 { // MUNMAP_TRACE 3741 list = heapmap->munmap (vaddr, hsize); 3742 3743 // Set allocation size to zero 3744 // Note: We're currently reusing PROP_HSIZE to mean allocation size 3745 // If we ever need to save the original HSIZE, we'll need to 3746 // create a new PROP_* to represent event allocation size 3747 // 3748 // For now, tuck the original size away as HOVADDR 3749 dview->setValue (PROP_HOVADDR, i, (uint64_t) hsize); 3750 dview->setValue (PROP_HSIZE, i, (uint64_t) 0); 3751 } 3752 Size total_freed = 0; 3753 while (list) 3754 { 3755 long idx = list->val; 3756 total_freed += list->size; 3757 Size leaked = dview->getLongValue (PROP_HLEAKED, idx); 3758 3759 // Decrease heap size 3760 memoryUsage -= list->size; 3761 dview->setValue (PROP_HMEM_USAGE, i, memoryUsage); 3762 3763 Size leak_update = leaked - list->size; 3764 // update allocation 3765 dview->setValue (PROP_HLEAKED, idx, leak_update); 3766 // update allocation's list of frees 3767 { 3768 UnmapChunk *copy = new UnmapChunk; 3769 heapUnmapEvents->append (copy); 3770 copy->val = dview->getIdByIdx (i); 3771 copy->size = list->size; 3772 copy->next = (UnmapChunk *) dview->getObjValue (PROP_VOIDP_OBJ, idx); 3773 dview->setObjValue (PROP_VOIDP_OBJ, idx, copy); 3774 } 3775 if (leak_update <= 0) 3776 if (leak_update == 0) 3777 dview->setValue (PROP_TSTAMP2, idx, tstamp); 3778 UnmapChunk *t = list; 3779 list = list->next; 3780 delete t; 3781 } 3782 // update this event 3783 if (total_freed) 3784 // only need to write value if it is non-zero 3785 dview->setValue (PROP_HFREED, i, total_freed); 3786 } 3787 break; 3788 // ignoring HEAPTYPE_LAST, which will never be recorded 3789 case HEAPTYPE_LAST: 3790 break; 3791 } 3792 } 3793 delete heapmap; 3794 delete dview; 3795 3796 return dDscr; 3797} 3798 3799DataDescriptor * 3800Experiment::get_heapsz_events () 3801{ 3802 DataDescriptor *dDscr = getDataDescriptor (DATA_HEAPSZ); 3803 if (dDscr) 3804 return dDscr; 3805 dDscr = get_heap_events (); // derived from DATA_HEAP 3806 if (dDscr == NULL) 3807 return NULL; 3808 dDscr = newDataDescriptor (DATA_HEAPSZ, 0, dDscr); 3809 return dDscr; 3810} 3811 3812static void 3813update_heapsz_packet (std::set<long> &pkt_id_set, DataView *dview, 3814 long alloc_pkt_id, int64_t net_alloc, uint64_t leaks) 3815{ 3816 // pkt_id_set: set is updated to include packet 3817 // alloc_pkt_id: data descriptor id (NOT dview idx) 3818 // net_alloc: adjustment to net allocation for this packet (note: signed value) 3819 // leaks: leak bytes to attribute to alloc_pkt_id 3820 std::pair < std::set<long>::iterator, bool> ret; 3821 ret = pkt_id_set.insert (alloc_pkt_id); // add to set 3822 bool new_to_set = ret.second; // was not in set 3823 if (!new_to_set) 3824 { 3825 // Has been seen before, update values 3826 net_alloc += dview->getDataDescriptorValue (PROP_HCUR_NET_ALLOC, alloc_pkt_id); 3827 if (leaks) 3828 { 3829 uint64_t old = dview->getDataDescriptorValue (PROP_HCUR_LEAKS, alloc_pkt_id); 3830 if (old != 0) 3831 leaks = old; 3832 } 3833 } 3834 dview->setDataDescriptorValue (PROP_HCUR_NET_ALLOC, alloc_pkt_id, net_alloc); 3835 dview->setDataDescriptorValue (PROP_HCUR_LEAKS, alloc_pkt_id, leaks); 3836} 3837 3838DataView * 3839Experiment::create_heapsz_data_view (DataView *heap_dview) 3840{ 3841 // heap_dview has DATA_HEAP _filtered_ packets. 3842 // This creates, populates, and returns DATA_HEAPSZ DataView 3843 DataDescriptor *dDscr = get_heapsz_events (); 3844 if (dDscr == NULL) 3845 return NULL; 3846 std::set<long> pkt_id_set; 3847 DataView *dview = heap_dview; 3848 long sz = dview->getSize (); 3849 for (long i = 0; i < sz; i++) 3850 { 3851 int64_t hsize = (int64_t) dview->getULongValue (PROP_HSIZE, i); 3852 uint64_t leaks = dview->getULongValue (PROP_HLEAKED, i); 3853 long alloc_pkt_id = dview->getIdByIdx (i); 3854 update_heapsz_packet (pkt_id_set, dview, alloc_pkt_id, hsize, leaks); 3855 3856 // linked free 3857 UnmapChunk *mmap_frees = (UnmapChunk *) dview->getObjValue (PROP_VOIDP_OBJ, i); // mmap metadata 3858 if (mmap_frees) 3859 { 3860 // mmap: all frees associated with this packet 3861 while (mmap_frees) 3862 { 3863 long free_pkt_id = mmap_frees->val; 3864 int64_t free_sz = mmap_frees->size; 3865 update_heapsz_packet (pkt_id_set, dview, free_pkt_id, -free_sz, 0); 3866 mmap_frees = mmap_frees->next; 3867 } 3868 } 3869 else 3870 { 3871 // malloc: check for associated free 3872 long free_pkt_id = dview->getLongValue (PROP_DDSCR_LNK, i) - 1; 3873 if (free_pkt_id >= 0) 3874 update_heapsz_packet (pkt_id_set, dview, free_pkt_id, -hsize, 0); 3875 } 3876 } 3877 3878 // create a new DataView based on the filtered-in and associated free events 3879 std::set<long>::iterator it; 3880 DataView *heapsz_dview = dDscr->createExtManagedView (); 3881 for (it = pkt_id_set.begin (); it != pkt_id_set.end (); ++it) 3882 { 3883 long ddscr_pkt_id = *it; 3884 heapsz_dview->appendDataDescriptorId (ddscr_pkt_id); 3885 } 3886 compute_heapsz_data_view (heapsz_dview); 3887 return heapsz_dview; 3888} 3889 3890void 3891Experiment::compute_heapsz_data_view (DataView *heapsz_dview) 3892{ 3893 DataView *dview = heapsz_dview; 3894 3895 // Keep track of memory usage 3896 int64_t currentAllocs = 0; 3897 Size currentLeaks = 0; 3898 dview->sort (PROP_TSTAMP); 3899 long sz = dview->getSize (); 3900 for (long i = 0; i < sz; i++) 3901 { 3902 int64_t net_alloc = dview->getLongValue (PROP_HCUR_NET_ALLOC, i); 3903 currentAllocs += net_alloc; 3904 dview->setValue (PROP_HCUR_ALLOCS, i, currentAllocs); 3905 3906 Size leaks = dview->getULongValue (PROP_HCUR_LEAKS, i); 3907 currentLeaks += leaks; 3908 dview->setValue (PROP_HCUR_LEAKS, i, currentLeaks); 3909 } 3910} 3911 3912void 3913Experiment::DBG_memuse (Sample * s) 3914{ 3915 DataDescriptor *dDscr = getDataDescriptor (DATA_HEAP); 3916 if (dDscr == NULL || dDscr->getSize () == 0) 3917 return; 3918 3919 DataView *dview = dDscr->createView (); 3920 dview->sort (PROP_TSTAMP); 3921 hrtime_t ts1 = s->get_start_time (); 3922 hrtime_t ts2 = s->get_end_time (); 3923 3924 HeapMap *heapmap = new HeapMap (); 3925 long sz = dview->getSize (); 3926 Size maxSize = 0; 3927 Size curSize = 0; 3928 hrtime_t maxTime = 0; 3929 for (long i = 0; i < sz; i++) 3930 { 3931 hrtime_t tstamp = dview->getLongValue (PROP_TSTAMP, i); 3932 if (tstamp < ts1) 3933 continue; 3934 if (tstamp >= ts2) 3935 break; 3936 3937 Heap_type mtype = (Heap_type) dview->getIntValue (PROP_HTYPE, i); 3938 Vaddr vaddr = dview->getULongValue (PROP_HVADDR, i); 3939 Vaddr ovaddr = dview->getULongValue (PROP_HOVADDR, i); 3940 switch (mtype) 3941 { 3942 case REALLOC_TRACE: 3943 break; 3944 case MALLOC_TRACE: 3945 ovaddr = 0; 3946 break; 3947 case FREE_TRACE: 3948 ovaddr = vaddr; 3949 vaddr = 0; 3950 break; 3951 default: 3952 vaddr = 0; 3953 ovaddr = 0; 3954 break; 3955 } 3956 if (ovaddr) 3957 { 3958 long idx = heapmap->deallocate (ovaddr) - 1; 3959 if (idx >= 0) 3960 curSize -= dview->getULongValue (PROP_HSIZE, idx); 3961 } 3962 if (vaddr) 3963 { 3964 heapmap->allocate (vaddr, i + 1); 3965 curSize += dview->getULongValue (PROP_HSIZE, i); 3966 if (curSize > maxSize) 3967 { 3968 maxSize = curSize; 3969 maxTime = tstamp; 3970 } 3971 } 3972 } 3973 printf ("SAMPLE=%s (id=%d) MEMUSE=%lld TSTAMP=%lld\n", s->get_start_label (), 3974 s->get_number (), maxSize, maxTime - getStartTime ()); 3975 delete dview; 3976 delete heapmap; 3977} 3978 3979void 3980Experiment::DBG_memuse (const char *sname) 3981{ 3982 for (int i = 0; i < samples->size (); ++i) 3983 { 3984 Sample *sample = samples->fetch (i); 3985 if (streq (sname, sample->get_start_label ())) 3986 { 3987 DBG_memuse (sample); 3988 break; 3989 } 3990 } 3991} 3992 3993DataDescriptor * 3994Experiment::get_race_events () 3995{ 3996 DataDescriptor *dDscr = getDataDescriptor (DATA_RACE); 3997 if (dDscr == NULL) 3998 return NULL; 3999 if (dDscr->getSize () == 0) 4000 { 4001 char *base_name = get_basename (expt_name); 4002 char *msg = dbe_sprintf (GTXT ("Loading Race Data: %s"), base_name); 4003 read_data_file (SP_RACETRACE_FILE, msg); 4004 free (msg); 4005 resolve_frame_info (dDscr); 4006 } 4007 return dDscr; 4008} 4009 4010DataDescriptor * 4011Experiment::get_deadlock_events () 4012{ 4013 DataDescriptor *dDscr = getDataDescriptor (DATA_DLCK); 4014 if (dDscr == NULL) 4015 return NULL; 4016 if (dDscr->getSize () == 0) 4017 { 4018 char *base_name = get_basename (expt_name); 4019 char *msg = dbe_sprintf (GTXT ("Loading Deadlocks Data: %s"), base_name); 4020 read_data_file (SP_DEADLOCK_FILE, msg); 4021 free (msg); 4022 resolve_frame_info (dDscr); 4023 } 4024 return dDscr; 4025} 4026 4027DataDescriptor * 4028Experiment::get_sample_events () 4029{ 4030 DataDescriptor *dDscr = getDataDescriptor (DATA_SAMPLE); 4031 if (dDscr == NULL) 4032 return NULL; 4033 if (dDscr->getSize () > 0) 4034 return dDscr; 4035 4036 // read_overview_file(); //YXXX do this here at some point instead of: 4037 PropDescr *tmp_propDscr; 4038 tmp_propDscr = new PropDescr (PROP_SMPLOBJ, NTXT ("SMPLOBJ")); 4039 tmp_propDscr->uname = NULL; 4040 tmp_propDscr->vtype = TYPE_OBJ; 4041 dDscr->addProperty (tmp_propDscr); 4042 4043 tmp_propDscr = new PropDescr (PROP_TSTAMP, NTXT ("TSTAMP")); 4044 tmp_propDscr->uname = dbe_strdup ("High resolution timestamp"); 4045 tmp_propDscr->vtype = TYPE_UINT64; 4046 dDscr->addProperty (tmp_propDscr); 4047 4048 tmp_propDscr = new PropDescr (PROP_SAMPLE, NTXT ("SAMPLE")); 4049 tmp_propDscr->uname = dbe_strdup ("Sample number"); 4050 tmp_propDscr->vtype = TYPE_UINT64; 4051 dDscr->addProperty (tmp_propDscr); 4052 4053 tmp_propDscr = new PropDescr (PROP_EVT_TIME, NTXT ("EVT_TIME")); 4054 tmp_propDscr->uname = dbe_strdup ("Event duration"); 4055 tmp_propDscr->vtype = TYPE_UINT64; 4056 dDscr->addProperty (tmp_propDscr); 4057 4058 long ssize = samples->size (); 4059 for (long ii = 0; ii < ssize; ii++) 4060 { 4061 Sample * sample = samples->fetch (ii); 4062 long recn = dDscr->addRecord (); 4063 hrtime_t sduration = sample->get_end_time () - sample->get_start_time (); 4064 dDscr->setObjValue (PROP_SMPLOBJ, recn, sample); 4065 dDscr->setValue (PROP_SAMPLE, recn, sample->get_number ()); 4066 dDscr->setValue (PROP_TSTAMP, recn, sample->get_end_time ()); 4067 dDscr->setValue (PROP_EVT_TIME, recn, sduration); 4068 } 4069 return dDscr; 4070} 4071 4072DataDescriptor * 4073Experiment::get_gc_events () 4074{ 4075 DataDescriptor *dDscr = getDataDescriptor (DATA_GCEVENT); 4076 if (dDscr == NULL) 4077 return NULL; 4078 if (dDscr->getSize () > 0) 4079 return dDscr; 4080 4081 // read_overview_file(); //YXXX do this here at some point instead of: 4082 PropDescr *tmp_propDscr; 4083 tmp_propDscr = new PropDescr (PROP_GCEVENTOBJ, NTXT ("GCEVENTOBJ")); 4084 tmp_propDscr->uname = NULL; 4085 tmp_propDscr->vtype = TYPE_OBJ; 4086 dDscr->addProperty (tmp_propDscr); 4087 4088 tmp_propDscr = new PropDescr (PROP_TSTAMP, NTXT ("TSTAMP")); 4089 tmp_propDscr->uname = dbe_strdup ("High resolution timestamp"); 4090 tmp_propDscr->vtype = TYPE_UINT64; 4091 dDscr->addProperty (tmp_propDscr); 4092 4093 tmp_propDscr = new PropDescr (PROP_GCEVENT, NTXT ("GCEVENT")); 4094 tmp_propDscr->uname = dbe_strdup ("GCEvent number"); 4095 tmp_propDscr->vtype = TYPE_UINT64; 4096 dDscr->addProperty (tmp_propDscr); 4097 4098 tmp_propDscr = new PropDescr (PROP_EVT_TIME, NTXT ("EVT_TIME")); 4099 tmp_propDscr->uname = dbe_strdup ("Event duration"); 4100 tmp_propDscr->vtype = TYPE_UINT64; 4101 dDscr->addProperty (tmp_propDscr); 4102 4103 long ssize = gcevents->size (); 4104 for (long ii = 0; ii < ssize; ii++) 4105 { 4106 GCEvent * gcevent = gcevents->fetch (ii); 4107 long recn = dDscr->addRecord (); 4108 hrtime_t sduration = gcevent->end - gcevent->start; 4109 dDscr->setObjValue (PROP_GCEVENTOBJ, recn, gcevent); 4110 dDscr->setValue (PROP_GCEVENT, recn, gcevent->id); 4111 dDscr->setValue (PROP_TSTAMP, recn, gcevent->end); 4112 dDscr->setValue (PROP_EVT_TIME, recn, sduration); 4113 } 4114 return dDscr; 4115} 4116 4117void 4118Experiment::update_last_event (hrtime_t ts/*wall_ts*/) 4119{ 4120 if (last_event == ZERO_TIME) 4121 { 4122 // not yet initialized 4123 last_event = ts; 4124 } 4125 if (last_event - exp_start_time < ts - exp_start_time) 4126 // compare deltas to avoid hrtime_t wrap 4127 last_event = ts; 4128} 4129 4130void 4131Experiment::write_header () 4132{ 4133 StringBuilder sb; 4134 4135 // write commentary to the experiment, describing the parameters 4136 if (dbeSession->ipc_mode || dbeSession->rdt_mode) 4137 { 4138 // In GUI: print start time at the beginning 4139 time_t t = (time_t) start_sec; 4140 char *start_time = ctime (&t); 4141 if (start_time != NULL) 4142 { 4143 sb.setLength (0); 4144 sb.sprintf (GTXT ("Experiment started %s"), start_time); 4145 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4146 } 4147 } 4148 // write message with target arglist 4149 if (uarglist != NULL) 4150 { 4151 sb.setLength (0); 4152 sb.sprintf (GTXT ("\nTarget command (%s): '%s'"), 4153 (wsize == W32 ? "32-bit" : "64-bit"), uarglist); 4154 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4155 } 4156 4157 sb.setLength (0); 4158 sb.sprintf (GTXT ("Process pid %d, ppid %d, pgrp %d, sid %d"), 4159 pid, ppid, pgrp, sid); 4160 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4161 4162 // add comment for user name, if set 4163 if (username != NULL) 4164 { 4165 sb.setLength (0); 4166 sb.sprintf (GTXT ("User: `%s'"), username); 4167 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4168 } 4169 4170 // add comment for current working directory 4171 if (ucwd != NULL) 4172 { 4173 sb.setLength (0); 4174 sb.sprintf (GTXT ("Current working directory: %s"), ucwd); 4175 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4176 } 4177 4178 // add comment for collector version string 4179 if (cversion != NULL) 4180 { 4181 char *wstring; 4182 switch (wsize) 4183 { 4184 case Wnone: 4185 wstring = NTXT ("?"); 4186 break; 4187 case W32: 4188 wstring = GTXT ("32-bit"); 4189 break; 4190 case W64: 4191 wstring = GTXT ("64-bit"); 4192 break; 4193 default: 4194 wstring = NTXT ("??"); 4195 break; 4196 } 4197 sb.setLength (0); 4198 sb.sprintf (GTXT ("Collector version: `%s'; experiment version %d.%d (%s)"), 4199 cversion, exp_maj_version, exp_min_version, wstring); 4200 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4201 } 4202 4203 // add comment for driver version string (er_kernel) 4204 if (dversion != NULL) 4205 { 4206 sb.setLength (0); 4207 sb.sprintf (GTXT ("Kernel driver version: `%s'"), dversion); 4208 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4209 } 4210 4211 if (jversion != NULL) 4212 { 4213 sb.setLength (0); 4214 sb.sprintf (GTXT ("JVM version: `%s'"), jversion); 4215 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4216 } 4217 4218 // add comment for hostname, parameters 4219 if (hostname == NULL) 4220 hostname = dbe_strdup (GTXT ("unknown")); 4221 if (os_version == NULL) 4222 os_version = dbe_strdup (GTXT ("unknown")); 4223 if (architecture == NULL) 4224 architecture = dbe_strdup (GTXT ("unknown")); 4225 sb.setLength (0); 4226 sb.sprintf (GTXT ("Host `%s', OS `%s', page size %d, architecture `%s'"), 4227 hostname, os_version, page_size, architecture); 4228 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4229 4230 sb.setLength (0); 4231 if (maxclock != minclock) 4232 { 4233 clock = maxclock; 4234 sb.sprintf ( 4235 GTXT (" %d CPUs, with clocks ranging from %d to %d MHz.; max of %d MHz. assumed"), 4236 ncpus, minclock, maxclock, clock); 4237 } 4238 else 4239 sb.sprintf (GTXT (" %d CPU%s, clock speed %d MHz."), 4240 ncpus, (ncpus == 1 ? NTXT ("") : "s"), clock); 4241 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4242 4243 // add comment for machine memory size 4244 if (page_size > 0 && npages > 0) 4245 { 4246 long long memsize = ((long long) npages * page_size) / (1024 * 1024); 4247 sb.setLength (0); 4248 sb.sprintf (GTXT (" Memory: %d pages @ %d = %lld MB."), 4249 npages, page_size, memsize); 4250 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4251 } 4252 4253 // add comment for machine memory size 4254 if (machinemodel != NULL) 4255 { 4256 sb.setLength (0); 4257 sb.sprintf (GTXT (" Machine model: %s"), machinemodel); 4258 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4259 } 4260 4261 // add comment for start time 4262 time_t t = (time_t) start_sec; 4263 char *p = ctime (&t); 4264 sb.setLength (0); 4265 if (p != NULL) 4266 sb.sprintf (GTXT ("Experiment started %s"), p); 4267 else 4268 sb.sprintf (GTXT ("\nExperiment start not recorded")); 4269 write_coll_params (); 4270 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4271 commentq->appendqueue (runlogq); 4272 runlogq->mark_clear (); 4273} 4274 4275void 4276Experiment::write_coll_params () 4277{ 4278 StringBuilder sb; 4279 4280 // now write the various collection parameters as comments 4281 sb.setLength (0); 4282 sb.append (GTXT ("Data collection parameters:")); 4283 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4284 if (coll_params.profile_mode == 1) 4285 { 4286 sb.setLength (0); 4287 sb.sprintf (GTXT (" Clock-profiling, interval = %d microsecs."), 4288 (int) (coll_params.ptimer_usec)); 4289 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4290 } 4291 if (coll_params.sync_mode == 1) 4292 { 4293 sb.setLength (0); 4294 char *scope_str = NTXT (""); 4295 switch (coll_params.sync_scope) 4296 { 4297 case 0: 4298 scope_str = GTXT ("Native- and Java-APIs"); 4299 break; 4300 case SYNCSCOPE_JAVA: 4301 scope_str = GTXT ("JAVA-APIs"); 4302 break; 4303 case SYNCSCOPE_NATIVE: 4304 scope_str = GTXT ("Native-APIs"); 4305 break; 4306 case SYNCSCOPE_JAVA | SYNCSCOPE_NATIVE: 4307 scope_str = GTXT ("Native- and Java-APIs"); 4308 break; 4309 } 4310 if (coll_params.sync_threshold < 0) 4311 sb.sprintf (GTXT (" Synchronization tracing, threshold = %d microsecs. (calibrated); %s"), 4312 -coll_params.sync_threshold, scope_str); 4313 else 4314 sb.sprintf (GTXT (" Synchronization tracing, threshold = %d microsecs.; %s"), 4315 coll_params.sync_threshold, scope_str); 4316 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4317 } 4318 if (coll_params.heap_mode == 1) 4319 { 4320 sb.setLength (0); 4321 sb.append (GTXT (" Heap tracing")); 4322 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4323 } 4324 if (coll_params.io_mode == 1) 4325 { 4326 sb.setLength (0); 4327 sb.append (GTXT (" IO tracing")); 4328 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4329 } 4330 if (coll_params.race_mode == 1) 4331 { 4332 sb.setLength (0); 4333 char *race_stack_name; 4334 switch (coll_params.race_stack) 4335 { 4336 case 0: 4337 race_stack_name = GTXT ("dual-stack"); 4338 break; 4339 case 1: 4340 race_stack_name = GTXT ("single-stack"); 4341 break; 4342 case 2: 4343 race_stack_name = GTXT ("leaf"); 4344 break; 4345 default: 4346 abort (); 4347 } 4348 sb.sprintf (GTXT (" Datarace detection, %s"), race_stack_name); 4349 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4350 } 4351 if (coll_params.deadlock_mode == 1) 4352 { 4353 sb.setLength (0); 4354 sb.append (GTXT (" Deadlock detection")); 4355 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4356 } 4357 if (coll_params.hw_mode == 1) 4358 { 4359 sb.setLength (0); 4360 if (hwc_default == true) 4361 sb.append (GTXT (" HW counter-profiling (default); counters:")); 4362 else 4363 sb.append (GTXT (" HW counter-profiling; counters:")); 4364 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4365 for (int i = 0; i < MAX_HWCOUNT; i++) 4366 { 4367 if (!coll_params.hw_aux_name[i]) 4368 continue; 4369 sb.setLength (0); 4370 sb.sprintf (GTXT (" %s, tag %d, interval %d, memop %d"), 4371 coll_params.hw_aux_name[i], i, 4372 coll_params.hw_interval[i], coll_params.hw_tpc[i]); 4373 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4374 } 4375 } 4376 if (coll_params.sample_periodic == 1) 4377 { 4378 sb.setLength (0); 4379 sb.sprintf (GTXT (" Periodic sampling, %d secs."), 4380 coll_params.sample_timer); 4381 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4382 } 4383 if (coll_params.limit != 0) 4384 { 4385 sb.setLength (0); 4386 sb.sprintf (GTXT (" Experiment size limit, %d"), 4387 coll_params.limit); 4388 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4389 } 4390 if (coll_params.linetrace != NULL) 4391 { 4392 sb.setLength (0); 4393 sb.sprintf (GTXT (" Follow descendant processes from: %s"), 4394 coll_params.linetrace); 4395 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4396 } 4397 if (coll_params.pause_sig != NULL) 4398 { 4399 sb.setLength (0); 4400 sb.sprintf (GTXT (" Pause signal %s"), coll_params.pause_sig); 4401 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4402 } 4403 if (coll_params.sample_sig != NULL) 4404 { 4405 sb.setLength (0); 4406 sb.sprintf (GTXT (" Sample signal %s"), coll_params.sample_sig); 4407 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4408 } 4409 if (coll_params.start_delay != NULL) 4410 { 4411 sb.setLength (0); 4412 sb.sprintf (GTXT (" Data collection delay start %s seconds"), coll_params.start_delay); 4413 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4414 } 4415 if (coll_params.terminate != NULL) 4416 { 4417 sb.setLength (0); 4418 sb.sprintf (GTXT (" Data collection termination after %s seconds"), coll_params.terminate); 4419 commentq->append (new Emsg (CMSG_COMMENT, sb)); 4420 } 4421 // add a blank line after data description 4422 commentq->append (new Emsg (CMSG_COMMENT, NTXT (""))); 4423} 4424 4425 4426/* 4427 * Raw packet processing 4428 */ 4429static int 4430check_mstate (char *ptr, PacketDescriptor *pDscr, int arg) 4431{ 4432 switch (arg) 4433 { 4434 case PROP_UCPU: 4435 case PROP_SCPU: 4436 case PROP_TRAP: 4437 case PROP_TFLT: 4438 case PROP_DFLT: 4439 case PROP_KFLT: 4440 case PROP_ULCK: 4441 case PROP_TSLP: 4442 case PROP_WCPU: 4443 case PROP_TSTP: 4444 break; 4445 default: 4446 return 0; 4447 } 4448 Vector<FieldDescr*> *fields = pDscr->getFields (); 4449 for (int i = 0, sz = fields->size (); i < sz; i++) 4450 { 4451 FieldDescr *fDscr = fields->fetch (i); 4452 if (fDscr->propID == arg) 4453 return *((int*) (ptr + fDscr->offset)); 4454 } 4455 return 0; 4456} 4457 4458#define PACKET_ALIGNMENT 4 4459 4460uint64_t 4461Experiment::readPacket (Data_window *dwin, Data_window::Span *span) 4462{ 4463 Common_packet *rcp = (Common_packet *) dwin->bind (span, 4464 sizeof (CommonHead_packet)); 4465 uint16_t v16; 4466 uint64_t size = 0; 4467 if (rcp) 4468 { 4469 if ((((long) rcp) % PACKET_ALIGNMENT) != 0) 4470 { 4471 invalid_packet++; 4472 size = PROFILE_BUFFER_CHUNK - span->offset % PROFILE_BUFFER_CHUNK; 4473 return size; 4474 } 4475 v16 = (uint16_t) rcp->tsize; 4476 size = dwin->decode (v16); 4477 if (size == 0) 4478 { 4479 size = PROFILE_BUFFER_CHUNK - span->offset % PROFILE_BUFFER_CHUNK; 4480 return size; 4481 } 4482 rcp = (Common_packet *) dwin->bind (span, size); 4483 } 4484 if (rcp == NULL) 4485 return 0; 4486 4487 if ((((long) rcp) % PACKET_ALIGNMENT) != 0) 4488 { 4489 invalid_packet++; 4490 size = PROFILE_BUFFER_CHUNK - span->offset % PROFILE_BUFFER_CHUNK; 4491 return size; 4492 } 4493 v16 = (uint16_t) rcp->type; 4494 uint32_t rcptype = dwin->decode (v16); 4495 if (rcptype == EMPTY_PCKT) 4496 return size; 4497 if (rcptype == FRAME_PCKT) 4498 { 4499 RawFramePacket *fp = new RawFramePacket; 4500 fp->uid = dwin->decode (((Frame_packet*) rcp)->uid); 4501 fp->uidn = NULL; 4502 fp->uidj = NULL; 4503 fp->omp_uid = NULL; 4504 fp->omp_state = 0; 4505 char *ptr = (char*) rcp + dwin->decode (((Frame_packet*) rcp)->hsize); 4506 if ((((long) ptr) % PACKET_ALIGNMENT) != 0) 4507 { 4508 invalid_packet++; 4509 delete fp; 4510 return size; 4511 } 4512 v16 = (uint16_t) ((Frame_packet*) rcp)->tsize; 4513 char *end = (char*) rcp + dwin->decode (v16); 4514 for (; ptr < end;) 4515 { 4516 Common_info *cinfo = (Common_info*) ptr; 4517 uint32_t hsize = dwin->decode (cinfo->hsize); 4518 if (hsize == 0 || ptr + hsize > end) 4519 break; 4520 int kind = dwin->decode (cinfo->kind); 4521 bool compressed = false; 4522 if (kind & COMPRESSED_INFO) 4523 { 4524 compressed = true; 4525 kind &= ~COMPRESSED_INFO; 4526 } 4527 switch (kind) 4528 { 4529 case STACK_INFO: 4530 { 4531 char *stack = ptr + sizeof (Stack_info); 4532 size_t stack_size = hsize - sizeof (Stack_info); 4533 uint64_t uidn = dwin->decode (((Stack_info*) cinfo)->uid); 4534 if (stack_size <= 0) 4535 { 4536 fp->uidn = get_uid_node (uidn); 4537 break; 4538 } 4539 uint64_t link_uid = (uint64_t) 0; 4540 if (compressed) 4541 { 4542 stack_size -= sizeof (uint64_t); 4543 unsigned char *s = (unsigned char*) (stack + stack_size); 4544 int shift = 0; 4545 for (size_t i = 0; i<sizeof (link_uid); i++) 4546 { 4547 link_uid |= (uint64_t) * s++ << shift; 4548 shift += 8; 4549 } 4550 } 4551 if (wsize == W32) 4552 fp->uidn = add_uid (dwin, uidn, 4553 (int) (stack_size / sizeof (uint32_t)), 4554 (uint32_t*) stack, link_uid); 4555 else 4556 fp->uidn = add_uid (dwin, uidn, 4557 (int) (stack_size / sizeof (uint64_t)), 4558 (uint64_t*) stack, link_uid); 4559 break; 4560 } 4561 case JAVA_INFO: 4562 { 4563 char *stack = ptr + sizeof (Java_info); 4564 size_t stack_size = hsize - sizeof (Java_info); 4565 uint64_t uidj = dwin->decode (((Java_info*) cinfo)->uid); 4566 if (stack_size <= 0) 4567 { 4568 fp->uidj = get_uid_node (uidj); 4569 break; 4570 } 4571 4572 uint64_t link_uid = (uint64_t) 0; 4573 if (compressed) 4574 { 4575 stack_size -= sizeof (uint64_t); 4576 unsigned char *s = (unsigned char*) (stack + stack_size); 4577 int shift = 0; 4578 for (size_t i = 0; i<sizeof (link_uid); i++) 4579 { 4580 link_uid |= (uint64_t) * s++ << shift; 4581 shift += 8; 4582 } 4583 } 4584 if (wsize == W32) 4585 fp->uidj = add_uid (dwin, uidj, 4586 (int) (stack_size / sizeof (uint32_t)), 4587 (uint32_t*) stack, link_uid); 4588 else 4589 { 4590 // bug 6909545: garbage in 64-bit JAVA_INFO 4591 char *nstack = (char*) malloc (stack_size); 4592 char *dst = nstack; 4593 char *srcmax = stack + stack_size - sizeof (uint64_t); 4594 for (char *src = stack; src <= srcmax;) 4595 { 4596 int64_t val = dwin->decode (*(int32_t*) src); 4597 *(uint64_t*) dst = dwin->decode (val); 4598 src += sizeof (uint64_t); 4599 dst += sizeof (uint64_t); 4600 if (src > srcmax) 4601 { 4602 fprintf (stderr, "er_print: Experiment::readPacket: Error in data: src=%llx greater than %llx\n", 4603 (long long) src, (long long) srcmax); 4604 break; 4605 } 4606 *(uint64_t*) dst = *(uint64_t*) src; 4607 src += sizeof (uint64_t); 4608 dst += sizeof (uint64_t); 4609 } 4610 fp->uidj = add_uid (dwin, uidj, 4611 (int) (stack_size / sizeof (uint64_t)), 4612 (uint64_t*) nstack, link_uid); 4613 free (nstack); 4614 } 4615 break; 4616 } 4617 case OMP_INFO: 4618 fp->omp_state = dwin->decode (((OMP_info*) ptr)->omp_state); 4619 break; 4620 case OMP2_INFO: 4621 { 4622 uint64_t omp_uid = dwin->decode (((OMP2_info*) ptr)->uid); 4623 fp->omp_uid = get_uid_node (omp_uid); 4624 fp->omp_state = dwin->decode (((OMP2_info*) ptr)->omp_state); 4625 break; 4626 } 4627 default: 4628 break; 4629 } 4630 ptr += hsize; 4631 } 4632 frmpckts->append (fp); 4633 return size; 4634 } 4635 else if (rcptype == UID_PCKT) 4636 { 4637 Uid_packet *uidp = (Uid_packet*) rcp; 4638 uint64_t uid = dwin->decode (uidp->uid); 4639 char *arr_bytes = (char*) (uidp + 1); 4640 v16 = (uint16_t) rcp->tsize; 4641 size_t arr_length = dwin->decode (v16) - sizeof (Uid_packet); 4642 if (arr_length <= 0) 4643 return size; 4644 uint64_t link_uid = (uint64_t) 0; 4645 if (dwin->decode (uidp->flags) & COMPRESSED_INFO) 4646 { 4647 arr_length -= sizeof (uint64_t); 4648 unsigned char *s = (unsigned char*) (arr_bytes + arr_length); 4649 int shift = 0; 4650 for (size_t i = 0; i<sizeof (link_uid); i++) 4651 { 4652 link_uid |= (uint64_t) * s++ << shift; 4653 shift += 8; 4654 } 4655 } 4656 if (wsize == W32) 4657 add_uid (dwin, uid, (int) (arr_length / sizeof (uint32_t)), 4658 (uint32_t*) arr_bytes, link_uid); 4659 else 4660 add_uid (dwin, uid, (int) (arr_length / sizeof (uint64_t)), 4661 (uint64_t*) arr_bytes, link_uid); 4662 return size; 4663 } 4664 4665 PacketDescriptor *pcktDescr = getPacketDescriptor (rcptype); 4666 if (pcktDescr == NULL) 4667 return size; 4668 DataDescriptor *dataDescr = pcktDescr->getDataDescriptor (); 4669 if (dataDescr == NULL) 4670 return size; 4671 4672 /* omazur: TBR START -- old experiment */ 4673 if (rcptype == PROF_PCKT) 4674 { 4675 // For backward compatibility with older SS12 experiments 4676 int numstates = get_params ()->lms_magic_id; // ugly, for old experiments 4677 if (numstates > LMS_NUM_SOLARIS_MSTATES) 4678 numstates = LMS_NUM_SOLARIS_MSTATES; 4679 for (int i = 0; i < numstates; i++) 4680 if (check_mstate ((char*) rcp, pcktDescr, PROP_UCPU + i)) 4681 readPacket (dwin, (char*) rcp, pcktDescr, dataDescr, PROP_UCPU + i, 4682 size); 4683 } 4684 else 4685 readPacket (dwin, (char*) rcp, pcktDescr, dataDescr, 0, size); 4686 return size; 4687} 4688 4689void 4690Experiment::readPacket (Data_window *dwin, char *ptr, PacketDescriptor *pDscr, 4691 DataDescriptor *dDscr, int arg, uint64_t pktsz) 4692{ 4693 union Value 4694 { 4695 uint32_t val32; 4696 uint64_t val64; 4697 } *v; 4698 4699 long recn = dDscr->addRecord (); 4700 Vector<FieldDescr*> *fields = pDscr->getFields (); 4701 int sz = fields->size (); 4702 for (int i = 0; i < sz; i++) 4703 { 4704 FieldDescr *field = fields->fetch (i); 4705 v = (Value*) (ptr + field->offset); 4706 if (field->propID == arg) 4707 { 4708 dDscr->setValue (PROP_NTICK, recn, dwin->decode (v->val32)); 4709 dDscr->setValue (PROP_MSTATE, recn, (uint32_t) (field->propID - PROP_UCPU)); 4710 } 4711 if (field->propID == PROP_THRID || field->propID == PROP_LWPID 4712 || field->propID == PROP_CPUID) 4713 { 4714 uint64_t tmp64 = 0; 4715 switch (field->vtype) 4716 { 4717 case TYPE_INT32: 4718 case TYPE_UINT32: 4719 tmp64 = dwin->decode (v->val32); 4720 break; 4721 case TYPE_INT64: 4722 case TYPE_UINT64: 4723 tmp64 = dwin->decode (v->val64); 4724 break; 4725 case TYPE_STRING: 4726 case TYPE_DOUBLE: 4727 case TYPE_OBJ: 4728 case TYPE_DATE: 4729 case TYPE_BOOL: 4730 case TYPE_ENUM: 4731 case TYPE_LAST: 4732 case TYPE_NONE: 4733 break; 4734 } 4735 uint32_t tag = mapTagValue ((Prop_type) field->propID, tmp64); 4736 dDscr->setValue (field->propID, recn, tag); 4737 } 4738 else 4739 { 4740 switch (field->vtype) 4741 { 4742 case TYPE_INT32: 4743 case TYPE_UINT32: 4744 dDscr->setValue (field->propID, recn, dwin->decode (v->val32)); 4745 break; 4746 case TYPE_INT64: 4747 case TYPE_UINT64: 4748 dDscr->setValue (field->propID, recn, dwin->decode (v->val64)); 4749 break; 4750 case TYPE_STRING: 4751 { 4752 int len = (int) (pktsz - field->offset); 4753 if ((len > 0) && (ptr[field->offset] != 0)) 4754 { 4755 StringBuilder *sb = new StringBuilder (); 4756 sb->append (ptr + field->offset, 0, len); 4757 dDscr->setObjValue (field->propID, recn, sb); 4758 } 4759 break; 4760 } 4761 // ignoring the following cases (why?) 4762 case TYPE_DOUBLE: 4763 case TYPE_OBJ: 4764 case TYPE_DATE: 4765 case TYPE_BOOL: 4766 case TYPE_ENUM: 4767 case TYPE_LAST: 4768 case TYPE_NONE: 4769 break; 4770 } 4771 } 4772 } 4773} 4774 4775#define PROG_BYTE 102400 // update progress bar every PROG_BYTE bytes 4776 4777void 4778Experiment::read_data_file (const char *fname, const char *msg) 4779{ 4780 Data_window::Span span; 4781 off64_t total_len, remain_len; 4782 char *progress_bar_msg; 4783 int progress_bar_percent = -1; 4784 4785 char *data_file_name = dbe_sprintf (NTXT ("%s/%s"), expt_name, fname); 4786 Data_window *dwin = new Data_window (data_file_name); 4787 // Here we can call stat(data_file_name) to get file size, 4788 // and call a function to reallocate vectors for clock profiling data 4789 free (data_file_name); 4790 if (dwin->not_opened ()) 4791 { 4792 delete dwin; 4793 return; 4794 } 4795 dwin->need_swap_endian = need_swap_endian; 4796 4797 span.offset = 0; 4798 span.length = dwin->get_fsize (); 4799 total_len = remain_len = span.length; 4800 progress_bar_msg = dbe_sprintf (NTXT ("%s %s"), NTXT (" "), msg); 4801 invalid_packet = 0; 4802 for (;;) 4803 { 4804 uint64_t pcktsz = readPacket (dwin, &span); 4805 if (pcktsz == 0) 4806 break; 4807 // Update progress bar 4808 if ((span.length <= remain_len) && (remain_len > 0)) 4809 { 4810 int percent = (int) (100 * (total_len - remain_len) / total_len); 4811 if (percent > progress_bar_percent) 4812 { 4813 progress_bar_percent += 10; 4814 theApplication->set_progress (percent, progress_bar_msg); 4815 } 4816 remain_len -= PROG_BYTE; 4817 } 4818 span.length -= pcktsz; 4819 span.offset += pcktsz; 4820 } 4821 delete dwin; 4822 4823 if (invalid_packet) 4824 { 4825 StringBuilder sb; 4826 sb.sprintf (GTXT ("WARNING: There are %d invalid packet(s) in the %s file"), 4827 invalid_packet, fname); 4828 Emsg *m = new Emsg (CMSG_WARN, sb); 4829 warnq->append (m); 4830 } 4831 4832 theApplication->set_progress (0, NTXT ("")); 4833 free (progress_bar_msg); 4834} 4835 4836int 4837Experiment::read_overview_file () 4838{ 4839 char *data_file_name = dbe_sprintf ("%s/%s", expt_name, SP_OVERVIEW_FILE); 4840 Data_window *dwin = new Data_window (data_file_name); 4841 free (data_file_name); 4842 if (dwin->not_opened ()) 4843 { 4844 delete dwin; 4845 return 0; 4846 } 4847 dwin->need_swap_endian = need_swap_endian; 4848 newDataDescriptor (DATA_SAMPLE); 4849 4850 Data_window::Span span; 4851 span.offset = 0; 4852 span.length = dwin->get_fsize (); 4853 4854 PrUsage *data = NULL, *data_prev = NULL; 4855 Sample *sample; 4856 int sample_number = 1; 4857 4858 int64_t prDataSize; 4859 if (wsize == W32) 4860 prDataSize = PrUsage::bind32Size (); 4861 else 4862 prDataSize = PrUsage::bind64Size (); 4863 4864 while (span.length > 0) 4865 { 4866 data_prev = data; 4867 data = new PrUsage (); 4868 4869 void *dw = dwin->bind (&span, prDataSize); 4870 if ((dw == NULL) || (prDataSize > span.length)) 4871 { 4872 Emsg *m = new Emsg (CMSG_ERROR, GTXT ("Warning: overview data file can't be read")); 4873 warnq->append (m); 4874 status = FAILURE; 4875 delete dwin; 4876 return status; 4877 } 4878 4879 if (wsize == W32) 4880 data->bind32 (dw, need_swap_endian); 4881 else 4882 data->bind64 (dw, need_swap_endian); 4883 span.length -= prDataSize; 4884 span.offset += prDataSize; 4885 4886 // Skip the first packet 4887 if (data_prev == NULL) 4888 continue; 4889 if (sample_number > samples->size ()) 4890 { // inconsistent log/overview 4891 sample = new Sample (sample_number); 4892 char * label = GTXT ("<unknown>"); 4893 sample->start_label = dbe_strdup (label); 4894 sample->end_label = dbe_strdup (label); 4895 samples->append (sample); 4896 } 4897 else 4898 sample = samples->fetch (sample_number - 1); 4899 sample_number++; 4900 sample->start_time = data_prev->pr_tstamp + 1; 4901 sample->end_time = data->pr_tstamp; 4902 sample->prusage = data_prev; 4903 4904 data_prev->pr_rtime = data->pr_rtime - data_prev->pr_rtime; 4905 data_prev->pr_utime = data->pr_utime - data_prev->pr_utime; 4906 data_prev->pr_stime = data->pr_stime - data_prev->pr_stime; 4907 data_prev->pr_ttime = data->pr_ttime - data_prev->pr_ttime; 4908 data_prev->pr_tftime = data->pr_tftime - data_prev->pr_tftime; 4909 data_prev->pr_dftime = data->pr_dftime - data_prev->pr_dftime; 4910 data_prev->pr_kftime = data->pr_kftime - data_prev->pr_kftime; 4911 data_prev->pr_ltime = data->pr_ltime - data_prev->pr_ltime; 4912 data_prev->pr_slptime = data->pr_slptime - data_prev->pr_slptime; 4913 data_prev->pr_wtime = data->pr_wtime - data_prev->pr_wtime; 4914 data_prev->pr_stoptime = data->pr_stoptime - data_prev->pr_stoptime; 4915 data_prev->pr_minf = data->pr_minf - data_prev->pr_minf; 4916 data_prev->pr_majf = data->pr_majf - data_prev->pr_majf; 4917 data_prev->pr_nswap = data->pr_nswap - data_prev->pr_nswap; 4918 data_prev->pr_inblk = data->pr_inblk - data_prev->pr_inblk; 4919 data_prev->pr_oublk = data->pr_oublk - data_prev->pr_oublk; 4920 data_prev->pr_msnd = data->pr_msnd - data_prev->pr_msnd; 4921 data_prev->pr_mrcv = data->pr_mrcv - data_prev->pr_mrcv; 4922 data_prev->pr_sigs = data->pr_sigs - data_prev->pr_sigs; 4923 data_prev->pr_vctx = data->pr_vctx - data_prev->pr_vctx; 4924 data_prev->pr_ictx = data->pr_ictx - data_prev->pr_ictx; 4925 data_prev->pr_sysc = data->pr_sysc - data_prev->pr_sysc; 4926 data_prev->pr_ioch = data->pr_ioch - data_prev->pr_ioch; 4927 sample->get_usage (); // force validation 4928 } 4929 4930 for (long smpNum = samples->size (); smpNum >= sample_number; smpNum--) 4931 { 4932 // overview file was truncated 4933 sample = samples->remove (smpNum - 1); 4934 delete sample; 4935 } 4936 4937 if (data) 4938 { 4939 // Update last_event so that getEndTime() covers 4940 // all loadobjects, too. 4941 update_last_event (data->pr_tstamp); 4942 delete data; 4943 } 4944 delete dwin; 4945 return SUCCESS; 4946} 4947 4948int 4949Experiment::uidNodeCmp (const void *a, const void *b) 4950{ 4951 UIDnode *nd1 = *(UIDnode**) a; 4952 UIDnode *nd2 = *(UIDnode**) b; 4953 if (nd1->uid == nd2->uid) 4954 return 0; 4955 return nd1->uid < nd2->uid ? -1 : 1; 4956} 4957 4958static uint64_t 4959funcAddr (uint32_t val) 4960{ 4961 if (val == (uint32_t) SP_LEAF_CHECK_MARKER) 4962 return (uint64_t) SP_LEAF_CHECK_MARKER; 4963 if (val == (uint32_t) SP_TRUNC_STACK_MARKER) 4964 return (uint64_t) SP_TRUNC_STACK_MARKER; 4965 if (val == (uint32_t) SP_FAILED_UNWIND_MARKER) 4966 return (uint64_t) SP_FAILED_UNWIND_MARKER; 4967 return val; 4968} 4969 4970Experiment::UIDnode * 4971Experiment::add_uid (Data_window *dwin, uint64_t uid, int size, 4972 uint32_t *array, uint64_t link_uid) 4973{ 4974 if (uid == (uint64_t) 0) 4975 return NULL; 4976 uint64_t val = funcAddr (dwin->decode (array[0])); 4977 UIDnode *node = NULL; 4978 UIDnode *res = get_uid_node (uid, val); 4979 UIDnode *next = res; 4980 for (int i = 0; i < size; i++) 4981 { 4982 val = funcAddr (dwin->decode (array[i])); 4983 if (next == NULL) 4984 { 4985 next = get_uid_node ((uint64_t) 0, val); 4986 if (node != NULL) 4987 node->next = next; 4988 } 4989 node = next; 4990 next = node->next; 4991 if (node->val == 0) 4992 node->val = val; 4993 else if (node->val != val) // Algorithmic error (should never happen) 4994 node->val = (uint64_t) SP_LEAF_CHECK_MARKER; 4995 } 4996 if (next == NULL && link_uid != (uint64_t) 0 && node != NULL) 4997 node->next = get_uid_node (link_uid); 4998 return res; 4999} 5000 5001Experiment::UIDnode * 5002Experiment::add_uid (Data_window *dwin, uint64_t uid, int size, uint64_t *array, uint64_t link_uid) 5003{ 5004 if (uid == (uint64_t) 0) 5005 return NULL; 5006 UIDnode *node = NULL; 5007 uint64_t val = dwin->decode (array[0]); 5008 UIDnode *res = get_uid_node (uid, val); 5009 UIDnode *next = res; 5010 for (int i = 0; i < size; i++) 5011 { 5012 val = dwin->decode (array[i]); 5013 if (next == NULL) 5014 { 5015 next = get_uid_node ((uint64_t) 0, val); 5016 if (node != NULL) 5017 node->next = next; 5018 } 5019 node = next; 5020 next = node->next; 5021 if (node->val == (uint64_t) 0) 5022 node->val = val; 5023 else if (node->val != val) // Algorithmic error (should never happen) 5024 node->val = (uint64_t) - 1; 5025 } 5026 if (next == NULL && link_uid != (uint64_t) 0 && node != NULL) 5027 node->next = get_uid_node (link_uid); 5028 return res; 5029} 5030 5031Experiment::UIDnode * 5032Experiment::new_uid_node (uint64_t uid, uint64_t val) 5033{ 5034#define NCHUNKSTEP 1024 5035 if (nnodes >= nchunks * CHUNKSZ) 5036 { 5037 // Reallocate Node chunk array 5038 UIDnode** old_chunks = chunks; 5039 chunks = new UIDnode*[nchunks + NCHUNKSTEP]; 5040 memcpy (chunks, old_chunks, nchunks * sizeof (UIDnode*)); 5041 nchunks += NCHUNKSTEP; 5042 delete[] old_chunks; 5043 // Clean future pointers 5044 memset (&chunks[nchunks - NCHUNKSTEP], 0, NCHUNKSTEP * sizeof (UIDnode*)); 5045 } 5046 5047 if (NULL == chunks[nnodes / CHUNKSZ]) // Allocate new chunk for nodes. 5048 chunks[nnodes / CHUNKSZ] = new UIDnode[CHUNKSZ]; 5049 UIDnode *node = &chunks[nnodes / CHUNKSZ][nnodes % CHUNKSZ]; 5050 node->uid = uid; 5051 node->val = val; 5052 node->next = NULL; 5053 nnodes++; 5054 return node; 5055} 5056 5057Experiment::UIDnode * 5058Experiment::get_uid_node (uint64_t uid, uint64_t val) 5059{ 5060 int hash = (((int) uid) >> 4) & (HTableSize - 1); 5061 if (uid != (uint64_t) 0) 5062 { 5063 UIDnode *node = uidHTable[hash]; 5064 if (node && node->uid == uid) 5065 return node; 5066 } 5067 UIDnode *node = new_uid_node (uid, val); 5068 if (uid != (uint64_t) 0) 5069 { 5070 uidHTable[hash] = node; 5071 uidnodes->append (node); 5072 } 5073 return node; 5074} 5075 5076Experiment::UIDnode * 5077Experiment::get_uid_node (uint64_t uid) 5078{ 5079 if (uid == (uint64_t) 0) 5080 return NULL; 5081 int hash = (((int) uid) >> 4) & (HTableSize - 1); 5082 UIDnode *node = uidHTable[hash]; 5083 if (node && node->uid == uid) 5084 return node; 5085 node = new_uid_node (uid, (uint64_t) 0); 5086 node->next = node; 5087 return node; 5088} 5089 5090Experiment::UIDnode * 5091Experiment::find_uid_node (uint64_t uid) 5092{ 5093 int hash = (((int) uid) >> 4) & (HTableSize - 1); 5094 UIDnode *node = uidHTable[hash]; 5095 if (node && node->uid == uid) 5096 return node; 5097 int lt = 0; 5098 int rt = uidnodes->size () - 1; 5099 while (lt <= rt) 5100 { 5101 int md = (lt + rt) / 2; 5102 node = uidnodes->fetch (md); 5103 if (node->uid < uid) 5104 lt = md + 1; 5105 else if (node->uid > uid) 5106 rt = md - 1; 5107 else 5108 { 5109 uidHTable[hash] = node; 5110 return node; 5111 } 5112 } 5113 return NULL; 5114} 5115 5116int 5117Experiment::frUidCmp (const void *a, const void *b) 5118{ 5119 RawFramePacket *fp1 = *(RawFramePacket**) a; 5120 RawFramePacket *fp2 = *(RawFramePacket**) b; 5121 if (fp1->uid == fp2->uid) 5122 return 0; 5123 return fp1->uid < fp2->uid ? -1 : 1; 5124} 5125 5126Experiment::RawFramePacket * 5127Experiment::find_frame_packet (uint64_t uid) 5128{ 5129 int lt = 0; 5130 int rt = frmpckts->size () - 1; 5131 while (lt <= rt) 5132 { 5133 int md = (lt + rt) / 2; 5134 RawFramePacket *fp = frmpckts->fetch (md); 5135 if (fp->uid < uid) 5136 lt = md + 1; 5137 else if (fp->uid > uid) 5138 rt = md - 1; 5139 else 5140 return fp; 5141 } 5142 5143 return NULL; 5144} 5145 5146#define FRINFO_CACHEOPT_SIZE_LIMIT 4000000 5147#define FRINFO_PIPELINE_SIZE_LIMIT 500000 5148#define FRINFO_PIPELINE_NUM_STAGES 3 5149 5150// Pipelined execution of resolve_frame_info() and add_stack(). 5151// Since this is the largest time consuming part of loading an experiment (especially 5152// so for large java experiments) - executing this part as a 3 stage pipeline can 5153// give significant performance gain - and this concept can be aggressively applied 5154// to enhance the gain further in future. The three stages are: 5155// Phase 1: resolve_frame_info() 5156// Phase 2: first part of add_stack() where the native stack is built 5157// Phase 3: second part og add_stack() where the java stack is built 5158// Phase 4: insert the native and java stacks into the stack map 5159// The main thread operates in the first Phase and the other stages are 5160// operated by a ssplib sequential queue - The threads working on the queues run concurrently 5161// with each other and with the main thread. But within a particular queue, jobs are 5162// executed sequentially 5163 5164 5165// This is the second phase of the pipeline of resolve_frame_info and add_stack 5166// It works on a chunk of iterations (size CSTCTX_CHUNK_SZ) and invokes add_stack() 5167// for each one of them 5168 5169void 5170Experiment::resolve_frame_info (DataDescriptor *dDscr) 5171{ 5172 if (!resolveFrameInfo) 5173 return; 5174 if (NULL == cstack) 5175 return; 5176 dDscr->setResolveFrInfoDone (); 5177 5178 // Check for TSTAMP 5179 int propID = dbeSession->getPropIdByName (NTXT ("TSTAMP")); 5180 Data *dataTStamp = dDscr->getData (propID); 5181 if (dataTStamp == NULL) 5182 return; 5183 5184 propID = dbeSession->getPropIdByName (NTXT ("FRINFO")); 5185 Data *dataFrinfo = dDscr->getData (propID); 5186 5187 propID = dbeSession->getPropIdByName (NTXT ("THRID")); 5188 Data *dataThrId = dDscr->getData (propID); 5189 5190 // We can get frame info either by FRINFO or by [THRID,STKIDX] 5191 if (dataFrinfo == NULL) 5192 return; 5193 5194 char *propName = NTXT ("MSTACK"); 5195 propID = dbeSession->getPropIdByName (propName); 5196 PropDescr *prMStack = new PropDescr (propID, propName); 5197 prMStack->uname = dbe_strdup (GTXT ("Machine Call Stack")); 5198 prMStack->vtype = TYPE_OBJ; 5199 dDscr->addProperty (prMStack); 5200 5201 propName = NTXT ("USTACK"); 5202 propID = dbeSession->getPropIdByName (propName); 5203 PropDescr *prUStack = new PropDescr (propID, propName); 5204 prUStack->uname = dbe_strdup (GTXT ("User Call Stack")); 5205 prUStack->vtype = TYPE_OBJ; 5206 dDscr->addProperty (prUStack); 5207 5208 propName = NTXT ("XSTACK"); 5209 propID = dbeSession->getPropIdByName (propName); 5210 PropDescr *prXStack = new PropDescr (propID, propName); 5211 prXStack->uname = dbe_strdup (GTXT ("Expert Call Stack")); 5212 prXStack->vtype = TYPE_OBJ; 5213 dDscr->addProperty (prXStack); 5214 5215 propName = NTXT ("HSTACK"); 5216 propID = dbeSession->getPropIdByName (propName); 5217 PropDescr *prHStack = new PropDescr (propID, propName); 5218 prHStack->uname = dbe_strdup (GTXT ("ShowHide Call Stack")); 5219 prHStack->vtype = TYPE_OBJ; 5220 dDscr->addProperty (prHStack); 5221 5222 if (has_java) 5223 { 5224 propName = NTXT ("JTHREAD"); 5225 propID = dbeSession->getPropIdByName (propName); 5226 PropDescr *prJThread = new PropDescr (propID, propName); 5227 prJThread->uname = dbe_strdup (GTXT ("Java Thread")); 5228 prJThread->vtype = TYPE_OBJ; 5229 dDscr->addProperty (prJThread); 5230 } 5231 5232 if (ompavail) 5233 { 5234 PropDescr *prop = new PropDescr (PROP_OMPSTATE, NTXT ("OMPSTATE")); 5235 prop->uname = dbe_strdup (GTXT ("OpenMP state")); 5236 prop->vtype = TYPE_UINT32; 5237 char * stateNames [OMP_LAST_STATE] = OMP_THR_STATE_STRINGS; 5238 char * stateUNames[OMP_LAST_STATE] = OMP_THR_STATE_USTRINGS; 5239 for (int ii = 0; ii < OMP_LAST_STATE; ii++) 5240 prop->addState (ii, stateNames[ii], stateUNames[ii]); 5241 dDscr->addProperty (prop); 5242 5243 // add PROP_CPRID to profiling data (not same as omptrace's PROP_CPRID) 5244 prop = dDscr->getProp (PROP_CPRID); 5245 if (prop) 5246 { 5247 VType_type type = prop->vtype; 5248 assert (type == TYPE_OBJ); //see 7040526 5249 } 5250 prop = new PropDescr (PROP_CPRID, NTXT ("CPRID")); //profiling PROP_CPRID 5251 prop->uname = dbe_strdup (GTXT ("OpenMP parallel region")); 5252 prop->vtype = TYPE_OBJ; 5253 dDscr->addProperty (prop); 5254 5255 // add PROP_TSKID to profiling data (not same as omptrace's PROP_TSKID) 5256 prop = dDscr->getProp (PROP_TSKID); 5257 if (prop) 5258 { 5259 VType_type type = prop->vtype; 5260 assert (type == TYPE_OBJ); //see 7040526 5261 } 5262 prop = new PropDescr (PROP_TSKID, NTXT ("TSKID")); //profiling PROP_TSKID 5263 prop->uname = dbe_strdup (GTXT ("OpenMP task")); 5264 prop->vtype = TYPE_OBJ; 5265 dDscr->addProperty (prop); 5266 } 5267 char *progress_bar_msg = dbe_sprintf (NTXT ("%s %s: %s"), NTXT (" "), 5268 GTXT ("Processing CallStack Data"), 5269 get_basename (expt_name)); 5270 int progress_bar_percent = -1; 5271 long deltaReport = 5000; 5272 long nextReport = 0; 5273 5274 long size = dDscr->getSize (); 5275 // bool resolve_frinfo_pipelined = size > FRINFO_PIPELINE_SIZE_LIMIT && !ompavail; 5276 bool resolve_frinfo_pipelined = false; 5277 5278 Map<uint64_t, uint64_t> *nodeCache = NULL; 5279 Map<uint64_t, uint64_t> *frameInfoCache = NULL; 5280 if (size > FRINFO_CACHEOPT_SIZE_LIMIT && dversion == NULL) 5281 { 5282 frameInfoCache = new CacheMap<uint64_t, uint64_t>; 5283 nodeCache = new CacheMap<uint64_t, uint64_t>; 5284 } 5285 5286 pushCnt = popCnt = pushCnt3 = popCnt3 = 0; 5287 nPush = nPop = 0; 5288 5289 FramePacket *fp = NULL; 5290 // DbeThreadPool * threadPool = new DbeThreadPool(5); 5291 fp = new FramePacket; 5292 fp->stack = new Vector<Vaddr>; 5293 fp->jstack = new Vector<Vaddr>; 5294 fp->ompstack = new Vector<Vaddr>; 5295 fp->omp_state = 0; 5296 fp->mpi_state = 0; 5297 5298 // piggyback on post-processing to calculate exp->last_event 5299 const hrtime_t _exp_start_time = getStartTime (); // wall clock time 5300 hrtime_t exp_duration = getLastEvent () == ZERO_TIME ? 0 5301 : getLastEvent () - _exp_start_time; // zero-based 5302 5303 int missed_fi = 0; 5304 int total_fi = 0; 5305 5306 for (long i = 0; i < size; i++) 5307 { 5308 if (i == nextReport) 5309 { 5310 int percent = (int) (i * 100 / size); 5311 if (percent > progress_bar_percent) 5312 { 5313 progress_bar_percent += 10; 5314 theApplication->set_progress (percent, progress_bar_msg); 5315 } 5316 nextReport += deltaReport; 5317 } 5318 5319 uint32_t thrid = (uint32_t) dataThrId->fetchInt (i); 5320 hrtime_t tstamp = (hrtime_t) dataTStamp->fetchLong (i); 5321 5322 // piggyback on post-processing to calculate exp->last_event 5323 { 5324 hrtime_t relative_timestamp = tstamp - _exp_start_time; 5325 if (exp_duration < relative_timestamp) 5326 exp_duration = relative_timestamp; 5327 } 5328 uint64_t frinfo = (uint64_t) dataFrinfo->fetchLong (i); 5329 5330 RawFramePacket *rfp = NULL; 5331 if (frinfo) 5332 { 5333 // CacheMap does not work with NULL key 5334 if (frameInfoCache != NULL) 5335 rfp = (RawFramePacket *) frameInfoCache->get (frinfo); 5336 } 5337 if (rfp == 0) 5338 { 5339 rfp = find_frame_packet (frinfo); 5340 if (rfp != 0) 5341 { 5342 if (frameInfoCache != NULL) 5343 frameInfoCache->put (frinfo, (uint64_t) rfp); 5344 } 5345 else 5346 missed_fi++; 5347 total_fi++; 5348 } 5349 5350 // Process OpenMP properties 5351 if (ompavail) 5352 { 5353 fp->omp_state = rfp ? rfp->omp_state : 0; 5354 dDscr->setValue (PROP_OMPSTATE, i, fp->omp_state); 5355 5356 fp->omp_cprid = mapPRid->get (thrid, tstamp, mapPRid->REL_EQLE); 5357 void *omp_preg = mapPReg->get (thrid, tstamp, mapPReg->REL_EQLE); 5358 if (!omp_preg) 5359 { 5360 char *idxname = NTXT ("OMP_preg"); 5361 int idxtype = dbeSession->findIndexSpaceByName (idxname); 5362 if (idxtype != -1) 5363 { 5364 Histable *preg0 = dbeSession->findObjectById (Histable::INDEXOBJ, idxtype, (int64_t) 0); 5365 if (preg0) 5366 { 5367 Vector<Histable*> pregs; 5368 pregs.append (preg0); 5369 omp_preg = cstack->add_stack (&pregs); 5370 mapPReg->put (thrid, tstamp, omp_preg); 5371 } 5372 } 5373 } 5374 dDscr->setObjValue (PROP_CPRID, i, omp_preg); //profiling PROP_CPRID 5375 void *omp_task = mapTask->get (thrid, tstamp, mapTask->REL_EQLE); 5376 if (!omp_task) 5377 { 5378 char *idxname = NTXT ("OMP_task"); 5379 int idxtype = dbeSession->findIndexSpaceByName (idxname); 5380 if (idxtype != -1) 5381 { 5382 Histable *task0 = dbeSession->findObjectById (Histable::INDEXOBJ, idxtype, (int64_t) 0); 5383 if (task0) 5384 { 5385 Vector<Histable*> tasks; 5386 tasks.append (task0); 5387 omp_task = cstack->add_stack (&tasks); 5388 mapTask->put (thrid, tstamp, omp_task); 5389 } 5390 } 5391 } 5392 dDscr->setObjValue (PROP_TSKID, i, omp_task); //profiling PROP_TSKID 5393 } 5394 else 5395 { 5396 fp->omp_state = 0; 5397 fp->omp_cprid = 0; 5398 } 5399 5400 // Construct the native stack 5401 fp->stack->reset (); 5402 Vaddr leafpc = dDscr->getULongValue (PROP_LEAFPC, i); 5403 if (leafpc) 5404 fp->stack->append (leafpc); 5405 UIDnode *node = rfp ? rfp->uidn : NULL; 5406 while (node) 5407 { 5408 if (node->next == node) 5409 // this node contains link_uid 5410 node = find_uid_node (node->uid); 5411 else 5412 { 5413 fp->stack->append (node->val); 5414 node = node->next; 5415 } 5416 } 5417 fp->truncated = 0; 5418 int last = fp->stack->size () - 1; 5419 if (last >= 0) 5420 { 5421 switch (fp->stack->fetch (last)) 5422 { 5423 case SP_TRUNC_STACK_MARKER: 5424 fp->truncated = (Vaddr) SP_TRUNC_STACK_MARKER; 5425 fp->stack->remove (last); 5426 break; 5427 case SP_FAILED_UNWIND_MARKER: 5428 fp->truncated = (Vaddr) SP_FAILED_UNWIND_MARKER; 5429 fp->stack->remove (last); 5430 break; 5431 } 5432 } 5433 5434 // Construct the Java stack 5435 fp->jstack->reset (); 5436 node = rfp ? rfp->uidj : NULL; 5437 while (node) 5438 { 5439 if (node->next == node) 5440 { 5441 // this node contains link_uid 5442 UIDnode *n = NULL; 5443 if (node->uid) 5444 { 5445 // CacheMap does not work with NULL key 5446 if (nodeCache != NULL) 5447 n = (UIDnode *) nodeCache->get (node->uid); 5448 } 5449 if (n == NULL) 5450 { 5451 n = find_uid_node (node->uid); 5452 if (n != NULL) 5453 { 5454 if (nodeCache != NULL) 5455 nodeCache->put (node->uid, (uint64_t) n); 5456 } 5457 } 5458 node = n; 5459 } 5460 else 5461 { 5462 fp->jstack->append (node->val); 5463 node = node->next; 5464 } 5465 } 5466 fp->jtruncated = false; 5467 last = fp->jstack->size () - 1; 5468 if (last >= 1 && fp->jstack->fetch (last) == SP_TRUNC_STACK_MARKER) 5469 { 5470 fp->jtruncated = true; 5471 fp->jstack->remove (last); 5472 fp->jstack->remove (last - 1); 5473 } 5474 5475 // Construct the OpenMP stack 5476 if (ompavail) 5477 { 5478 fp->ompstack->reset (); 5479 if (rfp && rfp->omp_uid) 5480 { 5481 if (leafpc) 5482 fp->ompstack->append (leafpc); 5483 node = rfp->omp_uid; 5484 while (node) 5485 { 5486 if (node->next == node) 5487 // this node contains link_uid 5488 node = find_uid_node (node->uid); 5489 else 5490 { 5491 fp->ompstack->append (node->val); 5492 node = node->next; 5493 } 5494 } 5495 fp->omptruncated = false; 5496 last = fp->ompstack->size () - 1; 5497 if (last >= 0) 5498 { 5499 switch (fp->ompstack->fetch (last)) 5500 { 5501 case SP_TRUNC_STACK_MARKER: 5502 fp->omptruncated = (Vaddr) SP_TRUNC_STACK_MARKER; 5503 fp->ompstack->remove (last); 5504 break; 5505 case SP_FAILED_UNWIND_MARKER: 5506 fp->omptruncated = (Vaddr) SP_FAILED_UNWIND_MARKER; 5507 fp->ompstack->remove (last); 5508 break; 5509 } 5510 } 5511 } 5512 } 5513 cstack->add_stack (dDscr, i, fp, NULL); 5514 } 5515 5516 // piggyback on post-processing to calculate exp->last_event 5517 { 5518 hrtime_t exp_end_time = _exp_start_time + exp_duration; 5519 update_last_event (exp_end_time); 5520 } 5521 5522 if (missed_fi > 0) 5523 { 5524 StringBuilder sb; 5525 sb.sprintf ( 5526 GTXT ("*** Warning: %d frameinfo packets are missing from total of %d when resolving %s."), 5527 missed_fi, total_fi, dDscr->getName ()); 5528 warnq->append (new Emsg (CMSG_WARN, sb)); 5529 } 5530 5531 // threadPool->wait_group(); 5532 // delete threadPool; 5533 theApplication->set_progress (0, NTXT ("")); 5534 free (progress_bar_msg); 5535 if (!resolve_frinfo_pipelined && fp != NULL) 5536 { 5537 delete fp->ompstack; 5538 delete fp->jstack; 5539 delete fp->stack; 5540 delete fp; 5541 } 5542 delete frameInfoCache; 5543 frameInfoCache = NULL; 5544 delete nodeCache; 5545 nodeCache = NULL; 5546} 5547 5548void 5549Experiment::post_process () 5550{ 5551 // update non_paused_time after final update to "last_event" 5552 if (resume_ts != MAX_TIME && last_event) 5553 { 5554 hrtime_t ts = last_event - exp_start_time; 5555 hrtime_t delta = ts - resume_ts; 5556 non_paused_time += delta; 5557 resume_ts = MAX_TIME; // collection is paused 5558 } 5559 5560 // GC: prune events outside of experiment duration, calculate GC duration, update indices 5561 int index; 5562 GCEvent * gcevent; 5563 gc_duration = ZERO_TIME; 5564 if (gcevents != NULL) 5565 { 5566 // delete events that finish before exp_start_time or start after last_event 5567 for (int ii = 0; ii < gcevents->size ();) 5568 { 5569 gcevent = gcevents->fetch (ii); 5570 if (gcevent->end - exp_start_time < 0 5571 || last_event - gcevent->start < 0) 5572 delete gcevents->remove (ii); 5573 else 5574 ii++; 5575 } 5576 } 5577 Vec_loop (GCEvent*, gcevents, index, gcevent) 5578 { 5579 gcevent->id = index + 1; // renumber to account for any deleted events 5580 if (gcevent->start - exp_start_time < 0 || gcevent->start == ZERO_TIME) 5581 // truncate events that start before experiment start 5582 gcevent->start = exp_start_time; 5583 if (last_event - gcevent->end < 0) 5584 // truncate events that end after experiment end 5585 gcevent->end = last_event; 5586 gc_duration += gcevent->end - gcevent->start; 5587 } 5588} 5589 5590Experiment::Exp_status 5591Experiment::find_expdir (char *path) 5592{ 5593 // This function checks that the experiment directory 5594 // is of the proper form, and accessible 5595 struct stat64 sbuf; 5596 5597 // Save the name 5598 expt_name = dbe_strdup (path); 5599 5600 // Check that the name ends in .er 5601 size_t i = strlen (path); 5602 if (i > 0 && path[i - 1] == '/') 5603 path[--i] = '\0'; 5604 5605 if (i < 4 || strcmp (&path[i - 3], NTXT (".er")) != 0) 5606 { 5607 Emsg *m = new Emsg (CMSG_FATAL, 5608 GTXT ("*** Error: not a valid experiment name")); 5609 errorq->append (m); 5610 status = FAILURE; 5611 return FAILURE; 5612 } 5613 5614 // Check if new directory structure (i.e., no pointer file) 5615 if (dbe_stat (path, &sbuf)) 5616 { 5617 Emsg *m = new Emsg (CMSG_FATAL, GTXT ("*** Error: experiment not found")); 5618 errorq->append (m); 5619 status = FAILURE; 5620 return FAILURE; 5621 } 5622 if (S_ISDIR (sbuf.st_mode) == 0) 5623 { 5624 // ignore pointer-file experiments 5625 Emsg *m = new Emsg (CMSG_FATAL, 5626 GTXT ("*** Error: experiment was recorded with an earlier version, and can not be read")); 5627 errorq->append (m); 5628 obsolete = 1; 5629 status = FAILURE; 5630 return FAILURE; 5631 } 5632 return SUCCESS; 5633} 5634 5635void 5636Experiment::purge () 5637{ 5638 // This routine will purge all of the caches of releasable storage. 5639 for (int i = 0; i < dataDscrs->size (); ++i) 5640 { 5641 DataDescriptor *dataDscr = dataDscrs->fetch (i); 5642 if (dataDscr == NULL) 5643 continue; 5644 dataDscr->reset (); 5645 } 5646 delete cstack; 5647 delete cstackShowHide; 5648 cstack = CallStack::getInstance (this); 5649 cstackShowHide = CallStack::getInstance (this); 5650} 5651 5652void 5653Experiment::resetShowHideStack () 5654{ 5655 delete cstackShowHide; 5656 cstackShowHide = CallStack::getInstance (this); 5657} 5658 5659#define GET_INT_VAL(v, s, len) \ 5660 for (v = len = 0; isdigit(*s); s++, len++) { v = v * 10 + (*s -'0'); } 5661 5662static int 5663dir_name_cmp (const void *a, const void *b) 5664{ 5665 char *s1 = *((char **) a); 5666 char *s2 = *((char **) b); 5667 while (*s1) 5668 { 5669 if (isdigit (*s1) && isdigit (*s2)) 5670 { 5671 int v1, v2, len1, len2; 5672 GET_INT_VAL (v1, s1, len1); 5673 GET_INT_VAL (v2, s2, len2); 5674 if (v1 != v2) 5675 return v1 - v2; 5676 if (len1 != len2) 5677 return len2 - len1; 5678 continue; 5679 } 5680 if (*s1 != *s2) 5681 break; 5682 s1++; 5683 s2++; 5684 } 5685 return *s1 - *s2; 5686} 5687 5688Vector<char*> * 5689Experiment::get_descendants_names () 5690{ 5691 char *dir_name = get_expt_name (); 5692 if (dir_name == NULL) 5693 return NULL; 5694 DIR *exp_dir = opendir (dir_name); 5695 if (exp_dir == NULL) 5696 return NULL; 5697 Vector<char*> *exp_names = new Vector<char*>(); 5698 for (struct dirent *entry = readdir (exp_dir); entry; 5699 entry = readdir (exp_dir)) 5700 { 5701 if (entry->d_name[0] == '_' || strncmp (entry->d_name, "M_r", 3) == 0) 5702 { 5703 char *dpath = dbe_sprintf (NTXT ("%s/%s"), dir_name, entry->d_name); 5704 struct stat64 sbuf; 5705 if (dbe_stat (dpath, &sbuf) == 0 && S_ISDIR (sbuf.st_mode)) 5706 exp_names->append (dpath); 5707 else 5708 free (dpath); 5709 } 5710 } 5711 closedir (exp_dir); 5712 if (exp_names->size () == 0) 5713 { 5714 delete exp_names; 5715 return NULL; 5716 } 5717 exp_names->sort (dir_name_cmp); 5718 return exp_names; 5719} 5720 5721bool 5722Experiment::create_dir (char *dname) 5723{ 5724 if (mkdir (dname, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0) 5725 { 5726 return true; 5727 } 5728 struct stat64 sbuf; 5729 if (dbe_stat (dname, &sbuf) != 0 || S_ISDIR (sbuf.st_mode) == 0) 5730 { 5731 char *buf = dbe_sprintf (GTXT ("Unable to create directory `%s'\n"), 5732 dname); 5733 errorq->append (new Emsg (CMSG_ERROR, buf)); 5734 free (buf); 5735 return false; 5736 } 5737 return true; 5738} 5739 5740char * 5741Experiment::get_arch_name () 5742{ 5743 if (arch_name == NULL) 5744 { 5745 // Determine the master experiment directory. 5746 // omazur: should do it in a less hacky way. XXXX 5747 char *ptr = strstr_r (expt_name, DESCENDANT_EXPT_KEY); 5748 ptr = ptr ? ptr + 3 : expt_name + strlen (expt_name); 5749 arch_name = dbe_sprintf (NTXT ("%.*s/%s"), (int) (ptr - expt_name), 5750 expt_name, SP_ARCHIVES_DIR); 5751 } 5752 return arch_name; 5753} 5754 5755char * 5756Experiment::get_fndr_arch_name () 5757{ 5758 if (fndr_arch_name == NULL) 5759 // Determine the founder experiment directory. 5760 fndr_arch_name = dbe_strdup (get_arch_name ()); 5761 return fndr_arch_name; 5762} 5763 5764enum 5765{ 5766 HASH_NAME_LEN = 11 // (64 / 6 + 1) = 11 5767}; 5768 5769static char * 5770get_hash_string (char buf[HASH_NAME_LEN + 1], uint64_t hash) 5771{ 5772 static const char *har = 5773 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"; 5774 for (int i = 0; i < HASH_NAME_LEN; i++) 5775 { 5776 buf[i] = har[hash & 0x3f]; 5777 hash = hash >> 6; 5778 } 5779 buf[HASH_NAME_LEN] = 0; 5780 return buf; 5781} 5782 5783char * 5784Experiment::getNameInArchive (const char *fname, bool archiveFile) 5785{ 5786 char *aname = get_archived_name (fname, archiveFile); 5787 char *ret = dbe_sprintf (NTXT ("%s/%s"), get_arch_name (), aname); 5788 free (aname); 5789 return ret; 5790} 5791 5792#define MAX_ARCHIVE_FILENAME_LEN (256 - HASH_NAME_LEN - 2) 5793 5794char * 5795Experiment::get_archived_name (const char *fname, bool archiveFile) 5796{ 5797 char *bname = get_basename (fname); 5798 5799 // dirname_hash: 5800 char dirnameHash[HASH_NAME_LEN + 1]; 5801 // Treat "a.out" and "./a.out" equally 5802 uint64_t hash = bname != fname ? crc64 (fname, bname - fname) 5803 : crc64 (NTXT ("./"), 2); 5804 get_hash_string (dirnameHash, hash); 5805 5806 char *ret; 5807 long bname_len = dbe_sstrlen (bname); 5808 if (bname_len > MAX_ARCHIVE_FILENAME_LEN) 5809 { 5810 char basenameHash[HASH_NAME_LEN + 1]; 5811 hash = crc64 (bname, bname_len); 5812 get_hash_string (basenameHash, hash); 5813 ret = dbe_sprintf ("%.*s%c%s_%s", 5814 MAX_ARCHIVE_FILENAME_LEN - HASH_NAME_LEN - 1, 5815 bname, archiveFile ? '.' : '_', 5816 dirnameHash, basenameHash); 5817 } 5818 else 5819 ret = dbe_sprintf ("%s%c%s", bname, archiveFile ? '.' : '_', dirnameHash); 5820 return ret; 5821} 5822 5823char * 5824Experiment::checkFileInArchive (const char *fname, bool archiveFile) 5825{ 5826 if (archiveMap) 5827 { 5828 char *aname = get_archived_name (fname, archiveFile); 5829 DbeFile *df = archiveMap->get (aname); 5830 free (aname); 5831 if (df) 5832 return strdup (df->get_location ()); 5833 return NULL; 5834 } 5835 if (founder_exp) 5836 return founder_exp->checkFileInArchive (fname, archiveFile); 5837 return NULL; 5838} 5839 5840 5841// Comparing SegMem 5842 5843static int 5844SegMemCmp (const void *a, const void *b) 5845{ 5846 SegMem *item1 = *((SegMem **) a); 5847 SegMem *item2 = *((SegMem **) b); 5848 return item1->unload_time > item2->unload_time ? 1 : 5849 item1->unload_time == item2->unload_time ? 0 : -1; 5850} 5851 5852SegMem* 5853Experiment::update_ts_in_maps (Vaddr addr, hrtime_t ts) 5854{ 5855 Vector<SegMem *> *segMems = (Vector<SegMem *> *) maps->values (); 5856 if (!segMems->is_sorted ()) 5857 { 5858 Dprintf (DEBUG_MAPS, NTXT ("update_ts_in_maps: segMems.size=%lld\n"), (long long) segMems->size ()); 5859 segMems->sort (SegMemCmp); 5860 } 5861 for (int i = 0, sz = segMems ? segMems->size () : 0; i < sz; i++) 5862 { 5863 SegMem *sm = segMems->fetch (i); 5864 if (ts < sm->unload_time) 5865 { 5866 for (; i < sz; i++) 5867 { 5868 sm = segMems->fetch (i); 5869 if ((addr >= sm->base) && (addr < sm->base + sm->size)) 5870 { 5871 Dprintf (DEBUG_MAPS, 5872 "update_ts_in_maps: old:%u.%09u -> %u.%09u addr=0x%08llx size=%lld\n", 5873 (unsigned) (sm->load_time / NANOSEC), 5874 (unsigned) (sm->load_time % NANOSEC), 5875 (unsigned) (ts / NANOSEC), (unsigned) (ts % NANOSEC), 5876 (unsigned long long) sm->base, (long long) sm->size); 5877 maps->remove (sm->base, sm->load_time); 5878 sm->load_time = ts; 5879 maps->insert (sm->base, ts, sm); 5880 return sm; 5881 } 5882 } 5883 } 5884 } 5885 Dprintf (DEBUG_MAPS, "update_ts_in_maps: NOT FOUND %u.%09u addr=0x%08llx\n", 5886 (unsigned) (ts / NANOSEC), (unsigned) (ts % NANOSEC), 5887 (unsigned long long) addr); 5888 return NULL; 5889} 5890 5891DbeInstr* 5892Experiment::map_Vaddr_to_PC (Vaddr addr, hrtime_t ts) 5893{ 5894 // Look up in the hash table first 5895 int hash = (((int) addr) >> 8) & (HTableSize - 1); 5896 SegMem *si = smemHTable[hash]; 5897 if (si == NULL || addr < si->base || addr >= si->base + si->size 5898 || ts < si->load_time || ts >= si->unload_time) 5899 { 5900 // Not in the hash table 5901 si = (SegMem*) maps->locate (addr, ts); 5902 if (si == NULL || addr < si->base || addr >= si->base + si->size 5903 || ts < si->load_time || ts >= si->unload_time) 5904 { 5905 si = update_ts_in_maps (addr, ts); 5906 if (si == NULL) 5907 return dbeSession->get_Unknown_Function ()->find_dbeinstr (PCInvlFlag, addr); 5908 } 5909 smemHTable[hash] = si; 5910 } 5911 5912 // Calculate the file offset of 'addr' 5913 uint64_t f_offset = si->get_file_offset () + (addr - si->base); 5914 5915 DbeInstr *instr; 5916 if (si->obj->get_type () == Histable::LOADOBJECT) 5917 { 5918 LoadObject *lo = (LoadObject*) si->obj; 5919 lo->sync_read_stabs (); 5920 instr = lo->find_dbeinstr (f_offset); 5921 } 5922 else 5923 { 5924 int hash2 = ((((int) addr) & 0xFFFC00) | (((int) f_offset) >> 2)) 5925 & (HTableSize - 1); 5926 instr = instHTable[hash2]; 5927 if (instr == NULL || instr->func != si->obj || instr->addr != f_offset) 5928 { 5929 // Not in the hash table 5930 Function *fp = (Function *) si->obj; 5931 instr = fp->find_dbeinstr (0, f_offset); 5932 instHTable[hash2] = instr; 5933 } 5934 } 5935 if (!instr->func->isUsed) 5936 { 5937 instr->func->isUsed = true; 5938 instr->func->module->isUsed = true; 5939 instr->func->module->loadobject->isUsed = true; 5940 } 5941 return instr; 5942} 5943 5944Sample * 5945Experiment::map_event_to_Sample (hrtime_t ts) 5946{ 5947 Sample *sample; 5948 int index; 5949 5950 // Check if the last used sample is the right one, 5951 // if not then find it. 5952 if (sample_last_used && ts >= sample_last_used->start_time 5953 && ts <= sample_last_used->end_time) 5954 return sample_last_used; 5955 5956 Vec_loop (Sample*, samples, index, sample) 5957 { 5958 if ((ts >= sample->start_time) && 5959 (ts <= sample->end_time)) 5960 { 5961 sample_last_used = sample; 5962 return sample; 5963 } 5964 } 5965 return (Sample*) NULL; 5966} 5967 5968GCEvent * 5969Experiment::map_event_to_GCEvent (hrtime_t ts) 5970{ 5971 GCEvent *gcevent; 5972 int index; 5973 5974 // Check if the last used sample is the right one, 5975 // if not then find it. 5976 if (gcevent_last_used && ts >= gcevent_last_used->start 5977 && ts <= gcevent_last_used->end) 5978 return gcevent_last_used; 5979 Vec_loop (GCEvent*, gcevents, index, gcevent) 5980 { 5981 if ((ts >= gcevent->start) && 5982 (ts <= gcevent->end)) 5983 { 5984 gcevent_last_used = gcevent; 5985 return gcevent; 5986 } 5987 } 5988 return (GCEvent*) NULL; 5989} 5990 5991DbeInstr* 5992Experiment::map_jmid_to_PC (Vaddr mid, int bci, hrtime_t ts) 5993{ 5994 if (mid == 0 || jmaps == NULL) 5995 // special case: no Java stack was recorded, bci - error code 5996 return dbeSession->get_JUnknown_Function ()->find_dbeinstr (0, bci); 5997 5998 JMethod *jmthd = jmidHTable->get (mid); 5999 if (jmthd == NULL) 6000 { 6001 jmthd = (JMethod *) jmaps->locate_exact_match (mid, ts); 6002 if (jmthd) 6003 jmidHTable->put (mid, jmthd); 6004 } 6005 if (jmthd == NULL || jmthd->get_type () != Histable::FUNCTION) 6006 return dbeSession->get_JUnknown_Function ()->find_dbeinstr (0, (uint64_t) mid); 6007 return jmthd->find_dbeinstr (0, bci); 6008} 6009 6010Emsg * 6011Experiment::fetch_comments () 6012{ 6013 return commentq->fetch (); 6014} 6015 6016Emsg * 6017Experiment::fetch_runlogq () 6018{ 6019 return runlogq->fetch (); 6020} 6021 6022Emsg * 6023Experiment::fetch_errors () 6024{ 6025 return errorq->fetch (); 6026} 6027 6028Emsg * 6029Experiment::fetch_warnings () 6030{ 6031 return warnq->fetch (); 6032} 6033 6034Emsg * 6035Experiment::fetch_notes () 6036{ 6037 return notesq->fetch (); 6038} 6039 6040Emsg * 6041Experiment::fetch_ifreq () 6042{ 6043 return ifreqq->fetch (); 6044} 6045 6046Emsg * 6047Experiment::fetch_pprocq () 6048{ 6049 return pprocq->fetch (); 6050} 6051 6052int 6053Experiment::read_dyntext_file () 6054{ 6055 char *data_file_name = dbe_sprintf ("%s/%s", expt_name, SP_DYNTEXT_FILE); 6056 Data_window *dwin = new Data_window (data_file_name); 6057 if (dwin->not_opened ()) 6058 { 6059 free (data_file_name); 6060 delete dwin; 6061 return 1; 6062 } 6063 dwin->need_swap_endian = need_swap_endian; 6064 6065 Function *fp = NULL; 6066 char *progress_msg = NULL; // Message for the progress bar 6067 for (int64_t offset = 0;;) 6068 { 6069 DT_common *cpckt = (DT_common *) dwin->bind (offset, sizeof (DT_common)); 6070 if (cpckt == NULL) 6071 break; 6072 size_t cpcktsize = dwin->decode (cpckt->size); 6073 cpckt = (DT_common *) dwin->bind (offset, cpcktsize); 6074 if (cpckt == NULL) 6075 break; 6076 switch (dwin->decode (cpckt->type)) 6077 { 6078 case DT_HEADER: 6079 { 6080 DT_header *hdr = (DT_header*) cpckt; 6081 hrtime_t ts = dwin->decode (hdr->time) + exp_start_time; 6082 SegMem *si = (SegMem*) maps->locate (dwin->decode (hdr->vaddr), ts); 6083 fp = si ? (Function *) si->obj : NULL; 6084 if (fp && (fp->get_type () != Histable::FUNCTION 6085 || !(fp->flags & FUNC_FLAG_DYNAMIC))) 6086 fp = NULL; 6087 break; 6088 } 6089 case DT_CODE: 6090 if (fp) 6091 { 6092 fp->img_fname = data_file_name; 6093 fp->img_offset = offset + sizeof (DT_common); 6094 if ((platform != Intel) && (platform != Amd64)) 6095 { //ARCH(SPARC) 6096 // Find out 'save' instruction address for SPARC 6097 char *ptr = ((char*) cpckt) + sizeof (DT_common); 6098 size_t img_size = cpcktsize - sizeof (DT_common); 6099 for (size_t i = 0; i < img_size; i += 4) 6100 if (ptr[i] == (char) 0x9d && ptr[i + 1] == (char) 0xe3) 6101 { 6102 fp->save_addr = i; 6103 break; 6104 } 6105 } 6106 } 6107 break; 6108 case DT_SRCFILE: 6109 if (fp) 6110 { 6111 char *srcname = dbe_strndup (((char*) cpckt) + sizeof (DT_common), 6112 cpcktsize - sizeof (DT_common)); 6113 LoadObject *ds = fp->module ? fp->module->loadobject : NULL; 6114 assert (ds != NULL); 6115 Module *mod = dbeSession->createModule (ds, NULL); 6116 mod->set_file_name (srcname); 6117 //} 6118 if (fp->module) 6119 { 6120 // It's most likely (unknown). Remove fp from it. 6121 long idx = fp->module->functions->find (fp); 6122 if (idx >= 0) 6123 fp->module->functions->remove (idx); 6124 } 6125 fp->module = mod; 6126 mod->functions->append (fp); 6127 } 6128 break; 6129 case DT_LTABLE: 6130 if (fp) 6131 { 6132 DT_lineno *ltab = (DT_lineno*) ((char*) cpckt + sizeof (DT_common)); 6133 size_t sz = (cpcktsize - sizeof (DT_common)) / sizeof (DT_lineno); 6134 if (sz <= 0) 6135 break; 6136 // Take care of the progress bar 6137 static int percent = 0; 6138 static long deltaReport = sz / 100; // 1000; 6139 static long nextReport = 0; 6140 static long progress_count = 0; 6141 fp->pushSrcFile (fp->getDefSrc (), 0); 6142 for (size_t i = 0; i < sz; i++) 6143 { 6144 int lineno = dwin->decode (ltab[i].lineno); 6145 if (fp->usrfunc != NULL) 6146 { 6147 // Update progress bar 6148 if (dbeSession->is_interactive ()) 6149 { 6150 if (progress_count == nextReport) 6151 { 6152 if (percent < 99) 6153 { 6154 percent++; 6155 if (NULL == progress_msg) 6156 { 6157 progress_msg = dbe_sprintf (GTXT ("Processing Dynamic Text: %s"), 6158 get_basename (expt_name)); 6159 } 6160 theApplication->set_progress (percent, progress_msg); 6161 nextReport += deltaReport; 6162 } 6163 } 6164 progress_count++; 6165 } 6166 DbeLine *dbeline = fp->usrfunc->mapPCtoLine (lineno, NULL); 6167 lineno = dbeline != NULL ? dbeline->lineno : -1; 6168 } 6169 fp->add_PC_info (dwin->decode (ltab[i].offset), lineno); 6170 } 6171 fp->popSrcFile (); 6172 } 6173 break; 6174 default: 6175 // skip unknown records 6176 break; 6177 } 6178 offset += cpcktsize; 6179 } 6180 free (progress_msg); 6181 free (data_file_name); 6182 delete dwin; 6183 return 0; 6184} 6185 6186uint32_t 6187Experiment::mapTagValue (Prop_type prop, uint64_t value) 6188{ 6189 Vector<Histable*> *objs = tagObjs->fetch (prop); 6190 int lt = 0; 6191 int rt = objs->size () - 1; 6192 while (lt <= rt) 6193 { 6194 int md = (lt + rt) / 2; 6195 Other *obj = (Other*) objs->fetch (md); 6196 if (obj->value64 < value) 6197 lt = md + 1; 6198 else if (obj->value64 > value) 6199 rt = md - 1; 6200 else 6201 return obj->tag; 6202 } 6203 6204 uint32_t tag; 6205 if (sparse_threads && (prop == PROP_THRID || prop == PROP_LWPID)) 6206 tag = objs->size () + 1; // "+ 1" related to 7038295 6207 else 6208 tag = (int) value; // truncation; See 6788767 6209 6210 Other *obj = new Other (); 6211 obj->value64 = value; 6212 obj->tag = tag; 6213 if (lt == objs->size ()) 6214 objs->append (obj); 6215 else 6216 objs->insert (lt, obj); 6217 6218 // Update min and max tags 6219 if (prop == PROP_LWPID) 6220 { 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; 6225 lwp_cnt++; 6226 } 6227 else if (prop == PROP_THRID) 6228 { 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; 6233 thread_cnt++; 6234 } 6235 else if (prop == PROP_CPUID) 6236 { 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; 6244 } 6245 cpu_cnt++; 6246 } 6247 return obj->tag; 6248} 6249 6250Vector<Histable*> * 6251Experiment::getTagObjs (Prop_type prop) 6252{ 6253 return tagObjs->fetch (prop); 6254} 6255 6256Histable * 6257Experiment::getTagObj (Prop_type prop, uint32_t tag) 6258{ 6259 Vector<Histable*> *objs = tagObjs->fetch (prop); 6260 if (objs == NULL) 6261 return NULL; 6262 for (int i = 0; i < objs->size (); i++) 6263 { 6264 Other *obj = (Other*) objs->fetch (i); 6265 if (obj->tag == tag) 6266 return obj; 6267 } 6268 return NULL; 6269} 6270 6271JThread * 6272Experiment::map_pckt_to_Jthread (uint32_t tid, hrtime_t tstamp) 6273{ 6274 if (!has_java) 6275 return JTHREAD_DEFAULT; 6276 int lt = 0; 6277 int rt = jthreads_idx->size () - 1; 6278 while (lt <= rt) 6279 { 6280 int md = (lt + rt) / 2; 6281 JThread *jthread = jthreads_idx->fetch (md); 6282 if (jthread->tid < tid) 6283 lt = md + 1; 6284 else if (jthread->tid > tid) 6285 rt = md - 1; 6286 else 6287 { 6288 for (; jthread; jthread = jthread->next) 6289 if (tstamp >= jthread->start && tstamp < jthread->end) 6290 return jthread; 6291 break; 6292 } 6293 } 6294 6295 return JTHREAD_NONE; 6296} 6297 6298JThread* 6299Experiment::get_jthread (uint32_t tid) 6300{ 6301 if (!has_java) 6302 return JTHREAD_DEFAULT; 6303 int lt = 0; 6304 int rt = jthreads_idx->size () - 1; 6305 while (lt <= rt) 6306 { 6307 int md = (lt + rt) / 2; 6308 JThread *jthread = jthreads_idx->fetch (md); 6309 if (jthread->tid < tid) 6310 lt = md + 1; 6311 else if (jthread->tid > tid) 6312 rt = md - 1; 6313 else 6314 { 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; 6321 } 6322 } 6323 6324 return JTHREAD_NONE; 6325} 6326 6327// SS12 experiment 6328DataDescriptor * 6329Experiment::newDataDescriptor (int data_id, int flags, 6330 DataDescriptor *master_dDscr) 6331{ 6332 DataDescriptor *dataDscr = NULL; 6333 if (data_id >= 0 && data_id < dataDscrs->size ()) 6334 { 6335 dataDscr = dataDscrs->fetch (data_id); 6336 if (dataDscr != NULL) 6337 return dataDscr; 6338 } 6339 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); 6343 6344 if (master_dDscr) 6345 dataDscr = new DataDescriptor (data_id, nm, uname, master_dDscr); 6346 else 6347 dataDscr = new DataDescriptor (data_id, nm, uname, flags); 6348 dataDscrs->store (data_id, dataDscr); 6349 return dataDscr; 6350} 6351 6352Vector<DataDescriptor*> * 6353Experiment::getDataDescriptors () 6354{ 6355 Vector<DataDescriptor*> *result = new Vector<DataDescriptor*>; 6356 for (int i = 0; i < dataDscrs->size (); ++i) 6357 { 6358 DataDescriptor *dd; 6359 dd = get_raw_events (i); // force data fetch 6360 if (dd != NULL) 6361 result->append (dd); 6362 } 6363 return result; 6364} 6365 6366DataDescriptor * 6367Experiment::getDataDescriptor (int data_id) 6368{ 6369 if (data_id < 0 || data_id >= dataDscrs->size ()) 6370 return NULL; 6371 return dataDscrs->fetch (data_id); 6372} 6373 6374PacketDescriptor * 6375Experiment::newPacketDescriptor (int kind, DataDescriptor *dDscr) 6376{ 6377 PacketDescriptor *pDscr = new PacketDescriptor (dDscr); 6378 pcktDscrs->store (kind, pDscr); 6379 return pDscr; 6380} 6381 6382PacketDescriptor * 6383Experiment::getPacketDescriptor (int kind) 6384{ 6385 if (kind < 0 || kind >= pcktDscrs->size ()) 6386 return NULL; 6387 return pcktDscrs->fetch (kind); 6388} 6389 6390void 6391Experiment::set_clock (int clk) 6392{ 6393 if (clk > 0) 6394 { 6395 if (maxclock < clk) 6396 { 6397 maxclock = clk; 6398 clock = maxclock; 6399 } 6400 if (minclock == 0 || minclock > clk) 6401 minclock = clk; 6402 } 6403} 6404 6405bool 6406JThread::is_system () 6407{ 6408 if (group_name == NULL) 6409 return false; 6410 return strcmp (group_name, NTXT ("system")) == 0; 6411} 6412 6413void 6414Experiment::dump_stacks (FILE *outfile) 6415{ 6416 cstack->print (outfile); 6417} 6418 6419void 6420Experiment::dump_map (FILE *outfile) 6421{ 6422 int index; 6423 SegMem *s; 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) 6427 { 6428 timestruc_t load; 6429 timestruc_t unload; 6430 hr2timestruc (&load, (s->load_time - exp_start_time)); 6431 if (load.tv_nsec < 0) 6432 { 6433 load.tv_sec--; 6434 load.tv_nsec += NANOSEC; 6435 } 6436 if (s->unload_time == MAX_TIME) 6437 { 6438 unload.tv_sec = 0; 6439 unload.tv_nsec = 0; 6440 } 6441 else 6442 hr2timestruc (&unload, (s->unload_time - exp_start_time)); 6443 if (load.tv_nsec < 0) 6444 { 6445 load.tv_sec--; 6446 load.tv_nsec += NANOSEC; 6447 } 6448 fprintf (outfile, 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 ()); 6454 } 6455 fprintf (outfile, NTXT ("\n")); 6456} 6457 6458/** 6459 * Copy file to archive 6460 * @param name 6461 * @param aname 6462 * @param hide_msg 6463 * @return 0 - success, 1 - error 6464 */ 6465int 6466Experiment::copy_file_to_archive (const char *name, const char *aname, int hide_msg) 6467{ 6468 errno = 0; 6469 int fd_w = open64 (aname, O_WRONLY | O_CREAT | O_EXCL, 0644); 6470 if (fd_w == -1) 6471 { 6472 if (errno == EEXIST) 6473 return 0; 6474 fprintf (stderr, GTXT ("er_archive: unable to copy `%s': %s\n"), 6475 name, STR (strerror (errno))); 6476 return 1; 6477 } 6478 6479 if (dbe_stat_file (name, NULL) != 0) 6480 { 6481 fprintf (stderr, GTXT ("er_archive: cannot access file `%s': %s\n"), 6482 name, STR (strerror (errno))); 6483 close (fd_w); 6484 return 1; 6485 } 6486 6487 int fd_r = open64 (name, O_RDONLY); 6488 if (fd_r == -1) 6489 { 6490 fprintf (stderr, GTXT ("er_archive: unable to open `%s': %s\n"), 6491 name, strerror (errno)); 6492 close (fd_w); 6493 unlink (aname); 6494 return 1; 6495 } 6496 6497 if (!hide_msg) 6498 fprintf (stderr, GTXT ("Copying `%s' to `%s'\n"), name, aname); 6499 bool do_unlink = false; 6500 for (;;) 6501 { 6502 unsigned char buf[65536]; 6503 int n, n1; 6504 n = (int) read (fd_r, (void *) buf, sizeof (buf)); 6505 if (n <= 0) 6506 break; 6507 n1 = (int) write (fd_w, buf, n); 6508 if (n != n1) 6509 { 6510 fprintf (stderr, GTXT ("er_archive: unable to write %d bytes to `%s': %s\n"), 6511 n, aname, STR (strerror (errno))); 6512 do_unlink = true; 6513 break; 6514 } 6515 } 6516 close (fd_w); 6517 6518 struct stat64 s_buf; 6519 if (fstat64 (fd_r, &s_buf) == 0) 6520 { 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); 6525 } 6526 close (fd_r); 6527 if (do_unlink) 6528 { 6529 if (!hide_msg) 6530 fprintf (stderr, GTXT ("er_archive: remove %s\n"), aname); 6531 unlink (aname); 6532 return 1; 6533 } 6534 return 0; 6535} 6536 6537/** 6538 * Copy file to common archive 6539 * Algorithm: 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 6549 */ 6550int 6551Experiment::copy_file_to_common_archive (const char *name, const char *aname, 6552 int hide_msg, 6553 const char *common_archive, 6554 int relative_path) 6555{ 6556 if (!name || !aname || !common_archive) 6557 { 6558 if (!name) 6559 fprintf (stderr, GTXT ("er_archive: Internal error: file name is NULL\n")); 6560 if (!aname) 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")); 6564 return 1; 6565 } 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 6570 char *cad = NULL; 6571 char *abs_aname = NULL; 6572 if ((common_archive[0] != '/') || (aname[0] != '/')) 6573 { 6574 long size = pathconf (NTXT ("."), _PC_PATH_MAX); 6575 if (size < 0) 6576 { 6577 fprintf (stderr, GTXT ("er_archive: Fatal error: pathconf(\".\", _PC_PATH_MAX) failed\n")); 6578 return 1; 6579 } 6580 char *buf = (char *) malloc ((size_t) size); 6581 if (buf == NULL) 6582 { 6583 fprintf (stderr, GTXT ("er_archive: Fatal error: unable to allocate memory\n")); 6584 return 1; 6585 } 6586 char *ptr = getcwd (buf, (size_t) size); 6587 if (ptr == NULL) 6588 { 6589 fprintf (stderr, GTXT ("er_archive: Fatal error: cannot determine current directory\n")); 6590 free (buf); 6591 return 1; 6592 } 6593 if (common_archive[0] != '/') 6594 cad = dbe_sprintf (NTXT ("%s/%s"), ptr, common_archive); 6595 else 6596 cad = dbe_strdup (common_archive); 6597 if (aname[0] != '/') 6598 abs_aname = dbe_sprintf (NTXT ("%s/%s"), ptr, aname); 6599 else 6600 abs_aname = dbe_strdup (aname); 6601 free (buf); 6602 } 6603 else 6604 { 6605 cad = dbe_strdup (common_archive); 6606 abs_aname = dbe_strdup (aname); 6607 } 6608 // Calculate checksum 6609 char * errmsg = NULL; 6610 uint32_t crcval = get_cksum (name, &errmsg); 6611 if (0 == crcval) 6612 { // error 6613 free (cad); 6614 free (abs_aname); 6615 if (NULL != errmsg) 6616 { 6617 fprintf (stderr, GTXT ("er_archive: Fatal error: %s\n"), errmsg); 6618 free (errmsg); 6619 return 1; 6620 } 6621 fprintf (stderr, 6622 GTXT ("er_archive: Fatal error: get_cksum(%s) returned %d\n"), 6623 name, crcval); 6624 return 1; 6625 } 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) 6630 { 6631 free (cad); 6632 free (abs_aname); 6633 fprintf (stderr, 6634 GTXT ("er_archive: Fatal error: unable to allocate memory\n")); 6635 return 1; 6636 } 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)) 6641 { // unknown error 6642 fprintf (stderr, GTXT ("er_archive: Fatal error: pathconf(%s, _PC_PATH_MAX) failed\n"), 6643 cad); 6644 free (abs_caname); 6645 free (cad); 6646 free (abs_aname); 6647 return 1; 6648 } 6649 if (len >= max) 6650 { 6651 // Try to truncate the name 6652 if ((len - max) <= dbe_sstrlen (fname)) 6653 { 6654 // Yes, we can do it 6655 abs_caname[max - 1] = 0; 6656 if (!hide_msg) 6657 fprintf (stderr, GTXT ("er_archive: file path is too long - truncated:%s\n"), 6658 abs_caname); 6659 } 6660 } 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)) 6666 { // unknown error 6667 fprintf (stderr, GTXT ("er_archive: Fatal error: pathconf(%s, _PC_NAME_MAX) failed\n"), 6668 cad); 6669 free (abs_caname); 6670 free (cad); 6671 free (abs_aname); 6672 return 1; 6673 } 6674 if (len >= max) 6675 { 6676 // Try to truncate the name 6677 if ((len - max) <= dbe_sstrlen (fname)) 6678 { 6679 // Yes, we can do it 6680 cafname[max - 1] = 0; 6681 if (!hide_msg) 6682 fprintf (stderr, GTXT ("er_archive: file name is too long - truncated:%s\n"), 6683 abs_caname); 6684 } 6685 } 6686 // Copy file to the common archive directory if it is not there yet 6687 int res = 0; 6688 if (dbe_stat_file (abs_caname, NULL) != 0) 6689 { 6690 // Use temporary file to avoid synchronization problems 6691 char *t = dbe_sprintf ("%s/archive_%llx", cad, (unsigned long long) gethrtime()); 6692 free (cad); 6693 // Copy file to temporary file 6694 res = copy_file_to_archive (name, t, hide_msg); // hide messages 6695 if (res != 0) 6696 { 6697 fprintf (stderr, GTXT ("er_archive: Fatal error: cannot copy file %s to temporary file: %s\n"), 6698 name, t); 6699 unlink (t); 6700 free (t); 6701 free (abs_caname); 6702 free (abs_aname); 6703 return 1; 6704 } 6705 // Set read-only permissions 6706 struct stat64 statbuf; 6707 if (0 == dbe_stat_file (name, &statbuf)) 6708 { 6709 mode_t mask = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 6710 mode_t mode = statbuf.st_mode & mask; 6711 chmod (t, mode); 6712 } 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); 6716 if (res != 0) 6717 { 6718 if (errno != EEXIST) 6719 { 6720 fprintf (stderr, GTXT ("er_archive: Fatal error: rename(%s, %s) returned error: %d\n"), 6721 t, abs_caname, res); 6722 unlink (t); 6723 free (t); 6724 free (abs_caname); 6725 free (abs_aname); 6726 return 1; 6727 } 6728 // File "abs_caname" is already there - continue 6729 } 6730 unlink (t); 6731 free (t); 6732 } 6733 else 6734 free (cad); 6735 char *lname = NULL; 6736 if (relative_path) 6737 { 6738 if (common_archive[0] != '/' && aname[0] != '/') 6739 { 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) 6743 { 6744 fprintf (stderr, GTXT ("er_archive: Fatal error: unable to allocate memory\n")); 6745 return 1; 6746 } 6747 lname = get_relative_link (rel_caname, aname); 6748 free (rel_caname); 6749 } 6750 else 6751 { 6752 if (abs_aname == NULL) 6753 { 6754 fprintf (stderr, GTXT ("er_archive: Fatal error: unable to allocate memory\n")); 6755 return 1; 6756 } 6757 lname = get_relative_link (abs_caname, abs_aname); 6758 } 6759 } 6760 else // absolute path 6761 lname = dbe_strdup (abs_caname); 6762 free (abs_aname); 6763 if (lname == NULL) 6764 { 6765 fprintf (stderr, GTXT ("er_archive: Fatal error: unable to allocate memory\n")); 6766 return 1; 6767 } 6768 // Create symbolic link: aname -> lname 6769 if (dbe_stat_file (abs_caname, NULL) == 0) 6770 { 6771 res = symlink (lname, aname); 6772 if (res != 0) 6773 { 6774 fprintf (stderr, GTXT ("er_archive: Fatal error: symlink(%s, %s) returned error: %d (errno=%s)\n"), 6775 lname, aname, res, strerror (errno)); 6776 free (abs_caname); 6777 free (lname); 6778 return 1; 6779 } 6780 if (!hide_msg) 6781 fprintf (stderr, GTXT ("Created symbolic link %s to file in common archive: %s\n"), 6782 aname, lname); 6783 } 6784 else 6785 { 6786 fprintf (stderr, GTXT ("er_archive: Internal error: file does not exist in common archive: %s\n"), 6787 abs_caname); 6788 res = 1; 6789 } 6790 free (abs_caname); 6791 free (lname); 6792 return res; 6793} 6794 6795/** 6796 * Copy file to archive 6797 * @param name 6798 * @param aname 6799 * @param hide_msg 6800 * @param common_archive 6801 * @return 0 - success 6802 */ 6803int 6804Experiment::copy_file (char *name, char *aname, int hide_msg, char *common_archive, int relative_path) 6805{ 6806 if (common_archive) 6807 { 6808 if (0 == copy_file_to_common_archive (name, aname, hide_msg, 6809 common_archive, relative_path)) 6810 return 0; 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); 6814 return 1; 6815 } 6816 return (copy_file_to_archive (name, aname, hide_msg)); 6817} 6818 6819LoadObject * 6820Experiment::createLoadObject (const char *path, uint64_t chksum) 6821{ 6822 LoadObject *lo = dbeSession->createLoadObject (path, chksum); 6823 if (lo->firstExp == NULL) 6824 lo->firstExp = this; 6825 return lo; 6826} 6827 6828LoadObject * 6829Experiment::createLoadObject (const char *path, const char *runTimePath) 6830{ 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)) 6836 { 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; 6842 } 6843 if (lo->firstExp == NULL) 6844 { 6845 lo->firstExp = this; 6846 lo->dbeFile->experiment = this; 6847 } 6848 return lo; 6849} 6850 6851SourceFile * 6852Experiment::get_source (const char *path) 6853{ 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) 6859 path += 2; 6860 SourceFile *sf = sourcesMap->get (path); 6861 if (sf) 6862 return sf; 6863 char *fnm = checkFileInArchive (path, false); 6864 if (fnm) 6865 { 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 6873 free (fnm); 6874 } 6875 else 6876 sf = dbeSession->createSourceFile (path); 6877 sourcesMap->put (path, sf); 6878 return sf; 6879} 6880 6881Vector<Histable*> * 6882Experiment::get_comparable_objs () 6883{ 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++) 6889 { 6890 ExpGroup *gr = dbeSession->expGroups->get (i); 6891 if (groupId == gr->groupId) 6892 { 6893 comparable_objs->append (this); 6894 continue; 6895 } 6896 Histable *h = NULL; 6897 for (long i1 = 0, sz1 = gr->exps ? gr->exps->size () : 0; i1 < sz1; i1++) 6898 { 6899 Experiment *exp = gr->exps->get (i1); 6900 if ((exp->comparable_objs == NULL) && (dbe_strcmp (utargname, exp->utargname) == 0)) 6901 { 6902 exp->phaseCompareIdx = phaseCompareIdx; 6903 h = exp; 6904 h->comparable_objs = comparable_objs; 6905 break; 6906 } 6907 } 6908 comparable_objs->append (h); 6909 } 6910 dump_comparable_objs (); 6911 return comparable_objs; 6912} 6913 6914DbeFile * 6915Experiment::findFileInArchive (const char *fname) 6916{ 6917 if (archiveMap) 6918 { 6919 char *aname = get_archived_name (fname); 6920 DbeFile *df = archiveMap->get (aname); 6921 free (aname); 6922 return df; 6923 } 6924 if (founder_exp) 6925 return founder_exp->findFileInArchive (fname); 6926 return NULL; 6927} 6928 6929DbeFile * 6930Experiment::findFileInArchive (const char *className, const char *runTimePath) 6931{ 6932 DbeFile *df = NULL; 6933 if (runTimePath) 6934 { 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; 6940 if (fnm) 6941 { 6942 const char *s = strchr (fnm, '!'); 6943 if (s) 6944 { 6945 char *s1 = dbe_strndup (fnm, s - fnm); 6946 df = findFileInArchive (s1); 6947 free (s1); 6948 } 6949 else 6950 df = findFileInArchive (fnm); 6951 if (df) 6952 df->filetype |= DbeFile::F_JAR_FILE; 6953 } 6954 else if (strncmp (runTimePath, NTXT ("file:"), 5) == 0) 6955 { 6956 fnm = runTimePath + 5; 6957 df = findFileInArchive (fnm); 6958 } 6959 else 6960 df = findFileInArchive (runTimePath); 6961 } 6962 if (df == NULL) 6963 df = findFileInArchive (className); 6964 return df; 6965} 6966