root/source4/torture/raw/tconrate.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. map_count_buffer
  2. fork_tcon_client
  3. children_remain
  4. rate_convert_secs
  5. torture_bench_treeconnect

   1 /*
   2    SMB tree connection rate test
   3 
   4    Copyright (C) 2006-2007 James Peach
   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 of the License, or
   9    (at your option) 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, see <http://www.gnu.org/licenses/>.
  18 */
  19 
  20 #include "includes.h"
  21 #include "libcli/libcli.h"
  22 #include "libcli/resolve/resolve.h"
  23 #include "torture/smbtorture.h"
  24 #include "lib/cmdline/popt_common.h"
  25 #include "param/param.h"
  26 
  27 #include "system/filesys.h"
  28 #include "system/shmem.h"
  29 
  30 #define TIME_LIMIT_SECS 30
  31 #define usec_to_sec(s) ((s) / 1000000)
  32 
  33 /* Map a shared memory buffer of at least nelem counters. */
  34 static void * map_count_buffer(unsigned nelem, size_t elemsz)
     /* [<][>][^][v][top][bottom][index][help] */
  35 {
  36         void * buf;
  37         size_t bufsz;
  38         size_t pagesz = getpagesize();
  39 
  40         bufsz = nelem * elemsz;
  41         bufsz = (bufsz + pagesz) % pagesz; /* round up to pagesz */
  42 
  43 #ifdef MAP_ANON
  44         /* BSD */
  45         buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED,
  46                         -1 /* fd */, 0 /* offset */);
  47 #else
  48         buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
  49                         open("/dev/zero", O_RDWR), 0 /* offset */);
  50 #endif
  51 
  52         if (buf == MAP_FAILED) {
  53                 printf("failed to map count buffer: %s\n",
  54                                 strerror(errno));
  55                 return NULL;
  56         }
  57 
  58         return buf;
  59 
  60 }
  61 
  62 static int fork_tcon_client(struct torture_context *tctx,
     /* [<][>][^][v][top][bottom][index][help] */
  63                 int *tcon_count, unsigned tcon_timelimit,
  64                 const char *host, const char *share)
  65 {
  66         pid_t child;
  67         struct smbcli_state *cli;
  68         struct timeval end;
  69         struct timeval now;
  70         struct smbcli_options options;
  71         struct smbcli_session_options session_options;
  72 
  73         lp_smbcli_options(tctx->lp_ctx, &options);
  74         lp_smbcli_session_options(tctx->lp_ctx, &session_options);
  75 
  76         child = fork();
  77         if (child == -1) {
  78                 printf("failed to fork child: %s\n,", strerror(errno));
  79                 return -1;
  80         } else if (child != 0) {
  81                 /* Parent, just return. */
  82                 return 0;
  83         }
  84 
  85         /* Child. Just make as many connections as possible within the
  86          * time limit. Don't bother synchronising the child start times
  87          * because it's probably not work the effort, and a bit of startup
  88          * jitter is probably a more realistic test.
  89          */
  90 
  91 
  92         end = timeval_current();
  93         now = timeval_current();
  94         end.tv_sec += tcon_timelimit;
  95         *tcon_count = 0;
  96 
  97         while (timeval_compare(&now, &end) == -1) {
  98                 NTSTATUS status;
  99 
 100                 status = smbcli_full_connection(NULL, &cli,
 101                                 host, lp_smb_ports(tctx->lp_ctx), share,
 102                                 NULL, lp_socket_options(tctx->lp_ctx), cmdline_credentials,
 103                                 lp_resolve_context(tctx->lp_ctx),
 104                                 tctx->ev, &options, &session_options,
 105                                 lp_iconv_convenience(tctx->lp_ctx),
 106                                 lp_gensec_settings(tctx, tctx->lp_ctx));
 107 
 108                 if (!NT_STATUS_IS_OK(status)) {
 109                         printf("failed to connect to //%s/%s: %s\n",
 110                                 host, share, nt_errstr(status));
 111                         goto done;
 112                 }
 113 
 114                 smbcli_tdis(cli);
 115 
 116                 *tcon_count = *tcon_count + 1;
 117                 now = timeval_current();
 118         }
 119 
 120 done:
 121         exit(0);
 122 }
 123 
 124 static bool children_remain(void)
     /* [<][>][^][v][top][bottom][index][help] */
 125 {
 126         /* Reap as many children as possible. */
 127         for (;;) {
 128                 pid_t ret = waitpid(-1, NULL, WNOHANG);
 129                 if (ret == 0) {
 130                         /* no children ready */
 131                         return true;
 132                 }
 133                 if (ret == -1) {
 134                         /* no children left. maybe */
 135                         return errno == ECHILD ? false : true;
 136                 }
 137         }
 138 
 139         /* notreached */
 140         return false;
 141 }
 142 
 143 static double rate_convert_secs(unsigned count,
     /* [<][>][^][v][top][bottom][index][help] */
 144                 const struct timeval *start, const struct timeval *end)
 145 {
 146         return (double)count /
 147                 usec_to_sec((double)usec_time_diff(end, start));
 148 }
 149 
 150 /* Test the rate at which the server will accept connections.  */
 151 bool torture_bench_treeconnect(struct torture_context *tctx)
     /* [<][>][^][v][top][bottom][index][help] */
 152 {
 153         const char *host = torture_setting_string(tctx, "host", NULL);
 154         const char *share = torture_setting_string(tctx, "share", NULL);
 155 
 156         int timelimit = torture_setting_int(tctx, "timelimit",
 157                                         TIME_LIMIT_SECS);
 158         int nprocs = torture_setting_int(tctx, "nprocs", 4);
 159 
 160         int *curr_counts = map_count_buffer(nprocs, sizeof(int));
 161         int *last_counts = talloc_array(NULL, int, nprocs);
 162 
 163         struct timeval now, last, start;
 164         int i, delta;
 165 
 166         torture_assert(tctx, nprocs > 0, "bad proc count");
 167         torture_assert(tctx, timelimit > 0, "bad timelimit");
 168         torture_assert(tctx, curr_counts, "allocation failure");
 169         torture_assert(tctx, last_counts, "allocation failure");
 170 
 171         start = last = timeval_current();
 172         for (i = 0; i < nprocs; ++i) {
 173                 fork_tcon_client(tctx, &curr_counts[i], timelimit, host, share);
 174         }
 175 
 176         while (children_remain()) {
 177 
 178                 sleep(1);
 179                 now = timeval_current();
 180 
 181                 for (i = 0, delta = 0; i < nprocs; ++i) {
 182                         delta += curr_counts[i] - last_counts[i];
 183                 }
 184 
 185                 printf("%u connections/sec\n",
 186                         (unsigned)rate_convert_secs(delta, &last, &now));
 187 
 188                 memcpy(last_counts, curr_counts, nprocs * sizeof(int));
 189                 last = timeval_current();
 190         }
 191 
 192         now = timeval_current();
 193 
 194         for (i = 0, delta = 0; i < nprocs; ++i) {
 195                 delta += curr_counts[i];
 196         }
 197 
 198         printf("TOTAL: %u connections/sec over %u secs\n",
 199                         (unsigned)rate_convert_secs(delta, &start, &now),
 200                         timelimit);
 201         return true;
 202 }
 203 
 204 /* vim: set sts=8 sw=8 : */

/* [<][>][^][v][top][bottom][index][help] */