LCOV - code coverage report
Current view: top level - source3/utils - status_profile.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 10 114 8.8 %
Date: 2024-01-11 09:59:51 Functions: 2 8 25.0 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation.
       3             :  * status reporting
       4             :  * Copyright (C) Andrew Tridgell 1994-1998
       5             :  * Copyright (C) James Peach 2005-2006
       6             :  *
       7             :  * This program is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * This program is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include "includes.h"
      22             : #include "smbprofile.h"
      23             : #include "status_profile.h"
      24             : #include "conn_tdb.h"
      25             : #include "librpc/gen_ndr/open_files.h"
      26             : #include "status_json.h"
      27             : 
      28          16 : static void profile_separator(const char * title,
      29             :                               struct traverse_state *state)
      30             : {
      31             :         char line[79 + 1];
      32             :         char * end;
      33             : 
      34          16 :         if (state->json_output) {
      35          16 :                 return;
      36             :         }
      37             : 
      38           0 :         snprintf(line, sizeof(line), "**** %s ", title);
      39             : 
      40           0 :         for (end = line + strlen(line); end < &line[sizeof(line) -1]; ++end) {
      41           0 :                 *end = '*';
      42             :         }
      43             : 
      44           0 :         line[sizeof(line) - 1] = '\0';
      45           0 :         d_printf("%s\n", line);
      46             : }
      47             : 
      48             : /*******************************************************************
      49             :  dump the elements of the profile structure
      50             :   ******************************************************************/
      51           2 : bool status_profile_dump(bool verbose,
      52             :                          struct traverse_state *state)
      53             : {
      54           2 :         struct profile_stats stats = {};
      55           2 :         const char* latest_section = NULL;
      56             : 
      57           2 :         if (!profile_setup(NULL, True)) {
      58           0 :                 fprintf(stderr,"Failed to initialise profile memory\n");
      59           0 :                 return False;
      60             :         }
      61             : 
      62           2 :         smbprofile_collect(&stats);
      63             : 
      64             : #define __PRINT_FIELD_LINE(name, _stats, field) do { \
      65             :         uintmax_t val = (uintmax_t)stats.values._stats.field; \
      66             :         if (!state->json_output) { \
      67             :                 d_printf("%-59s%20ju\n", \
      68             :                          name "_" #field ":", \
      69             :                          val); \
      70             :         } else { \
      71             :                add_profile_item_to_json(state, latest_section, name, #field, val); \
      72             :         } \
      73             : } while(0);
      74             : #define SMBPROFILE_STATS_START
      75             : #define SMBPROFILE_STATS_SECTION_START(name, display) do { \
      76             :         latest_section = display; \
      77             :         profile_separator(display, state);\
      78             : } while(0);
      79             : #define SMBPROFILE_STATS_COUNT(name) do { \
      80             :         __PRINT_FIELD_LINE(#name, name##_stats,  count); \
      81             : } while(0);
      82             : #define SMBPROFILE_STATS_TIME(name) do { \
      83             :         __PRINT_FIELD_LINE(#name, name##_stats,  time); \
      84             : } while(0);
      85             : #define SMBPROFILE_STATS_BASIC(name) do { \
      86             :         __PRINT_FIELD_LINE(#name, name##_stats,  count); \
      87             :         __PRINT_FIELD_LINE(#name, name##_stats,  time); \
      88             : } while(0);
      89             : #define SMBPROFILE_STATS_BYTES(name) do { \
      90             :         __PRINT_FIELD_LINE(#name, name##_stats,  count); \
      91             :         __PRINT_FIELD_LINE(#name, name##_stats,  time); \
      92             :         __PRINT_FIELD_LINE(#name, name##_stats,  idle); \
      93             :         __PRINT_FIELD_LINE(#name, name##_stats,  bytes); \
      94             : } while(0);
      95             : #define SMBPROFILE_STATS_IOBYTES(name) do { \
      96             :         __PRINT_FIELD_LINE(#name, name##_stats,  count); \
      97             :         __PRINT_FIELD_LINE(#name, name##_stats,  time); \
      98             :         __PRINT_FIELD_LINE(#name, name##_stats,  idle); \
      99             :         __PRINT_FIELD_LINE(#name, name##_stats,  inbytes); \
     100             :         __PRINT_FIELD_LINE(#name, name##_stats,  outbytes); \
     101             : } while(0);
     102             : #define SMBPROFILE_STATS_SECTION_END
     103             : #define SMBPROFILE_STATS_END
     104           2 :         SMBPROFILE_STATS_ALL_SECTIONS
     105             : #undef __PRINT_FIELD_LINE
     106             : #undef SMBPROFILE_STATS_START
     107             : #undef SMBPROFILE_STATS_SECTION_START
     108             : #undef SMBPROFILE_STATS_COUNT
     109             : #undef SMBPROFILE_STATS_TIME
     110             : #undef SMBPROFILE_STATS_BASIC
     111             : #undef SMBPROFILE_STATS_BYTES
     112             : #undef SMBPROFILE_STATS_IOBYTES
     113             : #undef SMBPROFILE_STATS_SECTION_END
     114             : #undef SMBPROFILE_STATS_END
     115             : 
     116           2 :         return True;
     117             : }
     118             : 
     119             : /* Convert microseconds to milliseconds. */
     120             : #define usec_to_msec(s) ((s) / 1000)
     121             : /* Convert microseconds to seconds. */
     122             : #define usec_to_sec(s) ((s) / 1000000)
     123             : /* One second in microseconds. */
     124             : #define one_second_usec (1000000)
     125             : 
     126             : #define sample_interval_usec one_second_usec
     127             : 
     128             : #define percent_time(used, period) ((double)(used) / (double)(period) * 100.0 )
     129             : 
     130           0 : static uint64_t print_count_count_samples(
     131             :         char *buf, const size_t buflen,
     132             :         const char *name,
     133             :         const struct smbprofile_stats_count * const current,
     134             :         const struct smbprofile_stats_count * const last,
     135             :         uint64_t delta_usec)
     136             : {
     137           0 :         uint64_t step = current->count - last->count;
     138           0 :         uint64_t count = 0;
     139             : 
     140           0 :         if (step != 0) {
     141           0 :                 uint64_t delta_sec = usec_to_sec(delta_usec);
     142             : 
     143           0 :                 count++;
     144             : 
     145           0 :                 if (buf[0] == '\0') {
     146           0 :                         snprintf(buf, buflen,
     147             :                                 "%-40s %ju/sec",
     148           0 :                                 name, (uintmax_t)(step / delta_sec));
     149             :                 } else {
     150           0 :                         printf("%-40s %s %ju/sec\n",
     151           0 :                                 buf, name, (uintmax_t)(step / delta_sec));
     152           0 :                         buf[0] = '\0';
     153             :                 }
     154             :         }
     155             : 
     156           0 :         return count;
     157             : }
     158             : 
     159           0 : static uint64_t print_basic_count_samples(
     160             :         char *buf, const size_t buflen,
     161             :         const char *name,
     162             :         const struct smbprofile_stats_basic * const current,
     163             :         const struct smbprofile_stats_basic * const last,
     164             :         uint64_t delta_usec)
     165             : {
     166           0 :         uint64_t step = current->count - last->count;
     167           0 :         uint64_t spent = current->time - last->time;
     168           0 :         uint64_t count = 0;
     169             : 
     170           0 :         if (step != 0) {
     171           0 :                 uint64_t delta_sec = usec_to_sec(delta_usec);
     172             : 
     173           0 :                 count++;
     174             : 
     175           0 :                 if (buf[0] == '\0') {
     176           0 :                         snprintf(buf, buflen,
     177             :                                 "%s %ju/sec (%.2f%%)",
     178           0 :                                 name, (uintmax_t)(step / delta_sec),
     179           0 :                                 percent_time(spent, delta_usec));
     180             :                 } else {
     181           0 :                         printf("%-40s %s %ju/sec (%.2f%%)\n",
     182           0 :                                 buf, name, (uintmax_t)(step / delta_sec),
     183           0 :                                 percent_time(spent, delta_usec));
     184           0 :                         buf[0] = '\0';
     185             :                 }
     186             :         }
     187             : 
     188           0 :         return count;
     189             : }
     190             : 
     191           0 : static uint64_t print_bytes_count_samples(
     192             :         char *buf, const size_t buflen,
     193             :         const char *name,
     194             :         const struct smbprofile_stats_bytes * const current,
     195             :         const struct smbprofile_stats_bytes * const last,
     196             :         uint64_t delta_usec)
     197             : {
     198           0 :         uint64_t step = current->count - last->count;
     199           0 :         uint64_t spent = current->time - last->time;
     200           0 :         uint64_t count = 0;
     201             : 
     202           0 :         if (step != 0) {
     203           0 :                 uint64_t delta_sec = usec_to_sec(delta_usec);
     204             : 
     205           0 :                 count++;
     206             : 
     207           0 :                 if (buf[0] == '\0') {
     208           0 :                         snprintf(buf, buflen,
     209             :                                 "%s %ju/sec (%.2f%%)",
     210           0 :                                 name, (uintmax_t)(step / delta_sec),
     211           0 :                                 percent_time(spent, delta_usec));
     212             :                 } else {
     213           0 :                         printf("%-40s %s %ju/sec (%.2f%%)\n",
     214           0 :                                 buf, name, (uintmax_t)(step / delta_sec),
     215           0 :                                 percent_time(spent, delta_usec));
     216           0 :                         buf[0] = '\0';
     217             :                 }
     218             :         }
     219             : 
     220           0 :         return count;
     221             : }
     222             : 
     223           0 : static uint64_t print_iobytes_count_samples(
     224             :         char *buf, const size_t buflen,
     225             :         const char *name,
     226             :         const struct smbprofile_stats_iobytes * const current,
     227             :         const struct smbprofile_stats_iobytes * const last,
     228             :         uint64_t delta_usec)
     229             : {
     230           0 :         uint64_t step = current->count - last->count;
     231           0 :         uint64_t spent = current->time - last->time;
     232           0 :         uint64_t count = 0;
     233             : 
     234           0 :         if (step != 0) {
     235           0 :                 uint64_t delta_sec = usec_to_sec(delta_usec);
     236             : 
     237           0 :                 count++;
     238             : 
     239           0 :                 if (buf[0] == '\0') {
     240           0 :                         snprintf(buf, buflen,
     241             :                                 "%s %ju/sec (%.2f%%)",
     242           0 :                                 name, (uintmax_t)(step / delta_sec),
     243           0 :                                 percent_time(spent, delta_usec));
     244             :                 } else {
     245           0 :                         printf("%-40s %s %ju/sec (%.2f%%)\n",
     246           0 :                                 buf, name, (uintmax_t)(step / delta_sec),
     247           0 :                                 percent_time(spent, delta_usec));
     248           0 :                         buf[0] = '\0';
     249             :                 }
     250             :         }
     251             : 
     252           0 :         return count;
     253             : }
     254             : 
     255           0 : static uint64_t print_count_samples(
     256             :         const struct profile_stats * const current,
     257             :         const struct profile_stats * const last,
     258             :         uint64_t delta_usec)
     259             : {
     260           0 :         uint64_t count = 0;
     261           0 :         char buf[60] = { '\0', };
     262             : 
     263           0 :         if (delta_usec == 0) {
     264           0 :                 return 0;
     265             :         }
     266             : 
     267             : #define SMBPROFILE_STATS_START
     268             : #define SMBPROFILE_STATS_SECTION_START(name, display)
     269             : #define SMBPROFILE_STATS_COUNT(name) do { \
     270             :         count += print_count_count_samples(buf, sizeof(buf), \
     271             :                                            #name, \
     272             :                                            &current->values.name##_stats, \
     273             :                                            &last->values.name##_stats, \
     274             :                                            delta_usec); \
     275             : } while(0);
     276             : #define SMBPROFILE_STATS_TIME(name) do { \
     277             : } while(0);
     278             : #define SMBPROFILE_STATS_BASIC(name) do { \
     279             :         count += print_basic_count_samples(buf, sizeof(buf), \
     280             :                                            #name, \
     281             :                                            &current->values.name##_stats, \
     282             :                                            &last->values.name##_stats, \
     283             :                                            delta_usec); \
     284             : } while(0);
     285             : #define SMBPROFILE_STATS_BYTES(name) do { \
     286             :         count += print_bytes_count_samples(buf, sizeof(buf), \
     287             :                                            #name, \
     288             :                                            &current->values.name##_stats, \
     289             :                                            &last->values.name##_stats, \
     290             :                                            delta_usec); \
     291             : } while(0);
     292             : #define SMBPROFILE_STATS_IOBYTES(name) do { \
     293             :         count += print_iobytes_count_samples(buf, sizeof(buf), \
     294             :                                              #name, \
     295             :                                              &current->values.name##_stats, \
     296             :                                              &last->values.name##_stats, \
     297             :                                              delta_usec); \
     298             : } while(0);
     299             : #define SMBPROFILE_STATS_SECTION_END
     300             : #define SMBPROFILE_STATS_END
     301           0 :         SMBPROFILE_STATS_ALL_SECTIONS
     302             : #undef SMBPROFILE_STATS_START
     303             : #undef SMBPROFILE_STATS_SECTION_START
     304             : #undef SMBPROFILE_STATS_COUNT
     305             : #undef SMBPROFILE_STATS_TIME
     306             : #undef SMBPROFILE_STATS_BASIC
     307             : #undef SMBPROFILE_STATS_BYTES
     308             : #undef SMBPROFILE_STATS_IOBYTES
     309             : #undef SMBPROFILE_STATS_SECTION_END
     310             : #undef SMBPROFILE_STATS_END
     311             : 
     312           0 :         if (buf[0] != '\0') {
     313           0 :                 printf("%-40s\n", buf);
     314           0 :                 buf[0] = '\0';
     315             :         }
     316             : 
     317           0 :         return count;
     318             : }
     319             : 
     320             : static struct profile_stats     sample_data[2];
     321             : static uint64_t         sample_time[2];
     322             : 
     323           0 : bool status_profile_rates(bool verbose)
     324             : {
     325             :         uint64_t remain_usec;
     326             :         uint64_t next_usec;
     327             :         uint64_t delta_usec;
     328             : 
     329           0 :         int last = 0;
     330           0 :         int current = 1;
     331             :         int tmp;
     332             : 
     333           0 :         if (verbose) {
     334           0 :             fprintf(stderr, "Sampling stats at %d sec intervals\n",
     335             :                     usec_to_sec(sample_interval_usec));
     336             :         }
     337             : 
     338           0 :         if (!profile_setup(NULL, True)) {
     339           0 :                 fprintf(stderr,"Failed to initialise profile memory\n");
     340           0 :                 return False;
     341             :         }
     342             : 
     343           0 :         smbprofile_collect(&sample_data[last]);
     344             :         for (;;) {
     345           0 :                 sample_time[current] = profile_timestamp();
     346           0 :                 next_usec = sample_time[current] + sample_interval_usec;
     347             : 
     348             :                 /* Take a sample. */
     349           0 :                 smbprofile_collect(&sample_data[current]);
     350             : 
     351             :                 /* Rate convert some values and print results. */
     352           0 :                 delta_usec = sample_time[current] - sample_time[last];
     353             : 
     354           0 :                 if (print_count_samples(&sample_data[current],
     355           0 :                         &sample_data[last], delta_usec)) {
     356           0 :                         printf("\n");
     357             :                 }
     358             : 
     359             :                 /* Swap sampling buffers. */
     360           0 :                 tmp = last;
     361           0 :                 last = current;
     362           0 :                 current = tmp;
     363             : 
     364             :                 /* Delay until next sample time. */
     365           0 :                 remain_usec = next_usec - profile_timestamp();
     366           0 :                 if (remain_usec > sample_interval_usec) {
     367           0 :                         fprintf(stderr, "eek! falling behind sampling rate!\n");
     368             :                 } else {
     369           0 :                         if (verbose) {
     370           0 :                             fprintf(stderr,
     371             :                                     "delaying for %lu msec\n",
     372           0 :                                     (unsigned long )usec_to_msec(remain_usec));
     373             :                         }
     374             : 
     375           0 :                         usleep(remain_usec);
     376             :                 }
     377             : 
     378             :         }
     379             : 
     380             :         return True;
     381             : }

Generated by: LCOV version 1.14