"Fossies" - the Fresh Open Source Software Archive

Member "bonnie++-2.00a/bon_file.cpp" (13 Dec 2016, 13506 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 "bon_file.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.97_vs_1.97.3.

    1 #include "bonnie.h"
    2 #include <fcntl.h>
    3 #include <dirent.h>
    4 #include <unistd.h>
    5 #include <string.h>
    6 #include <stdlib.h>
    7 
    8 #include "bon_file.h"
    9 #include "bon_time.h"
   10 #include "duration.h"
   11 
   12 CPCCHAR rand_chars = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   13 
   14 COpenTest::COpenTest(int chunk_size, bool use_sync, bool *doExit)
   15  : m_chunk_size(chunk_size)
   16  , m_number(0)
   17  , m_number_directories(1)
   18  , m_max(0)
   19  , m_min(0)
   20  , m_size_range(0)
   21  , m_dirname(NULL)
   22  , m_file_name_buf(NULL)
   23  , m_file_names(NULL)
   24  , m_sync(use_sync)
   25  , m_directoryHandles(NULL)
   26  , m_dirIndex(NULL)
   27  , m_buf(new char[m_chunk_size])
   28  , m_exit(doExit)
   29  , m_sync_dir(true)
   30 {
   31 }
   32 
   33 void COpenTest::random_sort(Rand &r)
   34 {
   35   for(int i = 0; i < m_number; i++)
   36   {
   37     char *tmp = m_file_names[i];
   38     int newind = r.getNum() % m_number;
   39     m_file_names[i] = m_file_names[newind];
   40     m_file_names[newind] = tmp;
   41     if(m_dirIndex)
   42     {
   43       int tmpInd = m_dirIndex[i];
   44       m_dirIndex[i] = m_dirIndex[newind];
   45       m_dirIndex[newind] = tmpInd;
   46     }
   47     if(*m_exit) return;
   48   }
   49 }
   50 
   51 COpenTest::~COpenTest()
   52 {
   53   int i;
   54   if(m_dirname)
   55   {
   56     fprintf(stderr, "Cleaning up test directory after error.\n");
   57     if(m_file_names)
   58     {
   59       for(i = 0; i < m_number; i++)
   60         unlink(m_file_names[i]);
   61     }
   62     if(m_number_directories > 1)
   63     {
   64       char buf[6];
   65       for(i = 0; i < m_number_directories; i++)
   66       {
   67         sprintf(buf, "%05d", i);
   68         if(rmdir(buf))
   69           io_error("rmdir");
   70       }
   71     }
   72     if(chdir("..") || rmdir(m_dirname))
   73       io_error("rmdir");
   74     delete m_dirname;
   75   }
   76   if(m_directoryHandles)
   77   {
   78     for(i = 0; i < m_number_directories; i++)
   79       close(m_directoryHandles[i]);
   80     delete m_directoryHandles;
   81   }
   82   delete m_file_name_buf;
   83   delete m_file_names;
   84   delete m_dirIndex;
   85   delete m_buf;
   86 }
   87 
   88 void COpenTest::make_names(Rand &r, bool do_random)
   89 {
   90   delete m_file_name_buf;
   91   delete m_file_names;
   92   int names_per_directory = m_number / m_number_directories;
   93   int names_in_dir = 0;
   94   int directory_num = 0;
   95   if(!m_dirIndex && m_sync)
   96     m_dirIndex = new int[m_number];
   97   if(m_number_directories == 1)
   98   {
   99     m_file_name_buf = new char[(MaxNameLen + 1) * m_number];
  100   }
  101   else
  102   {
  103     m_file_name_buf = new char[(MaxNameLen + 1 + 6) * m_number];
  104   }
  105   m_file_names = new PCHAR[m_number];
  106   PCHAR buf = m_file_name_buf;
  107   int num_rand_chars = strlen(rand_chars);
  108   for(int i = 0; i < m_number; i++)
  109   {
  110     if(*m_exit)
  111     {
  112       delete m_file_names;
  113       m_file_names = NULL;
  114       return;
  115     }
  116     char rand_buf[RandExtraLen + 1];
  117     int len = r.getNum() % (RandExtraLen + 1);
  118     int j;
  119     for(j = 0; j < len; j++)
  120     {
  121       rand_buf[j] = rand_chars[r.getNum() % num_rand_chars];
  122     }
  123     rand_buf[j] = '\0';
  124     m_file_names[i] = buf;
  125     if(m_number_directories != 1)
  126     {
  127       sprintf(buf, "%05d/", directory_num);
  128       buf += strlen(buf);
  129     }
  130     if(m_sync)
  131       m_dirIndex[i] = directory_num;
  132     names_in_dir++;
  133     if(names_in_dir > names_per_directory)
  134     {
  135       names_in_dir = 0;
  136       directory_num++;
  137     }
  138     if(do_random)
  139     {
  140       sprintf(buf, "%s%010x", rand_buf, i);
  141     }
  142     else
  143     {
  144       sprintf(buf, "%010x%s", i, rand_buf);
  145     }
  146     buf += strlen(buf) + 1;
  147   }
  148 }
  149 
  150 int COpenTest::create_a_file(const char *filename, char *buf, int size, int dir)
  151 {
  152   FILE_TYPE fd = 0;
  153   int flags = S_IRUSR | S_IWUSR;
  154   fd = file_open(filename, O_CREAT|O_EXCL|O_WRONLY, flags);
  155 
  156   if(fd == -1)
  157   {
  158     fprintf(stderr, "Can't create file %s\n", filename);
  159     return -1;
  160   }
  161   if(m_max)
  162   {
  163     for(int i = 0; i < size; i += m_chunk_size)
  164     {
  165       int to_write = size - i;
  166       if(to_write > m_chunk_size) to_write = m_chunk_size;
  167       if(to_write != write(fd, static_cast<void *>(buf), to_write))
  168       {
  169         fprintf(stderr, "Can't write data.\n");
  170         return -1;
  171       }
  172     }
  173   }
  174   if(m_sync)
  175   {
  176     if(fsync(fd))
  177     {
  178       fprintf(stderr, "Can't sync file.\n");
  179       return -1;
  180     }
  181     if(m_sync_dir && fsync(m_directoryHandles[dir]))
  182     {
  183       fprintf(stderr, "Can't sync directory, turning off dir-sync.\n");
  184       m_sync_dir = false;
  185     }
  186   }
  187   close(fd);
  188   return 0;
  189 }
  190 
  191 int COpenTest::create_a_link(const char *original, const char *filename, int dir)
  192 {
  193   if(m_max == -1)
  194   {
  195     if(link(original, filename))
  196     {
  197       fprintf(stderr, "Can't create link %s\n", filename);
  198       return -1;
  199     }
  200     if(m_sync)
  201     {
  202       if(fsync(m_directoryHandles[dir]))
  203       {
  204         fprintf(stderr, "Can't sync file.\n");
  205         return -1;
  206       }
  207     }
  208   }
  209   else
  210   {
  211     const char *name = strchr(original, '/');
  212     if(name)
  213       name++;
  214     else
  215       name = original;
  216     if(symlink(name, filename))
  217     {
  218       fprintf(stderr, "Can't create symlink %s\n", filename);
  219       return -1;
  220     }
  221     if(m_sync)
  222     {
  223       if(fsync(m_directoryHandles[dir]))
  224       {
  225         fprintf(stderr, "Can't sync file.\n");
  226         return -1;
  227       }
  228     }
  229   }
  230   return 0;
  231 }
  232 
  233 int COpenTest::create(CPCCHAR dirname, BonTimer &timer, int num, int max_size
  234                     , int min_size, int num_directories, bool do_random)
  235 {
  236   if(num_directories >= 100000)
  237   {
  238     fprintf(stderr, "Can't have more than 99,999 directories.\n");
  239     return -1;
  240   }
  241 
  242   m_number = num * DirectoryUnit;
  243   m_number_directories = num_directories;
  244   make_names(timer.random_source, do_random);
  245   m_max = max_size;
  246   m_min = min_size;
  247   m_size_range = m_max - m_min;
  248   m_dirname = new char[strlen(dirname) + 1];
  249   strcpy(m_dirname, dirname);
  250 
  251   if(num_directories >= 100000)
  252   {
  253     fprintf(stderr, "Can't have more than 99,999 directories.\n");
  254     return -1;
  255   }
  256   if(mkdir(dirname, S_IRWXU))
  257   {
  258     fprintf(stderr, "Can't make directory %s\n", dirname);
  259     return -1;
  260   }
  261   if(chdir(dirname))
  262   {
  263     fprintf(stderr, "Can't change to directory %s\n", dirname);
  264     return -1;
  265   }
  266   int i;
  267   if(m_sync)
  268     m_directoryHandles = new FILE_TYPE[num_directories];
  269   if(num_directories > 1)
  270   {
  271     for(i = 0; i < num_directories; i++)
  272     {
  273       sprintf(m_buf, "%05d", i);
  274       if(mkdir(m_buf, S_IRWXU))
  275       {
  276         fprintf(stderr, "Can't make directory %s\n", m_buf);
  277         return -1;
  278       }
  279       if(m_sync)
  280       {
  281         m_directoryHandles[i] = open(m_buf, O_RDONLY);
  282         if(m_directoryHandles[i] == -1)
  283         {
  284           fprintf(stderr, "Can't get directory handle.\n");
  285           return -1;
  286         }
  287       }
  288     }
  289   }
  290   else if(m_sync)
  291   {
  292     m_directoryHandles[0] = open(".", O_RDONLY);
  293     if(m_directoryHandles[0] == -1)
  294     {
  295       fprintf(stderr, "Can't get directory handle.\n");
  296       return -1;
  297     }
  298   }
  299 
  300   Duration dur;
  301   timer.start();
  302   for(i = 0; i < m_number; i++)
  303   {
  304     if(*m_exit)
  305     {
  306       if(m_number_directories != 1 && chdir(".."))
  307       {
  308         fprintf(stderr, "Can't change to directory ..\n");
  309         return -1;
  310       }
  311       return eCtrl_C;
  312     }
  313     dur.start();
  314     // m_max < 0 means link or sym-link
  315     if(m_max < 0)
  316     {
  317       if(i == 0)
  318       {
  319         if(create_a_file(m_file_names[0], m_buf, 0, m_dirIndex ? m_dirIndex[0] : 0))
  320           return -1;
  321       }
  322       else
  323       {
  324         // create_a_link() looks at m_max to see what to do
  325         if(create_a_link(m_file_names[0], m_file_names[i], m_dirIndex ? m_dirIndex[i] : 0))
  326           return -1;
  327       }
  328     }
  329     else
  330     {
  331       int size;
  332       if(m_size_range)
  333         size = m_min + (timer.random_source.getNum() % (m_size_range + 1));
  334       else
  335         size = m_max;
  336       if(create_a_file(m_file_names[i], m_buf, size, m_dirIndex ? m_dirIndex[i] : 0))
  337         return -1;
  338     }
  339     dur.stop();
  340   }
  341   sync();
  342   timer.stop_and_record(do_random ? CreateRand : CreateSeq);
  343   timer.add_latency(do_random ? CreateRand : CreateSeq, dur.getMax());
  344   return 0;
  345 }
  346 
  347 int COpenTest::delete_random(BonTimer &timer)
  348 {
  349   random_sort(timer.random_source);
  350   timer.start();
  351   int i;
  352   Duration dur;
  353   for(i = 0; i < m_number; i++)
  354   {
  355     dur.start();
  356     if(unlink(m_file_names[i]))
  357     {
  358       fprintf(stderr, "Can't delete file %s\n", m_file_names[i]);
  359       return -1;
  360     }
  361     if(m_sync && m_sync_dir)
  362     {
  363       if(fsync(m_directoryHandles[m_dirIndex[i]]))
  364       {
  365         fprintf(stderr, "Can't sync directory, turning off dir-sync.\n");
  366         m_sync_dir = false;
  367       }
  368     }
  369     dur.stop();
  370   }
  371   if(m_number_directories > 1)
  372   {
  373     char buf[6];
  374     for(i = 0; i < m_number_directories; i++)
  375     {
  376       sprintf(buf, "%05d", i);
  377       if(m_sync)
  378       {
  379         close(m_directoryHandles[i]);
  380       }
  381       if(rmdir(buf))
  382       {
  383         io_error("rmdir");
  384         return -1;
  385       }
  386     }
  387   }
  388   else
  389   {
  390     if(m_sync)
  391     {
  392       close(m_directoryHandles[0]);
  393     }
  394   }
  395   if(chdir("..") || rmdir(m_dirname))
  396   {
  397     io_error("rmdir");
  398     return -1;
  399   }
  400   delete m_dirname;
  401   m_dirname = NULL;
  402   sync();
  403   timer.stop_and_record(DelRand);
  404   timer.add_latency(DelRand, dur.getMax());
  405   return 0;
  406 }
  407 
  408 int COpenTest::delete_sequential(BonTimer &timer)
  409 {
  410   timer.start();
  411   int count = 0;
  412   Duration dur;
  413   for(int i = 0; i < m_number_directories; i++)
  414   {
  415     char buf[6];
  416     if(m_number_directories != 1)
  417     {
  418       sprintf(buf, "%05d", i);
  419       if(chdir(buf))
  420       {
  421         fprintf(stderr, "Can't change to directory %s\n", buf);
  422         return -1;
  423       }
  424     }
  425     DIR *d = opendir(".");
  426     if(!d)
  427     {
  428       fprintf(stderr, "Can't open directory.\n");
  429       if(m_number_directories != 1)
  430       {
  431         if(chdir(".."))
  432           fprintf(stderr, "Can't chdir().\n");
  433       }
  434       return -1;
  435     }
  436     dirent *file_ent;
  437 
  438     while(1)
  439     {
  440       dur.start();
  441       file_ent = readdir(d);
  442       if(file_ent == NULL)
  443         break;
  444       if(file_ent->d_name[0] != '.')
  445       {
  446         if(unlink(file_ent->d_name))
  447         {
  448           fprintf(stderr, "Can't delete file %s\n", file_ent->d_name);
  449           return -1;
  450         }
  451 
  452 
  453         if(m_sync && m_sync_dir)
  454         {
  455           if(fsync(m_directoryHandles[i]))
  456           {
  457             fprintf(stderr, "Can't sync directory, turning off dir-sync.\n");
  458             m_sync_dir = false;
  459           }
  460         }
  461         count++;
  462       }
  463       dur.stop();
  464     }
  465     closedir(d);
  466     if(m_sync)
  467     {
  468       close(m_directoryHandles[i]);
  469     }
  470     if(m_number_directories != 1)
  471     {
  472       if(chdir("..") || rmdir(buf))
  473       {
  474         io_error("rmdir");
  475         return -1;
  476       }
  477     }
  478   }
  479   if(chdir("..") || rmdir(m_dirname))
  480   {
  481     io_error("rmdir");
  482     return -1;
  483   }
  484   delete m_dirname;
  485   m_dirname = NULL;
  486   if(count != m_number)
  487   {
  488     fprintf(stderr, "Expected %d files but only got %d\n", m_number, count);
  489     return -1;
  490   }
  491   sync();
  492   timer.stop_and_record(DelSeq);
  493   timer.add_latency(DelSeq, dur.getMax());
  494   return 0;
  495 }
  496 
  497 int COpenTest::stat_file(CPCCHAR file)
  498 {
  499   struct stat st;
  500   if(stat(file, &st))
  501   {
  502     fprintf(stderr, "Can't stat file %s\n", file);
  503     return -1;
  504   }
  505   if(st.st_size)
  506   {
  507     FILE_TYPE fd = 0;
  508     int flags = O_RDONLY;
  509     fd = open(file, flags);
  510     if(fd == -1)
  511     {
  512       fprintf(stderr, "Can't open file %s\n", file);
  513       return -1;
  514     }
  515     for(int i = 0; i < st.st_size; i += m_chunk_size)
  516     {
  517       int to_read = st.st_size - i;
  518       if(to_read > m_chunk_size)
  519         to_read = m_chunk_size;
  520 
  521       if(to_read != read(fd, static_cast<void *>(m_buf), to_read))
  522       {
  523         fprintf(stderr, "Can't read data.\n");
  524         return -1;
  525       }
  526     }
  527     close(fd);
  528   }
  529   return 0;
  530 }
  531 
  532 int COpenTest::stat_random(BonTimer &timer)
  533 {
  534   random_sort(timer.random_source);
  535   timer.start();
  536 
  537   int i;
  538   Duration dur;
  539   for(i = 0; i < m_number; i++)
  540   {
  541     dur.start();
  542     if(-1 == stat_file(m_file_names[i]))
  543       return -1;
  544     dur.stop();
  545   }
  546   timer.stop_and_record(StatRand);
  547   timer.add_latency(StatRand, dur.getMax());
  548   return 0;
  549 }
  550 
  551 int COpenTest::stat_sequential(BonTimer &timer)
  552 {
  553   timer.start();
  554   int count = 0;
  555   Duration dur;
  556   for(int i = 0; i < m_number_directories; i++)
  557   {
  558     char buf[6];
  559     if(m_number_directories != 1)
  560     {
  561       sprintf(buf, "%05d", i);
  562       if(chdir(buf))
  563       {
  564         fprintf(stderr, "Can't change to directory %s\n", buf);
  565         return -1;
  566       }
  567     }
  568     DIR *d = opendir(".");
  569     if(!d)
  570     {
  571       fprintf(stderr, "Can't open directory.\n");
  572       if(m_number_directories != 1)
  573       {
  574         if(chdir(".."))
  575           fprintf(stderr, "Can't chdir().\n");
  576       }
  577       return -1;
  578     }
  579     dirent *file_ent;
  580     while(1)
  581     {
  582       dur.start();
  583       file_ent = readdir(d);
  584       if(file_ent == NULL)
  585         break;
  586       if(*m_exit)
  587       {
  588         if(m_number_directories != 1 && chdir(".."))
  589         {
  590           fprintf(stderr, "Can't change to directory ..\n");
  591           return -1;
  592         }
  593         return eCtrl_C;
  594       }
  595       if(file_ent->d_name[0] != '.') // our files do not start with a dot
  596       {
  597         if(-1 == stat_file(file_ent->d_name))
  598         {
  599           if(m_number_directories != 1)
  600           {
  601             if(chdir(".."))
  602             {
  603               fprintf(stderr, "Can't chdir().\n");
  604               return -1;
  605             }
  606           }
  607           dur.stop();
  608           return -1;
  609         }
  610         count++;
  611         dur.stop();
  612       }
  613     }
  614     closedir(d);
  615     if(m_number_directories != 1)
  616     {
  617       if(chdir(".."))
  618       {
  619         fprintf(stderr, "Can't change to directory ..\n");
  620         return -1;
  621       }
  622     }
  623   }
  624   if(count != m_number)
  625   {
  626     fprintf(stderr, "Expected %d files but only got %d\n", m_number, count);
  627     return -1;
  628   }
  629   timer.stop_and_record(StatSeq);
  630   timer.add_latency(StatSeq, dur.getMax());
  631   return 0;
  632 }
  633