1
2using namespace std;
3
4#include <sys/time.h>
5#ifdef OS2
6#define INCL_DOSFILEMGR
7#define INCL_BASE
8#include <os2.h>
9#include "os2-perfutil.h"
10/*
11   Convert 8-byte (low, high) time value to double
12*/
13#define LL2F(high, low) (4294967296.0*(high)+(low))
14#else
15#include <unistd.h>
16#include <sys/resource.h>
17#endif
18#include "bon_time.h"
19#include <time.h>
20#include <string.h>
21
22#ifndef NON_UNIX
23#include "conf.h"
24#endif
25
26#ifdef HAVE_ALGORITHM
27#include <algorithm>
28#else
29
30#ifdef HAVE_ALGO
31#include <algo>
32#else
33#ifdef HAVE_ALGO_H
34#include <algo.h>
35#else
36#define min(XX,YY) ((XX) < (YY) ? (XX) : (YY))
37#define max(XX,YY) ((XX) > (YY) ? (XX) : (YY))
38#endif
39#endif
40
41#endif
42
43#define TIMEVAL_TO_DOUBLE(XX) (double((XX).tv_sec) + double((XX).tv_usec) / 1000000.0)
44
45void BonTimer::timestamp()
46{
47  m_last_timestamp = get_cur_time();
48  m_last_cpustamp = get_cpu_use();
49}
50
51double
52BonTimer::time_so_far()
53{
54  return get_cur_time() - m_last_timestamp;
55}
56
57double
58BonTimer::cpu_so_far()
59{
60  return get_cpu_use() - m_last_cpustamp;
61}
62
63double
64BonTimer::get_cur_time()
65{
66#ifdef OS2
67  ULONG count = 0;
68  ULONG rc = DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &count, sizeof(count));
69  if(rc)
70    return 0.0;
71  return double(count)/1000.0;
72#else
73  struct timeval tp;
74
75  if (gettimeofday(&tp, static_cast<struct timezone *>(NULL)) == -1)
76    io_error("gettimeofday", true);
77  return TIMEVAL_TO_DOUBLE(tp);
78#endif
79}
80
81double
82BonTimer::get_cpu_use()
83{
84#ifdef OS2
85  double      busy_val, busy_val_prev;
86  double      intr_val, intr_val_prev;
87  CPUUTIL     CPUUtil;
88
89  ULONG rc = DosPerfSysCall(CMD_KI_RDCNT,(ULONG) &CPUUtil,0,0);
90  if(rc)
91    io_error("times", true);
92  return LL2F(CPUUtil.ulBusyHigh, CPUUtil.ulBusyLow)
93       + LL2F(CPUUtil.ulIntrHigh, CPUUtil.ulIntrLow);
94#else
95  struct rusage res_usage;
96
97  getrusage(RUSAGE_SELF, &res_usage);
98  return TIMEVAL_TO_DOUBLE(res_usage.ru_utime) + TIMEVAL_TO_DOUBLE(res_usage.ru_stime);
99#endif
100}
101
102void BonTimer::get_delta_t(tests_t test)
103{
104  m_delta[test].Elapsed = time_so_far();
105  m_delta[test].CPU = cpu_so_far();
106  timestamp();
107}
108
109void BonTimer::get_delta_report(report_s &rep)
110{
111  rep.EndTime = get_cur_time();
112  rep.CPU = cpu_so_far();
113  timestamp();
114}
115
116void BonTimer::add_delta_report(report_s &rep, tests_t test)
117{
118  if(m_delta[test].CPU == 0.0)
119  {
120    m_delta[test].FirstStart = rep.StartTime;
121    m_delta[test].LastStop = rep.EndTime;
122  }
123  else
124  {
125    m_delta[test].FirstStart = min(m_delta[test].FirstStart, rep.StartTime);
126    m_delta[test].LastStop = max(m_delta[test].LastStop, rep.EndTime);
127  }
128  m_delta[test].CPU += rep.CPU;
129  m_delta[test].Elapsed = m_delta[test].LastStop - m_delta[test].FirstStart;
130}
131
132BonTimer::BonTimer()
133 : m_type(txt)
134{
135  Initialize();
136}
137
138void
139BonTimer::Initialize()
140{
141  for(int i = 0; i < TestCount; i++)
142  {
143    m_delta[i].CPU = 0.0;
144    m_delta[i].Elapsed = 0.0;
145  }
146  timestamp();
147}
148
149int BonTimer::print_cpu_stat(tests_t test)
150{
151  if(m_delta[test].Elapsed == 0.0)
152  {
153    if(m_type == txt)
154      fprintf(m_fp, "    ");
155    else
156      fprintf(m_fp, ",");
157    return 0;
158  }
159  if(m_delta[test].Elapsed < MinTime)
160  {
161    if(m_type == txt)
162      fprintf(m_fp, " +++");
163    else
164      fprintf(m_fp, ",+++");
165    return 0;
166  }
167  int cpu = int(m_delta[test].CPU / m_delta[test].Elapsed * 100.0);
168  if(m_type == txt)
169    fprintf(m_fp, " %3d", cpu);
170  else
171    fprintf(m_fp, ",%d", cpu);
172  return 0;
173}
174
175int BonTimer::print_stat(tests_t test)
176{
177  if(m_delta[test].Elapsed == 0.0)
178  {
179    if(m_type == txt)
180      fprintf(m_fp, "      ");
181    else
182      fprintf(m_fp, ",");
183  }
184  else if(m_delta[test].Elapsed < MinTime)
185  {
186    if(m_type == txt)
187      fprintf(m_fp, " +++++");
188    else
189      fprintf(m_fp, ",+++++");
190  }
191  else
192  {
193    if(test == Lseek)
194    {
195      double seek_stat = double(Seeks) / m_delta[test].Elapsed;
196      if(m_type == txt)
197      {
198        if(seek_stat >= 1000.0)
199          fprintf(m_fp, " %5.0f", seek_stat);
200        else
201          fprintf(m_fp, " %5.1f", seek_stat);
202      }
203      else
204        fprintf(m_fp, ",%.1f", seek_stat);
205    }
206    else
207    {
208      int res = int(double(m_file_size) / (m_delta[test].Elapsed / 1024.0));
209      if(m_type == txt)
210        fprintf(m_fp, " %5d", res);
211      else
212        fprintf(m_fp, ",%d", res);
213    }
214  }
215  return print_cpu_stat(test);
216}
217
218int BonTimer::print_file_stat(tests_t test)
219{
220  if(m_delta[test].Elapsed == 0.0)
221  {
222    if(m_type == txt)
223      fprintf(m_fp, "      ");
224    else
225      fprintf(m_fp, ",");
226  }
227  else if(m_delta[test].Elapsed < MinTime)
228  {
229    if(m_type == txt)
230      fprintf(m_fp, " +++++");
231    else
232      fprintf(m_fp, ",+++++");
233  }
234  else
235  {
236    int res = int(double(m_directory_size) * double(DirectoryUnit)
237                / m_delta[test].Elapsed);
238    if(m_type == txt)
239      fprintf(m_fp, " %5d", res);
240    else
241      fprintf(m_fp, ",%d", res);
242  }
243
244  return print_cpu_stat(test);
245}
246
247void
248BonTimer::PrintHeader(FILE *fp)
249{
250  fprintf(fp, "name");
251  fprintf(fp, ",file_size,putc,putc_cpu,put_block,put_block_cpu,rewrite,rewrite_cpu,getc,getc_cpu,get_block,get_block_cpu,seeks,seeks_cpu");
252  fprintf(fp, ",num_files,seq_create,seq_create_cpu,seq_stat,seq_stat_cpu,seq_del,seq_del_cpu,ran_create,ran_create_cpu,ran_stat,ran_stat_cpu,ran_del,ran_del_cpu");
253  fprintf(fp, "\n");
254  fflush(NULL);
255}
256
257int
258BonTimer::DoReport(CPCCHAR machine, int file_size, int directory_size
259                 , int max_size, int min_size, int num_directories
260                 , int chunk_size, FILE *fp)
261{
262  m_fp = fp;
263  m_file_size = file_size;
264  m_directory_size = directory_size;
265  m_chunk_size = chunk_size;
266  const int txt_machine_size = 20;
267  if(m_file_size)
268  {
269    if(m_type == txt)
270    {
271      fprintf(m_fp, "Version %5s       ", BON_VERSION);
272      fprintf(m_fp,
273        "------Sequential Output------ --Sequential Input- --Random-\n");
274      fprintf(m_fp, "                    ");
275      fprintf(m_fp,
276        "-Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--\n");
277      if(m_chunk_size == DefaultChunkSize)
278        fprintf(m_fp, "Machine        Size ");
279      else
280        fprintf(m_fp, "Machine   Size:chnk ");
281      fprintf(m_fp, "K/sec %%CP K/sec %%CP K/sec %%CP K/sec %%CP K/sec ");
282      fprintf(m_fp, "%%CP  /sec %%CP\n");
283    }
284    char size_buf[1024];
285    if(m_file_size % 1024 == 0)
286      sprintf(size_buf, "%dG", m_file_size / 1024);
287    else
288      sprintf(size_buf, "%dM", m_file_size);
289    if(m_chunk_size != DefaultChunkSize)
290    {
291      char *tmp = size_buf + strlen(size_buf);
292      if(m_chunk_size >= 1024)
293        sprintf(tmp, ":%dk", m_chunk_size / 1024);
294      else
295        sprintf(tmp, ":%d", m_chunk_size);
296    }
297    char buf[4096];
298    if(m_type == txt)
299    {
300      // copy machine name to buf
301      //
302      snprintf(buf
303#ifndef NO_SNPRINTF
304              , txt_machine_size - 1
305#endif
306              , "%s                  ", machine);
307      buf[txt_machine_size - 1] = '\0';
308      // set cur to point to a byte past where we end the machine name
309      // size of the buf - size of the new data - 1 for the space - 1 for the
310      // terminating zero on the string
311      char *cur = &buf[txt_machine_size - strlen(size_buf) - 2];
312      *cur = ' '; // make cur a space
313      cur++; // increment to where we store the size
314      strcpy(cur, size_buf);  // copy the size in
315      fputs(buf, m_fp);
316    }
317    else
318    {
319      printf("%s,%s", machine, size_buf);
320    }
321    print_stat(Putc);
322    print_stat(FastWrite);
323    print_stat(ReWrite);
324    print_stat(Getc);
325    print_stat(FastRead);
326    print_stat(Lseek);
327    if(m_type == txt)
328      fprintf(m_fp, "\n");
329  }
330  else if(m_type == csv)
331  {
332    fprintf(m_fp, "%s,,,,,,,,,,,,,", machine);
333  }
334
335  if(m_directory_size)
336  {
337    char buf[128];
338    char *tmp;
339    sprintf(buf, "%d", m_directory_size);
340    if(max_size == -1)
341    {
342      strcat(buf, ":link");
343    }
344    else if(max_size == -2)
345    {
346      strcat(buf, ":symlink");
347    }
348    else if(max_size)
349    {
350      tmp = &buf[strlen(buf)];
351      sprintf(tmp, ":%d:%d", max_size, min_size);
352    }
353    if(num_directories > 1)
354    {
355      tmp = &buf[strlen(buf)];
356      sprintf(tmp, "/%d", num_directories);
357    }
358    if(m_type == txt)
359    {
360      if(m_file_size)
361        fprintf(m_fp, "                    ");
362      else
363        fprintf(m_fp, "Version %5s       ", BON_VERSION);
364      fprintf(m_fp,
365        "------Sequential Create------ --------Random Create--------\n");
366      if(m_file_size)
367        fprintf(m_fp, "                    ");
368      else
369        fprintf(m_fp, "%-19.19s ", machine);
370      fprintf(m_fp,
371           "-Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--\n");
372      if(min_size)
373      {
374        fprintf(m_fp, "files:max:min       ");
375      }
376      else
377      {
378        if(max_size)
379          fprintf(m_fp, "files:max           ");
380        else
381          fprintf(m_fp, "              files ");
382      }
383      fprintf(m_fp, " /sec %%CP  /sec %%CP  /sec %%CP  /sec %%CP  /sec ");
384      fprintf(m_fp, "%%CP  /sec %%CP\n");
385      fprintf(m_fp, "%19s", buf);
386    }
387    else
388    {
389      fprintf(m_fp, ",%s", buf);
390    }
391    print_file_stat(CreateSeq);
392    print_file_stat(StatSeq);
393    print_file_stat(DelSeq);
394    print_file_stat(CreateRand);
395    print_file_stat(StatRand);
396    print_file_stat(DelRand);
397    fprintf(m_fp, "\n");
398  }
399  else if(m_type == csv)
400  {
401    fprintf(m_fp, ",,,,,,,,,,,,,\n");
402  }
403  fflush(stdout);
404  return 0;
405}
406
407