~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/pbxt/src/iotest_xt.c

  • Committer: Brian Aker
  • Date: 2009-10-15 00:22:33 UTC
  • mto: (1183.1.11 merge)
  • mto: This revision was merged to the branch mainline in revision 1198.
  • Revision ID: brian@gaz-20091015002233-fa4ao2mbc67wls91
First pass of information engine. OMG, ponies... is it so much easier to
deal with creating and engine.

The list table iterator though... its ass, needs to go. We should also
abstract out share. Very few engines need a custom one. Just say'in

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2005 PrimeBase Technologies GmbH
2
 
 *
3
 
 * PrimeBase XT
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License as published by
7
 
 * the Free Software Foundation; either version 2 of the License, or
8
 
 * (at your option) any later version.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
 
 *
19
 
 * 2009-07-30   Paul McCullagh
20
 
 *
21
 
 * H&G2JCtL
22
 
 */
23
 
 
24
 
#include <pthread.h>
25
 
 
26
 
 
27
 
#include <stdlib.h>
28
 
#include <stddef.h>
29
 
#include <stdio.h>
30
 
#include <sys/time.h>
31
 
#include <unistd.h>
32
 
#include <dirent.h>
33
 
#include <stdio.h>
34
 
#include <sys/stat.h>
35
 
#include <fcntl.h>
36
 
#include <sys/types.h>
37
 
#include <ctype.h>
38
 
#include <string.h>
39
 
#include <errno.h>
40
 
#include <limits.h>
41
 
#include <assert.h>
42
 
 
43
 
#ifdef __APPLE__
44
 
#define MAC
45
 
#endif
46
 
 
47
 
/*
48
 
 * Define this if I/O should pause.
49
 
 */
50
 
//#define SHOULD_PAUSE
51
 
//#define PERIODIC_FLUSH
52
 
 
53
 
#define SIM_RECORD_SIZE                 221
54
 
#ifdef MAC
55
 
#define SIM_FILE_SIZE                   (256*1024*1024)
56
 
#define SIM_WRITE_AMOUNT                (1*1024*1024)
57
 
//#define SIM_WRITE_AMOUNT              (221 * 100)
58
 
#else
59
 
#define SIM_FILE_SIZE                   ((off_t) (2L*1024L*1024L*1024L))
60
 
#define SIM_WRITE_AMOUNT                (8*1024*1024)
61
 
#endif
62
 
#define SIM_FLUSH_THRESHOLD             (2*1024*1024)
63
 
#define SIM_PAUSE_THRESHOLD             (10*1024*1024)
64
 
 
65
 
#ifndef SHOULD_PAUSE
66
 
#undef  SIM_PAUSE_THRESHOLD
67
 
#define SIM_PAUSE_THRESHOLD             0
68
 
#endif
69
 
 
70
 
#ifndef PERIODIC_FLUSH
71
 
#undef  SIM_FLUSH_THRESHOLD
72
 
#define SIM_FLUSH_THRESHOLD             0
73
 
#endif
74
 
 
75
 
#define my_time                                 unsigned long long
76
 
#define u_long                                  unsigned long
77
 
#define TRUE                                    1
78
 
#define FALSE                                   0
79
 
 
80
 
typedef struct SortedRec {
81
 
        off_t           sr_offset;
82
 
        int                     sr_order;
83
 
        char            *sr_data;
84
 
} SortedRec;
85
 
 
86
 
#define SORTED_MAX_RECORDS              10000
87
 
#define SORTED_DATA_SIZE                (SORTED_MAX_RECORDS * SIM_RECORD_SIZE)
88
 
#define SORTED_BUFFER_SIZE              (256*1024)
89
 
 
90
 
typedef struct RewriteRec {
91
 
        off_t           rr_offset;
92
 
        off_t           rr_size;
93
 
} RewriteRec;
94
 
 
95
 
#define REWRITE_MAX_RECORDS             1000
96
 
/* This is the maximum distance between to blocks that
97
 
 * will cause the blocks to be combined and written
98
 
 * as one block!
99
 
 */
100
 
#ifdef MAC
101
 
#define REWRITE_BLOCK_DISTANCE  (64*1024)
102
 
#else
103
 
#define REWRITE_BLOCK_DISTANCE  (1024*1024)
104
 
#endif
105
 
 
106
 
#define REWRITE_RECORD_LIMIT    256
107
 
 
108
 
typedef struct File {   
109
 
        int                     file_fh;
110
 
        
111
 
        int                     fi_monitor_index;
112
 
        char            fi_file_path[200];
113
 
        char            fi_test_name[200];
114
 
        char            fi_monitor_name[10];
115
 
        int                     fi_monitor_active;
116
 
 
117
 
        my_time         total_time;
118
 
 
119
 
        my_time         flush_start;
120
 
        my_time         flush_time;
121
 
        u_long          flush_count;
122
 
 
123
 
        my_time         last_flush_time;
124
 
        u_long          last_flush_count;
125
 
 
126
 
        my_time         write_start;
127
 
        my_time         write_time;
128
 
        u_long          write_count;
129
 
        
130
 
        off_t           last_block_offset;
131
 
        size_t          last_block_size;
132
 
        u_long          block_write_count;
133
 
 
134
 
        my_time         last_write_time;
135
 
        u_long          last_write_count;
136
 
 
137
 
        my_time         read_start;
138
 
        my_time         read_time;
139
 
        u_long          read_count;
140
 
 
141
 
        my_time         last_read_time;
142
 
        u_long          last_read_count;
143
 
 
144
 
        /* Sorted file I/O */
145
 
        int                     sf_rec_count;
146
 
        SortedRec       sf_records[SORTED_MAX_RECORDS];
147
 
        size_t          sf_alloc_pos;
148
 
        int                     sf_order;
149
 
        char            sf_data[SORTED_DATA_SIZE];
150
 
        char            sf_buffer[SORTED_BUFFER_SIZE];
151
 
 
152
 
        /* Re-write sync: */
153
 
        off_t           rs_min_block_offset;
154
 
        off_t           rs_max_block_offset;
155
 
        size_t          rs_flush_block_total;
156
 
        size_t          rs_rec_count;
157
 
        RewriteRec      rs_records[REWRITE_MAX_RECORDS];
158
 
 
159
 
        void            (*fi_write)(struct File *f, void *block, size_t size, off_t start);
160
 
        void            (*fi_sync)(struct File *f);
161
 
        void            (*fi_write_all)(struct File *f);
162
 
} File;
163
 
 
164
 
/* -------------------  TIMING ------------------- */
165
 
 
166
 
static my_time my_clock(void)
167
 
{
168
 
        static my_time  my_start_clock = 0;
169
 
        struct timeval  tv;
170
 
        my_time                 now;
171
 
 
172
 
        gettimeofday(&tv, NULL);
173
 
        now = (my_time) tv.tv_sec * (my_time) 1000000 + tv.tv_usec;
174
 
        if (my_start_clock)
175
 
                return now - my_start_clock;
176
 
        my_start_clock = now;
177
 
        return 0;
178
 
}
179
 
 
180
 
/* -------------------  ERRORS ------------------- */
181
 
 
182
 
static void print_error(char *file, int err)
183
 
{
184
 
        printf("ERROR %s: %s\n", file, strerror(err));
185
 
}
186
 
 
187
 
static void error_exit(char *file, int err)
188
 
{
189
 
        print_error(file, err);
190
 
        exit(1);
191
 
}
192
 
 
193
 
static void fatal_error(char *message)
194
 
{
195
 
        printf("%s", message);
196
 
        exit(1);
197
 
}
198
 
 
199
 
/* -------------------  ERRORS ------------------- */
200
 
 
201
 
static void *my_bsearch(void *key, register const void *base, size_t count, size_t size, size_t *idx, int (*compare)(void *key, void *rec))
202
 
{
203
 
        register size_t         i;
204
 
        register size_t         guess;
205
 
        register int            r;
206
 
 
207
 
        i = 0;
208
 
        while (i < count) {
209
 
                guess = (i + count - 1) >> 1;
210
 
                r = compare(key, ((char *) base) + guess * size);
211
 
                if (r == 0) {
212
 
                        *idx = guess;
213
 
                        return ((char *) base) + guess * size;
214
 
                }
215
 
                if (r < 0)
216
 
                        count = guess;
217
 
                else
218
 
                        i = guess + 1;
219
 
        }
220
 
 
221
 
        *idx = i;
222
 
        return NULL;
223
 
}
224
 
 
225
 
/* -------------------  MONITORING THREAD ------------------- */
226
 
 
227
 
/* Monitor file types: */
228
 
#define MAX_FILES                       10
229
 
 
230
 
static int              monitor_file_count;
231
 
static int              monitor_files_in_use;
232
 
static int              monitor_running;
233
 
static  File    *monitor_files[MAX_FILES];
234
 
 
235
 
static void monitor_file(File *f, const char *test_name, const char *monitor_name)
236
 
{
237
 
        if (monitor_file_count == MAX_FILES)
238
 
                fatal_error("Too many files to monitor");
239
 
        monitor_files[monitor_file_count] = f;
240
 
        f->fi_monitor_index = monitor_file_count;
241
 
        sprintf(f->fi_file_path, "test-data-%d", (int) monitor_file_count);
242
 
        strcpy(f->fi_test_name, test_name);
243
 
        strcpy(f->fi_monitor_name, monitor_name);
244
 
        monitor_file_count++;
245
 
        f->fi_monitor_active = TRUE;
246
 
        monitor_files_in_use++;
247
 
}
248
 
 
249
 
static void unmonitor_file(File *f)
250
 
{
251
 
        /* Wait for the last activity to be reported! */
252
 
        while (monitor_running && f->fi_monitor_active) {
253
 
                usleep(100);
254
 
        }
255
 
        monitor_files_in_use--;
256
 
        monitor_files[f->fi_monitor_index] = NULL;
257
 
}
258
 
 
259
 
static void print_header()
260
 
{
261
 
        File    *f;
262
 
        int             i;
263
 
 
264
 
        printf("time ");
265
 
        for (i=0; i<MAX_FILES; i++) {
266
 
                if ((f = monitor_files[i])) {
267
 
                        printf("%7s %5s %9s %5s %9s %5s ", f->fi_monitor_name, f->fi_monitor_name, f->fi_monitor_name, f->fi_monitor_name, f->fi_monitor_name, f->fi_monitor_name);
268
 
                }
269
 
        }
270
 
        printf("\n");
271
 
        printf("     ");
272
 
        for (i=0; i<MAX_FILES; i++) {
273
 
                if ((f = monitor_files[i])) {
274
 
                        printf("%7s %5s %9s %5s %9s %5s ", "flush", "ftime", "write", "wtime", "read", "rtime");
275
 
                }
276
 
        }
277
 
        printf("\n");
278
 
}
279
 
 
280
 
static void *iotest_monitor(void *data)
281
 
{
282
 
        File    *f;
283
 
        int             i;
284
 
        int             row = 0;
285
 
        my_time curr, last;
286
 
        my_time now, fstart, wstart, rstart;
287
 
        int             version = 0;
288
 
        int             activity;
289
 
 
290
 
        my_time curr_flush_time;
291
 
        u_long  curr_flush_count;
292
 
        my_time curr_write_time;
293
 
        u_long  curr_write_count;
294
 
        my_time curr_read_time;
295
 
        u_long  curr_read_count;
296
 
 
297
 
        my_time flush_time;
298
 
        u_long  flush_count;
299
 
        my_time write_time;
300
 
        u_long  write_count;
301
 
        my_time read_time;
302
 
        u_long  read_count;
303
 
 
304
 
        monitor_running = TRUE;
305
 
        last = my_clock();
306
 
        for (;;) {
307
 
                curr = my_clock();
308
 
                
309
 
                if (!monitor_files_in_use)
310
 
                        goto wait_phase;
311
 
 
312
 
                if ((row % 20) == 0 || version != monitor_file_count) {
313
 
                        version = monitor_file_count;
314
 
                        print_header();
315
 
                }
316
 
 
317
 
                printf("%4.0f ", ((double) curr - (double) last) / (double) 1000);
318
 
                activity = FALSE;
319
 
                for (i=0; i<MAX_FILES; i++) {
320
 
                        if ((f = monitor_files[i])) {
321
 
                                curr_flush_time = f->flush_time;
322
 
                                fstart = f->flush_start;
323
 
                                curr_write_time = f->write_time;
324
 
                                wstart = f->write_start;
325
 
                                curr_read_time = f->read_time;
326
 
                                rstart = f->read_start;
327
 
                                now = my_clock();
328
 
 
329
 
                                if (fstart)
330
 
                                        curr_flush_time += now - fstart;
331
 
                                flush_time = curr_flush_time - f->last_flush_time;
332
 
                                f->last_flush_time = curr_flush_time;
333
 
 
334
 
                                curr_flush_count = f->flush_count;
335
 
                                flush_count = curr_flush_count - f->last_flush_count;
336
 
                                f->last_flush_count = curr_flush_count;
337
 
 
338
 
                                if (wstart)
339
 
                                        curr_write_time += now - wstart;
340
 
                                write_time = curr_write_time - f->last_write_time;
341
 
                                f->last_write_time = curr_write_time;
342
 
 
343
 
                                curr_write_count = f->write_count;
344
 
                                write_count = curr_write_count - f->last_write_count;
345
 
                                f->last_write_count = curr_write_count;
346
 
        
347
 
                                if (rstart)
348
 
                                        curr_read_time += now - rstart;
349
 
                                read_time = curr_read_time - f->last_read_time;
350
 
                                f->last_read_time = curr_read_time;
351
 
 
352
 
                                curr_read_count = f->read_count;
353
 
                                read_count = curr_read_count - f->last_read_count;
354
 
                                f->last_read_count = curr_read_count;
355
 
        
356
 
                                printf("%7lu %5.0f %9.2f %5.0f %9.2f %5.0f ", flush_count, (double) flush_time / (double) 1000,
357
 
                                        (double) write_count / (double) 1024, (double) write_time / (double) 1000,
358
 
                                        (double) read_count / (double) 1024, (double) read_time / (double) 1000);
359
 
                                if (flush_count || flush_time || write_count || write_time || read_count || read_time) {
360
 
                                        f->fi_monitor_active = TRUE;
361
 
                                        activity = TRUE;
362
 
                                }
363
 
                                else
364
 
                                        f->fi_monitor_active = FALSE;
365
 
                        }
366
 
                }
367
 
                printf("\n");
368
 
                row++;
369
 
 
370
 
                wait_phase:
371
 
 
372
 
                /* Leave the loop, only when there is no more activity. */
373
 
                if (!monitor_running && !activity)
374
 
                        break;
375
 
 
376
 
                do {
377
 
                        usleep(1000);
378
 
                } while (my_clock() - curr < 1000000);
379
 
                last = curr;
380
 
        }
381
 
        
382
 
        return NULL;
383
 
}
384
 
 
385
 
/* -------------------  BASIC FILE I/O ------------------- */
386
 
 
387
 
#define PREFILL                         0
388
 
#define SET_EOF                         1
389
 
#define TRUNCATE                        2
390
 
 
391
 
#define XT_MASK                         ((S_IRUSR | S_IWUSR) | (S_IRGRP | S_IWGRP) | (S_IROTH))
392
 
 
393
 
static void create_file(File *f, size_t size, int type)
394
 
{
395
 
        int             fd;
396
 
        size_t  tfer;
397
 
        char    *block;
398
 
        size_t  i;
399
 
        off_t   eof;
400
 
        off_t   offset;
401
 
 
402
 
        if (!(block = (char *) malloc(512)))
403
 
                error_exit(f->fi_file_path, errno);
404
 
        for (i=0; i<512; i++)
405
 
                block[i] = (char) i;
406
 
 
407
 
        fd = open(f->fi_file_path, O_CREAT | O_RDWR, XT_MASK);
408
 
        if (fd == -1)
409
 
                error_exit(f->fi_file_path, errno);
410
 
 
411
 
        eof = lseek(fd, 0, SEEK_END);
412
 
        if (type == PREFILL && size == eof)
413
 
                goto done;
414
 
 
415
 
        if (ftruncate(fd, 0) == -1)
416
 
                error_exit(f->fi_file_path, errno);
417
 
 
418
 
        if (type == SET_EOF) {
419
 
                if (size > 512)
420
 
                        offset = size - 512;
421
 
                else
422
 
                        offset = 0;
423
 
                if (pwrite(fd, block, 512, offset) != 512)
424
 
                        error_exit(f->fi_file_path, errno);
425
 
        }
426
 
        else {
427
 
                offset = 0;
428
 
                while (size > 0) {
429
 
                        tfer = size;
430
 
                        if (tfer > 512)
431
 
                                tfer = 512;
432
 
                        if (pwrite(fd, block, tfer, offset) != tfer)
433
 
                                error_exit(f->fi_file_path, errno);
434
 
                        size -= tfer;
435
 
                        offset += tfer;
436
 
                }
437
 
        }
438
 
 
439
 
        if (fsync(fd) == -1)
440
 
                error_exit(f->fi_file_path, errno);
441
 
 
442
 
        done:
443
 
        close(fd);
444
 
        free(block);
445
 
}
446
 
 
447
 
/*
448
 
static void delete_file(char *file)
449
 
{
450
 
        unlink(file);
451
 
}
452
 
*/
453
 
 
454
 
static void write_file(File *f, void *block, size_t size, off_t offset)
455
 
{
456
 
        my_time t, s;
457
 
 
458
 
        s = my_clock();
459
 
        f->write_start = s;
460
 
        if (pwrite(f->file_fh, block, size, offset) != size)
461
 
                error_exit(f->fi_file_path, errno);
462
 
        t = my_clock();
463
 
        f->write_start = 0;
464
 
        f->write_time += (t - s);
465
 
        f->write_count += size;
466
 
 
467
 
        /* Does this block touch the previous block? */
468
 
        if (f->last_block_offset == -1 ||
469
 
                offset < f->last_block_offset ||
470
 
                offset > f->last_block_offset + f->last_block_size)
471
 
                /* If not, it is a new block (with a gap): */
472
 
                f->block_write_count++;
473
 
        f->last_block_offset = offset;
474
 
        f->last_block_size = size;
475
 
}
476
 
 
477
 
static void read_file(File *f, void *block, size_t size, off_t start)
478
 
{
479
 
        my_time t, s;
480
 
 
481
 
        s = my_clock();
482
 
        f->read_start = s;
483
 
        if (pread(f->file_fh, block, size, start) != size)
484
 
                error_exit(f->fi_file_path, errno);
485
 
        t = my_clock();
486
 
        f->read_start = 0;
487
 
        f->read_time += (t - s);
488
 
        f->read_count += size;
489
 
}
490
 
 
491
 
static void sync_file(File *f)
492
 
{
493
 
        my_time t, s;
494
 
 
495
 
        s = my_clock();
496
 
        f->flush_start = s;
497
 
        if (fsync(f->file_fh) == -1)
498
 
                error_exit(f->fi_file_path, errno);
499
 
        t = my_clock();
500
 
        f->flush_start = 0;
501
 
        f->flush_time += t - s;
502
 
        f->flush_count++;
503
 
}
504
 
 
505
 
static void new_file(File **ret_f, const char *test_name, const char *monitor_name)
506
 
{
507
 
        File *f;
508
 
 
509
 
        f = malloc(sizeof(File));
510
 
        memset(f, 0, sizeof(File));
511
 
        f->last_block_offset = (off_t) -1;
512
 
        f->rs_min_block_offset = (off_t) -1;
513
 
 
514
 
        monitor_file(f, test_name, monitor_name);
515
 
        f->fi_write = write_file;
516
 
        f->fi_sync = sync_file;
517
 
 
518
 
        *ret_f = f;
519
 
}
520
 
 
521
 
static void open_file(File *f)
522
 
{
523
 
        f->file_fh = open(f->fi_file_path, O_RDWR, 0);
524
 
        if (f->file_fh == -1)
525
 
                error_exit(f->fi_file_path, errno);
526
 
 
527
 
        f->total_time = my_clock();
528
 
}
529
 
 
530
 
static void close_file(File *f)
531
 
{
532
 
        f->fi_sync(f);
533
 
        f->total_time = my_clock() - f->total_time;
534
 
        if (f->file_fh != -1)
535
 
                close(f->file_fh);
536
 
 
537
 
        unmonitor_file(f);
538
 
 
539
 
        printf("\n=* TEST: %s (%s) *=\n", f->fi_test_name, f->fi_monitor_name);
540
 
        printf("Written K:  %.2f\n", (double) f->write_count / (double) 1024);
541
 
        printf("Run time:   %.2f ms\n", (double) f->total_time / (double) 1000);
542
 
        if (f->rs_flush_block_total > 0)
543
 
                printf("Flush blks: %lu\n", f->rs_flush_block_total);
544
 
        if (f->write_count > 0) {
545
 
                printf("Tot blocks: %lu\n", f->block_write_count);
546
 
                printf("Seek time:  %.3f ms\n", (double) f->flush_time / (double) f->block_write_count / (double) 1000);
547
 
        }
548
 
        printf("\n");
549
 
        if (f->write_time)
550
 
                printf("Write K/s: %.2f\n", (double) f->write_count * (double) 1000000 / (double) 1024 / (double) f->write_time);
551
 
        if (f->read_time)
552
 
                printf("Read  K/s: %.2f\n", (double) f->read_count * (double) 1000000 / (double) 1024 / (double) f->read_time);
553
 
        if (f->flush_time)
554
 
                printf("Flush K/s: %.2f\n", (double) f->write_count * (double) 1000000 / (double) 1024 / (double) f->flush_time);
555
 
        if (f->write_time + f->read_time + f->flush_time)
556
 
                printf("Total K/s: %.2f\n", (double) f->write_count * (double) 1000000 / (double) 1024 / ((double) f->write_time + (double) f->read_time + (double) f->flush_time));
557
 
        printf("=*=\n");
558
 
}
559
 
 
560
 
/* -------------------  SORTED I/O ------------------- */
561
 
 
562
 
/* Sort records before they are writing.
563
 
 * Options are also added to write records,
564
 
 * in large blocks. This requires reading the block
565
 
 * first.
566
 
 */
567
 
 
568
 
static int compare_rec(const void *a, const void *b)
569
 
{
570
 
        SortedRec       *ra = (SortedRec *) a;
571
 
        SortedRec       *rb = (SortedRec *) b;
572
 
 
573
 
        if (ra->sr_offset == rb->sr_offset) {
574
 
                if (ra->sr_order == rb->sr_order)
575
 
                        return 0;
576
 
                if (ra->sr_order < rb->sr_order)
577
 
                        return -1;
578
 
                return 1;
579
 
        }
580
 
        if (ra->sr_offset < rb->sr_offset)
581
 
                return -1;
582
 
        return 1;
583
 
}
584
 
 
585
 
static void sorted_write_all(File *f)
586
 
{
587
 
        SortedRec       *rec;
588
 
        int                     i;
589
 
 
590
 
        qsort(f->sf_records, f->sf_rec_count, sizeof(SortedRec), compare_rec);
591
 
        rec = f->sf_records;
592
 
        for (i=0; i<f->sf_rec_count; i++) {
593
 
                write_file(f, rec->sr_data, SIM_RECORD_SIZE, rec->sr_offset);
594
 
                rec++;
595
 
        }
596
 
        
597
 
        f->sf_rec_count = 0;
598
 
        f->sf_alloc_pos = 0;
599
 
        f->sf_order = 0;
600
 
}
601
 
 
602
 
static void sorted_write_rw_all(File *f)
603
 
{
604
 
        SortedRec       *rec;
605
 
        int                     i;
606
 
        off_t           offset = 0;
607
 
        size_t          size = 0;
608
 
 
609
 
        qsort(f->sf_records, f->sf_rec_count, sizeof(SortedRec), compare_rec);
610
 
        rec = f->sf_records;
611
 
        for (i=0; i<f->sf_rec_count; i++) {
612
 
                reread:
613
 
                if (!size) {
614
 
                        offset = (rec->sr_offset / 1024) * 1024;
615
 
                        size = SORTED_BUFFER_SIZE;
616
 
                        if (offset+(off_t)size > SIM_FILE_SIZE)
617
 
                                size = (size_t) (SIM_FILE_SIZE - offset);
618
 
                        read_file(f, f->sf_buffer, size, offset);
619
 
                }
620
 
 
621
 
                if (rec->sr_offset >= offset && rec->sr_offset+SIM_RECORD_SIZE <= offset+size)
622
 
                        memcpy(&f->sf_buffer[rec->sr_offset - offset], rec->sr_data, SIM_RECORD_SIZE);
623
 
                else {
624
 
                        write_file(f, f->sf_buffer, size, offset);
625
 
                        size = 0;
626
 
                        goto reread;
627
 
                }
628
 
                rec++;
629
 
        }
630
 
        
631
 
        f->sf_rec_count = 0;
632
 
        f->sf_alloc_pos = 0;
633
 
        f->sf_order = 0;
634
 
}
635
 
 
636
 
static void sorted_write_rw_no_gaps_all(File *f)
637
 
{
638
 
        SortedRec       *rec;
639
 
        int                     i;
640
 
        off_t           offset;
641
 
        size_t          size = 0;
642
 
 
643
 
        qsort(f->sf_records, f->sf_rec_count, sizeof(SortedRec), compare_rec);
644
 
        rec = f->sf_records;
645
 
        if (!f->sf_rec_count)
646
 
                goto done;
647
 
 
648
 
        offset = (rec->sr_offset / 1024) * 1024;
649
 
        for (i=0; i<f->sf_rec_count; i++) {
650
 
                reread:
651
 
                if (!size) {
652
 
                        size = SORTED_BUFFER_SIZE;
653
 
                        if (offset+size > SIM_FILE_SIZE)
654
 
                                size = SIM_FILE_SIZE - offset;
655
 
                        read_file(f, f->sf_buffer, size, offset);
656
 
                }
657
 
 
658
 
                if (rec->sr_offset >= offset && rec->sr_offset+SIM_RECORD_SIZE <= offset+size)
659
 
                        memcpy(&f->sf_buffer[rec->sr_offset - offset], rec->sr_data, SIM_RECORD_SIZE);
660
 
                else {
661
 
                        write_file(f, f->sf_buffer, size, offset);
662
 
                        offset += size;
663
 
                        if (rec->sr_offset < offset)
664
 
                                offset = (rec->sr_offset / 1024) * 1024;
665
 
                        size = 0;
666
 
                        goto reread;
667
 
                }
668
 
                rec++;
669
 
        }
670
 
 
671
 
        done:
672
 
        f->sf_rec_count = 0;
673
 
        f->sf_alloc_pos = 0;
674
 
        f->sf_order = 0;
675
 
}
676
 
 
677
 
static void sorted_sync_file(File *f)
678
 
{
679
 
        f->fi_write_all(f);
680
 
        sync_file(f);
681
 
}
682
 
 
683
 
static void sorted_write_file(File *f, void *block, size_t size, off_t offset)
684
 
{
685
 
        SortedRec *rec;
686
 
 
687
 
        if (size != SIM_RECORD_SIZE)
688
 
                printf("ooops\n");
689
 
 
690
 
        if (f->sf_rec_count == SORTED_MAX_RECORDS ||
691
 
                f->sf_alloc_pos + size > SORTED_DATA_SIZE) {
692
 
                f->fi_write_all(f);
693
 
        }
694
 
 
695
 
        rec = &f->sf_records[f->sf_rec_count];
696
 
        rec->sr_offset = offset;
697
 
        rec->sr_order = f->sf_order;
698
 
        rec->sr_data = &f->sf_data[f->sf_alloc_pos];
699
 
        memcpy(rec->sr_data, block, size);
700
 
        f->sf_alloc_pos += size;
701
 
        f->sf_rec_count++;
702
 
        f->sf_order++;
703
 
}
704
 
 
705
 
/* -------------------  RE-WRITE FLUSH ------------------- */
706
 
 
707
 
/* The idea is that it is better to re-write the file
708
 
 * sequentially, then allow the FS to write scattered
709
 
 * dirty blocks!
710
 
 *
711
 
 * This comes from the fact that seeking is a lot more
712
 
 * expensive than sequential write.
713
 
 */
714
 
 
715
 
static void rewrite_all_sync_file(File *f)
716
 
{
717
 
        off_t   offset = 0;
718
 
        size_t  size = 0;
719
 
 
720
 
        while (offset < SIM_FILE_SIZE) {
721
 
                size = SORTED_BUFFER_SIZE;
722
 
                if (offset + size > SIM_FILE_SIZE)
723
 
                        size = SIM_FILE_SIZE - offset;
724
 
                read_file(f, f->sf_buffer, size, offset);
725
 
                write_file(f, f->sf_buffer, size, offset);
726
 
                offset += size;
727
 
        }
728
 
 
729
 
        sync_file(f);
730
 
}
731
 
 
732
 
static void rewrite_min_max_sync_file(File *f)
733
 
{
734
 
        off_t   offset = 0;
735
 
        size_t  size = 0;
736
 
        off_t   eof = SIM_FILE_SIZE;
737
 
 
738
 
        if (f->rs_min_block_offset != (off_t) -1)
739
 
                offset = f->rs_min_block_offset / 1024 * 1024;
740
 
        eof = (f->rs_max_block_offset + 1023) / 1024 * 1024;
741
 
        if (eof > SIM_FILE_SIZE)
742
 
                eof = SIM_FILE_SIZE;
743
 
        while (offset < eof) {
744
 
                size = SORTED_BUFFER_SIZE;
745
 
                if (offset + size > eof)
746
 
                        size = eof - offset;
747
 
                read_file(f, f->sf_buffer, size, offset);
748
 
                write_file(f, f->sf_buffer, size, offset);
749
 
                offset += size;
750
 
        }
751
 
 
752
 
        sync_file(f);
753
 
}
754
 
 
755
 
static void rewrite_min_max_write_file(File *f, void *block, size_t size, off_t offset)
756
 
{
757
 
        off_t           top_offset;
758
 
 
759
 
        write_file(f, block, size, offset);
760
 
 
761
 
        /* Round up and down by 1K */
762
 
        top_offset = offset + size;
763
 
        offset = offset / 1024 * 1024;
764
 
        top_offset = (top_offset + 1023) / 1024 * 1024;
765
 
        size = (size_t) (top_offset - offset);
766
 
 
767
 
        /* Calculate max and min and max offset: */
768
 
        if (f->rs_min_block_offset == (off_t) -1 || offset < f->rs_min_block_offset)
769
 
                f->rs_min_block_offset = offset;
770
 
        if (offset + size > f->rs_max_block_offset)
771
 
                f->rs_max_block_offset = offset + size;
772
 
}
773
 
 
774
 
static void rewrite_opt_rewrite_file(File *f)
775
 
{
776
 
        RewriteRec      *rec;
777
 
        int                     i;
778
 
        off_t           offset;
779
 
        off_t           size;
780
 
        size_t          tfer;
781
 
 
782
 
        /* Re-write all areas written: */
783
 
        rec = f->rs_records;
784
 
        for (i=0; i<f->rs_rec_count; i++) {
785
 
                size = rec->rr_size;
786
 
                offset = rec->rr_offset;
787
 
                while (size) {
788
 
                        tfer = SORTED_BUFFER_SIZE;
789
 
                        if ((off_t) tfer > size)
790
 
                                tfer = size;
791
 
                        read_file(f, f->sf_buffer, tfer, offset);
792
 
                        write_file(f, f->sf_buffer, tfer, offset);
793
 
                        offset += tfer;
794
 
                        size -= tfer;
795
 
                }
796
 
                rec++;
797
 
        }
798
 
 
799
 
        f->rs_flush_block_total += f->rs_rec_count;
800
 
        f->rs_rec_count = 0;
801
 
}
802
 
 
803
 
static int rewrite_opt_comp(void *k, void *r)
804
 
{
805
 
        register off_t          *key = (off_t *) k;
806
 
        register RewriteRec     *rec = (RewriteRec *) r;
807
 
 
808
 
        if (*key == rec->rr_offset)
809
 
                return 0;
810
 
        if (*key < rec->rr_offset)
811
 
                return -1;
812
 
        return 1;
813
 
}
814
 
 
815
 
static void rewrite_opt_sync_file(File *f)
816
 
{
817
 
        rewrite_opt_rewrite_file(f);
818
 
        sync_file(f);
819
 
}
820
 
 
821
 
static void rewrite_opt_write_file(File *f, void *block, size_t size, off_t offset)
822
 
{
823
 
        RewriteRec      *rec;
824
 
        size_t          idx;
825
 
        off_t           top_offset;
826
 
 
827
 
        write_file(f, block, size, offset);
828
 
 
829
 
        /* Round up and down by 1K */
830
 
        top_offset = offset + size;
831
 
        offset = offset / 1024 * 1024;
832
 
        top_offset = (top_offset + 1023) / 1024 * 1024;
833
 
        size = (size_t) (top_offset - offset);
834
 
 
835
 
        if ((rec = my_bsearch(&offset, f->rs_records, f->rs_rec_count, sizeof(RewriteRec), &idx, rewrite_opt_comp))) {
836
 
                if ((off_t) size > rec->rr_size)
837
 
                        rec->rr_size = size;
838
 
                goto merge_right;
839
 
        }
840
 
 
841
 
        if (idx == 0) {
842
 
                /* The offset is before the first entry. */
843
 
                if (idx < f->rs_rec_count) {
844
 
                        /* There is a first entry: */
845
 
                        rec = f->rs_records;
846
 
                        if (rec->rr_offset - (offset + size) < REWRITE_BLOCK_DISTANCE)
847
 
                                goto add_to_right;
848
 
                }
849
 
 
850
 
                /* Add the first entry: */
851
 
                goto add_the_entry;
852
 
        }
853
 
 
854
 
        /* Not the first entry: */
855
 
        idx--;
856
 
        rec = f->rs_records + idx;
857
 
 
858
 
        if (offset - (rec->rr_offset + rec->rr_size) < REWRITE_BLOCK_DISTANCE) {
859
 
                /* Add to block on left: */
860
 
                size = (offset + size) - rec->rr_offset;
861
 
                if (size > rec->rr_size)
862
 
                        rec->rr_size = size;
863
 
                goto merge_right;
864
 
        }
865
 
        
866
 
        idx++;
867
 
        rec = f->rs_records + idx;
868
 
 
869
 
        if (idx < f->rs_rec_count && rec->rr_offset - (offset + size) < REWRITE_BLOCK_DISTANCE)
870
 
                goto add_to_right;
871
 
 
872
 
        add_the_entry:
873
 
        if (f->rs_rec_count == REWRITE_MAX_RECORDS) {
874
 
                rewrite_opt_rewrite_file(f);
875
 
                idx = 0;
876
 
        }
877
 
        rec = f->rs_records + idx;
878
 
        memmove(rec+1, rec, (f->rs_rec_count - idx) * sizeof(RewriteRec));
879
 
        rec->rr_offset = offset;
880
 
        rec->rr_size = (off_t) size;
881
 
        f->rs_rec_count++;
882
 
        return;
883
 
 
884
 
        add_to_right:
885
 
        rec->rr_size += rec->rr_offset - offset;
886
 
        if (size > rec->rr_size)
887
 
                rec->rr_size = size;
888
 
        rec->rr_offset = offset;
889
 
 
890
 
        merge_right:
891
 
        if (idx+1 < f->rs_rec_count) {
892
 
                /* There is a record right: */
893
 
                if (rec->rr_offset + rec->rr_size + REWRITE_BLOCK_DISTANCE > (rec+1)->rr_offset) {
894
 
                        /* Merge and remove! */
895
 
                        size = (rec+1)->rr_size + ((rec+1)->rr_offset - rec->rr_offset);
896
 
                        if (size > rec->rr_size)
897
 
                                rec->rr_size = size;
898
 
                        f->rs_rec_count--;
899
 
                        assert(f->rs_rec_count > idx);
900
 
                        memmove(rec+1, rec+2, (f->rs_rec_count - idx - 1) * sizeof(RewriteRec));
901
 
                }
902
 
        }
903
 
        return;
904
 
        
905
 
}
906
 
 
907
 
static void rewrite_limit_sync_file(File *f)
908
 
{
909
 
        rewrite_opt_rewrite_file(f);
910
 
        sync_file(f);
911
 
}
912
 
 
913
 
/*
914
 
 * This options is like opt but it limits the number of
915
 
 * blocks that can be written.
916
 
 */
917
 
static void rewrite_limit_write_file(File *f, void *block, size_t size, off_t offset)
918
 
{
919
 
        RewriteRec      *rec;
920
 
 
921
 
        /* There must always be room for one more: */
922
 
        assert(f->rs_rec_count < REWRITE_RECORD_LIMIT);
923
 
        rewrite_opt_write_file(f, block, size, offset);
924
 
        if (f->rs_rec_count == REWRITE_RECORD_LIMIT) {
925
 
                /* Consolidate 2 blocks that are closest to each other in other to
926
 
                 * make space for another block:
927
 
                 */
928
 
                int             i, idx;
929
 
                off_t   gap;
930
 
                off_t   min_gap = (off_t) -1;
931
 
 
932
 
                rec = f->rs_records;
933
 
                for (i=0; i<f->rs_rec_count-1; i++) {
934
 
                        gap = (rec+1)->rr_offset - (rec->rr_offset + rec->rr_size);
935
 
                        if (min_gap == (off_t) -1 || gap < min_gap) {
936
 
                                idx = i;
937
 
                                min_gap = gap;
938
 
                        }
939
 
                        rec++;
940
 
                }
941
 
 
942
 
                /* Merge this with the next: */
943
 
                rec = f->rs_records + idx;
944
 
                size = (rec+1)->rr_size + ((rec+1)->rr_offset - rec->rr_offset);
945
 
                if (size > rec->rr_size)
946
 
                        rec->rr_size = size;
947
 
                f->rs_rec_count--;
948
 
                assert(f->rs_rec_count > idx);
949
 
                memmove(rec+1, rec+2, (f->rs_rec_count - idx - 1) * sizeof(RewriteRec));
950
 
        }       
951
 
}
952
 
 
953
 
/* -------------------  SIMULATION I/O ------------------- */
954
 
 
955
 
/*
956
 
static void random_read_bytes(File *f, off_t file_size, size_t size, size_t count, int print)
957
 
{
958
 
        char    *block;
959
 
        size_t  i;
960
 
        off_t   offset;
961
 
        long    x = (long) (file_size / (off_t) size), y;
962
 
        
963
 
        block = (char *) malloc(size);
964
 
 
965
 
        for (i=0; i<count; i++) {
966
 
                y = random() % x;
967
 
                offset = (off_t) y * (off_t) size;
968
 
                if (offset+size > file_size) {
969
 
                        printf("NOOO\n");
970
 
                        exit(1);
971
 
                }
972
 
                read_file(f, block, size, offset);
973
 
                if (print) {
974
 
                        if ((i%100) == 0)
975
 
                                printf("%ld\n", (long) i);
976
 
                }
977
 
        }
978
 
        free(block);
979
 
}
980
 
*/
981
 
 
982
 
static void read_write_bytes(File *f, off_t file_size)
983
 
{
984
 
        off_t   offset = 0;
985
 
        size_t  tfer;
986
 
 
987
 
        while (file_size > 0) {
988
 
                tfer = SORTED_BUFFER_SIZE;
989
 
                if ((off_t) tfer > file_size)
990
 
                        tfer = (size_t) file_size;
991
 
                read_file(f, f->sf_buffer, tfer, offset);
992
 
                f->fi_write(f, f->sf_buffer, tfer, offset);
993
 
                offset += tfer;
994
 
                file_size -= tfer;
995
 
        }
996
 
}
997
 
 
998
 
static void random_write_bytes(File *f, off_t file_size, size_t size, off_t amount_to_write, int sync_after, int pause_after)
999
 
{
1000
 
        char    *block;
1001
 
        off_t   offset;
1002
 
        long    x = (long) (file_size / (off_t) size), y;
1003
 
        long    pbytes_written = 0;
1004
 
        long    sbytes_written = 0;
1005
 
        off_t   total_written = 0;
1006
 
        int             i;
1007
 
        
1008
 
        block = (char *) malloc(size);
1009
 
        for (i=0; i<size; i++)
1010
 
                block[i] = (char) i;
1011
 
 
1012
 
        if (pause_after) {
1013
 
                pbytes_written = 0;
1014
 
                sleep(10);
1015
 
        }
1016
 
        while (total_written < amount_to_write) {
1017
 
                y = random() % x;
1018
 
                do {
1019
 
                        offset = (off_t) y * (off_t) size;
1020
 
                }
1021
 
                while (offset+size > file_size);
1022
 
                f->fi_write(f, block, size, offset);
1023
 
                sbytes_written += size;
1024
 
                pbytes_written += size;
1025
 
                total_written += size;
1026
 
                if (sync_after && sbytes_written > sync_after) {
1027
 
                        sbytes_written = 0;
1028
 
                        f->fi_sync(f);
1029
 
                }
1030
 
                if (pause_after && pbytes_written > pause_after) {
1031
 
                        pbytes_written = 0;
1032
 
                        sleep(10);
1033
 
                }
1034
 
        }
1035
 
        free(block);
1036
 
}
1037
 
 
1038
 
static void seq_write_bytes(File *f, off_t file_size, size_t size, off_t amount_to_write, int sync_after, int pause_after)
1039
 
{
1040
 
        char    *block;
1041
 
        off_t   offset;
1042
 
        long    pbytes_written = 0;
1043
 
        long    sbytes_written = 0;
1044
 
        off_t   total_written = 0;
1045
 
        int     i;
1046
 
 
1047
 
        block = (char *) malloc(size);
1048
 
        for (i=0; i<size; i++)
1049
 
                block[i] = (char) i;
1050
 
 
1051
 
        if (pause_after) {
1052
 
                pbytes_written = 0;
1053
 
                sleep(10);
1054
 
        }
1055
 
        offset = 0;
1056
 
        while (total_written < amount_to_write) {
1057
 
                if (offset+size > file_size)
1058
 
                        offset = 0;
1059
 
                f->fi_write(f, block, size, offset);
1060
 
                sbytes_written += size;
1061
 
                pbytes_written += size;
1062
 
                total_written += size;
1063
 
                offset += size;
1064
 
                if (sync_after && sbytes_written > sync_after) {
1065
 
                        sbytes_written = 0;
1066
 
                        f->fi_sync(f);
1067
 
                }
1068
 
                if (pause_after && pbytes_written > pause_after) {
1069
 
                        pbytes_written = 0;
1070
 
                        sleep(10);
1071
 
                }
1072
 
        }
1073
 
        free(block);
1074
 
}
1075
 
 
1076
 
static void simulate_xlog_write(File *f, off_t eof, off_t start_point, size_t size, off_t amount_to_write)
1077
 
{
1078
 
        char    *block;
1079
 
        off_t   start = start_point;
1080
 
        off_t   offset;
1081
 
        size_t  tfer;
1082
 
        off_t   total_written = 0;
1083
 
        int             i;
1084
 
        
1085
 
        block = (char *) malloc(1024*16);
1086
 
        for (i=0; i<1024*16; i++)
1087
 
                block[i] = (char) i;
1088
 
 
1089
 
        while (total_written < amount_to_write) {
1090
 
                /* Write 512 byte boundary block around random data we wish to write. */
1091
 
                offset = (start / 512) * 512;
1092
 
                tfer = (((start + size) / 512) * 512 + 512) - offset;
1093
 
                f->fi_write(f, block, tfer, offset);
1094
 
                total_written += tfer;
1095
 
                f->fi_sync(f);
1096
 
                start += size;
1097
 
                if (start + size > eof)
1098
 
                        start = start_point;
1099
 
        }
1100
 
 
1101
 
        free(block);
1102
 
}
1103
 
 
1104
 
static void seq_write_blocks_aligned(File *f, off_t file_size, size_t block_size, off_t amount_to_write)
1105
 
{
1106
 
        char    *block;
1107
 
        off_t   i, no_of_writes;
1108
 
        off_t   offset, inc;
1109
 
 
1110
 
        /* Blocks, 1 K in size: */
1111
 
        block_size = block_size / 1024 * 1024;
1112
 
 
1113
 
        block = (char *) malloc(block_size);
1114
 
        for (i=0; i<block_size; i++)
1115
 
                block[i] = (char) i;
1116
 
 
1117
 
        no_of_writes = amount_to_write / block_size;
1118
 
 
1119
 
        /* Calculate and round increment: */
1120
 
        inc = (file_size / no_of_writes) / 1024 * 1024;
1121
 
 
1122
 
        /* This is required if we want a gap: */
1123
 
        assert(inc > block_size);
1124
 
 
1125
 
        offset = 0;
1126
 
        for (i=0; i<no_of_writes; i++) {
1127
 
                f->fi_write(f, block, block_size, offset);
1128
 
                offset += inc;
1129
 
        }
1130
 
}
1131
 
 
1132
 
/* ------------------- TESTS ------------------- */
1133
 
 
1134
 
static void *test_xlog_write_prealloc(void *data)
1135
 
{
1136
 
        File    *f;
1137
 
 
1138
 
        new_file(&f, __FUNCTION__, "xlog");
1139
 
        create_file(f, SIM_FILE_SIZE, PREFILL);
1140
 
        open_file(f);
1141
 
        simulate_xlog_write(f, SIM_FILE_SIZE, 0, SIM_RECORD_SIZE, SIM_WRITE_AMOUNT);
1142
 
        close_file(f);
1143
 
        return NULL;
1144
 
}
1145
 
 
1146
 
static void *test_xlog_write_no_prealloc(void *data)
1147
 
{
1148
 
        File    *f;
1149
 
 
1150
 
        new_file(&f, __FUNCTION__, "xlog");
1151
 
        create_file(f, 512, TRUNCATE);
1152
 
        open_file(f);
1153
 
        simulate_xlog_write(f, SIM_FILE_SIZE, 0, SIM_RECORD_SIZE, SIM_WRITE_AMOUNT);
1154
 
        close_file(f);
1155
 
        return NULL;
1156
 
}
1157
 
 
1158
 
static void *test_xlog_write_set_eof(void *data)
1159
 
{
1160
 
        File    *f;
1161
 
 
1162
 
        new_file(&f, __FUNCTION__, "xlog");
1163
 
        create_file(f, SIM_FILE_SIZE, SET_EOF);
1164
 
        open_file(f);
1165
 
        simulate_xlog_write(f, SIM_FILE_SIZE, 0, SIM_RECORD_SIZE, SIM_WRITE_AMOUNT);
1166
 
        close_file(f);
1167
 
        return NULL;
1168
 
}
1169
 
 
1170
 
static void *test_rnd_write_prealloc(void *data)
1171
 
{
1172
 
        File    *f;
1173
 
 
1174
 
        new_file(&f, __FUNCTION__, "rndw");
1175
 
        create_file(f, SIM_FILE_SIZE, PREFILL);
1176
 
        open_file(f);
1177
 
        random_write_bytes(f, SIM_FILE_SIZE, SIM_RECORD_SIZE, SIM_WRITE_AMOUNT, SIM_FLUSH_THRESHOLD, SIM_PAUSE_THRESHOLD);
1178
 
        close_file(f);
1179
 
        return NULL;
1180
 
}
1181
 
 
1182
 
static void *test_rnd_write_no_prealloc(void *data)
1183
 
{
1184
 
        File    *f;
1185
 
 
1186
 
        new_file(&f, __FUNCTION__, "rndw");
1187
 
        create_file(f, 0, TRUNCATE);
1188
 
        open_file(f);
1189
 
        random_write_bytes(f, SIM_FILE_SIZE, SIM_RECORD_SIZE, SIM_WRITE_AMOUNT, SIM_FLUSH_THRESHOLD, SIM_PAUSE_THRESHOLD);
1190
 
        close_file(f);
1191
 
        return NULL;
1192
 
}
1193
 
 
1194
 
static void *test_rnd_write_rewrite_all_sync_prealloc(void *data)
1195
 
{
1196
 
        File    *f;
1197
 
 
1198
 
        new_file(&f, __FUNCTION__, "rndw");
1199
 
        create_file(f, SIM_FILE_SIZE, PREFILL);
1200
 
        open_file(f);
1201
 
        f->fi_sync = rewrite_all_sync_file;
1202
 
        random_write_bytes(f, SIM_FILE_SIZE, SIM_RECORD_SIZE, SIM_WRITE_AMOUNT, SIM_FLUSH_THRESHOLD, SIM_PAUSE_THRESHOLD);
1203
 
        close_file(f);
1204
 
        return NULL;
1205
 
}
1206
 
 
1207
 
static void *test_rnd_write_rewrite_min_max_sync_prealloc(void *data)
1208
 
{
1209
 
        File    *f;
1210
 
 
1211
 
        new_file(&f, __FUNCTION__, "rndw");
1212
 
        create_file(f, SIM_FILE_SIZE, PREFILL);
1213
 
        open_file(f);
1214
 
        f->fi_write = rewrite_min_max_write_file;
1215
 
        f->fi_sync = rewrite_min_max_sync_file;
1216
 
        random_write_bytes(f, SIM_FILE_SIZE, SIM_RECORD_SIZE, SIM_WRITE_AMOUNT, SIM_FLUSH_THRESHOLD, SIM_PAUSE_THRESHOLD);
1217
 
        close_file(f);
1218
 
        return NULL;
1219
 
}
1220
 
 
1221
 
static void *test_rnd_write_rewrite_opt_sync_prealloc(void *data)
1222
 
{
1223
 
        File    *f;
1224
 
 
1225
 
        new_file(&f, __FUNCTION__, "rndw");
1226
 
        create_file(f, SIM_FILE_SIZE, PREFILL);
1227
 
        open_file(f);
1228
 
        f->fi_write = rewrite_opt_write_file;
1229
 
        f->fi_sync = rewrite_opt_sync_file;
1230
 
        random_write_bytes(f, SIM_FILE_SIZE, SIM_RECORD_SIZE, SIM_WRITE_AMOUNT, SIM_FLUSH_THRESHOLD, SIM_PAUSE_THRESHOLD);
1231
 
        close_file(f);
1232
 
        return NULL;
1233
 
}
1234
 
 
1235
 
static void *test_rnd_write_rewrite_limit_sync_prealloc(void *data)
1236
 
{
1237
 
        File    *f;
1238
 
 
1239
 
        new_file(&f, __FUNCTION__, "rndw");
1240
 
        create_file(f, SIM_FILE_SIZE, PREFILL);
1241
 
        open_file(f);
1242
 
        f->fi_write = rewrite_limit_write_file;
1243
 
        f->fi_sync = rewrite_limit_sync_file;
1244
 
        random_write_bytes(f, SIM_FILE_SIZE, SIM_RECORD_SIZE, SIM_WRITE_AMOUNT, SIM_FLUSH_THRESHOLD, SIM_PAUSE_THRESHOLD);
1245
 
        close_file(f);
1246
 
        return NULL;
1247
 
}
1248
 
 
1249
 
static void *test_rnd_write_sorted_prealloc(void *data)
1250
 
{
1251
 
        File    *f;
1252
 
 
1253
 
        new_file(&f, __FUNCTION__, "rndsw");
1254
 
        create_file(f, SIM_FILE_SIZE, PREFILL);
1255
 
        open_file(f);
1256
 
        f->fi_write = sorted_write_file;
1257
 
        f->fi_sync = sorted_sync_file;
1258
 
        f->fi_write_all = sorted_write_all;
1259
 
        f->fi_write_all = sorted_write_rw_all;
1260
 
        f->fi_write_all = sorted_write_rw_no_gaps_all;
1261
 
        random_write_bytes(f, SIM_FILE_SIZE, SIM_RECORD_SIZE, SIM_WRITE_AMOUNT, SIM_FLUSH_THRESHOLD, SIM_PAUSE_THRESHOLD);
1262
 
        close_file(f);
1263
 
        return NULL;
1264
 
}
1265
 
 
1266
 
static void *test_seq_write_prealloc(void *data)
1267
 
{
1268
 
        File    *f;
1269
 
 
1270
 
        new_file(&f, __FUNCTION__, "seqw");
1271
 
        create_file(f, SIM_FILE_SIZE, PREFILL);
1272
 
        open_file(f);
1273
 
        seq_write_bytes(f, SIM_FILE_SIZE, SIM_RECORD_SIZE, SIM_WRITE_AMOUNT, SIM_FLUSH_THRESHOLD, SIM_PAUSE_THRESHOLD);
1274
 
        close_file(f);
1275
 
        return NULL;
1276
 
}
1277
 
 
1278
 
static void *test_seq_write_no_prealloc(void *data)
1279
 
{
1280
 
        File    *f;
1281
 
 
1282
 
        new_file(&f, __FUNCTION__, "seqw");
1283
 
        create_file(f, 0, TRUNCATE);
1284
 
        open_file(f);
1285
 
        seq_write_bytes(f, SIM_FILE_SIZE, SIM_RECORD_SIZE, SIM_WRITE_AMOUNT, SIM_FLUSH_THRESHOLD, SIM_PAUSE_THRESHOLD);
1286
 
        close_file(f);
1287
 
        return NULL;
1288
 
}
1289
 
 
1290
 
static void *test_seq_rw_prealloc(void *data)
1291
 
{
1292
 
        File    *f;
1293
 
 
1294
 
        new_file(&f, __FUNCTION__, "seqrw");
1295
 
        create_file(f, SIM_FILE_SIZE, PREFILL);
1296
 
        open_file(f);
1297
 
        read_write_bytes(f, SIM_FILE_SIZE);
1298
 
        close_file(f);
1299
 
        return NULL;
1300
 
}
1301
 
 
1302
 
int block_write_block_count = 128;
1303
 
 
1304
 
static void *test_block_write_aligned_prealloc(void *data)
1305
 
{
1306
 
        File    *f;
1307
 
        off_t   write_amount = SIM_FILE_SIZE / 2;
1308
 
 
1309
 
        new_file(&f, __FUNCTION__, "block");
1310
 
        create_file(f, SIM_FILE_SIZE, PREFILL);
1311
 
        open_file(f);
1312
 
        seq_write_blocks_aligned(f, SIM_FILE_SIZE, write_amount / block_write_block_count, write_amount);
1313
 
        close_file(f);
1314
 
        return NULL;
1315
 
}
1316
 
 
1317
 
/* -------------------  THREADING ------------------- */
1318
 
 
1319
 
static pthread_t run_task_as_thread(void *(*task)(void *))
1320
 
{
1321
 
        pthread_t       thread;
1322
 
        int                     err;
1323
 
 
1324
 
        err = pthread_create(&thread, NULL, task, NULL);
1325
 
        if (err)
1326
 
                error_exit("pthread_create", err);
1327
 
        return thread;
1328
 
}
1329
 
 
1330
 
static void wait_for_task(pthread_t thread)
1331
 
{
1332
 
        void *value;
1333
 
 
1334
 
        pthread_join(thread, &value);
1335
 
}
1336
 
 
1337
 
/* -------------------  MAIN ------------------- */
1338
 
 
1339
 
static void reference_tests()
1340
 
{
1341
 
        test_xlog_write_prealloc(NULL);
1342
 
        test_xlog_write_no_prealloc(NULL);
1343
 
        test_xlog_write_set_eof(NULL);
1344
 
 
1345
 
        test_rnd_write_prealloc(NULL);
1346
 
        test_rnd_write_no_prealloc(NULL);
1347
 
        test_rnd_write_rewrite_all_sync_prealloc(NULL);
1348
 
        test_rnd_write_rewrite_min_max_sync_prealloc(NULL);
1349
 
        test_rnd_write_rewrite_opt_sync_prealloc(NULL);
1350
 
        test_rnd_write_rewrite_limit_sync_prealloc(NULL);
1351
 
 
1352
 
        test_rnd_write_sorted_prealloc(NULL);
1353
 
 
1354
 
        test_seq_write_prealloc(NULL);
1355
 
        test_seq_write_no_prealloc(NULL);
1356
 
        test_seq_rw_prealloc(NULL);
1357
 
 
1358
 
        test_block_write_aligned_prealloc(NULL);
1359
 
}
1360
 
 
1361
 
static void do_task(void *(*task)(void *))
1362
 
{
1363
 
        pthread_t t1;
1364
 
        t1 = run_task_as_thread(task);
1365
 
        wait_for_task(t1);
1366
 
}
1367
 
 
1368
 
static void do_test_1()
1369
 
{
1370
 
        pthread_t t1;
1371
 
        //pthread_t t2;
1372
 
 
1373
 
        t1 = run_task_as_thread(test_rnd_write_sorted_prealloc);
1374
 
        //t2 = run_task_as_thread(test_xlog_write_prealloc);
1375
 
 
1376
 
        wait_for_task(t1);
1377
 
        //wait_for_task(t2);
1378
 
}
1379
 
 
1380
 
static void do_test_2()
1381
 
{
1382
 
        //do_task(test_rnd_write_prealloc);
1383
 
        //do_task(test_rnd_write_rewrite_min_max_sync_prealloc);
1384
 
        do_task(test_rnd_write_rewrite_limit_sync_prealloc);
1385
 
 
1386
 
        /*
1387
 
        block_write_block_count = 1;
1388
 
        do_task(test_block_write_aligned_prealloc);
1389
 
        block_write_block_count = 2;
1390
 
        do_task(test_block_write_aligned_prealloc);
1391
 
        block_write_block_count = 4;
1392
 
        do_task(test_block_write_aligned_prealloc);
1393
 
        block_write_block_count = 8;
1394
 
        do_task(test_block_write_aligned_prealloc);
1395
 
        block_write_block_count = 16;
1396
 
        do_task(test_block_write_aligned_prealloc);
1397
 
        block_write_block_count = 32;
1398
 
        do_task(test_block_write_aligned_prealloc);
1399
 
        block_write_block_count = 64;
1400
 
        do_task(test_block_write_aligned_prealloc);
1401
 
        block_write_block_count = 128;
1402
 
        do_task(test_block_write_aligned_prealloc);
1403
 
        */
1404
 
}
1405
 
 
1406
 
int main(int argc, char **argv)
1407
 
{
1408
 
        //pthread_t m;
1409
 
        
1410
 
        //m = run_task_as_thread(iotest_monitor);
1411
 
 
1412
 
        do_test_2();
1413
 
 
1414
 
        monitor_running = FALSE;
1415
 
        //wait_for_task(m);
1416
 
    return 0;
1417
 
}