~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/ut/ut0mem.c

Re-org'd the replication stuff into slots.

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
 
 
5
 
This program is free software; you can redistribute it and/or modify it under
6
 
the terms of the GNU General Public License as published by the Free Software
7
 
Foundation; version 2 of the License.
8
 
 
9
 
This program is distributed in the hope that it will be useful, but WITHOUT
10
 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
 
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
 
 
13
 
You should have received a copy of the GNU General Public License along with
14
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
 
St, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
*****************************************************************************/
18
 
 
19
 
/********************************************************************//**
20
 
@file ut/ut0mem.c
21
 
Memory primitives
22
 
 
23
 
Created 5/11/1994 Heikki Tuuri
24
 
*************************************************************************/
25
 
 
26
 
#include "ut0mem.h"
27
 
 
28
 
#ifdef UNIV_NONINL
29
 
#include "ut0mem.ic"
30
 
#endif
31
 
 
32
 
#ifndef UNIV_HOTBACKUP
33
 
# include "os0thread.h"
34
 
# include "srv0srv.h"
35
 
 
36
 
#include <stdlib.h>
37
 
#include <errno.h>
38
 
 
39
 
/** This struct is placed first in every allocated memory block */
40
 
typedef struct ut_mem_block_struct ut_mem_block_t;
41
 
 
42
 
/** The total amount of memory currently allocated from the operating
43
 
system with os_mem_alloc_large() or malloc().  Does not count malloc()
44
 
if srv_use_sys_malloc is set.  Protected by ut_list_mutex. */
45
 
UNIV_INTERN ulint               ut_total_allocated_memory       = 0;
46
 
 
47
 
/** Mutex protecting ut_total_allocated_memory and ut_mem_block_list */
48
 
UNIV_INTERN os_fast_mutex_t     ut_list_mutex;
49
 
 
50
 
/** Dynamically allocated memory block */
51
 
struct ut_mem_block_struct{
52
 
        UT_LIST_NODE_T(ut_mem_block_t) mem_block_list;
53
 
                        /*!< mem block list node */
54
 
        ulint   size;   /*!< size of allocated memory */
55
 
        ulint   magic_n;/*!< magic number (UT_MEM_MAGIC_N) */
56
 
};
57
 
 
58
 
/** The value of ut_mem_block_struct::magic_n.  Used in detecting
59
 
memory corruption. */
60
 
#define UT_MEM_MAGIC_N  1601650166
61
 
 
62
 
/** List of all memory blocks allocated from the operating system
63
 
with malloc.  Protected by ut_list_mutex. */
64
 
static UT_LIST_BASE_NODE_T(ut_mem_block_t)   ut_mem_block_list;
65
 
 
66
 
/** Flag: has ut_mem_block_list been initialized? */
67
 
static ibool  ut_mem_block_list_inited = FALSE;
68
 
 
69
 
/** A dummy pointer for generating a null pointer exception in
70
 
ut_malloc_low() */
71
 
static ulint*   ut_mem_null_ptr = NULL;
72
 
 
73
 
/**********************************************************************//**
74
 
Initializes the mem block list at database startup. */
75
 
UNIV_INTERN
76
 
void
77
 
ut_mem_init(void)
78
 
/*=============*/
79
 
{
80
 
        ut_a(!ut_mem_block_list_inited);
81
 
        os_fast_mutex_init(&ut_list_mutex);
82
 
        UT_LIST_INIT(ut_mem_block_list);
83
 
        ut_mem_block_list_inited = TRUE;
84
 
}
85
 
#endif /* !UNIV_HOTBACKUP */
86
 
 
87
 
/**********************************************************************//**
88
 
Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
89
 
defined and set_to_zero is TRUE.
90
 
@return own: allocated memory */
91
 
UNIV_INTERN
92
 
void*
93
 
ut_malloc_low(
94
 
/*==========*/
95
 
        ulint   n,              /*!< in: number of bytes to allocate */
96
 
        ibool   set_to_zero,    /*!< in: TRUE if allocated memory should be
97
 
                                set to zero if UNIV_SET_MEM_TO_ZERO is
98
 
                                defined */
99
 
        ibool   assert_on_error)/*!< in: if TRUE, we crash mysqld if the
100
 
                                memory cannot be allocated */
101
 
{
102
 
#ifndef UNIV_HOTBACKUP
103
 
        ulint   retry_count;
104
 
        void*   ret;
105
 
 
106
 
        if (UNIV_LIKELY(srv_use_sys_malloc)) {
107
 
                ret = malloc(n);
108
 
                ut_a(ret || !assert_on_error);
109
 
 
110
 
#ifdef UNIV_SET_MEM_TO_ZERO
111
 
                if (set_to_zero) {
112
 
                        memset(ret, '\0', n);
113
 
                        UNIV_MEM_ALLOC(ret, n);
114
 
                }
115
 
#endif
116
 
                return(ret);
117
 
        }
118
 
 
119
 
        ut_ad((sizeof(ut_mem_block_t) % 8) == 0); /* check alignment ok */
120
 
        ut_a(ut_mem_block_list_inited);
121
 
 
122
 
        retry_count = 0;
123
 
retry:
124
 
        os_fast_mutex_lock(&ut_list_mutex);
125
 
 
126
 
        ret = malloc(n + sizeof(ut_mem_block_t));
127
 
 
128
 
        if (ret == NULL && retry_count < 60) {
129
 
                if (retry_count == 0) {
130
 
                        ut_print_timestamp(stderr);
131
 
 
132
 
                        fprintf(stderr,
133
 
                                "  InnoDB: Error: cannot allocate"
134
 
                                " %lu bytes of\n"
135
 
                                "InnoDB: memory with malloc!"
136
 
                                " Total allocated memory\n"
137
 
                                "InnoDB: by InnoDB %lu bytes."
138
 
                                " Operating system errno: %lu\n"
139
 
                                "InnoDB: Check if you should"
140
 
                                " increase the swap file or\n"
141
 
                                "InnoDB: ulimits of your operating system.\n"
142
 
                                "InnoDB: On FreeBSD check you"
143
 
                                " have compiled the OS with\n"
144
 
                                "InnoDB: a big enough maximum process size.\n"
145
 
                                "InnoDB: Note that in most 32-bit"
146
 
                                " computers the process\n"
147
 
                                "InnoDB: memory space is limited"
148
 
                                " to 2 GB or 4 GB.\n"
149
 
                                "InnoDB: We keep retrying"
150
 
                                " the allocation for 60 seconds...\n",
151
 
                                (ulong) n, (ulong) ut_total_allocated_memory,
152
 
#ifdef __WIN__
153
 
                                (ulong) GetLastError()
154
 
#else
155
 
                                (ulong) errno
156
 
#endif
157
 
                                );
158
 
                }
159
 
 
160
 
                os_fast_mutex_unlock(&ut_list_mutex);
161
 
 
162
 
                /* Sleep for a second and retry the allocation; maybe this is
163
 
                just a temporary shortage of memory */
164
 
 
165
 
                os_thread_sleep(1000000);
166
 
 
167
 
                retry_count++;
168
 
 
169
 
                goto retry;
170
 
        }
171
 
 
172
 
        if (ret == NULL) {
173
 
                /* Flush stderr to make more probable that the error
174
 
                message gets in the error file before we generate a seg
175
 
                fault */
176
 
 
177
 
                fflush(stderr);
178
 
 
179
 
                os_fast_mutex_unlock(&ut_list_mutex);
180
 
 
181
 
                /* Make an intentional seg fault so that we get a stack
182
 
                trace */
183
 
                if (assert_on_error) {
184
 
                        ut_print_timestamp(stderr);
185
 
 
186
 
                        fprintf(stderr,
187
 
                                "  InnoDB: We now intentionally"
188
 
                                " generate a seg fault so that\n"
189
 
                                "InnoDB: on Linux we get a stack trace.\n");
190
 
 
191
 
                        if (*ut_mem_null_ptr) ut_mem_null_ptr = 0;
192
 
                } else {
193
 
                        return(NULL);
194
 
                }
195
 
        }
196
 
 
197
 
        if (set_to_zero) {
198
 
#ifdef UNIV_SET_MEM_TO_ZERO
199
 
                memset(ret, '\0', n + sizeof(ut_mem_block_t));
200
 
#endif
201
 
        }
202
 
 
203
 
        UNIV_MEM_ALLOC(ret, n + sizeof(ut_mem_block_t));
204
 
 
205
 
        ((ut_mem_block_t*)ret)->size = n + sizeof(ut_mem_block_t);
206
 
        ((ut_mem_block_t*)ret)->magic_n = UT_MEM_MAGIC_N;
207
 
 
208
 
        ut_total_allocated_memory += n + sizeof(ut_mem_block_t);
209
 
 
210
 
        UT_LIST_ADD_FIRST(mem_block_list, ut_mem_block_list,
211
 
                          ((ut_mem_block_t*)ret));
212
 
        os_fast_mutex_unlock(&ut_list_mutex);
213
 
 
214
 
        return((void*)((byte*)ret + sizeof(ut_mem_block_t)));
215
 
#else /* !UNIV_HOTBACKUP */
216
 
        void*   ret = malloc(n);
217
 
        ut_a(ret || !assert_on_error);
218
 
 
219
 
# ifdef UNIV_SET_MEM_TO_ZERO
220
 
        if (set_to_zero) {
221
 
                memset(ret, '\0', n);
222
 
        }
223
 
# endif
224
 
        return(ret);
225
 
#endif /* !UNIV_HOTBACKUP */
226
 
}
227
 
 
228
 
/**********************************************************************//**
229
 
Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
230
 
defined.
231
 
@return own: allocated memory */
232
 
UNIV_INTERN
233
 
void*
234
 
ut_malloc(
235
 
/*======*/
236
 
        ulint   n)      /*!< in: number of bytes to allocate */
237
 
{
238
 
#ifndef UNIV_HOTBACKUP
239
 
        return(ut_malloc_low(n, TRUE, TRUE));
240
 
#else /* !UNIV_HOTBACKUP */
241
 
        return(malloc(n));
242
 
#endif /* !UNIV_HOTBACKUP */
243
 
}
244
 
 
245
 
#ifndef UNIV_HOTBACKUP
246
 
/**********************************************************************//**
247
 
Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs
248
 
out. It cannot be used if we want to return an error message. Prints to
249
 
stderr a message if fails.
250
 
@return TRUE if succeeded */
251
 
UNIV_INTERN
252
 
ibool
253
 
ut_test_malloc(
254
 
/*===========*/
255
 
        ulint   n)      /*!< in: try to allocate this many bytes */
256
 
{
257
 
        void*   ret;
258
 
 
259
 
        ret = malloc(n);
260
 
 
261
 
        if (ret == NULL) {
262
 
                ut_print_timestamp(stderr);
263
 
                fprintf(stderr,
264
 
                        "  InnoDB: Error: cannot allocate"
265
 
                        " %lu bytes of memory for\n"
266
 
                        "InnoDB: a BLOB with malloc! Total allocated memory\n"
267
 
                        "InnoDB: by InnoDB %lu bytes."
268
 
                        " Operating system errno: %d\n"
269
 
                        "InnoDB: Check if you should increase"
270
 
                        " the swap file or\n"
271
 
                        "InnoDB: ulimits of your operating system.\n"
272
 
                        "InnoDB: On FreeBSD check you have"
273
 
                        " compiled the OS with\n"
274
 
                        "InnoDB: a big enough maximum process size.\n",
275
 
                        (ulong) n,
276
 
                        (ulong) ut_total_allocated_memory,
277
 
                        (int) errno);
278
 
                return(FALSE);
279
 
        }
280
 
 
281
 
        free(ret);
282
 
 
283
 
        return(TRUE);
284
 
}
285
 
#endif /* !UNIV_HOTBACKUP */
286
 
 
287
 
/**********************************************************************//**
288
 
Frees a memory block allocated with ut_malloc. Freeing a NULL pointer is
289
 
a nop. */
290
 
UNIV_INTERN
291
 
void
292
 
ut_free(
293
 
/*====*/
294
 
        void* ptr)  /*!< in, own: memory block, can be NULL */
295
 
{
296
 
#ifndef UNIV_HOTBACKUP
297
 
        ut_mem_block_t* block;
298
 
 
299
 
        if (ptr == NULL) {
300
 
                return;
301
 
        } else if (UNIV_LIKELY(srv_use_sys_malloc)) {
302
 
                free(ptr);
303
 
                return;
304
 
        }
305
 
 
306
 
        block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t));
307
 
 
308
 
        os_fast_mutex_lock(&ut_list_mutex);
309
 
 
310
 
        ut_a(block->magic_n == UT_MEM_MAGIC_N);
311
 
        ut_a(ut_total_allocated_memory >= block->size);
312
 
 
313
 
        ut_total_allocated_memory -= block->size;
314
 
 
315
 
        UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
316
 
        free(block);
317
 
 
318
 
        os_fast_mutex_unlock(&ut_list_mutex);
319
 
#else /* !UNIV_HOTBACKUP */
320
 
        free(ptr);
321
 
#endif /* !UNIV_HOTBACKUP */
322
 
}
323
 
 
324
 
#ifndef UNIV_HOTBACKUP
325
 
/**********************************************************************//**
326
 
Implements realloc. This is needed by /pars/lexyy.c. Otherwise, you should not
327
 
use this function because the allocation functions in mem0mem.h are the
328
 
recommended ones in InnoDB.
329
 
 
330
 
man realloc in Linux, 2004:
331
 
 
332
 
       realloc()  changes the size of the memory block pointed to
333
 
       by ptr to size bytes.  The contents will be  unchanged  to
334
 
       the minimum of the old and new sizes; newly allocated mem-
335
 
       ory will be uninitialized.  If ptr is NULL,  the  call  is
336
 
       equivalent  to malloc(size); if size is equal to zero, the
337
 
       call is equivalent to free(ptr).  Unless ptr is  NULL,  it
338
 
       must  have  been  returned by an earlier call to malloc(),
339
 
       calloc() or realloc().
340
 
 
341
 
RETURN VALUE
342
 
       realloc() returns a pointer to the newly allocated memory,
343
 
       which is suitably aligned for any kind of variable and may
344
 
       be different from ptr, or NULL if the  request  fails.  If
345
 
       size  was equal to 0, either NULL or a pointer suitable to
346
 
       be passed to free() is returned.  If realloc()  fails  the
347
 
       original  block  is  left  untouched  - it is not freed or
348
 
       moved.
349
 
@return own: pointer to new mem block or NULL */
350
 
UNIV_INTERN
351
 
void*
352
 
ut_realloc(
353
 
/*=======*/
354
 
        void*   ptr,    /*!< in: pointer to old block or NULL */
355
 
        ulint   size)   /*!< in: desired size */
356
 
{
357
 
        ut_mem_block_t* block;
358
 
        ulint           old_size;
359
 
        ulint           min_size;
360
 
        void*           new_ptr;
361
 
 
362
 
        if (UNIV_LIKELY(srv_use_sys_malloc)) {
363
 
                return(realloc(ptr, size));
364
 
        }
365
 
 
366
 
        if (ptr == NULL) {
367
 
 
368
 
                return(ut_malloc(size));
369
 
        }
370
 
 
371
 
        if (size == 0) {
372
 
                ut_free(ptr);
373
 
 
374
 
                return(NULL);
375
 
        }
376
 
 
377
 
        block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t));
378
 
 
379
 
        ut_a(block->magic_n == UT_MEM_MAGIC_N);
380
 
 
381
 
        old_size = block->size - sizeof(ut_mem_block_t);
382
 
 
383
 
        if (size < old_size) {
384
 
                min_size = size;
385
 
        } else {
386
 
                min_size = old_size;
387
 
        }
388
 
 
389
 
        new_ptr = ut_malloc(size);
390
 
 
391
 
        if (new_ptr == NULL) {
392
 
 
393
 
                return(NULL);
394
 
        }
395
 
 
396
 
        /* Copy the old data from ptr */
397
 
        ut_memcpy(new_ptr, ptr, min_size);
398
 
 
399
 
        ut_free(ptr);
400
 
 
401
 
        return(new_ptr);
402
 
}
403
 
 
404
 
/**********************************************************************//**
405
 
Frees in shutdown all allocated memory not freed yet. */
406
 
UNIV_INTERN
407
 
void
408
 
ut_free_all_mem(void)
409
 
/*=================*/
410
 
{
411
 
        ut_mem_block_t* block;
412
 
 
413
 
        ut_a(ut_mem_block_list_inited);
414
 
        ut_mem_block_list_inited = FALSE;
415
 
        os_fast_mutex_free(&ut_list_mutex);
416
 
 
417
 
        while ((block = UT_LIST_GET_FIRST(ut_mem_block_list))) {
418
 
 
419
 
                ut_a(block->magic_n == UT_MEM_MAGIC_N);
420
 
                ut_a(ut_total_allocated_memory >= block->size);
421
 
 
422
 
                ut_total_allocated_memory -= block->size;
423
 
 
424
 
                UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
425
 
                free(block);
426
 
        }
427
 
 
428
 
        if (ut_total_allocated_memory != 0) {
429
 
                fprintf(stderr,
430
 
                        "InnoDB: Warning: after shutdown"
431
 
                        " total allocated memory is %lu\n",
432
 
                        (ulong) ut_total_allocated_memory);
433
 
        }
434
 
 
435
 
        ut_mem_block_list_inited = FALSE;
436
 
}
437
 
#endif /* !UNIV_HOTBACKUP */
438
 
 
439
 
/**********************************************************************//**
440
 
Copies up to size - 1 characters from the NUL-terminated string src to
441
 
dst, NUL-terminating the result. Returns strlen(src), so truncation
442
 
occurred if the return value >= size.
443
 
@return strlen(src) */
444
 
UNIV_INTERN
445
 
ulint
446
 
ut_strlcpy(
447
 
/*=======*/
448
 
        char*           dst,    /*!< in: destination buffer */
449
 
        const char*     src,    /*!< in: source buffer */
450
 
        ulint           size)   /*!< in: size of destination buffer */
451
 
{
452
 
        ulint   src_size = strlen(src);
453
 
 
454
 
        if (size != 0) {
455
 
                ulint   n = ut_min(src_size, size - 1);
456
 
 
457
 
                memcpy(dst, src, n);
458
 
                dst[n] = '\0';
459
 
        }
460
 
 
461
 
        return(src_size);
462
 
}
463
 
 
464
 
/**********************************************************************//**
465
 
Like ut_strlcpy, but if src doesn't fit in dst completely, copies the last
466
 
(size - 1) bytes of src, not the first.
467
 
@return strlen(src) */
468
 
UNIV_INTERN
469
 
ulint
470
 
ut_strlcpy_rev(
471
 
/*===========*/
472
 
        char*           dst,    /*!< in: destination buffer */
473
 
        const char*     src,    /*!< in: source buffer */
474
 
        ulint           size)   /*!< in: size of destination buffer */
475
 
{
476
 
        ulint   src_size = strlen(src);
477
 
 
478
 
        if (size != 0) {
479
 
                ulint   n = ut_min(src_size, size - 1);
480
 
 
481
 
                memcpy(dst, src + src_size - n, n + 1);
482
 
        }
483
 
 
484
 
        return(src_size);
485
 
}
486
 
 
487
 
/**********************************************************************//**
488
 
Make a quoted copy of a NUL-terminated string.  Leading and trailing
489
 
quotes will not be included; only embedded quotes will be escaped.
490
 
See also ut_strlenq() and ut_memcpyq().
491
 
@return pointer to end of dest */
492
 
UNIV_INTERN
493
 
char*
494
 
ut_strcpyq(
495
 
/*=======*/
496
 
        char*           dest,   /*!< in: output buffer */
497
 
        char            q,      /*!< in: the quote character */
498
 
        const char*     src)    /*!< in: null-terminated string */
499
 
{
500
 
        while (*src) {
501
 
                if ((*dest++ = *src++) == q) {
502
 
                        *dest++ = q;
503
 
                }
504
 
        }
505
 
 
506
 
        return(dest);
507
 
}
508
 
 
509
 
/**********************************************************************//**
510
 
Make a quoted copy of a fixed-length string.  Leading and trailing
511
 
quotes will not be included; only embedded quotes will be escaped.
512
 
See also ut_strlenq() and ut_strcpyq().
513
 
@return pointer to end of dest */
514
 
UNIV_INTERN
515
 
char*
516
 
ut_memcpyq(
517
 
/*=======*/
518
 
        char*           dest,   /*!< in: output buffer */
519
 
        char            q,      /*!< in: the quote character */
520
 
        const char*     src,    /*!< in: string to be quoted */
521
 
        ulint           len)    /*!< in: length of src */
522
 
{
523
 
        const char*     srcend = src + len;
524
 
 
525
 
        while (src < srcend) {
526
 
                if ((*dest++ = *src++) == q) {
527
 
                        *dest++ = q;
528
 
                }
529
 
        }
530
 
 
531
 
        return(dest);
532
 
}
533
 
 
534
 
#ifndef UNIV_HOTBACKUP
535
 
/**********************************************************************//**
536
 
Return the number of times s2 occurs in s1. Overlapping instances of s2
537
 
are only counted once.
538
 
@return the number of times s2 occurs in s1 */
539
 
UNIV_INTERN
540
 
ulint
541
 
ut_strcount(
542
 
/*========*/
543
 
        const char*     s1,     /*!< in: string to search in */
544
 
        const char*     s2)     /*!< in: string to search for */
545
 
{
546
 
        ulint   count = 0;
547
 
        ulint   len = strlen(s2);
548
 
 
549
 
        if (len == 0) {
550
 
 
551
 
                return(0);
552
 
        }
553
 
 
554
 
        for (;;) {
555
 
                s1 = strstr(s1, s2);
556
 
 
557
 
                if (!s1) {
558
 
 
559
 
                        break;
560
 
                }
561
 
 
562
 
                count++;
563
 
                s1 += len;
564
 
        }
565
 
 
566
 
        return(count);
567
 
}
568
 
 
569
 
/**********************************************************************//**
570
 
Replace every occurrence of s1 in str with s2. Overlapping instances of s1
571
 
are only replaced once.
572
 
@return own: modified string, must be freed with mem_free() */
573
 
UNIV_INTERN
574
 
char*
575
 
ut_strreplace(
576
 
/*==========*/
577
 
        const char*     str,    /*!< in: string to operate on */
578
 
        const char*     s1,     /*!< in: string to replace */
579
 
        const char*     s2)     /*!< in: string to replace s1 with */
580
 
{
581
 
        char*           new_str;
582
 
        char*           ptr;
583
 
        const char*     str_end;
584
 
        ulint           str_len = strlen(str);
585
 
        ulint           s1_len = strlen(s1);
586
 
        ulint           s2_len = strlen(s2);
587
 
        ulint           count = 0;
588
 
        int             len_delta = (int)s2_len - (int)s1_len;
589
 
 
590
 
        str_end = str + str_len;
591
 
 
592
 
        if (len_delta <= 0) {
593
 
                len_delta = 0;
594
 
        } else {
595
 
                count = ut_strcount(str, s1);
596
 
        }
597
 
 
598
 
        new_str = mem_alloc(str_len + count * len_delta + 1);
599
 
        ptr = new_str;
600
 
 
601
 
        while (str) {
602
 
                const char*     next = strstr(str, s1);
603
 
 
604
 
                if (!next) {
605
 
                        next = str_end;
606
 
                }
607
 
 
608
 
                memcpy(ptr, str, next - str);
609
 
                ptr += next - str;
610
 
 
611
 
                if (next == str_end) {
612
 
 
613
 
                        break;
614
 
                }
615
 
 
616
 
                memcpy(ptr, s2, s2_len);
617
 
                ptr += s2_len;
618
 
 
619
 
                str = next + s1_len;
620
 
        }
621
 
 
622
 
        *ptr = '\0';
623
 
 
624
 
        return(new_str);
625
 
}
626
 
 
627
 
#ifdef UNIV_COMPILE_TEST_FUNCS
628
 
 
629
 
void
630
 
test_ut_str_sql_format()
631
 
{
632
 
        char    buf[128];
633
 
        ulint   ret;
634
 
 
635
 
#define CALL_AND_TEST(str, str_len, buf, buf_size, ret_expected, buf_expected)\
636
 
        do {\
637
 
                ibool   ok = TRUE;\
638
 
                memset(buf, 'x', 10);\
639
 
                buf[10] = '\0';\
640
 
                fprintf(stderr, "TESTING \"%s\", %lu, %lu\n",\
641
 
                        str, (ulint) str_len, (ulint) buf_size);\
642
 
                ret = ut_str_sql_format(str, str_len, buf, buf_size);\
643
 
                if (ret != ret_expected) {\
644
 
                        fprintf(stderr, "expected ret %lu, got %lu\n",\
645
 
                                (ulint) ret_expected, ret);\
646
 
                        ok = FALSE;\
647
 
                }\
648
 
                if (strcmp((char*) buf, buf_expected) != 0) {\
649
 
                        fprintf(stderr, "expected buf \"%s\", got \"%s\"\n",\
650
 
                                buf_expected, buf);\
651
 
                        ok = FALSE;\
652
 
                }\
653
 
                if (ok) {\
654
 
                        fprintf(stderr, "OK: %lu, \"%s\"\n\n",\
655
 
                                (ulint) ret, buf);\
656
 
                } else {\
657
 
                        return;\
658
 
                }\
659
 
        } while (0)
660
 
 
661
 
        CALL_AND_TEST("abcd", 4, buf, 0, 0, "xxxxxxxxxx");
662
 
 
663
 
        CALL_AND_TEST("abcd", 4, buf, 1, 1, "");
664
 
 
665
 
        CALL_AND_TEST("abcd", 4, buf, 2, 1, "");
666
 
 
667
 
        CALL_AND_TEST("abcd", 0, buf, 3, 3, "''");
668
 
        CALL_AND_TEST("abcd", 1, buf, 3, 1, "");
669
 
        CALL_AND_TEST("abcd", 2, buf, 3, 1, "");
670
 
        CALL_AND_TEST("abcd", 3, buf, 3, 1, "");
671
 
        CALL_AND_TEST("abcd", 4, buf, 3, 1, "");
672
 
 
673
 
        CALL_AND_TEST("abcd", 0, buf, 4, 3, "''");
674
 
        CALL_AND_TEST("abcd", 1, buf, 4, 4, "'a'");
675
 
        CALL_AND_TEST("abcd", 2, buf, 4, 4, "'a'");
676
 
        CALL_AND_TEST("abcd", 3, buf, 4, 4, "'a'");
677
 
        CALL_AND_TEST("abcd", 4, buf, 4, 4, "'a'");
678
 
        CALL_AND_TEST("abcde", 5, buf, 4, 4, "'a'");
679
 
        CALL_AND_TEST("'", 1, buf, 4, 3, "''");
680
 
        CALL_AND_TEST("''", 2, buf, 4, 3, "''");
681
 
        CALL_AND_TEST("a'", 2, buf, 4, 4, "'a'");
682
 
        CALL_AND_TEST("'a", 2, buf, 4, 3, "''");
683
 
        CALL_AND_TEST("ab", 2, buf, 4, 4, "'a'");
684
 
 
685
 
        CALL_AND_TEST("abcdef", 0, buf, 5, 3, "''");
686
 
        CALL_AND_TEST("abcdef", 1, buf, 5, 4, "'a'");
687
 
        CALL_AND_TEST("abcdef", 2, buf, 5, 5, "'ab'");
688
 
        CALL_AND_TEST("abcdef", 3, buf, 5, 5, "'ab'");
689
 
        CALL_AND_TEST("abcdef", 4, buf, 5, 5, "'ab'");
690
 
        CALL_AND_TEST("abcdef", 5, buf, 5, 5, "'ab'");
691
 
        CALL_AND_TEST("abcdef", 6, buf, 5, 5, "'ab'");
692
 
        CALL_AND_TEST("'", 1, buf, 5, 5, "''''");
693
 
        CALL_AND_TEST("''", 2, buf, 5, 5, "''''");
694
 
        CALL_AND_TEST("a'", 2, buf, 5, 4, "'a'");
695
 
        CALL_AND_TEST("'a", 2, buf, 5, 5, "''''");
696
 
        CALL_AND_TEST("ab", 2, buf, 5, 5, "'ab'");
697
 
        CALL_AND_TEST("abc", 3, buf, 5, 5, "'ab'");
698
 
 
699
 
        CALL_AND_TEST("ab", 2, buf, 6, 5, "'ab'");
700
 
 
701
 
        CALL_AND_TEST("a'b'c", 5, buf, 32, 10, "'a''b''c'");
702
 
        CALL_AND_TEST("a'b'c'", 6, buf, 32, 12, "'a''b''c'''");
703
 
}
704
 
 
705
 
#endif /* UNIV_COMPILE_TEST_FUNCS */
706
 
#endif /* !UNIV_HOTBACKUP */