"Fossies" - the Fresh Open Source Software Archive 
Member "bonnie++-1.04/bon_io.cpp" (4 Sep 2017, 11296 Bytes) of package /linux/privat/bonnie++_1.04.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "bon_io.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.03e_vs_1.04.
1 #ifdef OS2
2 #define INCL_DOSPROCESS
3 #define INCL_DOSFILEMGR
4 #include <os2.h>
5 #else
6 #include <dirent.h>
7 #include <unistd.h>
8 #include <sys/wait.h>
9 #endif
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include "bonnie.h"
14 #include "bon_io.h"
15 #include "semaphore.h"
16 #include "bon_time.h"
17
18 #include "forkit.h"
19
20 CFileOp::~CFileOp()
21 {
22 close();
23 if(m_name)
24 {
25 int len = strlen(m_name);
26 for(int i = 0; i < m_num_files; i++)
27 {
28 sprintf(&m_name[len], ".%03d", i);
29 unlink(m_name);
30 }
31 delete m_name;
32 }
33 delete m_buf;
34 }
35
36 void seeker(Fork *f, PVOID param, int)
37 {
38 struct report_s seeker_report;
39 CFileOp *file = (CFileOp *)param;
40 int num_chunks = file->chunks();
41 if(file->reopen(false))
42 exit(1);
43 char ticket;
44 int rc;
45 int lseek_count = 0;
46
47 rc = f->Read(&ticket, 1, 0);
48
49 file->getTimer().timestamp();
50 seeker_report.StartTime = file->getTimer().get_cur_time();
51
52 if(rc == 1 && ticket) do
53 {
54 bool update;
55 if( (lseek_count++ % UpdateSeek) == 0)
56 update = true;
57 else
58 update = false;
59 if(file->doseek(rand() % num_chunks, update) )
60 exit(1);
61 }
62 while((rc = f->Read(&ticket, 1, 0)) == 1 && ticket);
63
64 if(rc != 1)
65 {
66 fprintf(stderr, "Can't read ticket.\n");
67 exit(1);
68 }
69 file->close();
70 file->getTimer().get_delta_report(seeker_report);
71 if(f->Write(&seeker_report, sizeof(seeker_report)) != sizeof(seeker_report))
72 {
73 fprintf(stderr, "Can't write report.\n");
74 exit(1);
75 }
76 }
77
78 int CFileOp::seek_test(bool quiet, Semaphore &s)
79 {
80 char seek_tickets[SeekProcCount + Seeks];
81 int next;
82 for (next = 0; next < Seeks; next++)
83 seek_tickets[next] = 1;
84 for ( ; next < (Seeks + SeekProcCount); next++)
85 seek_tickets[next] = 0;
86 Fork f;
87 f.go(seeker, this, SeekProcCount);
88
89 sleep(5);
90 if(s.decrement_and_wait(Lseek))
91 return 1;
92 if(!quiet) fprintf(stderr, "start 'em...");
93 if(f.Write(seek_tickets, sizeof(seek_tickets)) != int(sizeof(seek_tickets)) )
94 {
95 fprintf(stderr, "Can't write tickets.\n");
96 return 1;
97 }
98 for (next = 0; next < SeekProcCount; next++)
99 { /* for each child */
100 struct report_s seeker_report;
101
102 int rc;
103 if((rc = f.Read(&seeker_report, sizeof(seeker_report), 0))
104 != sizeof(seeker_report))
105 {
106 fprintf(stderr, "Can't read from pipe, expected %d, got %d.\n"
107 , int(sizeof(seeker_report)), rc);
108 return 1;
109 }
110
111 /*
112 * each child writes back its CPU, start & end times. The elapsed time
113 * to do all the seeks is the time the first child started until the
114 * time the last child stopped
115 */
116 m_timer.add_delta_report(seeker_report, Lseek);
117 #ifdef OS2
118 TID status = 0;
119 if(DosWaitThread(&status, DCWW_WAIT))
120 #else
121 int status = 0;
122 if(wait(&status) == -1)
123 #endif
124 return io_error("wait");
125 if(!quiet) fprintf(stderr, "done...");
126 } /* for each child */
127 if(!quiet) fprintf(stderr, "\n");
128 return 0;
129 }
130
131 int CFileOp::seek(int offset, int whence)
132 {
133 switch(whence)
134 {
135 case SEEK_SET:
136 m_file_ind = offset / m_chunks_per_file;
137 m_cur_pos = offset % m_chunks_per_file;
138 break;
139 case SEEK_CUR:
140 m_cur_pos += offset;
141 while(m_cur_pos < 0)
142 {
143 m_file_ind--;
144 m_cur_pos += m_chunks_per_file;
145 }
146 while(m_cur_pos >= m_chunks_per_file)
147 {
148 m_file_ind++;
149 m_cur_pos -= m_chunks_per_file;
150 }
151 break;
152 default:
153 fprintf(stderr, "unsupported seek option\n");
154 return -1;
155 }
156 if(m_file_ind == m_num_files)
157 {
158 m_file_ind--;
159 m_cur_pos += m_chunks_per_file;
160 }
161 else
162 {
163 if(m_file_ind < 0 || m_file_ind >= m_num_files
164 || (m_file_ind == m_num_files - 1 && m_cur_pos >= m_last_file_chunks))
165 {
166 fprintf(stderr, "Bad seek offset\n");
167 return -1;
168 }
169 off_t rc;
170 if(m_fd)
171 {
172 #ifdef OS2
173 unsigned long actual;
174 rc = DosSetFilePtr(m_fd[m_file_ind], m_cur_pos << m_chunk_bits, FILE_BEGIN, &actual);
175 if(rc != 0) rc = -1;
176 #else
177 rc = lseek(m_fd[m_file_ind], m_cur_pos << m_chunk_bits, SEEK_SET);
178 #endif
179 }
180 else
181 {
182 rc = fseek(m_stream[m_file_ind], m_cur_pos << m_chunk_bits, SEEK_SET);
183 }
184
185 if(rc == off_t(-1))
186 fprintf(stderr, "Error in lseek to %d\n", (m_cur_pos << m_chunk_bits));
187 else
188 rc = 0;
189 return rc;
190 }
191 return 0;
192 }
193
194 int CFileOp::read_block(PVOID buf)
195 {
196 int total = 0;
197 bool printed_error = false;
198 while(total != m_chunk_size)
199 {
200 #ifdef OS2
201 unsigned long actual;
202 int rc = DosRead(m_fd[m_file_ind], buf, m_chunk_size - total
203 , &actual);
204 if(rc)
205 rc = -1;
206 else
207 rc = actual;
208 #else
209 int rc = ::read(m_fd[m_file_ind], buf, m_chunk_size - total);
210 #endif
211 m_cur_pos++;
212 if(m_cur_pos >= m_chunks_per_file)
213 {
214 if(seek(0, SEEK_CUR) == -1)
215 {
216 fprintf(stderr, "Error in seek(0)\n");
217 return -1;
218 }
219 }
220 if(rc == -1)
221 {
222 io_error("re-write read"); // exits program
223 }
224 else if(rc != m_chunk_size && !printed_error)
225 {
226 fprintf(stderr, "Can't read a full block, only got %d bytes.\n", rc);
227 printed_error = true;
228 }
229 total += rc;
230 }
231 return total;
232 }
233
234 int CFileOp::read_block_getc(char *buf)
235 {
236 int next;
237 for(int i = 0; i < m_chunk_size; i++)
238 {
239 if ((next = getc(m_stream[m_file_ind])) == EOF)
240 {
241 fprintf(stderr, "Can't getc(3)\n");
242 return -1;
243 }
244 /* just to fool optimizers */
245 buf[next]++;
246 }
247
248 m_cur_pos++;
249 if(m_cur_pos >= m_chunks_per_file)
250 {
251 if(seek(0, SEEK_CUR) == -1)
252 return -1;
253 }
254 return 0;
255 }
256
257 int CFileOp::write_block(PVOID buf)
258 {
259 #ifdef OS2
260 unsigned long actual;
261 int rc = DosWrite(m_fd[m_file_ind], buf, m_chunk_size, &actual);
262 if(rc)
263 rc = -1;
264 else
265 rc = 0;
266 if(actual != m_chunk_size)
267 rc = -1;
268 #else
269 int rc = ::write(m_fd[m_file_ind], buf, m_chunk_size);
270 if(rc != m_chunk_size)
271 {
272 fprintf(stderr, "Can't write block; rc=%d, buf=%p, chunk_size=%d\n", rc, buf, m_chunk_size);
273 return -1;
274 }
275 #endif
276 m_cur_pos++;
277 if(m_cur_pos >= m_chunks_per_file)
278 {
279 if(seek(0, SEEK_CUR) == -1)
280 return -1;
281 }
282 return rc;
283 }
284
285 int CFileOp::write_block_putc()
286 {
287 for(int i = 0; i < m_chunk_size; i++)
288 {
289 if (putc(i & 0x7f, m_stream[m_file_ind]) == EOF)
290 {
291 fprintf(stderr, "Can't putc() - disk full?\n");
292 return -1;
293 }
294 }
295 m_cur_pos++;
296 if(m_cur_pos >= m_chunks_per_file)
297 {
298 if(seek(0, SEEK_CUR) == -1)
299 return -1;
300 }
301 return 0;
302 }
303
304 int CFileOp::open(CPCCHAR base_name, bool create, bool use_fopen)
305 {
306 m_name = new char[strlen(base_name) + 9];
307 strcpy(m_name, base_name);
308 return reopen(create, use_fopen);
309 }
310
311 CFileOp::CFileOp(BonTimer &timer, int file_size, int chunk_bits, bool use_sync
312 #ifdef O_DIRECT
313 , bool use_direct_io
314 #endif
315 )
316 : m_timer(timer)
317 , m_stream(NULL)
318 , m_fd(NULL)
319 , m_isopen(false)
320 , m_name(NULL)
321 , m_sync(use_sync)
322 #ifdef O_DIRECT
323 , m_use_direct_io(use_direct_io)
324 #endif
325 , m_chunk_bits(chunk_bits)
326 , m_chunk_size(1 << m_chunk_bits)
327 , m_chunks_per_file(Unit / m_chunk_size * IOFileSize)
328 , m_total_chunks(Unit / m_chunk_size * file_size)
329 , m_last_file_chunks(m_total_chunks % m_chunks_per_file)
330 , m_cur_pos(0)
331 , m_file_ind(0)
332 , m_file_size(file_size)
333 , m_num_files(m_file_size / IOFileSize + 1)
334 , m_buf(new char[m_chunk_size])
335 {
336 if(m_last_file_chunks == 0)
337 {
338 m_last_file_chunks = m_chunks_per_file;
339 m_num_files--;
340 }
341 }
342
343 typedef FILE * PFILE;
344
345 int CFileOp::reopen(bool create, bool use_fopen)
346 {
347 int i;
348 m_cur_pos = 0;
349 m_file_ind = 0;
350
351 if(m_isopen) close();
352
353 m_isopen = true;
354 if(use_fopen)
355 {
356 m_stream = new PFILE[m_num_files];
357 for(i = 0; i < m_num_files; i++)
358 m_stream[i] = NULL;
359 }
360 else
361 {
362 #ifdef OS2
363 m_fd = new HFILE[m_num_files];
364 #else
365 m_fd = new int[m_num_files];
366 #endif
367 for(i = 0; i < m_num_files; i++)
368 m_fd[i] = -1;
369 }
370 int len = strlen(m_name);
371 for(i = 0; i < m_num_files; i++)
372 {
373 sprintf(&m_name[len], ".%04d", i);
374 if(m_open(m_name, i, create))
375 return 1;
376 }
377 m_name[len] = '\0';
378 return 0;
379 }
380
381 int CFileOp::m_open(CPCCHAR base_name, int ind, bool create)
382 {
383 #ifdef OS2
384 ULONG createFlag;
385 #else
386 int flags;
387 #endif
388 const char *fopen_mode;
389 if(create)
390 { /* create from scratch */
391 #ifndef OS2
392 unlink(base_name);
393 #endif
394 fopen_mode = "w+";
395 #ifdef OS2
396 createFlag = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
397 #else
398 flags = O_RDWR | O_CREAT | O_EXCL;
399 #ifdef O_DIRECT
400 if(m_use_direct_io)
401 {
402 flags |= O_DIRECT;
403 }
404 #endif
405 #endif
406 }
407 else
408 {
409 fopen_mode = "r+";
410 #ifdef OS2
411 createFlag = OPEN_ACTION_OPEN_IF_EXISTS;
412 #else
413 flags = O_RDWR;
414 #endif
415 }
416 if(m_fd)
417 {
418 #ifdef OS2
419 ULONG action = 0;
420 ULONG rc = DosOpen(base_name, &m_fd[ind], &action, 0, FILE_NORMAL, createFlag
421 , OPEN_FLAGS_SEQUENTIAL | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE
422 , NULL);
423 if(rc)
424 m_fd[ind] = -1;
425 #else
426 m_fd[ind] = ::open(base_name, flags, S_IRUSR | S_IWUSR);
427 #endif
428 }
429 else
430 {
431 m_stream[ind] = fopen(base_name, fopen_mode);
432 }
433
434 if( (m_fd && m_fd[ind] == -1) || (m_stream && m_stream[ind] == NULL) )
435 {
436 fprintf(stderr, "Can't open file %s\n", base_name);
437 return -1;
438 }
439 return 0;
440 }
441
442 void CFileOp::close()
443 {
444 if(!m_isopen)
445 return;
446 for(int i = 0; i < m_num_files; i++)
447 {
448 if(m_sync)
449 fflush(NULL);
450 if(m_stream && m_stream[i]) fclose(m_stream[i]);
451 if(m_fd && m_fd[i] != -1)
452 {
453 if(m_sync)
454 {
455 if(fsync(m_fd[i]))
456 fprintf(stderr, "Can't sync files.\n");
457 }
458 file_close(m_fd[i]);
459 }
460 }
461 m_isopen = false;
462 delete m_fd;
463 delete m_stream;
464 m_fd = NULL;
465 m_stream = NULL;
466 }
467
468
469 /*
470 * Do a typical-of-something random I/O. Any serious application that
471 * has a random I/O bottleneck is going to be smart enough to operate
472 * in a page mode, and not stupidly pull individual words out at
473 * odd offsets. To keep the cache from getting too clever, some
474 * pages must be updated. However an application that updated each of
475 * many random pages that it looked at is hard to imagine.
476 * However, it would be wrong to put the update percentage in as a
477 * parameter - the effect is too nonlinear. Need a profile
478 * of what Oracle or Ingres or some such actually does.
479 * Be warned - there is a *sharp* elbow in this curve - on a 1-MiB file,
480 * most substantial unix systems show >2000 random I/Os per second -
481 * obviously they've cached the whole thing and are just doing buffer
482 * copies.
483 */
484 int
485 CFileOp::doseek(long where, bool update)
486 {
487 if (seek(where, SEEK_SET) == -1)
488 return io_error("lseek in doseek");
489 if (read_block(PVOID(m_buf)) == -1)
490 return io_error("read in doseek");
491
492 /* every so often, update a block */
493 if (update)
494 { /* update this block */
495
496 /* touch a byte */
497 m_buf[int(rand()) % m_chunk_size]--;
498 if(seek(where, SEEK_SET) == -1)
499 return io_error("lseek in doseek update");
500 if (write_block(PVOID(m_buf)) == -1)
501 return io_error("write in doseek");
502 if(m_sync)
503 {
504 if(fsync(m_fd[m_file_ind]))
505 {
506 fprintf(stderr, "Can't sync file.\n");
507 return -1;
508 }
509 }
510 } /* update this block */
511 return 0;
512 }
513