"Fossies" - the Fresh Open Source Software Archive

Member "bonnie++-2.00a/zcav_io.cpp" (23 Nov 2012, 6073 Bytes) of package /linux/privat/bonnie++-2.00a.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_io.cpp" see the Fossies "Dox" file reference documentation.

    1 #include "zcav_io.h"
    2 
    3 #include <unistd.h>
    4 #include <sys/resource.h>
    5 #include <sys/time.h>
    6 #include <time.h>
    7 #include <stdlib.h>
    8 #include <string.h>
    9 
   10 ZcavRead::~ZcavRead()
   11 {
   12   delete m_name;
   13 }
   14 
   15 int ZcavRead::Open(bool *finished, int block_size, const char *file
   16                  , const char *log, int chunk_size, int do_write)
   17 {
   18   m_name = strdup(file);
   19   m_finished = finished;
   20   m_block_size = block_size;
   21   m_chunk_size = chunk_size;
   22   m_do_write = do_write;
   23   m_buf = calloc(chunk_size * MEG, 1);
   24 
   25   if(strcmp(file, "-"))
   26   {
   27     if(m_do_write)
   28       m_fd = file_open(file, O_WRONLY);
   29     else
   30       m_fd = file_open(file, O_RDONLY);
   31     if(m_fd == -1)
   32     {
   33       fprintf(stderr, "Can't open %s\n", file);
   34       return 1;
   35     }
   36   }
   37   else
   38   {
   39     m_fd = 0;
   40   }
   41   if(strcmp(log, "-"))
   42   {
   43     m_logFile = true;
   44     m_log = fopen(log, "w");
   45     if(m_log == NULL)
   46     {
   47       fprintf(stderr, "Can't open %s\n", log);
   48       close(m_fd);
   49       return 1;
   50     }
   51   }
   52   else
   53   {
   54     m_logFile = false;
   55     m_log = stdout;
   56   }
   57   return 0;
   58 }
   59 
   60 void ZcavRead::Close()
   61 {
   62   if(m_logFile)
   63     fclose(m_log);
   64   if(m_fd != 0)
   65     ::close(m_fd);
   66 }
   67 
   68 int ZcavRead::writeStatus(int fd, char c)
   69 {
   70   if(write(fd, &c, 1) != 1)
   71   {
   72     fprintf(stderr, "Write channel broken\n");
   73     return 1;
   74   }
   75   return 0;
   76 }
   77 
   78 int ZcavRead::Read(int max_loops, int max_size, int writeCom, int skip_rate, int start_offset)
   79 {
   80   bool exiting = false;
   81   if(max_loops == 1)
   82     fprintf(m_log, "#block offset (GiB), MiB/s, time\n");
   83   for(int loops = 0; !exiting && loops < max_loops; loops++)
   84   {
   85     int i = 0;
   86 #ifdef _LARGEFILE64_SOURCE
   87     if(start_offset)
   88     {
   89       OFF_TYPE real_offset = OFF_TYPE(start_offset) * OFF_TYPE(m_block_size) * OFF_TYPE(1<<20);
   90       if(file_lseek(m_fd, real_offset, SEEK_CUR) == OFF_TYPE(-1))
   91       {
   92         fprintf(stderr, "Can't lseek().\n");
   93         writeStatus(writeCom, eSEEK);
   94         return 1;
   95       }
   96       i = start_offset;
   97     }
   98     else
   99 #endif
  100     if(lseek(m_fd, 0, SEEK_SET))
  101     {
  102       fprintf(stderr, "Can't lseek().\n");
  103       writeStatus(writeCom, eSEEK);
  104       return 1;
  105     }
  106 
  107     // i is block index
  108     double total_read_time = 0.0;
  109     bool nextLoop = false;
  110     for( ; !nextLoop && (!max_size || i < max_size)
  111               && (loops == 0 || (m_times[i] && m_times[i][0] != -1.0))
  112               && (!max_size || i < max_size); i++)
  113     {
  114       double read_time = access_data(i ? skip_rate - 1 : 0);
  115       if(read_time < 0.0)
  116       {
  117         if(i == 0)
  118         {
  119           fprintf(stderr, "Data file/device \"%s\" too small.\n", m_name);
  120           writeStatus(writeCom, eSIZE);
  121           return 1;
  122         }
  123         nextLoop = true;
  124         break;
  125       }
  126       total_read_time += read_time;
  127       if(max_loops == 1)
  128       {
  129         printavg(i * skip_rate, read_time, m_block_size);
  130       }
  131       else
  132       {
  133         if(loops == 0)
  134         {
  135           m_times.push_back(new double[max_loops]);
  136           m_count.push_back(0);
  137         }
  138         m_times[i][loops] = read_time;
  139         m_count[i]++;
  140       }
  141     } // end loop for reading blocks
  142 
  143     time_t now = time(NULL);
  144     struct tm *cur_time = localtime(&now);
  145     fprintf(stderr, "# Finished loop %d, on device %s at %d:%02d:%02d\n"
  146           , loops + 1, m_name, cur_time->tm_hour, cur_time->tm_min
  147           , cur_time->tm_sec);
  148     fprintf(m_log, "# Read %d megs in %d seconds, %d megabytes per second.\n"
  149          , i * m_block_size, int(total_read_time)
  150          , int(double(i * m_block_size) / total_read_time));
  151 
  152     if(exiting)
  153       return 1;
  154   } // end loop for multiple disk reads
  155   if(max_loops > 1)
  156   {
  157     fprintf(m_log, "#loops: %d\n", max_loops);
  158     fprintf(m_log, "#block offset (GiB), MiB/s, time\n");
  159     for(int i = 0; m_times[i]; i++)
  160       printavg(i * skip_rate, average(m_times[i], m_count[i]), m_block_size);
  161   }
  162   writeStatus(writeCom, eEND);
  163   return 0;
  164 }
  165 
  166 void ZcavRead::printavg(int position, double avg, int block_size)
  167 {
  168   if(avg < 1.0)
  169     fprintf(m_log, "#%.2f ++++ %.3f\n", float(position) * float(block_size) / 1024.0, avg);
  170   else
  171     fprintf(m_log, "%.2f %.2f %.3f\n", float(position) * float(block_size) / 1024.0, double(block_size) / avg, avg);
  172 }
  173 
  174 int compar(const void *a, const void *b)
  175 {
  176   double *c = (double *)(a);
  177   double *d = (double *)(b);
  178   if(*c < *d) return -1;
  179   if(*c > *d) return 1;
  180   return 0;
  181 }
  182 
  183 // Returns the mean of the values in the array.  If the array contains
  184 // more than 2 items then discard the highest and lowest thirds of the
  185 // results before calculating the mean.
  186 double average(double *array, int count)
  187 {
  188   qsort(array, count, sizeof(double), compar);
  189   int skip = count / 3;
  190   int arr_items = count - (skip * 2);
  191   double total = 0.0;
  192   for(int i = skip; i < (count - skip); i++)
  193   {
  194     total += double(array[i]);
  195   }
  196   return total / double(arr_items);
  197 }
  198 
  199 // just like read() or write() but will not return a partial result and the
  200 // size is expressed in MEG.
  201 ssize_t ZcavRead::access_all(int count)
  202 {
  203   ssize_t total = 0;
  204   count *= MEG;
  205   while(total != static_cast<ssize_t>(count) )
  206   {
  207     ssize_t rc;
  208     // for both read and write just pass the base address of the buffer
  209     // as we don't care for the data, if we ever do checksums we have to
  210     // change this
  211     if(m_do_write)
  212       rc = write(m_fd, m_buf, count - total);
  213     else
  214       rc = read(m_fd, m_buf, count - total);
  215     if(rc == -1 || rc == 0)
  216       return -1;
  217     total += rc;
  218   }
  219   if(m_do_write && fsync(m_fd))
  220     return -1;
  221   return total / MEG;
  222 }
  223 
  224 // Read/write a block of data
  225 double ZcavRead::access_data(int skip)
  226 {
  227 #ifdef _LARGEFILE64_SOURCE
  228   if(skip)
  229   {
  230     OFF_TYPE real_offset = OFF_TYPE(skip) * OFF_TYPE(m_block_size) * OFF_TYPE(1<<20);
  231     if(file_lseek(m_fd, real_offset, SEEK_CUR) == OFF_TYPE(-1))
  232       return -1.0;
  233   }
  234 #endif
  235 
  236   m_dur.start();
  237   for(int i = 0; i < m_block_size; i+= m_chunk_size)
  238   {
  239     int access_size = m_chunk_size;
  240     if(i + m_chunk_size > m_block_size)
  241       access_size = m_block_size - i;
  242     int rc = access_all(access_size);
  243     if(rc != access_size)
  244       return -1.0;
  245   }
  246   return m_dur.stop();
  247 }
  248