00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "mem0mem.h"
00027
00028 #ifdef UNIV_NONINL
00029 #include "mem0mem.ic"
00030 #endif
00031
00032 #include "buf0buf.h"
00033 #include "srv0srv.h"
00034 #include "mem0dbg.cc"
00035 #include <stdarg.h>
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 #ifdef MEM_PERIODIC_CHECK
00095
00096 ibool mem_block_list_inited;
00097
00098 UT_LIST_BASE_NODE_T(mem_block_t) mem_block_list;
00099
00100 #endif
00101
00102
00105 UNIV_INTERN
00106 char*
00107 mem_heap_strdup(
00108
00109 mem_heap_t* heap,
00110 const char* str)
00111 {
00112 return(static_cast<char *>(mem_heap_dup(heap, str, strlen(str) + 1)));
00113 }
00114
00115
00118 UNIV_INTERN
00119 void*
00120 mem_heap_dup(
00121
00122 mem_heap_t* heap,
00123 const void* data,
00124 ulint len)
00125 {
00126 return(memcpy(mem_heap_alloc(heap, len), data, len));
00127 }
00128
00129
00132 UNIV_INTERN
00133 char*
00134 mem_heap_strcat(
00135
00136 mem_heap_t* heap,
00137 const char* s1,
00138 const char* s2)
00139 {
00140 char* s;
00141 ulint s1_len = strlen(s1);
00142 ulint s2_len = strlen(s2);
00143
00144 s = static_cast<char *>(mem_heap_alloc(heap, s1_len + s2_len + 1));
00145
00146 memcpy(s, s1, s1_len);
00147 memcpy(s + s1_len, s2, s2_len);
00148
00149 s[s1_len + s2_len] = '\0';
00150
00151 return(s);
00152 }
00153
00154
00155
00158 static
00159 ulint
00160 mem_heap_printf_low(
00161
00162 char* buf,
00164 const char* format,
00165 va_list ap)
00166 {
00167 ulint len = 0;
00168
00169 while (*format) {
00170
00171
00172 ibool is_long = FALSE;
00173
00174
00175 size_t plen;
00176
00177 if (*format++ != '%') {
00178
00179
00180 len++;
00181
00182 if (buf) {
00183 *buf++ = *(format - 1);
00184 }
00185
00186 continue;
00187 }
00188
00189 if (*format == 'l') {
00190 is_long = TRUE;
00191 format++;
00192 }
00193
00194 switch (*format++) {
00195 case 's':
00196
00197 {
00198 char* s = va_arg(ap, char*);
00199
00200
00201 ut_a(!is_long);
00202
00203 plen = strlen(s);
00204 len += plen;
00205
00206 if (buf) {
00207 memcpy(buf, s, plen);
00208 buf += plen;
00209 }
00210 }
00211
00212 break;
00213
00214 case 'u':
00215
00216 {
00217 char tmp[32];
00218 unsigned long val;
00219
00220
00221 ut_a(is_long);
00222
00223 val = va_arg(ap, unsigned long);
00224
00225 plen = sprintf(tmp, "%lu", val);
00226 len += plen;
00227
00228 if (buf) {
00229 memcpy(buf, tmp, plen);
00230 buf += plen;
00231 }
00232 }
00233
00234 break;
00235
00236 case '%':
00237
00238
00239 ut_a(!is_long);
00240
00241 len++;
00242
00243 if (buf) {
00244 *buf++ = '%';
00245 }
00246
00247 break;
00248
00249 default:
00250 ut_error;
00251 }
00252 }
00253
00254
00255 len++;
00256
00257 if (buf) {
00258 *buf = '\0';
00259 }
00260
00261 return(len);
00262 }
00263
00264
00270 UNIV_INTERN
00271 char*
00272 mem_heap_printf(
00273
00274 mem_heap_t* heap,
00275 const char* format,
00276 ...)
00277 {
00278 va_list ap;
00279 char* str;
00280 ulint len;
00281
00282
00283 len = 0;
00284 va_start(ap, format);
00285 len = mem_heap_printf_low(NULL, format, ap);
00286 va_end(ap);
00287
00288
00289 str = static_cast<char *>(mem_heap_alloc(heap, len));
00290 va_start(ap, format);
00291 mem_heap_printf_low(str, format, ap);
00292 va_end(ap);
00293
00294 return(str);
00295 }
00296
00297
00301 UNIV_INTERN
00302 mem_block_t*
00303 mem_heap_create_block(
00304
00305 mem_heap_t* heap,
00307 ulint n,
00308 ulint type,
00310 const char* file_name,
00311 ulint line)
00312 {
00313 #ifndef UNIV_HOTBACKUP
00314 buf_block_t* buf_block = NULL;
00315 #endif
00316 mem_block_t* block;
00317 ulint len;
00318
00319 ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
00320 || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
00321
00322 if (heap && heap->magic_n != MEM_BLOCK_MAGIC_N) {
00323 mem_analyze_corruption(heap);
00324 }
00325
00326
00327 len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n);
00328
00329 #ifndef UNIV_HOTBACKUP
00330 if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) {
00331
00332 ut_ad(type == MEM_HEAP_DYNAMIC || n <= MEM_MAX_ALLOC_IN_BUF);
00333
00334 block = static_cast<mem_block_info_t *>(mem_area_alloc(&len, mem_comm_pool));
00335 } else {
00336 len = UNIV_PAGE_SIZE;
00337
00338 if ((type & MEM_HEAP_BTR_SEARCH) && heap) {
00339
00340
00341
00342
00343 buf_block = static_cast<buf_block_t *>(heap->free_block);
00344 heap->free_block = NULL;
00345
00346 if (UNIV_UNLIKELY(!buf_block)) {
00347
00348 return(NULL);
00349 }
00350 } else {
00351 buf_block = buf_block_alloc(NULL, 0);
00352 }
00353
00354 block = (mem_block_t*) buf_block->frame;
00355 }
00356
00357 ut_ad(block);
00358 block->buf_block = buf_block;
00359 block->free_block = NULL;
00360 #else
00361 len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n);
00362 block = ut_malloc(len);
00363 ut_ad(block);
00364 #endif
00365
00366 block->magic_n = MEM_BLOCK_MAGIC_N;
00367 ut_strlcpy_rev(block->file_name, file_name, sizeof(block->file_name));
00368 block->line = line;
00369
00370 #ifdef MEM_PERIODIC_CHECK
00371 mutex_enter(&(mem_comm_pool->mutex));
00372
00373 if (!mem_block_list_inited) {
00374 mem_block_list_inited = TRUE;
00375 UT_LIST_INIT(mem_block_list);
00376 }
00377
00378 UT_LIST_ADD_LAST(mem_block_list, mem_block_list, block);
00379
00380 mutex_exit(&(mem_comm_pool->mutex));
00381 #endif
00382 mem_block_set_len(block, len);
00383 mem_block_set_type(block, type);
00384 mem_block_set_free(block, MEM_BLOCK_HEADER_SIZE);
00385 mem_block_set_start(block, MEM_BLOCK_HEADER_SIZE);
00386
00387 if (UNIV_UNLIKELY(heap == NULL)) {
00388
00389
00390 block->total_size = len;
00391 } else {
00392
00393
00394 ut_d(block->total_size = ULINT_UNDEFINED);
00395 UNIV_MEM_INVALID(&block->total_size,
00396 sizeof block->total_size);
00397
00398 heap->total_size += len;
00399 }
00400
00401 ut_ad((ulint)MEM_BLOCK_HEADER_SIZE < len);
00402
00403 return(block);
00404 }
00405
00406
00410 UNIV_INTERN
00411 mem_block_t*
00412 mem_heap_add_block(
00413
00414 mem_heap_t* heap,
00415 ulint n)
00416 {
00417 mem_block_t* block;
00418 mem_block_t* new_block;
00419 ulint new_size;
00420
00421 ut_ad(mem_heap_check(heap));
00422
00423 block = UT_LIST_GET_LAST(heap->base);
00424
00425
00426
00427
00428
00429 new_size = 2 * mem_block_get_len(block);
00430
00431 if (heap->type != MEM_HEAP_DYNAMIC) {
00432
00433 ut_a(n <= MEM_MAX_ALLOC_IN_BUF);
00434
00435 if (new_size > MEM_MAX_ALLOC_IN_BUF) {
00436 new_size = MEM_MAX_ALLOC_IN_BUF;
00437 }
00438 } else if (new_size > MEM_BLOCK_STANDARD_SIZE) {
00439
00440 new_size = MEM_BLOCK_STANDARD_SIZE;
00441 }
00442
00443 if (new_size < n) {
00444 new_size = n;
00445 }
00446
00447 new_block = mem_heap_create_block(heap, new_size, heap->type,
00448 heap->file_name, heap->line);
00449 if (new_block == NULL) {
00450
00451 return(NULL);
00452 }
00453
00454
00455
00456 UT_LIST_INSERT_AFTER(list, heap->base, block, new_block);
00457
00458 return(new_block);
00459 }
00460
00461
00463 UNIV_INTERN
00464 void
00465 mem_heap_block_free(
00466
00467 mem_heap_t* heap,
00468 mem_block_t* block)
00469 {
00470 ulint type;
00471 ulint len;
00472 #ifndef UNIV_HOTBACKUP
00473 buf_block_t* buf_block = static_cast<buf_block_t *>(block->buf_block);
00474 #endif
00475
00476 if (block->magic_n != MEM_BLOCK_MAGIC_N) {
00477 mem_analyze_corruption(block);
00478 }
00479
00480 UT_LIST_REMOVE(list, heap->base, block);
00481
00482 #ifdef MEM_PERIODIC_CHECK
00483 mutex_enter(&(mem_comm_pool->mutex));
00484
00485 UT_LIST_REMOVE(mem_block_list, mem_block_list, block);
00486
00487 mutex_exit(&(mem_comm_pool->mutex));
00488 #endif
00489
00490 ut_ad(heap->total_size >= block->len);
00491 heap->total_size -= block->len;
00492
00493 type = heap->type;
00494 len = block->len;
00495 block->magic_n = MEM_FREED_BLOCK_MAGIC_N;
00496
00497 #ifndef UNIV_HOTBACKUP
00498 #ifdef UNIV_MEM_DEBUG
00499
00500
00501
00502 mem_erase_buf((byte*)block, len);
00503 #else
00504 UNIV_MEM_ASSERT_AND_FREE(block, len);
00505 #endif
00506
00507 if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) {
00508
00509 ut_ad(!buf_block);
00510 mem_area_free(block, mem_comm_pool);
00511 } else {
00512 ut_ad(type & MEM_HEAP_BUFFER);
00513
00514 buf_block_free(buf_block);
00515 }
00516 #else
00517 #ifdef UNIV_MEM_DEBUG
00518
00519
00520
00521 mem_erase_buf((byte*)block, len);
00522 #else
00523 UNIV_MEM_ASSERT_AND_FREE(block, len);
00524 #endif
00525 ut_free(block);
00526 #endif
00527 }
00528
00529 #ifndef UNIV_HOTBACKUP
00530
00532 UNIV_INTERN
00533 void
00534 mem_heap_free_block_free(
00535
00536 mem_heap_t* heap)
00537 {
00538 if (UNIV_LIKELY_NULL(heap->free_block)) {
00539
00540 buf_block_free(static_cast<buf_block_t *>(heap->free_block));
00541
00542 heap->free_block = NULL;
00543 }
00544 }
00545 #endif
00546
00547 #ifdef MEM_PERIODIC_CHECK
00548
00551 UNIV_INTERN
00552 void
00553 mem_validate_all_blocks(void)
00554
00555 {
00556 mem_block_t* block;
00557
00558 mutex_enter(&(mem_comm_pool->mutex));
00559
00560 block = UT_LIST_GET_FIRST(mem_block_list);
00561
00562 while (block) {
00563 if (block->magic_n != MEM_BLOCK_MAGIC_N) {
00564 mem_analyze_corruption(block);
00565 }
00566
00567 block = UT_LIST_GET_NEXT(mem_block_list, block);
00568 }
00569
00570 mutex_exit(&(mem_comm_pool->mutex));
00571 }
00572 #endif