]> Git Repo - binutils.git/blob - gprofng/src/MetricList.cc
Automatic date update in version.in
[binutils.git] / gprofng / src / MetricList.cc
1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2    Contributed by Oracle.
3
4    This file is part of GNU Binutils.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20
21 #include "config.h"
22 #include "util.h"
23 #include "Command.h"
24 #include "DbeSession.h"
25 #include "MetricList.h"
26 #include "StringBuilder.h"
27
28 //  Build a metric reference list
29 MetricList::MetricList (Vector<BaseMetric*> *base_metrics, MetricType _mtype)
30 {
31   mtype = _mtype;
32   items = new Vector<Metric*>;
33   sort_ref_index = 0;
34   sort_reverse = false;
35
36   Metric *mitem;
37   // loop over the base_metrics, and add in all the appropriate subtypes
38   for (long i = 0, sz = base_metrics ? base_metrics->size () : 0; i < sz; i++)
39     {
40       BaseMetric *mtr = base_metrics->get (i);
41       if (mtr->is_internal ())
42         continue;
43       switch (mtype)
44         {
45         case MET_DATA:
46           if ((mtr->get_flavors () & BaseMetric::DATASPACE) != 0)
47             {
48               mitem = new Metric (mtr, BaseMetric::DATASPACE);
49               items->append (mitem);
50             }
51           break;
52
53         case MET_INDX:
54           {
55             if ((mtr->get_flavors () & BaseMetric::INCLUSIVE) != 0
56                 || (mtr->get_flavors () & BaseMetric::EXCLUSIVE) != 0)
57               {
58                 int index2;
59                 Metric *item2 = NULL;
60                 bool found = false;
61                 Vec_loop (Metric*, items, index2, item2)
62                 {
63                   if (item2->get_subtype () == BaseMetric::EXCLUSIVE
64                       && dbe_strcmp (item2->get_cmd (), mtr->get_cmd ()) == 0)
65                     {
66                       found = true;
67                       break;
68                     }
69                 }
70                 if (found == false)
71                   {
72                     mitem = new Metric (mtr, BaseMetric::EXCLUSIVE);
73                     items->append (mitem);
74                   }
75               }
76           }
77           break;
78
79         case MET_CALL:
80         case MET_CALL_AGR:
81           if ((mtr->get_flavors () & BaseMetric::ATTRIBUTED) != 0)
82             {
83               mitem = new Metric (mtr, BaseMetric::ATTRIBUTED);
84               items->append (mitem);
85             }
86           // now fall through to add exclusive and inclusive
87
88         case MET_NORMAL:
89         case MET_COMMON:
90           if (mtr->get_flavors () & BaseMetric::EXCLUSIVE)
91             {
92               mitem = new Metric (mtr, BaseMetric::EXCLUSIVE);
93               items->append (mitem);
94             }
95           if (mtr->get_flavors () & BaseMetric::INCLUSIVE)
96             {
97               mitem = new Metric (mtr, BaseMetric::INCLUSIVE);
98               items->append (mitem);
99             }
100           break;
101         case MET_SRCDIS:
102           if (mtr->get_flavors () & BaseMetric::INCLUSIVE)
103             {
104               mitem = new Metric (mtr, BaseMetric::INCLUSIVE);
105               items->append (mitem);
106             }
107           break;
108         case MET_IO:
109           {
110             if (mtr->get_packet_type () == DATA_IOTRACE
111                 && ((mtr->get_flavors () & BaseMetric::INCLUSIVE) != 0
112                     || (mtr->get_flavors () & BaseMetric::EXCLUSIVE) != 0))
113               {
114                 int index2;
115                 Metric *item2 = NULL;
116                 bool found = false;
117                 Vec_loop (Metric*, items, index2, item2)
118                 {
119                   if (item2->get_subtype () == BaseMetric::EXCLUSIVE
120                       && dbe_strcmp (item2->get_cmd (), mtr->get_cmd ()) == 0)
121                     {
122                       found = true;
123                       break;
124                     }
125                 }
126                 if (found == false)
127                   {
128                     mitem = new Metric (mtr, BaseMetric::EXCLUSIVE);
129                     items->append (mitem);
130                   }
131               }
132           }
133           break;
134         case MET_HEAP:
135           {
136             if (mtr->get_packet_type () == DATA_HEAP
137                 && ((mtr->get_flavors () & BaseMetric::INCLUSIVE) != 0
138                     || (mtr->get_flavors () & BaseMetric::EXCLUSIVE) != 0))
139               {
140                 int index2;
141                 Metric *item2 = NULL;
142                 bool found = false;
143                 Vec_loop (Metric*, items, index2, item2)
144                 {
145                   if ((item2->get_subtype () == BaseMetric::EXCLUSIVE) &&
146                       (dbe_strcmp (item2->get_cmd (), mtr->get_cmd ()) == 0))
147                     {
148                       found = true;
149                       break;
150                     }
151                 }
152                 if (found == false)
153                   {
154                     mitem = new Metric (mtr, BaseMetric::EXCLUSIVE);
155                     items->append (mitem);
156                   }
157               }
158           }
159           break;
160         }
161
162       // add the static
163       if (mtr->get_flavors () & BaseMetric::STATIC)
164         {
165           switch (mtype)
166             {
167             case MET_NORMAL:
168             case MET_COMMON:
169             case MET_CALL:
170             case MET_CALL_AGR:
171             case MET_SRCDIS:
172               mitem = new Metric (mtr, BaseMetric::STATIC);
173               items->append (mitem);
174               break;
175             default:
176               if (mtr->get_type () == BaseMetric::ONAME)
177                 {
178                   mitem = new Metric (mtr, BaseMetric::STATIC);
179                   items->append (mitem);
180                 }
181               break;
182             }
183         }
184     }
185   // set all metrics visible
186   for (long i = 0, sz = items ? items->size () : 0; i < sz; i++)
187     items->get (i)->enable_all_visbits ();
188 }
189
190 // Constructor for an empty list -- items will be added one at a time
191 MetricList::MetricList (MetricType _mtype)
192 {
193   mtype = _mtype;
194   items = new Vector<Metric*>;
195   sort_ref_index = 0;
196   sort_reverse = false;
197 }
198
199 MetricList::~MetricList ()
200 {
201   Destroy (items);
202 }
203
204 // Duplicate a metric list
205 MetricList::MetricList (MetricList *old)
206 {
207   mtype = old->mtype;
208
209   // get an empty vector
210   items = new Vector<Metric*>;
211   Metric *item;
212   Metric *nitem;
213   int index;
214   sort_ref_index = old->get_sort_ref_index ();
215   sort_reverse = old->get_sort_rev ();
216   Vec_loop (Metric*, old->items, index, item)
217   {
218     nitem = new Metric (*item);
219     items->append (nitem);
220   }
221 }
222
223 // set_metrics:
224 //      Sets the particular metric list, according to the metric spec
225 //      If fromRcFile, updates dbeSession->get_reg_metrics_tree() with new defaults.
226 char *
227 MetricList::set_metrics (const char *mspec, bool fromRcFile,
228                          DerivedMetrics * /* derived_metrics */)
229 {
230   BaseMetric::SubType subtypes[10];
231   int nsubtypes;
232   int dmetrics_vis; // literal translation of metrics/dmetrics %.+
233   bool parseOK = false;
234   char *errbuf;
235   Vector<Metric*> *old_items = items;
236   items = new Vector<Metric*>;
237   Vector<BaseMetric*> *base_items = dbeSession->get_base_reg_metrics ();
238
239   // and copy the input specification
240   char *buf = dbe_strdup (mspec);
241
242   // append metric items from parsing the string
243   for (char *mcmd = strtok (buf, NTXT (":")); mcmd != NULL;
244           mcmd = strtok (NULL, NTXT (":")))
245     {
246       // parse the single metric_spec, based on the type of list being constructed, into:
247       //        a vector of SubTypes (any of [iead] or STATIC)
248       //        a integer mask for the visibility bits
249       //        and the string name of the base metric
250       //            it might be "all", "any", or "hwc" or it should match a metric in the list
251       //            it might also be "bit", meaning any bit-computed metric
252       char *mname = parse_metric_spec (mcmd, subtypes, &nsubtypes,
253                                        &dmetrics_vis, &parseOK);
254       if (!parseOK)
255         {
256           // error parsing the metric specification
257           // not from an rc file, it's an error
258           if (!fromRcFile)
259             {
260               delete base_items;
261               items->destroy ();
262               delete items;
263               items = old_items;
264               free (buf);
265               return mname;
266             }
267           continue;
268         }
269
270       // loop over subtypes requested
271       // set the visibility of and sort order according to the vis bits,
272       //        and the order of encounter in the processing
273       int ret = add_matching_dmetrics (base_items, mname, subtypes, nsubtypes,
274                                        dmetrics_vis, fromRcFile);
275       if (ret != 0 && !fromRcFile)
276         {
277           if (ret == 1)
278             errbuf = dbe_sprintf (GTXT ("No data recorded to support metric specification: %s\n"),
279                                   mcmd);
280           else
281             errbuf = dbe_sprintf (GTXT ("Metric specification for `%s' has appeared before in %s"),
282                                     mcmd, mspec);
283           delete base_items;
284           items->destroy ();
285           delete items;
286           items = old_items;
287           free (buf);
288           return errbuf;
289         }
290     } // we've processed the entire spec
291
292   // update metric defaults
293   if (fromRcFile)
294     {
295       for (long i = 0, sz = items->size (); i < sz; i++)
296         {
297           Metric *m = items->get (i);
298           int visbits = m->get_visbits ();
299           BaseMetric::SubType subtype = m->get_subtype ();
300           BaseMetric *reg_bm = m->get_base_metric ();
301           reg_bm->set_default_visbits (subtype, visbits);
302           BaseMetricTreeNode *mtree = dbeSession->get_reg_metrics_tree ();
303           BaseMetricTreeNode *bmtnode = mtree->register_metric (m);
304           BaseMetric *tree_bm = bmtnode->get_BaseMetric ();
305           tree_bm->set_default_visbits (subtype, visbits);
306         }
307     }
308
309   // ensure that name is present, remove hidden metrics
310   nsubtypes = 1;
311   for (long i = items->size () - 1; i >= 0; i--)
312     {
313       Metric *m = items->fetch (i);
314       if (!m->is_any_visible ())
315         {
316           delete m;
317           items->remove (i);
318           continue;
319         }
320       if (m->get_type () == BaseMetric::ONAME)
321         nsubtypes = 0;
322     }
323
324   // did we get at least one valid match?
325   if (items->size () == 0 && !fromRcFile)
326     {
327       errbuf = dbe_sprintf (GTXT ("No valid metrics specified in `%s'\n"), mspec);
328       delete base_items;
329       items->destroy ();
330       delete items;
331       items = old_items;
332       free (buf);
333       return errbuf;
334     }
335
336   if (nsubtypes == 1)
337     {
338       subtypes[0] = BaseMetric::STATIC;
339       (void) add_matching_dmetrics (base_items, NTXT ("name"), subtypes, 1, VAL_VALUE, true);
340     }
341
342   // replace the old list of items, with the new set
343   if (old_items)
344     {
345       old_items->destroy ();
346       delete old_items;
347     }
348   set_fallback_sort ();
349   free (buf);
350   delete base_items;
351   return NULL;
352 }
353
354 void
355 MetricList::set_fallback_sort ()
356 {
357   // sort by first visible of the appropriate flavor
358   char *sortcmd = NULL;
359   switch (mtype)
360     {
361     case MET_NORMAL:
362     case MET_COMMON:
363       sortcmd = NTXT ("ei.any:name");
364       break;
365     case MET_SRCDIS:
366       sortcmd = NTXT ("i.any:name");
367       break;
368     case MET_CALL:
369     case MET_CALL_AGR:
370       sortcmd = NTXT ("a.any:name");
371       break;
372     case MET_DATA:
373       sortcmd = NTXT ("d.any:name");
374       break;
375     case MET_INDX:
376       sortcmd = NTXT ("e.any:name");
377       break;
378     case MET_IO:
379       sortcmd = NTXT ("e.any:name");
380       break;
381     case MET_HEAP:
382       sortcmd = NTXT ("e.any:name");
383       break;
384     }
385   if (NULL != sortcmd)
386     (void) set_sort (sortcmd, true);
387 }
388
389 void
390 MetricList::set_metrics (MetricList *mlist)
391 {
392   // verify that the type is appropriate for the call
393   if (mtype == MET_NORMAL || mtype == MET_COMMON
394       || (mlist->mtype != MET_NORMAL && mlist->mtype != MET_COMMON))
395     abort ();
396
397   Vector<Metric*> *mlist_items = mlist->get_items ();
398   items->destroy ();
399   items->reset ();
400
401   int sort_ind = mlist->get_sort_ref_index ();
402   for (int i = 0, mlist_sz = mlist_items->size (); i < mlist_sz; i++)
403     {
404       Metric *mtr = mlist_items->fetch (i);
405       if (!mtr->is_any_visible ())
406         continue;
407
408       //  Add a new Metric with probably a new sub_type to this->items:
409       //    for MET_CALL and MET_CALL_AGR the matching entry to an e. or i. is itself
410       //    for MET_DATA, the matching entry to an e. or i. is the d. metric
411       //    for MET_INDX, the matching entry to an e. or i. is the e. metric
412       //    for MET_IO, the matching entry to an e. or i. is the e. metric
413       //    for MET_HEAP, the matching entry to an e. or i. is the e. metric
414       //    Save static entries (SIZES and ADDRESS) only for MET_NORMAL, MET_CALL, MET_CALL_AGR, MET_SRCDIS
415       switch (mtr->get_type ())
416         {
417         case BaseMetric::SIZES:
418         case BaseMetric::ADDRESS:
419           switch (mtype)
420             {
421             case MET_NORMAL:
422             case MET_COMMON:
423             case MET_CALL:
424             case MET_CALL_AGR:
425             case MET_SRCDIS:
426               break;
427             default:
428               continue;
429             }
430           break;
431         default:
432           break;
433         }
434
435       BaseMetric::SubType st = mtr->get_subtype ();
436       if (st != BaseMetric::STATIC)
437         {
438           if (mtype == MET_CALL || mtype == MET_CALL_AGR)
439             {
440               if ((mtr->get_flavors () & BaseMetric::ATTRIBUTED) == 0)
441                 continue;
442               st = BaseMetric::ATTRIBUTED;
443             }
444           else if (mtype == MET_DATA)
445             {
446               if ((mtr->get_flavors () & BaseMetric::DATASPACE) == 0)
447                 continue;
448               st = BaseMetric::DATASPACE;
449             }
450           else if (mtype == MET_INDX)
451             {
452               if ((mtr->get_flavors () & BaseMetric::EXCLUSIVE) == 0)
453                 continue;
454               st = BaseMetric::EXCLUSIVE;
455             }
456           else if (mtype == MET_IO)
457             {
458               if (mtr->get_packet_type () != DATA_IOTRACE ||
459                   (mtr->get_flavors () & BaseMetric::EXCLUSIVE) == 0)
460                 continue;
461               st = BaseMetric::EXCLUSIVE;
462             }
463           else if (mtype == MET_HEAP)
464             {
465               if (mtr->get_packet_type () != DATA_HEAP ||
466                   (mtr->get_flavors () & BaseMetric::EXCLUSIVE) == 0)
467                 continue;
468               st = BaseMetric::EXCLUSIVE;
469             }
470           else if (mtype == MET_SRCDIS)
471             {
472               if ((mtr->get_flavors () & BaseMetric::INCLUSIVE) == 0)
473                 continue;
474               st = BaseMetric::INCLUSIVE;
475             }
476         }
477
478       bool found = false;
479       for (int i1 = 0, items_sz = items->size (); i1 < items_sz; i1++)
480         {
481           Metric *m1 = items->fetch (i1);
482           if (mtr->get_id () == m1->get_id () && st == m1->get_subtype ())
483             {
484               if (sort_ind == i)
485                 sort_ind = i1;
486               found = true;
487               break;
488             }
489         }
490       if (found)
491         continue;
492       Metric *m = new Metric (*mtr);
493       m->set_subtype (st);
494       m->set_raw_visbits (mtr->get_visbits ());
495       if (sort_ind == i)
496         sort_ind = items->size ();
497       items->append (m);
498     }
499   if (sort_ind >= items->size ())
500     sort_ind = 0;
501   if (mtype == MET_IO)
502     sort_ind = 0;
503   if (mtype == MET_HEAP)
504     sort_ind = 0;
505   sort_ref_index = sort_ind;
506
507 }
508
509
510 // set_sort:
511 //      Sets the sort for the metric list to the first metric
512 //      in mspec that is present; if fromRcFile is false, then
513 //      only one metric may be specified.  The requested sort
514 //      metric must be visible, or it won't  be in the metric list
515
516 char *
517 MetricList::set_sort (const char *mspec, bool fromRcFile)
518 {
519   char *mcmd;
520   BaseMetric::SubType subtypes[10];
521   int nsubtypes;
522   int vis;
523   bool parseOK = false;
524   bool reverse = false;
525   char buf[BUFSIZ];
526   char *list = buf;
527   char *mname;
528
529   // copy the input specification
530   snprintf (buf, sizeof (buf), NTXT ("%s"), mspec);
531   char *listp = list;
532   if (*listp == '-')
533     {
534       // reverse sort specified
535       reverse = true;
536       listp++;
537     }
538
539   // search for metric items from parsing the string
540   while ((mcmd = strtok (listp, NTXT (":"))) != NULL)
541     {
542       listp = NULL; // let strtok keep track
543
544       // parse the single metric_spec, based on the type of list being constructed, into:
545       //        a vector of SubTypes (any of [iead] or STATIC)
546       //        a integer mask for the visibility bits
547       //        and the string name of the base metric
548       mname = parse_metric_spec (mcmd, subtypes, &nsubtypes, &vis, &parseOK);
549       if (!parseOK)
550         {
551           // error parsing the metric specification
552           // not from an rc file, it's an error
553           if (!fromRcFile)
554             return (mname);
555           continue;
556         }
557       if (VAL_IS_HIDDEN (vis))
558         continue;
559
560       // loop over subtypes requested to find metric
561       // add a metric of that subtype, with specified vis.bits
562       for (int i = 0; i < nsubtypes; i++)
563         {
564           // make sure the subtype is acceptable
565           if ((mtype == MET_CALL || mtype == MET_CALL_AGR)
566               && subtypes[i] != BaseMetric::ATTRIBUTED
567               && subtypes[i] != BaseMetric::STATIC)
568               return dbe_sprintf (GTXT ("Inclusive, Exclusive, or Data metrics cannot be specified for caller-callee sort: %s\n"),
569                                   mcmd);
570           if (mtype == MET_DATA && subtypes[i] != BaseMetric::DATASPACE
571               && subtypes[i] != BaseMetric::STATIC)
572               return dbe_sprintf (GTXT ("Inclusive, Exclusive, or Attributed metrics cannot be specified for data-derived sort: %s\n"),
573                                   mcmd);
574           if (mtype == MET_INDX && subtypes[i] != BaseMetric::EXCLUSIVE
575                                    && subtypes[i] != BaseMetric::STATIC)
576             return dbe_sprintf (GTXT ("Inclusive, Data or Attributed metrics cannot be specified for index sort: %s\n"),
577                                 mcmd);
578           if ((mtype == MET_NORMAL || mtype == MET_COMMON
579                || mtype == MET_SRCDIS)
580               && (subtypes[i] == BaseMetric::DATASPACE
581                   || subtypes[i] == BaseMetric::ATTRIBUTED))
582             return dbe_sprintf (GTXT ("Data or Attributed metrics cannot be specified for sort: %s\n"), mcmd);
583           if (set_sort_metric (mname, subtypes[i], reverse))
584             return NULL;
585         }
586       // continue looking at entries
587     }
588
589   // not found on the list at all
590   switch (mtype)
591     {
592     case MET_NORMAL:
593     case MET_COMMON:
594     case MET_SRCDIS:
595       return dbe_sprintf (GTXT ("Invalid sort specification: %s\n"), mspec);
596     case MET_CALL:
597     case MET_CALL_AGR:
598       return dbe_sprintf (GTXT ("Invalid caller-callee sort specification: %s\n"),
599                           mspec);
600     case MET_DATA:
601       return dbe_sprintf (GTXT ("Invalid data-derived sort specification: %s\n"),
602                           mspec);
603     case MET_INDX:
604       return dbe_sprintf (GTXT ("Invalid index sort specification: %s\n"),
605                           mspec);
606     case MET_IO:
607       return dbe_sprintf (GTXT ("Invalid I/O sort specification: %s\n"), mspec);
608     case MET_HEAP:
609       return dbe_sprintf (GTXT ("Invalid heap sort specification: %s\n"),
610                           mspec);
611     }
612   return NULL;
613 }
614
615 // set_sort to the metric with the given visible index
616
617 void
618 MetricList::set_sort (int visindex, bool reverse)
619 {
620   Metric *mitem;
621   if (visindex < items->size ())
622     {
623       mitem = items->fetch (visindex);
624       if (mitem->is_any_visible ())
625         {
626           sort_ref_index = visindex;
627           sort_reverse = reverse;
628           return;
629         }
630     }
631   set_fallback_sort ();
632 }
633
634 bool
635 MetricList::set_sort_metric (char *mname, BaseMetric::SubType mst, bool reverse)
636 {
637   bool any = false, hwc = false, bit = false;
638
639   // check keywords 'any', 'all', 'bit' and 'hwc'
640   if (!strcasecmp (mname, Command::ANY_CMD))
641     any = true;
642   else if (!strcasecmp (mname, Command::ALL_CMD))
643     any = true;
644   else if (!strcasecmp (mname, Command::HWC_CMD))
645     hwc = true;
646   else if (!strcasecmp (mname, Command::BIT_CMD))
647     bit = true;
648
649   for (int i = 0, items_sz = items->size (); i < items_sz; i++)
650     {
651       Metric *m = items->fetch (i);
652       if (mst == m->get_subtype ()
653           && (any || (hwc && m->get_type () == BaseMetric::HWCNTR)
654               || (bit && m->get_cmd ()
655                   && strncmp (Command::BIT_CMD, m->get_cmd (),
656                               strlen (Command::BIT_CMD)) == 0)
657               || dbe_strcmp (mname, m->get_cmd ()) == 0))
658         {
659           sort_ref_index = i;
660           sort_reverse = reverse;
661           return true;
662         }
663     }
664   return false;
665 }
666
667 // Print to a file of a list of metrics from a supplied vector
668 //      Debug flag = 1, prints the short name and address of the list
669 //      Debug flag = 2, prints the details of the list
670 void
671 MetricList::print_metric_list (FILE *dis_file, char *leader, int debug)
672 {
673   Metric *item;
674   int index;
675   char fmt_name[64];
676   fprintf (dis_file, NTXT ("%s"), leader);
677   if (items == NULL)
678     {
679       fprintf (dis_file, GTXT ("NULL metric list can not be printed; aborting"));
680       abort ();
681     }
682
683   if (items->size () == 0)
684     {
685       fprintf (dis_file, GTXT ("metric list is empty; aborting\n"));
686       abort ();
687     }
688
689   // if debugging, print list address and string, and sort name
690   if (debug != 0)
691     {
692       char *s = get_metrics ();
693       fprintf (dis_file, "\tmetriclist at 0x%lx: %s, %lld metrics; sort by %s\n",
694                (unsigned long) this, s, (long long) items->size (),
695                get_sort_name ());
696       free (s);
697       if (debug == 1)
698         return;
699     }
700
701   // Find the longest metric name & command
702   size_t max_len = 0;
703   size_t max_len2 = 0;
704
705   Vec_loop (Metric*, items, index, item)
706   {
707     // get the name
708     char *mn = item->get_name ();
709     size_t len = strlen (mn);
710     if (max_len < len)
711       max_len = len;
712
713     mn = item->get_mcmd (true);
714     len = strlen (mn);
715     if (max_len2 < len)
716       max_len2 = len;
717     free (mn);
718
719   }
720   if (debug == 2)
721     snprintf (fmt_name, sizeof (fmt_name), "%%%ds: %%-%ds", (int) max_len,
722               (int) max_len2);
723   else
724     snprintf (fmt_name, sizeof (fmt_name), "%%%ds: %%s", (int) max_len);
725
726   Vec_loop (Metric*, items, index, item)
727   {
728     char *mcmd = item->get_mcmd (true);
729     fprintf (dis_file, fmt_name, item->get_name (), mcmd);
730     free (mcmd);
731     if (debug == 2)
732       fprintf (dis_file, "\t[st %2d, VT %d, vis = %4s, T=%d, sort = %c]",
733                item->get_subtype (), item->get_vtype (),
734                item->get_vis_str (), item->is_time_val (),
735                sort_ref_index == index ? 'Y' : 'N');
736     fputc ('\n', dis_file);
737   }
738
739   fputc ('\n', dis_file);
740   fflush (dis_file);
741 }
742
743 // Return a string formatted from a vector of metrics
744 //      string is in the form suitable for a "metrics <string>" command
745 char *
746 MetricList::get_metrics ()
747 {
748   Metric *item;
749   int index;
750   StringBuilder sb;
751   Vec_loop (Metric*, items, index, item)
752   {
753     if (sb.length () != 0)
754       sb.append (':');
755     char *mcmd = item->get_mcmd (false);
756     sb.append (mcmd);
757     free (mcmd);
758   }
759   return sb.toString ();
760 }
761
762 int
763 MetricList::get_listorder (Metric *mtr)
764 {
765   for (int i = 0, items_sz = items->size (); i < items_sz; i++)
766     {
767       Metric *m = items->fetch (i);
768       if (m->get_subtype () == mtr->get_subtype ()
769           && m->get_id () == mtr->get_id ())
770         return i;
771     }
772   return -1;
773 }
774
775 int
776 MetricList::get_listorder (char *cmd, BaseMetric::SubType st, const char *expr)
777 {
778   for (long i = 0, items_sz = items->size (); i < items_sz; i++)
779     {
780       Metric *m = items->fetch (i);
781       if (m->get_subtype () == st && dbe_strcmp (m->get_cmd (), cmd) == 0
782           && dbe_strcmp (m->get_expr_spec (), expr) == 0)
783         return (int) i;
784     }
785   return -1;
786 }
787
788 Metric *
789 MetricList::find_metric_by_name (char *cmd)
790 {
791   for (long i = 0, items_sz = items->size (); i < items_sz; i++)
792     {
793       Metric *m = items->fetch (i);
794       if (dbe_strcmp (m->get_cmd (), cmd) == 0)
795         return m;
796     }
797   return NULL;
798 }
799
800 //  find a metric by name and subtype
801 Metric *
802 MetricList::find_metric (char *cmd, BaseMetric::SubType st)
803 {
804   int i = get_listorder (cmd, st);
805   if (i < 0)
806     return NULL;
807   return items->fetch (i);
808 }
809
810 //  Get the sort metric from a list; forces sort by first if not set
811 Metric *
812 MetricList::get_sort_metric ()
813 {
814   int i = get_sort_ref_index ();
815   return i >= 0 ? items->fetch (i) : NULL;
816 }
817
818 char *
819 MetricList::get_sort_name ()
820 {
821   Metric *item = get_sort_metric ();
822   if (item == NULL)
823     return dbe_strdup (NTXT (""));
824   char *n = item->get_name ();
825   return sort_reverse ? dbe_sprintf ("-%s", n) : dbe_strdup (n);
826 }
827
828 char *
829 MetricList::get_sort_cmd ()
830 {
831   char *buf;
832   Metric *item = get_sort_metric ();
833   if (item == NULL)
834     return dbe_strdup (NTXT (""));
835   char *n = item->get_mcmd (false);
836   if (sort_reverse)
837     {
838       buf = dbe_sprintf (NTXT ("-%s"), n);
839       free (n);
840     }
841   else
842     buf = n;
843   return buf;
844 }
845
846 Metric *
847 MetricList::append (BaseMetric *bm, BaseMetric::SubType st, int visbits)
848 {
849   for (long i = 0, sz = items->size (); i < sz; i++)
850     {
851       Metric *m = items->get (i);
852       if (m->get_id () == bm->get_id () && m->get_subtype () == st)
853         return NULL;
854     }
855   Metric *met = new Metric (bm, st);
856   met->set_dmetrics_visbits (visbits);
857   items->append (met);
858   return met;
859 }
860
861 int
862 MetricList::add_matching_dmetrics (Vector<BaseMetric*> *base_items,
863                                    char *mcmd, BaseMetric::SubType *_subtypes,
864                                    int nsubtypes, int dmetrics_visbits,
865                                    bool fromRcFile)
866 {
867   bool any = false, hwc = false, bit = false;
868   int got_metric = 1;
869
870   // check keywords 'any', 'all', 'bit', and 'hwc'
871   if (!strcasecmp (mcmd, Command::ANY_CMD))
872     any = true;
873   else if (!strcasecmp (mcmd, Command::ALL_CMD))
874     any = true;
875   else if (!strcasecmp (mcmd, Command::HWC_CMD))
876     hwc = true;
877   else if (!strcasecmp (mcmd, Command::BIT_CMD))
878     bit = true;
879
880   BaseMetric::SubType *subtypes = _subtypes;
881   BaseMetric::SubType all_subtypes[2] =
882     { BaseMetric::EXCLUSIVE, BaseMetric::INCLUSIVE };
883
884   if (nsubtypes == 0 || (nsubtypes == 1 && subtypes[0] == BaseMetric::STATIC))
885     {
886       // user did not specify ei; treat as wildcard and supply both.
887       subtypes = all_subtypes;
888       nsubtypes = 2;
889     }
890
891   // scan the metrics to find all matches
892   for (int i = 0, base_sz = base_items->size (); i < base_sz; i++)
893     {
894       BaseMetric *item = base_items->fetch (i);
895       if (!(any || (hwc && item->get_type () == BaseMetric::HWCNTR)
896             || (bit && item->get_cmd ()
897                 && strncmp (item->get_cmd (), Command::BIT_CMD,
898                             strlen (Command::BIT_CMD)) == 0)
899             || dbe_strcmp (item->get_cmd (), mcmd) == 0))
900         continue;
901       if (item->is_internal ())
902         continue;
903       if (item->get_flavors () & BaseMetric::STATIC)
904         {
905           got_metric = 0;
906           int vis = item->get_type () != BaseMetric::ONAME ?
907                   dmetrics_visbits : VAL_VALUE;
908           if (append (item, BaseMetric::STATIC, vis) == NULL && !fromRcFile)
909             return 2;
910           continue;
911         }
912
913       // special case for omp metrics: make visible only if
914       // omp data has been collected
915       if (!dbeSession->is_omp_available ()
916           && (strcasecmp (mcmd, "ompwork") == 0
917               || strcasecmp (mcmd, "ompwait") == 0))
918           continue;
919
920       for (int j = 0; j < nsubtypes; j++)
921         {
922           if (append (item, subtypes[j], dmetrics_visbits) == NULL
923               && !fromRcFile)
924             return 2;
925         }
926       got_metric = 0;
927       if (!(any || hwc || bit))
928         break;
929     }
930   return got_metric;
931 }
932
933 // parse a single metric specification, to give:
934 //      a vector of subtypes, and a count of the number of them
935 //      an integer visibility
936 //      return the string for the metric name
937
938 char *
939 MetricList::parse_metric_spec (char *mcmd, BaseMetric::SubType *subtypes,
940                                int *nsubtypes, int *dmetrics_visb, bool *isOK)
941 {
942   size_t len_vtype;
943   int index;
944   int vis;
945   bool got_e, got_i, got_a, got_d;
946   char *str = mcmd;
947   char *str2;
948
949   *isOK = true;
950
951   // For dynamic metrics, each keyword is of the form  <flavor><visibility><metric-name>
952   // For static metrics, each keyword is of the form [<visibility>]<metric-name>
953   // <flavor> can be either "i" for inclusive or "e" for exclusive
954   // <visibility> can be any combination of "." (to show the metric as a time),
955   //    "%" (to show it as a percentage), "+" (to show it as a count), and "!" (turn off the metric)
956
957   // find subtype
958   index = 0;
959   size_t len_subtype = strspn (str, NTXT ("eiad"));
960   str2 = str + len_subtype;
961
962   // find vis
963   if (len_subtype == 0)
964     {
965       // only a . or ! is possible if no subtypes
966       len_vtype = strspn (str2, NTXT (".!"));
967       vis = VAL_VALUE;
968     }
969   else
970     {
971       len_vtype = strspn (str2, NTXT (".+%!"));
972       vis = VAL_NA;
973     }
974
975   // if no visibility bits, there can't be a subtype
976   if (len_vtype == 0)
977     len_subtype = 0;
978
979   if (len_subtype == 0)
980     {
981       // must be a static metric
982       subtypes[index++] = BaseMetric::STATIC;
983       vis = VAL_VALUE;
984     }
985   else
986     {
987       // figure out which subtypes are specified
988       got_e = got_i = got_a = got_d = false;
989       for (size_t i = 0; i < len_subtype; i++)
990         {
991           str += len_subtype;
992           if (mcmd[i] == 'e')
993             { // exclusive
994               if (mtype == MET_DATA)
995                 {
996                   *isOK = false;
997                   return dbe_sprintf (GTXT ("Invalid metric specification: %s inapplicable for data metrics\n"),
998                                       mcmd);
999                 }
1000               if (!got_e)
1001                 {
1002                   got_e = true;
1003                   subtypes[index++] = BaseMetric::EXCLUSIVE;
1004                 }
1005             }
1006           else if (mcmd[i] == 'i')
1007             { // inclusive
1008               if (mtype == MET_DATA)
1009                 {
1010                   *isOK = false;
1011                   return dbe_sprintf (GTXT ("Invalid metric specification: %s inapplicable for data metrics\n"),
1012                                       mcmd);
1013                 }
1014               if (mtype == MET_INDX)
1015                 {
1016                   *isOK = false;
1017                   return dbe_sprintf (GTXT ("Invalid metric specification: %s inapplicable for index metrics\n"),
1018                                       mcmd);
1019                 }
1020               if (!got_i)
1021                 {
1022                   got_i = true;
1023                   subtypes[index++] = BaseMetric::INCLUSIVE;
1024                 }
1025             }
1026           else if (mcmd[i] == 'a')
1027             { // attributed
1028               if (mtype != MET_CALL && mtype != MET_CALL_AGR)
1029                 {
1030                   *isOK = false;
1031                   return dbe_sprintf (GTXT ("Invalid metric specification: %s applicable for caller-callee metrics only\n"),
1032                                       mcmd);
1033                 }
1034               if (!got_a)
1035                 {
1036                   got_a = true;
1037                   subtypes[index++] = BaseMetric::ATTRIBUTED;
1038                 }
1039             }
1040           else if (mcmd[i] == 'd')
1041             { // data-space
1042               if (mtype != MET_DATA)
1043                 {
1044                   *isOK = false;
1045                   return dbe_sprintf (GTXT ("Invalid metric specification: %s applicable for data-derived metrics only\n"),
1046                                       mcmd);
1047                 }
1048               if (!got_d)
1049                 {
1050                   got_d = true;
1051                   subtypes[index++] = BaseMetric::DATASPACE;
1052                 }
1053             }
1054         }
1055     }
1056   *nsubtypes = index;
1057
1058   // now determine the visiblity bits
1059   if (len_vtype > 0)
1060     {
1061       for (size_t i = 0; i < len_vtype; i++)
1062         {
1063           if (str2[i] == '+')
1064             vis = (vis | VAL_VALUE);
1065           else if (str2[i] == '.')
1066             vis = (vis | VAL_TIMEVAL);
1067           else if (str2[i] == '%')
1068             vis = (vis | VAL_PERCENT);
1069           else if (str2[i] == '!')
1070             vis = (vis | VAL_HIDE_ALL);
1071         }
1072     }
1073   *dmetrics_visb = vis;
1074   return mcmd + len_subtype + len_vtype;
1075 }
This page took 0.085839 seconds and 4 git commands to generate.