"Fossies" - the Fresh Open Source Software Archive

Member "bonnie++-1.04/zcav.cpp" (5 Sep 2017, 8306 Bytes) of package /linux/privat/bonnie++_1.04.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "zcav.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.03e_vs_1.04.

    1 
    2 using namespace std;
    3 
    4 #include <unistd.h>
    5 #include <sys/time.h>
    6 #include <sys/resource.h>
    7 #include <time.h>
    8 #include <cstdlib>
    9 #include <cstring>
   10 #include "bonnie.h"
   11 #ifdef HAVE_VECTOR
   12 #include <vector>
   13 #else
   14 #include <vector.h>
   15 #endif
   16 
   17 // Read the specified number of megabytes of data from the fd and return the
   18 // amount of time elapsed in seconds.
   19 double access_data(int fd, int size, void *buf, int chunk_size, int do_write);
   20 
   21 // Returns the mean of the values in the array.  If the array contains
   22 // more than 2 items then discard the highest and lowest thirds of the
   23 // results before calculating the mean.
   24 double average(double *array, int count);
   25 void printavg(int position, double avg, int block_size);
   26 
   27 const int MEG = 1024*1024;
   28 const int DEFAULT_CHUNK_SIZE = 1;
   29 typedef double *PDOUBLE;
   30 
   31 void usage()
   32 {
   33   printf("Usage: zcav [-b block-size] [-c count] [-n number of megs to read]\n"
   34          "            [-u uid-to-use:gid-to-use] [-g gid-to-use]\n"
   35          "            [-f] file-name\n"
   36          "File name of \"-\" means standard input\n"
   37          "Count is the number of times to read the data (default 1).\n"
   38          "Version: " BON_VERSION "\n");
   39   exit(1);
   40 }
   41 
   42 int main(int argc, char *argv[])
   43 {
   44   vector<double *> times;
   45   vector<int> count;
   46   int block_size = 256;
   47 
   48   int max_loops = 1, pass_size = 0, chunk_size = DEFAULT_CHUNK_SIZE;
   49   int do_write = 0;
   50   char *file_name = NULL;
   51 
   52   char *userName = NULL, *groupName = NULL;
   53   int c;
   54   while(-1 != (c = getopt(argc, argv, "-c:b:f:g:n:u:w")) )
   55   {
   56     switch(char(c))
   57     {
   58       case 'b':
   59       {
   60         int rc = sscanf(optarg, "%d:%d", &block_size, &chunk_size);
   61         if(rc == 1)
   62           chunk_size = DEFAULT_CHUNK_SIZE;
   63         else if(rc != 2)
   64           usage();
   65       }
   66       break;
   67       case 'c':
   68         max_loops = atoi(optarg);
   69       break;
   70       case 'g':
   71         if(groupName)
   72           usage();
   73         groupName = optarg;
   74       break;
   75       case 'u':
   76       {
   77         if(userName)
   78           usage();
   79         userName = strdup(optarg);
   80         int i;
   81         for(i = 0; userName[i] && userName[i] != ':'; i++)
   82         {}
   83         if(userName[i] == ':')
   84         {
   85           if(groupName)
   86             usage();
   87           userName[i] = '\0';
   88           groupName = &userName[i + 1];
   89         }
   90       }
   91       break;
   92       case 'n':
   93         pass_size = atoi(optarg);
   94       break;
   95       case 'w':
   96         do_write = 1;
   97       break;
   98       case 'f':
   99       case char(1):
  100         file_name = optarg;
  101       break;
  102       default:
  103         usage();
  104     }
  105   }
  106 
  107   pass_size = pass_size / block_size;
  108 
  109   if(userName || groupName)
  110   {
  111     if(bon_setugid(userName, groupName, false))
  112       return 1;
  113     if(userName)
  114       free(userName);
  115   }
  116 
  117   if(max_loops < 1 || block_size < 1 || chunk_size < 1
  118     || chunk_size > block_size)
  119     usage();
  120   if(!file_name)
  121     usage();
  122   printf("#loops: %d, version: %s\n", max_loops, BON_VERSION);
  123 
  124   int i;
  125   void *buf = calloc(chunk_size * MEG, 1);
  126   int fd;
  127   if(strcmp(file_name, "-"))
  128   {
  129     if(do_write)
  130       fd = open(file_name, O_WRONLY);
  131     else
  132       fd = open(file_name, O_RDONLY);
  133     if(fd == -1)
  134     {
  135       printf("Can't open %s\n", file_name);
  136       return 1;
  137     }
  138   }
  139   else
  140   {
  141     fd = 0;
  142   }
  143   if(max_loops > 1)
  144   {
  145     struct stat stat_out, stat_err;
  146     if(fstat(1, &stat_out) || fstat(2, &stat_err))
  147     {
  148       printf("Can't stat stdout/stderr.\n");
  149       return 1;
  150     }
  151     for(int loops = 0; loops < max_loops; loops++)
  152     {
  153       if(lseek(fd, 0, SEEK_SET))
  154       {
  155         printf("Can't llseek().\n");
  156         return 1;
  157       }
  158       double total_read_time = 0.0;
  159       for(i = 0; (loops == 0 || times[0][i] != -1.0) && (!pass_size || i < pass_size); i++)
  160       {
  161         double read_time = access_data(fd, block_size, buf, chunk_size, do_write);
  162         total_read_time += read_time;
  163         if(loops == 0)
  164         {
  165           times.push_back(new double[max_loops]);
  166           count.push_back(0);
  167         }
  168         times[i][loops] = read_time;
  169         if(read_time < 0.0)
  170         {
  171           if(i == 0)
  172           {
  173             fprintf(stderr, "Data file/device too small.\n");
  174             return 1;
  175           }
  176           times[i][0] = -1.0;
  177           break;
  178         }
  179         count[i]++;
  180       }
  181       time_t now = time(NULL);
  182       struct tm *cur_time = localtime(&now);
  183       fprintf(stderr, "# Finished loop %d, %d:%02d:%02d\n", loops + 1
  184             , cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec);
  185       printf("# Read %d gigs in %d seconds, %d megabytes per second.\n"
  186            , i * block_size / 1024, int(total_read_time)
  187            , int(double(i * block_size) / total_read_time));
  188       if(stat_out.st_dev != stat_err.st_dev || stat_out.st_ino != stat_err.st_ino)
  189       {
  190         fprintf(stderr, "Read %d gigs in %d seconds, %d megabytes per second.\n"
  191              , i * block_size / 1024, int(total_read_time)
  192              , int(double(i * block_size) / total_read_time));
  193       }
  194     }
  195     printf("#\n#block offset (GiB), MiB/s, time\n");
  196     for(i = 0; count[i]; i++)
  197     {
  198       printavg(i, average(times[i], count[i]), block_size);
  199     }
  200   }
  201   else
  202   {
  203     printf("#block offset (GiB), MiB/s, time\n");
  204     double total_read_time = 0.0;
  205     for(i = 0; !pass_size || i < pass_size; i++)
  206     {
  207       double read_time = access_data(fd, block_size, buf, chunk_size, do_write);
  208       if(read_time < 0.0)
  209         break;
  210       printavg(i, read_time, block_size);
  211       total_read_time += read_time;
  212     }
  213     if(i == 0)
  214     {
  215       fprintf(stderr, "File/device too small.\n");
  216       return 1;
  217     }
  218     printf("# Read %d gigs in %d seconds, %d megabytes per second.\n"
  219          , i * block_size / 1024, int(total_read_time)
  220          , int(double(i * block_size) / total_read_time));
  221   }
  222   return 0;
  223 }
  224 
  225 void printavg(int position, double avg, int block_size)
  226 {
  227   if(avg < MinTime)
  228     printf("#%.2f ++++ %.3f \n", float(position) * float(block_size) / 1024.0, avg);
  229   else
  230     printf("%.2f %.2f %.3f\n", float(position) * float(block_size) / 1024.0, float(double(block_size) / avg), avg);
  231 }
  232 
  233 int compar(const void *a, const void *b)
  234 {
  235   double *c = (double *)(a);
  236   double *d = (double *)(b);
  237   if(*c < *d) return -1;
  238   if(*c > *d) return 1;
  239   return 0;
  240 }
  241 
  242 // Returns the mean of the values in the array.  If the array contains
  243 // more than 2 items then discard the highest and lowest thirds of the
  244 // results before calculating the mean.
  245 double average(double *array, int count)
  246 {
  247   qsort(array, count, sizeof(double), compar);
  248   int skip = count / 3;
  249   int arr_items = count - (skip * 2);
  250   double total = 0.0;
  251   for(int i = skip; i < (count - skip); i++)
  252   {
  253     total += array[i];
  254   }
  255   return total / arr_items;
  256 }
  257 
  258 // just like read() or write() but will not return a partial result and the
  259 // size is expressed in MEG.
  260 ssize_t access_all(int fd, void *buf, size_t chunk_size, int do_write)
  261 {
  262   ssize_t total = 0;
  263   chunk_size *= MEG;
  264   while(total != static_cast<ssize_t>(chunk_size) )
  265   {
  266     ssize_t rc;
  267     // for both read and write just pass the base address of the buffer
  268     // as we don't care for the data, if we ever do checksums we have to
  269     // change this
  270     if(do_write)
  271       rc = write(fd, buf, chunk_size - total);
  272     else
  273       rc = read(fd, buf, chunk_size - total);
  274     if(rc == -1 || rc == 0)
  275       return -1;
  276     total += rc;
  277   }
  278   if(do_write && fsync(fd))
  279     return -1;
  280   return total / MEG;
  281 }
  282 
  283 // Read the specified number of megabytes of data from the fd and return the
  284 // amount of time elapsed in seconds.  If do_write == 1 then write data.
  285 double access_data(int fd, int size, void *buf, int chunk_size, int do_write)
  286 {
  287   struct timeval tp;
  288  
  289   if (gettimeofday(&tp, static_cast<struct timezone *>(NULL)) == -1)
  290   {
  291     printf("Can't get time.\n");
  292     return -1.0;
  293   }
  294   double start = double(tp.tv_sec) +
  295     (double(tp.tv_usec) / 1000000.0);
  296 
  297   for(int i = 0; i < size; i += chunk_size)
  298   {
  299     int access_size = chunk_size;
  300     if(i + chunk_size > size)
  301       access_size = size - i;
  302     int rc = access_all(fd, buf, access_size, do_write);
  303     if(rc != access_size)
  304       return -1.0;
  305   }
  306   if (gettimeofday(&tp, static_cast<struct timezone *>(NULL)) == -1)
  307   {
  308     printf("Can't get time.\n");
  309     return -1.0;
  310   }
  311   return (double(tp.tv_sec) + (double(tp.tv_usec) / 1000000.0))
  312         - start;
  313 }
  314