Print this page
    
re #13388 rb4382 fmd_api.h uses bool which is a C99/C++ keyword
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/fm/fmstat/common/fmstat.c
          +++ new/usr/src/cmd/fm/fmstat/common/fmstat.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27   27  #include <fm/fmd_adm.h>
  28   28  
  29   29  #include <strings.h>
  30   30  #include <limits.h>
  31   31  #include <stdlib.h>
  32   32  #include <stdarg.h>
  33   33  #include <stdio.h>
  34   34  #include <errno.h>
  35   35  #include <poll.h>
  36   36  #include <locale.h>
  37   37  
  38   38  #include "statcommon.h"
  39   39  
  40   40  #define FMSTAT_EXIT_SUCCESS     0
  41   41  #define FMSTAT_EXIT_ERROR       1
  42   42  #define FMSTAT_EXIT_USAGE       2
  43   43  
  44   44  static const struct stats {
  45   45          fmd_stat_t module;
  46   46          fmd_stat_t authority;
  47   47          fmd_stat_t state;
  48   48          fmd_stat_t loadtime;
  49   49          fmd_stat_t snaptime;
  50   50          fmd_stat_t received;
  51   51          fmd_stat_t discarded;
  52   52          fmd_stat_t retried;
  53   53          fmd_stat_t replayed;
  54   54          fmd_stat_t lost;
  55   55          fmd_stat_t dispatched;
  56   56          fmd_stat_t dequeued;
  57   57          fmd_stat_t prdequeued;
  58   58          fmd_stat_t accepted;
  59   59          fmd_stat_t memtotal;
  60   60          fmd_stat_t buftotal;
  61   61          fmd_stat_t caseopen;
  62   62          fmd_stat_t casesolved;
  63   63          fmd_stat_t wcnt;
  64   64          fmd_stat_t wtime;
  65   65          fmd_stat_t wlentime;
  66   66          fmd_stat_t wlastupdate;
  67   67          fmd_stat_t dtime;
  68   68          fmd_stat_t dlastupdate;
  69   69  } stats_template = {
  70   70          { "module", FMD_TYPE_STRING },
  71   71          { "authority", FMD_TYPE_STRING },
  72   72          { "state", FMD_TYPE_STRING },
  73   73          { "loadtime", FMD_TYPE_TIME },
  74   74          { "snaptime", FMD_TYPE_TIME },
  75   75          { "received", FMD_TYPE_UINT64 },
  76   76          { "discarded", FMD_TYPE_UINT64 },
  77   77          { "retried", FMD_TYPE_UINT64 },
  78   78          { "replayed", FMD_TYPE_UINT64 },
  79   79          { "lost", FMD_TYPE_UINT64 },
  80   80          { "dispatched", FMD_TYPE_UINT64 },
  81   81          { "dequeued", FMD_TYPE_UINT64 },
  82   82          { "prdequeued", FMD_TYPE_UINT64 },
  83   83          { "accepted", FMD_TYPE_UINT64 },
  84   84          { "memtotal", FMD_TYPE_SIZE },
  85   85          { "buftotal", FMD_TYPE_SIZE },
  86   86          { "caseopen", FMD_TYPE_UINT64 },
  87   87          { "casesolved", FMD_TYPE_UINT64 },
  88   88          { "wcnt", FMD_TYPE_UINT32 },
  89   89          { "wtime", FMD_TYPE_TIME },
  90   90          { "wlentime", FMD_TYPE_TIME },
  91   91          { "wlastupdate", FMD_TYPE_TIME },
  92   92          { "dtime", FMD_TYPE_TIME },
  93   93          { "dlastupdate", FMD_TYPE_TIME },
  94   94  };
  95   95  
  96   96  static const char *g_pname;
  97   97  static fmd_adm_t *g_adm;
  98   98  
  99   99  static struct modstats {
 100  100          char *m_name;
 101  101          struct modstats *m_next;
 102  102          struct stats m_stbuf[2];
 103  103          int m_stidx;
 104  104          int m_id;
 105  105          struct stats *m_old;
 106  106          struct stats *m_new;
 107  107          double m_wait;
 108  108          double m_svc;
 109  109          double m_pct_b;
 110  110          double m_pct_w;
 111  111  } *g_mods;
 112  112  
 113  113  static uint_t timestamp_fmt = NODATE;
 114  114  
 115  115  #if !defined(TEXT_DOMAIN)               /* Should be defined by cc -D */
 116  116  #define TEXT_DOMAIN "SYS_TEST"          /* Use this only if it isn't */
 117  117  #endif
 118  118  
 119  119  static void
 120  120  vwarn(const char *format, va_list ap)
 121  121  {
 122  122          int err = errno;
 123  123  
 124  124          (void) fprintf(stderr, "%s: ", g_pname);
 125  125  
 126  126          if (format != NULL)
 127  127                  (void) vfprintf(stderr, format, ap);
 128  128  
 129  129          errno = err; /* restore errno for fmd_adm_errmsg() */
 130  130  
 131  131          if (format == NULL)
 132  132                  (void) fprintf(stderr, "%s\n", fmd_adm_errmsg(g_adm));
 133  133          else if (strchr(format, '\n') == NULL)
 134  134                  (void) fprintf(stderr, ": %s\n", fmd_adm_errmsg(g_adm));
 135  135  }
 136  136  
 137  137  /*PRINTFLIKE1*/
 138  138  void
 139  139  warn(const char *format, ...)
 140  140  {
 141  141          va_list ap;
 142  142  
 143  143          va_start(ap, format);
 144  144          vwarn(format, ap);
 145  145          va_end(ap);
 146  146  }
 147  147  
 148  148  /*PRINTFLIKE1*/
 149  149  void
 150  150  die(const char *format, ...)
 151  151  {
 152  152          va_list ap;
 153  153  
 154  154          va_start(ap, format);
 155  155          vwarn(format, ap);
 156  156          va_end(ap);
 157  157  
 158  158          fmd_adm_close(g_adm);
 159  159          exit(FMSTAT_EXIT_ERROR);
 160  160  }
 161  161  
 162  162  static char *
 163  163  time2str(char *buf, size_t len, uint64_t time)
 164  164  {
 165  165          static const struct unit {
 166  166                  const char *u_name;
 167  167                  hrtime_t u_mul;
 168  168          } units[] = {
 169  169                  { "d",  NANOSEC * (hrtime_t)(24 * 60 * 60) },
 170  170                  { "h",  NANOSEC * (hrtime_t)(60 * 60) },
 171  171                  { "m",  NANOSEC * (hrtime_t)60 },
 172  172                  { "s",  NANOSEC / SEC },
 173  173                  { "ms", NANOSEC / MILLISEC },
 174  174                  { "us", NANOSEC / MICROSEC },
 175  175                  { "ns", NANOSEC / NANOSEC },
 176  176          };
 177  177  
 178  178          const struct unit *up;
 179  179  
 180  180          for (up = units; time % up->u_mul != 0; up++)
 181  181                  continue; /* find largest unit of which 'time' is a multiple */
 182  182  
 183  183          (void) snprintf(buf, len, "%llu%s", time / up->u_mul, up->u_name);
 184  184          return (buf);
 185  185  }
 186  186  
 187  187  static char *
 188  188  size2str(char *buf, size_t len, uint64_t size)
 189  189  {
 190  190          static const char units[] = "bKMGTPE";
 191  191          const uint64_t scale = 1024;
 192  192          const char *up = units;
 193  193          uint64_t osize = 0;
 194  194  
 195  195          /*
 196  196           * Convert the input size to a round number of the appropriately
 197  197           * scaled units (saved in 'size') and a remainder (saved in 'osize').
 198  198           */
 199  199          while (size >= scale && up < (units + sizeof (units) - 2)) {
 200  200                  up++;
 201  201                  osize = size;
 202  202                  size = (size + (scale / 2)) / scale;
 203  203          }
 204  204  
 205  205          /*
 206  206           * Format the result using at most one decimal place and the unit
 207  207           * depending upon the amount of remainder (same as df -h algorithm).
 208  208           */
 209  209          if (osize != 0 && (osize / scale) < 10)
 210  210                  (void) snprintf(buf, len, "%.1f%c", (float)osize / scale, *up);
 211  211          else if (size != 0)
 212  212                  (void) snprintf(buf, len, "%llu%c", size, *up);
 213  213          else
 214  214                  (void) snprintf(buf, len, "0");
 215  215  
 216  216          return (buf);
 217  217  }
 218  218  
 219  219  static uint64_t
 220  220  u64delta(uint64_t old, uint64_t new)
 221  221  {
 222  222          return (new >= old ? (new - old) : ((UINT64_MAX - old) + new + 1));
 223  223  }
 224  224  
 225  225  static struct modstats *
 226  226  modstat_create(const char *name, id_t id)
 227  227  {
 228  228          struct modstats *mp = malloc(sizeof (struct modstats));
 229  229  
 230  230          if (mp == NULL)
 231  231                  return (NULL);
 232  232  
 233  233          bzero(mp, sizeof (struct modstats));
 234  234  
 235  235          if (name != NULL && (mp->m_name = strdup(name)) == NULL) {
 236  236                  free(mp);
 237  237                  return (NULL);
 238  238          }
 239  239  
 240  240          mp->m_id = id;
 241  241          mp->m_next = g_mods;
 242  242          g_mods = mp;
 243  243          return (mp);
 244  244  }
 245  245  
 246  246  /*
 247  247   * Given a statistics buffer containing event queue statistics, compute the
 248  248   * common queue statistics for the given module and store the results in 'mp'.
 249  249   * We set m_new and m_old for the caller, and store the compute values of
 250  250   * m_svc, m_wait, m_pct_w, and m_pct_b there as well.  The caller must not free
 251  251   * 'ams' until after using the results as m_new may contain pointers to it.
 252  252   */
 253  253  static void
 254  254  modstat_compute(struct modstats *mp, fmd_adm_stats_t *ams)
 255  255  {
 256  256          static fmd_stat_t *t_beg = (fmd_stat_t *)(&stats_template + 0);
 257  257          static fmd_stat_t *t_end = (fmd_stat_t *)(&stats_template + 1);
 258  258  
 259  259          struct stats *old, *new;
 260  260          fmd_stat_t *tsp, *nsp, *sp;
 261  261          double elapsed, avg_w, avg_d;
 262  262          uint64_t delta;
 263  263  
 264  264          old = mp->m_old = &mp->m_stbuf[mp->m_stidx];
 265  265          mp->m_stidx = 1 - mp->m_stidx;
 266  266          new = mp->m_new = &mp->m_stbuf[mp->m_stidx];
 267  267  
 268  268          /*
 269  269           * The statistics can come in any order; we compare each one to the
 270  270           * template of statistics of interest, find the matching ones, and copy
 271  271           * their values into the appropriate slot of the 'new' stats.
 272  272           */
 273  273          for (nsp = ams->ams_buf; nsp < ams->ams_buf + ams->ams_len; nsp++) {
 274  274                  for (tsp = t_beg; tsp < t_end; tsp++) {
 275  275                          const char *p = strrchr(nsp->fmds_name, '.');
 276  276  
 277  277                          /*
 278  278                           * The fmd queue stats can either be named fmd.<name>
 279  279                           * or fmd.xprt.%u.<name> depending on whether we're
 280  280                           * looking at the module queue or the transport queue.
 281  281                           * So we match using the patterns fmd.* and *.<name>
 282  282                           * and store only the value of <name> in stats_template.
 283  283                           */
 284  284                          if (p == NULL || strcmp(p + 1, tsp->fmds_name) != 0 ||
 285  285                              strncmp(nsp->fmds_name, "fmd.", 4) != 0)
 286  286                                  continue; /* continue until we match the stat */
 287  287  
 288  288                          if (tsp->fmds_type != nsp->fmds_type) {
 289  289                                  warn("%s has unexpected type (%u != %u)\n",
 290  290                                      nsp->fmds_name, tsp->fmds_type,
 291  291                                      nsp->fmds_type);
 292  292                          } else {
 293  293                                  sp = (fmd_stat_t *)new + (tsp - t_beg);
 294  294                                  sp->fmds_value = nsp->fmds_value;
 295  295                          }
 296  296                  }
 297  297          }
 298  298  
 299  299          /*
 300  300           * Compute the elapsed time by taking the delta between 'snaptime', or
 301  301           * or between snaptime and loadtime if there is no previous snapshot.
 302  302           * If delta is zero, set it to 1sec so we don't divide by zero later.
 303  303           */
 304  304          delta = u64delta(old->snaptime.fmds_value.ui64 ?
 305  305              old->snaptime.fmds_value.ui64 : old->loadtime.fmds_value.ui64,
 306  306              new->snaptime.fmds_value.ui64);
 307  307  
 308  308          elapsed = delta ? (double)delta : (double)NANOSEC;
 309  309  
 310  310          /*
 311  311           * Compute average wait queue len by taking the delta in the wait queue
 312  312           * len * time products (wlentime stat) and dividing by the elapsed time.
 313  313           */
 314  314          delta = u64delta(old->wlentime.fmds_value.ui64,
 315  315              new->wlentime.fmds_value.ui64);
 316  316  
 317  317          if (delta != 0)
 318  318                  mp->m_wait = (double)delta / elapsed;
 319  319          else
 320  320                  mp->m_wait = 0.0;
 321  321  
 322  322          /*
 323  323           * Compute average wait time by taking the delta in the wait queue time
 324  324           * (wtime) and dividing by the delta in the number of dispatches.
 325  325           */
 326  326          delta = u64delta(old->dispatched.fmds_value.ui64,
 327  327              new->dispatched.fmds_value.ui64);
 328  328  
 329  329          if (delta != 0) {
 330  330                  avg_w = (double)u64delta(old->wtime.fmds_value.ui64,
 331  331                      new->wtime.fmds_value.ui64) / (double)delta;
 332  332          } else
 333  333                  avg_w = 0.0;
 334  334  
 335  335          /*
 336  336           * Compute average dispatch time by taking the delta in the dispatch
 337  337           * time (dtime) and dividing by the delta in the number of dequeues.
 338  338           */
 339  339          delta = u64delta(old->dequeued.fmds_value.ui64,
 340  340              new->dequeued.fmds_value.ui64);
 341  341  
 342  342          if (delta != 0) {
 343  343                  avg_d = (double)u64delta(old->dtime.fmds_value.ui64,
 344  344                      new->dtime.fmds_value.ui64) / (double)delta;
 345  345          } else
 346  346                  avg_d = 0.0;
 347  347  
 348  348          /*
 349  349           * Finally compute the average overall service time by adding together
 350  350           * the average wait and dispatch times and converting to milliseconds.
 351  351           */
 352  352          mp->m_svc = ((avg_w + avg_d) * (double)MILLISEC) / (double)NANOSEC;
 353  353  
 354  354          /*
 355  355           * Compute the %wait and %busy times by taking the delta in wait and
 356  356           * busy times, dividing by the elapsed time, and multiplying by 100.
 357  357           */
 358  358          delta = u64delta(old->wtime.fmds_value.ui64,
 359  359              new->wtime.fmds_value.ui64);
 360  360  
 361  361          if (delta != 0)
 362  362                  mp->m_pct_w = ((double)delta / elapsed) * 100.0;
 363  363          else
 364  364                  mp->m_pct_w = 0.0;
 365  365  
 366  366          delta = u64delta(old->dtime.fmds_value.ui64,
 367  367              new->dtime.fmds_value.ui64);
 368  368  
 369  369          if (delta != 0)
 370  370                  mp->m_pct_b = ((double)delta / elapsed) * 100.0;
 371  371          else
 372  372                  mp->m_pct_b = 0.0;
 373  373  }
 374  374  
 375  375  /*ARGSUSED*/
 376  376  static int
 377  377  stat_one_xprt(id_t id, void *ignored)
 378  378  {
 379  379          fmd_adm_stats_t ams;
 380  380          struct modstats *mp;
 381  381  
 382  382          if (fmd_adm_xprt_stats(g_adm, id, &ams) != 0) {
 383  383                  warn("failed to retrieve statistics for transport %d", (int)id);
 384  384                  return (0); /* continue on to the next transport */
 385  385          }
 386  386  
 387  387          for (mp = g_mods; mp != NULL; mp = mp->m_next) {
 388  388                  if (mp->m_id == id)
 389  389                          break;
 390  390          }
 391  391  
 392  392          if (mp == NULL && (mp = modstat_create(NULL, id)) == NULL) {
 393  393                  warn("failed to allocate memory for transport %d", (int)id);
 394  394                  (void) fmd_adm_stats_free(g_adm, &ams);
 395  395                  return (0);
 396  396          }
 397  397  
 398  398          modstat_compute(mp, &ams);
 399  399  
 400  400          (void) printf("%3d %5s %7llu %7llu %7llu %7llu "
 401  401              "%4.1f %6.1f %3.0f %3.0f %s\n", (int)id,
 402  402              mp->m_new->state.fmds_value.str,
 403  403              u64delta(mp->m_old->prdequeued.fmds_value.ui64,
 404  404              mp->m_new->prdequeued.fmds_value.ui64),
 405  405              u64delta(mp->m_old->received.fmds_value.ui64,
 406  406              mp->m_new->received.fmds_value.ui64),
 407  407              u64delta(mp->m_old->discarded.fmds_value.ui64,
 408  408              mp->m_new->discarded.fmds_value.ui64),
 409  409              u64delta(mp->m_old->lost.fmds_value.ui64,
 410  410              mp->m_new->lost.fmds_value.ui64),
 411  411              mp->m_wait, mp->m_svc, mp->m_pct_w, mp->m_pct_b,
 412  412              mp->m_new->module.fmds_value.str);
 413  413  
 414  414          (void) fmd_adm_stats_free(g_adm, &ams);
 415  415          return (0);
 416  416  }
 417  417  
 418  418  static void
 419  419  stat_xprt(void)
 420  420  {
 421  421          (void) printf("%3s %5s %7s %7s %7s %7s %4s %6s %3s %3s %s\n",
 422  422              "id", "state", "ev_send", "ev_recv", "ev_drop", "ev_lost",
 423  423              "wait", "svc_t", "%w", "%b", "module");
 424  424  
 425  425          if (fmd_adm_xprt_iter(g_adm, stat_one_xprt, NULL) != 0)
 426  426                  die("failed to retrieve list of transports");
 427  427  }
 428  428  
 429  429  static int
 430  430  stat_one_xprt_auth(id_t id, void *arg)
 431  431  {
 432  432          const char *module = arg;
 433  433          fmd_adm_stats_t ams;
 434  434          struct modstats *mp;
 435  435  
 436  436          if (fmd_adm_xprt_stats(g_adm, id, &ams) != 0) {
 437  437                  warn("failed to retrieve statistics for transport %d", (int)id);
 438  438                  return (0); /* continue on to the next transport */
 439  439          }
 440  440  
 441  441          for (mp = g_mods; mp != NULL; mp = mp->m_next) {
 442  442                  if (mp->m_id == id)
 443  443                          break;
 444  444          }
 445  445  
 446  446          if (mp == NULL && (mp = modstat_create(NULL, id)) == NULL) {
 447  447                  warn("failed to allocate memory for transport %d", (int)id);
 448  448                  (void) fmd_adm_stats_free(g_adm, &ams);
 449  449                  return (0);
 450  450          }
 451  451  
 452  452          modstat_compute(mp, &ams);
 453  453  
 454  454          if (module == NULL ||
 455  455              strcmp(module, mp->m_new->module.fmds_value.str) == 0) {
 456  456                  (void) printf("%3d %5s %-18s  %s\n", (int)id,
 457  457                      mp->m_new->state.fmds_value.str,
 458  458                      mp->m_new->module.fmds_value.str,
 459  459                      mp->m_new->authority.fmds_value.str ?
 460  460                      mp->m_new->authority.fmds_value.str : "-");
 461  461          }
 462  462  
 463  463          (void) fmd_adm_stats_free(g_adm, &ams);
 464  464          return (0);
 465  465  }
 466  466  
 467  467  static void
 468  468  stat_xprt_auth(const char *module)
 469  469  {
 470  470          (void) printf("%3s %5s %-18s  %s\n",
 471  471              "id", "state", "module", "authority");
 472  472  
 473  473          if (fmd_adm_xprt_iter(g_adm, stat_one_xprt_auth, (void *)module) != 0)
 474  474                  die("failed to retrieve list of transports");
 475  475  }
 476  476  
 477  477  /*ARGSUSED*/
 478  478  static int
 479  479  stat_one_fmd(const fmd_adm_modinfo_t *ami, void *ignored)
 480  480  {
 481  481          char memsz[8], bufsz[8];
 482  482          fmd_adm_stats_t ams;
 483  483          struct modstats *mp;
 484  484  
 485  485          if (fmd_adm_module_stats(g_adm, ami->ami_name, &ams) != 0) {
 486  486                  warn("failed to retrieve statistics for %s", ami->ami_name);
 487  487                  return (0); /* continue on to the next module */
 488  488          }
 489  489  
 490  490          for (mp = g_mods; mp != NULL; mp = mp->m_next) {
 491  491                  if (strcmp(mp->m_name, ami->ami_name) == 0)
 492  492                          break;
 493  493          }
 494  494  
 495  495          if (mp == NULL && (mp = modstat_create(ami->ami_name, 0)) == NULL) {
 496  496                  warn("failed to allocate memory for %s", ami->ami_name);
 497  497                  (void) fmd_adm_stats_free(g_adm, &ams);
 498  498                  return (0);
 499  499          }
 500  500  
 501  501          modstat_compute(mp, &ams);
 502  502  
 503  503          (void) printf("%-18s %7llu %7llu %4.1f %6.1f %3.0f %3.0f "
 504  504              "%5llu %5llu %6s %6s\n", ami->ami_name,
 505  505              u64delta(mp->m_old->prdequeued.fmds_value.ui64,
 506  506              mp->m_new->prdequeued.fmds_value.ui64),
 507  507              u64delta(mp->m_old->accepted.fmds_value.ui64,
 508  508              mp->m_new->accepted.fmds_value.ui64),
 509  509              mp->m_wait, mp->m_svc, mp->m_pct_w, mp->m_pct_b,
 510  510              mp->m_new->caseopen.fmds_value.ui64,
 511  511              mp->m_new->casesolved.fmds_value.ui64,
 512  512              size2str(memsz, sizeof (memsz),
 513  513              mp->m_new->memtotal.fmds_value.ui64),
 514  514              size2str(bufsz, sizeof (bufsz),
 515  515              mp->m_new->buftotal.fmds_value.ui64));
 516  516  
 517  517          (void) fmd_adm_stats_free(g_adm, &ams);
 518  518          return (0);
 519  519  }
 520  520  
 521  521  static void
 522  522  stat_fmd(void)
 523  523  {
 524  524          (void) printf("%-18s %7s %7s %4s %6s %3s %3s %5s %5s %6s %6s\n",
 525  525              "module", "ev_recv", "ev_acpt", "wait", "svc_t", "%w", "%b",
 526  526              "open", "solve", "memsz", "bufsz");
 527  527  
 528  528          if (fmd_adm_module_iter(g_adm, stat_one_fmd, NULL) != 0)
 529  529                  die("failed to retrieve list of modules");
 530  530  }
 531  531  
 532  532  static void
 533  533  stat_mod(const char *name, int aflag, int zflag)
 534  534  {
 535  535          fmd_adm_stats_t ams;
 536  536          fmd_stat_t *sp;
 537  537          char buf[64];
 538  538  
 539  539          if (fmd_adm_stats_read(g_adm, name, &ams) != 0) {
 540  540                  die("failed to retrieve statistics for %s",
 541  541                      name ? name : "fmd(1M)");
 542  542          }
 543  543  
 544  544          (void) printf("%20s %-16s %s\n", "NAME", "VALUE", "DESCRIPTION");
 545  545  
 546  546          for (sp = ams.ams_buf; sp < ams.ams_buf + ams.ams_len; sp++) {
 547  547                  if (aflag == 0 && strncmp(sp->fmds_name, "fmd.", 4) == 0)
 548  548                          continue; /* skip fmd-internal stats unless -a used */
 549  549  
 550  550                  if (zflag) {
 551  551                          switch (sp->fmds_type) {
 552  552                          case FMD_TYPE_INT32:
 553  553                          case FMD_TYPE_UINT32:
 554  554                                  if (sp->fmds_value.ui32 == 0)
 555  555                                          continue;
 556  556                                  break;
 557  557                          case FMD_TYPE_INT64:
 558  558                          case FMD_TYPE_UINT64:
 559  559                          case FMD_TYPE_TIME:
 560  560                          case FMD_TYPE_SIZE:
 561  561                                  if (sp->fmds_value.ui64 == 0)
 562  562                                          continue;
 563  563                                  break;
 564  564                          case FMD_TYPE_STRING:
 565  565                                  if (sp->fmds_value.str == NULL ||
 566  566                                      sp->fmds_value.str[0] == '\0')
  
    | 
      ↓ open down ↓ | 
    566 lines elided | 
    
      ↑ open up ↑ | 
  
 567  567                                          continue;
 568  568                                  break;
 569  569                          }
 570  570                  }
 571  571  
 572  572                  (void) printf("%20s ", sp->fmds_name);
 573  573  
 574  574                  switch (sp->fmds_type) {
 575  575                  case FMD_TYPE_BOOL:
 576  576                          (void) printf("%-16s",
 577      -                            sp->fmds_value.bool ? "true" : "false");
      577 +                            sp->fmds_value.b ? "true" : "false");
 578  578                          break;
 579  579                  case FMD_TYPE_INT32:
 580  580                          (void) printf("%-16d", sp->fmds_value.i32);
 581  581                          break;
 582  582                  case FMD_TYPE_UINT32:
 583  583                          (void) printf("%-16u", sp->fmds_value.ui32);
 584  584                          break;
 585  585                  case FMD_TYPE_INT64:
 586  586                          (void) printf("%-16lld", sp->fmds_value.i64);
 587  587                          break;
 588  588                  case FMD_TYPE_UINT64:
 589  589                          (void) printf("%-16llu", sp->fmds_value.ui64);
 590  590                          break;
 591  591                  case FMD_TYPE_STRING:
 592  592                          (void) printf("%-16s", sp->fmds_value.str ?
 593  593                              sp->fmds_value.str : "<<null>>");
 594  594                          break;
 595  595                  case FMD_TYPE_TIME:
 596  596                          (void) printf("%-16s",
 597  597                              time2str(buf, sizeof (buf), sp->fmds_value.ui64));
 598  598                          break;
 599  599                  case FMD_TYPE_SIZE:
 600  600                          (void) printf("%-16s",
 601  601                              size2str(buf, sizeof (buf), sp->fmds_value.ui64));
 602  602                          break;
 603  603                  default:
 604  604                          (void) snprintf(buf, sizeof (buf),
 605  605                              "<<type=%u>>\n", sp->fmds_type);
 606  606                          (void) printf("%-16s", buf);
 607  607                  }
 608  608  
 609  609                  (void) printf(" %s\n", sp->fmds_desc);
 610  610          }
 611  611  
 612  612          (void) fmd_adm_stats_free(g_adm, &ams);
 613  613  }
 614  614  
 615  615  /*ARGSUSED*/
 616  616  static int
 617  617  stat_one_serd(const fmd_adm_serdinfo_t *asi, void *ignored)
 618  618  {
 619  619          char buf1[32], buf2[32], n[32];
 620  620  
 621  621          (void) snprintf(n, sizeof (n), ">%llu", asi->asi_n);
 622  622  
 623  623          (void) printf("%-36s %3s %5s %3u %24s %s\n",
 624  624              asi->asi_name, n, time2str(buf1, sizeof (buf1), asi->asi_t),
 625  625              asi->asi_count, time2str(buf2, sizeof (buf2), asi->asi_delta),
 626  626              (asi->asi_flags & FMD_ADM_SERD_FIRED) ? "fire" : "pend");
 627  627  
 628  628          return (0);
 629  629  }
 630  630  
 631  631  static void
 632  632  stat_mod_serd(const char *name)
 633  633  {
 634  634          (void) printf("%-36s %3s %5s %3s %24s %4s\n",
 635  635              "NAME", ">N", "T", "CNT", "DELTA", "STAT");
 636  636  
 637  637          if (fmd_adm_serd_iter(g_adm, name, stat_one_serd, NULL) != 0)
 638  638                  die("failed to retrieve serd engines for %s", name);
 639  639  }
 640  640  
 641  641  static int
 642  642  getint(const char *name, const char *s)
 643  643  {
 644  644          long val;
 645  645          char *p;
 646  646  
 647  647          errno = 0;
 648  648          val = strtol(s, &p, 10);
 649  649  
 650  650          if (errno != 0 || p == s || *p != '\0' || val < 0 || val > INT_MAX) {
 651  651                  (void) fprintf(stderr, "%s: invalid %s argument -- %s\n",
 652  652                      g_pname, name, s);
 653  653                  exit(FMSTAT_EXIT_USAGE);
 654  654          }
 655  655  
 656  656          return ((int)val);
 657  657  }
 658  658  
 659  659  static uint32_t
 660  660  getu32(const char *name, const char *s)
 661  661  {
 662  662          u_longlong_t val;
 663  663          char *p;
 664  664  
 665  665          errno = 0;
 666  666          val = strtoull(s, &p, 0);
 667  667  
 668  668          if (errno != 0 || p == s || *p != '\0' || val > UINT32_MAX) {
 669  669                  (void) fprintf(stderr, "%s: invalid %s argument -- %s\n",
 670  670                      g_pname, name, s);
 671  671                  exit(FMSTAT_EXIT_USAGE);
 672  672          }
 673  673  
 674  674          return ((uint32_t)val);
 675  675  }
 676  676  
 677  677  static int
 678  678  usage(FILE *fp)
 679  679  {
 680  680          (void) fprintf(fp, "Usage: %s [-astTz] [-m module] "
 681  681              "[-P prog] [-d d|u] [interval [count]]\n\n", g_pname);
 682  682  
 683  683          (void) fprintf(fp,
 684  684              "\t-a show all statistics, including those kept by fmd\n"
 685  685              "\t-d display a timestamp in date (d) or unix time_t (u)\n"
 686  686              "\t-m show module-specific statistics\n"
 687  687              "\t-P connect to alternate fmd program\n"
 688  688              "\t-s show module-specific serd engines\n"
 689  689              "\t-t show transport-specific statistics\n"
 690  690              "\t-T show transport modules and authorities\n"
 691  691              "\t-z suppress zero-valued statistics\n");
 692  692  
 693  693          return (FMSTAT_EXIT_USAGE);
 694  694  }
 695  695  
 696  696  int
 697  697  main(int argc, char *argv[])
 698  698  {
 699  699          int opt_a = 0, opt_s = 0, opt_t = 0, opt_T = 0, opt_z = 0;
 700  700          const char *opt_m = NULL;
 701  701          int msec = 0, iter = 1;
 702  702  
 703  703          uint32_t program;
 704  704          char *p;
 705  705          int c;
 706  706  
 707  707          if ((p = strrchr(argv[0], '/')) == NULL)
 708  708                  g_pname = argv[0];
 709  709          else
 710  710                  g_pname = p + 1;
 711  711  
 712  712          if ((p = getenv("FMD_PROGRAM")) != NULL)
 713  713                  program = getu32("$FMD_PROGRAM", p);
 714  714          else
 715  715                  program = FMD_ADM_PROGRAM;
 716  716  
 717  717          (void) setlocale(LC_ALL, "");
 718  718          (void) textdomain(TEXT_DOMAIN);
 719  719  
 720  720          while ((c = getopt(argc, argv, "ad:m:P:stTz")) != EOF) {
 721  721                  switch (c) {
 722  722                  case 'a':
 723  723                          opt_a++;
 724  724                          break;
 725  725                  case 'd':
 726  726                          if (optarg) {
 727  727                                  if (*optarg == 'u')
 728  728                                          timestamp_fmt = UDATE;
 729  729                                  else if (*optarg == 'd')
 730  730                                          timestamp_fmt = DDATE;
 731  731                                  else
 732  732                                          return (usage(stderr));
 733  733                          } else {
 734  734                                  return (usage(stderr));
 735  735                          }
 736  736                          break;
 737  737                  case 'm':
 738  738                          opt_m = optarg;
 739  739                          break;
 740  740                  case 'P':
 741  741                          program = getu32("program", optarg);
 742  742                          break;
 743  743                  case 's':
 744  744                          opt_s++;
 745  745                          break;
 746  746                  case 't':
 747  747                          opt_t++;
 748  748                          break;
 749  749                  case 'T':
 750  750                          opt_T++;
 751  751                          break;
 752  752                  case 'z':
 753  753                          opt_z++;
 754  754                          break;
 755  755                  default:
 756  756                          return (usage(stderr));
 757  757                  }
 758  758          }
 759  759  
 760  760          if (optind < argc) {
 761  761                  msec = getint("interval", argv[optind++]) * MILLISEC;
 762  762                  iter = -1;
 763  763          }
 764  764  
 765  765          if (optind < argc)
 766  766                  iter = getint("count", argv[optind++]);
 767  767  
 768  768          if (optind < argc)
 769  769                  return (usage(stderr));
 770  770  
 771  771          if (opt_t != 0 && (opt_m != NULL || opt_s != 0)) {
 772  772                  (void) fprintf(stderr,
 773  773                      "%s: -t cannot be used with -m or -s\n", g_pname);
 774  774                  return (FMSTAT_EXIT_USAGE);
 775  775          }
 776  776  
 777  777          if (opt_t != 0 && opt_T != 0) {
 778  778                  (void) fprintf(stderr,
 779  779                      "%s: -t and -T are mutually exclusive options\n", g_pname);
 780  780                  return (FMSTAT_EXIT_USAGE);
 781  781          }
 782  782  
 783  783          if (opt_m == NULL && opt_s != 0) {
 784  784                  (void) fprintf(stderr,
 785  785                      "%s: -s requires -m <module>\n", g_pname);
 786  786                  return (FMSTAT_EXIT_USAGE);
 787  787          }
 788  788  
 789  789          if ((g_adm = fmd_adm_open(NULL, program, FMD_ADM_VERSION)) == NULL)
 790  790                  die(NULL); /* fmd_adm_errmsg() has enough info */
 791  791  
 792  792          while (iter < 0 || iter-- > 0) {
 793  793                  if (timestamp_fmt != NODATE)
 794  794                          print_timestamp(timestamp_fmt);
 795  795                  if (opt_s)
 796  796                          stat_mod_serd(opt_m);
 797  797                  else if (opt_T)
 798  798                          stat_xprt_auth(opt_m);
 799  799                  else if (opt_a || opt_m)
 800  800                          stat_mod(opt_m, opt_a, opt_z);
 801  801                  else if (opt_t)
 802  802                          stat_xprt();
 803  803                  else
 804  804                          stat_fmd();
 805  805  
 806  806                  if (iter != 0) {
 807  807                          (void) poll(NULL, 0, msec);
 808  808                          (void) putchar('\n');
 809  809                  }
 810  810          }
 811  811  
 812  812          fmd_adm_close(g_adm);
 813  813          return (FMSTAT_EXIT_SUCCESS);
 814  814  }
  
    | 
      ↓ open down ↓ | 
    227 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX