~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/innodb_plugin/ut/ut0ut.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

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