Statistics
| Branch: | Revision:

root / synthbench / bonnie++ / .svn / text-base / bon_file.cpp.svn-base @ 0:839f52ef7657

History | View | Annotate | Download (14.6 kB)

1
#include <fcntl.h>
2
#include <sys/types.h>
3
#ifdef OS2
4
#define INCL_DOSFILEMGR
5
#include <os2.h>
6
#else
7
#include <dirent.h>
8
#include <unistd.h>
9
#endif
10
#include <string.h>
11
#include <stdlib.h>
12
#include <sys/stat.h>
13

    
14
#include "bon_file.h"
15
#include "bon_time.h"
16

    
17
CPCCHAR rand_chars = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
18

    
19

    
20
COpenTest::COpenTest(int chunk_size, bool use_sync, bool *doExit)
21
 : m_chunk_size(chunk_size)
22
 , m_number(0)
23
 , m_number_directories(1)
24
 , m_max(0)
25
 , m_min(0)
26
 , m_size_range(0)
27
 , m_dirname(NULL)
28
 , m_file_name_buf(NULL)
29
 , m_file_names(NULL)
30
 , m_sync(use_sync)
31
 , m_directoryHandles(NULL)
32
 , m_dirIndex(NULL)
33
 , m_buf(new char[m_chunk_size])
34
 , m_exit(doExit)
35
 , m_sync_dir(true)
36
{
37
}
38

    
39
void COpenTest::random_sort()
40
{
41
  for(int i = 0; i < m_number; i++)
42
  {
43
    char *tmp = m_file_names[i];
44
    int newind = rand() % m_number;
45
    m_file_names[i] = m_file_names[newind];
46
    m_file_names[newind] = tmp;
47
    if(m_dirIndex)
48
    {
49
      int tmpInd = m_dirIndex[i];
50
      m_dirIndex[i] = m_dirIndex[newind];
51
      m_dirIndex[newind] = tmpInd;
52
    }
53
    if(*m_exit) return;
54
  }
55
}
56

    
57
COpenTest::~COpenTest()
58
{
59
  int i;
60
  if(m_dirname)
61
  {
62
    fprintf(stderr, "Cleaning up test directory after error.\n");
63
    if(m_file_names)
64
    {
65
      for(i = 0; i < m_number; i++)
66
        unlink(m_file_names[i]);
67
    }
68
    if(m_number_directories > 1)
69
    {
70
      char buf[6];
71
      for(i = 0; i < m_number_directories; i++)
72
      {
73
        sprintf(buf, "%05d", i);
74
        if(rmdir(buf))
75
          io_error("rmdir");
76
      }
77
    }
78
    if(chdir("..") || rmdir(m_dirname))
79
      io_error("rmdir");
80
    delete m_dirname;
81
  }
82
  if(m_directoryHandles)
83
  {
84
    for(i = 0; i < m_number_directories; i++)
85
      close(m_directoryHandles[i]);
86
    delete m_directoryHandles;
87
  }
88
  delete m_file_name_buf;
89
  delete m_file_names;
90
  delete m_dirIndex;
91
  delete m_buf;
92
}
93

    
94
void COpenTest::make_names(bool do_random)
95
{
96
  delete m_file_name_buf;
97
  delete m_file_names;
98
  int names_per_directory = m_number / m_number_directories;
99
  int names_in_dir = 0;
100
  int directory_num = 0;
101
  if(!m_dirIndex && m_sync)
102
    m_dirIndex = new int[m_number];
103
  if(m_number_directories == 1)
104
  {
105
    m_file_name_buf = new char[(MaxNameLen + 1) * m_number];
106
  }
107
  else
108
  {
109
    m_file_name_buf = new char[(MaxNameLen + 1 + 6) * m_number];
110
  }
111
  m_file_names = new PCHAR[m_number];
112
  PCHAR buf = m_file_name_buf;
113
  for(int i = 0; i < m_number; i++)
114
  {
115
    if(*m_exit)
116
    {
117
      delete m_file_names;
118
      m_file_names = NULL;
119
      return;
120
    }
121
    char rand_buf[RandExtraLen + 1];
122
    int len = rand() % (RandExtraLen + 1);
123
    int j;
124
    for(j = 0; j < len; j++)
125
    {
126
      rand_buf[j] = rand_chars[rand() % strlen(rand_chars)];
127
    }
128
    rand_buf[j] = '\0';
129
    m_file_names[i] = buf;
130
    if(m_number_directories != 1)
131
    {
132
      sprintf(buf, "%05d/", directory_num);
133
      buf += strlen(buf);
134
    }
135
    if(m_sync)
136
      m_dirIndex[i] = directory_num;
137
    names_in_dir++;
138
    if(names_in_dir > names_per_directory)
139
    {
140
      names_in_dir = 0;
141
      directory_num++;
142
    }
143
    if(do_random)
144
    {
145
      sprintf(buf, "%s%07d", rand_buf, i);
146
    }
147
    else
148
    {
149
      sprintf(buf, "%07d%s", i, rand_buf);
150
    }
151
    buf += strlen(buf) + 1;
152
  }
153
}
154

    
155
int COpenTest::create_a_file(const char *filename, char *buf, int size, int dir)
156
{
157
  FILE_TYPE fd = 0;
158
#ifdef OS2
159
  ULONG action = 0;
160
  ULONG rc = DosOpen(filename, &fd, &action, 0, FILE_NORMAL
161
                   , OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS
162
                   , OPEN_FLAGS_SEQUENTIAL | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE
163
                   , NULL);
164
#else
165
  fd = creat(filename, S_IRUSR | S_IWUSR);
166
#endif
167
  if(fd == -1)
168
  {
169
    fprintf(stderr, "Can't create file %s\n", filename);
170
    return -1;
171
  }
172
  if(m_max)
173
  {
174
    for(int i = 0; i < size; i += m_chunk_size)
175
    {
176
      int to_write = size - i;
177
      if(to_write > m_chunk_size) to_write = m_chunk_size;
178
#ifdef OS2
179
      ULONG actual = 0;
180
      if(DosWrite(fd, PVOID(buf), to_write, &actual))
181
      {
182
        fprintf(stderr, "Can't write data.\n");
183
        return -1;
184
      }
185
#else
186
      if(to_write != write(fd, static_cast<void *>(buf), to_write))
187
      {
188
        fprintf(stderr, "Can't write data.\n");
189
        return -1;
190
      }
191
#endif
192
    }
193
  }
194
  if(m_sync)
195
  {
196
    if(fsync(fd))
197
    {
198
      fprintf(stderr, "Can't sync file.\n");
199
      return -1;
200
    }
201
    if(m_sync_dir && fsync(m_directoryHandles[dir]))
202
    {
203
      fprintf(stderr, "Can't sync directory, turning off dir-sync.\n");
204
      m_sync_dir = false;
205
    }
206
  }
207
  file_close(fd);
208
  return 0;
209
}
210

    
211
int COpenTest::create_a_link(const char *original, const char *filename, int dir)
212
{
213
#ifdef OS2
214
  fprintf(stderr, "Not supported on OS/2\n");
215
  return -1;
216
#else
217
  if(m_max == -1)
218
  {
219
    if(link(original, filename))
220
    {
221
      fprintf(stderr, "Can't create link %s\n", filename);
222
      return -1;
223
    }
224
    if(m_sync)
225
    {
226
      if(fsync(m_directoryHandles[dir]))
227
      {
228
        fprintf(stderr, "Can't sync file.\n");
229
        return -1;
230
      }
231
    }
232
  }
233
  else
234
  {
235
    if(symlink(original, filename))
236
    {
237
      fprintf(stderr, "Can't create symlink %s\n", filename);
238
      return -1;
239
    }
240
    if(m_sync)
241
    {
242
      if(fsync(m_directoryHandles[dir]))
243
      {
244
        fprintf(stderr, "Can't sync file.\n");
245
        return -1;
246
      }
247
    }
248
  }
249
  return 0;
250
#endif
251
}
252

    
253
int COpenTest::create(CPCCHAR dirname, BonTimer &timer, int num, int max_size
254
                    , int min_size, int num_directories, bool do_random)
255
{
256
  if(num_directories >= 100000)
257
  {
258
    fprintf(stderr, "Can't have more than 99,999 directories.\n");
259
    return -1;
260
  }
261

    
262
  m_number = num * DirectoryUnit;
263
  m_number_directories = num_directories;
264
  make_names(do_random);
265
  m_max = max_size;
266
  m_min = min_size;
267
  m_size_range = m_max - m_min;
268
  m_dirname = new char[strlen(dirname) + 1];
269
  strcpy(m_dirname, dirname);
270

    
271
  if(make_directory(dirname))
272
  {
273
    fprintf(stderr, "Can't make directory %s\n", dirname);
274
    return -1;
275
  }
276
  if(chdir(dirname))
277
  {
278
    fprintf(stderr, "Can't change to directory %s\n", dirname);
279
    return -1;
280
  }
281
  int i;
282
  if(m_sync)
283
    m_directoryHandles = new FILE_TYPE[num_directories];
284
  if(num_directories > 1)
285
  {
286
    for(i = 0; i < num_directories; i++)
287
    {
288
      sprintf(m_buf, "%05d", i);
289
      if(make_directory(m_buf))
290
      {
291
        fprintf(stderr, "Can't make directory %s\n", m_buf);
292
        return -1;
293
      }
294
      if(m_sync)
295
      {
296
        m_directoryHandles[i] = open(m_buf, O_RDONLY);
297
        if(m_directoryHandles[i] == -1)
298
        {
299
          fprintf(stderr, "Can't get directory handle.\n");
300
          return -1;
301
        }
302
      }
303
    }
304
  }
305
  else if(m_sync)
306
  {
307
    m_directoryHandles[0] = open(".", O_RDONLY);
308
    if(m_directoryHandles[0] == -1)
309
    {
310
      fprintf(stderr, "Can't get directory handle.\n");
311
      return -1;
312
    }
313
  }
314

    
315
  timer.timestamp();
316
  for(i = 0; i < m_number; i++)
317
  {
318
    if(*m_exit)
319
    {
320
      return EXIT_CTRL_C;
321
    }
322
    // m_max < 0 means link or sym-link
323
    if(m_max < 0)
324
    {
325
      if(i == 0)
326
      {
327
        if(create_a_file(m_file_names[0], m_buf, 0, m_dirIndex ? m_dirIndex[0] : 0))
328
          return -1;
329
      }
330
      else
331
      {
332
        // create_a_link() looks at m_max to see what to do
333
        if(create_a_link(m_file_names[0], m_file_names[i], m_dirIndex ? m_dirIndex[i] : 0))
334
          return -1;
335
      }
336
    }
337
    else
338
    {
339
      int size;
340
      if(m_size_range)
341
        size = m_min + (rand() % (m_size_range + 1));
342
      else
343
        size = m_max;
344
      if(create_a_file(m_file_names[i], m_buf, size, m_dirIndex ? m_dirIndex[i] : 0))
345
        return -1;
346
    }
347
  }
348
  timer.get_delta_t(do_random ? CreateRand : CreateSeq);
349
  return 0;
350
}
351

    
352
int COpenTest::delete_random(BonTimer &timer)
353
{
354
  random_sort();
355
  timer.timestamp();
356
  int i;
357
  for(i = 0; i < m_number; i++)
358
  {
359
    if(unlink(m_file_names[i]))
360
    {
361
      fprintf(stderr, "Can't delete file %s\n", m_file_names[i]);
362
      return -1;
363
    }
364
    if(m_sync && m_sync_dir)
365
    {
366
      if(fsync(m_directoryHandles[m_dirIndex[i]]))
367
      {
368
        fprintf(stderr, "Can't sync directory, turning off dir-sync.\n");
369
        m_sync_dir = false;
370
      }
371
    }
372
  }
373
  if(m_number_directories > 1)
374
  {
375
    char buf[6];
376
    for(i = 0; i < m_number_directories; i++)
377
    {
378
      sprintf(buf, "%05d", i);
379
      if(m_sync)
380
      {
381
        close(m_directoryHandles[i]);
382
      }
383
      if(rmdir(buf))
384
      {
385
        io_error("rmdir");
386
        return -1;
387
      }
388
    }
389
  }
390
  else
391
  {
392
    if(m_sync)
393
    {
394
      close(m_directoryHandles[0]);
395
    }
396
  }
397
  if(chdir("..") || rmdir(m_dirname))
398
  {
399
    io_error("rmdir");
400
    return -1;
401
  }
402
  delete m_dirname;
403
  m_dirname = NULL;
404
  timer.get_delta_t(DelRand);
405
  return 0;
406
}
407

    
408
int COpenTest::delete_sequential(BonTimer &timer)
409
{
410
  timer.timestamp();
411
  int count = 0;
412
  for(int i = 0; i < m_number_directories; i++)
413
  {
414
    char buf[6];
415
    if(m_number_directories != 1)
416
    {
417
      sprintf(buf, "%05d", i);
418
      if(chdir(buf))
419
      {
420
        fprintf(stderr, "Can't change to directory %s\n", buf);
421
        return -1;
422
      }
423
    }
424
#ifdef OS2
425
    HDIR d = 0;
426
    ULONG entries = 1;
427
    FILEFINDBUF3 findBuf;
428
    ULONG rc = DosFindFirst("*", &d
429
                          , FILE_ARCHIVED | FILE_SYSTEM | FILE_HIDDEN | FILE_READONLY
430
                          , &findBuf, sizeof(findBuf), &entries, FIL_STANDARD);
431
    if(rc || !entries)
432
    {
433
      fprintf(stderr, "Can't open directory.\n");
434
      return -1;
435
    }
436
    do
437
    {
438
      if(unlink(findBuf.achName))
439
      {
440
        fprintf(stderr, "Can't delete file %s\n", findBuf.achName);
441
        DosFindClose(d);
442
        return -1;
443
      }
444
      count++;
445
      rc = DosFindNext(d, &findBuf, sizeof(findBuf), &entries);
446
    } while(!rc && entries == 1);
447
    DosFindClose(d);
448
#else
449
    DIR *d = opendir(".");
450
    if(!d)
451
    {
452
      fprintf(stderr, "Can't open directory.\n");
453
      return -1;
454
    }
455
    dirent *file_ent;
456

    
457
    while((file_ent = readdir(d)) != NULL)
458
    {
459
      if(file_ent->d_name[0] != '.')
460
      {
461
        if(unlink(file_ent->d_name))
462
        {
463
          fprintf(stderr, "Can't delete file %s\n", file_ent->d_name);
464
          return -1;
465
        }
466

    
467

    
468
        if(m_sync && m_sync_dir)
469
        {
470
          if(fsync(m_directoryHandles[i]))
471
          {
472
            fprintf(stderr, "Can't sync directory, turning off dir-sync.\n");
473
            m_sync_dir = false;
474
          }
475
        }
476
        count++;
477
      }
478
    }
479
    closedir(d);
480
#endif
481
    if(m_sync)
482
    {
483
      close(m_directoryHandles[i]);
484
    }
485
    if(m_number_directories != 1)
486
    {
487
      if(chdir("..") || rmdir(buf))
488
      {
489
        io_error("rmdir");
490
        return -1;
491
      }
492
    }
493
  }
494
  if(chdir("..") || rmdir(m_dirname))
495
  {
496
    io_error("rmdir");
497
    return -1;
498
  }
499
  delete m_dirname;
500
  m_dirname = NULL;
501
  if(count != m_number)
502
  {
503
    fprintf(stderr, "Expected %d files but only got %d\n", m_number, count);
504
    return -1;
505
  }
506
  timer.get_delta_t(DelSeq);
507
  return 0;
508
}
509

    
510
int COpenTest::stat_file(CPCCHAR file)
511
{
512
  struct stat st;
513
  if(stat(file, &st))
514
  {
515
    fprintf(stderr, "Can't stat file %s\n", file);
516
    return -1;
517
  }
518
  if(st.st_size)
519
  {
520
    FILE_TYPE fd = 0;
521
#ifdef OS2
522
    ULONG action = 0;
523
    ULONG rc = DosOpen(file, &fd, &action, 0, FILE_NORMAL
524
                     , OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS
525
                     , OPEN_FLAGS_SEQUENTIAL | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE
526
                     , NULL);
527
    if(rc)
528
      fd = -1;
529
#else
530
    fd = open(file, O_RDONLY);
531
#endif
532
    if(fd == -1)
533
    {
534
      fprintf(stderr, "Can't open file %s\n", file);
535
      return -1;
536
    }
537
    for(int i = 0; i < st.st_size; i += m_chunk_size)
538
    {
539
      int to_read = st.st_size - i;
540
      if(to_read > m_chunk_size) to_read = m_chunk_size;
541
#ifdef OS2
542
      ULONG actual = 0;
543
      rc = DosRead(fd, PVOID(m_buf), to_read, &actual);
544
      if(to_read != actual || rc)
545
#else
546
      if(to_read != read(fd, static_cast<void *>(m_buf), to_read))
547
#endif
548
      {
549
        fprintf(stderr, "Can't read data.\n");
550
        return -1;
551
      }
552
    }
553
    file_close(fd);
554
  }
555
  return 0;
556
}
557

    
558
int COpenTest::stat_random(BonTimer &timer)
559
{
560
  random_sort();
561
  timer.timestamp();
562

    
563
  int i;
564
  for(i = 0; i < m_number; i++)
565
  {
566
    if(-1 == stat_file(m_file_names[i]))
567
      return -1;
568
  }
569
  timer.get_delta_t(StatRand);
570
  return 0;
571
}
572

    
573
int COpenTest::stat_sequential(BonTimer &timer)
574
{
575
  timer.timestamp();
576
  int count = 0;
577
  for(int i = 0; i < m_number_directories; i++)
578
  {
579
    char buf[6];
580
    if(m_number_directories != 1)
581
    {
582
      sprintf(buf, "%05d", i);
583
      if(chdir(buf))
584
      {
585
        fprintf(stderr, "Can't change to directory %s\n", buf);
586
        return -1;
587
      }
588
    }
589
#ifdef OS2
590
    HDIR d = 0;
591
    ULONG entries = 1;
592
    FILEFINDBUF3 findBuf;
593
    ULONG rc = DosFindFirst("*", &d
594
                          , FILE_ARCHIVED | FILE_SYSTEM | FILE_HIDDEN | FILE_READONLY
595
                          , &findBuf, sizeof(findBuf), &entries, FIL_STANDARD);
596
    if(rc || !entries)
597
    {
598
      fprintf(stderr, "Can't open directory.\n");
599
      if(m_number_directories != 1)
600
      {
601
        if(chdir(".."))
602
          fprintf(stderr, "Can't chdir().\n");
603
      }
604
      return -1;
605
    }
606
    do
607
    {
608
      if(*m_exit)
609
      {
610
        return EXIT_CTRL_C;
611
      }
612
      if(findBuf.achName[0] != '.') // our files do not start with a dot
613
      {
614
        if(-1 == stat_file(findBuf.achName))
615
        {
616
          if(m_number_directories != 1)
617
          {
618
            if(chdir(".."))
619
              fprintf(stderr, "Can't chdir().\n");
620
          }
621
          return -1;
622
        }
623
        count++;
624
      }
625
      rc = DosFindNext(d, &findBuf, sizeof(findBuf), &entries);
626
    } while(!rc && entries == 1);
627
    DosFindClose(d);
628
#else
629
    DIR *d = opendir(".");
630
    if(!d)
631
    {
632
      fprintf(stderr, "Can't open directory.\n");
633
      if(m_number_directories != 1)
634
      {
635
        if(chdir(".."))
636
          fprintf(stderr, "Can't chdir().\n");
637
      }
638
      return -1;
639
    }
640
    dirent *file_ent;
641
    while((file_ent = readdir(d)) != NULL)
642
    {
643
      if(*m_exit)
644
      {
645
        if(m_number_directories != 1 && chdir(".."))
646
        {
647
          fprintf(stderr, "Can't change to directory ..\n");
648
          return -1;
649
        }
650
        return EXIT_CTRL_C;
651
      }
652
      if(file_ent->d_name[0] != '.') // our files do not start with a dot
653
      {
654
        if(-1 == stat_file(file_ent->d_name))
655
        {
656
          if(m_number_directories != 1)
657
          {
658
            if(chdir(".."))
659
              fprintf(stderr, "Can't chdir().\n");
660
          }
661
          return -1;
662
        }
663
        count++;
664
      }
665
    }
666
    closedir(d);
667
#endif
668
    if(m_number_directories != 1 && chdir(".."))
669
    {
670
      fprintf(stderr, "Can't change to directory ..\n");
671
      return -1;
672
    }
673
  }
674
  if(count != m_number)
675
  {
676
    fprintf(stderr, "Expected %d files but only got %d\n", m_number, count);
677
    return -1;
678
  }
679
  timer.get_delta_t(StatSeq);
680
  return 0;
681
}
682