~drizzle-trunk/drizzle/development

641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1
/*****************************************************************************
2
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
3
Copyright (C) 1994, 2009, Innobase Oy. All Rights Reserved.
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
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
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
16
17
*****************************************************************************/
18
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
19
/********************************************************************//**
20
@file ut/ut0mem.c
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
32
#ifndef UNIV_HOTBACKUP
33
# include "os0thread.h"
34
# include "srv0srv.h"
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
35
36
#include <stdlib.h>
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
37
#include <errno.h>
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
38
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
39
/** This struct is placed first in every allocated memory block */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
40
typedef struct ut_mem_block_struct ut_mem_block_t;
41
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
42
/** The total amount of memory currently allocated from the operating
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
47
/** Mutex protecting ut_total_allocated_memory and ut_mem_block_list */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
48
UNIV_INTERN os_fast_mutex_t	ut_list_mutex;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
49
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
50
/** Dynamically allocated memory block */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
51
struct ut_mem_block_struct{
52
	UT_LIST_NODE_T(ut_mem_block_t) mem_block_list;
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
53
			/*!< mem block list node */
54
	ulint	size;	/*!< size of allocated memory */
55
	ulint	magic_n;/*!< magic number (UT_MEM_MAGIC_N) */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
56
};
57
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
58
/** The value of ut_mem_block_struct::magic_n.  Used in detecting
59
memory corruption. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
60
#define UT_MEM_MAGIC_N	1601650166
61
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
62
/** List of all memory blocks allocated from the operating system
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
63
with malloc.  Protected by ut_list_mutex. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
64
static UT_LIST_BASE_NODE_T(ut_mem_block_t)   ut_mem_block_list;
65
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
66
/** Flag: has ut_mem_block_list been initialized? */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
67
static ibool  ut_mem_block_list_inited = FALSE;
68
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
69
/** A dummy pointer for generating a null pointer exception in
70
ut_malloc_low() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
71
static ulint*	ut_mem_null_ptr	= NULL;
72
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
73
/**********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
74
Initializes the mem block list at database startup. */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
75
UNIV_INTERN
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
76
void
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
77
ut_mem_init(void)
78
/*=============*/
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
79
{
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
80
	ut_a(!ut_mem_block_list_inited);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
81
	os_fast_mutex_init(&ut_list_mutex);
82
	UT_LIST_INIT(ut_mem_block_list);
83
	ut_mem_block_list_inited = TRUE;
84
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
85
#endif /* !UNIV_HOTBACKUP */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
86
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
87
/**********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
88
Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
89
defined and set_to_zero is TRUE.
90
@return	own: allocated memory */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
91
UNIV_INTERN
92
void*
93
ut_malloc_low(
94
/*==========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
95
	ulint	n,		/*!< in: number of bytes to allocate */
96
	ibool	set_to_zero,	/*!< in: TRUE if allocated memory should be
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
97
				set to zero if UNIV_SET_MEM_TO_ZERO is
98
				defined */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
99
	ibool	assert_on_error)/*!< in: if TRUE, we crash mysqld if the
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
100
				memory cannot be allocated */
101
{
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
102
#ifndef UNIV_HOTBACKUP
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
103
	ulint	retry_count;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
104
	void*	ret;
105
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
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
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
119
	ut_ad((sizeof(ut_mem_block_t) % 8) == 0); /* check alignment ok */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
120
	ut_a(ut_mem_block_list_inited);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
121
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
122
	retry_count = 0;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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)));
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
226
}
227
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
228
/**********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
229
Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
230
defined.
231
@return	own: allocated memory */
2023.3.2 by Monty Taylor
Fixed lexer symbols.
232
extern "C"
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
233
UNIV_INTERN
234
void*
235
ut_malloc(
236
/*======*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
237
	ulint	n)	/*!< in: number of bytes to allocate */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
238
{
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
239
#ifndef UNIV_HOTBACKUP
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
240
	return(ut_malloc_low(n, TRUE, TRUE));
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
241
#else /* !UNIV_HOTBACKUP */
242
	return(malloc(n));
243
#endif /* !UNIV_HOTBACKUP */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
244
}
245
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
246
#ifndef UNIV_HOTBACKUP
247
/**********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
248
Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs
249
out. It cannot be used if we want to return an error message. Prints to
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
250
stderr a message if fails.
251
@return	TRUE if succeeded */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
252
UNIV_INTERN
253
ibool
254
ut_test_malloc(
255
/*===========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
256
	ulint	n)	/*!< in: try to allocate this many bytes */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
257
{
258
	void*	ret;
259
260
	ret = malloc(n);
261
262
	if (ret == NULL) {
263
		ut_print_timestamp(stderr);
264
		fprintf(stderr,
265
			"  InnoDB: Error: cannot allocate"
266
			" %lu bytes of memory for\n"
267
			"InnoDB: a BLOB with malloc! Total allocated memory\n"
268
			"InnoDB: by InnoDB %lu bytes."
269
			" Operating system errno: %d\n"
270
			"InnoDB: Check if you should increase"
271
			" the swap file or\n"
272
			"InnoDB: ulimits of your operating system.\n"
273
			"InnoDB: On FreeBSD check you have"
274
			" compiled the OS with\n"
275
			"InnoDB: a big enough maximum process size.\n",
276
			(ulong) n,
277
			(ulong) ut_total_allocated_memory,
278
			(int) errno);
279
		return(FALSE);
280
	}
281
282
	free(ret);
283
284
	return(TRUE);
285
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
286
#endif /* !UNIV_HOTBACKUP */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
287
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
288
/**********************************************************************//**
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
289
Frees a memory block allocated with ut_malloc. Freeing a NULL pointer is
290
a nop. */
2023.3.2 by Monty Taylor
Fixed lexer symbols.
291
extern "C"
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
292
UNIV_INTERN
293
void
294
ut_free(
295
/*====*/
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
296
	void* ptr)  /*!< in, own: memory block, can be NULL */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
297
{
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
298
#ifndef UNIV_HOTBACKUP
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
299
	ut_mem_block_t* block;
300
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
301
	if (ptr == NULL) {
302
		return;
303
	} else if (UNIV_LIKELY(srv_use_sys_malloc)) {
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
304
		free(ptr);
305
		return;
306
	}
307
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
308
	block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t));
309
310
	os_fast_mutex_lock(&ut_list_mutex);
311
312
	ut_a(block->magic_n == UT_MEM_MAGIC_N);
313
	ut_a(ut_total_allocated_memory >= block->size);
314
315
	ut_total_allocated_memory -= block->size;
316
317
	UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
318
	free(block);
319
320
	os_fast_mutex_unlock(&ut_list_mutex);
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
321
#else /* !UNIV_HOTBACKUP */
322
	free(ptr);
323
#endif /* !UNIV_HOTBACKUP */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
324
}
325
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
326
#ifndef UNIV_HOTBACKUP
327
/**********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
328
Implements realloc. This is needed by /pars/lexyy.c. Otherwise, you should not
329
use this function because the allocation functions in mem0mem.h are the
330
recommended ones in InnoDB.
331
332
man realloc in Linux, 2004:
333
334
       realloc()  changes the size of the memory block pointed to
335
       by ptr to size bytes.  The contents will be  unchanged  to
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
336
       the minimum of the old and new sizes; newly allocated mem-
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
337
       ory will be uninitialized.  If ptr is NULL,  the	 call  is
338
       equivalent  to malloc(size); if size is equal to zero, the
339
       call is equivalent to free(ptr).	 Unless ptr is	NULL,  it
340
       must  have  been	 returned by an earlier call to malloc(),
341
       calloc() or realloc().
342
343
RETURN VALUE
344
       realloc() returns a pointer to the newly allocated memory,
345
       which is suitably aligned for any kind of variable and may
346
       be different from ptr, or NULL if the  request  fails.  If
347
       size  was equal to 0, either NULL or a pointer suitable to
348
       be passed to free() is returned.	 If realloc()  fails  the
349
       original	 block	is  left  untouched  - it is not freed or
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
350
       moved.
351
@return	own: pointer to new mem block or NULL */
2023.3.2 by Monty Taylor
Fixed lexer symbols.
352
extern "C"
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
353
UNIV_INTERN
354
void*
355
ut_realloc(
356
/*=======*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
357
	void*	ptr,	/*!< in: pointer to old block or NULL */
358
	ulint	size)	/*!< in: desired size */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
359
{
360
	ut_mem_block_t* block;
361
	ulint		old_size;
362
	ulint		min_size;
363
	void*		new_ptr;
364
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
365
	if (UNIV_LIKELY(srv_use_sys_malloc)) {
366
		return(realloc(ptr, size));
367
	}
368
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
369
	if (ptr == NULL) {
370
371
		return(ut_malloc(size));
372
	}
373
374
	if (size == 0) {
375
		ut_free(ptr);
376
377
		return(NULL);
378
	}
379
380
	block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t));
381
382
	ut_a(block->magic_n == UT_MEM_MAGIC_N);
383
384
	old_size = block->size - sizeof(ut_mem_block_t);
385
386
	if (size < old_size) {
387
		min_size = size;
388
	} else {
389
		min_size = old_size;
390
	}
391
392
	new_ptr = ut_malloc(size);
393
394
	if (new_ptr == NULL) {
395
396
		return(NULL);
397
	}
398
399
	/* Copy the old data from ptr */
400
	ut_memcpy(new_ptr, ptr, min_size);
401
402
	ut_free(ptr);
403
404
	return(new_ptr);
405
}
406
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
407
/**********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
408
Frees in shutdown all allocated memory not freed yet. */
409
UNIV_INTERN
410
void
411
ut_free_all_mem(void)
412
/*=================*/
413
{
414
	ut_mem_block_t* block;
415
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
416
	ut_a(ut_mem_block_list_inited);
417
	ut_mem_block_list_inited = FALSE;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
418
	os_fast_mutex_free(&ut_list_mutex);
419
420
	while ((block = UT_LIST_GET_FIRST(ut_mem_block_list))) {
421
422
		ut_a(block->magic_n == UT_MEM_MAGIC_N);
423
		ut_a(ut_total_allocated_memory >= block->size);
424
425
		ut_total_allocated_memory -= block->size;
426
427
		UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
428
		free(block);
429
	}
430
431
	if (ut_total_allocated_memory != 0) {
432
		fprintf(stderr,
433
			"InnoDB: Warning: after shutdown"
434
			" total allocated memory is %lu\n",
435
			(ulong) ut_total_allocated_memory);
436
	}
1819.5.106 by stewart at flamingspork
[patch 106/129] Merge patch for revision 1915 from InnoDB SVN:
437
438
	ut_mem_block_list_inited = FALSE;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
439
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
440
#endif /* !UNIV_HOTBACKUP */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
441
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
442
/**********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
443
Copies up to size - 1 characters from the NUL-terminated string src to
444
dst, NUL-terminating the result. Returns strlen(src), so truncation
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
445
occurred if the return value >= size.
446
@return	strlen(src) */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
447
UNIV_INTERN
448
ulint
449
ut_strlcpy(
450
/*=======*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
451
	char*		dst,	/*!< in: destination buffer */
452
	const char*	src,	/*!< in: source buffer */
453
	ulint		size)	/*!< in: size of destination buffer */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
454
{
455
	ulint	src_size = strlen(src);
456
457
	if (size != 0) {
458
		ulint	n = ut_min(src_size, size - 1);
459
460
		memcpy(dst, src, n);
461
		dst[n] = '\0';
462
	}
463
464
	return(src_size);
465
}
466
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
467
/**********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
468
Like ut_strlcpy, but if src doesn't fit in dst completely, copies the last
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
469
(size - 1) bytes of src, not the first.
470
@return	strlen(src) */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
471
UNIV_INTERN
472
ulint
473
ut_strlcpy_rev(
474
/*===========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
475
	char*		dst,	/*!< in: destination buffer */
476
	const char*	src,	/*!< in: source buffer */
477
	ulint		size)	/*!< in: size of destination buffer */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
478
{
479
	ulint	src_size = strlen(src);
480
481
	if (size != 0) {
482
		ulint	n = ut_min(src_size, size - 1);
483
484
		memcpy(dst, src + src_size - n, n + 1);
485
	}
486
487
	return(src_size);
488
}
489
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
490
/**********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
491
Make a quoted copy of a NUL-terminated string.	Leading and trailing
492
quotes will not be included; only embedded quotes will be escaped.
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
493
See also ut_strlenq() and ut_memcpyq().
494
@return	pointer to end of dest */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
495
UNIV_INTERN
496
char*
497
ut_strcpyq(
498
/*=======*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
499
	char*		dest,	/*!< in: output buffer */
500
	char		q,	/*!< in: the quote character */
501
	const char*	src)	/*!< in: null-terminated string */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
502
{
503
	while (*src) {
504
		if ((*dest++ = *src++) == q) {
505
			*dest++ = q;
506
		}
507
	}
508
509
	return(dest);
510
}
511
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
512
/**********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
513
Make a quoted copy of a fixed-length string.  Leading and trailing
514
quotes will not be included; only embedded quotes will be escaped.
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
515
See also ut_strlenq() and ut_strcpyq().
516
@return	pointer to end of dest */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
517
UNIV_INTERN
518
char*
519
ut_memcpyq(
520
/*=======*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
521
	char*		dest,	/*!< in: output buffer */
522
	char		q,	/*!< in: the quote character */
523
	const char*	src,	/*!< in: string to be quoted */
524
	ulint		len)	/*!< in: length of src */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
525
{
526
	const char*	srcend = src + len;
527
528
	while (src < srcend) {
529
		if ((*dest++ = *src++) == q) {
530
			*dest++ = q;
531
		}
532
	}
533
534
	return(dest);
535
}
536
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
537
#ifndef UNIV_HOTBACKUP
538
/**********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
539
Return the number of times s2 occurs in s1. Overlapping instances of s2
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
540
are only counted once.
541
@return	the number of times s2 occurs in s1 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
542
UNIV_INTERN
543
ulint
544
ut_strcount(
545
/*========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
546
	const char*	s1,	/*!< in: string to search in */
547
	const char*	s2)	/*!< in: string to search for */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
548
{
549
	ulint	count = 0;
550
	ulint	len = strlen(s2);
551
552
	if (len == 0) {
553
554
		return(0);
555
	}
556
557
	for (;;) {
558
		s1 = strstr(s1, s2);
559
560
		if (!s1) {
561
562
			break;
563
		}
564
565
		count++;
566
		s1 += len;
567
	}
568
569
	return(count);
570
}
571
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
572
/**********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
573
Replace every occurrence of s1 in str with s2. Overlapping instances of s1
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
574
are only replaced once.
575
@return	own: modified string, must be freed with mem_free() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
576
UNIV_INTERN
577
char*
578
ut_strreplace(
579
/*==========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
580
	const char*	str,	/*!< in: string to operate on */
581
	const char*	s1,	/*!< in: string to replace */
582
	const char*	s2)	/*!< in: string to replace s1 with */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
583
{
584
	char*		new_str;
585
	char*		ptr;
586
	const char*	str_end;
587
	ulint		str_len = strlen(str);
588
	ulint		s1_len = strlen(s1);
589
	ulint		s2_len = strlen(s2);
590
	ulint		count = 0;
591
	int		len_delta = (int)s2_len - (int)s1_len;
592
593
	str_end = str + str_len;
594
595
	if (len_delta <= 0) {
596
		len_delta = 0;
597
	} else {
598
		count = ut_strcount(str, s1);
599
	}
600
2023.3.6 by Monty Taylor
Fixing some of the innodb c++ casting issues.
601
	new_str = static_cast<char *>(mem_alloc(str_len + count * len_delta + 1));
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
602
	ptr = new_str;
603
604
	while (str) {
605
		const char*	next = strstr(str, s1);
606
607
		if (!next) {
608
			next = str_end;
609
		}
610
611
		memcpy(ptr, str, next - str);
612
		ptr += next - str;
613
614
		if (next == str_end) {
615
616
			break;
617
		}
618
619
		memcpy(ptr, s2, s2_len);
620
		ptr += s2_len;
621
622
		str = next + s1_len;
623
	}
624
625
	*ptr = '\0';
626
627
	return(new_str);
628
}
629
630
#ifdef UNIV_COMPILE_TEST_FUNCS
631
632
void
633
test_ut_str_sql_format()
634
{
635
	char	buf[128];
636
	ulint	ret;
637
638
#define CALL_AND_TEST(str, str_len, buf, buf_size, ret_expected, buf_expected)\
639
	do {\
640
		ibool	ok = TRUE;\
641
		memset(buf, 'x', 10);\
642
		buf[10] = '\0';\
643
		fprintf(stderr, "TESTING \"%s\", %lu, %lu\n",\
644
			str, (ulint) str_len, (ulint) buf_size);\
645
		ret = ut_str_sql_format(str, str_len, buf, buf_size);\
646
		if (ret != ret_expected) {\
647
			fprintf(stderr, "expected ret %lu, got %lu\n",\
648
				(ulint) ret_expected, ret);\
649
			ok = FALSE;\
650
		}\
651
		if (strcmp((char*) buf, buf_expected) != 0) {\
652
			fprintf(stderr, "expected buf \"%s\", got \"%s\"\n",\
653
				buf_expected, buf);\
654
			ok = FALSE;\
655
		}\
656
		if (ok) {\
657
			fprintf(stderr, "OK: %lu, \"%s\"\n\n",\
658
				(ulint) ret, buf);\
659
		} else {\
660
			return;\
661
		}\
662
	} while (0)
663
664
	CALL_AND_TEST("abcd", 4, buf, 0, 0, "xxxxxxxxxx");
665
666
	CALL_AND_TEST("abcd", 4, buf, 1, 1, "");
667
668
	CALL_AND_TEST("abcd", 4, buf, 2, 1, "");
669
670
	CALL_AND_TEST("abcd", 0, buf, 3, 3, "''");
671
	CALL_AND_TEST("abcd", 1, buf, 3, 1, "");
672
	CALL_AND_TEST("abcd", 2, buf, 3, 1, "");
673
	CALL_AND_TEST("abcd", 3, buf, 3, 1, "");
674
	CALL_AND_TEST("abcd", 4, buf, 3, 1, "");
675
676
	CALL_AND_TEST("abcd", 0, buf, 4, 3, "''");
677
	CALL_AND_TEST("abcd", 1, buf, 4, 4, "'a'");
678
	CALL_AND_TEST("abcd", 2, buf, 4, 4, "'a'");
679
	CALL_AND_TEST("abcd", 3, buf, 4, 4, "'a'");
680
	CALL_AND_TEST("abcd", 4, buf, 4, 4, "'a'");
681
	CALL_AND_TEST("abcde", 5, buf, 4, 4, "'a'");
682
	CALL_AND_TEST("'", 1, buf, 4, 3, "''");
683
	CALL_AND_TEST("''", 2, buf, 4, 3, "''");
684
	CALL_AND_TEST("a'", 2, buf, 4, 4, "'a'");
685
	CALL_AND_TEST("'a", 2, buf, 4, 3, "''");
686
	CALL_AND_TEST("ab", 2, buf, 4, 4, "'a'");
687
688
	CALL_AND_TEST("abcdef", 0, buf, 5, 3, "''");
689
	CALL_AND_TEST("abcdef", 1, buf, 5, 4, "'a'");
690
	CALL_AND_TEST("abcdef", 2, buf, 5, 5, "'ab'");
691
	CALL_AND_TEST("abcdef", 3, buf, 5, 5, "'ab'");
692
	CALL_AND_TEST("abcdef", 4, buf, 5, 5, "'ab'");
693
	CALL_AND_TEST("abcdef", 5, buf, 5, 5, "'ab'");
694
	CALL_AND_TEST("abcdef", 6, buf, 5, 5, "'ab'");
695
	CALL_AND_TEST("'", 1, buf, 5, 5, "''''");
696
	CALL_AND_TEST("''", 2, buf, 5, 5, "''''");
697
	CALL_AND_TEST("a'", 2, buf, 5, 4, "'a'");
698
	CALL_AND_TEST("'a", 2, buf, 5, 5, "''''");
699
	CALL_AND_TEST("ab", 2, buf, 5, 5, "'ab'");
700
	CALL_AND_TEST("abc", 3, buf, 5, 5, "'ab'");
701
702
	CALL_AND_TEST("ab", 2, buf, 6, 5, "'ab'");
703
704
	CALL_AND_TEST("a'b'c", 5, buf, 32, 10, "'a''b''c'");
705
	CALL_AND_TEST("a'b'c'", 6, buf, 32, 12, "'a''b''c'''");
706
}
707
708
#endif /* UNIV_COMPILE_TEST_FUNCS */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
709
#endif /* !UNIV_HOTBACKUP */