~percona-dev/percona-innodb-plugin/percona-innodb-1.0

« back to all changes in this revision

Viewing changes to ut/ut0ut.c

  • Committer: Vadim Tkachenko
  • Date: 2008-12-01 02:05:57 UTC
  • Revision ID: vadim@percona.com-20081201020557-p7k2m94mjtdg1a83
New rw-locks

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************
 
2
Various utilities for Innobase.
 
3
 
 
4
(c) 1994, 1995 Innobase Oy
 
5
 
 
6
Created 5/11/1994 Heikki Tuuri
 
7
********************************************************************/
 
8
 
 
9
#include "ut0ut.h"
 
10
 
 
11
#ifdef UNIV_NONINL
 
12
#include "ut0ut.ic"
 
13
#endif
 
14
 
 
15
#include <stdarg.h>
 
16
#include <string.h>
 
17
#include <ctype.h>
 
18
 
 
19
#include "trx0trx.h"
 
20
#include "ha_prototypes.h"
 
21
#ifndef UNIV_HOTBACKUP
 
22
# include "mysql_com.h" /* NAME_LEN */
 
23
#endif /* UNIV_HOTBACKUP */
 
24
 
 
25
UNIV_INTERN ibool       ut_always_false = FALSE;
 
26
 
 
27
#ifdef __WIN__
 
28
/*********************************************************************
 
29
NOTE: The Windows epoch starts from 1601/01/01 whereas the Unix
 
30
epoch starts from 1970/1/1. For selection of constant see:
 
31
http://support.microsoft.com/kb/167296/ */
 
32
#define WIN_TO_UNIX_DELTA_USEC  ((ib_int64_t) 11644473600000000ULL)
 
33
 
 
34
 
 
35
/*********************************************************************
 
36
This is the Windows version of gettimeofday(2).*/
 
37
static
 
38
int
 
39
ut_gettimeofday(
 
40
/*============*/
 
41
                        /* out: 0 if all OK else -1 */
 
42
        struct timeval* tv,     /* out: Values are relative to Unix epoch */
 
43
        void*           tz)     /* in: not used */
 
44
{
 
45
        FILETIME        ft;
 
46
        ib_int64_t      tm;
 
47
 
 
48
        if (!tv) {
 
49
                errno = EINVAL;
 
50
                return(-1);
 
51
        }
 
52
 
 
53
        GetSystemTimeAsFileTime(&ft);
 
54
 
 
55
        tm = (ib_int64_t) ft.dwHighDateTime << 32;
 
56
        tm |= ft.dwLowDateTime;
 
57
 
 
58
        ut_a(tm >= 0);  /* If tm wraps over to negative, the quotient / 10
 
59
                        does not work */
 
60
 
 
61
        tm /= 10;       /* Convert from 100 nsec periods to usec */
 
62
 
 
63
        /* If we don't convert to the Unix epoch the value for
 
64
        struct timeval::tv_sec will overflow.*/
 
65
        tm -= WIN_TO_UNIX_DELTA_USEC;
 
66
 
 
67
        tv->tv_sec  = (long) (tm / 1000000L);
 
68
        tv->tv_usec = (long) (tm % 1000000L);
 
69
 
 
70
        return(0);
 
71
}
 
72
#else
 
73
#define ut_gettimeofday         gettimeofday
 
74
#endif
 
75
 
 
76
/************************************************************
 
77
Gets the high 32 bits in a ulint. That is makes a shift >> 32,
 
78
but since there seem to be compiler bugs in both gcc and Visual C++,
 
79
we do this by a special conversion. */
 
80
UNIV_INTERN
 
81
ulint
 
82
ut_get_high32(
 
83
/*==========*/
 
84
                        /* out: a >> 32 */
 
85
        ulint   a)      /* in: ulint */
 
86
{
 
87
        ib_int64_t      i;
 
88
 
 
89
        i = (ib_int64_t)a;
 
90
 
 
91
        i = i >> 32;
 
92
 
 
93
        return((ulint)i);
 
94
}
 
95
 
 
96
/**************************************************************
 
97
Returns system time. We do not specify the format of the time returned:
 
98
the only way to manipulate it is to use the function ut_difftime. */
 
99
UNIV_INTERN
 
100
ib_time_t
 
101
ut_time(void)
 
102
/*=========*/
 
103
{
 
104
        return(time(NULL));
 
105
}
 
106
 
 
107
/**************************************************************
 
108
Returns system time. */
 
109
UNIV_INTERN
 
110
void
 
111
ut_usectime(
 
112
/*========*/
 
113
        ulint*  sec,    /* out: seconds since the Epoch */
 
114
        ulint*  ms)     /* out: microseconds since the Epoch+*sec */
 
115
{
 
116
        struct timeval  tv;
 
117
 
 
118
        ut_gettimeofday(&tv, NULL);
 
119
        *sec = (ulint) tv.tv_sec;
 
120
        *ms  = (ulint) tv.tv_usec;
 
121
}
 
122
 
 
123
/**************************************************************
 
124
Returns the number of microseconds since epoch. Similar to
 
125
time(3), the return value is also stored in *tloc, provided
 
126
that tloc is non-NULL. */
 
127
UNIV_INTERN
 
128
ullint
 
129
ut_time_us(
 
130
/*=======*/
 
131
                        /* out: us since epoch */
 
132
        ullint* tloc)   /* out: us since epoch, if non-NULL */
 
133
{
 
134
        struct timeval  tv;
 
135
        ullint          us;
 
136
 
 
137
        ut_gettimeofday(&tv, NULL);
 
138
 
 
139
        us = (ullint) tv.tv_sec * 1000000 + tv.tv_usec;
 
140
 
 
141
        if (tloc != NULL) {
 
142
                *tloc = us;
 
143
        }
 
144
 
 
145
        return(us);
 
146
}
 
147
 
 
148
/**************************************************************
 
149
Returns the difference of two times in seconds. */
 
150
UNIV_INTERN
 
151
double
 
152
ut_difftime(
 
153
/*========*/
 
154
                                /* out: time2 - time1 expressed in seconds */
 
155
        ib_time_t       time2,  /* in: time */
 
156
        ib_time_t       time1)  /* in: time */
 
157
{
 
158
        return(difftime(time2, time1));
 
159
}
 
160
 
 
161
/**************************************************************
 
162
Prints a timestamp to a file. */
 
163
UNIV_INTERN
 
164
void
 
165
ut_print_timestamp(
 
166
/*===============*/
 
167
        FILE*  file) /* in: file where to print */
 
168
{
 
169
#ifdef __WIN__
 
170
        SYSTEMTIME cal_tm;
 
171
 
 
172
        GetLocalTime(&cal_tm);
 
173
 
 
174
        fprintf(file,"%02d%02d%02d %2d:%02d:%02d",
 
175
                (int)cal_tm.wYear % 100,
 
176
                (int)cal_tm.wMonth,
 
177
                (int)cal_tm.wDay,
 
178
                (int)cal_tm.wHour,
 
179
                (int)cal_tm.wMinute,
 
180
                (int)cal_tm.wSecond);
 
181
#else
 
182
        struct tm  cal_tm;
 
183
        struct tm* cal_tm_ptr;
 
184
        time_t     tm;
 
185
 
 
186
        time(&tm);
 
187
 
 
188
#ifdef HAVE_LOCALTIME_R
 
189
        localtime_r(&tm, &cal_tm);
 
190
        cal_tm_ptr = &cal_tm;
 
191
#else
 
192
        cal_tm_ptr = localtime(&tm);
 
193
#endif
 
194
        fprintf(file,"%02d%02d%02d %2d:%02d:%02d",
 
195
                cal_tm_ptr->tm_year % 100,
 
196
                cal_tm_ptr->tm_mon + 1,
 
197
                cal_tm_ptr->tm_mday,
 
198
                cal_tm_ptr->tm_hour,
 
199
                cal_tm_ptr->tm_min,
 
200
                cal_tm_ptr->tm_sec);
 
201
#endif
 
202
}
 
203
 
 
204
/**************************************************************
 
205
Sprintfs a timestamp to a buffer, 13..14 chars plus terminating NUL. */
 
206
UNIV_INTERN
 
207
void
 
208
ut_sprintf_timestamp(
 
209
/*=================*/
 
210
        char*   buf) /* in: buffer where to sprintf */
 
211
{
 
212
#ifdef __WIN__
 
213
        SYSTEMTIME cal_tm;
 
214
 
 
215
        GetLocalTime(&cal_tm);
 
216
 
 
217
        sprintf(buf, "%02d%02d%02d %2d:%02d:%02d",
 
218
                (int)cal_tm.wYear % 100,
 
219
                (int)cal_tm.wMonth,
 
220
                (int)cal_tm.wDay,
 
221
                (int)cal_tm.wHour,
 
222
                (int)cal_tm.wMinute,
 
223
                (int)cal_tm.wSecond);
 
224
#else
 
225
        struct tm  cal_tm;
 
226
        struct tm* cal_tm_ptr;
 
227
        time_t     tm;
 
228
 
 
229
        time(&tm);
 
230
 
 
231
#ifdef HAVE_LOCALTIME_R
 
232
        localtime_r(&tm, &cal_tm);
 
233
        cal_tm_ptr = &cal_tm;
 
234
#else
 
235
        cal_tm_ptr = localtime(&tm);
 
236
#endif
 
237
        sprintf(buf, "%02d%02d%02d %2d:%02d:%02d",
 
238
                cal_tm_ptr->tm_year % 100,
 
239
                cal_tm_ptr->tm_mon + 1,
 
240
                cal_tm_ptr->tm_mday,
 
241
                cal_tm_ptr->tm_hour,
 
242
                cal_tm_ptr->tm_min,
 
243
                cal_tm_ptr->tm_sec);
 
244
#endif
 
245
}
 
246
 
 
247
/**************************************************************
 
248
Sprintfs a timestamp to a buffer with no spaces and with ':' characters
 
249
replaced by '_'. */
 
250
UNIV_INTERN
 
251
void
 
252
ut_sprintf_timestamp_without_extra_chars(
 
253
/*=====================================*/
 
254
        char*   buf) /* in: buffer where to sprintf */
 
255
{
 
256
#ifdef __WIN__
 
257
        SYSTEMTIME cal_tm;
 
258
 
 
259
        GetLocalTime(&cal_tm);
 
260
 
 
261
        sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d",
 
262
                (int)cal_tm.wYear % 100,
 
263
                (int)cal_tm.wMonth,
 
264
                (int)cal_tm.wDay,
 
265
                (int)cal_tm.wHour,
 
266
                (int)cal_tm.wMinute,
 
267
                (int)cal_tm.wSecond);
 
268
#else
 
269
        struct tm  cal_tm;
 
270
        struct tm* cal_tm_ptr;
 
271
        time_t     tm;
 
272
 
 
273
        time(&tm);
 
274
 
 
275
#ifdef HAVE_LOCALTIME_R
 
276
        localtime_r(&tm, &cal_tm);
 
277
        cal_tm_ptr = &cal_tm;
 
278
#else
 
279
        cal_tm_ptr = localtime(&tm);
 
280
#endif
 
281
        sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d",
 
282
                cal_tm_ptr->tm_year % 100,
 
283
                cal_tm_ptr->tm_mon + 1,
 
284
                cal_tm_ptr->tm_mday,
 
285
                cal_tm_ptr->tm_hour,
 
286
                cal_tm_ptr->tm_min,
 
287
                cal_tm_ptr->tm_sec);
 
288
#endif
 
289
}
 
290
 
 
291
/**************************************************************
 
292
Returns current year, month, day. */
 
293
UNIV_INTERN
 
294
void
 
295
ut_get_year_month_day(
 
296
/*==================*/
 
297
        ulint*  year,   /* out: current year */
 
298
        ulint*  month,  /* out: month */
 
299
        ulint*  day)    /* out: day */
 
300
{
 
301
#ifdef __WIN__
 
302
        SYSTEMTIME cal_tm;
 
303
 
 
304
        GetLocalTime(&cal_tm);
 
305
 
 
306
        *year = (ulint)cal_tm.wYear;
 
307
        *month = (ulint)cal_tm.wMonth;
 
308
        *day = (ulint)cal_tm.wDay;
 
309
#else
 
310
        struct tm  cal_tm;
 
311
        struct tm* cal_tm_ptr;
 
312
        time_t     tm;
 
313
 
 
314
        time(&tm);
 
315
 
 
316
#ifdef HAVE_LOCALTIME_R
 
317
        localtime_r(&tm, &cal_tm);
 
318
        cal_tm_ptr = &cal_tm;
 
319
#else
 
320
        cal_tm_ptr = localtime(&tm);
 
321
#endif
 
322
        *year = (ulint)cal_tm_ptr->tm_year + 1900;
 
323
        *month = (ulint)cal_tm_ptr->tm_mon + 1;
 
324
        *day = (ulint)cal_tm_ptr->tm_mday;
 
325
#endif
 
326
}
 
327
 
 
328
/*****************************************************************
 
329
Runs an idle loop on CPU. The argument gives the desired delay
 
330
in microseconds on 100 MHz Pentium + Visual C++. */
 
331
UNIV_INTERN
 
332
ulint
 
333
ut_delay(
 
334
/*=====*/
 
335
                        /* out: dummy value */
 
336
        ulint   delay)  /* in: delay in microseconds on 100 MHz Pentium */
 
337
{
 
338
        ulint   i, j;
 
339
 
 
340
        j = 0;
 
341
 
 
342
        for (i = 0; i < delay * 50; i++) {
 
343
                j += i;
 
344
        }
 
345
 
 
346
        if (ut_always_false) {
 
347
                ut_always_false = (ibool) j;
 
348
        }
 
349
 
 
350
        return(j);
 
351
}
 
352
 
 
353
/*****************************************************************
 
354
Prints the contents of a memory buffer in hex and ascii. */
 
355
UNIV_INTERN
 
356
void
 
357
ut_print_buf(
 
358
/*=========*/
 
359
        FILE*           file,   /* in: file where to print */
 
360
        const void*     buf,    /* in: memory buffer */
 
361
        ulint           len)    /* in: length of the buffer */
 
362
{
 
363
        const byte*     data;
 
364
        ulint           i;
 
365
 
 
366
        UNIV_MEM_ASSERT_RW(buf, len);
 
367
 
 
368
        fprintf(file, " len %lu; hex ", len);
 
369
 
 
370
        for (data = (const byte*)buf, i = 0; i < len; i++) {
 
371
                fprintf(file, "%02lx", (ulong)*data++);
 
372
        }
 
373
 
 
374
        fputs("; asc ", file);
 
375
 
 
376
        data = (const byte*)buf;
 
377
 
 
378
        for (i = 0; i < len; i++) {
 
379
                int     c = (int) *data++;
 
380
                putc(isprint(c) ? c : ' ', file);
 
381
        }
 
382
 
 
383
        putc(';', file);
 
384
}
 
385
 
 
386
/*****************************************************************
 
387
Calculates fast the number rounded up to the nearest power of 2. */
 
388
UNIV_INTERN
 
389
ulint
 
390
ut_2_power_up(
 
391
/*==========*/
 
392
                        /* out: first power of 2 which is >= n */
 
393
        ulint   n)      /* in: number != 0 */
 
394
{
 
395
        ulint   res;
 
396
 
 
397
        res = 1;
 
398
 
 
399
        ut_ad(n > 0);
 
400
 
 
401
        while (res < n) {
 
402
                res = res * 2;
 
403
        }
 
404
 
 
405
        return(res);
 
406
}
 
407
 
 
408
/**************************************************************************
 
409
Outputs a NUL-terminated file name, quoted with apostrophes. */
 
410
UNIV_INTERN
 
411
void
 
412
ut_print_filename(
 
413
/*==============*/
 
414
        FILE*           f,      /* in: output stream */
 
415
        const char*     name)   /* in: name to print */
 
416
{
 
417
        putc('\'', f);
 
418
        for (;;) {
 
419
                int     c = *name++;
 
420
                switch (c) {
 
421
                case 0:
 
422
                        goto done;
 
423
                case '\'':
 
424
                        putc(c, f);
 
425
                        /* fall through */
 
426
                default:
 
427
                        putc(c, f);
 
428
                }
 
429
        }
 
430
done:
 
431
        putc('\'', f);
 
432
}
 
433
 
 
434
/**************************************************************************
 
435
Outputs a fixed-length string, quoted as an SQL identifier.
 
436
If the string contains a slash '/', the string will be
 
437
output as two identifiers separated by a period (.),
 
438
as in SQL database_name.identifier. */
 
439
UNIV_INTERN
 
440
void
 
441
ut_print_name(
 
442
/*==========*/
 
443
        FILE*           f,      /* in: output stream */
 
444
        trx_t*          trx,    /* in: transaction */
 
445
        ibool           table_id,/* in: TRUE=print a table name,
 
446
                                FALSE=print other identifier */
 
447
        const char*     name)   /* in: name to print */
 
448
{
 
449
        ut_print_namel(f, trx, table_id, name, strlen(name));
 
450
}
 
451
 
 
452
/**************************************************************************
 
453
Outputs a fixed-length string, quoted as an SQL identifier.
 
454
If the string contains a slash '/', the string will be
 
455
output as two identifiers separated by a period (.),
 
456
as in SQL database_name.identifier. */
 
457
UNIV_INTERN
 
458
void
 
459
ut_print_namel(
 
460
/*===========*/
 
461
        FILE*           f,      /* in: output stream */
 
462
        trx_t*          trx,    /* in: transaction (NULL=no quotes) */
 
463
        ibool           table_id,/* in: TRUE=print a table name,
 
464
                                FALSE=print other identifier */
 
465
        const char*     name,   /* in: name to print */
 
466
        ulint           namelen)/* in: length of name */
 
467
{
 
468
#ifdef UNIV_HOTBACKUP
 
469
        fwrite(name, 1, namelen, f);
 
470
#else
 
471
        /* 2 * NAME_LEN for database and table name,
 
472
        and some slack for the #mysql50# prefix and quotes */
 
473
        char            buf[3 * NAME_LEN];
 
474
        const char*     bufend;
 
475
 
 
476
        bufend = innobase_convert_name(buf, sizeof buf,
 
477
                                       name, namelen,
 
478
                                       trx ? trx->mysql_thd : NULL,
 
479
                                       table_id);
 
480
 
 
481
        fwrite(buf, 1, bufend - buf, f);
 
482
#endif
 
483
}
 
484
 
 
485
/**************************************************************************
 
486
Catenate files. */
 
487
UNIV_INTERN
 
488
void
 
489
ut_copy_file(
 
490
/*=========*/
 
491
        FILE*   dest,   /* in: output file */
 
492
        FILE*   src)    /* in: input file to be appended to output */
 
493
{
 
494
        long    len = ftell(src);
 
495
        char    buf[4096];
 
496
 
 
497
        rewind(src);
 
498
        do {
 
499
                size_t  maxs = len < (long) sizeof buf
 
500
                        ? (size_t) len
 
501
                        : sizeof buf;
 
502
                size_t  size = fread(buf, 1, maxs, src);
 
503
                fwrite(buf, 1, size, dest);
 
504
                len -= (long) size;
 
505
                if (size < maxs) {
 
506
                        break;
 
507
                }
 
508
        } while (len > 0);
 
509
}
 
510
 
 
511
/**************************************************************************
 
512
snprintf(). */
 
513
 
 
514
#ifdef __WIN__
 
515
#include <stdarg.h>
 
516
int
 
517
ut_snprintf(
 
518
                                /* out: number of characters that would
 
519
                                have been printed if the size were
 
520
                                unlimited, not including the terminating
 
521
                                '\0'. */
 
522
        char*           str,    /* out: string */
 
523
        size_t          size,   /* in: str size */
 
524
        const char*     fmt,    /* in: format */
 
525
        ...)                    /* in: format values */
 
526
{
 
527
        int     res;
 
528
        va_list ap1;
 
529
        va_list ap2;
 
530
 
 
531
        va_start(ap1, fmt);
 
532
        va_start(ap2, fmt);
 
533
 
 
534
        res = _vscprintf(fmt, ap1);
 
535
        ut_a(res != -1);
 
536
 
 
537
        if (size > 0) {
 
538
                _vsnprintf(str, size, fmt, ap2);
 
539
 
 
540
                if ((size_t) res >= size) {
 
541
                        str[size - 1] = '\0';
 
542
                }
 
543
        }
 
544
 
 
545
        va_end(ap1);
 
546
        va_end(ap2);
 
547
 
 
548
        return(res);
 
549
}
 
550
#endif /* __WIN__ */